diff options
author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-01-23 18:13:05 -0500 |
---|---|---|
committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-01-23 18:13:05 -0500 |
commit | a3f8d3884a1deca5eccfb6d990e2a7b42fbbe08a (patch) | |
tree | 9b0f8ed8a93c22c90512751e3f2f5937e1925760 /src | |
parent | 5557677f1570eb564a30cfcebb6030235dc84d47 (diff) | |
download | tanzanite-a3f8d3884a1deca5eccfb6d990e2a7b42fbbe08a.tar.gz tanzanite-a3f8d3884a1deca5eccfb6d990e2a7b42fbbe08a.tar.bz2 tanzanite-a3f8d3884a1deca5eccfb6d990e2a7b42fbbe08a.zip |
fix discord.js breaking changes, some other stuff
Diffstat (limited to 'src')
159 files changed, 1375 insertions, 968 deletions
diff --git a/src/arguments/messageLink.ts b/src/arguments/messageLink.ts index 2a9800c..565fab1 100644 --- a/src/arguments/messageLink.ts +++ b/src/arguments/messageLink.ts @@ -13,7 +13,7 @@ export const messageLink: BushArgumentTypeCaster<Promise<Message | null>> = asyn if (!guild) return null; const channel = guild.channels.cache.get(channel_id); - if (!channel || (!channel.isText() && !channel.isThread())) return null; + if (!channel || (!channel.isTextBased() && !channel.isThread())) return null; const message = await channel.messages.fetch(message_id).catch(() => null); return message; diff --git a/src/commands/_fake-command/ironmoon.ts b/src/commands/_fake-command/ironmoon.ts index 428b554..1f63c06 100644 --- a/src/commands/_fake-command/ironmoon.ts +++ b/src/commands/_fake-command/ironmoon.ts @@ -12,6 +12,7 @@ export default class IronmoonCommand extends BushCommand { userPermissions: [] }); } + public override condition(message: BushMessage): boolean { return false; if (message.content.toLowerCase().includes('ironmoon')) return true; diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts index 026f1a6..f0d2c65 100644 --- a/src/commands/admin/channelPermissions.ts +++ b/src/commands/admin/channelPermissions.ts @@ -1,5 +1,5 @@ import { BushCommand, ButtonPaginator, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; export default class ChannelPermissionsCommand extends BushCommand { public constructor() { @@ -18,7 +18,7 @@ export default class ChannelPermissionsCommand extends BushCommand { readableType: 'member|role', prompt: 'What user/role would you like to change?', retry: '{error} Choose a valid user/role to change.', - slashType: 'MENTIONABLE' + slashType: ApplicationCommandOptionType.Mentionable }, { id: 'permission', @@ -26,7 +26,7 @@ export default class ChannelPermissionsCommand extends BushCommand { type: 'permission', prompt: 'What permission would you like to change?', retry: '{error} Choose a valid permission.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'state', @@ -39,7 +39,7 @@ export default class ChannelPermissionsCommand extends BushCommand { readableType: "'enable'|'disable'|'remove'", prompt: 'What should that permission be set to?', retry: '{error} Set the state to either `enable`, `disable`, or `remove`.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: [ { name: 'Enabled', value: 'true' }, { name: 'Disabled', value: 'false' }, @@ -47,8 +47,8 @@ export default class ChannelPermissionsCommand extends BushCommand { ] } ], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS']), - userPermissions: ['ADMINISTRATOR'], + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS]), + userPermissions: [Permissions.FLAGS.ADMINISTRATOR], channel: 'guild', slash: true }); @@ -63,7 +63,7 @@ export default class ChannelPermissionsCommand extends BushCommand { } ) { if (!message.inGuild()) return await message.util.reply(`${util.emojis.error} This command can only be run in a server.`); - if (!message.member!.permissions.has('ADMINISTRATOR') && !message.member!.user.isOwner()) + if (!message.member!.permissions.has(Permissions.FLAGS.ADMINISTRATOR) && !message.member!.user.isOwner()) return await message.util.reply(`${util.emojis.error} You must have admin perms to use this command.`); if (message.util.isSlashMessage(message)) await message.interaction.deferReply(); diff --git a/src/commands/admin/roleAll.ts b/src/commands/admin/roleAll.ts index 6e82011..3b438d9 100644 --- a/src/commands/admin/roleAll.ts +++ b/src/commands/admin/roleAll.ts @@ -1,5 +1,5 @@ import { AllowedMentions, BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, Permissions, type GuildMember } from 'discord.js'; export default class RoleAllCommand extends BushCommand { public constructor() { @@ -16,7 +16,7 @@ export default class RoleAllCommand extends BushCommand { type: 'role', prompt: 'What role would you like to give to every member on the server?', retry: '{error} Pick a valid role.', - slashType: 'ROLE' + slashType: ApplicationCommandOptionType.Role }, { id: 'bots', @@ -25,13 +25,13 @@ export default class RoleAllCommand extends BushCommand { prompt: 'Would you like to also give roles to bots?', flag: '--bots', default: false, - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']), - userPermissions: ['ADMINISTRATOR'], + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_ROLES]), + userPermissions: [Permissions.FLAGS.ADMINISTRATOR], typing: true, slash: true }); @@ -39,7 +39,7 @@ export default class RoleAllCommand extends BushCommand { public override async exec(message: BushMessage | BushSlashMessage, args: { role: ArgType<'role'>; bots: ArgType<'boolean'> }) { if (!message.inGuild()) return await message.util.reply(`${util.emojis.error} This command can only be run in a server.`); - if (!message.member!.permissions.has('ADMINISTRATOR') && !message.member!.user.isOwner()) + if (!message.member!.permissions.has(Permissions.FLAGS.ADMINISTRATOR) && !message.member!.user.isOwner()) return await message.util.reply(`${util.emojis.error} You must have admin perms to use this command.`); if (message.util.isSlashMessage(message)) await message.interaction.deferReply(); diff --git a/src/commands/config/_customAutomodPhrases.ts b/src/commands/config/_customAutomodPhrases.ts index cd59c9a..1c91f28 100644 --- a/src/commands/config/_customAutomodPhrases.ts +++ b/src/commands/config/_customAutomodPhrases.ts @@ -1,4 +1,5 @@ // import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; +// import { Permissions } from 'discord.js'; // export default class CustomAutomodPhrasesCommand extends BushCommand { // public constructor() { @@ -15,7 +16,7 @@ // description: 'This is the first argument.', // prompt: 'What would you like to set your first argument to be?', // retry: '{error} Pick a valid argument.', -// slashType: 'STRING' +// slashType: ApplicationCommandOptionType.String // }, // { // id: 'optional_argument', @@ -24,13 +25,13 @@ // prompt: 'What would you like to set your second argument to be?', // retry: '{error} Pick a valid argument.', // optional: true, -// slashType: 'STRING' +// slashType: ApplicationCommandOptionType.String // } // ], // slash: true, // channel: 'guild', // clientPermissions: (m) => util.clientSendAndPermCheck(m), -// userPermissions: ['MANAGE_GUILD'] +// userPermissions: [Permissions.FLAGS.MANAGE_GUILD] // }); // } diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts index d15b8d7..0498b87 100644 --- a/src/commands/config/blacklist.ts +++ b/src/commands/config/blacklist.ts @@ -1,5 +1,5 @@ import { AllowedMentions, BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { User } from 'discord.js'; +import { ApplicationCommandOptionType, Permissions, User } from 'discord.js'; export default class BlacklistCommand extends BushCommand { public constructor() { @@ -15,7 +15,7 @@ export default class BlacklistCommand extends BushCommand { description: 'Whether to blacklist or unblacklist the target.', readableType: "'blacklist'|'unblacklist'", prompt: 'Would you like to add or remove someone or something from/to the blacklist?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: ['blacklist', 'unblacklist'].map((c) => ({ name: c, value: c })), only: 'slash' }, @@ -26,7 +26,7 @@ export default class BlacklistCommand extends BushCommand { readableType: 'channel|user', prompt: 'What channel or user that you would like to blacklist/unblacklist?', retry: '{error} Pick a valid user or channel.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'global', @@ -42,7 +42,7 @@ export default class BlacklistCommand extends BushCommand { slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['MANAGE_GUILD'] + userPermissions: [Permissions.FLAGS.MANAGE_GUILD] }); } diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts index 6e08cc3..41bdc04 100644 --- a/src/commands/config/config.ts +++ b/src/commands/config/config.ts @@ -9,16 +9,20 @@ import { type GuildSettingType } from '#lib'; import assert from 'assert'; -import { type ArgumentOptions, type Flag } from 'discord-akairo'; +import { SlashOption, type ArgumentOptions, type Flag } from 'discord-akairo'; import { + ActionRow, + ApplicationCommandOptionType, + ButtonComponent, + ButtonStyle, Channel, Formatters, GuildMember, - MessageActionRow, - MessageButton, MessageEmbed, - MessageSelectMenu, + Permissions, Role, + SelectMenuComponent, + SelectMenuOption, User, type Message, type MessageComponentInteraction, @@ -37,33 +41,45 @@ export default class ConfigCommand extends BushCommand { ], examples: ['settings', 'config prefix set -'], slash: true, - slashOptions: settingsArr.map((setting) => { + slashOptions: settingsArr.map((setting): SlashOption => { const obj = guildSettingsObj[setting]; const type = obj.type; const baseTypeUpper = type.replace('-array', '').toUpperCase() as SlashArgType; const isArray = type.includes('-array'); const loweredName = obj.name.toLowerCase(); + const enumType = + baseTypeUpper === 'CHANNEL' + ? ApplicationCommandOptionType.Channel + : baseTypeUpper === 'ROLE' + ? ApplicationCommandOptionType.Role + : baseTypeUpper === 'STRING' + ? ApplicationCommandOptionType.String + : baseTypeUpper === 'USER' + ? ApplicationCommandOptionType.User + : new Error(`Unknown type: ${type}`); + if (enumType instanceof Error) throw enumType; + return { name: _.snakeCase(setting), description: `Manage the server's ${loweredName}`, - type: 'SUB_COMMAND_GROUP', + type: ApplicationCommandOptionType.SubcommandGroup, options: isArray ? [ { name: 'view', description: `View the server's ${loweredName}.`, - type: 'SUB_COMMAND' + type: ApplicationCommandOptionType.Subcommand }, { name: 'add', description: `Add a value to the server's ${loweredName}.`, - type: 'SUB_COMMAND', + type: ApplicationCommandOptionType.Subcommand, options: [ { name: 'value', description: `What would you like to add to the server's ${loweredName}?'`, - type: baseTypeUpper, + type: enumType, channelTypes: baseTypeUpper === 'CHANNEL' && obj.subType ? obj.subType : undefined, required: true } @@ -72,12 +88,12 @@ export default class ConfigCommand extends BushCommand { { name: 'remove', description: `Remove a value from the server's ${loweredName}.`, - type: 'SUB_COMMAND', + type: ApplicationCommandOptionType.Subcommand, options: [ { name: 'value', description: `What would you like to remove from the server's ${loweredName}?'`, - type: baseTypeUpper, + type: enumType, channelTypes: baseTypeUpper === 'CHANNEL' && obj.subType ? obj.subType : undefined, required: true } @@ -88,17 +104,17 @@ export default class ConfigCommand extends BushCommand { { name: 'view', description: `View the server's ${loweredName}.`, - type: 'SUB_COMMAND' + type: ApplicationCommandOptionType.Subcommand }, { name: 'set', description: `Set the server's ${loweredName}.`, - type: 'SUB_COMMAND', + type: ApplicationCommandOptionType.Subcommand, options: [ { name: 'value', description: `What would you like to set the server's ${loweredName} to?'`, - type: baseTypeUpper, + type: enumType, channelTypes: baseTypeUpper === 'CHANNEL' && obj.subType ? obj.subType : undefined, required: true } @@ -109,7 +125,7 @@ export default class ConfigCommand extends BushCommand { }), channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['MANAGE_GUILD'] + userPermissions: [Permissions.FLAGS.MANAGE_GUILD] }); } @@ -192,8 +208,8 @@ export default class ConfigCommand extends BushCommand { } ) { if (!message.guild) return await message.util.reply(`${util.emojis.error} This command can only be used in servers.`); - if (!message.member?.permissions.has('MANAGE_GUILD') && !message.member?.user.isOwner()) - return await message.util.reply(`${util.emojis.error} You must have the **MANAGE_GUILD** permission to run this command.`); + if (!message.member?.permissions.has(Permissions.FLAGS.MANAGE_GUILD) && !message.member?.user.isOwner()) + return await message.util.reply(`${util.emojis.error} You must have the **Manage Server** permission to run this command.`); const setting = message.util.isSlash ? (_.camelCase(args.subcommandGroup)! as GuildSettings) : args.setting!; const action = message.util.isSlash ? args.subcommand! : args.action!; const value = args.value; @@ -278,14 +294,15 @@ export default class ConfigCommand extends BushCommand { const desc = settingsArr.map((s) => `:wrench: **${guildSettingsObj[s].name}**`).join('\n'); settingsEmbed.setDescription(desc); - const selMenu = new MessageActionRow().addComponents( - new MessageSelectMenu() + const selMenu = new ActionRow().addComponents( + new SelectMenuComponent() .addOptions( - ...settingsArr.map((s) => ({ - label: guildSettingsObj[s].name, - value: s, - description: guildSettingsObj[s].description - })) + ...settingsArr.map((s) => + new SelectMenuOption() + .setLabel(guildSettingsObj[s].name) + .setValue(s) + .setDescription(guildSettingsObj[s].description) + ) ) .setPlaceholder('Select A Setting to View') .setMaxValues(1) @@ -335,8 +352,8 @@ export default class ConfigCommand extends BushCommand { : '[No Value Set]'; }; - const components = new MessageActionRow().addComponents( - new MessageButton().setStyle('PRIMARY').setCustomId('command_settingsBack').setLabel('Back') + const components = new ActionRow().addComponents( + new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId('command_settingsBack').setLabel('Back') ); settingsEmbed.setDescription( `${Formatters.italic(guildSettingsObj[setting].description)}\n\n**Type**: ${guildSettingsObj[setting].type}` diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts index 564f90f..d59ff55 100644 --- a/src/commands/config/disable.ts +++ b/src/commands/config/disable.ts @@ -1,6 +1,6 @@ import { AllowedMentions, BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { AutocompleteInteraction } from 'discord.js'; +import { ApplicationCommandOptionType, AutocompleteInteraction, Permissions } from 'discord.js'; import Fuse from 'fuse.js'; assert(Fuse); @@ -20,7 +20,7 @@ export default class DisableCommand extends BushCommand { description: 'Whether to disable or enable the command.', readableType: "'disable'|'enable", prompt: 'Would you like to disable or enable a command?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: ['disable', 'enable'].map((v) => ({ name: v, value: v })), only: 'slash' }, @@ -31,7 +31,7 @@ export default class DisableCommand extends BushCommand { readableType: 'command|commandAlias', prompt: 'What command would you like to enable/disable?', retry: '{error} Pick a valid command.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, autocomplete: true }, { @@ -48,7 +48,7 @@ export default class DisableCommand extends BushCommand { slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['MANAGE_GUILD'] + userPermissions: [Permissions.FLAGS.MANAGE_GUILD] }); } diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts index 894c90a..fdd6c1e 100644 --- a/src/commands/config/features.ts +++ b/src/commands/config/features.ts @@ -6,7 +6,16 @@ import { type BushSlashMessage, type GuildFeatures } from '#lib'; -import { MessageActionRow, MessageEmbed, MessageSelectMenu, type Message, type SelectMenuInteraction } from 'discord.js'; +import { + ActionRow, + ComponentType, + MessageEmbed, + Permissions, + SelectMenuComponent, + SelectMenuOption, + type Message, + type SelectMenuInteraction +} from 'discord.js'; export default class FeaturesCommand extends BushCommand { public constructor() { @@ -18,8 +27,8 @@ export default class FeaturesCommand extends BushCommand { examples: ['features'], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), - userPermissions: ['MANAGE_GUILD'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), + userPermissions: [Permissions.FLAGS.MANAGE_GUILD] }); } @@ -33,7 +42,7 @@ export default class FeaturesCommand extends BushCommand { const components = this.generateComponents(guildFeaturesArr, false); const msg = (await message.util.reply({ embeds: [featureEmbed], components: [components] })) as Message; const collector = msg.createMessageComponentCollector({ - componentType: 'SELECT_MENU', + componentType: ComponentType.SelectMenu, time: 300_000, filter: (i) => i.guildId === msg.guildId && i.message?.id === msg.id }); @@ -74,19 +83,17 @@ export default class FeaturesCommand extends BushCommand { } public generateComponents(guildFeatures: GuildFeatures[], disable: boolean) { - return new MessageActionRow().addComponents( - new MessageSelectMenu({ - customId: 'command_selectFeature', - disabled: disable, - maxValues: 1, - minValues: 1, - options: guildFeatures.map((f) => ({ - label: guildFeaturesObj[f].name, - value: f, - description: guildFeaturesObj[f].description - })), - placeholder: 'Select A Feature to Toggle' - }) + return new ActionRow().addComponents( + new SelectMenuComponent() + .setCustomId('command_selectFeature') + .setDisabled(disable) + .setMaxValues(1) + .setMinValues(1) + .setOptions( + guildFeatures.map((f) => + new SelectMenuOption().setLabel(guildFeaturesObj[f].name).setValue(f).setDescription(guildFeaturesObj[f].description) + ) + ) ); } } diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts index 3072866..5906623 100644 --- a/src/commands/config/log.ts +++ b/src/commands/config/log.ts @@ -1,5 +1,6 @@ import { BushCommand, guildLogsArr, type ArgType, type BushMessage, type BushSlashMessage, type GuildLogType } from '#lib'; import { type ArgumentOptions, type Flag } from 'discord-akairo'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class LogCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class LogCommand extends BushCommand { id: 'log_type', description: 'The log type to change.', prompt: 'What log type would you like to change?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: guildLogsArr.map((log) => ({ name: log, value: log })), only: 'slash' }, @@ -24,14 +25,14 @@ export default class LogCommand extends BushCommand { description: 'The channel to have logs of the selected type to be sent in.', type: 'channel', prompt: 'What channel would you like these logs to be sent in?', - slashType: 'CHANNEL', - channelTypes: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], only: 'slash' } ], channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['MANAGE_GUILD'] + userPermissions: [Permissions.FLAGS.MANAGE_GUILD] }); } diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts index 6adba08..7ea1784 100644 --- a/src/commands/dev/__template.ts +++ b/src/commands/dev/__template.ts @@ -1,4 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage, type OptionalArgType } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class TemplateCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class TemplateCommand extends BushCommand { type: 'string', prompt: 'What would you like to set your first argument to be?', retry: '{error} Pick a valid argument.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'optional_argument', @@ -24,7 +25,7 @@ export default class TemplateCommand extends BushCommand { prompt: 'What would you like to set your second argument to be?', retry: '{error} Pick a valid argument.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: false, //set this to true diff --git a/src/commands/dev/debug.ts b/src/commands/dev/debug.ts new file mode 100644 index 0000000..f8c614d --- /dev/null +++ b/src/commands/dev/debug.ts @@ -0,0 +1,79 @@ +// import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; +// import { ApplicationCommandOptionType, AutocompleteInteraction, ChatInputCommandInteraction } from 'discord.js'; +// import Fuse from 'fuse.js'; + +// export default class DebugCommand extends BushCommand { +// public constructor() { +// super('debug', { +// aliases: ['debug'], +// category: 'debug', +// description: 'Command description.', +// usage: ['template <requiredArg> [optionalArg]'], +// examples: ['template 1 2'], +// args: [ +// { +// id: 'action', +// description: 'Debug action.', +// type: 'string', +// prompt: 'Debug action.', +// retry: '{error} Pick valid action.', +// slashType: ApplicationCommandOptionType.String, +// autocomplete: true +// } +// ], +// slash: true, +// slashGuilds: ['516977525906341928'], +// superUserOnly: true, +// clientPermissions: (m) => util.clientSendAndPermCheck(m), +// userPermissions: [] +// }); +// } + +// public override async exec(message: BushMessage | BushSlashMessage, args: { action: ArgType<'string'> }) { +// if (args.action === 'util.reply') { +// return await message.util.reply(`This is a util.reply`); +// } else if (args.action === 'util.reply-object') { +// return await message.util.reply({ +// content: `This is a util.reply with object parameters`, +// embeds: [{ description: 'And an embed' }] +// }); +// } else if (args.action === 'util.send') { +// return await message.util.send(`This is a util.send`); +// } else if (args.action === 'util.send-object') { +// return await message.util.send({ +// content: `This is a util.send with object parameters`, +// embeds: [{ description: 'And an embed' }] +// }); +// } else if (args.action === 'interaction.reply') { +// return await (message.interaction as ChatInputCommandInteraction).reply(`This is a interaction.reply`); +// } else if (args.action === 'interaction.reply-object') { +// return await (message.interaction as ChatInputCommandInteraction).reply({ +// content: `This is a interaction.reply with object parameters`, +// embeds: [{ description: 'And an embed' }] +// }); +// } else { +// return await message.util.reply(`${util.emojis.error} Invalid action.`); +// } +// } + +// public override autocomplete(interaction: AutocompleteInteraction) { +// const actions = [ +// 'util.reply', +// 'util.reply-object', +// 'util.send', +// 'util.send-object', +// 'interaction.reply', +// 'interaction.reply-object' +// ]; + +// const fuzzy = new Fuse(actions, { +// threshold: 0.5, +// isCaseSensitive: false, +// findAllMatches: true +// }).search(interaction.options.getFocused().toString()); + +// const res = fuzzy.slice(0, fuzzy.length >= 25 ? 25 : undefined).map((v) => ({ name: v.item, value: v.item })); + +// void interaction.respond(res.length ? res : actions.map((v) => ({ name: v, value: v }))); +// } +// } diff --git a/src/commands/dev/dm.ts b/src/commands/dev/dm.ts index d702875..0646f59 100644 --- a/src/commands/dev/dm.ts +++ b/src/commands/dev/dm.ts @@ -1,4 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class DMCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class DMCommand extends BushCommand { description: 'The user to send the dm to.', prompt: 'Who would you like to dm?', retry: '{error} Pick a valid user to send a dm to.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'content', @@ -24,7 +25,7 @@ export default class DMCommand extends BushCommand { description: 'The content to send to the user.', prompt: 'What would you like to send to the user?', retry: '{error} Pick something to send the user.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: false, @@ -34,6 +35,7 @@ export default class DMCommand extends BushCommand { userPermissions: [] }); } + public override async exec( message: BushMessage | BushSlashMessage, args: { user: ArgType<'user'>; content: ArgType<'string'> } diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 656eeff..92b1117 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -12,26 +12,28 @@ import { StickyRole, type ArgType } from '#lib'; +import { Snowflake as Snowflake_ } from '@sapphire/snowflake'; import { Canvas } from 'canvas'; import { exec } from 'child_process'; import { + ActionRow, + ApplicationCommandOptionType, + ButtonComponent, ButtonInteraction, Collection, Collector, CommandInteraction, - ContextMenuInteraction, + ContextMenuCommandInteraction, DMChannel, Emoji, Interaction, InteractionCollector, Message, - MessageActionRow, MessageAttachment, - MessageButton, MessageCollector, MessageEmbed, - MessageSelectMenu, ReactionCollector, + SelectMenuComponent, Util } from 'discord.js'; import ts from 'typescript'; @@ -39,7 +41,8 @@ import { promisify } from 'util'; const { transpile } = ts, emojis = util.emojis, colors = util.colors, - sh = promisify(exec); + sh = promisify(exec), + SnowflakeUtil = new Snowflake_(1420070400000n); /* eslint-enable @typescript-eslint/no-unused-vars */ export default class EvalCommand extends BushCommand { @@ -57,7 +60,7 @@ export default class EvalCommand extends BushCommand { match: 'rest', prompt: 'What would you like to eval?', retry: '{error} Invalid code to eval.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'sel_depth', @@ -67,7 +70,7 @@ export default class EvalCommand extends BushCommand { flag: '--depth', default: 0, prompt: 'How deep would you like to inspect the output?', - slashType: 'INTEGER', + slashType: ApplicationCommandOptionType.Integer, optional: true }, { @@ -76,7 +79,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--sudo', prompt: 'Would you like to override checks?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -95,7 +98,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--silent', prompt: 'Would you like to make the response silent?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -104,7 +107,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--ts', prompt: 'Is this code written in typescript?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -113,7 +116,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--hidden', prompt: 'Would you like to show hidden items?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -122,7 +125,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--proto', prompt: 'Would you like to show the prototype of the output?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -131,7 +134,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: ['--func', '--function', '--functions', '--meth', '--method', '--methods'], prompt: 'Would you like to inspect the prototype chain to find methods?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -140,7 +143,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: '--async', prompt: 'Would you like to wrap the code in an async function?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -149,7 +152,7 @@ export default class EvalCommand extends BushCommand { match: 'flag', flag: ['--strings', '--string'], prompt: 'Would you like to not inspect strings?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], @@ -242,9 +245,7 @@ export default class EvalCommand extends BushCommand { embed.addField('📤 Error', await util.inspectCleanRedactCodeblock(e, 'js')); } - embed - .setTimestamp() - .setFooter({ text: message.author.tag, iconURL: message.author.displayAvatarURL({ dynamic: true }) ?? undefined }); + embed.setTimestamp().setFooter({ text: message.author.tag, iconURL: message.author.displayAvatarURL() ?? undefined }); if (!args.silent || message.util.isSlashMessage(message)) { await message.util.reply({ embeds: [embed] }); @@ -260,4 +261,4 @@ export default class EvalCommand extends BushCommand { } } -/** @typedef {ActivePunishment|Global|Guild|Level|ModLog|StickyRole|ButtonInteraction|Collection|Collector|CommandInteraction|ContextMenuInteraction|DMChannel|Emoji|Interaction|InteractionCollector|Message|MessageActionRow|MessageAttachment|MessageButton|MessageCollector|MessageSelectMenu|ReactionCollector|Util|Canvas|Shared} VSCodePleaseDontRemove */ +/** @typedef {ActivePunishment|Global|Guild|Level|ModLog|StickyRole|ButtonInteraction|Collection|Collector|CommandInteraction|ContextMenuCommandInteraction|DMChannel|Emoji|Interaction|InteractionCollector|Message|ActionRow|MessageAttachment|ButtonComponent|MessageCollector|SelectMenuComponent|ReactionCollector|Util|Canvas|Shared} VSCodePleaseDontRemove */ diff --git a/src/commands/dev/javascript.ts b/src/commands/dev/javascript.ts index c8113aa..9d6a20b 100644 --- a/src/commands/dev/javascript.ts +++ b/src/commands/dev/javascript.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed } from 'discord.js'; import { VM } from 'vm2'; assert(VM); @@ -19,7 +19,7 @@ export default class JavascriptCommand extends BushCommand { match: 'rest', prompt: 'What code would you like to run in a sand boxed environment?', retry: '{error} Invalid code to run in a sand boxed environment.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'sel_depth', @@ -29,7 +29,7 @@ export default class JavascriptCommand extends BushCommand { flag: '--depth', default: 0, prompt: 'How deep would you like to inspect the output?', - slashType: 'INTEGER', + slashType: ApplicationCommandOptionType.Integer, optional: true } ], @@ -75,9 +75,7 @@ export default class JavascriptCommand extends BushCommand { embed.addField('📤 Error', await util.inspectCleanRedactCodeblock(e, 'js')); } - embed - .setTimestamp() - .setFooter({ text: message.author.tag, iconURL: message.author.displayAvatarURL({ dynamic: true }) ?? undefined }); + embed.setTimestamp().setFooter({ text: message.author.tag, iconURL: message.author.displayAvatarURL() ?? undefined }); await message.util.reply({ embeds: [embed] }); } diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts index 6d030b7..d874c83 100644 --- a/src/commands/dev/reload.ts +++ b/src/commands/dev/reload.ts @@ -16,7 +16,7 @@ export default class ReloadCommand extends BushCommand { // flag: '--fast', // prompt: 'Would you like to use esbuild for fast compiling?', // optional: true, - // slashType:'BOOLEAN' + // slashType: ApplicationCommandOptionType.Boolean // } // ], ownerOnly: true, diff --git a/src/commands/dev/say.ts b/src/commands/dev/say.ts index 2c8151f..bbada0c 100644 --- a/src/commands/dev/say.ts +++ b/src/commands/dev/say.ts @@ -1,4 +1,5 @@ import { AllowedMentions, BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class SayCommand extends BushCommand { public constructor() { @@ -16,7 +17,7 @@ export default class SayCommand extends BushCommand { match: 'rest', prompt: 'What would you like the bot to say?', retry: '{error} Choose something for the bot to send.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], ownerOnly: true, diff --git a/src/commands/dev/sh.ts b/src/commands/dev/sh.ts index 9956897..f74dedf 100644 --- a/src/commands/dev/sh.ts +++ b/src/commands/dev/sh.ts @@ -2,8 +2,9 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; import chalk from 'chalk'; import { exec } from 'child_process'; -import { MessageEmbed, Util } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Util } from 'discord.js'; import { promisify } from 'util'; + assert(chalk); const sh = promisify(exec); @@ -30,7 +31,7 @@ export default class ShCommand extends BushCommand { match: 'rest', prompt: 'What would you like run', retry: '{error} Invalid command to run.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], ownerOnly: true, @@ -46,7 +47,7 @@ export default class ShCommand extends BushCommand { const embed = new MessageEmbed() .setColor(util.colors.gray) - .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL({ dynamic: true }) ?? undefined }) + .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined }) .setTimestamp() .setTitle('Shell Command') .addField('📥 Input', await util.codeblock(input, 1024, 'sh', true)) diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index 1ec7f71..63c1112 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,6 +1,13 @@ import { BushCommand, ButtonPaginator, Shared, type BushMessage } from '#lib'; -import { MessageActionRow, MessageButton, MessageEmbed, type ApplicationCommand, type Collection } from 'discord.js'; -import { MessageButtonStyles } from 'discord.js/typings/enums'; +import { + ActionRow, + ActionRowComponent, + ButtonComponent, + ButtonStyle, + MessageEmbed, + type ApplicationCommand, + type Collection +} from 'discord.js'; import badLinksSecretArray from '../../lib/badlinks-secret.js'; import badLinksArray from '../../lib/badlinks.js'; import badWords from '../../lib/badwords.js'; @@ -44,12 +51,12 @@ export default class TestCommand extends BushCommand { } if (['button', 'buttons'].includes(args?.feature?.toLowerCase())) { - const ButtonRow = new MessageActionRow().addComponents( - new MessageButton({ style: MessageButtonStyles.PRIMARY, customId: 'primaryButton', label: 'Primary' }), - new MessageButton({ style: MessageButtonStyles.SECONDARY, customId: 'secondaryButton', label: 'Secondary' }), - new MessageButton({ style: MessageButtonStyles.SUCCESS, customId: 'success', label: 'Success' }), - new MessageButton({ style: MessageButtonStyles.DANGER, customId: 'danger', label: 'Danger' }), - new MessageButton({ style: MessageButtonStyles.LINK, label: 'Link', url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }) + const ButtonRow = new ActionRow().addComponents( + new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId('primaryButton').setLabel('Primary'), + new ButtonComponent().setStyle(ButtonStyle.Secondary).setCustomId('secondaryButton').setLabel('Secondary'), + new ButtonComponent().setStyle(ButtonStyle.Success).setCustomId('successButton').setLabel('Success'), + new ButtonComponent().setStyle(ButtonStyle.Danger).setCustomId('dangerButton').setLabel('Danger'), + new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Link').setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ') ); return await message.util.reply({ content: 'buttons', components: [ButtonRow] }); } else if (['embed', 'button embed'].includes(args?.feature?.toLowerCase())) { @@ -67,25 +74,17 @@ export default class TestCommand extends BushCommand { ) .setTitle('Title'); - const buttonRow = new MessageActionRow().addComponents( - new MessageButton({ - style: MessageButtonStyles.LINK, - label: 'Link', - url: 'https://www.google.com/' - }) + const buttonRow = new ActionRow().addComponents( + new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Link').setURL('https://google.com/') ); return await message.util.reply({ content: 'Test', embeds: [embed], components: [buttonRow] }); } else if (['lots of buttons'].includes(args?.feature?.toLowerCase())) { - const ButtonRows: MessageActionRow[] = []; + const ButtonRows: ActionRow<ActionRowComponent>[] = []; for (let a = 1; a <= 5; a++) { - const row = new MessageActionRow(); + const row = new ActionRow(); for (let b = 1; b <= 5; b++) { const id = (a + 5 * (b - 1)).toString(); - const button = new MessageButton({ - style: MessageButtonStyles.SECONDARY, - customId: id, - label: id - }); + const button = new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId(id).setLabel(id); row.addComponents(button); } ButtonRows.push(row); @@ -99,39 +98,25 @@ export default class TestCommand extends BushCommand { return await ButtonPaginator.send(message, embeds); } else if (['lots of embeds'].includes(args?.feature?.toLowerCase())) { const description = 'This is a description.'; - const _avatar = message.author.avatarURL({ dynamic: true }) ?? undefined; + const _avatar = message.author.avatarURL() ?? undefined; const author = { name: 'This is a author', iconURL: _avatar }; const footer = { text: 'This is a footer', iconURL: _avatar }; - const fields = []; - for (let i = 0; i < 25; i++) { - fields.push({ name: `Field ${i}`, value: `Field Value ${i}` }); - } + const fields = Array(25) + .fill(0) + .map((_, i) => ({ name: `Field ${i}`, value: 'Field Value' })); const c = util.colors; const o = { description, author, footer, fields, time: Date.now() }; - const embeds = [ - { ...o, title: 'Embed Title 0', color: c.red }, - { ...o, title: 'Embed Title 1', color: c.orange }, - { ...o, title: 'Embed Title 2', color: c.gold }, - { ...o, title: 'Embed Title 3', color: c.yellow }, - { ...o, title: 'Embed Title 4', color: c.green }, - { ...o, title: 'Embed Title 5', color: c.darkGreen }, - { ...o, title: 'Embed Title 6', color: c.aqua }, - { ...o, title: 'Embed Title 7', color: c.blue }, - { ...o, title: 'Embed Title 8', color: c.purple }, - { ...o, title: 'Embed Title 9', color: c.pink } - ]; + const colors = [c.red, c.orange, c.gold, c.yellow, c.green, c.darkGreen, c.aqua, c.blue, c.purple, c.pink]; + + const embeds = colors.map((c, i) => ({ ...o, title: `Embed Title ${i}`, color: c })); - const ButtonRows: MessageActionRow[] = []; + const ButtonRows: ActionRow<ActionRowComponent>[] = []; for (let a = 1; a <= 5; a++) { - const row = new MessageActionRow(); + const row = new ActionRow(); for (let b = 1; b <= 5; b++) { const id = (a + 5 * (b - 1)).toString(); - const button = new MessageButton({ - style: MessageButtonStyles.SECONDARY, - customId: id, - label: id - }); + const button = new ButtonComponent().setStyle(ButtonStyle.Secondary).setCustomId(id).setLabel(id); row.addComponents(button); } ButtonRows.push(row); diff --git a/src/commands/fun/eightBall.ts b/src/commands/fun/eightBall.ts index b4d2fbe..ff06fe5 100644 --- a/src/commands/fun/eightBall.ts +++ b/src/commands/fun/eightBall.ts @@ -1,4 +1,5 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class EightBallCommand extends BushCommand { public constructor() { @@ -16,7 +17,7 @@ export default class EightBallCommand extends BushCommand { match: 'rest', prompt: 'What question would you like answered?', retry: '{error} Invalid question.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts index 6878c05..b9737a3 100644 --- a/src/commands/fun/minesweeper.ts +++ b/src/commands/fun/minesweeper.ts @@ -1,6 +1,7 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import { Minesweeper } from '@notenoughupdates/discord.js-minesweeper'; import assert from 'assert'; +import { ApplicationCommandOptionType } from 'discord.js'; assert(Minesweeper); export default class MinesweeperCommand extends BushCommand { @@ -20,7 +21,7 @@ export default class MinesweeperCommand extends BushCommand { retry: '{error} Choose a valid number of rows', optional: true, default: 9, - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer }, { id: 'columns', @@ -30,7 +31,7 @@ export default class MinesweeperCommand extends BushCommand { retry: '{error} Choose a valid number of columns', optional: true, default: 9, - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer }, { id: 'mines', @@ -40,7 +41,7 @@ export default class MinesweeperCommand extends BushCommand { retry: '{error} Choose a valid number of mines', optional: true, default: 10, - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer }, { id: 'spaces', @@ -48,7 +49,7 @@ export default class MinesweeperCommand extends BushCommand { match: 'flag', flag: '--spaces', prompt: 'Would you like there to be spaces?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -57,7 +58,7 @@ export default class MinesweeperCommand extends BushCommand { match: 'flag', flag: '--revealFirstCell', prompt: 'Would you like to automatically reveal the first cell?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts index ce2543f..58d8bca 100644 --- a/src/commands/info/avatar.ts +++ b/src/commands/info/avatar.ts @@ -1,5 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, GuildMember, MessageEmbed, Permissions } from 'discord.js'; export default class AvatarCommand extends BushCommand { constructor() { @@ -18,10 +18,10 @@ export default class AvatarCommand extends BushCommand { prompt: 'Who would you like to see the avatar of?', retry: '{error} Choose a valid user.', optional: true, - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], slash: true }); diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts index fa572e8..3aea3cd 100644 --- a/src/commands/info/botInfo.ts +++ b/src/commands/info/botInfo.ts @@ -1,6 +1,6 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed, version as discordJSVersion } from 'discord.js'; +import { MessageEmbed, Permissions, version as discordJSVersion } from 'discord.js'; import * as os from 'os'; const { default: prettyBytes } = await import('pretty-bytes'); assert(prettyBytes); @@ -15,7 +15,7 @@ export default class BotInfoCommand extends BushCommand { usage: ['bot-info'], examples: ['bot-info'], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts index 5b2c818..d385c53 100644 --- a/src/commands/info/color.ts +++ b/src/commands/info/color.ts @@ -9,7 +9,7 @@ import { type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed, Role } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions, Role } from 'discord.js'; import tinycolor from 'tinycolor2'; assert(tinycolor); @@ -36,11 +36,11 @@ export default class ColorCommand extends BushCommand { match: 'restContent', prompt: 'What color code, role, or user would you like to find the color of?', retry: '{error} Choose a valid color, role, or member.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index 7d3d170..afc5111 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -1,9 +1,14 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage, type OptionalArgType } from '#lib'; import assert from 'assert'; +import { GuildDefaultMessageNotifications, GuildExplicitContentFilter } from 'discord-api-types'; import { - Constants, + ApplicationCommandOptionType, Guild, + GuildMFALevel, + GuildPremiumTier, + GuildVerificationLevel, MessageEmbed, + Permissions, type BaseGuildVoiceChannel, type GuildPreview, type Snowflake, @@ -27,11 +32,11 @@ export default class GuildInfoCommand extends BushCommand { prompt: 'What server would you like to find information about?', retry: '{error} Choose a valid server to find information about.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -66,20 +71,20 @@ export default class GuildInfoCommand extends BushCommand { const guildStats: string[] = []; const guildSecurity: string[] = []; const verifiedGuilds = Object.values(client.consts.mappings.guilds); - if (verifiedGuilds.includes(guild.id as typeof verifiedGuilds[number])) emojis.push(otherEmojis.BUSH_VERIFIED); + if (verifiedGuilds.includes(guild.id as typeof verifiedGuilds[number])) emojis.push(otherEmojis.BushVerified); if (!isPreview && guild instanceof Guild) { - if (guild.premiumTier !== 'NONE') emojis.push(otherEmojis[`BOOST_${guild.premiumTier}`]); + if (guild.premiumTier !== 'None') emojis.push(otherEmojis[`Boost${guild.premiumTier}`]); await guild.fetch(); const channels = guild.channels.cache; - const channelTypes = ( - ['GUILD_TEXT', 'GUILD_VOICE', 'GUILD_STAGE_VOICE', 'GUILD_STORE', 'GUILD_CATEGORY', 'THREAD'] as const - ).map((type) => `${otherEmojis[type]} ${channels.filter((channel) => channel.type.includes(type)).size.toLocaleString()}`); + const channelTypes = (['Text', 'Voice', 'News', 'Stage', 'Store', 'Category', 'Thread'] as const).map( + (type) => `${otherEmojis[`Channel${type}`]} ${channels.filter((channel) => channel[`is${type}`]()).size.toLocaleString()}` + ); const guildRegions = [ ...new Set( - guild.channels.cache.filter((c) => c.isVoice()).map((c) => (c as BaseGuildVoiceChannel).rtcRegion ?? 'automatic') + guild.channels.cache.filter((c) => c.isVoiceBased()).map((c) => (c as BaseGuildVoiceChannel).rtcRegion ?? 'automatic') ) ] as RTCRegion[]; @@ -92,48 +97,42 @@ export default class GuildInfoCommand extends BushCommand { `**Regions:** ${guildRegions.map((region) => client.consts.mappings.regions[region] || region).join(', ')}` ); if (guild.premiumSubscriptionCount) - guildAbout.push( - `**Boosts:** Level ${Constants.PremiumTiers[guild.premiumTier]} with ${guild.premiumSubscriptionCount ?? 0} boosts` - ); - if (guild.me?.permissions.has('MANAGE_GUILD') && guild.vanityURLCode) { + guildAbout.push(`**Boosts:** Level ${guild.premiumTier} with ${guild.premiumSubscriptionCount ?? 0} boosts`); + if (guild.me?.permissions.has(Permissions.FLAGS.MANAGE_GUILD) && guild.vanityURLCode) { const vanityInfo: Vanity = await guild.fetchVanityData(); guildAbout.push(`**Vanity URL:** discord.gg/${vanityInfo.code}`, `**Vanity Uses:** ${vanityInfo.uses?.toLocaleString()}`); } - if (guild.icon) guildAbout.push(`**Icon:** [link](${guild.iconURL({ dynamic: true, size: 4096, format: 'png' })})`); + if (guild.icon) guildAbout.push(`**Icon:** [link](${guild.iconURL({ size: 4096, format: 'png' })})`); if (guild.banner) guildAbout.push(`**Banner:** [link](${guild.bannerURL({ size: 4096, format: 'png' })})`); if (guild.splash) guildAbout.push(`**Splash:** [link](${guild.splashURL({ size: 4096, format: 'png' })})`); const EmojiTierMap = { - TIER_3: 500, - TIER_2: 300, - TIER_1: 100, - NONE: 50 + [GuildPremiumTier.Tier3]: 500, + [GuildPremiumTier.Tier2]: 300, + [GuildPremiumTier.Tier1]: 100, + [GuildPremiumTier.None]: 50 } as const; const StickerTierMap = { - TIER_3: 60, - TIER_2: 30, - TIER_1: 15, - NONE: 0 + [GuildPremiumTier.Tier3]: 60, + [GuildPremiumTier.Tier2]: 30, + [GuildPremiumTier.Tier1]: 15, + [GuildPremiumTier.None]: 0 } as const; guildStats.push( `**Channels:** ${guild.channels.cache.size.toLocaleString()} / 500 (${channelTypes.join(', ')})`, // subtract 1 for @everyone role `**Roles:** ${((guild.roles.cache.size ?? 0) - 1).toLocaleString()} / 250`, - `**Emojis:** ${guild.emojis.cache.size?.toLocaleString() ?? 0} / ${EmojiTierMap[guild.premiumTier]}`, - `**Stickers:** ${guild.stickers.cache.size?.toLocaleString() ?? 0} / ${StickerTierMap[guild.premiumTier]}` + `**Emojis:** ${guild.emojis.cache.size?.toLocaleString() ?? 0} / ${(<any>EmojiTierMap)[guild.premiumTier]}`, + `**Stickers:** ${guild.stickers.cache.size?.toLocaleString() ?? 0} / ${(<any>StickerTierMap)[guild.premiumTier]}` ); guildSecurity.push( - `**Verification Level**: ${guild.verificationLevel.toLowerCase().replace(/_/g, ' ')}`, - `**Explicit Content Filter:** ${guild.explicitContentFilter.toLowerCase().replace(/_/g, ' ')}`, - `**Default Message Notifications:** ${ - typeof guild.defaultMessageNotifications === 'string' - ? guild.defaultMessageNotifications.toLowerCase().replace(/_/g, ' ') - : guild.defaultMessageNotifications - }`, - `**2FA Required**: ${guild.mfaLevel === 'ELEVATED' ? 'yes' : 'no'}` + `**Verification Level**: ${(<any>BushGuildVerificationLevel)[guild.verificationLevel]}`, + `**Explicit Content Filter:** ${(<any>BushGuildExplicitContentFilter)[guild.explicitContentFilter]}`, + `**Default Message Notifications:** ${(<any>BushGuildDefaultMessageNotifications)[guild.defaultMessageNotifications]}`, + `**2FA Required**: ${guild.mfaLevel === GuildMFALevel.Elevated ? 'True' : 'False'}` ); } else { guildAbout.push( @@ -142,8 +141,8 @@ export default class GuildInfoCommand extends BushCommand { }, ${util.emojis.offlineCircle} ${( (guild.approximateMemberCount ?? 0) - (guild.approximatePresenceCount ?? 0) ).toLocaleString()})`, - `**Emojis:** ${(guild as GuildPreview).emojis.size?.toLocaleString() ?? 0}` - // `**Stickers:** ${(guild as GuildPreview).stickers.size}` + `**Emojis:** ${(guild as GuildPreview).emojis.size?.toLocaleString() ?? 0}`, + `**Stickers:** ${(guild as GuildPreview).stickers.size}` ); } @@ -174,7 +173,7 @@ export default class GuildInfoCommand extends BushCommand { .setColor(util.colors.default) .addField('» About', guildAbout.join('\n')); if (guildStats.length) guildInfoEmbed.addField('» Stats', guildStats.join('\n')); - const guildIcon = guild.iconURL({ size: 2048, format: 'png', dynamic: true }); + const guildIcon = guild.iconURL({ size: 2048, format: 'png' }); if (guildIcon) { guildInfoEmbed.setThumbnail(guildIcon); } @@ -203,3 +202,22 @@ type RTCRegion = | 'japan' | 'india' | 'automatic'; + +enum BushGuildVerificationLevel { + 'None' = GuildVerificationLevel.None, + 'Low' = GuildVerificationLevel.Low, + 'Medium' = GuildVerificationLevel.Medium, + 'High' = GuildVerificationLevel.High, + 'Very High' = GuildVerificationLevel.VeryHigh +} + +enum BushGuildExplicitContentFilter { + 'Disabled' = GuildExplicitContentFilter.Disabled, + 'Members Without Roles' = GuildExplicitContentFilter.MembersWithoutRoles, + 'All Members' = GuildExplicitContentFilter.AllMembers +} + +enum BushGuildDefaultMessageNotifications { + 'All Messages' = GuildDefaultMessageNotifications.AllMessages, + 'Only Mentions' = GuildDefaultMessageNotifications.OnlyMentions +} diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index 1ac7b3e..c77b5d2 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -1,8 +1,17 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { AutocompleteInteraction, MessageActionRow, MessageButton, MessageEmbed } from 'discord.js'; +import { + ActionRow, + ApplicationCommandOptionType, + AutocompleteInteraction, + ButtonComponent, + ButtonStyle, + MessageEmbed, + Permissions +} from 'discord.js'; import Fuse from 'fuse.js'; import packageDotJSON from '../../../package.json' assert { type: 'json' }; + assert(Fuse); assert(packageDotJSON); @@ -22,7 +31,7 @@ export default class HelpCommand extends BushCommand { match: 'content', prompt: 'What command do you need help with?', retry: '{error} Choose a valid command to find help for.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true, autocomplete: true }, @@ -31,14 +40,14 @@ export default class HelpCommand extends BushCommand { description: 'Whether ot not to show hidden commands as well.', match: 'flag', flag: '--hidden', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, ownerOnly: true, only: 'text', optional: true } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -117,40 +126,23 @@ export default class HelpCommand extends BushCommand { if (restrictions.length) embed.addField('» Restrictions', restrictions.join('\n')); } - return await message.util.reply({ embeds: [embed], components: row.components.length ? [row] : undefined }); + const params = { embeds: [embed], components: row.components.length ? [row] : undefined }; + return await message.util.reply(params); } private addLinks(message: BushMessage | BushSlashMessage) { - const row = new MessageActionRow(); + const row = new ActionRow(); if (!client.config.isDevelopment && !client.guilds.cache.some((guild) => guild.ownerId === message.author.id)) { - row.addComponents( - new MessageButton({ - style: 'LINK', - label: 'Invite Me', - url: `https://discord.com/api/oauth2/authorize?client_id=${ - client.user!.id - }&permissions=5368709119918&scope=bot%20applications.commands` - }) - ); + row.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Invite Me').setURL(util.invite)); } if (!client.guilds.cache.get(client.config.supportGuild.id)?.members.cache.has(message.author.id)) { row.addComponents( - new MessageButton({ - style: 'LINK', - label: 'Support Server', - url: client.config.supportGuild.invite - }) + new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Support Server').setURL(client.config.supportGuild.invite) ); } if (packageDotJSON?.repository) - row.addComponents( - new MessageButton({ - style: 'LINK', - label: 'GitHub', - url: packageDotJSON.repository - }) - ); + row.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('GitHub').setURL(packageDotJSON.repository)); else void message.channel?.send('Error importing package.json, please report this to my developer.'); return row; diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts index 42b7fa4..9602d40 100644 --- a/src/commands/info/icon.ts +++ b/src/commands/info/icon.ts @@ -1,5 +1,5 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; export default class IconCommand extends BushCommand { constructor() { @@ -9,7 +9,7 @@ export default class IconCommand extends BushCommand { description: "A command to get the server's icon", usage: ['icon'], examples: ['icon'], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], channel: 'guild', slash: true @@ -23,7 +23,6 @@ export default class IconCommand extends BushCommand { .setImage( message.guild!.iconURL({ size: 2048, - dynamic: true, format: 'png' })! ) diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts index b0d2007..25b040c 100644 --- a/src/commands/info/links.ts +++ b/src/commands/info/links.ts @@ -1,7 +1,8 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; import { assert } from 'console'; -import { MessageActionRow, MessageButton } from 'discord.js'; +import { ActionRow, ButtonComponent, ButtonStyle } from 'discord.js'; import packageDotJSON from '../../../package.json' assert { type: 'json' }; + assert(packageDotJSON); export default class LinksCommand extends BushCommand { @@ -19,26 +20,14 @@ export default class LinksCommand extends BushCommand { } public override async exec(message: BushMessage | BushSlashMessage) { - if (client.config.isDevelopment) return await message.util.reply(`${util.emojis.error} The dev bot cannot be invited.`); - const ButtonRow = new MessageActionRow().addComponents( - new MessageButton({ - style: 'LINK', - label: 'Invite Me', - url: `https://discord.com/api/oauth2/authorize?client_id=${ - client.user!.id - }&permissions=5368709119918&scope=bot%20applications.commands` - }), - new MessageButton({ - style: 'LINK', - label: 'Support Server', - url: client.config.supportGuild.invite - }), - new MessageButton({ - style: 'LINK', - label: 'GitHub', - url: packageDotJSON.repository - }) + const buttonRow = new ActionRow(); + if (!client.config.isDevelopment || message.author.isOwner()) { + buttonRow.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Invite Me').setURL(util.invite)); + } + buttonRow.addComponents( + new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Support Server').setURL(client.config.supportGuild.invite), + new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('GitHub').setURL(packageDotJSON.repository) ); - return await message.util.reply({ content: '\u200B', components: [ButtonRow] }); + return await message.util.reply({ content: 'Here are some useful links:', components: [buttonRow] }); } } diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts index a156368..1a8f542 100644 --- a/src/commands/info/ping.ts +++ b/src/commands/info/ping.ts @@ -1,5 +1,5 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed, type Message } from 'discord.js'; +import { MessageEmbed, Permissions, type Message } from 'discord.js'; export default class PingCommand extends BushCommand { public constructor() { @@ -10,7 +10,7 @@ export default class PingCommand extends BushCommand { usage: ['ping'], examples: ['ping'], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -24,7 +24,7 @@ export default class PingCommand extends BushCommand { .setTitle('Pong! 🏓') .addField('Bot Latency', botLatency, true) .addField('API Latency', apiLatency, true) - .setFooter({ text: message.author.username, iconURL: message.author.displayAvatarURL({ dynamic: true }) }) + .setFooter({ text: message.author.username, iconURL: message.author.displayAvatarURL() }) .setColor(util.colors.default) .setTimestamp(); await sentMessage.edit({ @@ -45,7 +45,7 @@ export default class PingCommand extends BushCommand { .addField('API Latency', apiLatency, true) .setFooter({ text: message.interaction.user.username, - iconURL: message.interaction.user.displayAvatarURL({ dynamic: true }) + iconURL: message.interaction.user.displayAvatarURL() }) .setColor(util.colors.default) .setTimestamp(); diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts index 9b9f870..e390865 100644 --- a/src/commands/info/pronouns.ts +++ b/src/commands/info/pronouns.ts @@ -1,5 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; export default class PronounsCommand extends BushCommand { public constructor() { @@ -17,10 +17,10 @@ export default class PronounsCommand extends BushCommand { prompt: 'Who would you like to view the pronouns of?', retry: '{error} Choose a valid user to view the pronouns of.', optional: true, - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], slash: true }); diff --git a/src/commands/info/snowflake.ts b/src/commands/info/snowflake.ts index 1a41257..d9ad108 100644 --- a/src/commands/info/snowflake.ts +++ b/src/commands/info/snowflake.ts @@ -1,18 +1,14 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import { + ApplicationCommandOptionType, MessageEmbed, + Permissions, SnowflakeUtil, - type CategoryChannel, type DeconstructedSnowflake, - type DMChannel, type Guild, - type NewsChannel, type Role, type Snowflake, - type StageChannel, - type TextChannel, - type User, - type VoiceChannel + type User } from 'discord.js'; export default class SnowflakeCommand extends BushCommand { @@ -30,11 +26,10 @@ export default class SnowflakeCommand extends BushCommand { type: 'snowflake', prompt: 'What snowflake would you like to get information about?', retry: '{error} Choose a valid snowflake.', - optional: false, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], slash: true }); @@ -46,35 +41,25 @@ export default class SnowflakeCommand extends BushCommand { // Channel if (client.channels.cache.has(snowflake)) { - const channel = client.channels.cache.get(snowflake)!; + const channel = client.channels.resolve(snowflake)!; const channelInfo = [`**Type:** ${channel.type}`]; - if (['DM', 'GROUP_DM'].includes(channel.type)) { - const _channel = channel as DMChannel; - channelInfo.push(`**Recipient:** ${util.discord.escapeMarkdown(_channel.recipient.tag)} (${_channel.recipient.id})`); - snowflakeEmbed.setTitle( - `:snowflake: DM with ${util.discord.escapeMarkdown((channel as DMChannel).recipient.tag)} \`[Channel]\`` - ); + if (channel.isDM()) { + channelInfo.push(`**Recipient:** ${util.discord.escapeMarkdown(channel.recipient.tag)} (${channel.recipient.id})`); + snowflakeEmbed.setTitle(`:snowflake: DM with ${util.discord.escapeMarkdown(channel.recipient.tag)} \`[Channel]\``); } else if ( - ( - [ - 'GUILD_CATEGORY', - 'GUILD_NEWS', - 'GUILD_TEXT', - 'GUILD_VOICE', - 'GUILD_STORE', - 'GUILD_STAGE_VOICE', - 'GUILD_NEWS_THREAD', - 'GUILD_PUBLIC_THREAD', - 'GUILD_PRIVATE_THREAD' - ] as const - ).includes(channel.type) + channel.isCategory() || + channel.isNews() || + channel.isText() || + channel.isVoice() || + channel.isStore() || + channel.isStage() || + channel.isThread() ) { - const _channel = channel as TextChannel | VoiceChannel | NewsChannel | StageChannel | CategoryChannel | StageChannel; channelInfo.push( - `**Channel Name:** <#${_channel.id}> (${util.discord.escapeMarkdown(_channel.name)})`, - `**Channel's Server:** ${util.discord.escapeMarkdown(_channel.guild.name)} (${_channel.guild.id})` + `**Channel Name:** <#${channel.id}> (${util.discord.escapeMarkdown(channel.name)})`, + `**Channel's Server:** ${util.discord.escapeMarkdown(channel.guild.name)} (${channel.guild.id})` ); - snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(_channel.name)} \`[Channel]\``); + snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(channel.name)} \`[Channel]\``); } snowflakeEmbed.addField('» Channel Info', channelInfo.join('\n')); } @@ -89,7 +74,7 @@ export default class SnowflakeCommand extends BushCommand { })`, `**Members:** ${guild.memberCount?.toLocaleString()}` ]; - if (guild.icon) snowflakeEmbed.setThumbnail(guild.iconURL({ size: 2048, dynamic: true })!); + if (guild.icon) snowflakeEmbed.setThumbnail(guild.iconURL({ size: 2048 })!); snowflakeEmbed.addField('» Server Info', guildInfo.join('\n')); snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(guild.name)} \`[Server]\``); } @@ -99,7 +84,7 @@ export default class SnowflakeCommand extends BushCommand { if (client.users.cache.has(snowflake) || fetchedUser) { const user: User = (client.users.cache.get(snowflake) ?? fetchedUser)!; const userInfo = [`**Name:** <@${user.id}> (${util.discord.escapeMarkdown(user.tag)})`]; - if (user.avatar) snowflakeEmbed.setThumbnail(user.avatarURL({ size: 2048, dynamic: true })!); + if (user.avatar) snowflakeEmbed.setThumbnail(user.avatarURL({ size: 2048 })!); snowflakeEmbed.addField('» User Info', userInfo.join('\n')); snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(user.tag)} \`[User]\``); } @@ -136,11 +121,10 @@ export default class SnowflakeCommand extends BushCommand { const deconstructedSnowflake: DeconstructedSnowflake = SnowflakeUtil.deconstruct(snowflake); const snowflakeInfo = [ `**Timestamp:** ${deconstructedSnowflake.timestamp}`, - `**Created:** ${util.timestamp(deconstructedSnowflake.date)}`, + `**Created:** ${util.timestamp(new Date(Number(deconstructedSnowflake.timestamp)))}`, `**Worker ID:** ${deconstructedSnowflake.workerId}`, `**Process ID:** ${deconstructedSnowflake.processId}`, `**Increment:** ${deconstructedSnowflake.increment}` - // `**Binary:** ${deconstructedSnowflake.binary}` ]; snowflakeEmbed.addField('» Snowflake Info', snowflakeInfo.join('\n')); diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts index 609bd94..38c9ea6 100644 --- a/src/commands/info/userInfo.ts +++ b/src/commands/info/userInfo.ts @@ -7,7 +7,7 @@ import { type BushSlashMessage, type BushUser } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ActivityType, ApplicationCommandOptionType, MessageEmbed, Permissions, UserFlags } from 'discord.js'; // TODO: Add bot information export default class UserInfoCommand extends BushCommand { @@ -27,11 +27,11 @@ export default class UserInfoCommand extends BushCommand { prompt: 'What user would you like to find information about?', retry: '{error} Choose a valid user to find information about.', optional: true, - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -58,12 +58,12 @@ export default class UserInfoCommand extends BushCommand { const userEmbed: MessageEmbed = new MessageEmbed() .setTitle(util.discord.escapeMarkdown(user.tag)) - .setThumbnail(user.displayAvatarURL({ size: 2048, format: 'png', dynamic: true })) + .setThumbnail(user.displayAvatarURL({ size: 2048, format: 'png' })) .setTimestamp(); // Flags - if (client.config.owners.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.DEVELOPER); - if (superUsers.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.SUPERUSER); + if (client.config.owners.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.Developer); + if (superUsers.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.Superuser); const flags = user.flags?.toArray(); if (flags) { flags.forEach((f) => { @@ -77,15 +77,15 @@ export default class UserInfoCommand extends BushCommand { if ( Number(user.discriminator) < 10 || client.consts.mappings.maybeNitroDiscrims.includes(user.discriminator) || - user.displayAvatarURL({ dynamic: true })?.endsWith('.gif') || - user.flags?.toArray().includes('PARTNERED_SERVER_OWNER') + user.displayAvatarURL()?.endsWith('.gif') || + user.flags?.has(UserFlags.FLAGS.PARTNER) ) { - emojis.push(client.consts.mappings.otherEmojis.NITRO); + emojis.push(client.consts.mappings.otherEmojis.Nitro); } - if (guild?.ownerId == user.id) emojis.push(client.consts.mappings.otherEmojis.OWNER); - else if (member?.permissions.has('ADMINISTRATOR')) emojis.push(client.consts.mappings.otherEmojis.ADMIN); - if (member?.premiumSinceTimestamp) emojis.push(client.consts.mappings.otherEmojis.BOOSTER); + if (guild?.ownerId == user.id) emojis.push(client.consts.mappings.otherEmojis.Owner); + else if (member?.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) emojis.push(client.consts.mappings.otherEmojis.Admin); + if (member?.premiumSinceTimestamp) emojis.push(client.consts.mappings.otherEmojis.Booster); const createdAt = util.timestamp(user.createdAt), createdAtDelta = util.dateDelta(user.createdAt), @@ -97,7 +97,7 @@ export default class UserInfoCommand extends BushCommand { // General Info const generalInfo = [`**Mention:** <@${user.id}>`, `**ID:** ${user.id}`, `**Created:** ${createdAt} (${createdAtDelta} ago)`]; if (user.accentColor !== null) generalInfo.push(`**Accent Color:** ${user.hexAccentColor}`); - if (user.banner) generalInfo.push(`**Banner:** [link](${user.bannerURL({ dynamic: true, format: 'png', size: 4096 })})`); + if (user.banner) generalInfo.push(`**Banner:** [link](${user.bannerURL({ format: 'png', size: 4096 })})`); const pronouns = await Promise.race([util.getPronounsOf(user), util.sleep(2)]); if (pronouns && typeof pronouns === 'string') generalInfo.push(`**Pronouns:** ${pronouns}`); @@ -126,7 +126,7 @@ export default class UserInfoCommand extends BushCommand { const activitiesNames: string[] = []; if (member.presence.activities) { member.presence.activities.forEach((a) => { - if (a.type == 'CUSTOM' && a.state) { + if (a.type == ActivityType.Custom && a.state) { const emoji = `${a.emoji ? `${a.emoji.toString()} ` : ''}`; customStatus = `${emoji}${a.state}`; } @@ -169,7 +169,7 @@ export default class UserInfoCommand extends BushCommand { // Important Perms const perms = []; - if (member?.permissions.has('ADMINISTRATOR') || guild?.ownerId == user.id) { + if (member?.permissions.has(Permissions.FLAGS.ADMINISTRATOR) || guild?.ownerId == user.id) { perms.push('`Administrator`'); } else if (member?.permissions.toArray().length) { member.permissions.toArray().forEach((permission) => { diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts index ffed9e9..2e0ce5d 100644 --- a/src/commands/leveling/leaderboard.ts +++ b/src/commands/leveling/leaderboard.ts @@ -1,5 +1,5 @@ import { BushCommand, ButtonPaginator, Level, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; export default class LeaderboardCommand extends BushCommand { public constructor() { @@ -17,7 +17,7 @@ export default class LeaderboardCommand extends BushCommand { prompt: 'What page of the leaderboard would you like to view?', retry: '{error} Pick a valid argument.', optional: true, - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer } ], slash: true, @@ -32,7 +32,7 @@ export default class LeaderboardCommand extends BushCommand { if (!(await message.guild.hasFeature('leveling'))) return await message.util.reply( `${util.emojis.error} This command can only be run in servers with the leveling feature enabled.${ - message.member?.permissions.has('MANAGE_GUILD') + message.member?.permissions.has(Permissions.FLAGS.MANAGE_GUILD) ? ` You can toggle features using the \`${util.prefix(message)}features\` command.` : '' }` diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts index 48cf3ed..18648e8 100644 --- a/src/commands/leveling/level.ts +++ b/src/commands/leveling/level.ts @@ -12,7 +12,7 @@ import { import { SimplifyNumber } from '@notenoughupdates/simplify-number'; import assert from 'assert'; import canvas from 'canvas'; -import { MessageAttachment } from 'discord.js'; +import { ApplicationCommandOptionType, MessageAttachment, Permissions } from 'discord.js'; import got from 'got'; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; @@ -36,7 +36,7 @@ export default class LevelCommand extends BushCommand { prompt: 'What user would you like to see the level of?', retry: '{error} Choose a valid user to see the level of.', optional: true, - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], slash: true, @@ -51,7 +51,7 @@ export default class LevelCommand extends BushCommand { if (!(await message.guild.hasFeature('leveling'))) return await message.util.reply( `${util.emojis.error} This command can only be run in servers with the leveling feature enabled.${ - message.member?.permissions.has('MANAGE_GUILD') + message.member?.permissions.has(Permissions.FLAGS.MANAGE_GUILD) ? ` You can toggle features using the \`${util.prefix(message)}features\` command.` : '' }` diff --git a/src/commands/leveling/levelRoles.ts b/src/commands/leveling/levelRoles.ts index a5eb5c4..115ace1 100644 --- a/src/commands/leveling/levelRoles.ts +++ b/src/commands/leveling/levelRoles.ts @@ -1,5 +1,6 @@ import { AllowedMentions, BushCommand, type ArgType, type BushMessage, type BushSlashMessage, type OptionalArgType } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class LevelRolesCommand extends BushCommand { public constructor() { @@ -17,7 +18,7 @@ export default class LevelRolesCommand extends BushCommand { description: 'The level to assign the role when reached.', prompt: 'What level would you like to set a role for when reached?', retry: '{error} Pick a valid integer representing the role to assign a role to when reached.', - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer }, { id: 'role', @@ -26,14 +27,14 @@ export default class LevelRolesCommand extends BushCommand { description: 'The role to assign to a user who reaches the specified level.', prompt: 'What role would you like to assign to users when they reach that level?', retry: '{error} Choose a valid role to assign to users upon reaching the specified level.', - slashType: 'ROLE', + slashType: ApplicationCommandOptionType.Role, optional: true } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']), - userPermissions: ['MANAGE_GUILD', 'MANAGE_ROLES'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_ROLES]), + userPermissions: [Permissions.FLAGS.MANAGE_GUILD, Permissions.FLAGS.MANAGE_ROLES] }); } diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts index 184ee1b..29f36e0 100644 --- a/src/commands/leveling/setLevel.ts +++ b/src/commands/leveling/setLevel.ts @@ -1,4 +1,5 @@ import { AllowedMentions, BushCommand, Level, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class SetLevelCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class SetLevelCommand extends BushCommand { type: 'user', prompt: 'What user would you like to change the level of?', retry: '{error} Choose a valid user to change the level of.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'level', @@ -23,13 +24,13 @@ export default class SetLevelCommand extends BushCommand { type: 'integer', prompt: 'What level would you like to set the user to?', retry: '{error} Choose a valid level to set the user to.', - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer } ], slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['ADMINISTRATOR'] + userPermissions: [Permissions.FLAGS.ADMINISTRATOR] }); } diff --git a/src/commands/leveling/setXp.ts b/src/commands/leveling/setXp.ts index d6f28b2..721f28f 100644 --- a/src/commands/leveling/setXp.ts +++ b/src/commands/leveling/setXp.ts @@ -1,4 +1,5 @@ import { AllowedMentions, BushCommand, Level, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class SetXpCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class SetXpCommand extends BushCommand { type: 'user', prompt: 'What user would you like to change the xp of?', retry: '{error} Choose a valid user to change the xp of.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'xp', @@ -24,13 +25,13 @@ export default class SetXpCommand extends BushCommand { match: 'restContent', prompt: 'How much xp should the user have?', retry: "{error} Choose a valid number to set the user's xp to.", - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer } ], slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: ['ADMINISTRATOR'] + userPermissions: [Permissions.FLAGS.ADMINISTRATOR] }); } diff --git a/src/commands/moderation/_activePunishments.ts b/src/commands/moderation/_activePunishments.ts index 98c4912..5b1674c 100644 --- a/src/commands/moderation/_activePunishments.ts +++ b/src/commands/moderation/_activePunishments.ts @@ -1,5 +1,6 @@ // import { BushCommand, ModLog, ModLogModel, type BushGuildMember, type BushMessage, type BushSlashMessage } from '#lib'; // import { FindOptions, Op } from 'sequelize'; +// import { Permissions } from 'discord.js'; // const punishmentTypes = ['ban', 'kick', 'mute', 'warn', 'role'] as const; @@ -19,8 +20,8 @@ // match: 'option', // prompt: 'Only show active punishments from what user?', // optional: true, -// slashType: 'USER', -// slashResolve: 'member' +// slashType: ApplicationCommandOptionType.User, +// slashResolve: 'Member' // }, // { // id: 'type', @@ -29,7 +30,7 @@ // readableType: punishmentTypes.map((v) => `'${v}'`).join('|'), // match: 'option', // optional: true, -// slashType: 'STRING', +// slashType: ApplicationCommandOptionType.String, // choices: punishmentTypes.map((v) => ({ name: v, value: v })) // } // ], @@ -37,9 +38,10 @@ // channel: 'guild', // hidden: true, // clientPermissions: (m) => util.clientSendAndPermCheck(m), -// userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) +// userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) // }); // } +// // public override async exec( // message: BushMessage | BushSlashMessage, // args: { moderator?: BushGuildMember; type: typeof punishmentTypes[number] } diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index aeb03f0..33f980d 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -8,7 +8,7 @@ import { type BushSlashMessage, type OptionalArgType } from '#lib'; -import { type User } from 'discord.js'; +import { ApplicationCommandOptionType, Permissions, type User } from 'discord.js'; export default class BanCommand extends BushCommand { public constructor() { @@ -25,7 +25,7 @@ export default class BanCommand extends BushCommand { type: util.arg.union('user', 'snowflake'), prompt: 'What user would you like to ban?', retry: '{error} Choose a valid user to ban.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason_and_duration', @@ -34,7 +34,7 @@ export default class BanCommand extends BushCommand { match: 'rest', prompt: 'Why should this user be banned and for how long?', retry: '{error} Choose a valid ban reason and duration.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true }, { @@ -46,7 +46,7 @@ export default class BanCommand extends BushCommand { retry: '{error} Choose between 0 and 7 days to delete messages from the user for.', type: util.arg.range('integer', 0, 7, true), optional: true, - slashType: 'INTEGER', + slashType: ApplicationCommandOptionType.Integer, choices: [...Array(8).keys()].map((v) => ({ name: v.toString(), value: v })) }, { @@ -62,8 +62,8 @@ export default class BanCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'] + clientPermissions: [Permissions.FLAGS.BAN_MEMBERS], + userPermissions: [Permissions.FLAGS.BAN_MEMBERS] }); } @@ -141,6 +141,8 @@ export default class BanCommand extends BushCommand { return `${util.emojis.warn} Banned ${victim} however I could not send them a dm.`; case banResponse.SUCCESS: return `${util.emojis.success} Successfully banned ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts index 57f909a..0b6458d 100644 --- a/src/commands/moderation/block.ts +++ b/src/commands/moderation/block.ts @@ -11,6 +11,7 @@ import { type OptionalArgType } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class BlockCommand extends BushCommand { public constructor() { @@ -27,7 +28,7 @@ export default class BlockCommand extends BushCommand { type: 'user', prompt: 'What user would you like to block?', retry: '{error} Choose a valid user to block.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason_and_duration', @@ -37,7 +38,7 @@ export default class BlockCommand extends BushCommand { prompt: 'Why should this user be blocked and for how long?', retry: '{error} Choose a valid block reason and duration.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -52,8 +53,8 @@ export default class BlockCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, 'MANAGE_CHANNELS'), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS]), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -120,6 +121,8 @@ export default class BlockCommand extends BushCommand { return `${util.emojis.warn} Blocked ${victim} however I could not send them a dm.`; case blockResponse.SUCCESS: return `${util.emojis.success} Successfully blocked ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts index cff63ed..155d804 100644 --- a/src/commands/moderation/evidence.ts +++ b/src/commands/moderation/evidence.ts @@ -1,5 +1,6 @@ import { BushCommand, ModLog, type BushMessage, type BushSlashMessage } from '#lib'; import { type ArgumentOptions, type Flag } from 'discord-akairo'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class EvidenceCommand extends BushCommand { public constructor() { @@ -15,7 +16,7 @@ export default class EvidenceCommand extends BushCommand { description: 'The case to modify the evidence of.', type: 'string', prompt: 'What case would you like to modify the evidence of?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, only: 'slash' }, { @@ -23,14 +24,14 @@ export default class EvidenceCommand extends BushCommand { description: 'The value to set the evidence to.', type: 'string', prompt: 'What would you like to modify the evidence to?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, only: 'slash' } ], slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts index e12d8c8..2c71119 100644 --- a/src/commands/moderation/hideCase.ts +++ b/src/commands/moderation/hideCase.ts @@ -1,4 +1,5 @@ import { BushCommand, ModLog, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class HideCaseCommand extends BushCommand { public constructor() { @@ -15,12 +16,12 @@ export default class HideCaseCommand extends BushCommand { type: 'string', prompt: 'What modlog case would you like to hide?', retry: '{error} Choose a valid case id.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]), channel: 'guild' }); } diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts index af486ac..4fd6c10 100644 --- a/src/commands/moderation/kick.ts +++ b/src/commands/moderation/kick.ts @@ -7,6 +7,7 @@ import { type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class KickCommand extends BushCommand { public constructor() { @@ -23,7 +24,7 @@ export default class KickCommand extends BushCommand { type: 'user', prompt: 'What user would you like to kick?', retry: '{error} Choose a valid user to kick.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -33,7 +34,7 @@ export default class KickCommand extends BushCommand { prompt: 'Why should this user be kicked?', retry: '{error} Choose a valid kick reason.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -47,8 +48,8 @@ export default class KickCommand extends BushCommand { } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['KICK_MEMBERS']), - userPermissions: ['KICK_MEMBERS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.KICK_MEMBERS]), + userPermissions: [Permissions.FLAGS.KICK_MEMBERS] }); } @@ -86,6 +87,8 @@ export default class KickCommand extends BushCommand { return `${util.emojis.warn} Kicked ${victim} however I could not send them a dm.`; case kickResponse.SUCCESS: return `${util.emojis.success} Successfully kicked ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/lockdown.ts b/src/commands/moderation/lockdown.ts index 87a2f05..350ce26 100644 --- a/src/commands/moderation/lockdown.ts +++ b/src/commands/moderation/lockdown.ts @@ -11,7 +11,7 @@ import { type OptionalArgType } from '#lib'; import assert from 'assert'; -import { Collection } from 'discord.js'; +import { ApplicationCommandOptionType, Collection, Permissions } from 'discord.js'; export default class LockdownCommand extends BushCommand { public constructor() { @@ -27,8 +27,8 @@ export default class LockdownCommand extends BushCommand { description: 'Specify a different channel to lockdown instead of the one you trigger the command in.', type: util.arg.union('textChannel', 'newsChannel', 'threadChannel'), prompt: 'What channel would you like to lockdown?', - slashType: 'CHANNEL', - channelTypes: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], optional: true }, { @@ -37,7 +37,7 @@ export default class LockdownCommand extends BushCommand { type: 'string', match: 'rest', prompt: 'What is the reason for the lockdown?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true }, { @@ -46,14 +46,14 @@ export default class LockdownCommand extends BushCommand { match: 'flag', flag: '--all', prompt: 'Would you like to lockdown all configured channels?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS']), - userPermissions: ['MANAGE_CHANNELS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS]), + userPermissions: [Permissions.FLAGS.MANAGE_CHANNELS] }); } @@ -134,7 +134,7 @@ export default class LockdownCommand extends BushCommand { action === 'lockdown' ? 'locked down' : 'unlocked' } **${num}** channel${num > 0 ? 's' : ''}.`; } else { - throw new Error(`Unknown response: ${response}`); + return `${util.emojis.error} An error occurred: ${util.format.input(response)}}`; } assert(messageResponse); diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts index 8651afe..e7b3576 100644 --- a/src/commands/moderation/modlog.ts +++ b/src/commands/moderation/modlog.ts @@ -1,5 +1,5 @@ import { BushCommand, ButtonPaginator, ModLog, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed, User } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions, User } from 'discord.js'; export default class ModlogCommand extends BushCommand { public constructor() { @@ -16,7 +16,7 @@ export default class ModlogCommand extends BushCommand { type: util.arg.union('user', 'string'), prompt: 'What case id or user would you like to see?', retry: '{error} Choose a valid case id or user.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'hidden', @@ -26,12 +26,12 @@ export default class ModlogCommand extends BushCommand { flag: ['--hidden', '-h'], default: false, optional: true, - slashType: 'BOOLEAN' + slashType: ApplicationCommandOptionType.Boolean } ], slash: true, clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts index 40e13e7..ea935ce 100644 --- a/src/commands/moderation/mute.ts +++ b/src/commands/moderation/mute.ts @@ -9,6 +9,7 @@ import { type OptionalArgType } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class MuteCommand extends BushCommand { public constructor() { @@ -25,7 +26,7 @@ export default class MuteCommand extends BushCommand { type: 'user', prompt: 'What user would you like to mute?', retry: '{error} Choose a valid user to mute.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason_and_duration', @@ -35,7 +36,7 @@ export default class MuteCommand extends BushCommand { prompt: 'Why should this user be muted and for how long?', retry: '{error} Choose a valid mute reason and duration.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -50,8 +51,8 @@ export default class MuteCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_ROLES]), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -118,6 +119,8 @@ export default class MuteCommand extends BushCommand { return `${util.emojis.warn} Muted ${victim} however I could not send them a dm.`; case muteResponse.SUCCESS: return `${util.emojis.success} Successfully muted ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts index 8fa279b..b48f997 100644 --- a/src/commands/moderation/purge.ts +++ b/src/commands/moderation/purge.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { Collection, type Snowflake } from 'discord.js'; +import { ApplicationCommandOptionType, Collection, Permissions, type Snowflake } from 'discord.js'; export default class PurgeCommand extends BushCommand { public constructor() { @@ -18,7 +18,7 @@ export default class PurgeCommand extends BushCommand { readableType: 'integer', prompt: 'How many messages would you like to purge?', retry: '{error} Please pick a number between 1 and 100.', - slashType: 'INTEGER', + slashType: ApplicationCommandOptionType.Integer, minValue: 1, maxValue: 100 }, @@ -28,7 +28,7 @@ export default class PurgeCommand extends BushCommand { match: 'flag', flag: '--bot', prompt: 'Would you like to only delete messages that are from bots?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -37,13 +37,14 @@ export default class PurgeCommand extends BushCommand { match: 'option', type: 'user', flag: '--user', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES', 'EMBED_LINKS'], true), - userPermissions: ['MANAGE_MESSAGES'], + clientPermissions: (m) => + util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES, Permissions.FLAGS.EMBED_LINKS], true), + userPermissions: [Permissions.FLAGS.MANAGE_MESSAGES], channel: 'guild' }); } @@ -53,7 +54,7 @@ export default class PurgeCommand extends BushCommand { args: { amount: number; bot: boolean; user: ArgType<'user'> } ) { assert(message.channel); - if (message.channel.type === 'DM') return message.util.reply(`${util.emojis.error} You cannot run this command in dms.`); + if (!message.inGuild()) return message.util.reply(`${util.emojis.error} You cannot run this command in dms.`); if (args.amount > 100 || args.amount < 1) return message.util.reply(`${util.emojis.error} `); const messageFilter = (filterMessage: BushMessage): boolean => { diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts index 919ee40..61759ae 100644 --- a/src/commands/moderation/removeReactionEmoji.ts +++ b/src/commands/moderation/removeReactionEmoji.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { Message, type Emoji } from 'discord.js'; +import { ApplicationCommandOptionType, Message, Permissions, type Emoji } from 'discord.js'; export default class RemoveReactionEmojiCommand extends BushCommand { public constructor() { @@ -17,7 +17,7 @@ export default class RemoveReactionEmojiCommand extends BushCommand { type: 'guildMessage', prompt: 'What message would you like to remove a reaction from?', retry: '{error} Please pick a valid message.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'emoji', @@ -27,13 +27,14 @@ export default class RemoveReactionEmojiCommand extends BushCommand { match: 'restContent', prompt: 'What emoji would you like to remove?', retry: '{error} Please pick a valid emoji.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES', 'EMBED_LINKS'], true), - userPermissions: ['MANAGE_MESSAGES', 'MANAGE_EMOJIS_AND_STICKERS'] // Can't undo the removal of 1000s of reactions + clientPermissions: (m) => + util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES, Permissions.FLAGS.EMBED_LINKS], true), + userPermissions: [Permissions.FLAGS.MANAGE_MESSAGES, Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS] // Can't undo the removal of 1000s of reactions }); } diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index f0d0448..0d4d91b 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -9,7 +9,7 @@ import { type OptionalArgType } from '#lib'; import { type ArgumentOptions, type Flag } from 'discord-akairo'; -import { type Snowflake } from 'discord.js'; +import { ApplicationCommandOptionType, Permissions, type Snowflake } from 'discord.js'; export default class RoleCommand extends BushCommand { public constructor() { @@ -24,7 +24,7 @@ export default class RoleCommand extends BushCommand { id: 'action', description: 'Whether to add or remove a role for the the user.', prompt: 'Would you like to add or remove a role?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: [ { name: 'add', value: 'add' }, { name: 'remove', value: 'remove' } @@ -35,8 +35,8 @@ export default class RoleCommand extends BushCommand { id: 'member', description: 'The user to add/remove a role to/from.', prompt: 'What user do you want to add/remove a role to/from?', - slashType: 'USER', - slashResolve: 'member', + slashType: ApplicationCommandOptionType.User, + slashResolve: 'Member', optional: true, only: 'slash' }, @@ -44,7 +44,7 @@ export default class RoleCommand extends BushCommand { id: 'role', description: 'The role you would like to add/remove from the to/from.', prompt: 'What role would you like to add/remove from the user?', - slashType: 'ROLE', + slashType: ApplicationCommandOptionType.Role, optional: true, only: 'slash' }, @@ -52,7 +52,7 @@ export default class RoleCommand extends BushCommand { id: 'duration', description: 'The time before the role will be removed (ignored if removing a role).', prompt: 'How long would you like to role to last?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true, only: 'slash' } @@ -60,7 +60,8 @@ export default class RoleCommand extends BushCommand { slash: true, channel: 'guild', typing: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES', 'EMBED_LINKS'], true), + clientPermissions: (m) => + util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_ROLES, Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -129,7 +130,7 @@ export default class RoleCommand extends BushCommand { if (!args.role) return await message.util.reply(`${util.emojis.error} You must specify a role.`); if (args.duration === null) args.duration = 0; if ( - !message.member!.permissions.has('MANAGE_ROLES') && + !message.member!.permissions.has(Permissions.FLAGS.MANAGE_ROLES) && message.member!.id !== message.guild?.ownerId && !message.member!.user.isOwner() ) { @@ -202,6 +203,8 @@ export default class RoleCommand extends BushCommand { return `${util.emojis.success} Successfully ${args.action === 'add' ? 'added' : 'removed'} <@&${args.role.id}> ${ args.action === 'add' ? 'to' : 'from' } ${victim}${args.duration ? ` for ${util.humanizeDuration(args.duration)}` : ''}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts index bfa6462..a724006 100644 --- a/src/commands/moderation/slowmode.ts +++ b/src/commands/moderation/slowmode.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import { Argument } from 'discord-akairo'; -import { type TextChannel, type ThreadChannel } from 'discord.js'; +import { ApplicationCommandOptionType, ChannelType, Permissions, type TextChannel, type ThreadChannel } from 'discord.js'; export default class SlowmodeCommand extends BushCommand { public constructor() { @@ -19,7 +19,7 @@ export default class SlowmodeCommand extends BushCommand { prompt: 'What would you like to set the slowmode to?', retry: '{error} Please set the slowmode to a valid length.', optional: true, - slashType: 'INTEGER' + slashType: ApplicationCommandOptionType.Integer }, { id: 'channel', @@ -28,14 +28,15 @@ export default class SlowmodeCommand extends BushCommand { prompt: 'What channel would you like to change?', retry: '{error} Choose a valid channel.', optional: true, - slashType: 'CHANNEL', - channelTypes: ['GUILD_TEXT', 'GUILD_PRIVATE_THREAD', 'GUILD_PUBLIC_THREAD'] + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildText', 'GuildPrivateThread', 'GuildPublicThread'] } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS', 'EMBED_LINKS'], true), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + clientPermissions: (m) => + util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS, Permissions.FLAGS.EMBED_LINKS], true), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -49,10 +50,10 @@ export default class SlowmodeCommand extends BushCommand { channel: ArgType<'channel'>; } ) { - if (message.channel!.type === 'DM') + if (message.channel!.type === ChannelType.DM) return await message.util.reply(`${util.emojis.error} This command cannot be run in dms.`); if (!channel) channel = message.channel as any; - if (!(['GUILD_TEXT', 'GUILD_PRIVATE_THREAD', 'GUILD_PUBLIC_THREAD'] as const).includes(channel.type)) + if (![ChannelType.GuildText, ChannelType.GuildPrivateThread, ChannelType.GuildPublicThread].includes(channel.type)) return await message.util.reply(`${util.emojis.error} <#${channel.id}> is not a text or thread channel.`); if (length) { length = diff --git a/src/commands/moderation/timeout.ts b/src/commands/moderation/timeout.ts index ec79271..73b9d50 100644 --- a/src/commands/moderation/timeout.ts +++ b/src/commands/moderation/timeout.ts @@ -8,6 +8,7 @@ import { type BushSlashMessage } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class TimeoutCommand extends BushCommand { public constructor() { @@ -24,7 +25,7 @@ export default class TimeoutCommand extends BushCommand { type: 'user', prompt: 'What user would you like to timeout?', retry: '{error} Choose a valid user to timeout.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason_and_duration', @@ -33,7 +34,7 @@ export default class TimeoutCommand extends BushCommand { match: 'rest', prompt: 'Why should this user be timed out and for how long?', retry: '{error} Choose a valid timeout reason and duration.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -48,8 +49,8 @@ export default class TimeoutCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MODERATE_MEMBERS']), - userPermissions: ['MODERATE_MEMBERS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MODERATE_MEMBERS]), + userPermissions: [Permissions.FLAGS.MODERATE_MEMBERS] }); } @@ -101,6 +102,8 @@ export default class TimeoutCommand extends BushCommand { return `${util.emojis.warn} Timed out ${victim} however I could not send them a dm.`; case timeoutResponse.SUCCESS: return `${util.emojis.success} Successfully timed out ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts index c939792..b2bdd72 100644 --- a/src/commands/moderation/unban.ts +++ b/src/commands/moderation/unban.ts @@ -7,6 +7,7 @@ import { type BushSlashMessage, type OptionalArgType } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class UnbanCommand extends BushCommand { public constructor() { @@ -23,7 +24,7 @@ export default class UnbanCommand extends BushCommand { type: 'globalUser', prompt: 'What user would you like to unban?', retry: '{error} Choose a valid user to unban.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -33,15 +34,16 @@ export default class UnbanCommand extends BushCommand { prompt: 'Why should this user be unbanned?', retry: '{error} Choose a valid unban reason.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, channel: 'guild', - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'] + clientPermissions: [Permissions.FLAGS.BAN_MEMBERS], + userPermissions: [Permissions.FLAGS.BAN_MEMBERS] }); } + public override async exec( message: BushMessage | BushSlashMessage, { user, reason }: { user: ArgType<'user'>; reason: OptionalArgType<'string'> } @@ -68,6 +70,8 @@ export default class UnbanCommand extends BushCommand { case unbanResponse.DM_ERROR: case unbanResponse.SUCCESS: return `${util.emojis.success} Successfully unbanned ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts index 454de8b..1abf2be 100644 --- a/src/commands/moderation/unblock.ts +++ b/src/commands/moderation/unblock.ts @@ -11,6 +11,7 @@ import { type OptionalArgType } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class UnblockCommand extends BushCommand { public constructor() { @@ -27,7 +28,7 @@ export default class UnblockCommand extends BushCommand { type: 'user', prompt: 'What user would you like to unblock?', retry: '{error} Choose a valid user to unblock.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -37,7 +38,7 @@ export default class UnblockCommand extends BushCommand { prompt: 'Why should this user be blocked and for how long?', retry: '{error} Choose a valid block reason and duration.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -52,8 +53,8 @@ export default class UnblockCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, 'MANAGE_CHANNELS'), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS]), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -102,6 +103,8 @@ export default class UnblockCommand extends BushCommand { return `${util.emojis.warn} Unblocked ${victim} however I could not send them a dm.`; case unblockResponse.SUCCESS: return `${util.emojis.success} Successfully unblocked ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/unlockdown.ts b/src/commands/moderation/unlockdown.ts index 3d363ac..d7ba5ee 100644 --- a/src/commands/moderation/unlockdown.ts +++ b/src/commands/moderation/unlockdown.ts @@ -1,5 +1,6 @@ import { LockdownCommand } from '#commands'; import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage, type OptionalArgType } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class UnlockdownCommand extends BushCommand { public constructor() { @@ -15,8 +16,8 @@ export default class UnlockdownCommand extends BushCommand { description: 'Specify a different channel to unlockdown instead of the one you trigger the command in.', type: util.arg.union('textChannel', 'newsChannel', 'threadChannel'), prompt: 'What channel would you like to unlockdown?', - slashType: 'CHANNEL', - channelTypes: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], optional: true }, { @@ -25,7 +26,7 @@ export default class UnlockdownCommand extends BushCommand { type: 'string', match: 'rest', prompt: 'What is the reason for the unlock?', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true }, { @@ -34,14 +35,14 @@ export default class UnlockdownCommand extends BushCommand { match: 'flag', flag: '--all', prompt: 'Would you like to unlockdown all configured channels?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS']), - userPermissions: ['MANAGE_CHANNELS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_CHANNELS]), + userPermissions: [Permissions.FLAGS.MANAGE_CHANNELS] }); } diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts index 3bd399f..9974b8d 100644 --- a/src/commands/moderation/unmute.ts +++ b/src/commands/moderation/unmute.ts @@ -9,6 +9,7 @@ import { type BushSlashMessage, type OptionalArgType } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class UnmuteCommand extends BushCommand { public constructor() { @@ -25,7 +26,7 @@ export default class UnmuteCommand extends BushCommand { type: 'user', prompt: 'What user would you like to unmute?', retry: '{error} Choose a valid user to unmute.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -35,7 +36,7 @@ export default class UnmuteCommand extends BushCommand { prompt: 'Why should this user be unmuted?', retry: '{error} Choose a valid unmute reason.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'force', @@ -50,8 +51,8 @@ export default class UnmuteCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_ROLES]), + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -98,6 +99,8 @@ export default class UnmuteCommand extends BushCommand { return `${util.emojis.warn} unmuted ${victim} however I could not send them a dm.`; case unmuteResponse.SUCCESS: return `${util.emojis.success} Successfully unmuted ${victim}.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/untimeout.ts b/src/commands/moderation/untimeout.ts index c5518b4..6ebd777 100644 --- a/src/commands/moderation/untimeout.ts +++ b/src/commands/moderation/untimeout.ts @@ -9,6 +9,7 @@ import { type OptionalArgType } from '#lib'; import assert from 'assert'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class UntimeoutCommand extends BushCommand { public constructor() { @@ -25,7 +26,7 @@ export default class UntimeoutCommand extends BushCommand { type: 'user', prompt: 'What user would you like to untimeout?', retry: '{error} Choose a valid user to untimeout.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -34,7 +35,7 @@ export default class UntimeoutCommand extends BushCommand { match: 'rest', prompt: 'Why should this user have their timeout removed?', retry: '{error} Choose a valid reason to remove the timeout.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true }, { @@ -50,8 +51,8 @@ export default class UntimeoutCommand extends BushCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MODERATE_MEMBERS']), - userPermissions: ['MODERATE_MEMBERS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MODERATE_MEMBERS]), + userPermissions: [Permissions.FLAGS.MODERATE_MEMBERS] }); } @@ -92,6 +93,8 @@ export default class UntimeoutCommand extends BushCommand { return `${util.emojis.warn} Removed ${victim}'s timeout however I could not send them a dm.`; case removeTimeoutResponse.SUCCESS: return `${util.emojis.success} Successfully removed ${victim}'s timeout.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts index aebf300..af45782 100644 --- a/src/commands/moderation/warn.ts +++ b/src/commands/moderation/warn.ts @@ -9,6 +9,7 @@ import { type BushSlashMessage, type OptionalArgType } from '#lib'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; export default class WarnCommand extends BushCommand { public constructor() { @@ -25,7 +26,7 @@ export default class WarnCommand extends BushCommand { type: 'user', prompt: 'What user would you like to warn?', retry: '{error} Choose a valid user to warn.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'reason', @@ -33,7 +34,7 @@ export default class WarnCommand extends BushCommand { match: 'rest', prompt: 'Why should this user be warned?', retry: '{error} Choose a valid warn reason.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, optional: true }, { @@ -50,7 +51,7 @@ export default class WarnCommand extends BushCommand { slash: true, channel: 'guild', clientPermissions: (m) => util.clientSendAndPermCheck(m), - userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']) + userPermissions: (m) => util.userGuildPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES]) }); } @@ -85,6 +86,8 @@ export default class WarnCommand extends BushCommand { )} time, however I could not send them a dm.`; case warnResponse.SUCCESS: return `${util.emojis.success} Successfully warned ${victim} for the ${util.ordinal(caseNum ?? 0)} time.`; + default: + return `${util.emojis.error} An error occurred: ${util.format.input(response)}}`; } }; return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() }); diff --git a/src/commands/moulberry-bush/capePermissions.ts b/src/commands/moulberry-bush/capePermissions.ts index c873095..19c1381 100644 --- a/src/commands/moulberry-bush/capePermissions.ts +++ b/src/commands/moulberry-bush/capePermissions.ts @@ -1,5 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; import got from 'got'; export default class CapePermissionsCommand extends BushCommand { @@ -17,11 +17,11 @@ export default class CapePermissionsCommand extends BushCommand { type: 'string', prompt: 'Who would you like to see the cape permissions of?', retry: '{error} Choose someone to see the capes their available capes.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], channel: 'guild' }); diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts index 117fd1c..3a956fc 100644 --- a/src/commands/moulberry-bush/capes.ts +++ b/src/commands/moulberry-bush/capes.ts @@ -1,8 +1,9 @@ import { BushCommand, ButtonPaginator, DeleteButton, type BushMessage, type OptionalArgType } from '#lib'; import assert from 'assert'; -import { AutocompleteInteraction, type MessageEmbedOptions } from 'discord.js'; +import { ApplicationCommandOptionType, AutocompleteInteraction, Permissions, type MessageEmbedOptions } from 'discord.js'; import Fuse from 'fuse.js'; import got from 'got'; + assert(Fuse); assert(got); @@ -22,12 +23,12 @@ export default class CapesCommand extends BushCommand { prompt: 'What cape would you like to see?', retry: '{error} Choose a cape to see.', optional: true, - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, autocomplete: true } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts index 28f920a..dbbb613 100644 --- a/src/commands/moulberry-bush/giveawayPing.ts +++ b/src/commands/moulberry-bush/giveawayPing.ts @@ -1,4 +1,5 @@ import { AllowedMentions, BushCommand, type BushMessage } from '#lib'; +import { Permissions } from 'discord.js'; export default class GiveawayPingCommand extends BushCommand { public constructor() { @@ -8,8 +9,14 @@ export default class GiveawayPingCommand extends BushCommand { description: 'Pings the giveaway role.', usage: ['giveaway-ping'], examples: ['giveaway-ping'], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES'], true), - userPermissions: ['MANAGE_GUILD', 'MANAGE_MESSAGES', 'BAN_MEMBERS', 'KICK_MEMBERS', 'VIEW_CHANNEL'], + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_MESSAGES], true), + userPermissions: [ + Permissions.FLAGS.MANAGE_GUILD, + Permissions.FLAGS.MANAGE_MESSAGES, + Permissions.FLAGS.BAN_MEMBERS, + Permissions.FLAGS.KICK_MEMBERS, + Permissions.FLAGS.VIEW_CHANNEL + ], channel: 'guild', ignoreCooldown: [], ignorePermissions: [], @@ -22,7 +29,7 @@ export default class GiveawayPingCommand extends BushCommand { } public override async exec(message: BushMessage) { - if (!message.member!.permissions.has('MANAGE_GUILD') && !message.member!.user.isOwner()) + if (!message.member!.permissions.has(Permissions.FLAGS.MANAGE_GUILD) && !message.member!.user.isOwner()) await message.util.reply(`${util.emojis.error} You are missing the **MANAGE_GUILD** permission.`); await message.delete().catch(() => {}); @@ -47,7 +54,7 @@ export default class GiveawayPingCommand extends BushCommand { content: '🎉 <@&767782793261875210> Giveaway.\n\n<:mad:783046135392239626> Spamming, line breaking, gibberish etc. disqualifies you from winning. We can and will ban you from giveaways. Winners will all be checked and rerolled if needed.', username: `${message.member.nickname || message.author.username}`, - avatarURL: message.author.avatarURL({ dynamic: true }), + avatarURL: message.author.avatarURL(), allowedMentions: AllowedMentions.roles() }); */ } diff --git a/src/commands/moulberry-bush/moulHammer.ts b/src/commands/moulberry-bush/moulHammer.ts index 6d87571..4cf3f35 100644 --- a/src/commands/moulberry-bush/moulHammer.ts +++ b/src/commands/moulberry-bush/moulHammer.ts @@ -1,5 +1,5 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; export default class MoulHammerCommand extends BushCommand { public constructor() { @@ -16,13 +16,13 @@ export default class MoulHammerCommand extends BushCommand { type: 'user', prompt: 'What user would you like to moul hammer?', retry: '{error} Choose a valid user to moul hammer', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], slash: true, slashGuilds: ['516977525906341928'], restrictedGuilds: ['516977525906341928'], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts index 90abc97..f2c10bc 100644 --- a/src/commands/moulberry-bush/report.ts +++ b/src/commands/moulberry-bush/report.ts @@ -1,7 +1,8 @@ import { AllowedMentions, BushCommand, type ArgType, type BushMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; import moment from 'moment'; + assert(moment); export default class ReportCommand extends BushCommand { @@ -19,7 +20,7 @@ export default class ReportCommand extends BushCommand { type: 'member', prompt: 'Who would you like to report?', retry: '{error} Choose a valid user to report.', - slashType: 'USER' + slashType: ApplicationCommandOptionType.User }, { id: 'evidence', @@ -29,11 +30,11 @@ export default class ReportCommand extends BushCommand { prompt: 'What did the user do wrong?', retry: '{error} Provide evidence.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], channel: 'guild' }); @@ -66,7 +67,7 @@ export default class ReportCommand extends BushCommand { .setTimestamp() .setAuthor({ name: `Report From: ${message.author.tag}`, - iconURL: message.author.avatarURL({ dynamic: true }) ?? undefined + iconURL: message.author.avatarURL() ?? undefined }) .setTitle('New Report') .setColor(util.colors.red) diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts index 28483a4..1bfcfe7 100644 --- a/src/commands/moulberry-bush/rule.ts +++ b/src/commands/moulberry-bush/rule.ts @@ -1,5 +1,5 @@ import { AllowedMentions, BushCommand, BushSlashMessage, type BushMessage, type OptionalArgType } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, Permissions } from 'discord.js'; const rules = [ { @@ -68,7 +68,7 @@ export default class RuleCommand extends BushCommand { prompt: 'What rule would you like to have cited?', retry: '{error} Choose a valid rule.', optional: true, - slashType: 'INTEGER', + slashType: ApplicationCommandOptionType.Integer, minValue: 1, maxValue: rules.length }, @@ -79,13 +79,13 @@ export default class RuleCommand extends BushCommand { prompt: 'What user would you like to mention?', retry: '{error} Choose a valid user to mention.', optional: true, - slashType: 'USER' + slashType: ApplicationCommandOptionType.User } ], slash: true, slashGuilds: ['516977525906341928'], channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], restrictedGuilds: ['516977525906341928'] }); @@ -99,7 +99,7 @@ export default class RuleCommand extends BushCommand { .setColor('#ef3929') .setFooter({ text: `Triggered by ${message.author.tag}`, - iconURL: message.author.avatarURL({ dynamic: true }) ?? undefined + iconURL: message.author.avatarURL() ?? undefined }) .setTimestamp(); diff --git a/src/commands/moulberry-bush/serverStatus.ts b/src/commands/moulberry-bush/serverStatus.ts index 3d8e780..28b38a5 100644 --- a/src/commands/moulberry-bush/serverStatus.ts +++ b/src/commands/moulberry-bush/serverStatus.ts @@ -1,7 +1,8 @@ import { BushCommand, type BushMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; import got from 'got'; + assert(got); export default class ServerStatusCommand extends BushCommand { @@ -12,7 +13,7 @@ export default class ServerStatusCommand extends BushCommand { description: "Gives the status of moulberry's server", usage: ['server-status'], examples: ['server-status', 'ss'], - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], slash: true }); diff --git a/src/commands/utilities/activity.ts b/src/commands/utilities/activity.ts index 28d466b..948f82a 100644 --- a/src/commands/utilities/activity.ts +++ b/src/commands/utilities/activity.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushArgumentTypeCaster, type BushMessage, type BushSlashMessage } from '#lib'; import { type ArgumentOptions, type ArgumentTypeCaster, type Flag } from 'discord-akairo'; -import { type DiscordAPIError, type Snowflake } from 'discord.js'; +import { ApplicationCommandOptionType, ChannelType, type DiscordAPIError, type Snowflake } from 'discord.js'; const activityMap = { 'Poker Night': { @@ -93,8 +93,8 @@ export default class ActivityCommand extends BushCommand { description: 'The channel to create the activity in.', type: 'voiceChannel', prompt: 'What channel would you like to use?', - slashType: 'CHANNEL', - channelTypes: ['GUILD_VOICE'], + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildVoice'], only: 'slash' }, { @@ -107,7 +107,7 @@ export default class ActivityCommand extends BushCommand { .flatMap((a) => a.aliases) .map((a) => `\`${a}\``) .join(', ')}.`, - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: Object.keys(activityMap).map((key) => ({ name: key, value: activityMap[key as keyof typeof activityMap].id @@ -155,7 +155,7 @@ export default class ActivityCommand extends BushCommand { args: { channel: ArgType<'voiceChannel'>; activity: string } ) { const channel = typeof args.channel === 'string' ? message.guild?.channels.cache.get(args.channel) : args.channel; - if (!channel || channel.type !== 'GUILD_VOICE') + if (!channel || channel.type !== ChannelType.GuildVoice) return await message.util.reply(`${util.emojis.error} Choose a valid voice channel`); const target_application_id = message.util.isSlashMessage(message) diff --git a/src/commands/utilities/calculator.ts b/src/commands/utilities/calculator.ts index 2eeb3a6..df79cc2 100644 --- a/src/commands/utilities/calculator.ts +++ b/src/commands/utilities/calculator.ts @@ -1,7 +1,8 @@ import { AllowedMentions, BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed } from 'discord.js'; import { evaluate } from 'mathjs'; + assert(evaluate); export default class CalculatorCommand extends BushCommand { @@ -20,7 +21,7 @@ export default class CalculatorCommand extends BushCommand { match: 'rest', prompt: 'What would you like to calculate?', retry: '{error} Pick something to calculate.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, @@ -28,6 +29,7 @@ export default class CalculatorCommand extends BushCommand { userPermissions: [] }); } + public override async exec(message: BushMessage | BushSlashMessage, args: { expression: string }) { const decodedEmbed = new MessageEmbed().addField('📥 Input', await util.inspectCleanRedactCodeblock(args.expression, 'mma')); try { diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts index 76f735b..f5d8920 100644 --- a/src/commands/utilities/decode.ts +++ b/src/commands/utilities/decode.ts @@ -1,6 +1,6 @@ import { AllowedMentions, BushCommand, type BushMessage } from '#lib'; import { type AkairoMessage } from 'discord-akairo'; -import { MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed } from 'discord.js'; const encodingTypesArray = ['ascii', 'utf8', 'utf-8', 'utf16le', 'ucs2', 'ucs-2', 'base64', 'latin1', 'binary', 'hex']; const encodingTypesString = encodingTypesArray.map((e) => `\`${e}\``).join(', '); @@ -20,7 +20,7 @@ export default class DecodeCommand extends BushCommand { customType: encodingTypesArray, prompt: 'What is the encoding of the original data?', retry: `{error} Choose one of the following ${encodingTypesString} for the encoding of the original data.`, - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: encodingTypesArray.map((e) => ({ name: e, value: e })) }, { @@ -29,7 +29,7 @@ export default class DecodeCommand extends BushCommand { customType: encodingTypesArray, prompt: 'What would you like the encoding of the resulting data to be?', retry: `{error} Choose one of the following ${encodingTypesString} for the encoding of the resulting data.`, - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, choices: encodingTypesArray.map((e) => ({ name: e, value: e })) }, { @@ -39,7 +39,7 @@ export default class DecodeCommand extends BushCommand { match: 'restContent', prompt: 'What would you to decode.', retry: '{error} Choose a valid string to decode.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts index 7e892f5..7cc59f3 100644 --- a/src/commands/utilities/hash.ts +++ b/src/commands/utilities/hash.ts @@ -1,7 +1,9 @@ import { BushCommand, type BushMessage } from '#lib'; import assert from 'assert'; import crypto from 'crypto'; +import { ApplicationCommandOptionType } from 'discord.js'; import got from 'got'; + assert(crypto); assert(got); @@ -20,7 +22,7 @@ export default class HashCommand extends BushCommand { type: 'url', prompt: 'What url would you like to find the hash of?', retry: '{error} Enter a valid url.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], clientPermissions: (m) => util.clientSendAndPermCheck(m), diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts index 409f544..9fb79bc 100644 --- a/src/commands/utilities/price.ts +++ b/src/commands/utilities/price.ts @@ -1,8 +1,9 @@ import { BushCommand, type BushMessage } from '#lib'; import assert from 'assert'; -import { AutocompleteInteraction, MessageEmbed } from 'discord.js'; +import { ApplicationCommandOptionType, AutocompleteInteraction, MessageEmbed, Permissions } from 'discord.js'; import Fuse from 'fuse.js'; import got from 'got'; + assert(Fuse); assert(got); @@ -24,7 +25,7 @@ export default class PriceCommand extends BushCommand { match: 'content', prompt: 'What item would you like to find the price of?', retry: '{error} Choose a valid item.', - slashType: 'STRING', + slashType: ApplicationCommandOptionType.String, autocomplete: true }, { @@ -34,11 +35,11 @@ export default class PriceCommand extends BushCommand { flag: '--strict', prompt: 'Would you like to bypass the fuzzy search?', optional: true, - slashType: 'BOOLEAN' + slashType: ApplicationCommandOptionType.Boolean } ], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [], typing: true }); diff --git a/src/commands/utilities/remind.ts b/src/commands/utilities/remind.ts index 6339343..4b7ccb9 100644 --- a/src/commands/utilities/remind.ts +++ b/src/commands/utilities/remind.ts @@ -1,4 +1,5 @@ import { BushCommand, Reminder, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class RemindCommand extends BushCommand { public constructor() { @@ -17,7 +18,7 @@ export default class RemindCommand extends BushCommand { prompt: 'What would you like to be reminded about and when?', retry: '{error} Choose a reason to be reminded about with a duration for when to be notified.', optional: true, - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, diff --git a/src/commands/utilities/reminders.ts b/src/commands/utilities/reminders.ts index 8b4124d..40ec9a2 100644 --- a/src/commands/utilities/reminders.ts +++ b/src/commands/utilities/reminders.ts @@ -1,7 +1,8 @@ import { BushCommand, ButtonPaginator, Reminder, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { type MessageEmbedOptions } from 'discord.js'; +import { Permissions, type MessageEmbedOptions } from 'discord.js'; import { Op } from 'sequelize'; + assert(Op); export default class RemindersCommand extends BushCommand { @@ -13,7 +14,7 @@ export default class RemindersCommand extends BushCommand { usage: ['reminder'], examples: ['reminders'], slash: true, - clientPermissions: (m) => util.clientSendAndPermCheck(m, 'EMBED_LINKS'), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS]), userPermissions: [] }); } diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts index 834fc10..a963746 100644 --- a/src/commands/utilities/steal.ts +++ b/src/commands/utilities/steal.ts @@ -1,8 +1,10 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; import { type ArgumentOptions, type ArgumentType, type ArgumentTypeCaster, type Flag } from 'discord-akairo'; +import { ApplicationCommandOptionType, Permissions } from 'discord.js'; import _ from 'lodash'; import { URL } from 'url'; + assert(_); export default class StealCommand extends BushCommand { @@ -23,7 +25,7 @@ export default class StealCommand extends BushCommand { retry: '{error} Pick a valid emoji, emoji id, or image url.', optional: true, only: 'slash', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'name', @@ -32,13 +34,13 @@ export default class StealCommand extends BushCommand { retry: '{error} Choose a valid name fore the emoji.', optional: true, only: 'slash', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_EMOJIS_AND_STICKERS']), - userPermissions: ['MANAGE_EMOJIS_AND_STICKERS'] + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS]), + userPermissions: [Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS] }); } @@ -106,9 +108,10 @@ export default class StealCommand extends BushCommand { if (!(creationSuccess instanceof Error)) return await message.util.reply(`${util.emojis.success} You successfully stole ${creationSuccess}.`); - else + else { return await message.util.reply( `${util.emojis.error} The was an error stealing that emoji \`${creationSuccess.message}\`.` ); + } } } diff --git a/src/commands/utilities/uuid.ts b/src/commands/utilities/uuid.ts index d842b58..4df9132 100644 --- a/src/commands/utilities/uuid.ts +++ b/src/commands/utilities/uuid.ts @@ -1,4 +1,5 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class UuidCommand extends BushCommand { public constructor() { @@ -16,7 +17,7 @@ export default class UuidCommand extends BushCommand { readableType: 'ign', prompt: 'What ign would you like to find the uuid of?', retry: '{error} Choose a valid ign.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'dashed', @@ -24,7 +25,7 @@ export default class UuidCommand extends BushCommand { match: 'flag', flag: '--dashed', prompt: 'Would you like to include dashes in the uuid?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], diff --git a/src/commands/utilities/viewRaw.ts b/src/commands/utilities/viewRaw.ts index b524b3c..4b1ff1e 100644 --- a/src/commands/utilities/viewRaw.ts +++ b/src/commands/utilities/viewRaw.ts @@ -7,7 +7,7 @@ import { type BushTextChannel, type OptionalArgType } from '#lib'; -import { Message, MessageEmbed, type Snowflake } from 'discord.js'; +import { ApplicationCommandOptionType, Message, MessageEmbed, Permissions, type Snowflake } from 'discord.js'; export default class ViewRawCommand extends BushCommand { public constructor() { @@ -25,7 +25,7 @@ export default class ViewRawCommand extends BushCommand { readableType: 'guildMessage|messageLink', prompt: 'What message would you like to view?', retry: '{error} Choose a valid message.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'channel', @@ -34,8 +34,8 @@ export default class ViewRawCommand extends BushCommand { prompt: 'What channel is the message in?', retry: '{error} Choose a valid channel.', optional: true, - slashType: 'CHANNEL', - channelTypes: util.discordConstants.TextBasedChannelTypes + slashType: ApplicationCommandOptionType.Channel, + channelTypes: ['GuildText', 'DM', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'] }, { id: 'json', @@ -43,7 +43,7 @@ export default class ViewRawCommand extends BushCommand { match: 'flag', flag: '--json', prompt: 'Would you like to view the raw JSON message data?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true }, { @@ -52,13 +52,13 @@ export default class ViewRawCommand extends BushCommand { match: 'flag', flag: '--js', prompt: 'Would you like to view the raw message data?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], slash: true, channel: 'guild', - clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true), + clientPermissions: (m) => util.clientSendAndPermCheck(m, [Permissions.FLAGS.EMBED_LINKS], true), userPermissions: [] }); } @@ -96,7 +96,7 @@ export default class ViewRawCommand extends BushCommand { : message.content || '[No Content]'; const lang = options.json ? 'json' : options.js ? 'js' : undefined; return new MessageEmbed() - .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL({ dynamic: true }) ?? undefined }) + .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined }) .setTimestamp(message.createdTimestamp) .setColor(message.member?.roles?.color?.color ?? util.colors.default) .setTitle('Raw Message Information') diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts index 60543c1..4993528 100644 --- a/src/commands/utilities/whoHasRole.ts +++ b/src/commands/utilities/whoHasRole.ts @@ -1,5 +1,5 @@ import { BushCommand, ButtonPaginator, type ArgType, type BushMessage, type BushSlashMessage } from '#lib'; -import { Util, type CommandInteraction } from 'discord.js'; +import { ApplicationCommandOptionType, Util, type CommandInteraction } from 'discord.js'; export default class WhoHasRoleCommand extends BushCommand { public constructor() { @@ -17,7 +17,7 @@ export default class WhoHasRoleCommand extends BushCommand { prompt: 'What role would you like to find the users of?', retry: '{error} Pick a valid role.', optional: false, - slashType: 'ROLE' + slashType: ApplicationCommandOptionType.Role } ], slash: true, @@ -27,6 +27,7 @@ export default class WhoHasRoleCommand extends BushCommand { typing: true }); } + public override async exec(message: BushMessage | BushSlashMessage, args: { role: ArgType<'role'> }) { if (message.util.isSlash) await (message.interaction as CommandInteraction).deferReply(); const roleMembers = args.role.members.map((member) => `${member.user} (${Util.escapeMarkdown(member.user.tag)})`); diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts index 6d8342c..984d617 100644 --- a/src/commands/utilities/wolframAlpha.ts +++ b/src/commands/utilities/wolframAlpha.ts @@ -1,7 +1,8 @@ import { AllowedMentions, BushCommand, type BushMessage, type BushSlashMessage } from '#lib'; import { initializeClass as WolframAlphaAPI } from '@notenoughupdates/wolfram-alpha-api'; import assert from 'assert'; -import { MessageEmbed, type MessageOptions } from 'discord.js'; +import { ApplicationCommandOptionType, MessageEmbed, type MessageOptions } from 'discord.js'; + assert(WolframAlphaAPI); export default class WolframAlphaCommand extends BushCommand { @@ -20,7 +21,7 @@ export default class WolframAlphaCommand extends BushCommand { match: 'rest', prompt: 'What would you like to look up?', retry: '{error} Pick something to look up.', - slashType: 'STRING' + slashType: ApplicationCommandOptionType.String }, { id: 'image', @@ -28,7 +29,7 @@ export default class WolframAlphaCommand extends BushCommand { match: 'flag', flag: '--image', prompt: 'Would you like to use the Simple API instead of the Short Answers API?', - slashType: 'BOOLEAN', + slashType: ApplicationCommandOptionType.Boolean, optional: true } ], @@ -37,6 +38,7 @@ export default class WolframAlphaCommand extends BushCommand { userPermissions: [] }); } + public override async exec(message: BushMessage | BushSlashMessage, args: { expression: string; image: boolean }) { if (message.util.isSlashMessage(message)) await message.interaction.deferReply(); diff --git a/src/context-menu-commands/message/viewRaw.ts b/src/context-menu-commands/message/viewRaw.ts index 1ece8cd..c283635 100644 --- a/src/context-menu-commands/message/viewRaw.ts +++ b/src/context-menu-commands/message/viewRaw.ts @@ -1,18 +1,18 @@ import { ViewRawCommand } from '#commands'; import { type BushMessage } from '#lib'; import { ContextMenuCommand } from 'discord-akairo'; -import { type ContextMenuInteraction } from 'discord.js'; +import { ApplicationCommandType, type ContextMenuCommandInteraction } from 'discord.js'; export default class ViewRawContextMenuCommand extends ContextMenuCommand { public constructor() { super('viewRaw', { name: 'View Raw', - type: 'MESSAGE', + type: ApplicationCommandType.Message, category: 'message' }); } - public override async exec(interaction: ContextMenuInteraction) { + public override async exec(interaction: ContextMenuCommandInteraction) { await interaction.deferReply({ ephemeral: true }); const embed = await ViewRawCommand.getRawData(interaction.options.getMessage('message') as BushMessage, { json: false, diff --git a/src/context-menu-commands/user/userInfo.ts b/src/context-menu-commands/user/userInfo.ts index 0c43958..d6e8132 100644 --- a/src/context-menu-commands/user/userInfo.ts +++ b/src/context-menu-commands/user/userInfo.ts @@ -1,18 +1,18 @@ import { UserInfoCommand } from '#commands'; import { type BushGuild, type BushGuildMember, type BushUser } from '#lib'; import { ContextMenuCommand } from 'discord-akairo'; -import { type ContextMenuInteraction } from 'discord.js'; +import { ApplicationCommandType, type ContextMenuCommandInteraction } from 'discord.js'; export default class UserInfoContextMenuCommand extends ContextMenuCommand { public constructor() { super('userInfo', { name: 'User Info', - type: 'USER', + type: ApplicationCommandType.User, category: 'user' }); } - public override async exec(interaction: ContextMenuInteraction) { + public override async exec(interaction: ContextMenuCommandInteraction) { await interaction.deferReply({ ephemeral: true }); const user = (await interaction.user.fetch()) as BushUser; diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts index 7a30820..4de242a 100644 --- a/src/lib/common/AutoMod.ts +++ b/src/lib/common/AutoMod.ts @@ -1,5 +1,14 @@ import { banResponse, Moderation, type BushButtonInteraction, type BushMessage } from '#lib'; -import { GuildMember, MessageActionRow, MessageButton, MessageEmbed, type TextChannel } from 'discord.js'; +import { + ActionRow, + ButtonComponent, + ButtonStyle, + ChannelType, + GuildMember, + MessageEmbed, + Permissions, + type TextChannel +} from 'discord.js'; /** * Handles auto moderation functionality. @@ -28,7 +37,7 @@ export class AutoMod { * Handles the auto moderation */ private async handle() { - if (this.message.channel.type === 'DM' || !this.message.guild) return; + if (this.message.channel.type === ChannelType.DM || !this.message.guild) return; if (!(await this.message.guild.hasFeature('automod'))) return; if (this.message.author.bot) return; if (this.message.author.isOwner()) return; @@ -110,7 +119,10 @@ export class AutoMod { const includes = this.message.content.toLocaleLowerCase().includes; if (!includes('@everyone') && !includes('@here')) return; // It would be bad if we deleted a message that actually pinged @everyone or @here - if (this.message.member?.permissionsIn(this.message.channelId).has('MENTION_EVERYONE') || this.message.mentions.everyone) + if ( + this.message.member?.permissionsIn(this.message.channelId).has(Permissions.FLAGS.MENTION_EVERYONE) || + this.message.mentions.everyone + ) return; if ( @@ -142,9 +154,9 @@ export class AutoMod { components: Severity.TEMP_MUTE >= 2 ? [ - new MessageActionRow().addComponents( - new MessageButton() - .setStyle('DANGER') + new ActionRow().addComponents( + new ButtonComponent() + .setStyle(ButtonStyle.Danger) .setLabel('Ban User') .setCustomId(`automod;ban;${this.message.author.id};everyone mention and scam phrase`) ) @@ -263,9 +275,9 @@ export class AutoMod { components: highestOffence.severity >= 2 ? [ - new MessageActionRow().addComponents( - new MessageButton() - .setStyle('DANGER') + new ActionRow().addComponents( + new ButtonComponent() + .setStyle(ButtonStyle.Danger) .setLabel('Ban User') .setCustomId(`automod;ban;${this.message.author.id};${highestOffence.reason}`) ) @@ -279,7 +291,7 @@ export class AutoMod { * @param interaction The button interaction. */ public static async handleInteraction(interaction: BushButtonInteraction) { - if (!interaction.memberPermissions?.has('BAN_MEMBERS')) + if (!interaction.memberPermissions?.has(Permissions.FLAGS.BAN_MEMBERS)) return interaction.reply({ content: `${util.emojis.error} You are missing the **Ban Members** permission.`, ephemeral: true diff --git a/src/lib/common/ButtonPaginator.ts b/src/lib/common/ButtonPaginator.ts index 83f4219..9e72551 100644 --- a/src/lib/common/ButtonPaginator.ts +++ b/src/lib/common/ButtonPaginator.ts @@ -1,13 +1,15 @@ import { DeleteButton, type BushMessage, type BushSlashMessage } from '#lib'; import { CommandUtil } from 'discord-akairo'; import { - MessageActionRow, - MessageButton, + ActionRow, + ActionRowComponent, + ButtonComponent, + ButtonStyle, + ComponentType, MessageEmbed, type MessageComponentInteraction, type MessageEmbedOptions } from 'discord.js'; -import { MessageButtonStyles } from 'discord.js/typings/enums'; /** * Sends multiple embeds with controls to switch between them @@ -94,9 +96,15 @@ export class ButtonPaginator { })) as BushMessage; const collector = this.sentMessage.createMessageComponentCollector({ - filter: (i) => i.customId.startsWith('paginate_') && i.message?.id === this.sentMessage!.id, - time: 300000 + componentType: ComponentType.Button, + filter: (i) => { + const ret = i.customId.startsWith('paginate_') && i.message.id === this.sentMessage!.id; + console.debug(ret); + return ret; + }, + idle: 300000 }); + console.debug('got here'); collector.on('collect', (i) => void this.collect(i)); collector.on('end', () => void this.end()); @@ -107,8 +115,9 @@ export class ButtonPaginator { * @param interaction The interaction received */ protected async collect(interaction: MessageComponentInteraction) { + console.debug(1); if (interaction.user.id !== this.message.author.id && !client.config.owners.includes(interaction.user.id)) - return await interaction?.deferUpdate().catch(() => null); + return await interaction?.deferUpdate(); /* .catch(() => null); */ switch (interaction.customId) { case 'paginate_beginning': @@ -121,17 +130,16 @@ export class ButtonPaginator { break; case 'paginate_stop': if (this.deleteOnExit) { - await interaction.deferUpdate().catch(() => null); - await this.sentMessage!.delete().catch(() => null); + await interaction.deferUpdate(); /* .catch(() => null); */ + await this.sentMessage!.delete(); /* .catch(() => null); */ break; } else { - await interaction - ?.update({ - content: `${this.text ? `${this.text}\n` : ''}Command closed by user.`, - embeds: [], - components: [] - }) - .catch(() => null); + await interaction?.update({ + content: `${this.text ? `${this.text}\n` : ''}Command closed by user.`, + embeds: [], + components: [] + }); + /* .catch(() => null); */ break; } case 'paginate_next': @@ -150,13 +158,12 @@ export class ButtonPaginator { */ protected async end() { if (this.sentMessage && !CommandUtil.deletedMessages.has(this.sentMessage.id)) - await this.sentMessage - .edit({ - content: this.text, - embeds: [this.embeds[this.curPage]], - components: [this.getPaginationRow(true)] - }) - .catch(() => null); + await this.sentMessage.edit({ + content: this.text, + embeds: [this.embeds[this.curPage]], + components: [this.getPaginationRow(true)] + }); + /* .catch(() => null); */ } /** @@ -164,52 +171,46 @@ export class ButtonPaginator { * @param interaction The interaction received */ protected async edit(interaction: MessageComponentInteraction) { - await interaction - ?.update({ - content: this.text, - embeds: [this.embeds[this.curPage]], - components: [this.getPaginationRow()] - }) - .catch(() => null); + await interaction?.update({ + content: this.text, + embeds: [this.embeds[this.curPage]], + components: [this.getPaginationRow()] + }); + /* .catch(() => null); */ } /** * Generates the pagination row based on the class properties * @param disableAll Whether to disable all buttons - * @returns The generated {@link MessageActionRow} + * @returns The generated {@link ActionRow} */ - protected getPaginationRow(disableAll = false): MessageActionRow { - return new MessageActionRow().addComponents( - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate_beginning', - emoji: PaginateEmojis.BEGGING, - disabled: disableAll || this.curPage === 0 - }), - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate_back', - emoji: PaginateEmojis.BACK, - disabled: disableAll || this.curPage === 0 - }), - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate_stop', - emoji: PaginateEmojis.STOP, - disabled: disableAll - }), - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate_next', - emoji: PaginateEmojis.FORWARD, - disabled: disableAll || this.curPage === this.numPages - 1 - }), - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate_end', - emoji: PaginateEmojis.END, - disabled: disableAll || this.curPage === this.numPages - 1 - }) + protected getPaginationRow(disableAll = false): ActionRow<ActionRowComponent> { + return new ActionRow().addComponents( + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate_beginning') + .setEmoji(PaginateEmojis.BEGINNING) + .setDisabled(disableAll || this.curPage === 0), + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate_back') + .setEmoji(PaginateEmojis.BACK) + .setDisabled(disableAll || this.curPage === 0), + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate_stop') + .setEmoji(PaginateEmojis.STOP) + .setDisabled(disableAll), + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate_next') + .setEmoji(PaginateEmojis.FORWARD) + .setDisabled(disableAll || this.curPage === this.embeds.length - 1), + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate_end') + .setEmoji(PaginateEmojis.END) + .setDisabled(disableAll || this.curPage === this.embeds.length - 1) ); } @@ -235,10 +236,10 @@ export class ButtonPaginator { } } -export const enum PaginateEmojis { - BEGGING = '853667381335162910', - BACK = '853667410203770881', - STOP = '853667471110570034', - FORWARD = '853667492680564747', - END = '853667514915225640' -} +export const PaginateEmojis = { + BEGINNING: { id: '853667381335162910', name: 'w_paginate_beginning', animated: false } as const, + BACK: { id: '853667410203770881', name: 'w_paginate_back', animated: false } as const, + STOP: { id: '853667471110570034', name: 'w_paginate_stop', animated: false } as const, + FORWARD: { id: '853667492680564747', name: 'w_paginate_next', animated: false } as const, + END: { id: '853667514915225640', name: 'w_paginate_end', animated: false } as const +} as const; diff --git a/src/lib/common/ConfirmationPrompt.ts b/src/lib/common/ConfirmationPrompt.ts index a4acf83..97f18b3 100644 --- a/src/lib/common/ConfirmationPrompt.ts +++ b/src/lib/common/ConfirmationPrompt.ts @@ -1,6 +1,5 @@ import { type BushMessage, type BushSlashMessage } from '#lib'; -import { MessageActionRow, MessageButton, type MessageComponentInteraction, type MessageOptions } from 'discord.js'; -import { MessageButtonStyles } from 'discord.js/typings/enums'; +import { ActionRow, ButtonComponent, ButtonStyle, type MessageComponentInteraction, type MessageOptions } from 'discord.js'; /** * Sends a message with buttons for the user to confirm or cancel the action. @@ -30,19 +29,17 @@ export class ConfirmationPrompt { */ protected async send(): Promise<boolean> { this.messageOptions.components = [ - new MessageActionRow().addComponents( - new MessageButton({ - style: MessageButtonStyles.SUCCESS, - customId: 'confirmationPrompt_confirm', - emoji: util.emojis.successFull, - label: 'Yes' - }), - new MessageButton({ - style: MessageButtonStyles.DANGER, - customId: 'confirmationPrompt_deny', - emoji: util.emojis.errorFull, - label: 'No' - }) + new ActionRow().addComponents( + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('confirmationPrompt_confirm') + .setEmoji({ id: util.emojis.successFull, name: 'successFull', animated: false }) + .setLabel('Yes'), + new ButtonComponent() + .setStyle(ButtonStyle.Danger) + .setCustomId('confirmationPrompt_cancel') + .setEmoji({ id: util.emojis.errorFull, name: 'errorFull', animated: false }) + .setLabel('No') ) ]; diff --git a/src/lib/common/DeleteButton.ts b/src/lib/common/DeleteButton.ts index b666a4f..edc40fe 100644 --- a/src/lib/common/DeleteButton.ts +++ b/src/lib/common/DeleteButton.ts @@ -1,7 +1,6 @@ import { PaginateEmojis, type BushMessage, type BushSlashMessage } from '#lib'; import { CommandUtil } from 'discord-akairo'; -import { MessageActionRow, MessageButton, type MessageComponentInteraction, type MessageOptions } from 'discord.js'; -import { MessageButtonStyles } from 'discord.js/typings/enums'; +import { ActionRow, ButtonComponent, ButtonStyle, MessageComponentInteraction, type MessageOptions } from 'discord.js'; /** * Sends a message with a button for the user to delete it. @@ -59,13 +58,12 @@ export class DeleteButton { */ protected updateComponents(edit = false, disable = false): void { this.messageOptions.components = [ - new MessageActionRow().addComponents( - new MessageButton({ - style: MessageButtonStyles.PRIMARY, - customId: 'paginate__stop', - emoji: PaginateEmojis.STOP, - disabled: disable - }) + new ActionRow().addComponents( + new ButtonComponent() + .setStyle(ButtonStyle.Primary) + .setCustomId('paginate__stop') + .setEmoji(PaginateEmojis.STOP) + .setDisabled(disable) ) ]; if (edit) { diff --git a/src/lib/common/util/Moderation.ts b/src/lib/common/util/Moderation.ts index e5cb872..84d9fbf 100644 --- a/src/lib/common/util/Moderation.ts +++ b/src/lib/common/util/Moderation.ts @@ -10,7 +10,7 @@ import { type BushUserResolvable, type ModLogType } from '#lib'; -import { MessageEmbed, type Snowflake } from 'discord.js'; +import { MessageEmbed, Permissions, type Snowflake } from 'discord.js'; /** * A utility class with moderation-related methods. @@ -70,7 +70,11 @@ export class Moderation { ) { return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as I do.`; } - if (checkModerator && victim.permissions.has('MANAGE_MESSAGES') && !(type.startsWith('un') && moderator.id === victim.id)) { + if ( + checkModerator && + victim.permissions.has(Permissions.FLAGS.MANAGE_MESSAGES) && + !(type.startsWith('un') && moderator.id === victim.id) + ) { if (await moderator.guild.hasFeature('modsCanPunishMods')) { return true; } else { diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts index cb1e50b..01620a8 100644 --- a/src/lib/extensions/discord-akairo/BushClient.ts +++ b/src/lib/extensions/discord-akairo/BushClient.ts @@ -24,6 +24,7 @@ import { patch, type PatchedElements } from '@notenoughupdates/events-intercept' import * as Sentry from '@sentry/node'; import { AkairoClient, ContextMenuCommandHandler, version as akairoVersion } from 'discord-akairo'; import { + ActivityType, Intents, Options, Structures, @@ -61,7 +62,7 @@ import { BushConstants } from '../../utils/BushConstants.js'; import { BushLogger } from '../../utils/BushLogger.js'; import { BushButtonInteraction } from '../discord.js/BushButtonInteraction.js'; import { BushCategoryChannel } from '../discord.js/BushCategoryChannel.js'; -import { BushCommandInteraction } from '../discord.js/BushCommandInteraction.js'; +import { BushChatInputCommandInteraction } from '../discord.js/BushChatInputCommandInteraction.js'; import { BushDMChannel } from '../discord.js/BushDMChannel.js'; import { BushGuild } from '../discord.js/BushGuild.js'; import { BushGuildEmoji } from '../discord.js/BushGuildEmoji.js'; @@ -193,7 +194,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re activities: [ { name: 'Beep Boop', - type: 'WATCHING' + type: ActivityType.Watching } ], status: 'online' @@ -252,7 +253,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re automateCategories: false, autoRegisterSlashCommands: true, skipBuiltInPostInhibitors: true, - useSlashPermissions: true, + useSlashPermissions: false, aliasReplacement: /-/g }); this.contextMenuCommandHandler = new ContextMenuCommandHandler(this, { @@ -320,7 +321,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re Structures.extend('VoiceState', () => BushVoiceState); Structures.extend('Role', () => BushRole); Structures.extend('User', () => BushUser); - Structures.extend('CommandInteraction', () => BushCommandInteraction); + Structures.extend('ChatInputCommandInteraction', () => BushChatInputCommandInteraction); Structures.extend('ButtonInteraction', () => BushButtonInteraction); Structures.extend('SelectMenuInteraction', () => BushSelectMenuInteraction); } @@ -440,13 +441,17 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re */ public async start() { this.intercept('ready', async (arg, done) => { - await this.guilds.fetch(); - const promises = this.guilds.cache.map((guild) => { - return guild.members.fetch(); - }); + console.debug('ready start'); + console.time('ready'); + const promises = this.guilds.cache + .filter((g) => g.large) + .map((guild) => { + return guild.members.fetch(); + }); await Promise.all(promises); this.customReady = true; this.taskHandler.startAll(); + console.timeEnd('ready'); return done(null, `intercepted ${arg}`); }); diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index 12becd3..79aa4c1 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -26,13 +26,13 @@ import { GuildMember, Message, MessageEmbed, + Permissions, ThreadMember, User, Util as DiscordUtil, type ColorResolvable, type CommandInteraction, type InteractionReplyOptions, - type PermissionResolvable, type Snowflake, type TextChannel, type UserResolvable @@ -43,6 +43,8 @@ import { inspect, promisify } from 'util'; import CommandErrorListener from '../../../listeners/commands/commandError.js'; import { Format } from '../../common/util/Format.js'; +export type StripPrivate<T> = { [K in keyof T]: T[K] extends Record<string, any> ? StripPrivate<T[K]> : T[K] }; + export class BushClientUtil extends ClientUtil { /** * The client. @@ -208,7 +210,7 @@ export class BushClientUtil extends ClientUtil { if (author) embed = embed.setAuthor({ name: author.username, - iconURL: author.displayAvatarURL({ dynamic: true }), + iconURL: author.displayAvatarURL(), url: `https://discord.com/users/${author.id}` }); if (color) embed = embed.setColor(color); @@ -425,7 +427,7 @@ export class BushClientUtil extends ClientUtil { * @returns The combined elements or `ifEmpty`. * * @example - * const permissions = oxford(['ADMINISTRATOR', 'SEND_MESSAGES', 'MANAGE_MESSAGES'], 'and', 'none'); + * const permissions = oxford([Permissions.FLAGS.ADMINISTRATOR, Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.MANAGE_MESSAGES], 'and', 'none'); * console.log(permissions); // ADMINISTRATOR, SEND_MESSAGES and MANAGE_MESSAGES */ public oxford(array: string[], conjunction: string, ifEmpty?: string): string | undefined { @@ -785,10 +787,10 @@ export class BushClientUtil extends ClientUtil { * @param permissions The permissions to check for. * @returns The missing permissions or null if none are missing. */ - public userGuildPermCheck(message: BushMessage | BushSlashMessage, permissions: PermissionResolvable) { + public userGuildPermCheck(message: BushMessage | BushSlashMessage, permissions: bigint[]) { const missing = message.member?.permissions.missing(permissions) ?? []; - return missing.length ? missing : null; + return missing.length ? missing.map((p) => Permissions.FLAGS[p]) : null; } /** @@ -797,10 +799,10 @@ export class BushClientUtil extends ClientUtil { * @param permissions The permissions to check for. * @returns The missing permissions or null if none are missing. */ - public clientGuildPermCheck(message: BushMessage | BushSlashMessage, permissions: PermissionResolvable) { + public clientGuildPermCheck(message: BushMessage | BushSlashMessage, permissions: bigint[]) { const missing = message.guild?.me?.permissions.missing(permissions) ?? []; - return missing.length ? missing : null; + return missing.length ? missing.map((p) => Permissions.FLAGS[p]) : null; } /** @@ -811,19 +813,18 @@ export class BushClientUtil extends ClientUtil { * @param checkChannel Whether to check the channel permissions instead of the guild permissions. * @returns The missing permissions or null if none are missing. */ - public clientSendAndPermCheck( - message: BushMessage | BushSlashMessage, - permissions: PermissionResolvable = [], - checkChannel = false - ) { + public clientSendAndPermCheck(message: BushMessage | BushSlashMessage, permissions: bigint[] = [], checkChannel = false) { const missing = []; - const sendPerm = message.channel!.isThread() ? 'SEND_MESSAGES' : 'SEND_MESSAGES_IN_THREADS'; + const sendPerm = message.channel!.isThread() ? Permissions.FLAGS.SEND_MESSAGES : Permissions.FLAGS.SEND_MESSAGES_IN_THREADS; if (!message.guild!.me!.permissionsIn(message.channel!.id!).has(sendPerm)) missing.push(sendPerm); missing.push( ...(checkChannel - ? message.guild!.me!.permissionsIn(message.channel!.id!).missing(permissions) + ? message + .guild!.me!.permissionsIn(message.channel!.id!) + .missing(permissions) + .map((p) => Permissions.FLAGS[p]) : this.clientGuildPermCheck(message, permissions) ?? []) ); @@ -894,6 +895,12 @@ export class BushClientUtil extends ClientUtil { return Object.fromEntries(values); } + public get invite() { + return `https://discord.com/api/oauth2/authorize?client_id=${client.user!.id}&permissions=${ + Permissions.ALL + }&scope=bot%20applications.commands`; + } + /** * A wrapper for the Argument class that adds custom typings. */ diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts index fb488be..0456b80 100644 --- a/src/lib/extensions/discord-akairo/BushCommand.ts +++ b/src/lib/extensions/discord-akairo/BushCommand.ts @@ -315,12 +315,12 @@ export interface BaseBushCommandOptions /** * Permissions required by the client to run this command. */ - clientPermissions: PermissionResolvable | PermissionResolvable[] | BushMissingPermissionSupplier; + clientPermissions: bigint | bigint[] | BushMissingPermissionSupplier; /** * Permissions required by the user to run this command. */ - userPermissions: PermissionResolvable | PermissionResolvable[] | BushMissingPermissionSupplier; + userPermissions: bigint | bigint[] | BushMissingPermissionSupplier; /** * Restrict this argument to owners diff --git a/src/lib/extensions/discord-akairo/BushSlashMessage.ts b/src/lib/extensions/discord-akairo/BushSlashMessage.ts index cefd360..d342ea6 100644 --- a/src/lib/extensions/discord-akairo/BushSlashMessage.ts +++ b/src/lib/extensions/discord-akairo/BushSlashMessage.ts @@ -1,4 +1,5 @@ import { + BushGuildTextBasedChannel, type BushClient, type BushCommandUtil, type BushGuild, @@ -7,14 +8,14 @@ import { type BushUser } from '#lib'; import { AkairoMessage } from 'discord-akairo'; -import { type CommandInteraction } from 'discord.js'; +import { type ChatInputCommandInteraction, type ContextMenuCommandInteraction } from 'discord.js'; export class BushSlashMessage extends AkairoMessage { public declare client: BushClient; public declare util: BushCommandUtil<BushSlashMessage>; public declare author: BushUser; public declare member: BushGuildMember | null; - public constructor(client: BushClient, interaction: CommandInteraction) { + public constructor(client: BushClient, interaction: ChatInputCommandInteraction | ContextMenuCommandInteraction) { super(client, interaction); } } @@ -22,5 +23,10 @@ export class BushSlashMessage extends AkairoMessage { export interface BushSlashMessage extends AkairoMessage { get channel(): BushTextBasedChannel | null; get guild(): BushGuild | null; - inGuild(): this is this & { guild: BushGuild; member: BushGuildMember }; + inGuild(): this is BushSlashMessageInGuild & this; +} + +interface BushSlashMessageInGuild { + guild: BushGuild; + channel: BushGuildTextBasedChannel; } diff --git a/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts b/src/lib/extensions/discord.js/BushApplicationCommandManager.ts index 2aa366d..24a7b22 100644 --- a/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts +++ b/src/lib/extensions/discord.js/BushApplicationCommandManager.ts @@ -3,10 +3,12 @@ import type { BushApplicationCommandPermissionsManager, BushApplicationCommandResolvable, BushClient, - BushGuildResolvable + BushGuildResolvable, + StripPrivate } from '#lib'; import type { APIApplicationCommand } from 'discord-api-types'; import { + ApplicationCommandManager, CachedManager, type ApplicationCommandData, type Collection, @@ -17,11 +19,14 @@ import { /** * Manages API methods for application commands and stores their cache. */ -export class BushApplicationCommandManager< - ApplicationCommandScope = BushApplicationCommand<{ guild: BushGuildResolvable }>, - PermissionsOptionsExtras = { guild: BushGuildResolvable }, - PermissionsGuildType = null -> extends CachedManager<Snowflake, ApplicationCommandScope, BushApplicationCommandResolvable> { +export declare class BushApplicationCommandManager< + ApplicationCommandScope = BushApplicationCommand<{ guild: BushGuildResolvable }>, + PermissionsOptionsExtras = { guild: BushGuildResolvable }, + PermissionsGuildType = null + > + extends CachedManager<Snowflake, ApplicationCommandScope, BushApplicationCommandResolvable> + implements StripPrivate<ApplicationCommandManager<ApplicationCommandScope, PermissionsOptionsExtras, PermissionsGuildType>> +{ public constructor(client: BushClient, iterable?: Iterable<unknown>); /** diff --git a/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts b/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts index ff32be4..f07bde9 100644 --- a/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts +++ b/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts @@ -1,6 +1,7 @@ import type { BushClient, BushRoleResolvable, BushUserResolvable } from '#lib'; import type { APIApplicationCommandPermission } from 'discord-api-types'; import { + ApplicationCommandPermissionType, BaseManager, type ApplicationCommand, type ApplicationCommandManager, @@ -11,12 +12,11 @@ import { type GuildApplicationCommandPermissionData, type Snowflake } from 'discord.js'; -import type { ApplicationCommandPermissionTypes } from 'discord.js/typings/enums'; /** * Manages API methods for permissions of Application Commands. */ -export class BushApplicationCommandPermissionsManager< +export declare class BushApplicationCommandPermissionsManager< BaseOptions, FetchSingleOptions, FullPermissionsOptions, @@ -179,6 +179,6 @@ export class BushApplicationCommandPermissionsManager< private static transformPermissions( permissions: ApplicationCommandPermissionData, received: true - ): Omit<APIApplicationCommandPermission, 'type'> & { type: keyof ApplicationCommandPermissionTypes }; + ): Omit<APIApplicationCommandPermission, 'type'> & { type: keyof ApplicationCommandPermissionType }; private static transformPermissions(permissions: ApplicationCommandPermissionData): APIApplicationCommandPermission; } diff --git a/src/lib/extensions/discord.js/BushBaseGuildEmojiManager.d.ts b/src/lib/extensions/discord.js/BushBaseGuildEmojiManager.ts index 347ff65..66abbc2 100644 --- a/src/lib/extensions/discord.js/BushBaseGuildEmojiManager.d.ts +++ b/src/lib/extensions/discord.js/BushBaseGuildEmojiManager.ts @@ -1,11 +1,14 @@ import type { BushClient, BushEmojiIdentifierResolvable, BushEmojiResolvable, BushGuildEmoji } from '#lib'; -import { CachedManager, type Snowflake } from 'discord.js'; +import { BaseGuildEmojiManager, CachedManager, type Snowflake } from 'discord.js'; import { type RawGuildEmojiData } from 'discord.js/typings/rawDataTypes'; /** * Holds methods to resolve GuildEmojis and stores their cache. */ -export class BushBaseGuildEmojiManager extends CachedManager<Snowflake, BushGuildEmoji, BushEmojiResolvable> { +export declare class BushBaseGuildEmojiManager + extends CachedManager<Snowflake, BushGuildEmoji, BushEmojiResolvable> + implements BaseGuildEmojiManager +{ public constructor(client: BushClient, iterable?: Iterable<RawGuildEmojiData>); /** diff --git a/src/lib/extensions/discord.js/BushBaseGuildVoiceChannel.d.ts b/src/lib/extensions/discord.js/BushBaseGuildVoiceChannel.ts index 21be206..2ffb2fd 100644 --- a/src/lib/extensions/discord.js/BushBaseGuildVoiceChannel.d.ts +++ b/src/lib/extensions/discord.js/BushBaseGuildVoiceChannel.ts @@ -6,7 +6,7 @@ import { BushGuildMember } from './BushGuildMember'; /** * Represents a voice-based guild channel on Discord. */ -export class BushBaseGuildVoiceChannel extends BaseGuildVoiceChannel { +export declare class BushBaseGuildVoiceChannel extends BaseGuildVoiceChannel { public readonly members: Collection<Snowflake, BushGuildMember>; public guild: BushGuild; public readonly parent: BushCategoryChannel | null; diff --git a/src/lib/extensions/discord.js/BushCategoryChannel.ts b/src/lib/extensions/discord.js/BushCategoryChannel.ts index b711a54..ac82bf0 100644 --- a/src/lib/extensions/discord.js/BushCategoryChannel.ts +++ b/src/lib/extensions/discord.js/BushCategoryChannel.ts @@ -1,4 +1,19 @@ -import { BushNonThreadGuildBasedChannel, type BushClient, type BushGuild, type BushGuildMember } from '#lib'; +import { + BushDMChannel, + BushGuildBasedChannel, + BushNewsChannel, + BushNonThreadGuildBasedChannel, + BushStageChannel, + BushStoreChannel, + BushTextBasedChannel, + BushTextChannel, + BushThreadChannel, + BushVoiceBasedChannel, + BushVoiceChannel, + type BushClient, + type BushGuild, + type BushGuildMember +} from '#lib'; import { CategoryChannel, type Collection, type Snowflake } from 'discord.js'; import { type RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; @@ -16,3 +31,17 @@ export class BushCategoryChannel extends CategoryChannel { super(guild, data, client, immediatePatch); } } + +export interface BushCategoryChannel extends CategoryChannel { + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + // eslint-disable-next-line deprecation/deprecation + isStore(): this is BushStoreChannel; + isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/BushChannel.d.ts b/src/lib/extensions/discord.js/BushChannel.d.ts deleted file mode 100644 index 42443ba..0000000 --- a/src/lib/extensions/discord.js/BushChannel.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { BushClient, BushTextBasedChannel, BushThreadChannel } from '#lib'; -import { Channel, type ChannelMention, type Snowflake } from 'discord.js'; -import type { ChannelTypes } from 'discord.js/typings/enums'; -import type { RawChannelData } from 'discord.js/typings/rawDataTypes'; -import { BushBaseGuildVoiceChannel } from './BushBaseGuildVoiceChannel'; - -/** - * Represents any channel on Discord. - */ -export class BushChannel extends Channel { - public constructor(client: BushClient, data?: RawChannelData, immediatePatch?: boolean); - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public deleted: boolean; - public id: Snowflake; - public readonly partial: false; - public type: keyof typeof ChannelTypes; - public delete(): Promise<this>; - public fetch(force?: boolean): Promise<this>; - public isText(): this is BushTextBasedChannel; - public isVoice(): this is BushBaseGuildVoiceChannel; - public isThread(): this is BushThreadChannel; - public toString(): ChannelMention; -} diff --git a/src/lib/extensions/discord.js/BushChannel.ts b/src/lib/extensions/discord.js/BushChannel.ts new file mode 100644 index 0000000..50ec723 --- /dev/null +++ b/src/lib/extensions/discord.js/BushChannel.ts @@ -0,0 +1,41 @@ +/* eslint-disable deprecation/deprecation */ +import type { + BushCategoryChannel, + BushClient, + BushDMChannel, + BushNewsChannel, + BushStageChannel, + BushStoreChannel, + BushTextBasedChannel, + BushTextChannel, + BushThreadChannel, + BushVoiceBasedChannel, + BushVoiceChannel +} from '#lib'; +import { Channel, ChannelType, type Snowflake } from 'discord.js'; +import type { RawChannelData } from 'discord.js/typings/rawDataTypes'; + +/** + * Represents any channel on Discord. + */ +export declare class BushChannel extends Channel { + public constructor(client: BushClient, data?: RawChannelData, immediatePatch?: boolean); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public deleted: boolean; + public id: Snowflake; + public readonly partial: false; + public type: ChannelType; + public delete(): Promise<this>; + public fetch(force?: boolean): Promise<this>; + public isText(): this is BushTextChannel; + public isDM(): this is BushDMChannel; + public isVoice(): this is BushVoiceChannel; + public isCategory(): this is BushCategoryChannel; + public isNews(): this is BushNewsChannel; + public isStore(): this is BushStoreChannel; + public isThread(): this is BushThreadChannel; + public isStage(): this is BushStageChannel; + public isTextBased(): this is BushTextBasedChannel; + public isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/BushChannelManager.d.ts b/src/lib/extensions/discord.js/BushChannelManager.ts index 514cdd3..ff93209 100644 --- a/src/lib/extensions/discord.js/BushChannelManager.d.ts +++ b/src/lib/extensions/discord.js/BushChannelManager.ts @@ -1,11 +1,14 @@ import type { BushAnyChannel, BushChannelResolvable } from '#lib'; -import { CachedManager, type Client, type FetchChannelOptions, type Snowflake } from 'discord.js'; +import { CachedManager, ChannelManager, type Client, type FetchChannelOptions, type Snowflake } from 'discord.js'; import type { RawChannelData } from 'discord.js/typings/rawDataTypes'; /** * A manager of channels belonging to a client */ -export class BushChannelManager extends CachedManager<Snowflake, BushAnyChannel, BushChannelResolvable> { +export declare class BushChannelManager + extends CachedManager<Snowflake, BushAnyChannel, BushChannelResolvable> + implements ChannelManager +{ public constructor(client: Client, iterable: Iterable<RawChannelData>); /** diff --git a/src/lib/extensions/discord.js/BushCommandInteraction.ts b/src/lib/extensions/discord.js/BushChatInputCommandInteraction.ts index f4be5ed..56bef21 100644 --- a/src/lib/extensions/discord.js/BushCommandInteraction.ts +++ b/src/lib/extensions/discord.js/BushChatInputCommandInteraction.ts @@ -11,7 +11,7 @@ import type { BushUser } from '#lib'; import type { APIInteractionGuildMember } from '@discordjs/builders/node_modules/discord-api-types'; -import { CommandInteraction, type CacheType, type CacheTypeReducer, type Invite, type Snowflake } from 'discord.js'; +import { ChatInputCommandInteraction, type CacheType, type CacheTypeReducer, type Invite, type Snowflake } from 'discord.js'; import type { RawCommandInteractionData } from 'discord.js/typings/rawDataTypes'; export type BushGuildResolvable = @@ -26,7 +26,7 @@ export type BushGuildResolvable = /** * Represents a command interaction. */ -export class BushCommandInteraction<Cached extends CacheType = CacheType> extends CommandInteraction<Cached> { +export class BushChatInputCommandInteraction<Cached extends CacheType = CacheType> extends ChatInputCommandInteraction<Cached> { public declare readonly client: BushClient; public declare readonly command: BushApplicationCommand | BushApplicationCommand<{ guild: BushGuildResolvable }> | null; public declare readonly channel: CacheTypeReducer< diff --git a/src/lib/extensions/discord.js/BushClientEvents.d.ts b/src/lib/extensions/discord.js/BushClientEvents.ts index b5ad749..02f0017 100644 --- a/src/lib/extensions/discord.js/BushClientEvents.d.ts +++ b/src/lib/extensions/discord.js/BushClientEvents.ts @@ -43,10 +43,7 @@ import type { export interface BushClientEvents extends AkairoClientEvents { applicationCommandCreate: [command: BushApplicationCommand]; applicationCommandDelete: [command: BushApplicationCommand]; - applicationCommandUpdate: [ - oldCommand: BushApplicationCommand | null, - newCommand: BushApplicationCommand - ]; + applicationCommandUpdate: [oldCommand: BushApplicationCommand | null, newCommand: BushApplicationCommand]; channelCreate: [channel: BushNonThreadGuildBasedChannel]; channelDelete: [channel: BushDMChannel | BushNonThreadGuildBasedChannel]; channelPinsUpdate: [channel: BushTextBasedChannel, date: Date]; @@ -78,37 +75,18 @@ export interface BushClientEvents extends AkairoClientEvents { nonce: string | undefined; } ]; - guildMemberUpdate: [ - oldMember: BushGuildMember | PartialBushGuildMember, - newMember: BushGuildMember - ]; + guildMemberUpdate: [oldMember: BushGuildMember | PartialBushGuildMember, newMember: BushGuildMember]; guildUpdate: [oldGuild: BushGuild, newGuild: BushGuild]; inviteCreate: [invite: Invite]; inviteDelete: [invite: Invite]; messageCreate: [message: BushMessage]; messageDelete: [message: BushMessage | PartialBushMessage]; - messageReactionRemoveAll: [ - message: BushMessage | PartialBushMessage, - reactions: Collection<string, BushMessageReaction> - ]; - messageReactionRemoveEmoji: [ - reaction: BushMessageReaction | PartialBushMessageReaction - ]; - messageDeleteBulk: [ - messages: Collection<Snowflake, BushMessage | PartialBushMessage> - ]; - messageReactionAdd: [ - reaction: BushMessageReaction | PartialBushMessageReaction, - user: BushUser | PartialBushUser - ]; - messageReactionRemove: [ - reaction: BushMessageReaction | PartialBushMessageReaction, - user: BushUser | PartialBushUser - ]; - messageUpdate: [ - oldMessage: BushMessage | PartialBushMessage, - newMessage: BushMessage | PartialBushMessage - ]; + messageReactionRemoveAll: [message: BushMessage | PartialBushMessage, reactions: Collection<string, BushMessageReaction>]; + messageReactionRemoveEmoji: [reaction: BushMessageReaction | PartialBushMessageReaction]; + messageDeleteBulk: [messages: Collection<Snowflake, BushMessage | PartialBushMessage>]; + messageReactionAdd: [reaction: BushMessageReaction | PartialBushMessageReaction, user: BushUser | PartialBushUser]; + messageReactionRemove: [reaction: BushMessageReaction | PartialBushMessageReaction, user: BushUser | PartialBushUser]; + messageUpdate: [oldMessage: BushMessage | PartialBushMessage, newMessage: BushMessage | PartialBushMessage]; presenceUpdate: [oldPresence: BushPresence | null, newPresence: BushPresence]; rateLimit: [rateLimitData: RateLimitData]; invalidRequestWarning: [invalidRequestWarningData: InvalidRequestWarningData]; @@ -120,14 +98,8 @@ export interface BushClientEvents extends AkairoClientEvents { threadCreate: [thread: BushThreadChannel]; threadDelete: [thread: BushThreadChannel]; threadListSync: [threads: Collection<Snowflake, BushThreadChannel>]; - threadMemberUpdate: [ - oldMember: BushThreadMember, - newMember: BushThreadMember - ]; - threadMembersUpdate: [ - oldMembers: Collection<Snowflake, BushThreadMember>, - newMembers: Collection<Snowflake, BushThreadMember> - ]; + threadMemberUpdate: [oldMember: BushThreadMember, newMember: BushThreadMember]; + threadMembersUpdate: [oldMembers: Collection<Snowflake, BushThreadMember>, newMembers: Collection<Snowflake, BushThreadMember>]; threadUpdate: [oldThread: BushThreadChannel, newThread: BushThreadChannel]; typingStart: [typing: Typing]; userUpdate: [oldUser: BushUser | PartialBushUser, newUser: BushUser]; @@ -139,28 +111,16 @@ export interface BushClientEvents extends AkairoClientEvents { shardReconnecting: [shardId: number]; shardResume: [shardId: number, replayedEvents: number]; stageInstanceCreate: [stageInstance: BushStageInstance]; - stageInstanceUpdate: [ - oldStageInstance: BushStageInstance | null, - newStageInstance: BushStageInstance - ]; + stageInstanceUpdate: [oldStageInstance: BushStageInstance | null, newStageInstance: BushStageInstance]; stageInstanceDelete: [stageInstance: BushStageInstance]; stickerCreate: [sticker: Sticker]; stickerDelete: [sticker: Sticker]; stickerUpdate: [oldSticker: Sticker, newSticker: Sticker]; guildScheduledEventCreate: [guildScheduledEvent: GuildScheduledEvent]; - guildScheduledEventUpdate: [ - oldGuildScheduledEvent: GuildScheduledEvent, - newGuildScheduledEvent: GuildScheduledEvent - ]; + guildScheduledEventUpdate: [oldGuildScheduledEvent: GuildScheduledEvent, newGuildScheduledEvent: GuildScheduledEvent]; guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent]; - guildScheduledEventUserAdd: [ - guildScheduledEvent: GuildScheduledEvent, - user: BushUser - ]; - guildScheduledEventUserRemove: [ - guildScheduledEvent: GuildScheduledEvent, - user: BushUser - ]; + guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent, user: BushUser]; + guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent, user: BushUser]; /* Custom */ bushBan: [ victim: BushGuildMember | BushUser, @@ -318,9 +278,4 @@ export interface BushClientEvents extends AkairoClientEvents { ]; } -type Setting = - | GuildSettings - | 'enabledFeatures' - | 'blacklistedChannels' - | 'blacklistedUsers' - | 'disabledCommands'; +type Setting = GuildSettings | 'enabledFeatures' | 'blacklistedChannels' | 'blacklistedUsers' | 'disabledCommands'; diff --git a/src/lib/extensions/discord.js/BushClientUser.d.ts b/src/lib/extensions/discord.js/BushClientUser.ts index 503413b..a9a47f9 100644 --- a/src/lib/extensions/discord.js/BushClientUser.d.ts +++ b/src/lib/extensions/discord.js/BushClientUser.ts @@ -13,7 +13,7 @@ import { BushUser } from './BushUser'; /** * Represents the logged in client's Discord user. */ -export class BushClientUser extends BushUser implements ClientUser { +export declare class BushClientUser extends BushUser implements ClientUser { /** * If the bot's {@link ClientApplication.owner Owner} has MFA enabled on their account */ diff --git a/src/lib/extensions/discord.js/BushDMChannel.ts b/src/lib/extensions/discord.js/BushDMChannel.ts index 1af3ca1..363c620 100644 --- a/src/lib/extensions/discord.js/BushDMChannel.ts +++ b/src/lib/extensions/discord.js/BushDMChannel.ts @@ -1,12 +1,19 @@ +/* eslint-disable deprecation/deprecation */ import type { - BushBaseGuildVoiceChannel, + BushCategoryChannel, BushClient, BushMessageManager, + BushNewsChannel, + BushStageChannel, + BushStoreChannel, BushTextBasedChannel, + BushTextChannel, BushThreadChannel, - BushUser + BushUser, + BushVoiceBasedChannel, + BushVoiceChannel } from '#lib'; -import { DMChannel } from 'discord.js'; +import { DMChannel, type Partialize } from 'discord.js'; import type { RawDMChannelData } from 'discord.js/typings/rawDataTypes'; /** @@ -23,7 +30,18 @@ export class BushDMChannel extends DMChannel { } export interface BushDMChannel extends DMChannel { - isText(): this is BushTextBasedChannel; - isVoice(): this is BushBaseGuildVoiceChannel; + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} + +export interface PartialBushDMChannel extends Partialize<BushDMChannel, null, null, 'lastMessageId'> { + lastMessageId: undefined; } diff --git a/src/lib/extensions/discord.js/BushGuild.ts b/src/lib/extensions/discord.js/BushGuild.ts index 33ee3fc..9f114b6 100644 --- a/src/lib/extensions/discord.js/BushGuild.ts +++ b/src/lib/extensions/discord.js/BushGuild.ts @@ -5,6 +5,7 @@ import { punishmentEntryRemove, type BanResponse, type BushClient, + type BushGuildChannelManager, type BushGuildMember, type BushGuildMemberManager, type BushGuildMemberResolvable, @@ -17,7 +18,7 @@ import { type GuildLogType, type GuildModel } from '#lib'; -import { Collection, Guild, Snowflake, type GuildChannelManager, type MessageOptions, type MessagePayload } from 'discord.js'; +import { Collection, Guild, Permissions, Snowflake, type MessageOptions, type MessagePayload } from 'discord.js'; import type { RawGuildData } from 'discord.js/typings/rawDataTypes'; import _ from 'lodash'; import { Moderation } from '../../common/util/Moderation.js'; @@ -33,7 +34,7 @@ export class BushGuild extends Guild { public declare readonly client: BushClient; public declare readonly me: BushGuildMember | null; public declare members: BushGuildMemberManager; - public declare channels: GuildChannelManager; + public declare channels: BushGuildChannelManager; public constructor(client: BushClient, data: RawGuildData) { super(client, data); @@ -133,8 +134,13 @@ export class BushGuild extends Guild { */ public async sendLogChannel(logType: GuildLogType, message: string | MessagePayload | MessageOptions) { const logChannel = await this.getLogChannel(logType); - if (!logChannel || logChannel.type !== 'GUILD_TEXT') return; - if (!logChannel.permissionsFor(this.me!.id)?.has(['VIEW_CHANNEL', 'SEND_MESSAGES', 'EMBED_LINKS'])) return; + if (!logChannel || !logChannel.isTextBased()) return; + if ( + !logChannel + .permissionsFor(this.me!.id) + ?.has([Permissions.FLAGS.VIEW_CHANNEL, Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.EMBED_LINKS]) + ) + return; return await logChannel.send(message).catch(() => null); } @@ -156,12 +162,13 @@ export class BushGuild extends Guild { */ public async bushBan(options: GuildBushBanOptions): Promise<BanResponse> { // checks - if (!this.me!.permissions.has('BAN_MEMBERS')) return banResponse.MISSING_PERMISSIONS; + if (!this.me!.permissions.has(Permissions.FLAGS.BAN_MEMBERS)) return banResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const user = (await util.resolveNonCachedUser(options.user))!; - const moderator = client.users.resolve(options.moderator ?? client.user!)!; + const user = await util.resolveNonCachedUser(options.user); + const moderator = client.users.resolve(options.moderator ?? client.user!); + if (!user || !moderator) return banResponse.CANNOT_RESOLVE_USER; if ((await this.bans.fetch()).has(user.id)) return banResponse.ALREADY_BANNED; @@ -234,12 +241,13 @@ export class BushGuild extends Guild { */ public async bushUnban(options: GuildBushUnbanOptions): Promise<UnbanResponse> { // checks - if (!this.me!.permissions.has('BAN_MEMBERS')) return unbanResponse.MISSING_PERMISSIONS; + if (!this.me!.permissions.has(Permissions.FLAGS.BAN_MEMBERS)) return unbanResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const user = (await util.resolveNonCachedUser(options.user))!; - const moderator = client.users.resolve(options.moderator ?? client.user!)!; + const user = await util.resolveNonCachedUser(options.user); + const moderator = client.users.resolve(options.moderator ?? client.user!); + if (!user || !moderator) return unbanResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { const bans = await this.bans.fetch(); @@ -327,11 +335,11 @@ export class BushGuild extends Guild { success.set(channel.id, false); continue; } - if (!channel.permissionsFor(this.me!.id)?.has(['MANAGE_CHANNELS'])) { + if (!channel.permissionsFor(this.me!.id)?.has([Permissions.FLAGS.MANAGE_CHANNELS])) { errors.set(channel.id, new Error('client no permission')); success.set(channel.id, false); continue; - } else if (!channel.permissionsFor(options.moderator)?.has(['MANAGE_CHANNELS'])) { + } else if (!channel.permissionsFor(moderator)?.has([Permissions.FLAGS.MANAGE_CHANNELS])) { errors.set(channel.id, new Error('moderator no permission')); success.set(channel.id, false); continue; @@ -342,8 +350,12 @@ export class BushGuild extends Guild { }`; const permissionOverwrites = channel.isThread() ? channel.parent!.permissionOverwrites : channel.permissionOverwrites; - const perms = { [channel.isThread() ? 'SEND_MESSAGES_IN_THREADS' : 'SEND_MESSAGES']: options.unlock ? null : false }; - const permsForMe = { [channel.isThread() ? 'SEND_MESSAGES_IN_THREADS' : 'SEND_MESSAGES']: options.unlock ? null : true }; // so I can send messages in the channel + const perms = { + [channel.isThread() ? 'SEND_MESSAGES_IN_THREADS' : 'FLAGS.SEND_MESSAGES']: options.unlock ? null : false + }; + const permsForMe = { + [channel.isThread() ? 'SEND_MESSAGES_IN_THREADS' : 'FLAGS.SEND_MESSAGES']: options.unlock ? null : true + }; // so I can send messages in the channel const changePermSuccess = await permissionOverwrites.edit(this.id, perms, { reason }).catch((e) => e); if (changePermSuccess instanceof Error) { @@ -355,7 +367,7 @@ export class BushGuild extends Guild { await channel.send({ embeds: [ { - author: { name: moderator.user.tag, iconURL: moderator.displayAvatarURL({ dynamic: true }) }, + author: { name: moderator.user.tag, iconURL: moderator.displayAvatarURL() }, title: `This channel has been ${options.unlock ? 'un' : ''}locked`, description: options.reason ?? 'No reason provided', color: options.unlock ? util.colors.discord.GREEN : util.colors.discord.RED, diff --git a/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts b/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts index 4d76b07..ba9db66 100644 --- a/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts @@ -12,7 +12,11 @@ import type { RawApplicationCommandData } from 'discord.js/typings/rawDataTypes' /** * An extension for guild-specific application commands. */ -export class BushGuildApplicationCommandManager extends BushApplicationCommandManager<BushApplicationCommand, {}, BushGuild> { +export declare class BushGuildApplicationCommandManager extends BushApplicationCommandManager< + BushApplicationCommand, + {}, + BushGuild +> { public constructor(guild: BushGuild, iterable?: Iterable<RawApplicationCommandData>); public declare readonly client: BushClient; diff --git a/src/lib/extensions/discord.js/BushGuildBan.d.ts b/src/lib/extensions/discord.js/BushGuildBan.ts index 11875f3..496e798 100644 --- a/src/lib/extensions/discord.js/BushGuildBan.d.ts +++ b/src/lib/extensions/discord.js/BushGuildBan.ts @@ -5,7 +5,7 @@ import type { RawGuildBanData } from 'discord.js/typings/rawDataTypes'; /** * Represents a ban in a guild on Discord. */ -export class BushGuildBan extends GuildBan { +export declare class BushGuildBan extends GuildBan { public constructor(client: BushClient, data: RawGuildBanData, guild: BushGuild); public guild: BushGuild; public user: BushUser; diff --git a/src/lib/extensions/discord.js/BushGuildChannel.ts b/src/lib/extensions/discord.js/BushGuildChannel.ts index 6880daf..053507e 100644 --- a/src/lib/extensions/discord.js/BushGuildChannel.ts +++ b/src/lib/extensions/discord.js/BushGuildChannel.ts @@ -1,4 +1,19 @@ -import type { BushClient, BushGuild } from '#lib'; +/* eslint-disable deprecation/deprecation */ +import type { + BushCategoryChannel, + BushClient, + BushDMChannel, + BushGuild, + BushGuildBasedChannel, + BushNewsChannel, + BushStageChannel, + BushStoreChannel, + BushTextBasedChannel, + BushTextChannel, + BushThreadChannel, + BushVoiceBasedChannel, + BushVoiceChannel +} from '#lib'; import { GuildChannel } from 'discord.js'; import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; @@ -19,3 +34,16 @@ export class BushGuildChannel extends GuildChannel { super(guild, data, client, immediatePatch); } } + +export interface BushGuildChannel extends GuildChannel { + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; + isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/BushGuildChannelManager.d.ts b/src/lib/extensions/discord.js/BushGuildChannelManager.ts index 3b07145..dd3885b 100644 --- a/src/lib/extensions/discord.js/BushGuildChannelManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildChannelManager.ts @@ -1,6 +1,7 @@ import type { BushFetchedThreads, BushGuild, + BushGuildBasedChannel, BushMappedGuildChannelTypes, BushNonThreadGuildBasedChannel, BushStoreChannel @@ -10,7 +11,6 @@ import { type BaseFetchOptions, type ChannelPosition, type Collection, - type GuildBasedChannel, type GuildChannelCreateOptions, type GuildChannelManager, type GuildChannelResolvable, @@ -22,8 +22,8 @@ import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for GuildChannels and stores their cache. */ -export class BushGuildChannelManager - extends CachedManager<Snowflake, GuildBasedChannel, GuildChannelResolvable> +export declare class BushGuildChannelManager + extends CachedManager<Snowflake, BushGuildBasedChannel, GuildChannelResolvable> implements GuildChannelManager { public constructor(guild: BushGuild, iterable?: Iterable<RawGuildChannelData>); @@ -51,7 +51,7 @@ export class BushGuildChannelManager * @example * // Create a new channel with permission overwrites * guild.channels.create('new-voice', { - * type: 'GUILD_VOICE', + * type: 'GuildVoice', * permissionOverwrites: [ * { * id: message.author.id, @@ -62,7 +62,7 @@ export class BushGuildChannelManager * @deprecated See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ // eslint-disable-next-line deprecation/deprecation - public create(name: string, options: GuildChannelCreateOptions & { type: 'GUILD_STORE' }): Promise<BushStoreChannel>; + public create(name: string, options: GuildChannelCreateOptions & { type: 'GuildStore' }): Promise<BushStoreChannel>; /** * Creates a new channel in the guild. @@ -112,7 +112,7 @@ export class BushGuildChannelManager /** * Obtains all active thread channels in the guild from Discord - * @param cache Whether to cache the fetched data + * @param {} [cache=true] Whether to cache the fetched data * @example * // Fetch all threads from the guild * message.guild.channels.fetchActiveThreads() diff --git a/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts b/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts index 9253cad..8b069ae 100644 --- a/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts @@ -1,10 +1,13 @@ import type { BushClient, BushGuild, BushGuildEmoji, BushRole, BushRoleResolvable } from '#lib'; -import { DataManager, type Collection, type Snowflake } from 'discord.js'; +import { DataManager, GuildEmojiRoleManager, type Collection, type Snowflake } from 'discord.js'; /** * Manages API methods for roles belonging to emojis and stores their cache. */ -export class BushGuildEmojiRoleManager extends DataManager<Snowflake, BushRole, BushRoleResolvable> { +export declare class BushGuildEmojiRoleManager + extends DataManager<Snowflake, BushRole, BushRoleResolvable> + implements GuildEmojiRoleManager +{ public constructor(emoji: BushGuildEmoji); public declare readonly client: BushClient; diff --git a/src/lib/extensions/discord.js/BushGuildManager.d.ts b/src/lib/extensions/discord.js/BushGuildManager.ts index 95719a3..41618e3 100644 --- a/src/lib/extensions/discord.js/BushGuildManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildManager.ts @@ -1,6 +1,7 @@ import type { BushClient, BushGuild, BushGuildResolvable } from '#lib'; import { CachedManager, + GuildManager, type Collection, type FetchGuildOptions, type FetchGuildsOptions, @@ -13,7 +14,7 @@ import { type RawGuildData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for Guilds and stores their cache. */ -export class BushGuildManager extends CachedManager<Snowflake, BushGuild, BushGuildResolvable> { +export declare class BushGuildManager extends CachedManager<Snowflake, BushGuild, BushGuildResolvable> implements GuildManager { public constructor(client: BushClient, iterable?: Iterable<RawGuildData>); /** diff --git a/src/lib/extensions/discord.js/BushGuildMember.ts b/src/lib/extensions/discord.js/BushGuildMember.ts index 54fb3f0..10d8a4c 100644 --- a/src/lib/extensions/discord.js/BushGuildMember.ts +++ b/src/lib/extensions/discord.js/BushGuildMember.ts @@ -11,7 +11,7 @@ import { type BushThreadChannelResolvable, type BushUser } from '#lib'; -import { GuildMember, type Partialize, type Role } from 'discord.js'; +import { GuildMember, Permissions, type Partialize, type Role } from 'discord.js'; import type { RawGuildMemberData } from 'discord.js/typings/rawDataTypes'; /* eslint-enable @typescript-eslint/no-unused-vars */ @@ -48,7 +48,8 @@ export class BushGuildMember extends GuildMember { public async bushWarn(options: BushPunishmentOptions): Promise<{ result: WarnResponse; caseNum: number | null }> { let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return { result: warnResponse.CANNOT_RESOLVE_USER, caseNum: null }; const ret = await (async (): Promise<{ result: WarnResponse; caseNum: number | null }> => { // add modlog entry @@ -89,12 +90,13 @@ export class BushGuildMember extends GuildMember { */ public async bushAddRole(options: AddRoleOptions): Promise<AddRoleResponse> { // checks - if (!this.guild.me!.permissions.has('MANAGE_ROLES')) return addRoleResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return addRoleResponse.MISSING_PERMISSIONS; const ifShouldAddRole = this.#checkIfShouldAddRole(options.role, options.moderator); if (ifShouldAddRole !== true) return ifShouldAddRole; let caseID: string | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return addRoleResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { if (options.addToModlog || options.duration) { @@ -159,12 +161,13 @@ export class BushGuildMember extends GuildMember { */ public async bushRemoveRole(options: RemoveRoleOptions): Promise<RemoveRoleResponse> { // checks - if (!this.guild.me!.permissions.has('MANAGE_ROLES')) return removeRoleResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return removeRoleResponse.MISSING_PERMISSIONS; const ifShouldAddRole = this.#checkIfShouldAddRole(options.role, options.moderator); if (ifShouldAddRole !== true) return ifShouldAddRole; let caseID: string | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return removeRoleResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { if (options.addToModlog) { @@ -249,7 +252,7 @@ export class BushGuildMember extends GuildMember { */ public async bushMute(options: BushTimedPunishmentOptions): Promise<MuteResponse> { // checks - if (!this.guild.me!.permissions.has('MANAGE_ROLES')) return muteResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return muteResponse.MISSING_PERMISSIONS; const muteRoleID = await this.guild.getSetting('muteRole'); if (!muteRoleID) return muteResponse.NO_MUTE_ROLE; const muteRole = this.guild.roles.cache.get(muteRoleID); @@ -259,7 +262,8 @@ export class BushGuildMember extends GuildMember { let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return muteResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // add role @@ -334,7 +338,7 @@ export class BushGuildMember extends GuildMember { */ public async bushUnmute(options: BushPunishmentOptions): Promise<UnmuteResponse> { // checks - if (!this.guild.me!.permissions.has('MANAGE_ROLES')) return unmuteResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return unmuteResponse.MISSING_PERMISSIONS; const muteRoleID = await this.guild.getSetting('muteRole'); if (!muteRoleID) return unmuteResponse.NO_MUTE_ROLE; const muteRole = this.guild.roles.cache.get(muteRoleID); @@ -344,7 +348,8 @@ export class BushGuildMember extends GuildMember { let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return unmuteResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // remove role @@ -416,11 +421,13 @@ export class BushGuildMember extends GuildMember { */ public async bushKick(options: BushPunishmentOptions): Promise<KickResponse> { // checks - if (!this.guild.me?.permissions.has('KICK_MEMBERS') || !this.kickable) return kickResponse.MISSING_PERMISSIONS; + if (!this.guild.me?.permissions.has(Permissions.FLAGS.KICK_MEMBERS) || !this.kickable) + return kickResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return kickResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // dm user const dmSuccess = options.silent ? null : await this.bushPunishDM('kicked', options.reason); @@ -467,11 +474,12 @@ export class BushGuildMember extends GuildMember { */ public async bushBan(options: BushBanOptions): Promise<Exclude<BanResponse, typeof banResponse['ALREADY_BANNED']>> { // checks - if (!this.guild.me!.permissions.has('BAN_MEMBERS') || !this.bannable) return banResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.BAN_MEMBERS) || !this.bannable) return banResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return banResponse.CANNOT_RESOLVE_USER; // ignore result, they should still be banned even if their mute cannot be removed await this.bushUnmute({ @@ -542,16 +550,16 @@ export class BushGuildMember extends GuildMember { * @param options Options for blocking the user. */ public async bushBlock(options: BlockOptions): Promise<BlockResponse> { - const _channel = this.guild.channels.resolve(options.channel); - if (!_channel || (!_channel.isText() && !_channel.isThread())) return blockResponse.INVALID_CHANNEL; - const channel = _channel as BushGuildTextBasedChannel; + const channel = this.guild.channels.resolve(options.channel); + if (!channel || (!channel.isTextBased() && !channel.isThread())) return blockResponse.INVALID_CHANNEL; // checks - if (!channel.permissionsFor(this.guild.me!)!.has('MANAGE_CHANNELS')) return blockResponse.MISSING_PERMISSIONS; + if (!channel.permissionsFor(this.guild.me!)!.has(Permissions.FLAGS.MANAGE_CHANNELS)) return blockResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return blockResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // change channel permissions @@ -635,11 +643,13 @@ export class BushGuildMember extends GuildMember { const channel = _channel as BushGuildTextBasedChannel; // checks - if (!channel.permissionsFor(this.guild.me!)!.has('MANAGE_CHANNELS')) return unblockResponse.MISSING_PERMISSIONS; + if (!channel.permissionsFor(this.guild.me!)!.has(Permissions.FLAGS.MANAGE_CHANNELS)) + return unblockResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return unblockResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // change channel permissions @@ -710,14 +720,15 @@ export class BushGuildMember extends GuildMember { */ public async bushTimeout(options: BushTimeoutOptions): Promise<TimeoutResponse> { // checks - if (!this.guild.me!.permissions.has('MODERATE_MEMBERS')) return timeoutResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MODERATE_MEMBERS)) return timeoutResponse.MISSING_PERMISSIONS; const twentyEightDays = client.consts.timeUnits.days.value * 28; if (options.duration > twentyEightDays) return timeoutResponse.INVALID_DURATION; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return timeoutResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // timeout @@ -773,11 +784,12 @@ export class BushGuildMember extends GuildMember { */ public async bushRemoveTimeout(options: BushPunishmentOptions): Promise<RemoveTimeoutResponse> { // checks - if (!this.guild.me!.permissions.has('MODERATE_MEMBERS')) return removeTimeoutResponse.MISSING_PERMISSIONS; + if (!this.guild.me!.permissions.has(Permissions.FLAGS.MODERATE_MEMBERS)) return removeTimeoutResponse.MISSING_PERMISSIONS; let caseID: string | undefined = undefined; let dmSuccessEvent: boolean | undefined = undefined; - const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!; + const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.me); + if (!moderator) return removeTimeoutResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // remove timeout @@ -949,7 +961,8 @@ type ValueOf<T> = T[keyof T]; export const basePunishmentResponse = Object.freeze({ SUCCESS: 'success', MODLOG_ERROR: 'error creating modlog entry', - ACTION_ERROR: 'error performing action' + ACTION_ERROR: 'error performing action', + CANNOT_RESOLVE_USER: 'cannot resolve user' } as const); export const dmResponse = Object.freeze({ diff --git a/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts b/src/lib/extensions/discord.js/BushGuildMemberManager.ts index a0e65e7..bb130fc 100644 --- a/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildMemberManager.ts @@ -1,6 +1,7 @@ import type { BushClient, BushGuild, BushGuildMember, BushGuildMemberResolvable, BushUser, BushUserResolvable } from '#lib'; import { CachedManager, + GuildMemberManager, type AddGuildMemberOptions, type BanOptions, type Collection, @@ -17,7 +18,10 @@ import type { RawGuildMemberData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for GuildMembers and stores their cache. */ -export class BushGuildMemberManager extends CachedManager<Snowflake, BushGuildMember, BushGuildMemberResolvable> { +export declare class BushGuildMemberManager + extends CachedManager<Snowflake, BushGuildMember, BushGuildMemberResolvable> + implements GuildMemberManager +{ public constructor(guild: BushGuild, iterable?: Iterable<RawGuildMemberData>); public declare readonly client: BushClient; diff --git a/src/lib/extensions/discord.js/BushMessage.ts b/src/lib/extensions/discord.js/BushMessage.ts index 16c57a2..420f8f5 100644 --- a/src/lib/extensions/discord.js/BushMessage.ts +++ b/src/lib/extensions/discord.js/BushMessage.ts @@ -10,10 +10,10 @@ import type { BushUser } from '#lib'; import { + ActionRowComponent, Message, type EmojiIdentifierResolvable, type If, - type MessageActionRowComponent, type MessageEditOptions, type MessagePayload, type Partialize, @@ -55,7 +55,7 @@ export interface BushMessage<Cached extends boolean = boolean> extends Message<C react(emoji: EmojiIdentifierResolvable): Promise<BushMessageReaction>; removeAttachments(): Promise<BushMessage>; reply(options: string | MessagePayload | ReplyMessageOptions): Promise<BushMessage>; - resolveComponent(customId: string): MessageActionRowComponent | null; + resolveComponent(customId: string): ActionRowComponent | null; startThread(options: StartThreadOptions): Promise<BushThreadChannel>; suppressEmbeds(suppress?: boolean): Promise<BushMessage>; unpin(): Promise<BushMessage>; diff --git a/src/lib/extensions/discord.js/BushMessageManager.d.ts b/src/lib/extensions/discord.js/BushMessageManager.ts index 84918c0..7ed4199 100644 --- a/src/lib/extensions/discord.js/BushMessageManager.d.ts +++ b/src/lib/extensions/discord.js/BushMessageManager.ts @@ -1,6 +1,7 @@ import { BushMessageResolvable, BushTextBasedChannel, type BushMessage } from '#lib'; import { CachedManager, + MessageManager, type BaseFetchOptions, type ChannelLogsQueryOptions, type Collection, @@ -14,7 +15,10 @@ import type { RawMessageData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for Messages and holds their cache. */ -export class BushMessageManager extends CachedManager<Snowflake, BushMessage, BushMessageResolvable> { +export declare class BushMessageManager + extends CachedManager<Snowflake, BushMessage, BushMessageResolvable> + implements MessageManager +{ public constructor(channel: BushTextBasedChannel, iterable?: Iterable<RawMessageData>); /** @@ -44,7 +48,7 @@ export class BushMessageManager extends CachedManager<Snowflake, BushMessage, Bu * @param message The message to edit * @param options The options to edit the message */ - public edit(message: BushMessageResolvable, options: MessagePayload | MessageEditOptions): Promise<BushMessage>; + public edit(message: BushMessageResolvable, options: string | MessagePayload | MessageEditOptions): Promise<BushMessage>; /** * Gets a message, or messages, from this channel. @@ -75,7 +79,7 @@ export class BushMessageManager extends CachedManager<Snowflake, BushMessage, Bu * Fetches the pinned messages of this channel and returns a collection of them. * <info>The returned Collection does not contain any reaction data of the messages. * Those need to be fetched separately.</info> - * @param cache Whether to cache the message(s) + * @param {} [cache=true] Whether to cache the message(s) * @example * // Get pinned messages * channel.messages.fetchPinned() diff --git a/src/lib/extensions/discord.js/BushStoreChannel.ts b/src/lib/extensions/discord.js/BushStoreChannel.ts index cb75076..dbc53e8 100644 --- a/src/lib/extensions/discord.js/BushStoreChannel.ts +++ b/src/lib/extensions/discord.js/BushStoreChannel.ts @@ -1,4 +1,19 @@ -import type { BushCategoryChannel, BushClient, BushGuild, BushGuildMember } from '#lib'; +/* eslint-disable deprecation/deprecation */ +import type { + BushCategoryChannel, + BushClient, + BushDMChannel, + BushGuild, + BushGuildBasedChannel, + BushGuildMember, + BushNewsChannel, + BushStageChannel, + BushTextBasedChannel, + BushTextChannel, + BushThreadChannel, + BushVoiceBasedChannel, + BushVoiceChannel +} from '#lib'; import { StoreChannel, type Collection, type Snowflake } from 'discord.js'; import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; @@ -6,7 +21,6 @@ import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; * Represents a guild store channel on Discord. * @deprecated Store channels are deprecated and will be removed from Discord in March 2022. See [Self-serve Game Selling Deprecation](https://support-dev.discord.com/hc/en-us/articles/4414590563479) for more information */ -// eslint-disable-next-line deprecation/deprecation export class BushStoreChannel extends StoreChannel { public declare guild: BushGuild; public declare readonly members: Collection<Snowflake, BushGuildMember>; @@ -16,3 +30,16 @@ export class BushStoreChannel extends StoreChannel { super(guild, data, client); } } + +export interface BushStoreChannel extends StoreChannel { + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; + isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/BushTextChannel.ts b/src/lib/extensions/discord.js/BushTextChannel.ts index 45e1200..15be7bd 100644 --- a/src/lib/extensions/discord.js/BushTextChannel.ts +++ b/src/lib/extensions/discord.js/BushTextChannel.ts @@ -1,4 +1,19 @@ -import type { BushGuild, BushMessageManager, BushThreadManager } from '#lib'; +/* eslint-disable deprecation/deprecation */ +import type { + BushCategoryChannel, + BushDMChannel, + BushGuild, + BushGuildBasedChannel, + BushMessageManager, + BushNewsChannel, + BushStageChannel, + BushStoreChannel, + BushTextBasedChannel, + BushThreadChannel, + BushThreadManager, + BushVoiceBasedChannel, + BushVoiceChannel +} from '#lib'; import { TextChannel, type AllowedThreadTypeForTextChannel } from 'discord.js'; import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; @@ -14,3 +29,16 @@ export class BushTextChannel extends TextChannel { super(guild, data); } } + +export interface BushTextChannel extends TextChannel { + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; + isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/BushThreadChannel.ts b/src/lib/extensions/discord.js/BushThreadChannel.ts index 3c8859c..a342dd7 100644 --- a/src/lib/extensions/discord.js/BushThreadChannel.ts +++ b/src/lib/extensions/discord.js/BushThreadChannel.ts @@ -1,13 +1,20 @@ +/* eslint-disable deprecation/deprecation */ import type { - BushBaseGuildVoiceChannel, + BushCategoryChannel, BushClient, + BushDMChannel, BushGuild, + BushGuildBasedChannel, BushGuildMember, BushMessageManager, BushNewsChannel, + BushStageChannel, + BushStoreChannel, BushTextBasedChannel, BushTextChannel, - BushThreadMemberManager + BushThreadMemberManager, + BushVoiceBasedChannel, + BushVoiceChannel } from '#lib'; import { ThreadChannel, type Collection, type Snowflake } from 'discord.js'; import type { RawThreadChannelData } from 'discord.js/typings/rawDataTypes'; @@ -29,7 +36,14 @@ export class BushThreadChannel extends ThreadChannel { } export interface BushThreadChannel extends ThreadChannel { - isText(): this is BushTextBasedChannel; - isVoice(): this is BushBaseGuildVoiceChannel; + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; } diff --git a/src/lib/extensions/discord.js/BushThreadManager.d.ts b/src/lib/extensions/discord.js/BushThreadManager.ts index 6b3340d..b84b98d 100644 --- a/src/lib/extensions/discord.js/BushThreadManager.d.ts +++ b/src/lib/extensions/discord.js/BushThreadManager.ts @@ -5,6 +5,7 @@ import { NewsChannel, TextChannel, ThreadChannel, + ThreadManager, type BaseFetchOptions, type FetchArchivedThreadOptions, type FetchThreadsOptions, @@ -17,7 +18,10 @@ import type { RawThreadChannelData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for {@link BushThreadChannel} objects and stores their cache. */ -export class BushThreadManager<AllowedThreadType> extends CachedManager<Snowflake, BushThreadChannel, ThreadChannelResolvable> { +export declare class BushThreadManager<AllowedThreadType> + extends CachedManager<Snowflake, BushThreadChannel, ThreadChannelResolvable> + implements ThreadManager<AllowedThreadType> +{ public constructor(channel: TextChannel | NewsChannel, iterable?: Iterable<RawThreadChannelData>); /** @@ -44,7 +48,7 @@ export class BushThreadManager<AllowedThreadType> extends CachedManager<Snowflak * .create({ * name: 'mod-talk', * autoArchiveDuration: 60, - * type: 'GUILD_PRIVATE_THREAD', + * type: 'GuildPrivateThread', * reason: 'Needed a separate thread for moderation', * }) * .then(threadChannel => console.log(threadChannel)) diff --git a/src/lib/extensions/discord.js/BushThreadMemberManager.d.ts b/src/lib/extensions/discord.js/BushThreadMemberManager.ts index dedf102..d597673 100644 --- a/src/lib/extensions/discord.js/BushThreadMemberManager.d.ts +++ b/src/lib/extensions/discord.js/BushThreadMemberManager.ts @@ -1,11 +1,21 @@ -import type { BushClient, BushThreadChannel, BushThreadMember, BushThreadMemberResolvable } from '#lib'; -import { CachedManager, type BaseFetchOptions, type Collection, type Snowflake, type UserResolvable } from 'discord.js'; +import type { BushClient, BushThreadChannel, BushThreadMember, BushThreadMemberResolvable, BushUserResolvable } from '#lib'; +import { + CachedManager, + ThreadMemberManager, + type BaseFetchOptions, + type Collection, + type Snowflake, + type UserResolvable +} from 'discord.js'; import type { RawThreadMemberData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for GuildMembers and stores their cache. */ -export class BushThreadMemberManager extends CachedManager<Snowflake, BushThreadMember, BushThreadMemberResolvable> { +export declare class BushThreadMemberManager + extends CachedManager<Snowflake, BushThreadMember, BushThreadMemberResolvable> + implements ThreadMemberManager +{ public constructor(thread: BushThreadChannel, iterable?: Iterable<RawThreadMemberData>); public declare readonly client: BushClient; @@ -23,15 +33,10 @@ export class BushThreadMemberManager extends CachedManager<Snowflake, BushThread /** * Fetches member(s) for the thread from Discord, requires access to the `GUILD_MEMBERS` gateway intent. - * @param member The member to fetch. If `undefined`, all members in the thread are fetched, and will be - * cached based on `options.cache`. If boolean, this serves the purpose of `options.cache`. - * @param options Additional options for this fetch - */ - public fetch(member?: UserResolvable, options?: BaseFetchOptions): Promise<BushThreadMember>; - - /** - * @deprecated Use `fetch(member, options)` instead. + * @param options Additional options for this fetch, when a `boolean` is provided + * all members are fetched with `options.cache` set to the boolean value */ + public fetch(options?: BushThreadMemberFetchOptions): Promise<BushThreadMember>; public fetch(cache?: boolean): Promise<Collection<Snowflake, BushThreadMember>>; /** @@ -41,3 +46,10 @@ export class BushThreadMemberManager extends CachedManager<Snowflake, BushThread */ public remove(id: Snowflake | '@me', reason?: string): Promise<Snowflake>; } + +export interface BushThreadMemberFetchOptions extends BaseFetchOptions { + /** + * The specific user to fetch from the thread + */ + member?: BushUserResolvable; +} diff --git a/src/lib/extensions/discord.js/BushUserManager.d.ts b/src/lib/extensions/discord.js/BushUserManager.ts index 5d814da..ae28f1d 100644 --- a/src/lib/extensions/discord.js/BushUserManager.d.ts +++ b/src/lib/extensions/discord.js/BushUserManager.ts @@ -5,6 +5,7 @@ import { MessageOptions, MessagePayload, UserFlags, + UserManager, type BaseFetchOptions, type Snowflake } from 'discord.js'; @@ -13,7 +14,7 @@ import type { RawUserData } from 'discord.js/typings/rawDataTypes'; /** * Manages API methods for users and stores their cache. */ -export class BushUserManager extends CachedManager<Snowflake, BushUser, BushUserResolvable> { +export declare class BushUserManager extends CachedManager<Snowflake, BushUser, BushUserResolvable> implements UserManager { private constructor(client: BushClient, iterable?: Iterable<RawUserData>); /** @@ -24,14 +25,14 @@ export class BushUserManager extends CachedManager<Snowflake, BushUser, BushUser public dmChannel(userId: Snowflake): BushDMChannel | null; /** - * Creates a {@link DMChannel} between the client and a user. + * Creates a {@link BushDMChannel} between the client and a user. * @param user The UserResolvable to identify * @param options Additional options for this fetch */ public createDM(user: BushUserResolvable, options?: BaseFetchOptions): Promise<BushDMChannel>; /** - * Deletes a {@link DMChannel} (if one exists) between the client and a user. Resolves with the channel if successful. + * Deletes a {@link BushDMChannel} (if one exists) between the client and a user. Resolves with the channel if successful. * @param user The UserResolvable to identify */ public deleteDM(user: BushUserResolvable): Promise<BushDMChannel>; diff --git a/src/lib/extensions/discord.js/BushVoiceChannel.ts b/src/lib/extensions/discord.js/BushVoiceChannel.ts index 9f246e5..a0ee47d 100644 --- a/src/lib/extensions/discord.js/BushVoiceChannel.ts +++ b/src/lib/extensions/discord.js/BushVoiceChannel.ts @@ -1,4 +1,19 @@ -import type { BushClient, BushGuild, BushGuildMember } from '#lib'; +/* eslint-disable deprecation/deprecation */ +import type { + BushCategoryChannel, + BushClient, + BushDMChannel, + BushGuild, + BushGuildBasedChannel, + BushGuildMember, + BushNewsChannel, + BushStageChannel, + BushStoreChannel, + BushTextBasedChannel, + BushTextChannel, + BushThreadChannel, + BushVoiceBasedChannel +} from '#lib'; import { VoiceChannel, type Collection, type Snowflake } from 'discord.js'; import type { RawGuildChannelData } from 'discord.js/typings/rawDataTypes'; @@ -13,3 +28,16 @@ export class BushVoiceChannel extends VoiceChannel { super(guild, data); } } + +export interface BushVoiceChannel extends VoiceChannel { + isText(): this is BushTextChannel; + isDM(): this is BushDMChannel; + isVoice(): this is BushVoiceChannel; + isCategory(): this is BushCategoryChannel; + isNews(): this is BushNewsChannel; + isStore(): this is BushStoreChannel; + isThread(): this is BushThreadChannel; + isStage(): this is BushStageChannel; + isTextBased(): this is BushGuildBasedChannel & BushTextBasedChannel; + isVoiceBased(): this is BushVoiceBasedChannel; +} diff --git a/src/lib/extensions/discord.js/other.ts b/src/lib/extensions/discord.js/other.ts index f81e01c..784442d 100644 --- a/src/lib/extensions/discord.js/other.ts +++ b/src/lib/extensions/discord.js/other.ts @@ -1,3 +1,4 @@ +/* eslint-disable deprecation/deprecation */ import type { BushApplicationCommand, BushCategoryChannel, @@ -15,10 +16,10 @@ import type { BushThreadChannel, BushThreadMember, BushUser, - BushVoiceChannel + BushVoiceChannel, + PartialBushDMChannel } from '#lib'; -import type { Collection, EnumValueMapped, Message, PartialDMChannel, Snowflake } from 'discord.js'; -import type { ChannelTypes } from 'discord.js/typings/enums'; +import type { ChannelType, Collection, Message, Snowflake } from 'discord.js'; /** * Data that resolves to give a ThreadMember object. @@ -86,10 +87,9 @@ export type BushGuildChannelResolvable = Snowflake | BushGuildBasedChannel; export type BushAnyChannel = | BushCategoryChannel | BushDMChannel - | PartialDMChannel + | PartialBushDMChannel | BushNewsChannel | BushStageChannel - // eslint-disable-next-line deprecation/deprecation | BushStoreChannel | BushTextChannel | BushThreadChannel @@ -98,7 +98,7 @@ export type BushAnyChannel = /** * The channels that are text-based. */ -export type BushTextBasedChannel = PartialDMChannel | BushThreadChannel | BushDMChannel | BushNewsChannel | BushTextChannel; +export type BushTextBasedChannel = PartialBushDMChannel | BushThreadChannel | BushDMChannel | BushNewsChannel | BushTextChannel; /** * The types of channels that are text-based. @@ -123,25 +123,17 @@ export type BushTextChannelResolvable = Snowflake | BushTextChannel; */ export type BushGuildVoiceChannelResolvable = BushVoiceBasedChannel | Snowflake; -export type BushMappedChannelCategoryTypes = EnumValueMapped< - typeof ChannelTypes, - { - GUILD_NEWS: BushNewsChannel; - GUILD_VOICE: BushVoiceChannel; - GUILD_TEXT: BushTextChannel; - // eslint-disable-next-line deprecation/deprecation - GUILD_STORE: BushStoreChannel; - GUILD_STAGE_VOICE: BushStageChannel; - } ->; - -export type BushMappedGuildChannelTypes = EnumValueMapped< - typeof ChannelTypes, - { - GUILD_CATEGORY: BushCategoryChannel; - } -> & - BushMappedChannelCategoryTypes; +export interface BushMappedChannelCategoryTypes { + [ChannelType.GuildNews]: BushNewsChannel; + [ChannelType.GuildVoice]: BushVoiceChannel; + [ChannelType.GuildText]: BushTextChannel; + [ChannelType.GuildStore]: BushStoreChannel; + [ChannelType.GuildStageVoice]: BushStageChannel; +} + +export type BushMappedGuildChannelTypes = { + [ChannelType.GuildCategory]: BushCategoryChannel; +} & BushMappedChannelCategoryTypes; /** * The data returned from a thread fetch that returns multiple threads. @@ -157,3 +149,15 @@ export interface BushFetchedThreads { */ hasMore?: boolean; } + +// for reverse key mapping + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-type + */ +export enum BushInteractionType { + Ping = 1, + ApplicationCommand = 2, + MessageComponent = 3, + ApplicationCommandAutocomplete = 4 +} diff --git a/src/lib/extensions/global.d.ts b/src/lib/extensions/global.ts index a6f2b5a..a6f2b5a 100644 --- a/src/lib/extensions/global.d.ts +++ b/src/lib/extensions/global.ts diff --git a/src/lib/index.ts b/src/lib/index.ts index 37bc443..79bc553 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -30,9 +30,9 @@ export * from './extensions/discord.js/BushButtonInteraction.js'; export * from './extensions/discord.js/BushCategoryChannel.js'; export type { BushChannel } from './extensions/discord.js/BushChannel.js'; export type { BushChannelManager } from './extensions/discord.js/BushChannelManager.js'; +export * from './extensions/discord.js/BushChatInputCommandInteraction.js'; export type { BushClientEvents } from './extensions/discord.js/BushClientEvents.js'; export type { BushClientUser } from './extensions/discord.js/BushClientUser.js'; -export * from './extensions/discord.js/BushCommandInteraction.js'; export * from './extensions/discord.js/BushDMChannel.js'; export * from './extensions/discord.js/BushEmoji.js'; export * from './extensions/discord.js/BushGuild.js'; diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts index 34f6747..fd90dbf 100644 --- a/src/lib/models/Guild.ts +++ b/src/lib/models/Guild.ts @@ -1,5 +1,4 @@ -import { ExcludeEnum, type Snowflake } from 'discord.js'; -import { ChannelTypes } from 'discord.js/typings/enums'; +import { ChannelType, type Snowflake } from 'discord.js'; import { type Sequelize } from 'sequelize'; import { BadWordDetails } from '../common/AutoMod.js'; import { type BushClient } from '../extensions/discord-akairo/BushClient.js'; @@ -183,7 +182,7 @@ export interface GuildSetting { name: string; description: string; type: GuildSettingType; - subType: ExcludeEnum<typeof ChannelTypes, 'UNKNOWN'>[] | undefined; + subType: (keyof typeof ChannelType)[] | undefined; configurable: boolean; } const asGuildSetting = <T>(et: { [K in keyof T]: GuildSetting }) => et; @@ -200,14 +199,14 @@ export const guildSettingsObj = asGuildSetting({ name: 'Auto Publish Channels', description: 'Channels were every message is automatically published.', type: 'channel-array', - subType: ['GUILD_NEWS'], + subType: ['GuildNews'], configurable: true }, welcomeChannel: { name: 'Welcome Channel', description: 'The channel where the bot will send join and leave message.', type: 'channel', - subType: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + subType: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], configurable: true }, muteRole: { @@ -228,7 +227,7 @@ export const guildSettingsObj = asGuildSetting({ name: 'Lockdown Channels', description: 'Channels that are locked down when a mass lockdown is specified.', type: 'channel-array', - subType: ['GUILD_TEXT'], + subType: ['GuildText'], configurable: true }, joinRoles: { @@ -249,7 +248,7 @@ export const guildSettingsObj = asGuildSetting({ name: 'Log Channels', description: 'The channel were logs are sent.', type: 'custom', - subType: ['GUILD_TEXT'], + subType: ['GuildText'], configurable: false }, autoModPhases: { @@ -263,7 +262,7 @@ export const guildSettingsObj = asGuildSetting({ name: 'No Xp Channels', description: 'Channels where users will not earn xp for leveling.', type: 'channel-array', - subType: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + subType: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], configurable: true }, levelRoles: { @@ -277,7 +276,7 @@ export const guildSettingsObj = asGuildSetting({ name: 'Level Up Channel', description: 'The channel to send level up messages in instead of last channel.', type: 'channel', - subType: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD'], + subType: ['GuildText', 'GuildNews', 'GuildNewsThread', 'GuildPublicThread', 'GuildPrivateThread'], configurable: true } }); diff --git a/src/lib/utils/AllowedMentions.ts b/src/lib/utils/AllowedMentions.ts index b4b188d..c0c76ee 100644 --- a/src/lib/utils/AllowedMentions.ts +++ b/src/lib/utils/AllowedMentions.ts @@ -7,31 +7,37 @@ export class AllowedMentions { public static none(): MessageMentionOptions { return { parse: [] }; } + public static all(): MessageMentionOptions { return { parse: ['everyone', 'roles', 'users'] }; } + public static users(): MessageMentionOptions { return { parse: ['users'] }; } + public static everyone(): MessageMentionOptions { return { parse: ['everyone'] }; } + public static roles(): MessageMentionOptions { return { parse: ['roles'] }; } + public constructor(users = true, roles = false, everyone = false) { this.everyone = everyone; this.roles = roles; this.users = users; } + public toObject(): MessageMentionOptions { return { parse: [ diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts index 306f580..e8366a1 100644 --- a/src/lib/utils/BushConstants.ts +++ b/src/lib/utils/BushConstants.ts @@ -85,7 +85,7 @@ export class BushConstants { } as const); public static regex = BushClientUtil.deepFreeze({ - snowflake: /\d{15,21}/im, + snowflake: /^\d{15,21}$/im, discordEmoji: /<a?:(?<name>[a-zA-Z0-9_]+):(?<id>\d{15,21})>/im, //stolen from geek @@ -222,49 +222,48 @@ export class BushConstants { }, otherEmojis: { - SERVER_BOOSTER_1: '<:serverBooster1:848740052091142145>', - SERVER_BOOSTER_2: '<:serverBooster2:848740090506510388>', - SERVER_BOOSTER_3: '<:serverBooster3:848740124992077835>', - SERVER_BOOSTER_6: '<:serverBooster6:848740155245461514>', - SERVER_BOOSTER_9: '<:serverBooster9:848740188846030889>', - SERVER_BOOSTER_12: '<:serverBooster12:848740304365551668>', - SERVER_BOOSTER_15: '<:serverBooster15:848740354890137680>', - SERVER_BOOSTER_18: '<:serverBooster18:848740402886606868>', - SERVER_BOOSTER_24: '<:serverBooster24:848740444628320256>', - NITRO: '<:nitro:848740498054971432>', - BOOSTER: '<:booster:848747775020892200>', - OWNER: '<:owner:848746439311753286>', - ADMIN: '<:admin:848963914628333598>', - SUPERUSER: '<:superUser:848947986326224926>', - DEVELOPER: '<:developer:848954538111139871>', - BUSH_VERIFIED: '<:verfied:853360152090771497>', - BOOST_TIER_1: '<:boostitle:853363736679940127>', - BOOST_TIER_2: '<:boostitle:853363752728789075>', - BOOST_TIER_3: '<:boostitle:853363769132056627>', - GUILD_TEXT: '<:text:853375537791893524>', - GUILD_NEWS: '<:announcements:853375553531674644>', - GUILD_VOICE: '<:voice:853375566735212584>', - GUILD_STAGE_VOICE: '<:stage:853375583521210468>', - GUILD_STORE: '<:store:853375601175691266>', - GUILD_CATEGORY: '<:category:853375615260819476>', - THREAD: '<:thread:865033845753249813>' + ServerBooster1: '<:serverBooster1:848740052091142145>', + ServerBooster2: '<:serverBooster2:848740090506510388>', + ServerBooster3: '<:serverBooster3:848740124992077835>', + ServerBooster6: '<:serverBooster6:848740155245461514>', + ServerBooster9: '<:serverBooster9:848740188846030889>', + ServerBooster12: '<:serverBooster12:848740304365551668>', + ServerBooster15: '<:serverBooster15:848740354890137680>', + ServerBooster18: '<:serverBooster18:848740402886606868>', + ServerBooster24: '<:serverBooster24:848740444628320256>', + Nitro: '<:nitro:848740498054971432>', + Booster: '<:booster:848747775020892200>', + Owner: '<:owner:848746439311753286>', + Admin: '<:admin:848963914628333598>', + Superuser: '<:superUser:848947986326224926>', + Developer: '<:developer:848954538111139871>', + BushVerified: '<:verfied:853360152090771497>', + BoostTier1: '<:boostitle:853363736679940127>', + BoostTier2: '<:boostitle:853363752728789075>', + BoostTier3: '<:boostitle:853363769132056627>', + ChannelText: '<:text:853375537791893524>', + ChannelNews: '<:announcements:853375553531674644>', + ChannelVoice: '<:voice:853375566735212584>', + ChannelStage: '<:stage:853375583521210468>', + ChannelStore: '<:store:853375601175691266>', + ChannelCategory: '<:category:853375615260819476>', + ChannelThread: '<:thread:865033845753249813>' }, userFlags: { - DISCORD_EMPLOYEE: '<:discordEmployee:848742947826434079>', - PARTNERED_SERVER_OWNER: '<:partneredServerOwner:848743051593777152>', - HYPESQUAD_EVENTS: '<:hypeSquadEvents:848743108283072553>', - BUGHUNTER_LEVEL_1: '<:bugHunter:848743239850393640>', - HOUSE_BRAVERY: '<:hypeSquadBravery:848742910563844127>', - HOUSE_BRILLIANCE: '<:hypeSquadBrilliance:848742840649646101>', - HOUSE_BALANCE: '<:hypeSquadBalance:848742877537370133>', - EARLY_SUPPORTER: '<:earlySupporter:848741030102171648>', - TEAM_USER: 'TEAM_USER', - SYSTEM: 'SYSTEM', - BUGHUNTER_LEVEL_2: '<:bugHunterGold:848743283080822794>', + STAFF: '<:discordEmployee:848742947826434079>', + PARTNER: '<:partneredServerOwner:848743051593777152>', + HYPESQUAD: '<:hypeSquadEvents:848743108283072553>', + BUG_HUNTER_LEVEL_1: '<:bugHunter:848743239850393640>', + HYPESQUAD_ONLINE_HOUSE_1: '<:hypeSquadBravery:848742910563844127>', + HYPESQUAD_ONLINE_HOUSE_2: '<:hypeSquadBrilliance:848742840649646101>', + HYPESQUAD_ONLINE_HOUSE_3: '<:hypeSquadBalance:848742877537370133>', + PREMIUM_EARLY_SUPPORTER: '<:earlySupporter:848741030102171648>', + TEAM_PSEUDO_USER: 'TEAM_PSEUDO_USER', + BUG_HUNTER_LEVEL_2: '<:bugHunterGold:848743283080822794>', VERIFIED_BOT: 'VERIFIED_BOT', - EARLY_VERIFIED_BOT_DEVELOPER: '<:earlyVerifiedBotDeveloper:848741079875846174>', - DISCORD_CERTIFIED_MODERATOR: '<:discordCertifiedModerator:877224285901582366>', + VERIFIED_DEVELOPER: '<:earlyVerifiedBotDeveloper:848741079875846174>', + CERTIFIED_MODERATOR: '<:discordCertifiedModerator:877224285901582366>', BOT_HTTP_INTERACTIONS: 'BOT_HTTP_INTERACTIONS' }, @@ -365,8 +364,7 @@ export class BushConstants { 'Giveaway (25m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], 'Giveaway (10m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], 'Giveaway (5m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], - 'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], - 'DJ': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'] + 'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'] } } as const); diff --git a/src/listeners/bush/joinAutoBan.ts b/src/listeners/bush/joinAutoBan.ts index 031c989..421e708 100644 --- a/src/listeners/bush/joinAutoBan.ts +++ b/src/listeners/bush/joinAutoBan.ts @@ -40,7 +40,7 @@ export default class JoinAutoBanListener extends BushListener { color: client.consts.colors.red, author: { name: member.user.tag, - iconURL: member.displayAvatarURL({ dynamic: true }) + iconURL: member.displayAvatarURL() } } ] diff --git a/src/listeners/bush/userUpdateAutoBan.ts b/src/listeners/bush/userUpdateAutoBan.ts index c829cc3..67d9f5c 100644 --- a/src/listeners/bush/userUpdateAutoBan.ts +++ b/src/listeners/bush/userUpdateAutoBan.ts @@ -46,7 +46,7 @@ export default class UserUpdateAutoBanListener extends BushListener { color: client.consts.colors.red, author: { name: member.user.tag, - iconURL: member.displayAvatarURL({ dynamic: true }) + iconURL: member.displayAvatarURL() } } ] diff --git a/src/listeners/client/interactionCreate.ts b/src/listeners/client/interactionCreate.ts index 7eb2f10..6543d03 100644 --- a/src/listeners/client/interactionCreate.ts +++ b/src/listeners/client/interactionCreate.ts @@ -1,4 +1,4 @@ -import { AutoMod, BushListener, type BushButtonInteraction, type BushClientEvents } from '#lib'; +import { AutoMod, BushInteractionType, BushListener, type BushButtonInteraction, type BushClientEvents } from '#lib'; export default class InteractionCreateListener extends BushListener { public constructor() { @@ -13,9 +13,7 @@ export default class InteractionCreateListener extends BushListener { if (!interaction) return; void client.console.verbose( 'interactionVerbose', - `An interaction of type <<${interaction.type.toLowerCase().replaceAll('_', '')}>> was received from <<${ - interaction.user.tag - }>>.` + `An interaction of type <<${BushInteractionType[interaction.type]}>> was received from <<${interaction.user.tag}>>.` ); if (interaction.isCommand()) { return; diff --git a/src/listeners/client/rateLimit.ts b/src/listeners/client/rateLimit.ts new file mode 100644 index 0000000..26eaf18 --- /dev/null +++ b/src/listeners/client/rateLimit.ts @@ -0,0 +1,15 @@ +import { BushListener, type BushClientEvents } from '#lib'; + +export default class RateLimitListener extends BushListener { + public constructor() { + super('rateLimit', { + emitter: 'client', + event: 'rateLimit', + category: 'client' + }); + } + + public override async exec(...[message]: BushClientEvents['rateLimit']): Promise<void> { + void client.console.superVerboseRaw('rateLimit', message); + } +} diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts index ac81bae..44d20a4 100644 --- a/src/listeners/commands/commandError.ts +++ b/src/listeners/commands/commandError.ts @@ -1,7 +1,7 @@ import { type BushCommandHandlerEvents } from '#lib'; import { Severity } from '@sentry/types'; import { type AkairoMessage, type Command } from 'discord-akairo'; -import { Formatters, GuildTextBasedChannel, MessageEmbed, type DMChannel, type Message } from 'discord.js'; +import { Formatters, GuildTextBasedChannel, MessageEmbed, type Message } from 'discord.js'; import { BushListener } from '../../lib/extensions/discord-akairo/BushListener.js'; export default class CommandErrorListener extends BushListener { @@ -21,10 +21,7 @@ export default class CommandErrorListener extends BushListener { ) { const isSlash = message.util.isSlash; const errorNum = Math.floor(Math.random() * 6969696969) + 69; // hehe funny number - const channel = - message.channel?.type === 'DM' - ? (message.channel as DMChannel)?.recipient.tag - : (message.channel as GuildTextBasedChannel)?.name; + const channel = message.channel?.isDM() ? message.channel?.recipient.tag : (<GuildTextBasedChannel>message.channel)?.name; const command = _command ?? message.util.parsed?.command; client.sentry.captureException(error, { @@ -35,10 +32,7 @@ export default class CommandErrorListener extends BushListener { 'message.id': message.id, 'message.type': message.util.isSlash ? 'slash' : 'normal', 'message.parsed.content': message.util.parsed?.content, - 'channel.id': - message.channel?.type === 'DM' - ? (message.channel as DMChannel)?.recipient.id - : (message.channel as GuildTextBasedChannel)?.id, + 'channel.id': message.channel?.isDM() ? message.channel?.recipient.id : (<GuildTextBasedChannel>message.channel)?.id, 'channel.name': channel, 'guild.id': message.guild?.id, 'guild.name': message.guild?.name, diff --git a/src/listeners/commands/commandMissingPermissions.ts b/src/listeners/commands/commandMissingPermissions.ts index 596a73f..4d9aa1b 100644 --- a/src/listeners/commands/commandMissingPermissions.ts +++ b/src/listeners/commands/commandMissingPermissions.ts @@ -18,7 +18,7 @@ export default class CommandMissingPermissionsListener extends BushListener { | BushCommandHandlerEvents['missingPermissions'] | BushCommandHandlerEvents['slashMissingPermissions'] ) { - const niceMissing = (missing.includes('ADMINISTRATOR') ? (['ADMINISTRATOR'] as 'ADMINISTRATOR'[]) : missing).map( + const niceMissing = (missing.includes('ADMINISTRATOR') ? (['ADMINISTRATOR'] as const) : missing).map( (perm) => client.consts.mappings.permissions[perm]?.name ?? missing ); diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts index 76974c8..4917402 100644 --- a/src/listeners/commands/commandStarted.ts +++ b/src/listeners/commands/commandStarted.ts @@ -1,6 +1,6 @@ import { BushListener, type BushCommandHandlerEvents } from '#lib'; import { Severity } from '@sentry/types'; -import { GuildTextBasedChannel, type DMChannel } from 'discord.js'; +import { ChannelType, GuildTextBasedChannel } from 'discord.js'; export default class CommandStartedListener extends BushListener { public constructor() { @@ -21,14 +21,8 @@ export default class CommandStartedListener extends BushListener { 'message.id': message.id, 'message.type': message.util.isSlash ? 'slash' : 'normal', 'message.parsed.content': message.util.parsed!.content, - 'channel.id': - message.channel!.type === 'DM' - ? (message.channel as DMChannel)!.recipient.id - : (message.channel as GuildTextBasedChannel)!.id, - 'channel.name': - message.channel!.type === 'DM' - ? (message.channel as DMChannel)!.recipient.tag - : (message.channel as GuildTextBasedChannel)!.name, + 'channel.id': message.channel.isDM() ? message.channel!.recipient.id : (<GuildTextBasedChannel>message.channel)?.id, + 'channel.name': message.channel.isDM() ? message.channel.recipient.tag : (<GuildTextBasedChannel>message.channel)?.name, 'guild.id': message.guild?.id, 'guild.name': message.guild?.name, 'environment': client.config.environment @@ -38,7 +32,7 @@ export default class CommandStartedListener extends BushListener { void client.logger.info( 'commandStarted', `The <<${command.id}>> command was used by <<${message.author.tag}>> in ${ - message.channel.type === 'DM' ? `their <<DMs>>` : `<<#${message.channel.name}>> in <<${message.guild?.name}>>` + message.channel.type === ChannelType.DM ? `their <<DMs>>` : `<<#${message.channel.name}>> in <<${message.guild?.name}>>` }.`, true ); diff --git a/src/listeners/commands/slashCommandError.ts b/src/listeners/commands/slashCommandError.ts index 5694391..25c0f3e 100644 --- a/src/listeners/commands/slashCommandError.ts +++ b/src/listeners/commands/slashCommandError.ts @@ -9,6 +9,7 @@ export default class SlashCommandErrorListener extends BushListener { category: 'commands' }); } + public override async exec(...[error, message, command]: BushCommandHandlerEvents['slashError']) { return await CommandErrorListener.handleError(error, message, command); } diff --git a/src/listeners/commands/slashStarted.ts b/src/listeners/commands/slashStarted.ts index d742a75..0084dc6 100644 --- a/src/listeners/commands/slashStarted.ts +++ b/src/listeners/commands/slashStarted.ts @@ -1,4 +1,5 @@ import { BushListener, type BushCommandHandlerEvents } from '#lib'; +import { ChannelType } from 'discord.js'; export default class SlashStartedListener extends BushListener { public constructor() { @@ -8,12 +9,13 @@ export default class SlashStartedListener extends BushListener { category: 'commands' }); } + public override async exec(...[message, command]: BushCommandHandlerEvents['slashStarted']) { return void client.logger.info( 'slashStarted', `The <<${command.id}>> command was used by <<${message.author.tag}>> in ${ message.channel - ? message.channel.type === 'DM' + ? message.channel.type === ChannelType.DM ? `their <<DMs>>` : `<<#${message.channel.name}>> in <<${message.guild?.name}>>` : 'unknown' diff --git a/src/listeners/member-custom/bushBan.ts b/src/listeners/member-custom/bushBan.ts index c37d872..dfa3292 100644 --- a/src/listeners/member-custom/bushBan.ts +++ b/src/listeners/member-custom/bushBan.ts @@ -19,7 +19,7 @@ export default class BushBanListener extends BushListener { .setColor(util.colors.discord.RED) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${duration ? 'Temp Ban' : 'Perm Ban'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushBlock.ts b/src/listeners/member-custom/bushBlock.ts index 13523da..6151f9d 100644 --- a/src/listeners/member-custom/bushBlock.ts +++ b/src/listeners/member-custom/bushBlock.ts @@ -21,7 +21,7 @@ export default class BushBlockListener extends BushListener { .setColor(util.colors.discord.PURPLE) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${duration ? 'Temp Block' : 'Perm Block'}`) .addField('**Channel**', `<#${channel.id}>`) .addField('**User**', `${user} (${user.tag})`) diff --git a/src/listeners/member-custom/bushKick.ts b/src/listeners/member-custom/bushKick.ts index 52b4ff2..0e1d305 100644 --- a/src/listeners/member-custom/bushKick.ts +++ b/src/listeners/member-custom/bushKick.ts @@ -19,7 +19,7 @@ export default class BushKickListener extends BushListener { .setColor(util.colors.discord.RED) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Kick'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushMute.ts b/src/listeners/member-custom/bushMute.ts index 844ae55..53542a5 100644 --- a/src/listeners/member-custom/bushMute.ts +++ b/src/listeners/member-custom/bushMute.ts @@ -19,7 +19,7 @@ export default class BushMuteListener extends BushListener { .setColor(util.colors.discord.ORANGE) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${duration ? 'Temp Mute' : 'Perm Mute'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushPunishRole.ts b/src/listeners/member-custom/bushPunishRole.ts index 9abac3c..0a066d9 100644 --- a/src/listeners/member-custom/bushPunishRole.ts +++ b/src/listeners/member-custom/bushPunishRole.ts @@ -19,7 +19,7 @@ export default class BushPunishRoleListener extends BushListener { .setColor(util.colors.discord.YELLOW) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${duration ? 'Temp Punishment Role' : 'Perm Punishment Role'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushPunishRoleRemove.ts b/src/listeners/member-custom/bushPunishRoleRemove.ts index a24546e..fe81d19 100644 --- a/src/listeners/member-custom/bushPunishRoleRemove.ts +++ b/src/listeners/member-custom/bushPunishRoleRemove.ts @@ -19,7 +19,7 @@ export default class BushPunishRoleRemoveListener extends BushListener { .setColor(util.colors.discord.GREEN) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Remove Punishment Role'}`) .addField('**Role**', `${role}`) .addField('**User**', `${user} (${user.tag})`) diff --git a/src/listeners/member-custom/bushPurge.ts b/src/listeners/member-custom/bushPurge.ts index 8a1e0c5..355569b 100644 --- a/src/listeners/member-custom/bushPurge.ts +++ b/src/listeners/member-custom/bushPurge.ts @@ -27,7 +27,7 @@ export default class BushPurgeListener extends BushListener { .setColor(util.colors.discord.DARK_PURPLE) .setTimestamp() .setFooter({ text: `${messages.size.toLocaleString()} Messages` }) - .setAuthor({ name: moderator.tag, iconURL: moderator.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: moderator.tag, iconURL: moderator.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Purge'}`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) .addField('**Channel**', `<#${channel.id}> (${channel.name})`) diff --git a/src/listeners/member-custom/bushRemoveTimeout.ts b/src/listeners/member-custom/bushRemoveTimeout.ts index 0f41039..af56dac 100644 --- a/src/listeners/member-custom/bushRemoveTimeout.ts +++ b/src/listeners/member-custom/bushRemoveTimeout.ts @@ -19,7 +19,7 @@ export default class BushRemoveTimeoutListener extends BushListener { .setColor(util.colors.discord.GREEN) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Remove Timeout'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushTimeout.ts b/src/listeners/member-custom/bushTimeout.ts index a311710..0ec76bf 100644 --- a/src/listeners/member-custom/bushTimeout.ts +++ b/src/listeners/member-custom/bushTimeout.ts @@ -21,7 +21,7 @@ export default class BushTimeoutListener extends BushListener { .setColor(util.colors.discord.ORANGE) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Timeout'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushUnban.ts b/src/listeners/member-custom/bushUnban.ts index b2426e3..7f3f812 100644 --- a/src/listeners/member-custom/bushUnban.ts +++ b/src/listeners/member-custom/bushUnban.ts @@ -19,7 +19,7 @@ export default class BushUnbanListener extends BushListener { .setColor(util.colors.discord.GREEN) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Unban'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushUnblock.ts b/src/listeners/member-custom/bushUnblock.ts index 43097a1..6be1888 100644 --- a/src/listeners/member-custom/bushUnblock.ts +++ b/src/listeners/member-custom/bushUnblock.ts @@ -19,7 +19,7 @@ export default class BushUnblockListener extends BushListener { .setColor(util.colors.discord.GREEN) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Unblock'}`) .addField('**Channel**', `<#${channel.id}>`) .addField('**User**', `${user} (${user.tag})`) diff --git a/src/listeners/member-custom/bushUnmute.ts b/src/listeners/member-custom/bushUnmute.ts index 89bca46..2ed5104 100644 --- a/src/listeners/member-custom/bushUnmute.ts +++ b/src/listeners/member-custom/bushUnmute.ts @@ -19,7 +19,7 @@ export default class BushUnmuteListener extends BushListener { .setColor(util.colors.discord.GREEN) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Unmute'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/member-custom/bushUpdateModlog.ts b/src/listeners/member-custom/bushUpdateModlog.ts index 46910b9..065ec7e 100644 --- a/src/listeners/member-custom/bushUpdateModlog.ts +++ b/src/listeners/member-custom/bushUpdateModlog.ts @@ -19,7 +19,7 @@ export default class BushUpdateModlogListener extends BushListener { .setTimestamp() .setAuthor({ name: moderator.user.tag, - iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: moderator.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Update Modlog'}`) .addField('**Moderator**', `${moderator} (${moderator.user.tag})`) diff --git a/src/listeners/member-custom/bushUpdateSettings.ts b/src/listeners/member-custom/bushUpdateSettings.ts index 6a9c3d8..49f0aec 100644 --- a/src/listeners/member-custom/bushUpdateSettings.ts +++ b/src/listeners/member-custom/bushUpdateSettings.ts @@ -19,7 +19,7 @@ export default class BushUpdateSettingsListener extends BushListener { if (moderator) logEmbed.setAuthor({ name: moderator.user.tag, - iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: moderator.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }); logEmbed.addField('**Action**', `${'Update Settings'}`); if (moderator) logEmbed.addField('**Moderator**', `${moderator} (${moderator.user.tag})`); diff --git a/src/listeners/member-custom/bushWarn.ts b/src/listeners/member-custom/bushWarn.ts index af8fa62..61ab2e1 100644 --- a/src/listeners/member-custom/bushWarn.ts +++ b/src/listeners/member-custom/bushWarn.ts @@ -19,7 +19,7 @@ export default class BushWarnListener extends BushListener { .setColor(util.colors.discord.YELLOW) .setTimestamp() .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Warn'}`) .addField('**User**', `${user} (${user.tag})`) .addField('**Moderator**', `${moderator} (${moderator.tag})`) diff --git a/src/listeners/message/autoPublisher.ts b/src/listeners/message/autoPublisher.ts index af75ea3..b074fda 100644 --- a/src/listeners/message/autoPublisher.ts +++ b/src/listeners/message/autoPublisher.ts @@ -13,7 +13,7 @@ export default class autoPublisherListener extends BushListener { if (!message.guild || !(await message.guild.hasFeature('autoPublish'))) return; const autoPublishChannels = await message.guild.getSetting('autoPublishChannels'); if (autoPublishChannels) { - if (message.channel.type === 'GUILD_NEWS' && autoPublishChannels.some((x) => message.channel.id.includes(x))) { + if (message.channel.isNews() && autoPublishChannels.some((x) => message.channel.id.includes(x))) { await message .crosspost() .then( diff --git a/src/listeners/message/autoThread.ts b/src/listeners/message/autoThread.ts index 6ee19ed..77ff33c 100644 --- a/src/listeners/message/autoThread.ts +++ b/src/listeners/message/autoThread.ts @@ -1,5 +1,5 @@ import { BushListener, type BushClientEvents, type BushTextChannel } from '#lib'; -import { GuildTextBasedChannel, MessageEmbed } from 'discord.js'; +import { GuildTextBasedChannel, MessageEmbed, MessageType, Permissions } from 'discord.js'; export default class autoThreadListener extends BushListener { public constructor() { @@ -13,7 +13,7 @@ export default class autoThreadListener extends BushListener { public override async exec(...[message]: BushClientEvents['messageCreate']): Promise<Promise<void> | undefined> { if (!client.config.isProduction) return; if (!message.guild || !message.channel) return; - if (!['DEFAULT', 'REPLY'].includes(message.type)) return; + if (![MessageType.Default, MessageType.Reply].includes(message.type)) return; if ( message.author.bot && message.author.id === '444871677176709141' && //fire @@ -35,7 +35,8 @@ export default class autoThreadListener extends BushListener { // todo: make these configurable etc... if (message.guild.id !== '516977525906341928') return; // mb if (message.channel.id !== '714332750156660756') return; // neu-support-1 - if (!(message.channel as BushTextChannel).permissionsFor(message.guild.me!).has('CREATE_PUBLIC_THREADS')) return; + if (!(message.channel as BushTextChannel).permissionsFor(message.guild.me!).has(Permissions.FLAGS.CREATE_PUBLIC_THREADS)) + return; const thread = await message .startThread({ name: `Support - ${message.author.username}#${message.author.discriminator}`, diff --git a/src/listeners/message/blacklistedFile.ts b/src/listeners/message/blacklistedFile.ts index 5b01218..9d52ab0 100644 --- a/src/listeners/message/blacklistedFile.ts +++ b/src/listeners/message/blacklistedFile.ts @@ -1,5 +1,6 @@ import { BushListener, type BushClientEvents } from '#lib'; import * as crypto from 'crypto'; +import { ChannelType } from 'discord.js'; import got from 'got'; export default class BlacklistedFileListener extends BushListener { @@ -131,7 +132,7 @@ export default class BlacklistedFileListener extends BushListener { await message.util.send( `<@!${message.author.id}>, please do not send ${foundFiles.map((f) => f.description).join(' or ')}.` ); - if (message.channel.type === 'DM') return; + if (message.channel.type === ChannelType.DM) return; void client.console.info( 'blacklistedFile', `Deleted <<${foundFiles.map((f) => f.description).join(' and ')}>> sent by <<${message.author.tag}>> in ${ @@ -145,7 +146,7 @@ export default class BlacklistedFileListener extends BushListener { void client.console.warn( 'blacklistedFile', `Failed to delete <<${foundFiles.map((f) => f.description).join(' and ')}>> sent by <<${message.author.tag}>> in <<${ - message.channel.type === 'DM' ? `${message.channel.recipient.tag}'s DMs` : message.channel.name + message.channel.type === ChannelType.DM ? `${message.channel.recipient.tag}'s DMs` : message.channel.name }>>.` ); } diff --git a/src/listeners/message/boosterMessage.ts b/src/listeners/message/boosterMessage.ts index 0ebe393..989f671 100644 --- a/src/listeners/message/boosterMessage.ts +++ b/src/listeners/message/boosterMessage.ts @@ -1,4 +1,5 @@ import { BushListener, type BushClientEvents } from '#lib'; +import { MessageType } from 'discord.js'; export default class BoosterMessageListener extends BushListener { public constructor() { @@ -11,7 +12,7 @@ export default class BoosterMessageListener extends BushListener { public override async exec(...[message]: BushClientEvents['messageCreate']) { if (!message.guild || !(await message.guild?.hasFeature('boosterMessageReact'))) return; - if (message.type === 'USER_PREMIUM_GUILD_SUBSCRIPTION') { + if (message.type === MessageType.UserPremiumGuildSubscription) { return await message.react('<:nitroboost:785160348885975062>').catch(() => { void client.console.warn('boosterMessage', `Failed to react to <<${message.id}>>.`); }); diff --git a/src/listeners/message/directMessage.ts b/src/listeners/message/directMessage.ts index 39d203c..dfc9222 100644 --- a/src/listeners/message/directMessage.ts +++ b/src/listeners/message/directMessage.ts @@ -1,5 +1,5 @@ import { BushListener, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { ChannelType, MessageEmbed } from 'discord.js'; export default class DirectMessageListener extends BushListener { public constructor() { @@ -11,7 +11,7 @@ export default class DirectMessageListener extends BushListener { } public override async exec(...[message]: BushClientEvents['messageCreate']) { - if (message.channel.type === 'DM') { + if (message.channel.type === ChannelType.DM) { if (!(message.author.id == client.user!.id) && message.author.bot) return; if (client.cache.global.blacklistedUsers.includes(message.author.id)) return; const dmLogEmbed = new MessageEmbed().setTimestamp().setFooter({ text: `User ID • ${message.channel.recipient.id}` }); @@ -20,7 +20,7 @@ export default class DirectMessageListener extends BushListener { dmLogEmbed .setAuthor({ name: `From: ${message.author.username}`, - iconURL: `${message.author.displayAvatarURL({ dynamic: true })}` + iconURL: `${message.author.displayAvatarURL()}` }) .setDescription(`**DM:**\n${message}`) .setColor(util.colors.blue); @@ -28,7 +28,7 @@ export default class DirectMessageListener extends BushListener { dmLogEmbed .setAuthor({ name: `To: ${message.channel.recipient.username}`, - iconURL: `${message.channel.recipient.displayAvatarURL({ dynamic: true })}` + iconURL: `${message.channel.recipient.displayAvatarURL()}` }) .setDescription(`**DM:**\n${message}`) .setColor(util.colors.red) diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts index bce4614..c16e811 100644 --- a/src/listeners/message/level.ts +++ b/src/listeners/message/level.ts @@ -1,5 +1,5 @@ import { BushListener, Level, type BushCommandHandlerEvents, type BushGuild, type BushMessage } from '#lib'; -import { type MessageType } from 'discord.js'; +import { MessageType } from 'discord.js'; export default class LevelListener extends BushListener { #levelCooldowns: Set<string> = new Set(); @@ -10,13 +10,13 @@ export default class LevelListener extends BushListener { category: 'message' }); } + public override async exec(...[message]: BushCommandHandlerEvents['messageInvalid']) { if (message.author.bot || !message.author || !message.guild || !message.guildId) return; if (this.#levelCooldowns.has(`${message.guildId}-${message.author.id}`)) return; if ((await message.guild.getSetting('noXpChannels')).includes(message.channel.id)) return; - const allowedMessageTypes: MessageType[] = ['DEFAULT', 'REPLY']; // this is so ts will yell at me when discord.js makes some unnecessary breaking change - if (!allowedMessageTypes.includes(message.type)) return; //checks for join messages, slash commands, booster messages etc + if (message.type !== MessageType.Default && message.type !== MessageType.Reply) return; //checks for join messages, slash commands, booster messages etc const [user] = await Level.findOrBuild({ where: { user: message.author.id, diff --git a/src/listeners/message/verbose.ts b/src/listeners/message/verbose.ts index cf5a698..1225412 100644 --- a/src/listeners/message/verbose.ts +++ b/src/listeners/message/verbose.ts @@ -1,4 +1,5 @@ import { BushListener, type BushClientEvents } from '#lib'; +import { ChannelType } from 'discord.js'; export default class MessageVerboseListener extends BushListener { public constructor() { @@ -11,7 +12,7 @@ export default class MessageVerboseListener extends BushListener { public override exec(...[message]: BushClientEvents['messageCreate']): void { if (client.customReady) { - if (message.channel?.type === 'DM') return; + if (message.channel?.type === ChannelType.DM) return; void client.console.verbose( 'messageVerbose', `A message was sent by <<${message.author.tag}>> in <<${message.channel.name}>> in <<${message.guild!.name}>>.` diff --git a/src/listeners/other/consoleListener.ts b/src/listeners/other/consoleListener.ts index fca8255..5a3e4e4 100644 --- a/src/listeners/other/consoleListener.ts +++ b/src/listeners/other/consoleListener.ts @@ -23,13 +23,13 @@ export default class ConsoleListener extends BushListener { CommandInteraction, Interaction, Message, - MessageActionRow, + ActionRow, MessageAttachment, - MessageButton, + ButtonComponent, MessageCollector, InteractionCollector, MessageEmbed, - MessageSelectMenu, + SelectMenuComponent, ReactionCollector, Util, Collection diff --git a/src/listeners/track-manual-punishments/modlogSyncBan.ts b/src/listeners/track-manual-punishments/modlogSyncBan.ts index 7fe2f7e..88334a4 100644 --- a/src/listeners/track-manual-punishments/modlogSyncBan.ts +++ b/src/listeners/track-manual-punishments/modlogSyncBan.ts @@ -1,5 +1,5 @@ import { BushListener, BushUser, Moderation, ModLogType, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; export default class ModlogSyncBanListener extends BushListener { public constructor() { @@ -12,7 +12,8 @@ export default class ModlogSyncBanListener extends BushListener { public override async exec(...[ban]: BushClientEvents['guildBanAdd']) { if (!(await ban.guild.hasFeature('logManualPunishments'))) return; - if (!ban.guild.me!.permissions.has('VIEW_AUDIT_LOG')) { + if (!ban.guild.me) return; // bot was banned + if (!ban.guild.me.permissions.has(Permissions.FLAGS.VIEW_AUDIT_LOG)) { return ban.guild.error( 'modlogSyncBan', `Could not sync the manual ban of ${ban.user.tag} to the modlog because I do not have the "View Audit Log" permission.` @@ -22,7 +23,7 @@ export default class ModlogSyncBanListener extends BushListener { const now = new Date(); await util.sleep(0.5); // wait for audit log entry - const logs = (await ban.guild.fetchAuditLogs({ type: 'MEMBER_BAN_ADD' })).entries.filter( + const logs = (await ban.guild.fetchAuditLogs({ type: 'MemberBanAdd' })).entries.filter( (entry) => entry.target?.id === ban.user.id ); @@ -54,7 +55,7 @@ export default class ModlogSyncBanListener extends BushListener { .setFooter({ text: `CaseID: ${log.id}` }) .setAuthor({ name: ban.user.tag, - iconURL: ban.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: ban.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Manual Ban'}`) .addField('**User**', `${ban.user} (${ban.user.tag})`) diff --git a/src/listeners/track-manual-punishments/modlogSyncKick.ts b/src/listeners/track-manual-punishments/modlogSyncKick.ts index 7c06c4d..f7da96f 100644 --- a/src/listeners/track-manual-punishments/modlogSyncKick.ts +++ b/src/listeners/track-manual-punishments/modlogSyncKick.ts @@ -1,5 +1,5 @@ import { BushListener, BushUser, Moderation, ModLogType, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; export default class ModlogSyncKickListener extends BushListener { public constructor() { @@ -12,7 +12,8 @@ export default class ModlogSyncKickListener extends BushListener { public override async exec(...[member]: BushClientEvents['guildMemberRemove']) { if (!(await member.guild.hasFeature('logManualPunishments'))) return; - if (!member.guild.me!.permissions.has('VIEW_AUDIT_LOG')) { + if (!member.guild.me) return; // bot was removed from guild + if (!member.guild.me.permissions.has(Permissions.FLAGS.VIEW_AUDIT_LOG)) { return member.guild.error( 'modlogSyncKick', `Could not sync the potential manual kick of ${member.user.tag} to the modlog because I do not have the "View Audit Log" permission.` @@ -22,7 +23,7 @@ export default class ModlogSyncKickListener extends BushListener { const now = new Date(); await util.sleep(0.5); // wait for audit log entry - const logs = (await member.guild.fetchAuditLogs({ type: 'MEMBER_KICK' })).entries.filter( + const logs = (await member.guild.fetchAuditLogs({ type: 'MemberKick' })).entries.filter( (entry) => entry.target?.id === member.user.id ); @@ -54,7 +55,7 @@ export default class ModlogSyncKickListener extends BushListener { .setFooter({ text: `CaseID: ${log.id}` }) .setAuthor({ name: member.user.tag, - iconURL: member.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: member.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Manual Kick'}`) .addField('**User**', `${member.user} (${member.user.tag})`) diff --git a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts index e29af7e..c28aacf 100644 --- a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts +++ b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts @@ -1,5 +1,5 @@ import { BushListener, BushUser, Moderation, ModLogType, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; export default class ModlogSyncTimeoutListener extends BushListener { public constructor() { @@ -12,7 +12,7 @@ export default class ModlogSyncTimeoutListener extends BushListener { public override async exec(...[_oldMember, newMember]: BushClientEvents['guildMemberUpdate']) { if (!(await newMember.guild.hasFeature('logManualPunishments'))) return; - if (!newMember.guild.me!.permissions.has('VIEW_AUDIT_LOG')) { + if (!newMember.guild.me!.permissions.has(Permissions.FLAGS.VIEW_AUDIT_LOG)) { return newMember.guild.error( 'modlogSyncTimeout', `Could not sync the potential manual timeout of ${newMember.user.tag} to the modlog because I do not have the "View Audit Log" permission.` @@ -22,7 +22,7 @@ export default class ModlogSyncTimeoutListener extends BushListener { const now = new Date(); await util.sleep(0.5); // wait for audit log entry - const logs = (await newMember.guild.fetchAuditLogs({ type: 'MEMBER_UPDATE' })).entries.filter( + const logs = (await newMember.guild.fetchAuditLogs({ type: 'MemberUpdate' })).entries.filter( (entry) => entry.target?.id === newMember.user.id ); @@ -60,7 +60,7 @@ export default class ModlogSyncTimeoutListener extends BushListener { .setFooter({ text: `CaseID: ${log.id}` }) .setAuthor({ name: newMember.user.tag, - iconURL: newMember.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: newMember.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${newTime ? 'Manual Timeout' : 'Manual Remove Timeout'}`) .addField('**User**', `${newMember.user} (${newMember.user.tag})`) diff --git a/src/listeners/track-manual-punishments/modlogSyncUnban.ts b/src/listeners/track-manual-punishments/modlogSyncUnban.ts index 67031b0..2d28e1c 100644 --- a/src/listeners/track-manual-punishments/modlogSyncUnban.ts +++ b/src/listeners/track-manual-punishments/modlogSyncUnban.ts @@ -1,5 +1,5 @@ import { BushListener, BushUser, Moderation, ModLogType, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed, Permissions } from 'discord.js'; export default class ModlogSyncUnbanListener extends BushListener { public constructor() { @@ -12,7 +12,7 @@ export default class ModlogSyncUnbanListener extends BushListener { public override async exec(...[ban]: BushClientEvents['guildBanRemove']) { if (!(await ban.guild.hasFeature('logManualPunishments'))) return; - if (!ban.guild.me!.permissions.has('VIEW_AUDIT_LOG')) { + if (!ban.guild.me!.permissions.has(Permissions.FLAGS.VIEW_AUDIT_LOG)) { return ban.guild.error( 'modlogSyncBan', `Could not sync the manual unban of ${ban.user.tag} to the modlog because I do not have the "View Audit Log" permission.` @@ -22,7 +22,7 @@ export default class ModlogSyncUnbanListener extends BushListener { const now = new Date(); await util.sleep(0.5); // wait for audit log entry - const logs = (await ban.guild.fetchAuditLogs({ type: 'MEMBER_BAN_REMOVE' })).entries.filter( + const logs = (await ban.guild.fetchAuditLogs({ type: 'MemberBanRemove' })).entries.filter( (entry) => entry.target?.id === ban.user.id ); @@ -54,7 +54,7 @@ export default class ModlogSyncUnbanListener extends BushListener { .setFooter({ text: `CaseID: ${log.id}` }) .setAuthor({ name: ban.user.tag, - iconURL: ban.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + iconURL: ban.user.avatarURL({ format: 'png', size: 4096 }) ?? undefined }) .addField('**Action**', `${'Manual Unban'}`) .addField('**User**', `${ban.user} (${ban.user.tag})`) |