diff options
Diffstat (limited to 'src')
35 files changed, 280 insertions, 206 deletions
diff --git a/src/arguments/contentWithDuration.ts b/src/arguments/contentWithDuration.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/arguments/contentWithDuration.ts diff --git a/src/arguments/duration.ts b/src/arguments/duration.ts index a2f7751..7b7a922 100644 --- a/src/arguments/duration.ts +++ b/src/arguments/duration.ts @@ -1,45 +1,11 @@ import { BushArgumentTypeCaster } from '../lib/extensions/BushArgumentTypeCaster'; import { BushMessage } from '../lib/extensions/BushMessage'; +import { BushConstants } from '../lib/utils/BushConstants'; -// Stolen from @Mzato0001 (pr to discord akairo that hasn't been merged yet) -const TimeUnits = { - years: { - label: '(?:years?|y)', - value: 1000 * 60 * 60 * 24 * 365 - }, - months: { - label: '(?:months?|mo)', - value: 1000 * 60 * 60 * 24 * 30 - }, - weeks: { - label: '(?:weeks?|w)', - value: 1000 * 60 * 60 * 24 * 7 - }, - days: { - label: '(?:days?|d)', - value: 1000 * 60 * 60 * 24 - }, - hours: { - label: '(?:hours?|hrs?|h)', - value: 1000 * 60 * 60 - }, - minutes: { - label: '(?:minutes?|mins?|m)', - value: 1000 * 60 - }, - seconds: { - label: '(?:seconds?|secs?|s)', - value: 1000 - }, - milliseconds: { - label: '(?:milliseconds?|msecs?|ms)', - value: 1 - } -}; export const durationTypeCaster: BushArgumentTypeCaster = async (_message: BushMessage, phrase): Promise<number> => { if (!phrase) return null; - const regexString = Object.entries(TimeUnits) + const regexString = Object.entries(BushConstants.TimeUnits) .map(([name, { label }]) => String.raw`(?:(?<${name}>-?(?:\d+)?\.?\d+) *${label})?`) .join('\\s*'); const match = new RegExp(`^${regexString}$`, 'i').exec(phrase); @@ -48,7 +14,7 @@ export const durationTypeCaster: BushArgumentTypeCaster = async (_message: BushM let milliseconds = 0; for (const key in match.groups) { const value = Number(match.groups[key] || 0); - milliseconds += value * TimeUnits[key].value; + milliseconds += value * BushConstants.TimeUnits[key].value; } return milliseconds; diff --git a/src/commands/config/muteRole.ts b/src/commands/config/muteRole.ts index f51c5ce..a354bcc 100644 --- a/src/commands/config/muteRole.ts +++ b/src/commands/config/muteRole.ts @@ -1,8 +1,8 @@ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { Role } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; -import { Guild } from '../../lib/models'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; import AllowedMentions from '../../lib/utils/AllowedMentions'; export default class MuteRoleCommand extends BushCommand { @@ -11,7 +11,7 @@ export default class MuteRoleCommand extends BushCommand { aliases: ['muterole'], category: 'config', description: { - content: 'Set the prefix of the current server (resets to default if prefix is not given)', + content: 'Configure what role to use when muting users.', usage: 'prefix [prefix]', examples: ['prefix', 'prefix +'] }, @@ -31,9 +31,9 @@ export default class MuteRoleCommand extends BushCommand { slash: true, slashOptions: [ { - type: 'ROLE', + type: ApplicationCommandOptionType.ROLE, name: 'role', - description: 'The mute role for this server.', + description: "What would you like to set the server's mute role to?", required: true } ] @@ -41,16 +41,9 @@ export default class MuteRoleCommand extends BushCommand { } async exec(message: BushMessage | BushSlashMessage, args: { role: Role }): Promise<void> { - let row = await Guild.findByPk(message.guild.id); - if (!row) { - row = Guild.build({ - id: message.guild.id - }); - } - row.muteRole = args.role.id; - await row.save(); + await message.guild.setSetting('muteRole', args.role.id); await message.util.send({ - content: `${this.client.util.emojis.success} Changed the mute role to <@&${args.role.id}>.`, + content: `${this.client.util.emojis.success} Changed the server's mute role to <@&${args.role.id}>.`, allowedMentions: AllowedMentions.none() }); } diff --git a/src/commands/config/prefix.ts b/src/commands/config/prefix.ts index 5b73a1a..fc7b3bf 100644 --- a/src/commands/config/prefix.ts +++ b/src/commands/config/prefix.ts @@ -1,13 +1,20 @@ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; -import { Guild } from '../../lib/models'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class PrefixCommand extends BushCommand { constructor() { super('prefix', { aliases: ['prefix'], category: 'config', + description: { + content: 'Set or reset the prefix for the server.', + usage: 'prefix [prefix]', + examples: ['prefix', 'prefix +'] + }, + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD'], args: [ { id: 'prefix', @@ -19,37 +26,31 @@ export default class PrefixCommand extends BushCommand { } } ], - clientPermissions: ['SEND_MESSAGES'], - userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD'], - description: { - content: 'Set the prefix of the current server (resets to default if prefix is not given)', - usage: 'prefix [prefix]', - examples: ['prefix', 'prefix +'] - }, + slash: true, slashOptions: [ { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'prefix', - description: 'The prefix to set for this server', + description: 'What would you like the new prefix to be?', required: false } - ], - slash: true + ] }); } - async exec(message: BushMessage | BushSlashMessage, { prefix }: { prefix?: string }): Promise<void> { - let row = await Guild.findByPk(message.guild.id); - if (!row) { - row = Guild.build({ - id: message.guild.id - }); - } - await row.update({ prefix: prefix || this.client.config.prefix }); - if (prefix) { - await message.util.send(`${this.client.util.emojis.success} changed prefix from \`${prefix}\` to `); + async exec(message: BushMessage | BushSlashMessage, args: { prefix?: string }): Promise<unknown> { + const oldPrefix = message.guild.getSetting('prefix'); + await message.guild.setSetting('prefix', args.prefix ?? this.client.config.prefix); + if (args.prefix) { + return await message.util.send( + `${this.client.util.emojis.success} changed the server's prefix ${oldPrefix ? `from \`${oldPrefix}\`` : ''} to \`${ + args.prefix + }\`.` + ); } else { - await message.util.send(`${this.client.util.emojis.success} reset prefix to \`${this.client.config.prefix}\``); + return await message.util.send( + `${this.client.util.emojis.success} reset the server's prefix to \`${this.client.config.prefix}\`.` + ); } } } diff --git a/src/commands/config/welcomeChannel.ts b/src/commands/config/welcomeChannel.ts index 72e55f1..8cab33c 100644 --- a/src/commands/config/welcomeChannel.ts +++ b/src/commands/config/welcomeChannel.ts @@ -1,7 +1,8 @@ -import { User } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord-api-types'; +import { Channel } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushMessage } from '../../lib/extensions/BushMessage'; -import { Global } from '../../lib/models'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class WelcomeChannelCommand extends BushCommand { public constructor() { @@ -9,41 +10,45 @@ export default class WelcomeChannelCommand extends BushCommand { aliases: ['welcomechannel', 'wc'], category: 'config', description: { - content: 'Configure the what channel you want the bot to send a message in when someone joins the server.', + content: 'Configure the what channel you want BushBot to send a message in when someone joins the server.', usage: 'welcomechannel [channel]', examples: ['welcomechannel #welcome'] }, clientPermissions: ['SEND_MESSAGES'], - ownerOnly: true + userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD'], + args: [ + { + id: 'channel', + type: 'channel', + prompt: { + start: 'What channel would you like me to send welcome messages in?', + retry: '{error} Choose a valid channel', + optional: true + } + } + ], + slash: true, + slashOptions: [ + { + type: ApplicationCommandOptionType.CHANNEL, + name: 'channel', + description: 'What channel would you like me to send welcome messages in?', + required: false + } + ] }); } - public async exec(message: BushMessage, args: { action: 'add' | 'remove'; user: User }): Promise<unknown> { - if (!this.client.config.owners.includes(message.author.id)) - return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command...`); - - const superUsers = (await Global.findByPk(this.client.config.dev ? 'development' : 'production')).superUsers; - let success; - if (args.action === 'add') { - if (superUsers.includes(args.user.id)) { - return message.util.reply(`${this.client.util.emojis.warn} \`${args.user.tag}\` is already a superuser.`); - } - success = await this.client.util.insertOrRemoveFromGlobal('add', 'superUsers', args.user.id).catch(() => false); - } else { - if (!superUsers.includes(args.user.id)) { - return message.util.reply(`${this.client.util.emojis.warn} \`${args.user.tag}\` is not superuser.`); - } - success = await this.client.util.insertOrRemoveFromGlobal('remove', 'superUsers', args.user.id).catch(() => false); - } - if (success) { - const responses = [args.action == 'remove' ? `` : 'made', args.action == 'remove' ? 'is no longer' : '']; - return message.util.reply( - `${this.client.util.emojis.success} ${responses[0]} \`${args.user.tag}\` ${responses[1]} a superuser.` + public async exec(message: BushMessage | BushSlashMessage, args: { channel: Channel }): Promise<unknown> { + const oldChannel = await message.guild.getSetting('welcomeChannel'); + await message.guild.setSetting('welcomeChannel', args.channel.id ?? undefined); + if (args.channel) { + return await message.util.send( + `${this.client.util.emojis.success} changed the server's welcome channel ${ + oldChannel ? `from <#${oldChannel}>` : '' + } to <#${args.channel.id}>.` ); } else { - const response = [args.action == 'remove' ? `removing` : 'making', args.action == 'remove' ? `from` : 'to']; - return message.util.reply( - `${this.client.util.emojis.error} There was an error ${response[0]} \`${args.user.tag}\` ${response[1]} the superuser list.` - ); + return await message.util.send(`${this.client.util.emojis.success} removed the server's welcome channel.`); } } } diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 310a2c5..04c5158 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -1,12 +1,13 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { exec } from 'child_process'; import { Constants } from 'discord-akairo'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, MessageEmbed, MessageEmbedOptions, Util } from 'discord.js'; import { transpile } from 'typescript'; import { inspect, promisify } from 'util'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; const clean = (text) => { if (typeof text === 'string') { @@ -79,43 +80,43 @@ export default class EvalCommand extends BushCommand { { name: 'code', description: 'The code you would like to evaluate.', - type: 'STRING', + type: ApplicationCommandOptionType.STRING, required: true }, { name: 'sel_depth', description: 'How deep to display the output.', - type: 'INTEGER', + type: ApplicationCommandOptionType.INTEGER, required: false }, { name: 'sudo', description: 'Whether or not to override checks.', - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, required: false }, { name: 'silent', description: 'Whether or not to make the response silent', - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, required: false }, { name: 'typescript', description: 'Whether or not to compile the code from typescript.', - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, required: false }, { name: 'hidden', description: 'Whether or not to show hidden items.', - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, required: false }, { name: 'show_proto', description: 'Show prototype.', - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, required: false } ] @@ -135,7 +136,7 @@ export default class EvalCommand extends BushCommand { show_proto: boolean; } ): Promise<unknown> { - if (!this.client.config.owners.includes(message.author.id)) + if (!message.author.isOwner()) return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command.`); if (message.util.isSlash) { await (message as BushSlashMessage).interaction.defer({ ephemeral: args.silent }); diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts index f5fee88..07218f2 100644 --- a/src/commands/dev/reload.ts +++ b/src/commands/dev/reload.ts @@ -1,7 +1,7 @@ -import { stripIndent } from 'common-tags'; -import { Message } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; +import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class ReloadCommand extends BushCommand { constructor() { @@ -24,7 +24,7 @@ export default class ReloadCommand extends BushCommand { typing: true, slashOptions: [ { - type: 'BOOLEAN', + type: ApplicationCommandOptionType.BOOLEAN, name: 'fast', description: 'Whether to use esbuild for fast compiling or not', required: false @@ -34,23 +34,21 @@ export default class ReloadCommand extends BushCommand { }); } - private async getResponse(fast: boolean): Promise<string> { + public async exec(message: BushMessage | BushSlashMessage, { fast }: { fast: boolean }): Promise<unknown> { + if (!message.author.isOwner()) + return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command.`); + try { const s = new Date(); await this.client.util.shell(`yarn build-${fast ? 'esbuild' : 'tsc'}`); this.client.commandHandler.reloadAll(); this.client.listenerHandler.reloadAll(); this.client.inhibitorHandler.reloadAll(); - return `🔁 Successfully reloaded! (${new Date().getTime() - s.getTime()}ms)`; + return message.util.send(`🔁 Successfully reloaded! (${new Date().getTime() - s.getTime()}ms)`); } catch (e) { - return stripIndent` - An error occured while reloading: - ${await this.client.util.haste(e.stack)} - `; + return message.util.send( + `An error occurred while reloading:\n${await this.client.util.codeblock(e.stack, 2048 - 34, 'js')}` + ); } } - - public async exec(message: Message | BushSlashMessage, { fast }: { fast: boolean }): Promise<void> { - await message.util.send(await this.getResponse(fast)); - } } diff --git a/src/commands/dev/setLevel.ts b/src/commands/dev/setLevel.ts index f536109..7e07ce0 100644 --- a/src/commands/dev/setLevel.ts +++ b/src/commands/dev/setLevel.ts @@ -1,5 +1,8 @@ -import { Message, User } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord-api-types'; +import { User } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; +import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; import { Level } from '../../lib/models'; import AllowedMentions from '../../lib/utils/AllowedMentions'; @@ -34,13 +37,13 @@ export default class SetLevelCommand extends BushCommand { ownerOnly: true, slashOptions: [ { - type: 'USER', + type: /* 'USER' */ ApplicationCommandOptionType.USER, name: 'user', description: 'The user to change the level of', required: true }, { - type: 'INTEGER', + type: /* 'INTEGER' */ ApplicationCommandOptionType.INTEGER, name: 'level', description: 'The level to set the user to', required: true @@ -50,7 +53,10 @@ export default class SetLevelCommand extends BushCommand { }); } - private async setLevel(user: User, level: number): Promise<string> { + async exec(message: BushMessage | BushSlashMessage, { user, level }: { user: User; level: number }): Promise<unknown> { + if (!message.author.isOwner()) + return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command.`); + const [levelEntry] = await Level.findOrBuild({ where: { id: user.id @@ -60,12 +66,8 @@ export default class SetLevelCommand extends BushCommand { } }); await levelEntry.update({ xp: Level.convertLevelToXp(level) }); - return `Successfully set level of <@${user.id}> to \`${level}\` (\`${levelEntry.xp}\` XP)`; - } - - async exec(message: Message, { user, level }: { user: User; level: number }): Promise<void> { - await message.util.send({ - content: await this.setLevel(user, level), + return await message.util.send({ + content: `Successfully set level of <@${user.id}> to \`${level}\` (\`${levelEntry.xp}\` XP)`, allowedMentions: AllowedMentions.none() }); } diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts index 4562e6f..773209c 100644 --- a/src/commands/dev/superUser.ts +++ b/src/commands/dev/superUser.ts @@ -42,8 +42,8 @@ export default class SuperUserCommand extends BushCommand { return { action, user }; } public async exec(message: BushMessage, args: { action: 'add' | 'remove'; user: User }): Promise<unknown> { - if (!this.client.config.owners.includes(message.author.id)) - return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command...`); + if (!message.author.isOwner()) + return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command.`); const superUsers = (await Global.findByPk(this.client.config.dev ? 'development' : 'production')).superUsers; let success; @@ -59,7 +59,7 @@ export default class SuperUserCommand extends BushCommand { success = await this.client.util.insertOrRemoveFromGlobal('remove', 'superUsers', args.user.id).catch(() => false); } if (success) { - const responses = [args.action == 'remove' ? `` : 'made', args.action == 'remove' ? 'is no longer' : '']; + const responses = [args.action == 'remove' ? '' : 'made', args.action == 'remove' ? 'is no longer' : '']; return message.util.reply( `${this.client.util.emojis.success} ${responses[0]} \`${args.user.tag}\` ${responses[1]} a superuser.` ); diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index 8969efc..30606e1 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -1,7 +1,8 @@ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { MessageActionRow, MessageButton, MessageEmbed } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class HelpCommand extends BushCommand { constructor() { @@ -35,7 +36,7 @@ export default class HelpCommand extends BushCommand { slash: true, slashOptions: [ { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'command', description: 'The command you would like to find information about.', required: false diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts index 3038658..6584ab5 100644 --- a/src/commands/info/ping.ts +++ b/src/commands/info/ping.ts @@ -1,6 +1,6 @@ import { Message, MessageEmbed } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class PingCommand extends BushCommand { constructor() { diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts index 2175233..107af82 100644 --- a/src/commands/info/pronouns.ts +++ b/src/commands/info/pronouns.ts @@ -1,6 +1,8 @@ -import { CommandInteraction, Message, MessageEmbed, User } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord-api-types'; +import { Message, MessageEmbed, User } from 'discord.js'; import got, { HTTPError } from 'got'; import { BushCommand } from '../../lib/extensions/BushCommand'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export const pronounMapping = { unspecified: 'Unspecified', @@ -41,13 +43,17 @@ export default class PronounsCommand extends BushCommand { { id: 'user', type: 'user', - default: null + prompt: { + start: 'Who would you like to view the pronouns of?', + retry: '{error} Choose a valid user to view the pronouns of.', + optional: true + } } ], clientPermissions: ['SEND_MESSAGES'], slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'The user to get pronouns for', required: false @@ -56,52 +62,36 @@ export default class PronounsCommand extends BushCommand { slash: true }); } - async sendResponse(message: Message | CommandInteraction, user: User, author: boolean): Promise<void> { + async exec(message: Message | BushSlashMessage, args: { user?: User }): Promise<void> { + const user = args.user || message.author; + const author = user.id === message.author.id; try { const apiRes: { pronouns: pronounsType } = await got .get(`https://pronoundb.org/api/v1/lookup?platform=discord&id=${user.id}`) .json(); - if (message instanceof Message) { - message.reply({ - embeds: [ - new MessageEmbed({ - title: `${author ? 'Your' : `${user.tag}'s`} pronouns:`, - description: pronounMapping[apiRes.pronouns], - footer: { - text: 'Data provided by https://pronoundb.org/' - } - }) - ] - }); - } else { - message.reply({ - embeds: [ - new MessageEmbed({ - title: `${author ? 'Your' : `${user.tag}'s`} pronouns:`, - description: pronounMapping[apiRes.pronouns], - footer: { - text: 'Data provided by https://pronoundb.org/' - } - }) - ] - }); - } + message.util.reply({ + embeds: [ + new MessageEmbed({ + title: `${author ? 'Your' : `${user.tag}'s`} pronouns:`, + description: pronounMapping[apiRes.pronouns], + footer: { + text: 'Data provided by https://pronoundb.org/' + } + }) + ] + }); } catch (e) { if (e instanceof HTTPError && e.response.statusCode === 404) { if (author) { - await message.reply( + await message.util.reply( 'You do not appear to have any pronouns set. Please go to https://pronoundb.org/ and set your pronouns.' ); } else { - await message.reply( + await message.util.reply( `${user.tag} does not appear to have any pronouns set. Please tell them to go to https://pronoundb.org/ and set their pronouns.` ); } } else throw e; } } - async exec(message: Message, { user }: { user?: User }): Promise<void> { - const u = user || message.author; - await this.sendResponse(message, u, u.id === message.author.id); - } } diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index 7ce222a..9d7eb4d 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -1,4 +1,5 @@ import { Argument } from 'discord-akairo'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, Message, User } from 'discord.js'; import moment from 'moment'; import { BushCommand } from '../../lib/extensions/BushCommand'; @@ -52,19 +53,19 @@ export default class BanCommand extends BushCommand { }, slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'Who would you like to ban?', required: true }, { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'reason', description: 'Why are they getting banned?', required: false }, { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'time', description: 'How long should they be banned for?', required: false diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts index eed3038..d7fdfbd 100644 --- a/src/commands/moderation/kick.ts +++ b/src/commands/moderation/kick.ts @@ -1,6 +1,7 @@ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, GuildMember, Message } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; import { Guild, ModLog, ModLogType } from '../../lib/models'; export default class KickCommand extends BushCommand { @@ -32,13 +33,13 @@ export default class KickCommand extends BushCommand { }, slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'The user to kick', required: true }, { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'reason', description: 'The reason to show in modlogs and audit log', required: false diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts index 9b6ad70..eeb2d04 100644 --- a/src/commands/moderation/mute.ts +++ b/src/commands/moderation/mute.ts @@ -1,4 +1,5 @@ import { Argument } from 'discord-akairo'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, Message, User } from 'discord.js'; import moment from 'moment'; import { BushCommand } from '../../lib/extensions/BushCommand'; @@ -43,19 +44,19 @@ export default class MuteCommand extends BushCommand { }, slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'The user to mute.', required: true }, { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'reason', description: 'Why the user is getting muted.', required: false }, { - type: 'STRING', + type: ApplicationCommandOptionType.STRING, name: 'time', description: 'How long the user should be muted for.', required: false diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index f0918f0..4eb745d 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-empty-function */ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { GuildMember, Message, Role } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; import AllowedMentions from '../../lib/utils/AllowedMentions'; @@ -57,13 +58,13 @@ export default class RoleCommand extends BushCommand { ], slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'The user to add/remove the role on', required: true }, { - type: 'ROLE', + type: ApplicationCommandOptionType.ROLE, name: 'role', description: 'The role to add/remove', required: true diff --git a/src/commands/moulberry-bush/capePerms.ts b/src/commands/moulberry-bush/capePerms.ts index d1850c8..49e591a 100644 --- a/src/commands/moulberry-bush/capePerms.ts +++ b/src/commands/moulberry-bush/capePerms.ts @@ -1,4 +1,5 @@ import { Constants } from 'discord-akairo'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { MessageEmbed } from 'discord.js'; import got from 'got'; import { BushCommand } from '../../lib/extensions/BushCommand'; @@ -61,7 +62,7 @@ export default class CapePermissionsCommand extends BushCommand { { name: 'ign', description: 'The ign of the player you would like to view the capes permissions of.', - type: 'STRING', + type: ApplicationCommandOptionType.STRING, required: true } ] diff --git a/src/commands/moulberry-bush/level.ts b/src/commands/moulberry-bush/level.ts index 41541e0..ea51f94 100644 --- a/src/commands/moulberry-bush/level.ts +++ b/src/commands/moulberry-bush/level.ts @@ -1,6 +1,7 @@ +import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message, User } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; import { Level } from '../../lib/models'; /* import canvas from 'canvas'; @@ -33,7 +34,7 @@ export default class LevelCommand extends BushCommand { ], slashOptions: [ { - type: 'USER', + type: ApplicationCommandOptionType.USER, name: 'user', description: 'The user to get the level of', required: false diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts index 3cd9ec6..8aec247 100644 --- a/src/commands/moulberry-bush/rule.ts +++ b/src/commands/moulberry-bush/rule.ts @@ -1,4 +1,5 @@ import { Argument, Constants } from 'discord-akairo'; +import { ApplicationCommandOptionType } from 'discord-api-types'; import { MessageEmbed, User } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushMessage } from '../../lib/extensions/BushMessage'; @@ -94,13 +95,13 @@ export default class RuleCommand extends BushCommand { { name: 'rule', description: 'The rule you would you like to have cited', - type: 'INTEGER', + type: ApplicationCommandOptionType.INTEGER, required: false }, { name: 'user', description: 'The user you would like to mention.', - type: 'USER', + type: ApplicationCommandOptionType.USER, required: false } ], diff --git a/src/inhibitors/blacklist/guildBlacklist.ts b/src/inhibitors/blacklist/guildBlacklist.ts index 93d8aee..4c541e8 100644 --- a/src/inhibitors/blacklist/guildBlacklist.ts +++ b/src/inhibitors/blacklist/guildBlacklist.ts @@ -1,6 +1,6 @@ import { BushInhibitor } from '../../lib/extensions/BushInhibitor'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class GuildBlacklistInhibitor extends BushInhibitor { constructor() { diff --git a/src/inhibitors/blacklist/userBlacklist.ts b/src/inhibitors/blacklist/userBlacklist.ts index bbced28..73ad846 100644 --- a/src/inhibitors/blacklist/userBlacklist.ts +++ b/src/inhibitors/blacklist/userBlacklist.ts @@ -1,6 +1,6 @@ import { BushInhibitor } from '../../lib/extensions/BushInhibitor'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class UserBlacklistInhibitor extends BushInhibitor { constructor() { diff --git a/src/inhibitors/commands/disabledCommand.ts b/src/inhibitors/commands/disabledCommand.ts index 8538858..caf7bf7 100644 --- a/src/inhibitors/commands/disabledCommand.ts +++ b/src/inhibitors/commands/disabledCommand.ts @@ -1,7 +1,7 @@ import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInhibitor } from '../../lib/extensions/BushInhibitor'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class DisabledCommandInhibitor extends BushInhibitor { constructor() { diff --git a/src/inhibitors/noCache.ts b/src/inhibitors/noCache.ts index 61f0b3e..a8f52d7 100644 --- a/src/inhibitors/noCache.ts +++ b/src/inhibitors/noCache.ts @@ -1,6 +1,6 @@ import { BushInhibitor } from '../lib/extensions/BushInhibitor'; -import { BushSlashMessage } from '../lib/extensions/BushInteractionMessage'; import { BushMessage } from '../lib/extensions/BushMessage'; +import { BushSlashMessage } from '../lib/extensions/BushSlashMessage'; export default class noCacheInhibitor extends BushInhibitor { constructor() { diff --git a/src/lang/en-us.json b/src/lang/en-us.json new file mode 100644 index 0000000..4900abb --- /dev/null +++ b/src/lang/en-us.json @@ -0,0 +1,14 @@ +{ + "commands": { + "config": { + "muteRole": { + "description": "" + } + }, + "dev": {}, + "info": {}, + "moderation": {}, + "moulberry-bush": {}, + "utilities": {} + } +} diff --git a/src/lib/extensions/BushCommand.ts b/src/lib/extensions/BushCommand.ts index b62d26e..f22a628 100644 --- a/src/lib/extensions/BushCommand.ts +++ b/src/lib/extensions/BushCommand.ts @@ -4,8 +4,8 @@ import { ArgumentGenerator, ArgumentOptions, ArgumentPromptOptions, Command, Com import { Snowflake } from 'discord.js'; import { BushClient } from './BushClient'; import { BushCommandHandler } from './BushCommandHandler'; -import { BushSlashMessage } from './BushInteractionMessage'; import { BushMessage } from './BushMessage'; +import { BushSlashMessage } from './BushSlashMessage'; export interface BushArgumentOptions extends ArgumentOptions { id: string; diff --git a/src/lib/extensions/BushGuild.ts b/src/lib/extensions/BushGuild.ts new file mode 100644 index 0000000..470e93a --- /dev/null +++ b/src/lib/extensions/BushGuild.ts @@ -0,0 +1,20 @@ +import { Guild } from 'discord.js'; +import { Guild as GuildDB, GuildModel } from '../models/Guild'; +import { BushClient } from './BushClient'; + +export class BushGuild extends Guild { + public declare client: BushClient; + public constructor(client: BushClient, data: unknown) { + super(client, data); + } + + public async getSetting(setting: keyof GuildModel) { + return ((await GuildDB.findByPk(this.id)) ?? GuildDB.build({ id: this.id })).get(setting); + } + + public async setSetting<K extends keyof GuildModel>(setting: K, value: GuildDB[K]) { + const row = (await GuildDB.findByPk(this.id)) ?? GuildDB.build({ id: this.id }); + row[setting] = value; + return await row.save(); + } +} diff --git a/src/lib/extensions/BushGuildMember.ts b/src/lib/extensions/BushGuildMember.ts new file mode 100644 index 0000000..d193f9e --- /dev/null +++ b/src/lib/extensions/BushGuildMember.ts @@ -0,0 +1,13 @@ +import { GuildMember } from 'discord.js'; +import { BushClient } from './BushClient'; +import { BushGuild } from './BushGuild'; +import { BushUser } from './BushUser'; + +export class BushGuildMember extends GuildMember { + public declare client: BushClient; + public declare guild: BushGuild; + public declare BushUser: BushUser; + public constructor(client: BushClient, data: unknown, guild: BushGuild) { + super(client, data, guild); + } +} diff --git a/src/lib/extensions/BushInhibitor.ts b/src/lib/extensions/BushInhibitor.ts index 8a31abf..602ff65 100644 --- a/src/lib/extensions/BushInhibitor.ts +++ b/src/lib/extensions/BushInhibitor.ts @@ -2,8 +2,8 @@ import { Inhibitor } from 'discord-akairo'; import { BushClient } from './BushClient'; import { BushCommand } from './BushCommand'; -import { BushSlashMessage } from './BushInteractionMessage'; import { BushMessage } from './BushMessage'; +import { BushSlashMessage } from './BushSlashMessage'; export class BushInhibitor extends Inhibitor { public declare client: BushClient; diff --git a/src/lib/extensions/BushMessage.ts b/src/lib/extensions/BushMessage.ts index afa6bde..7dbeeb2 100644 --- a/src/lib/extensions/BushMessage.ts +++ b/src/lib/extensions/BushMessage.ts @@ -1,11 +1,17 @@ import { DMChannel, Message, NewsChannel, TextChannel } from 'discord.js'; import { BushClient } from './BushClient'; import { BushCommandUtil } from './BushCommandUtil'; +import { BushGuild } from './BushGuild'; +import { BushGuildMember } from './BushGuildMember'; +import { BushUser } from './BushUser'; export class BushMessage extends Message { - declare client: BushClient; - declare util: BushCommandUtil; - constructor(client: BushClient, data: unknown, channel: TextChannel | DMChannel | NewsChannel) { + public declare client: BushClient; + public declare util: BushCommandUtil; + public declare guild: BushGuild; + public declare member: BushGuildMember; + public declare author: BushUser; + public constructor(client: BushClient, data: unknown, channel: TextChannel | DMChannel | NewsChannel) { super(client, data, channel); this.client = client; this.channel = channel; diff --git a/src/lib/extensions/BushInteractionMessage.ts b/src/lib/extensions/BushSlashMessage.ts index 62d2519..33ca11f 100644 --- a/src/lib/extensions/BushInteractionMessage.ts +++ b/src/lib/extensions/BushSlashMessage.ts @@ -2,10 +2,14 @@ import { AkairoMessage } from 'discord-akairo'; import { CommandInteraction } from 'discord.js'; import { BushClient } from './BushClient'; import { BushCommandUtil } from './BushCommandUtil'; +import { BushGuild } from './BushGuild'; +import { BushUser } from './BushUser'; export class BushSlashMessage extends AkairoMessage { public declare client: BushClient; public declare util: BushCommandUtil; + public declare guild: BushGuild; + public declare author: BushUser; public constructor( client: BushClient, interaction: CommandInteraction, diff --git a/src/lib/extensions/BushUser.ts b/src/lib/extensions/BushUser.ts new file mode 100644 index 0000000..dd07b7d --- /dev/null +++ b/src/lib/extensions/BushUser.ts @@ -0,0 +1,17 @@ +import { User } from 'discord.js'; +import { BushClient } from './BushClient'; + +export class BushUser extends User { + public declare client: BushClient; + public constructor(client: BushClient, data: unknown) { + super(client, data); + } + + public isOwner(): boolean { + return this.client.isOwner(this); + } + + public isSuperUser(): boolean { + return this.client.isSuperUser(this); + } +} diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts index 1015229..0e3f6bb 100644 --- a/src/lib/utils/BushConstants.ts +++ b/src/lib/utils/BushConstants.ts @@ -1,4 +1,40 @@ export class BushConstants { + // Stolen from @Mzato0001 (pr to discord akairo that hasn't been merged yet) + public static TimeUnits = { + years: { + label: '(?:years?|y)', + value: 1000 * 60 * 60 * 24 * 365 + }, + months: { + label: '(?:months?|mon|mo?)', + value: 1000 * 60 * 60 * 24 * 30 + }, + weeks: { + label: '(?:weeks?|w)', + value: 1000 * 60 * 60 * 24 * 7 + }, + days: { + label: '(?:days?|d)', + value: 1000 * 60 * 60 * 24 + }, + hours: { + label: '(?:hours?|hrs?|h)', + value: 1000 * 60 * 60 + }, + minutes: { + label: '(?:minutes?|mins?)', + value: 1000 * 60 + }, + seconds: { + label: '(?:seconds?|secs?|s)', + value: 1000 + }, + milliseconds: { + label: '(?:milliseconds?|msecs?|ms)', + value: 1 + } + }; + /** A bunch of mappings */ public static mappings = { guilds: { diff --git a/src/listeners/commands/slashBlocked.ts b/src/listeners/commands/slashBlocked.ts index e64253a..761bef8 100644 --- a/src/listeners/commands/slashBlocked.ts +++ b/src/listeners/commands/slashBlocked.ts @@ -1,6 +1,6 @@ import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushListener } from '../../lib/extensions/BushListener'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class SlashBlockedListener extends BushListener { public constructor() { diff --git a/src/listeners/commands/slashCommandError.ts b/src/listeners/commands/slashCommandError.ts index 1a5f293..da00eb4 100644 --- a/src/listeners/commands/slashCommandError.ts +++ b/src/listeners/commands/slashCommandError.ts @@ -1,8 +1,8 @@ import { stripIndents } from 'common-tags'; import { MessageEmbed } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushListener } from '../../lib/extensions/BushListener'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class SlashCommandErrorListener extends BushListener { constructor() { diff --git a/src/listeners/commands/slashStarted.ts b/src/listeners/commands/slashStarted.ts index c6b966a..534d89d 100644 --- a/src/listeners/commands/slashStarted.ts +++ b/src/listeners/commands/slashStarted.ts @@ -1,6 +1,6 @@ import { BushCommand } from '../../lib/extensions/BushCommand'; -import { BushSlashMessage } from '../../lib/extensions/BushInteractionMessage'; import { BushListener } from '../../lib/extensions/BushListener'; +import { BushSlashMessage } from '../../lib/extensions/BushSlashMessage'; export default class SlashStartedListener extends BushListener { constructor() { |