diff options
37 files changed, 283 insertions, 137 deletions
diff --git a/package.json b/package.json index ab53e62..41b4630 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "chalk": "^4.1.1", "common-tags": "^1.8.0", "discord-akairo": "NotEnoughUpdates/discord-akairo", - "discord-api-types": "0.19.0", + "discord-api-types": "0.20.2", "discord.js": "NotEnoughUpdates/discord.js", "discord.js-minesweeper": "^1.0.6", "fuse.js": "^6.4.6", diff --git a/src/arguments/duration.ts b/src/arguments/duration.ts index 53b200e..ce181e8 100644 --- a/src/arguments/duration.ts +++ b/src/arguments/duration.ts @@ -1,18 +1,5 @@ import { BushArgumentTypeCaster, BushMessage } from '@lib'; export const durationTypeCaster: BushArgumentTypeCaster = (_message: BushMessage, phrase): number => { - // if (!phrase) return null; - // const regexString = Object.entries(BushConstants.TimeUnits) - // .map(([name, { label }]) => String.raw`(?:(?<${name}>-?(?:\d+)?\.?\d+) *${label})?`) - // .join('\\s*'); - // const match = new RegExp(`^${regexString}$`, 'im').exec(phrase); - // if (!match) return null; - // let milliseconds = 0; - // for (const key in match.groups) { - // const value = Number(match.groups[key] || 0); - // milliseconds += value * BushConstants.TimeUnits[key].value; - // } - // return milliseconds; - return client.util.parseDuration(phrase).duration; }; diff --git a/src/arguments/permission.ts b/src/arguments/permission.ts new file mode 100644 index 0000000..dc90f3a --- /dev/null +++ b/src/arguments/permission.ts @@ -0,0 +1,12 @@ +import { Permissions } from 'discord.js'; +import { BushArgumentTypeCaster } from '../lib/extensions/discord-akairo/BushArgumentTypeCaster'; + +export const permissionTypeCaster: BushArgumentTypeCaster = (_, phrase) => { + if (!phrase) return null; + phrase = phrase.toUpperCase().replace(/ /g, '_'); + if (!Permissions.FLAGS[phrase]) { + return null; + } else { + return phrase; + } +}; diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts index 08d0068..1cc44ca 100644 --- a/src/commands/admin/channelPermissions.ts +++ b/src/commands/admin/channelPermissions.ts @@ -1,4 +1,3 @@ -import { Argument, Constants } from 'discord-akairo'; import { GuildChannel, GuildMember, MessageEmbed, Role } from 'discord.js'; import { BushCommand, BushMessage } from '../../lib'; @@ -16,8 +15,7 @@ export default class ChannelPermissionsCommand extends BushCommand { args: [ { id: 'target', - type: Argument.union(Constants.ArgumentTypes.ROLE, Constants.ArgumentTypes.MEMBER), - match: Constants.ArgumentMatches.PHRASE, + customType: util.arg.union('member', 'member'), prompt: { start: 'What user/role would you like to change?', retry: 'Invalid response. What user/role would you like to change?' @@ -26,7 +24,6 @@ export default class ChannelPermissionsCommand extends BushCommand { { id: 'permission', type: 'permission', - match: Constants.ArgumentMatches.PHRASE, prompt: { start: 'What permission would you like to change?', retry: '{error} Choose a valid permission.' @@ -34,12 +31,11 @@ export default class ChannelPermissionsCommand extends BushCommand { }, { id: 'state', - type: [ + customType: [ ['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`.' diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts index 8093d83..150a1b7 100644 --- a/src/commands/config/blacklist.ts +++ b/src/commands/config/blacklist.ts @@ -15,8 +15,8 @@ export default class BlacklistCommand extends BushCommand { args: [ { id: 'target', - type: Argument.union('channel', 'user'), - match: 'phrase', + customType: Argument.union('channel', 'user'), + prompt: { start: 'What channel or user that you would like to blacklist/unblacklist?', retry: '{error} Pick a valid command.', diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts index 41ca8a4..5d2e4dd 100644 --- a/src/commands/config/disable.ts +++ b/src/commands/config/disable.ts @@ -1,5 +1,4 @@ import { AllowedMentions, BushCommand, BushMessage, BushSlashMessage, Global } from '@lib'; -import { Argument } from 'discord-akairo'; export default class DisableCommand extends BushCommand { public constructor() { @@ -14,8 +13,7 @@ export default class DisableCommand extends BushCommand { args: [ { id: 'command', - type: Argument.union('commandAlias', 'command'), - match: 'phrase', + customType: util.arg.union('commandAlias', 'command'), prompt: { start: 'What command would you like to enable/disable?', retry: '{error} Pick a valid command.', diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts index 1e65457..35c57db 100644 --- a/src/commands/dev/__template.ts +++ b/src/commands/dev/__template.ts @@ -14,7 +14,7 @@ export default class TemplateCommand extends BushCommand { { 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.', @@ -24,7 +24,7 @@ export default class TemplateCommand extends BushCommand { { 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.', diff --git a/src/commands/dev/sh.ts b/src/commands/dev/sh.ts index ed1dfd7..b8c8379 100644 --- a/src/commands/dev/sh.ts +++ b/src/commands/dev/sh.ts @@ -1,7 +1,6 @@ import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; import chalk from 'chalk'; import { exec } from 'child_process'; -import { Constants } from 'discord-akairo'; import { MessageEmbed, Util } from 'discord.js'; import { promisify } from 'util'; @@ -25,8 +24,8 @@ export default class ShCommand extends BushCommand { args: [ { id: 'command', - type: Constants.ArgumentTypes.STRING, - match: Constants.ArgumentMatches.REST, + type: 'string', + match: 'rest', prompt: { start: 'What would you like run', retry: '{error} Invalid command to run.' diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts index 9071a8d..eade861 100644 --- a/src/commands/dev/superUser.ts +++ b/src/commands/dev/superUser.ts @@ -1,5 +1,4 @@ import { BushCommand, BushMessage, BushSlashMessage, Global } from '@lib'; -import { Constants } from 'discord-akairo'; import { User } from 'discord.js'; export default class SuperUserCommand extends BushCommand { @@ -20,7 +19,6 @@ export default class SuperUserCommand extends BushCommand { const action = yield { id: 'action', type: ['add', 'remove'], - match: Constants.ArgumentMatches.PHRASE, prompt: { start: 'Would you like to `add` or `remove` a user from the superuser list?', retry: '{error} Choose if you would like to `add` or `remove` a user.', @@ -29,8 +27,8 @@ export default class SuperUserCommand extends BushCommand { }; const user = yield { id: 'user', - type: Constants.ArgumentTypes.USER, - match: Constants.ArgumentMatches.REST_CONTENT, + type: 'user', + match: 'restContent', prompt: { start: `Who would you like to ${action || 'add/remove'} from the superuser list?`, retry: `Choose a valid user to ${action || 'add/remove'} from the superuser list.`, diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index 3a27be0..6b49dce 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { BushCommand, BushMessage } from '@lib'; -import { Constants } from 'discord-akairo'; import { Constants as jsConstants, MessageActionRow, MessageButton, MessageEmbed } from 'discord.js'; export default class TestCommand extends BushCommand { @@ -18,8 +17,8 @@ export default class TestCommand extends BushCommand { args: [ { id: 'feature', - type: Constants.ArgumentTypes.STRING, - match: Constants.ArgumentMatches.REST, + type: 'string', + match: 'rest', prompt: { start: 'start prompt', retry: 'retry prompt', diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts index 4f7449b..eefdc02 100644 --- a/src/commands/info/avatar.ts +++ b/src/commands/info/avatar.ts @@ -1,4 +1,3 @@ -import { Constants } from 'discord-akairo'; import { MessageEmbed, User } from 'discord.js'; import { BushCommand, BushMessage, BushSlashMessage } from '../../lib'; @@ -15,8 +14,7 @@ export default class AvatarCommand extends BushCommand { args: [ { id: 'user', - type: Constants.ArgumentTypes.USER, - match: Constants.ArgumentMatches.PHRASE, + type: 'user', prompt: { start: 'Who would you like to see the avatar of?', retry: '{error} Choose a valid user.', diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts index 61790ad..e995d79 100644 --- a/src/commands/info/color.ts +++ b/src/commands/info/color.ts @@ -24,7 +24,7 @@ export default class ColorCommand extends BushCommand { args: [ { id: 'color', - type: Argument.union(isValidTinyColor, 'role', 'member'), + customType: Argument.union(isValidTinyColor, 'role', 'member'), prompt: { start: 'What color code, role, or user would you like to find the color of?', retry: '{error} Choose a valid color, role, or member.' diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index 577086b..6ce4d76 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -1,4 +1,3 @@ -import { Argument, Constants } from 'discord-akairo'; import { BaseGuildVoiceChannel, Guild, GuildPreview, MessageEmbed, Snowflake, Vanity } from 'discord.js'; import { BushCommand, BushMessage, BushSlashMessage } from '../../lib'; @@ -15,8 +14,7 @@ export default class GuildInfoCommand extends BushCommand { args: [ { id: 'guild', - type: Argument.union(Constants.ArgumentTypes.GUILD, Constants.ArgumentTypes.BIGINT), - match: Constants.ArgumentMatches.PHRASE, + customType: util.arg.union('guild', 'bigint'), prompt: { start: 'What server would you like to find information about?', retry: '{error} Choose a valid server to find information about.', diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts index e36e92b..cecf5ec 100644 --- a/src/commands/info/userInfo.ts +++ b/src/commands/info/userInfo.ts @@ -1,7 +1,7 @@ import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; import { GuildMember, MessageEmbed } from 'discord.js'; -// TODO: Allow looking up a user not in the guild and not cached +// TODO: Allow looking up a user not in the guild and not cached (if possible) // TODO: Re-Implement Status Emojis // TODO: Add bot information export default class UserInfoCommand extends BushCommand { diff --git a/src/commands/moderation/_lockdown.ts b/src/commands/moderation/_lockdown.ts index db074b1..df5a9b4 100644 --- a/src/commands/moderation/_lockdown.ts +++ b/src/commands/moderation/_lockdown.ts @@ -13,7 +13,7 @@ export default class LockdownCommand extends BushCommand { args: [ { id: 'all', - type: 'flag', + match: 'flag', flag: '--all' } ], diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index 3736165..9239f2a 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -10,7 +10,7 @@ export default class BanCommand extends BushCommand { description: { content: 'Ban a member from the server.', usage: 'ban <member> <reason> [--delete ]', - examples: ['ban 322862723090219008 1 day commands in #general --delete 7'] + examples: ['ban ironm00n 1 day commands in #general --delete 7'] }, args: [ { @@ -35,7 +35,7 @@ export default class BanCommand extends BushCommand { id: 'days', flag: '--days', match: 'option', - type: Argument.range('integer', 0, 7, true), + customType: util.arg.range('integer', 0, 7, true), default: 0 }, { diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts index c55b9a3..4850a4d 100644 --- a/src/commands/moderation/modlog.ts +++ b/src/commands/moderation/modlog.ts @@ -1,5 +1,4 @@ import { BushCommand, BushMessage, BushSlashMessage, BushUser, ModLog } from '@lib'; -import { Argument } from 'discord-akairo'; import { MessageEmbed, User } from 'discord.js'; export default class ModlogCommand extends BushCommand { @@ -15,7 +14,7 @@ export default class ModlogCommand extends BushCommand { args: [ { id: 'search', - type: Argument.union('user', 'string'), + customType: util.arg.union('user', 'string'), prompt: { start: 'What case id or user would you like to see?', retry: '{error} Choose a valid case id or user.' diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts index 31cd233..7f3edbb 100644 --- a/src/commands/moderation/mute.ts +++ b/src/commands/moderation/mute.ts @@ -9,7 +9,7 @@ export default class MuteCommand extends BushCommand { description: { content: 'Mute a user.', usage: 'mute <member> [reason] [duration]', - examples: ['mute 322862723090219008 1 day commands in #general'] + examples: ['mute ironm00n 1 day commands in #general'] }, args: [ { diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts index cb1be04..de5e8ce 100644 --- a/src/commands/moderation/removeReactionEmoji.ts +++ b/src/commands/moderation/removeReactionEmoji.ts @@ -1,5 +1,4 @@ import { BushCommand, BushMessage } from '@lib'; -import { Argument } from 'discord-akairo'; import { Emoji } from 'discord.js'; export default class RemoveReactionEmojiCommand extends BushCommand { @@ -25,7 +24,7 @@ export default class RemoveReactionEmojiCommand extends BushCommand { }, { id: 'emoji', - type: Argument.union('emoji', 'bigint'), + customType: util.arg.union('emoji', 'bigint'), match: 'restContent', prompt: { start: 'What emoji would you like to remove?', diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index fe8724d..bd8cf8d 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -14,7 +14,7 @@ export default class RoleCommand extends BushCommand { args: [ { id: 'action', - type: [['add'], ['remove']], + customType: [['add'], ['remove']], prompt: { start: 'Would you like to `add` or `remove` a role?', retry: '{error} Choose whether you would you like to `add` or `remove` a role.' diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts index 9b0d300..441a0ac 100644 --- a/src/commands/moderation/slowmode.ts +++ b/src/commands/moderation/slowmode.ts @@ -15,7 +15,7 @@ export default class SlowModeCommand extends BushCommand { args: [ { id: 'length', - type: Argument.union('duration', 'off', 'none', 'disable'), + customType: Argument.union('duration', 'off', 'none', 'disable'), default: 0, prompt: { start: 'What would you like to set the slowmode to?', diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts index c5b4f43..3f9e9b5 100644 --- a/src/commands/moderation/warn.ts +++ b/src/commands/moderation/warn.ts @@ -21,7 +21,6 @@ export default class WarnCommand extends BushCommand { }, { id: 'reason', - type: 'content', match: 'rest', prompt: { start: 'Why should this user be warned?', diff --git a/src/commands/moulberry-bush/capePerms.ts b/src/commands/moulberry-bush/capePerms.ts index d613217..7a021ed 100644 --- a/src/commands/moulberry-bush/capePerms.ts +++ b/src/commands/moulberry-bush/capePerms.ts @@ -1,5 +1,4 @@ import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; -import { Constants } from 'discord-akairo'; import { MessageEmbed } from 'discord.js'; import got from 'got'; @@ -16,8 +15,7 @@ export default class CapePermissionsCommand extends BushCommand { args: [ { id: 'ign', - type: Constants.ArgumentTypes.STRING, - match: Constants.ArgumentMatches.PHRASE, + type: 'string', prompt: { start: 'Who would you like to see the cape permissions of?', retry: '{error} Choose someone to see the capes their available capes.', diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts index 4c6adc1..2ee02bd 100644 --- a/src/commands/moulberry-bush/report.ts +++ b/src/commands/moulberry-bush/report.ts @@ -1,4 +1,3 @@ -import { Constants } from 'discord-akairo'; import { GuildMember, MessageEmbed, TextChannel } from 'discord.js'; import moment from 'moment'; import { AllowedMentions, BushCommand, BushMessage } from '../../lib'; @@ -16,8 +15,7 @@ export default class ReportCommand extends BushCommand { args: [ { id: 'member', - type: Constants.ArgumentTypes.MEMBER, - match: Constants.ArgumentMatches.PHRASE, + type: 'member', prompt: { start: 'Who would you like to report?', retry: `{error} Choose a valid user to report.`, @@ -26,8 +24,8 @@ export default class ReportCommand extends BushCommand { }, { id: 'evidence', - type: Constants.ArgumentTypes.STRING, - match: Constants.ArgumentMatches.REST, + type: 'string', + match: 'rest', prompt: { start: 'What evidence do you have?', retry: `{error} Provide what did they do wrong.`, diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts index 1681a1b..41dd8de 100644 --- a/src/commands/moulberry-bush/rule.ts +++ b/src/commands/moulberry-bush/rule.ts @@ -1,4 +1,3 @@ -import { Argument, Constants } from 'discord-akairo'; import { MessageEmbed, User } from 'discord.js'; import { AllowedMentions, BushCommand, BushMessage } from '../../lib'; @@ -65,8 +64,7 @@ export default class RuleCommand extends BushCommand { args: [ { id: 'rule', - type: Argument.range(Constants.ArgumentTypes.INTEGER, 1, rules.length, true), - match: Constants.ArgumentMatches.PHRASE, + customType: util.arg.range('integer', 1, rules.length, true), prompt: { start: 'What rule would you like to have cited?', retry: '{error} Choose a valid rule.', @@ -76,7 +74,6 @@ export default class RuleCommand extends BushCommand { { id: 'user', type: 'user', - match: Constants.ArgumentMatches.PHRASE, prompt: { start: 'What user would you like to mention?', retry: '{error} Choose a valid user to mention.', diff --git a/src/commands/skyblock-reborn/chooseColor.ts b/src/commands/skyblock-reborn/chooseColor.ts index 2b72301..9b4b7c9 100644 --- a/src/commands/skyblock-reborn/chooseColor.ts +++ b/src/commands/skyblock-reborn/chooseColor.ts @@ -1,5 +1,4 @@ import { AllowedMentions, BushCommand, BushGuildMember, BushMessage, BushSlashMessage } from '@lib'; -import { Constants } from 'discord-akairo'; import { CommandInteraction, Role, RoleResolvable, Snowflake } from 'discord.js'; const roleColorMap = [ @@ -94,7 +93,7 @@ export default class ChooseColorCommand extends BushCommand { { id: 'color', type: 'role', - match: Constants.ArgumentMatches.REST, + match: 'rest', prompt: { start: 'Please choose a valid color.', retry: `{error} Provide what did they do wrong.`, diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts index aa3d455..cab23d8 100644 --- a/src/commands/utilities/decode.ts +++ b/src/commands/utilities/decode.ts @@ -18,7 +18,7 @@ export default class DecodeCommand extends BushCommand { args: [ { id: 'from', - type: encodingTypesArray, + customType: encodingTypesArray, prompt: { start: 'What is the encoding of the original data?', retry: `{error} Choose one of the following ${encodingTypesString} for the encoding of the original data.` @@ -26,7 +26,7 @@ export default class DecodeCommand extends BushCommand { }, { id: 'to', - type: encodingTypesArray, + customType: encodingTypesArray, prompt: { start: '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.` diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts index 4b5b01c..fcf2da3 100644 --- a/src/commands/utilities/hash.ts +++ b/src/commands/utilities/hash.ts @@ -1,5 +1,4 @@ import crypto from 'crypto'; -import { Constants } from 'discord-akairo'; import got from 'got'; import { BushCommand, BushMessage } from '../../lib'; @@ -16,8 +15,7 @@ export default class HashCommand extends BushCommand { args: [ { id: 'url', - type: Constants.ArgumentTypes.URL, - match: Constants.ArgumentMatches.PHRASE, + type: 'url', prompt: { start: 'What url would you like to find the hash of?', retry: '{error} Enter a valid url.' diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts index d04544b..38cd8ca 100644 --- a/src/commands/utilities/price.ts +++ b/src/commands/utilities/price.ts @@ -1,4 +1,3 @@ -import { Constants } from 'discord-akairo'; import { MessageEmbed } from 'discord.js'; import Fuse from 'fuse.js'; import fetch from 'node-fetch'; @@ -66,8 +65,8 @@ export default class PriceCommand extends BushCommand { args: [ { id: 'item', - match: Constants.ArgumentMatches.CONTENT, - type: Constants.ArgumentTypes.STRING, + type: 'string', + match: 'content', prompt: { start: 'What item would you like to find the price of?', retry: '{error} Choose a valid item.' @@ -75,7 +74,7 @@ export default class PriceCommand extends BushCommand { }, { id: 'strict', - match: Constants.ArgumentMatches.FLAG, + match: 'flag', flag: '--strict', default: false } diff --git a/src/commands/utilities/uuid.ts b/src/commands/utilities/uuid.ts index 7ff80d2..02ca506 100644 --- a/src/commands/utilities/uuid.ts +++ b/src/commands/utilities/uuid.ts @@ -1,4 +1,3 @@ -import { Constants } from 'discord-akairo'; import { BushCommand, BushMessage } from '../../lib'; export default class UuidCommand extends BushCommand { @@ -14,8 +13,8 @@ export default class UuidCommand extends BushCommand { args: [ { id: 'ign', - type: /\w{1,16}/im, - match: Constants.ArgumentMatches.PHRASE, + customType: /\w{1,16}/im, + prompt: { start: 'What ign would you like to find the uuid of?', retry: '{error} Choose a valid ign.', diff --git a/src/commands/utilities/viewraw.ts b/src/commands/utilities/viewraw.ts index ca5b2de..ca21b4b 100644 --- a/src/commands/utilities/viewraw.ts +++ b/src/commands/utilities/viewraw.ts @@ -1,4 +1,3 @@ -import { Argument, Constants } from 'discord-akairo'; import { DMChannel, Message, MessageEmbed, NewsChannel, Snowflake, TextChannel } from 'discord.js'; import { inspect } from 'util'; import { BushCommand, BushMessage, BushSlashMessage } from '../../lib'; @@ -17,8 +16,8 @@ export default class ViewRawCommand extends BushCommand { args: [ { id: 'message', - type: Argument.union(Constants.ArgumentTypes.MESSAGE, Constants.ArgumentTypes.BIGINT), - match: Constants.ArgumentMatches.PHRASE, + customType: util.arg.union('message', 'bigint'), + prompt: { start: 'What message would you like to view?', retry: '{error} Choose a valid message.', @@ -27,8 +26,7 @@ export default class ViewRawCommand extends BushCommand { }, { id: 'channel', - type: Constants.ArgumentTypes.CHANNEL, - match: Constants.ArgumentMatches.PHRASE, + type: 'channel', prompt: { start: 'What channel is the message in?', retry: '{error} Choose a valid channel.', @@ -38,7 +36,7 @@ export default class ViewRawCommand extends BushCommand { }, { id: 'json', - match: Constants.ArgumentMatches.FLAG, + match: 'flag', flag: '--json' } ] diff --git a/src/lib/badwords.json b/src/lib/badwords.json index 94c854f..6ea3618 100644 --- a/src/lib/badwords.json +++ b/src/lib/badwords.json @@ -11,5 +11,6 @@ "hi, bro h am leaving cs:go and giving away my skin": 3, "hi friend, today i am leaving this fucking game": 3, "hi guys, i'm leaving this fucking game, take my": 3, - "you can choose any skin for yourself": 3 + "you can choose any skin for yourself": 3, + "ironmoon": 1 } diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts index 54b5250..7b270f6 100644 --- a/src/lib/extensions/discord-akairo/BushClient.ts +++ b/src/lib/extensions/discord-akairo/BushClient.ts @@ -20,6 +20,7 @@ import readline from 'readline'; import { Sequelize } from 'sequelize'; import { contentWithDurationTypeCaster } from '../../../arguments/contentWithDuration'; import { durationTypeCaster } from '../../../arguments/duration'; +import { permissionTypeCaster } from '../../../arguments/permission'; import { UpdateCacheTask } from '../../../tasks/updateCache'; import { ActivePunishment } from '../../models/ActivePunishment'; import { Global } from '../../models/Global'; @@ -228,7 +229,8 @@ export class BushClient extends AkairoClient { }); this.commandHandler.resolver.addTypes({ duration: durationTypeCaster, - contentWithDuration: contentWithDurationTypeCaster + contentWithDuration: contentWithDurationTypeCaster, + permission: permissionTypeCaster }); // loads all the handlers const loaders = { diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index b6c9c1f..aecc635 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { + BushArgumentType, BushCache, BushClient, BushConstants, @@ -16,7 +17,7 @@ import { ModLogType } from '@lib'; import { exec } from 'child_process'; -import { ClientUtil } from 'discord-akairo'; +import { Argument, ArgumentTypeCaster, ClientUtil, Flag, ParsedValuePredicate, TypeResolver } from 'discord-akairo'; import { APIMessage } from 'discord-api-types'; import { ButtonInteraction, @@ -796,4 +797,121 @@ export class BushClientUtil extends ClientUtil { public capitalizeFirstLetter(string: string): string { return string.charAt(0)?.toUpperCase() + string.slice(1); } + + public arg = new (class Arg { + /** + * Casts a phrase to this argument's type. + * @param type - The type to cast to. + * @param resolver - The type resolver. + * @param message - Message that called the command. + * @param phrase - Phrase to process. + */ + public cast(type: BushArgumentType, resolver: TypeResolver, message: Message, phrase: string): Promise<any> { + return Argument.cast(type, resolver, message, phrase); + } + + /** + * Creates a type that is the left-to-right composition of the given types. + * If any of the types fails, the entire composition fails. + * @param types - Types to use. + */ + public compose(...types: BushArgumentType[]): ArgumentTypeCaster { + return Argument.compose(types); + } + + /** + * Creates a type that is the left-to-right composition of the given types. + * If any of the types fails, the composition still continues with the failure passed on. + * @param types - Types to use. + */ + public composeWithFailure(...types: BushArgumentType[]): ArgumentTypeCaster { + return Argument.composeWithFailure(types); + } + + /** + * Checks if something is null, undefined, or a fail flag. + * @param value - Value to check. + */ + public isFailure(value: any): value is null | undefined | (Flag & { value: any }) { + return Argument.isFailure(value); + } + + /** + * Creates a type from multiple types (product type). + * Only inputs where each type resolves with a non-void value are valid. + * @param types - Types to use. + */ + public product(...types: BushArgumentType[]): ArgumentTypeCaster { + return Argument.product(types); + } + + /** + * Creates a type where the parsed value must be within a range. + * @param type - The type to use. + * @param min - Minimum value. + * @param max - Maximum value. + * @param inclusive - Whether or not to be inclusive on the upper bound. + */ + public range(type: BushArgumentType, min: number, max: number, inclusive?: boolean): ArgumentTypeCaster { + return Argument.range(type, min, max, inclusive); + } + + /** + * Creates a type that parses as normal but also tags it with some data. + * Result is in an object `{ tag, value }` and wrapped in `Flag.fail` when failed. + * @param type - The type to use. + * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string. + */ + public tagged(type: BushArgumentType, tag?: any): ArgumentTypeCaster { + return Argument.tagged(type, tag); + } + + /** + * Creates a type from multiple types (union type). + * The first type that resolves to a non-void value is used. + * Each type will also be tagged using `tagged` with themselves. + * @param types - Types to use. + */ + public taggedUnion(...types: BushArgumentType[]): ArgumentTypeCaster { + return Argument.taggedUnion(types); + } + + /** + * Creates a type that parses as normal but also tags it with some data and carries the original input. + * Result is in an object `{ tag, input, value }` and wrapped in `Flag.fail` when failed. + * @param type - The type to use. + * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string. + */ + public taggedWithInput(type: BushArgumentType, tag?: any): ArgumentTypeCaster { + return Argument.taggedWithInput(type, tag); + } + + /** + * Creates a type from multiple types (union type). + * The first type that resolves to a non-void value is used. + * @param types - Types to use. + */ + public union(...types: BushArgumentType[]): ArgumentTypeCaster { + return Argument.union(types); + } + + /** + * Creates a type with extra validation. + * If the predicate is not true, the value is considered invalid. + * @param type - The type to use. + * @param predicate - The predicate function. + */ + public validate(type: BushArgumentType, predicate: ParsedValuePredicate): ArgumentTypeCaster { + return Argument.validate(type, predicate); + } + + /** + * Creates a type that parses as normal but also carries the original input. + * Result is in an object `{ input, value }` and wrapped in `Flag.fail` when failed. + * @param type - The type to use. + */ + public withInput(type: BushArgumentType): ArgumentTypeCaster { + return Argument.withInput(type); + } + })(); } diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts index 3f79aeb..6616d1d 100644 --- a/src/lib/extensions/discord-akairo/BushCommand.ts +++ b/src/lib/extensions/discord-akairo/BushCommand.ts @@ -1,20 +1,13 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - ArgumentGenerator, - ArgumentOptions, - ArgumentPromptOptions, - ArgumentTypeCaster, - Command, - CommandOptions -} from 'discord-akairo'; +import { ArgumentOptions, ArgumentPromptOptions, ArgumentTypeCaster, Command, CommandOptions } from 'discord-akairo'; import { Snowflake } from 'discord.js'; import { BushMessage } from '../discord.js/BushMessage'; import { BushClient } from './BushClient'; import { BushCommandHandler } from './BushCommandHandler'; import { BushSlashMessage } from './BushSlashMessage'; -type BushArgumentType = +export type BushArgumentType = | 'string' | 'lowercase' | 'uppercase' @@ -67,17 +60,74 @@ type BushArgumentType = | 'command' | 'inhibitor' | 'listener' - | 'duration'; - -interface BaseBushArgumentOptions extends ArgumentOptions { + | 'duration' + | 'contentWithDuration' + | 'permission'; +interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type'> { id: string; description?: string; prompt?: ArgumentPromptOptions; } export interface BushArgumentOptions extends BaseBushArgumentOptions { + /** + * The type that the argument should be cast to. + * - `string` does not cast to any type. + * - `lowercase` makes the input lowercase. + * - `uppercase` makes the input uppercase. + * - `charCodes` transforms the input to an array of char codes. + * - `number` casts to a number. + * - `integer` casts to an integer. + * - `bigint` casts to a big integer. + * - `url` casts to an `URL` object. + * - `date` casts to a `Date` object. + * - `color` casts a hex code to an integer. + * - `commandAlias` tries to resolve to a command from an alias. + * - `command` matches the ID of a command. + * - `inhibitor` matches the ID of an inhibitor. + * - `listener` matches the ID of a listener. + * + * Possible Discord-related types. + * These types can be plural (add an 's' to the end) and a collection of matching objects will be used. + * - `user` tries to resolve to a user. + * - `member` tries to resolve to a member. + * - `relevant` tries to resolve to a relevant user, works in both guilds and DMs. + * - `channel` tries to resolve to a channel. + * - `textChannel` tries to resolve to a text channel. + * - `voiceChannel` tries to resolve to a voice channel. + * - `stageChannel` tries to resolve to a stage channel. + * - `threadChannel` tries to resolve a thread channel. + * - `role` tries to resolve to a role. + * - `emoji` tries to resolve to a custom emoji. + * - `guild` tries to resolve to a guild. + * - `permission` tries to resolve to a permissions. + * + * Other Discord-related types: + * - `message` tries to fetch a message from an ID within the channel. + * - `guildMessage` tries to fetch a message from an ID within the guild. + * - `relevantMessage` is a combination of the above, works in both guilds and DMs. + * - `invite` tries to fetch an invite object from a link. + * - `userMention` matches a mention of a user. + * - `memberMention` matches a mention of a guild member. + * - `channelMention` matches a mention of a channel. + * - `roleMention` matches a mention of a role. + * - `emojiMention` matches a mention of an emoji. + * + * Misc: + * - `duration` tries to parse duration in milliseconds + * - `contentWithDuration` tries to parse duration in milliseconds and returns the remaining content with the duration + * removed + */ type?: BushArgumentType; } export interface CustomBushArgumentOptions extends BaseBushArgumentOptions { + /** + * An array of strings can be used to restrict input to only those strings, case insensitive. + * The array can also contain an inner array of strings, for aliases. + * If so, the first entry of the array will be used as the final argument. + * + * A regular expression can also be used. + * The evaluated argument will be an object containing the `match` and `matches` if global. + */ customType?: ArgumentTypeCaster | (string | string[])[] | RegExp | string; } @@ -90,7 +140,7 @@ export interface BushCommandOptions extends CommandOptions { usage: string | string[]; examples: string | string[]; }; - args?: BushArgumentOptions[] | CustomBushArgumentOptions[] | ArgumentGenerator; + args?: BushArgumentOptions[] & CustomBushArgumentOptions[]; category: string; completelyHide?: boolean; } @@ -124,7 +174,10 @@ export class BushCommand extends Command { this.completelyHide = options.completelyHide; if (options.args && typeof options.args !== 'function') { options.args.forEach((arg: BushArgumentOptions | CustomBushArgumentOptions) => { - if (arg['customType']) arg.type = arg['customType']; + if (arg['customType']) { + arg['type'] = arg['customType']; + delete arg['customType']; + } }); } } diff --git a/src/listeners/message/automodCreate.ts b/src/listeners/message/automodCreate.ts index 0321aca..990632b 100644 --- a/src/listeners/message/automodCreate.ts +++ b/src/listeners/message/automodCreate.ts @@ -18,34 +18,31 @@ export default class AutomodMessageCreateListener extends BushListener { } public static async automod(message: BushMessage): Promise<unknown> { - if (message.guild.id !== client.consts.mappings.guilds.bush) return; // just temporary + if (message.guild?.id !== client.consts.mappings.guilds.bush) return; // just temporary /* await message.guild.getSetting('autoModPhases'); */ const badLinks = {}; _badLinks.forEach((link) => { badLinks[link] = 3; }); - // client.console.debug(badLinks, 1); - // client.console.debug(badWords, 1); - - const wordArray = [...Object.keys(badWords), ...Object.keys(badLinks)]; + const wordMap = { ...badWords, ...badLinks }; + const wordKeys = Object.keys(wordMap); const offences: { [key: string]: number } = {}; - // client.console.debug(wordArray); - wordArray.forEach((word) => { - const cleanMessageContent = message.content?.toLowerCase().replace(/ /g, ''); + const cleanMessageContent = message.content?.toLowerCase().replace(/ /g, ''); + wordKeys.forEach((word) => { const cleanWord = word.toLowerCase().replace(/ /g, ''); - // client.console.debug(cleanMessageContent); - // client.console.debug(cleanWord); if (cleanMessageContent.includes(cleanWord)) { - if (offences[word]) offences[word] = wordArray[word]; + if (!offences[word]) offences[word] = wordMap[word]; } }); if (!Object.keys(offences)?.length) return; const highestOffence = Object.values(offences).sort((a, b) => b - a)[0]; + client.console.debug(message.deletable); + switch (highestOffence) { case 0: { if (message.deletable) void message.delete(); @@ -61,10 +61,10 @@ __metadata: languageName: node linkType: hard -"@discordjs/collection@npm:^0.1.6": - version: 0.1.6 - resolution: "@discordjs/collection@npm:0.1.6" - checksum: a0ddf757098fa01a4d9d5812daf3c2ea88c1297618d346705e603642c2f19656188fbfb3d503ee77f2ee69e7a1c1bfe25932aec032692ee3c338335524886e05 +"@discordjs/collection@npm:^0.2.0": + version: 0.2.0 + resolution: "@discordjs/collection@npm:0.2.0" + checksum: 4f9fc995ca81eb981aa9a8c081f46da831db9cea69727f3f6a6b7690c30d237eb64b758c1fc3f3510a403cb55dce8aa618133a43391f241b218ac817abe1780b languageName: node linkType: hard @@ -329,9 +329,9 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 16.4.7 - resolution: "@types/node@npm:16.4.7" - checksum: a1e80deea93f10225d1ac0825bd5eff3355dbc37084a88b0138921c9c930eb54acebb008d090a332a96d31ff50de69f2f5fc1402571070ea745f023e9f874805 + version: 16.4.8 + resolution: "@types/node@npm:16.4.8" + checksum: 1d4a421b95ac4d7671de17c56969bf95943c252c410dbe33c380e97a8afdfa7c2e5dcda0063a5c24fcc5538f40ef33c2582ae37f004c3c666da3758d8c8eecfc languageName: node linkType: hard @@ -805,7 +805,7 @@ __metadata: chalk: ^4.1.1 common-tags: ^1.8.0 discord-akairo: NotEnoughUpdates/discord-akairo - discord-api-types: 0.19.0 + discord-api-types: 0.20.2 discord.js: NotEnoughUpdates/discord.js discord.js-minesweeper: ^1.0.6 esbuild: ^0.12.11 @@ -1335,15 +1335,15 @@ __metadata: discord-akairo@NotEnoughUpdates/discord-akairo: version: 8.2.2 - resolution: "discord-akairo@https://github.com/NotEnoughUpdates/discord-akairo.git#commit=ce7f4a08d97bf28af7f35184de750b01b59dc34a" - checksum: 89a0c720a14ddb32d588f9f043bf5f38ed86793f2bed51e5173185e20fbb87d334cc3c833e1c7804473d1e81b64e6c36f69df355fffd339544a4fa849b349b12 + resolution: "discord-akairo@https://github.com/NotEnoughUpdates/discord-akairo.git#commit=c2618f883533b95741fdffc920f07728385be973" + checksum: dd754c904e6f872664a74609f0521d5949ca2503ae4dde5972808928f240b3ca981751f2d2e98c30fd6c62ce13959d633e3f7e7e02771cb05507a6cf46548ee3 languageName: node linkType: hard -"discord-api-types@npm:0.19.0, discord-api-types@npm:^0.19.0": - version: 0.19.0 - resolution: "discord-api-types@npm:0.19.0" - checksum: 83d9363772a0ac0fcfa9df61da1c510c5427c2d82cc4b1c2e0a8ab50c31b2ae297a416cd1559b21b039dcc8065e5dca962dbac12522ee5e3447e9f4ebcb8a846 +"discord-api-types@npm:0.20.2": + version: 0.20.2 + resolution: "discord-api-types@npm:0.20.2" + checksum: e0903f90b27d082159a19f32e46c84f5b2133dd2c7640edc5b0dbd169a7a8678294dbe960a150efb6dce304c7347d73982255483b1e389309e8573263485e22a languageName: node linkType: hard @@ -1354,6 +1354,13 @@ discord-akairo@NotEnoughUpdates/discord-akairo: languageName: node linkType: hard +"discord-api-types@npm:^0.21.0": + version: 0.21.0 + resolution: "discord-api-types@npm:0.21.0" + checksum: 00872f1c453964d86579e59a6aa57fc7b2025b84bf7168fb4dad1d8e218db09dc78c20758ef9e15135bbfc76c9bf51102e671c0a20530e552ad7fc6f93a971c3 + languageName: node + linkType: hard + "discord.js-minesweeper@npm:^1.0.6": version: 1.0.6 resolution: "discord.js-minesweeper@npm:1.0.6" @@ -1363,18 +1370,18 @@ discord-akairo@NotEnoughUpdates/discord-akairo: discord.js@NotEnoughUpdates/discord.js: version: 13.0.0-dev - resolution: "discord.js@https://github.com/NotEnoughUpdates/discord.js.git#commit=1ed8c6263c844719b42a821ca1f1c4081a20b68a" + resolution: "discord.js@https://github.com/NotEnoughUpdates/discord.js.git#commit=c453840a652e054e92d521106a1dec1255990511" dependencies: "@discordjs/builders": ^0.2.0 - "@discordjs/collection": ^0.1.6 + "@discordjs/collection": ^0.2.0 "@discordjs/form-data": ^3.0.1 "@sapphire/async-queue": ^1.1.4 "@types/ws": ^7.4.5 abort-controller: ^3.0.0 - discord-api-types: ^0.19.0 + discord-api-types: ^0.21.0 node-fetch: ^2.6.1 ws: ^7.5.1 - checksum: 4ea6042c37545f4048677e2fd865e76cf4718ebf404bb4f5e539e9f141978c76a402d1269618f43c879aec3b4e70fe88d1b82c43296eb6789dbee7d39f4e6d0f + checksum: 67f91118eb0d8ed90017dfb096377555c6df5bc2be1d7af70caaf02b3ddaffd10965da2454a887363e5f00a3d9c9ebb1d8a6d638c6946f7592d99dd217a50e21 languageName: node linkType: hard @@ -1557,8 +1564,8 @@ discord.js@NotEnoughUpdates/discord.js: linkType: hard "eslint@npm:^7.29.0": - version: 7.31.0 - resolution: "eslint@npm:7.31.0" + version: 7.32.0 + resolution: "eslint@npm:7.32.0" dependencies: "@babel/code-frame": 7.12.11 "@eslint/eslintrc": ^0.4.3 @@ -1602,7 +1609,7 @@ discord.js@NotEnoughUpdates/discord.js: v8-compile-cache: ^2.0.3 bin: eslint: bin/eslint.js - checksum: fd73d07ce0b73e5ea950b295a6eaf8d45914b4e56cba4ef49e55a36dc7e965a4865f63f618c0a096a01d089752d9e44180b80ba8657039b8e631dd40e0af1663 + checksum: cc85af9985a3a11085c011f3d27abe8111006d34cc274291b3c4d7bea51a4e2ff6135780249becd919ba7f6d6d1ecc38a6b73dacb6a7be08d38453b344dc8d37 languageName: node linkType: hard |