diff --git a/package.json b/package.json index 30834cb..888ceaf 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "@discordjs/rest": "^0.2.0-canary.0", "@hokify/agenda": "^6.2.12", "@tsconfig/node18-strictest-esm": "^1.0.0", - "@types/lodash": "^4.14.191", "@types/node-cron": "^3.0.1", "@ungap/structured-clone": "^1.0.1", "agenda": "^4.3.0", @@ -11,7 +10,7 @@ "body-parser": "^1.20.0", "chalk": "^5.0.0", "deno": "^0.1.1", - "discord.js": "14.7.1", + "discord.js": "^14.7.1", "eslint": "^8.21.0", "express": "^4.18.1", "form-data": "^4.0.0", @@ -61,6 +60,7 @@ "private": false, "type": "module", "devDependencies": { + "@types/lodash": "^4.14.191", "@typescript-eslint/eslint-plugin": "^5.32.0", "@typescript-eslint/parser": "^5.32.0", "eslint-config-prettier": "^8.5.0", diff --git a/src/commands/help.ts b/src/commands/help.ts index 1cb1ae2..a040358 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -39,7 +39,7 @@ const styles: Record = { "tags": {emoji: "PUNISH.NICKNAME.RED"}, "ticket": {emoji: "GUILD.TICKET.CLOSE"}, "user": {emoji: "MEMBER.LEAVE"}, - "verify": {emoji: "CONTROL.BLOCKTICK"} + "verify": {emoji: "CONTROL.REDTICK"} } const callback = async (interaction: CommandInteraction): Promise => { @@ -47,7 +47,7 @@ const callback = async (interaction: CommandInteraction): Promise => { const commands = client.fetchedCommands; let closed = false; - let currentPath: [string, string, string] = ["","",""] + let currentPath: [string, string, string] = ["", "", ""] do { const commandRow = new ActionRowBuilder() .addComponents( diff --git a/src/commands/mod/_meta.ts b/src/commands/mod/_meta.ts index af8006c..c5fcca5 100644 --- a/src/commands/mod/_meta.ts +++ b/src/commands/mod/_meta.ts @@ -5,4 +5,4 @@ const description = "Perform moderator actions"; const subcommand = await command(name, description, `mod`); -export { name, description, subcommand as command }; +export { name, description, subcommand as command }; \ No newline at end of file diff --git a/src/commands/mod/about.ts b/src/commands/mod/about.ts index d34b634..ab3ca49 100644 --- a/src/commands/mod/about.ts +++ b/src/commands/mod/about.ts @@ -435,6 +435,8 @@ const check = (interaction: CommandInteraction) => { return true; }; -export { command }; -export { callback }; -export { check }; +export { command, callback, check }; +export const metadata = { + longDescription: "Shows the moderation history (all previous bans, kicks, warns etc.), and moderator notes for a user.", + premiumOnly: true, +} diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts index 362bde8..7e67222 100644 --- a/src/commands/mod/ban.ts +++ b/src/commands/mod/ban.ts @@ -199,3 +199,7 @@ const check = async (interaction: CommandInteraction, partial: boolean = false) }; export { command, callback, check }; +export const metadata = { + longDescription: "Removes a member from the server - this will prevent them from rejoining until they are unbanned, and will delete a specified number of days of messages from them.", + premiumOnly: true, +} diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts index d9418e6..6743ebf 100644 --- a/src/commands/mod/kick.ts +++ b/src/commands/mod/kick.ts @@ -197,3 +197,7 @@ const check = (interaction: CommandInteraction, partial: boolean = false) => { }; export { command, callback, check }; +export const metadata = { + longDescription: "Removes a member from the server. They will be able to rejoin if they have an invite link.", + premiumOnly: true, +} diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts index ef677df..b7c1405 100644 --- a/src/commands/mod/mute.ts +++ b/src/commands/mod/mute.ts @@ -389,3 +389,7 @@ const check = async (interaction: CommandInteraction, partial: boolean = false) }; export { command, callback, check }; +export const metadata = { + longDescription: "Stops a member from being able to send messages or join voice channels for a specified amount of time.", + premiumOnly: true, +} diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts index 2787a51..9d5aa3a 100644 --- a/src/commands/mod/nick.ts +++ b/src/commands/mod/nick.ts @@ -217,3 +217,7 @@ const check = async (interaction: CommandInteraction, partial: boolean = false) }; export { command, callback, check }; +export const metadata = { + longDescription: "Changes the nickname of a member. This is the name that shows in the member list and on messages.", + premiumOnly: true, +} diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts index 89f311f..6673c97 100644 --- a/src/commands/mod/purge.ts +++ b/src/commands/mod/purge.ts @@ -407,3 +407,7 @@ const check = (interaction: CommandInteraction, partial: boolean = false) => { }; export { command, callback, check }; +export const metadata = { + longDescription: "Deletes a specified amount of messages from a channel, optionally from a specific user. Without an amount, you can repeatedly choose a number of messages to delete.", + premiumOnly: true, +} diff --git a/src/commands/mod/slowmode.ts b/src/commands/mod/slowmode.ts index 886d4bb..8d5b709 100644 --- a/src/commands/mod/slowmode.ts +++ b/src/commands/mod/slowmode.ts @@ -88,3 +88,7 @@ const check = (interaction: CommandInteraction, partial: boolean = false) => { }; export { command, callback, check }; +export const metadata = { + longDescription: "Stops members from being able to send messages without waiting a certain amount of time between messages.", + premiumOnly: true, +} diff --git a/src/commands/settings/filters/_meta.ts b/src/commands/settings/filters/_meta.ts new file mode 100644 index 0000000..d2aff53 --- /dev/null +++ b/src/commands/settings/filters/_meta.ts @@ -0,0 +1,8 @@ +import { group } from "../../../utils/commandRegistration/slashCommandBuilder.js"; + +const name = "filters"; +const description = "Settings for filters"; + +const subcommand = await group(name, description, `settings/filters`) + +export { name, description, subcommand as command}; diff --git a/src/commands/settings/rolemenu.ts b/src/commands/settings/rolemenu.ts index 1591273..8796892 100644 --- a/src/commands/settings/rolemenu.ts +++ b/src/commands/settings/rolemenu.ts @@ -9,7 +9,9 @@ import createPageIndicator from "../../utils/createPageIndicator.js"; import { configToDropdown } from "../../actions/roleMenu.js"; import { modalInteractionCollector } from "../../utils/dualCollector.js"; import lodash from 'lodash'; + const isEqual = lodash.isEqual; + const command = (builder: SlashCommandSubcommandBuilder) => builder .setName("rolemenu") @@ -37,6 +39,60 @@ const defaultRolePageConfig = { ] } +const reorderRoleMenuPages = async (interaction: CommandInteraction, m: Message, currentObj: ObjectSchema[]) => { + let reorderRow = new ActionRowBuilder() + .addComponents( + new StringSelectMenuBuilder() + .setCustomId("reorder") + .setPlaceholder("Select a page to move...") + .setMinValues(1) + .addOptions( + currentObj.map((o, i) => new StringSelectMenuOptionBuilder() + .setLabel(o.name) + .setValue(i.toString()) + ) + ) + ); + let buttonRow = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId("back") + .setLabel("Back") + .setStyle(ButtonStyle.Secondary) + .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji) + ) + await interaction.editReply({ + embeds: [ + new EmojiEmbed() + .setTitle("Role Menu") + .setDescription("Select pages in the order you want them to appear.") + .setStatus("Success") + ], + components: [reorderRow, buttonRow] + }); + let out: StringSelectMenuInteraction | ButtonInteraction | null; + try { + out = await m.awaitMessageComponent({ + filter: (i) => i.channel!.id === interaction.channel!.id, + time: 300000 + }) as StringSelectMenuInteraction | ButtonInteraction | null; + } catch (e) { + console.error(e); + out = null; + } + if(!out) return; + if (out.isButton()) return; + if(!out.values) return; + const values = out.values; + + const newOrder: ObjectSchema[] = currentObj.map((_, i) => { + const index = values.findIndex(v => v === i.toString()); + return currentObj[index]; + }) as ObjectSchema[]; + + return newOrder; +} + const editNameDescription = async (i: ButtonInteraction, interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data: {name?: string, description?: string}) => { let {name, description} = data; @@ -374,6 +430,9 @@ const callback = async (interaction: CommandInteraction): Promise => { page = currentObject.length - 1; break; case "reorder": + let reordered = await reorderRoleMenuPages(interaction, m, currentObject); + if(!reordered) break; + currentObject = reordered; break; case "save": client.database.guilds.write(interaction.guild.id, {"roleMenu.options": currentObject}); diff --git a/src/commands/settings/tracks.ts b/src/commands/settings/tracks.ts new file mode 100644 index 0000000..0cad55c --- /dev/null +++ b/src/commands/settings/tracks.ts @@ -0,0 +1,26 @@ +import type { CommandInteraction, GuildMember, SlashCommandSubcommandBuilder } from "discord.js"; +import client from "../../utils/client.js"; + + +const command = (builder: SlashCommandSubcommandBuilder) => + builder + .setName("tracks") + .setDescription("Manage the tracks for the server") + + +const callback = async (interaction: CommandInteraction) => { + + + +} + +const check = (interaction: CommandInteraction, _partial: boolean = false) => { + const member = interaction.member as GuildMember; + if (!member.permissions.has("ManageRoles")) + return "You must have the *Manage Server* permission to use this command"; + return true; +}; + +export { command }; +export { callback }; +export { check }; diff --git a/src/reflex/scanners.ts b/src/reflex/scanners.ts index 9761e4b..f69156a 100644 --- a/src/reflex/scanners.ts +++ b/src/reflex/scanners.ts @@ -80,7 +80,7 @@ export async function testLink(link: string): Promise<{ safe: boolean; tags: str } export async function saveAttachment(link: string): Promise { - const image = (await (await fetch(link)).buffer()).toString("base64"); + const image = (await fetch(link)).arrayBuffer().toString(); const fileName = generateFileName(link.split("/").pop()!.split(".").pop()!); writeFileSync(fileName, image, "base64"); return fileName;