diff options
Diffstat (limited to 'src')
53 files changed, 1485 insertions, 211 deletions
diff --git a/src/commands/_fake-command/test.ts b/src/commands/_fake-command/test.ts new file mode 100644 index 0000000..8eeca9e --- /dev/null +++ b/src/commands/_fake-command/test.ts @@ -0,0 +1,18 @@ +import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; + +export default class TestCommand extends BushCommand { + public constructor() { + super('test', { + category: 'fake-commands', + description: { content: '', examples: '', usage: '' }, + condition: (message: BushMessage) => { + if (message.content.toLowerCase().includes('ironmoon')) return true; + else return false; + }, + completelyHide: true + }); + } + public async exec(message: BushMessage | BushSlashMessage): Promise<unknown> { + return await message.util.reply('Your message included the word ironmoon.'); + } +} diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts new file mode 100644 index 0000000..249789d --- /dev/null +++ b/src/commands/admin/channelPermissions.ts @@ -0,0 +1,97 @@ +import { Argument, Constants } from 'discord-akairo'; +import { GuildChannel, GuildMember, MessageEmbed, Role } from 'discord.js'; +import { BushCommand, BushMessage } from '../../lib'; + +export default class ChannelPermissionsCommand extends BushCommand { + public constructor() { + super('channelpermissions', { + aliases: ['channelperms', 'cperms', 'cperm', 'chanperms', 'chanperm', 'channelpermissions'], + category: 'admin', + typing: true, + description: { + content: 'Use to mass change the channel ', + usage: 'ChannelPerms <role_id> <perm> <state>', + examples: ['ChannelPerms 783794633129197589 read_messages deny'] + }, + args: [ + { + id: 'target', + type: Argument.union(Constants.ArgumentTypes.ROLE, Constants.ArgumentTypes.MEMBER), + match: Constants.ArgumentMatches.PHRASE, + prompt: { + start: 'What user/role would you like to change?', + retry: 'Invalid response. What user/role would you like to change?' + } + }, + { + id: 'permission', + type: 'permission', + match: Constants.ArgumentMatches.PHRASE, + prompt: { + start: 'What permission would you like to change?', + retry: '{error} Choose a valid permission.' + } + }, + { + id: 'state', + type: [ + ['true', '1', 'yes', 'enable', 'allow'], + ['false', '0', 'no', 'disable', 'disallow', 'deny'], + ['neutral', 'remove', 'none'] + ], + match: Constants.ArgumentMatches.PHRASE, + prompt: { + start: 'What should that permission be set to?', + retry: '{error} Set the state to either `enable`, `disable`, or `remove`.' + } + } + ], + ratelimit: 4, + cooldown: 4000, + clientPermissions: ['MANAGE_CHANNELS', 'SEND_MESSAGES'], + userPermissions: ['ADMINISTRATOR'], + channel: 'guild' + }); + } + + public async exec( + message: BushMessage, + { + target, + permission, + state + }: { + target: Role | GuildMember; + permission: string; + state: 'true' | 'false' | 'neutral'; + } + ): Promise<void> { + const failedChannels = []; + for (const channel of message.guild.channels.cache.array()) { + try { + if (channel.isThread()) return; + if (channel.permissionsLocked) return; + const permissionState = state === 'true' ? true : state === 'false' ? false : null; + await channel.permissionOverwrites.create( + target.id, + { [permission]: permissionState }, + { reason: 'Changing overwrites for mass channel channel perms command' } + ); + } catch (e) { + this.client.console.debug(e.stack); + failedChannels.push(channel); + } + } + const failure = failedChannels.map((e: GuildChannel) => `<#${e.id}>`).join(' '); + if (failure.length > 2000) { + const paginate: MessageEmbed[] = []; + for (let i = 0; i < failure.length; i += 2000) { + paginate.push(new MessageEmbed().setDescription(failure.substring(i, Math.min(failure.length, i + 2000)))); + } + const normalMessage = `Finished changing perms! Failed channels:`; + this.client.util.buttonPaginate(message, paginate, normalMessage); + } else { + await message.util.reply({ content: `Finished changing perms! Failed channels:`, embeds: [{ description: failure }] }); + } + } +} diff --git a/src/commands/config/autoPublishChannel.ts b/src/commands/config/autoPublishChannel.ts index 421e030..a2692e2 100644 --- a/src/commands/config/autoPublishChannel.ts +++ b/src/commands/config/autoPublishChannel.ts @@ -1,4 +1,4 @@ -import { BushCommand, BushMessage } from '@lib'; +import { AllowedMentions, BushCommand, BushMessage } from '@lib'; import { Channel } from 'discord.js'; export default class AutoPublishChannelCommand extends BushCommand { @@ -40,14 +40,17 @@ export default class AutoPublishChannelCommand extends BushCommand { public async exec(message: BushMessage, { channel }: { channel: Channel }): Promise<unknown> { const autoPublishChannels = await message.guild.getSetting('autoPublishChannels'); - autoPublishChannels.includes(channel.id) - ? autoPublishChannels.splice(autoPublishChannels.indexOf(channel.id), 1) - : autoPublishChannels.push(channel.id); - await message.guild.setSetting('autoPublishChannels', autoPublishChannels); - return await message.util.reply( - `${this.client.util.emojis.success} Successfully ${ - autoPublishChannels.includes(channel.id) ? 'disabled' : 'enabled' - } auto publishing in <#${channel.id}>.` + const newValue = this.client.util.addOrRemoveFromArray( + autoPublishChannels.includes(channel.id) ? 'remove' : 'add', + autoPublishChannels, + channel.id ); + await message.guild.setSetting('autoPublishChannels', newValue); + return await message.util.reply({ + content: `${this.client.util.emojis.success} Successfully ${ + autoPublishChannels.includes(channel.id) ? 'disabled' : 'enabled' + } auto publishing in <#${channel.id}>.`, + allowedMentions: AllowedMentions.none() + }); } } diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts new file mode 100644 index 0000000..4706041 --- /dev/null +++ b/src/commands/config/blacklist.ts @@ -0,0 +1,132 @@ +import { AllowedMentions, BushCommand, BushMessage, BushSlashMessage, Global } from '@lib'; +import { Argument } from 'discord-akairo'; +import { Channel, User } from 'discord.js'; + +export default class BlacklistCommand extends BushCommand { + public constructor() { + super('blacklist', { + aliases: ['blacklist', 'unblacklist'], + category: 'config', + description: { + content: 'A command to blacklist users and channels.', + usage: 'blacklist|unblacklist <user|channel>', + examples: ['blacklist @user', 'unblacklist #channel'] + }, + args: [ + { + id: 'target', + type: Argument.union('channel', 'user'), + match: 'phrase', + prompt: { + start: 'What channel or user that you would like to blacklist/unblacklist?', + retry: '{error} Pick a valid command.', + optional: false + } + }, + { + id: 'global', + match: 'flag', + flag: '--global' + } + ], + slash: true, + slashOptions: [ + { + name: 'action', + description: 'Would you like to add or remove someone or something from/to the blacklist?', + type: 'STRING', + choices: [ + { + name: 'blacklist', + value: 'blacklist' + }, + { + name: 'unblacklist', + value: 'unblacklist' + } + ], + required: true + }, + { + name: 'target', + description: 'What channel or user that you would like to blacklist/unblacklist?', + type: 'STRING', + required: true + } + ], + channel: 'guild', + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD'] + }); + } + + public async exec( + message: BushMessage | BushSlashMessage, + args: { action: 'blacklist' | 'unblacklist'; target: Channel | User | string; global: boolean } + ): Promise<unknown> { + let action: 'blacklist' | 'unblacklist' | 'toggle' = + args.action ?? (message?.util?.parsed?.alias as 'blacklist' | 'unblacklist') ?? 'toggle'; + const global = args.global && message.author.isOwner(); + const target = + typeof args.target === 'string' + ? (await Argument.cast('channel', this.client.commandHandler.resolver, message as BushMessage, args.target)) ?? + (await Argument.cast('user', this.client.commandHandler.resolver, message as BushMessage, args.target)) + : args.target; + if (!target) return await message.util.reply(`${this.client.util.emojis.error} Choose a valid channel or user.`); + const targetID = target.id; + + if (global) { + if (action === 'toggle') { + const blacklistedUsers = (await Global.findByPk(this.client.config.dev ? 'development' : 'production')) + .blacklistedUsers; + const blacklistedChannels = (await Global.findByPk(this.client.config.dev ? 'development' : 'production')) + .blacklistedChannels; + action = blacklistedUsers.includes(targetID) || blacklistedChannels.includes(targetID) ? 'unblacklist' : 'blacklist'; + } + const success = await this.client.util + .insertOrRemoveFromGlobal( + action === 'blacklist' ? 'add' : 'remove', + target instanceof User ? 'blacklistedUsers' : 'blacklistedChannels', + targetID + ) + .catch(() => false); + if (!success) + return await message.util.reply({ + content: `${this.client.util.emojis.error} There was an error globally **${action}ing** ${ + target?.tag ?? target.name + }.`, + allowedMentions: AllowedMentions.none() + }); + else + return await message.util.reply({ + content: `${this.client.util.emojis.success} Successfully **${action}ed** ${target?.tag ?? target.name} globally.`, + allowedMentions: AllowedMentions.none() + }); + // guild disable + } else { + const blacklistedChannels = await message.guild.getSetting('blacklistedChannels'); + const blacklistedUsers = await message.guild.getSetting('blacklistedUsers'); + if (action === 'toggle') { + action = blacklistedChannels.includes(targetID) ?? blacklistedUsers.includes(targetID) ? 'unblacklist' : 'blacklist'; + } + const newValue = this.client.util.addOrRemoveFromArray( + action === 'blacklist' ? 'add' : 'remove', + target instanceof User ? blacklistedUsers : blacklistedChannels, + targetID + ); + const success = await message.guild + .setSetting(target instanceof User ? 'blacklistedUsers' : 'blacklistedChannels', newValue) + .catch(() => false); + if (!success) + return await message.util.reply({ + content: `${this.client.util.emojis.error} There was an error **${action}ing** ${target?.tag ?? target.name}.`, + allowedMentions: AllowedMentions.none() + }); + else + return await message.util.reply({ + content: `${this.client.util.emojis.success} Successfully **${action}ed** ${target?.tag ?? target.name}.`, + allowedMentions: AllowedMentions.none() + }); + } + } +} diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts new file mode 100644 index 0000000..007cdb1 --- /dev/null +++ b/src/commands/config/disable.ts @@ -0,0 +1,128 @@ +import { AllowedMentions, BushCommand, BushMessage, BushSlashMessage, Global } from '@lib'; + +export default class DisableCommand extends BushCommand { + public constructor() { + super('disable', { + aliases: ['disable', 'enable'], + category: 'config', + description: { + content: 'A command to disable and enable commands.', + usage: 'disable|enable <command>', + examples: ['enable ban', 'disable kick'] + }, + args: [ + { + id: 'command', + type: 'commandAlias', + match: 'phrase', + prompt: { + start: 'What command would you like to enable/disable?', + retry: '{error} Pick a valid command.', + optional: false + } + }, + { + id: 'global', + match: 'flag', + flag: '--global' + } + ], + slash: true, + slashOptions: [ + { + name: 'action', + description: 'Would you like to disable or enable a command?', + type: 'STRING', + choices: [ + { + name: 'enable', + value: 'enable' + }, + { + name: 'disable', + value: 'disable' + } + ], + required: true + }, + { + name: 'command', + description: 'What command would you like to enable/disable?', + type: 'STRING', + required: true + } + ], + channel: 'guild', + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD'] + }); + } + + blacklistedCommands = ['eval', 'disable']; + + public async exec( + message: BushMessage | BushSlashMessage, + args: { action: 'enable' | 'disable'; command: BushCommand | string; global: boolean } + ): Promise<unknown> { + let action: 'disable' | 'enable' | 'toggle' = + args.action ?? (message?.util?.parsed?.alias as 'disable' | 'enable') ?? 'toggle'; + const global = args.global && message.author.isOwner(); + const commandID = (args.command as BushCommand).id; + + if (global) { + if (action === 'toggle') { + const disabledCommands = (await Global.findByPk(this.client.config.dev ? 'development' : 'production')) + .disabledCommands; + action = disabledCommands.includes(commandID) ? 'disable' : 'enable'; + } + const success = await this.client.util + .insertOrRemoveFromGlobal(action === 'disable' ? 'remove' : 'add', 'disabledCommands', commandID) + .catch(() => false); + if (!success) + return await message.util.reply({ + content: `${this.client.util.emojis.error} There was an error globally **${action.substr( + 0, + action.length - 2 + )}ing** the **${commandID}** command.`, + allowedMentions: AllowedMentions.none() + }); + else + return await message.util.reply({ + content: `${this.client.util.emojis.success} Successfully **${action.substr( + 0, + action.length - 2 + )}ed** the **${commandID}** command globally.`, + allowedMentions: AllowedMentions.none() + }); + + // guild disable + } else { + const disabledCommands = await message.guild.getSetting('disabledCommands'); + if (action === 'toggle') { + action = disabledCommands.includes(commandID) ? 'disable' : 'enable'; + } + const newValue = this.client.util.addOrRemoveFromArray( + action === 'disable' ? 'remove' : 'add', + disabledCommands, + commandID + ); + const success = await message.guild.setSetting('disabledCommands', newValue).catch(() => false); + if (!success) + return await message.util.reply({ + content: `${this.client.util.emojis.error} There was an error **${action.substr( + 0, + action.length - 2 + )}ing** the **${commandID}** command.`, + allowedMentions: AllowedMentions.none() + }); + else + return await message.util.reply({ + content: `${this.client.util.emojis.success} Successfully **${action.substr( + 0, + action.length - 2 + )}ed** the **${commandID}** command.`, + allowedMentions: AllowedMentions.none() + }); + } + } +} diff --git a/src/commands/config/prefix.ts b/src/commands/config/prefix.ts index 79956be..380442b 100644 --- a/src/commands/config/prefix.ts +++ b/src/commands/config/prefix.ts @@ -1,4 +1,4 @@ -import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; +import { AllowedMentions, BushCommand, BushMessage, BushSlashMessage } from '@lib'; export default class PrefixCommand extends BushCommand { public constructor() { @@ -40,15 +40,17 @@ export default class PrefixCommand extends BushCommand { const oldPrefix = await 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 - }\`.` - ); + return await message.util.send({ + content: `${this.client.util.emojis.success} changed the server's prefix ${ + oldPrefix ? `from \`${oldPrefix}\`` : '' + } to \`${args.prefix}\`.`, + allowedMentions: AllowedMentions.none() + }); } else { - return await message.util.send( - `${this.client.util.emojis.success} reset the server's prefix to \`${this.client.config.prefix}\`.` - ); + return await message.util.send({ + content: `${this.client.util.emojis.success} reset the server's prefix to \`${this.client.config.prefix}\`.`, + allowedMentions: AllowedMentions.none() + }); } } } diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts new file mode 100644 index 0000000..ffc67ae --- /dev/null +++ b/src/commands/dev/__template.ts @@ -0,0 +1,61 @@ +import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; + +export default class TemplateCommand extends BushCommand { + public constructor() { + super('template', { + aliases: ['template'], + category: 'template', + description: { + content: 'Command description.', + usage: 'template <requiredArg> [optionalArg]', + examples: ['template 1 2'] + }, + args: [ + { + id: 'required_argument', + type: 'string', + match: 'phrase', + prompt: { + start: 'What would you like to set your first argument to be?', + retry: '{error} Pick a valid argument.', + optional: false + } + }, + { + id: 'optional_argument', + type: 'string', + match: 'phrase', + prompt: { + start: 'What would you like to set your second argument to be?', + retry: '{error} Pick a valid argument.', + optional: true + } + } + ], + slash: false, //set this to true + slashOptions: [ + { + name: 'required_argument', + description: 'What would you like to set your first argument to be?', + type: 'STRING', + required: true + }, + { + name: 'optional_argument', + description: 'What would you like to set your second argument to be?', + type: 'STRING', + required: false + } + ], + superUserOnly: true, + ownerOnly: true, + channel: 'guild', + hidden: true, + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES'] + }); + } + public async exec(message: BushMessage | BushSlashMessage): Promise<unknown> { + return await message.util.reply(`${this.client.util.emojis.error} Do not use the template command.`); + } +} diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index f3a30ab..76a78ba 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -20,7 +20,7 @@ export default class EvalCommand extends BushCommand { aliases: ['eval', 'ev'], category: 'dev', description: { - content: 'Use the command to eval stuff in the bot.', + content: 'Evaluate code.', usage: 'eval [--depth #] <code> [--sudo] [--silent] [--delete] [--proto] [--hidden] [--ts]', examples: ['eval message.guild.name', 'eval this.client.ownerID'] }, @@ -72,7 +72,6 @@ export default class EvalCommand extends BushCommand { } } ], - ownerOnly: true, slash: true, slashOptions: [ { @@ -117,7 +116,8 @@ export default class EvalCommand extends BushCommand { type: 'BOOLEAN', required: false } - ] + ], + ownerOnly: true }); } @@ -141,8 +141,8 @@ export default class EvalCommand extends BushCommand { } const code: { js?: string | null; ts?: string | null; lang?: 'js' | 'ts' } = {}; args.code = args.code.replace(/[“”]/g, '"'); - args.code = args.code.replace(/```/g, ''); - if (args.typescript) { + args.code = args.code.replace(/```*(?:js|ts)?/g, ''); + if (args.typescript || message) { code.ts = args.code; code.js = transpile(args.code); code.lang = 'ts'; diff --git a/src/commands/dev/servers.ts b/src/commands/dev/servers.ts new file mode 100644 index 0000000..08f74e8 --- /dev/null +++ b/src/commands/dev/servers.ts @@ -0,0 +1,48 @@ +import { Guild, MessageEmbed } from 'discord.js'; +import { BushCommand, BushMessage, BushSlashMessage } from '../../lib'; + +export default class ServersCommand extends BushCommand { + public constructor() { + super('servers', { + aliases: ['servers'], + category: 'dev', + description: { + content: 'Displays all the severs the bot is in', + usage: 'servers', + examples: ['servers'] + }, + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES'], + superUserOnly: true + }); + } + + public async exec(message: BushMessage | BushSlashMessage): Promise<unknown> { + const maxLength = 10; + const guilds = this.client.guilds.cache.sort((a, b) => (a.memberCount < b.memberCount ? 1 : -1)).array(); + const chunkedGuilds: Guild[][] = []; + const embeds: MessageEmbed[] = []; + + for (let i = 0, j = guilds.length; i < j; i += maxLength) { + chunkedGuilds.push(guilds.slice(i, i + maxLength)); + } + + chunkedGuilds.forEach((c: Guild[]) => { + const embed = new MessageEmbed(); + c.forEach((g: Guild) => { + const owner = this.client.users.cache.get(g.ownerId)?.tag; + embed + .addField( + `**${g.name}**`, + `**ID:** ${g.id}\n**Owner:** ${owner ? owner : g.ownerId}\n**Members:** ${g.memberCount.toLocaleString()}`, + false + ) + .setTitle('Server List') + .setColor(this.client.util.colors.default); + }); + embeds.push(embed); + }); + + return await this.client.util.buttonPaginate(message, embeds); + } +} diff --git a/src/commands/dev/setLevel.ts b/src/commands/dev/setLevel.ts index f2ae6c7..4ec4c08 100644 --- a/src/commands/dev/setLevel.ts +++ b/src/commands/dev/setLevel.ts @@ -54,10 +54,12 @@ export default class SetLevelCommand extends BushCommand { const [levelEntry] = await Level.findOrBuild({ where: { - id: user.id + user: user.id, + guild: message.guild.id }, defaults: { - id |
