aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-11-28 09:27:41 -0500
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-11-28 09:27:41 -0500
commit453683b57b8ff013ff25e2aaa4aa1d2e047edcb7 (patch)
tree8b98d2f30dbb6a8448602446cfacf9091667cc33 /src
parentde4c3dcaf172804d34ae708be1ed3e75af42f4d5 (diff)
downloadtanzanite-453683b57b8ff013ff25e2aaa4aa1d2e047edcb7.tar.gz
tanzanite-453683b57b8ff013ff25e2aaa4aa1d2e047edcb7.tar.bz2
tanzanite-453683b57b8ff013ff25e2aaa4aa1d2e047edcb7.zip
a few small changes
Diffstat (limited to 'src')
-rw-r--r--src/arguments/messageLink.ts19
-rw-r--r--src/commands/_fake-command/ironmoon.ts4
-rw-r--r--src/commands/admin/channelPermissions.ts77
-rw-r--r--src/commands/admin/roleAll.ts38
-rw-r--r--src/commands/config/blacklist.ts62
-rw-r--r--src/commands/config/config.ts14
-rw-r--r--src/commands/config/customAutomodPhrases.ts8
-rw-r--r--src/commands/config/disable.ts134
-rw-r--r--src/commands/config/features.ts8
-rw-r--r--src/commands/config/levelRoles.ts24
-rw-r--r--src/commands/config/log.ts33
-rw-r--r--src/commands/dev/__template.ts41
-rw-r--r--src/commands/dev/dm.ts46
-rw-r--r--src/commands/dev/eval.ts103
-rw-r--r--src/commands/dev/javascript.ts30
-rw-r--r--src/commands/dev/reload.ts22
-rw-r--r--src/commands/dev/say.ts14
-rw-r--r--src/commands/dev/servers.ts10
-rw-r--r--src/commands/dev/sh.ts16
-rw-r--r--src/commands/dev/superUser.ts25
-rw-r--r--src/commands/dev/test.ts19
-rw-r--r--src/commands/fun/coinflip.ts8
-rw-r--r--src/commands/fun/dice.ts8
-rw-r--r--src/commands/fun/eightBall.ts24
-rw-r--r--src/commands/fun/minesweeper.ts74
-rw-r--r--src/commands/info/avatar.ts29
-rw-r--r--src/commands/info/botInfo.ts8
-rw-r--r--src/commands/info/color.ts38
-rw-r--r--src/commands/info/guildInfo.ts63
-rw-r--r--src/commands/info/help.ts49
-rw-r--r--src/commands/info/icon.ts8
-rw-r--r--src/commands/info/links.ts8
-rw-r--r--src/commands/info/ping.ts8
-rw-r--r--src/commands/info/pronouns.ts26
-rw-r--r--src/commands/info/snowflake.ts54
-rw-r--r--src/commands/info/userInfo.ts29
-rw-r--r--src/commands/leveling/leaderboard.ts26
-rw-r--r--src/commands/leveling/level.ts26
-rw-r--r--src/commands/leveling/setLevel.ts38
-rw-r--r--src/commands/leveling/setXp.ts40
-rw-r--r--src/commands/moderation/_lockdown.ts23
-rw-r--r--src/commands/moderation/activePunishments.ts76
-rw-r--r--src/commands/moderation/ban.ts73
-rw-r--r--src/commands/moderation/evidence.ts32
-rw-r--r--src/commands/moderation/hideCase.ts24
-rw-r--r--src/commands/moderation/kick.ts49
-rw-r--r--src/commands/moderation/modlog.ts46
-rw-r--r--src/commands/moderation/mute.ts49
-rw-r--r--src/commands/moderation/purge.ts57
-rw-r--r--src/commands/moderation/removeReactionEmoji.ts48
-rw-r--r--src/commands/moderation/role.ts123
-rw-r--r--src/commands/moderation/slowmode.ts44
-rw-r--r--src/commands/moderation/unban.ts42
-rw-r--r--src/commands/moderation/unmute.ts49
-rw-r--r--src/commands/moderation/warn.ts49
-rw-r--r--src/commands/moulberry-bush/capePerms.ts27
-rw-r--r--src/commands/moulberry-bush/capes.ts28
-rw-r--r--src/commands/moulberry-bush/giveawayPing.ts8
-rw-r--r--src/commands/moulberry-bush/moulHammer.ts22
-rw-r--r--src/commands/moulberry-bush/report.ts41
-rw-r--r--src/commands/moulberry-bush/rule.ts45
-rw-r--r--src/commands/moulberry-bush/serverStatus.ts8
-rw-r--r--src/commands/utilities/activity.ts127
-rw-r--r--src/commands/utilities/calculator.ts25
-rw-r--r--src/commands/utilities/decode.ts56
-rw-r--r--src/commands/utilities/hash.ts16
-rw-r--r--src/commands/utilities/price.ts35
-rw-r--r--src/commands/utilities/steal.ts105
-rw-r--r--src/commands/utilities/suicide.ts8
-rw-r--r--src/commands/utilities/uuid.ts39
-rw-r--r--src/commands/utilities/viewRaw.ts78
-rw-r--r--src/commands/utilities/whoHasRole.ts26
-rw-r--r--src/commands/utilities/wolframAlpha.ts37
-rw-r--r--src/lib/common/Format.ts52
-rw-r--r--src/lib/common/util/Arg.ts6
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts4
-rw-r--r--src/lib/extensions/discord-akairo/BushClientUtil.ts283
-rw-r--r--src/lib/extensions/discord-akairo/BushCommand.ts309
-rw-r--r--src/lib/extensions/discord.js/BushGuild.ts48
-rw-r--r--src/lib/extensions/global.d.ts9
-rw-r--r--src/lib/utils/BushConstants.ts399
-rw-r--r--src/lib/utils/BushLogger.ts68
-rw-r--r--src/listeners/client/ready.ts5
-rw-r--r--src/listeners/commands/commandBlocked.ts12
-rw-r--r--src/listeners/commands/messageBlocked.ts5
-rw-r--r--src/listeners/custom/bushLevelUpdate.ts8
-rw-r--r--src/listeners/guild/guildMemberAdd.ts51
-rw-r--r--src/listeners/guild/guildMemberRemove.ts14
-rw-r--r--src/listeners/other/promiseRejection.ts3
-rw-r--r--src/listeners/other/uncaughtException.ts3
90 files changed, 2150 insertions, 1955 deletions
diff --git a/src/arguments/messageLink.ts b/src/arguments/messageLink.ts
new file mode 100644
index 0000000..d270abd
--- /dev/null
+++ b/src/arguments/messageLink.ts
@@ -0,0 +1,19 @@
+import { type BushArgumentTypeCaster } from '../lib';
+
+export const messageLink: BushArgumentTypeCaster = async (_, phrase) => {
+ const match = client.consts.regex.messageLink.exec(phrase);
+ if (!match || !match.groups) return null;
+
+ const { guild_id, channel_id, message_id } = match.groups;
+
+ if (!guild_id || !channel_id || message_id) return null;
+
+ const guild = client.guilds.cache.get(guild_id);
+ if (!guild) return null;
+
+ const channel = guild.channels.cache.get(channel_id);
+ if (!channel || (!channel.isText() && !channel.isThread())) return null;
+
+ const message = await channel.messages.fetch(message_id).catch(() => null);
+ return message;
+};
diff --git a/src/commands/_fake-command/ironmoon.ts b/src/commands/_fake-command/ironmoon.ts
index b13d1d3..428b554 100644
--- a/src/commands/_fake-command/ironmoon.ts
+++ b/src/commands/_fake-command/ironmoon.ts
@@ -4,7 +4,9 @@ export default class IronmoonCommand extends BushCommand {
public constructor() {
super('ironmoon', {
category: 'fake-commands',
- description: { content: '', examples: [''], usage: [''] },
+ description: '',
+ examples: [''],
+ usage: [''],
pseudo: true,
clientPermissions: [],
userPermissions: []
diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts
index befa3ea..b44ae21 100644
--- a/src/commands/admin/channelPermissions.ts
+++ b/src/commands/admin/channelPermissions.ts
@@ -7,79 +7,50 @@ export default class ChannelPermissionsCommand extends BushCommand {
aliases: ['channel-perms', 'cperms', 'cperm', 'chanperms', 'chanperm', 'channel-permissions'],
category: 'admin',
typing: true,
- description: {
- content: 'Use to mass change the channel permissions.',
- usage: ['channel-perms <role_id> <perm> <state>'],
- examples: ['channel-perms 783794633129197589 read_messages deny']
- },
+ description: 'Use to mass change the channel permissions.',
+ usage: ['channel-perms <role_id> <perm> <state>'],
+ examples: ['channel-perms 783794633129197589 read_messages deny'],
args: [
{
id: 'target',
- customType: util.arg.union('member', 'member'),
- prompt: {
- start: 'What user/role would you like to change?',
- retry: '{error} Choose a valid user/role to change.'
- }
+ description: 'The user/role to change the permissions of.',
+ customType: util.arg.union('member', 'role'),
+ readableType: 'member|role',
+ prompt: 'What user/role would you like to change?',
+ retry: '{error} Choose a valid user/role to change.',
+ slashType: 'MENTIONABLE'
},
{
id: 'permission',
+ description: 'The permission to change for the target user/role.',
type: 'permission',
- prompt: {
- start: 'What permission would you like to change?',
- retry: '{error} Choose a valid permission.'
- }
+ prompt: 'What permission would you like to change?',
+ retry: '{error} Choose a valid permission.',
+ slashType: 'STRING'
},
{
id: 'state',
+ description: 'The state that the permission should be set to for the target.',
customType: [
['true', '1', 'yes', 'enable', 'allow'],
['false', '0', 'no', 'disable', 'disallow', 'deny'],
['neutral', 'remove', 'none']
],
- prompt: {
- start: 'What should that permission be set to?',
- retry: '{error} Set the state to either `enable`, `disable`, or `remove`.'
- }
+ readableType: "'enable'|'disable'|'remove'",
+ prompt: 'What should that permission be set to?',
+ retry: '{error} Set the state to either `enable`, `disable`, or `remove`.',
+ slashType: 'STRING',
+ choices: [
+ { name: 'Enabled', value: 'true' },
+ { name: 'Disabled', value: 'false' },
+ { name: 'Neutral', value: 'neutral' }
+ ]
}
],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS']),
userPermissions: ['ADMINISTRATOR'],
channel: 'guild',
- slash: true,
- slashOptions: [
- {
- name: 'target',
- description: 'What user/role would you like to change?',
- type: 'MENTIONABLE',
- required: true
- },
- {
- name: 'permission',
- description: 'What permission would you like to change?',
- type: 'STRING',
- required: true
- },
- {
- name: 'state',
- description: 'What should that permission be set to?',
- type: 'STRING',
- choices: [
- {
- name: 'Enabled',
- value: 'true'
- },
- {
- name: 'Disabled',
- value: 'false'
- },
- {
- name: 'Neutral',
- value: 'neutral'
- }
- ],
- required: true
- }
- ]
+ slash: true
});
}
diff --git a/src/commands/admin/roleAll.ts b/src/commands/admin/roleAll.ts
index 3c6b629..585e6cc 100644
--- a/src/commands/admin/roleAll.ts
+++ b/src/commands/admin/roleAll.ts
@@ -6,46 +6,34 @@ export default class RoleAllCommand extends BushCommand {
super('roleAll', {
aliases: ['role-all', 'rall'],
category: 'admin',
- description: {
- content: 'Give a role to every member on the server.',
- usage: ['role-all <role> [--bots]'],
- examples: ['role-all 783794633129197589 --bots']
- },
+ description: 'Give a role to every member on the server.',
+ usage: ['role-all <role> [--bots]'],
+ examples: ['role-all 783794633129197589 --bots'],
args: [
{
id: 'role',
+ description: 'The role to assigned to every member on the server.',
type: 'role',
- prompt: {
- start: 'What role would you like to give to every member on the server?',
- retry: '{error} Pick a valid role.'
- }
+ prompt: 'What role would you like to give to every member on the server?',
+ retry: '{error} Pick a valid role.',
+ slashType: 'ROLE'
},
{
id: 'bots',
+ description: 'Also give the role to bots.',
match: 'flag',
+ prompt: 'Would you like to also give roles to bots?',
flag: '--bots',
- default: false
+ default: false,
+ slashType: 'BOOLEAN',
+ optional: true
}
],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']),
userPermissions: ['ADMINISTRATOR'],
typing: true,
- slash: true,
- slashOptions: [
- {
- name: 'role',
- description: 'What role would you like to give to every member on the server?',
- type: 'ROLE',
- required: true
- },
- {
- name: 'bots',
- description: 'Would you like to also give roles to bots?',
- type: 'BOOLEAN',
- required: false
- }
- ]
+ slash: true
});
}
diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts
index f0173a4..8bb778c 100644
--- a/src/commands/config/blacklist.ts
+++ b/src/commands/config/blacklist.ts
@@ -6,45 +6,43 @@ export default class BlacklistCommand extends BushCommand {
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']
- },
+ description: 'A command to blacklist users and channels.',
+ usage: ['blacklist|unblacklist <user|channel>'],
+ examples: ['blacklist @user', 'unblacklist #channel'],
args: [
{
+ id: 'action',
+ description: 'Whether to blacklist or unblacklist the target.',
+ readableType: "'blacklist'|'unblacklist'",
+ prompt: 'Would you like to add or remove someone or something from/to the blacklist?',
+ slashType: 'STRING',
+ choices: [
+ { name: 'blacklist', value: 'blacklist' },
+ { name: 'unblacklist', value: 'unblacklist' }
+ ],
+ only: 'slash'
+ },
+ {
id: 'target',
+ description: 'The channel/user to blacklist.',
customType: util.arg.union('channel', 'user'),
- prompt: {
- start: 'What channel or user that you would like to blacklist/unblacklist?',
- retry: '{error} Pick a valid user or channel.'
- }
+ readableType: 'channel|user',
+ prompt: 'What channel or user that you would like to blacklist/unblacklist?',
+ retry: '{error} Pick a valid user or channel.',
+ slashType: 'STRING'
},
{
id: 'global',
+ description: 'Blacklist the target globally.',
match: 'flag',
- flag: '--global'
+ flag: '--global',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
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: (m) => util.clientSendAndPermCheck(m),
userPermissions: ['MANAGE_GUILD']
@@ -82,14 +80,14 @@ export default class BlacklistCommand extends BushCommand {
.catch(() => false);
if (!success)
return await message.util.reply({
- content: `${util.emojis.error} There was an error globally ${action}ing ${util.format.bold(
+ content: `${util.emojis.error} There was an error globally ${action}ing ${util.format.input(
target?.tag ?? target.name
)}.`,
allowedMentions: AllowedMentions.none()
});
else
return await message.util.reply({
- content: `${util.emojis.success} Successfully ${action}ed ${util.format.bold(target?.tag ?? target.name)} globally.`,
+ content: `${util.emojis.success} Successfully ${action}ed ${util.format.input(target?.tag ?? target.name)} globally.`,
allowedMentions: AllowedMentions.none()
});
// guild disable
@@ -110,12 +108,12 @@ export default class BlacklistCommand extends BushCommand {
.catch(() => false);
if (!success)
return await message.util.reply({
- content: `${util.emojis.error} There was an error ${action}ing ${util.format.bold(target?.tag ?? target.name)}.`,
+ content: `${util.emojis.error} There was an error ${action}ing ${util.format.input(target?.tag ?? target.name)}.`,
allowedMentions: AllowedMentions.none()
});
else
return await message.util.reply({
- content: `${util.emojis.success} Successfully ${action}ed ${util.format.bold(target?.tag ?? target.name)}.`,
+ content: `${util.emojis.success} Successfully ${action}ed ${util.format.input(target?.tag ?? target.name)}.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts
index 2ce4246..6af5895 100644
--- a/src/commands/config/config.ts
+++ b/src/commands/config/config.ts
@@ -22,15 +22,11 @@ export default class SettingsCommand extends BushCommand {
super('config', {
aliases: ['config', 'settings', 'setting', 'configure'],
category: 'config',
- description: {
- content: 'Configure server settings.',
- usage: [
- `settings (${settingsArr.map((s) => `\`${s}\``).join(', ')}) (${['view', 'set', 'add', 'remove'].map(
- (s) => `\`${s}\``
- )})`
- ],
- examples: ['settings', 'config prefix set -']
- },
+ description: 'Configure server settings.',
+ usage: [
+ `settings (${settingsArr.map((s) => `\`${s}\``).join(', ')}) (${['view', 'set', 'add', 'remove'].map((s) => `\`${s}\``)})`
+ ],
+ examples: ['settings', 'config prefix set -'],
slash: true,
slashOptions: settingsArr.map((setting) => {
return {
diff --git a/src/commands/config/customAutomodPhrases.ts b/src/commands/config/customAutomodPhrases.ts
index 9fbebf5..cf37595 100644
--- a/src/commands/config/customAutomodPhrases.ts
+++ b/src/commands/config/customAutomodPhrases.ts
@@ -5,11 +5,9 @@
// super('customAutomodPhrases', {
// aliases: ['custom-automod-phrases'],
// category: 'config',
-// description: {
-// content: 'Configure additional phrases to be used for automod.',
-// usage: ['custom-automod-phrases <requiredArg> [optionalArg]'],
-// examples: ['custom-automod-phrases 1 2']
-// },
+// description: 'Configure additional phrases to be used for automod.',
+// usage: ['custom-automod-phrases <requiredArg> [optionalArg]'],
+// examples: ['custom-automod-phrases 1 2'],
// args: [
// {
// id: 'required_argument',
diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts
index 83b4608..333ae19 100644
--- a/src/commands/config/disable.ts
+++ b/src/commands/config/disable.ts
@@ -5,52 +5,40 @@ export default class DisableCommand extends BushCommand {
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']
- },
+ description: 'A command to disable and enable commands.',
+ usage: ['disable|enable <command>'],
+ examples: ['enable ban', 'disable kick'],
args: [
{
+ id: 'action',
+ description: 'Whether to disable or enable the command.',
+ readableType: "'blacklist'|'unblacklist",
+ prompt: 'Would you like to disable or enable a command?',
+ slashType: 'STRING',
+ choices: ['blacklist', 'unblacklist'].map((v) => ({ name: v, value: v })),
+ only: 'slash'
+ },
+ {
id: 'command',
+ description: 'The command to disable/enable.',
customType: util.arg.union('commandAlias', 'command'),
- prompt: {
- start: 'What command would you like to enable/disable?',
- retry: '{error} Pick a valid command.',
- optional: false
- }
+ readableType: 'command|commandAlias',
+ prompt: 'What command would you like to enable/disable?',
+ retry: '{error} Pick a valid command.',
+ slashType: 'STRING'
},
{
id: 'global',
+ description: 'Disable the command globally.',
match: 'flag',
- flag: '--global'
+ flag: '--global',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
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: (m) => util.clientSendAndPermCheck(m),
userPermissions: ['MANAGE_GUILD']
@@ -67,57 +55,31 @@ export default class DisableCommand extends BushCommand {
const global = args.global && message.author.isOwner();
const commandID = (args.command as BushCommand).id;
- if (global) {
- if (action === 'toggle') {
- const disabledCommands = (
- (await Global.findByPk(client.config.environment)) ?? (await Global.create({ environment: client.config.environment }))
- ).disabledCommands;
- action = disabledCommands.includes(commandID) ? 'disable' : 'enable';
- }
- const success = await util
- .insertOrRemoveFromGlobal(action === 'disable' ? 'remove' : 'add', 'disabledCommands', commandID)
- .catch(() => false);
- if (!success)
- return await message.util.reply({
- content: `${util.emojis.error} There was an error globally **${action.substring(
- 0,
- action.length - 2
- )}ing** the **${commandID}** command.`,
- allowedMentions: AllowedMentions.none()
- });
- else
- return await message.util.reply({
- content: `${util.emojis.success} Successfully **${action.substring(
- 0,
- action.length - 2
- )}ed** the **${commandID}** command globally.`,
- allowedMentions: AllowedMentions.none()
- });
+ const disabledCommands = global
+ ? ((await Global.findByPk(client.config.environment)) ?? (await Global.create({ environment: client.config.environment })))
+ .disabledCommands
+ : await message.guild!.getSetting('disabledCommands');
- // guild disable
- } else {
- const disabledCommands = await message.guild!.getSetting('disabledCommands');
- if (action === 'toggle') {
- action = disabledCommands.includes(commandID) ? 'disable' : 'enable';
- }
- const newValue = util.addOrRemoveFromArray(action === 'disable' ? 'remove' : 'add', disabledCommands, commandID);
- const success = await message.guild!.setSetting('disabledCommands', newValue, message.member!).catch(() => false);
- if (!success)
- return await message.util.reply({
- content: `${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: `${util.emojis.success} Successfully **${action.substr(
- 0,
- action.length - 2
- )}ed** the **${commandID}** command.`,
- allowedMentions: AllowedMentions.none()
- });
- }
+ if (action === 'toggle') action = disabledCommands.includes(commandID) ? 'disable' : 'enable';
+ const newValue = util.addOrRemoveFromArray(action === 'disable' ? 'remove' : 'add', disabledCommands, commandID);
+ const success = global
+ ? await util.setGlobal('disabledCommands', newValue).catch(() => false)
+ : await message.guild!.setSetting('disabledCommands', newValue, message.member!).catch(() => false);
+ if (!success)
+ return await message.util.reply({
+ content: `${util.emojis.error} There was an error${global ? ' globally' : ''} **${action.substring(
+ 0,
+ action.length - 2
+ )}ing** the **${commandID}** command.`,
+ allowedMentions: AllowedMentions.none()
+ });
+ else
+ return await message.util.reply({
+ content: `${util.emojis.success} Successfully **${action.substring(
+ 0,
+ action.length - 2
+ )}ed** the **${commandID}** command${global ? ' globally' : ''}.`,
+ allowedMentions: AllowedMentions.none()
+ });
}
}
diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts
index 095d985..894c90a 100644
--- a/src/commands/config/features.ts
+++ b/src/commands/config/features.ts
@@ -13,11 +13,9 @@ export default class FeaturesCommand extends BushCommand {
super('features', {
aliases: ['features'],
category: 'config',
- description: {
- content: 'Toggle features the server.',
- usage: ['features'],
- examples: ['features']
- },
+ description: 'Toggle features the server.',
+ usage: ['features'],
+ examples: ['features'],
slash: true,
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
diff --git a/src/commands/config/levelRoles.ts b/src/commands/config/levelRoles.ts
index e7b4505..7f99580 100644
--- a/src/commands/config/levelRoles.ts
+++ b/src/commands/config/levelRoles.ts
@@ -5,11 +5,9 @@
// super('levelRole', {
// aliases: ['level-role', 'level-roles', 'lr'],
// category: 'config',
-// description: {
-// content: 'Configure roles to be assigned to users upon reaching certain levels.',
-// usage: ['level-role add <level> <role>', 'level-role remove <level>'],
-// examples: ['level-role 1 2']
-// },
+// description: 'Configure roles to be assigned to users upon reaching certain levels.',
+// usage: ['level-role add <level> <role>', 'level-role remove <level>'],
+// examples: ['level-role 1 2'],
// args: [
// {
// id: 'action',
@@ -18,20 +16,16 @@
// {
// id: 'role',
// type: 'role',
-// prompt: {
-// start: 'What would you like to set your first argument to be?',
-// retry: '{error} Pick a valid argument.',
-// optional: false
-// }
+// prompt: 'What would you like to set your first argument to be?',
+// retry: '{error} Pick a valid argument.',
+// optional: false
// },
// {
// id: 'level',
// type: 'integer',
-// prompt: {
-// start: 'What would you like to set your second argument to be?',
-// retry: '{error} Pick a valid argument.',
-// optional: false
-// }
+// prompt: 'What would you like to set your second argument to be?',
+// retry: '{error} Pick a valid argument.',
+// optional: false
// }
// ],
// slash: true,
diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts
index cccef8c..6121ad7 100644
--- a/src/commands/config/log.ts
+++ b/src/commands/config/log.ts
@@ -7,25 +7,26 @@ export default class LogCommand extends BushCommand {
super('log', {
aliases: ['log', 'logging'],
category: 'config',
- description: {
- content: 'Set or remove a log channel.',
- usage: ['log <logType> [channel]'],
- examples: ['log automod #automod-logs']
- },
+ description: 'Set or remove a log channel.',
+ usage: ['log <logType> [channel]'],
+ examples: ['log automod #automod-logs'],
slash: true,
- slashOptions: [
+ args: [
{
- name: 'log_type',
- description: 'What log type would you like to change?',
- type: 'STRING',
- required: true,
- choices: guildLogsArr.map((log) => ({ name: log, value: log }))
+ id: 'log_type',
+ description: 'The log type to change.',
+ prompt: 'What log type would you like to change?',
+ slashType: 'STRING',
+ choices: guildLogsArr.map((log) => ({ name: log, value: log })),
+ only: 'slash'
},
{
- name: 'channel',
- description: 'What channel would you like these logs to be sent in?',
- type: 'CHANNEL',
- required: false
+ id: 'channel',
+ description: 'The channel to have logs of the seleted type to be sent in.',
+ type: 'channel',
+ prompt: 'What channel would you like these logs to be sent in?',
+ slashType: 'CHANNEL',
+ channelTypes: ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD']
}
],
channel: 'guild',
@@ -36,7 +37,7 @@ export default class LogCommand extends BushCommand {
override *args(): IterableIterator<ArgumentOptions | Flag> {
const log_type = yield {
- id: 'log',
+ id: 'log_type',
type: guildLogsArr,
prompt: {
start: 'What log type would you like to change?',
diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts
index fe685ff..5bb29c8 100644
--- a/src/commands/dev/__template.ts
+++ b/src/commands/dev/__template.ts
@@ -5,46 +5,29 @@ export default class TemplateCommand extends BushCommand {
super('template', {
aliases: ['template'],
category: 'template',
- description: {
- content: 'Command description.',
- usage: ['template <requiredArg> [optionalArg]'],
- examples: ['template 1 2']
- },
+ description: 'Command description.',
+ usage: ['template <requiredArg> [optionalArg]'],
+ examples: ['template 1 2'],
args: [
{
id: 'required_argument',
type: 'string',
- prompt: {
- start: 'What would you like to set your first argument to be?',
- retry: '{error} Pick a valid argument.',
- optional: false
- }
+ description: 'This is the first argument.',
+ prompt: 'What would you like to set your first argument to be?',
+ retry: '{error} Pick a valid argument.',
+ slashType: 'STRING'
},
{
id: 'optional_argument',
type: 'string',
- prompt: {
- start: 'What would you like to set your second argument to be?',
- retry: '{error} Pick a valid argument.',
- optional: true
- }
+ description: 'This is the second argument.',
+ prompt: 'What would you like to set your second argument to be?',
+ retry: '{error} Pick a valid argument.',
+ optional: true,
+ slashType: 'STRING'
}
],
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',
diff --git a/src/commands/dev/dm.ts b/src/commands/dev/dm.ts
new file mode 100644
index 0000000..5031dfd
--- /dev/null
+++ b/src/commands/dev/dm.ts
@@ -0,0 +1,46 @@
+import { BushCommand, BushUser, type BushMessage, type BushSlashMessage } from '#lib';
+
+export default class DMCommand extends BushCommand {
+ public constructor() {
+ super('dm', {
+ aliases: ['dm'],
+ category: 'dev',
+ description: 'Send a direct message to a specified user from the bot.',
+ usage: ['dm <user> <content>'],
+ examples: ['dm IRONM00N hi'],
+ args: [
+ {
+ id: 'user',
+ type: 'string',
+ description: 'The user to send the dm to.',
+ prompt: 'Who would you like to dm?',
+ retry: '{error} Pick a valid user to send a dm to.',
+ slashType: 'STRING'
+ },
+ {
+ id: 'content',
+ type: 'string',
+ description: 'This is the second argument.',
+ prompt: 'What would you like to set your second argument to be?',
+ retry: '{error} Pick a valid argument.',
+ optional: true,
+ slashType: 'STRING'
+ }
+ ],
+ slash: false,
+ ownerOnly: true,
+ hidden: true,
+ clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ userPermissions: []
+ });
+ }
+ public override async exec(message: BushMessage | BushSlashMessage, args: { user: BushUser; content: string }) {
+ try {
+ const u = await client.users.fetch(args.user.id);
+ await u.send(args.content);
+ } catch (e) {
+ return message.util.reply(`${util.emojis.error} There was an error sending ${util.format.input(args.user.tag)} a dm.`);
+ }
+ return message.util.reply(`${util.emojis.success} Successfully sent ${util.format.input(args.user.tag)} a dm.`);
+ }
+}
diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts
index b82534c..5b30d96 100644
--- a/src/commands/dev/eval.ts
+++ b/src/commands/dev/eval.ts
@@ -11,42 +11,95 @@ export default class EvalCommand extends BushCommand {
super('eval', {
aliases: ['eval', 'ev', 'evaluate'],
category: 'dev',
- description: {
- content: 'Evaluate code.',
- usage: ['eval <code> [--depth #] [--sudo] [--silent] [--delete] [--proto] [--hidden] [--ts]'],
- examples: ['eval message.channel.delete()']
- },
+ description: 'Evaluate code.',
+ usage: ['eval <code> [--depth #] [--sudo] [--silent] [--delete] [--proto] [--hidden] [--ts]'],
+ examples: ['eval message.channel.delete()'],
args: [
- { id: 'sel_depth', match: 'option', type: 'integer', flag: '--depth', default: 0 },
- { id: 'sudo', match: 'flag', flag: '--sudo' },
- { id: 'delete_msg', match: 'flag', flag: '--delete' },
- { id: 'silent', match: 'flag', flag: '--silent' },
- { id: 'typescript', match: 'flag', flag: '--ts' },
- { id: 'hidden', match: 'flag', flag: '--hidden' },
- { id: 'show_proto', match: 'flag', flag: '--proto' },
+ {
+ id: 'sel_depth',
+ description: 'How deep to inspect the output.',
+ match: 'option',
+ type: 'integer',
+ flag: '--depth',
+ default: 0,
+ prompt: 'How deep would you like to inspect the output?',
+ slashType: 'INTEGER',
+ optional: true
+ },
+ {
+ id: 'sudo',
+ description: 'Whether or not to override checks.',
+ match: 'flag',
+ flag: '--sudo',
+ prompt: 'Would you like to override checks?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
+ {
+ id: 'delete_msg',
+ description: 'Whether or not to delete the message that invoked the command.',
+ match: 'flag',
+ flag: '--delete',
+ prompt: 'Would you like to delete the message that invoked the command?',
+ slashType: false,
+ optional: true,
+ only: 'text'
+ },
+ {
+ id: 'silent',
+ description: 'Whether or not to make the response silent',
+ match: 'flag',
+ flag: '--silent',
+ prompt: 'Would you like to make the response silent?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
+ {
+ id: 'typescript',
+ description: 'Whether or not to treat the code as typescript and transpile it.',
+ match: 'flag',
+ flag: '--ts',
+ prompt: 'Is this code written in typescript?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
+ {
+ id: 'hidden',
+ description: 'Whether or not to show hidden items.',
+ match: 'flag',
+ flag: '--hidden',
+ prompt: 'Would you like to show hidden items?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
+ {
+ id: 'show_proto',
+ description: 'Whether or not to show the prototype of the output.',
+ match: 'flag',
+ flag: '--proto',
+ prompt: 'Would you like to show the prototype of the output?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
{
id: 'show_methods',
+ description: 'Whether or not to inspect the prototype chain for methods.',
match: 'flag',
- flag: ['--func', '--function', '--functions', '--meth', '--method', '--methods']
+ flag: ['--func', '--function', '--functions', '--meth', '--method', '--methods'],
+ prompt: 'Would you like to inspect the prototype chain to find methods?',
+ slashType: 'BOOLEAN',
+ optional: true
},
{
id: 'code',
+ description: 'The code you would like to evaluate.',
match: 'rest',
- type: 'string',
- prompt: { start: 'What would you like to eval?', retry: '{error} Invalid code to eval.' }
+ prompt: 'What would you like to eval?',
+ retry: '{error} Invalid code to eval.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- { name: 'code', description: 'The code you would like to evaluate.', type: 'STRING', required: true },
- { name: 'sel_depth', description: 'How deep to display the output.', type: 'INTEGER', required: false },
- { name: 'sudo', description: 'Whether or not to override checks.', type: 'BOOLEAN', required: false },
- { name: 'silent', description: 'Whether or not to make the response silent', type: 'BOOLEAN', required: false },
- { name: 'typescript', description: 'Whether or not the code is typescript.', type: 'BOOLEAN', required: false },
- { name: 'hidden', description: 'Whether or not to show hidden items.', type: 'BOOLEAN', required: false },
- { name: 'show_proto', description: 'Show prototype.', type: 'BOOLEAN', required: false },
- { name: 'show_methods', description: 'Show class functions.', type: 'BOOLEAN', required: false }
- ],
ownerOnly: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
diff --git a/src/commands/dev/javascript.ts b/src/commands/dev/javascript.ts
index 8a47b23..5173cd1 100644
--- a/src/commands/dev/javascript.ts
+++ b/src/commands/dev/javascript.ts
@@ -7,25 +7,31 @@ export default class JavascriptCommand extends BushCommand {
super('javascript', {
aliases: ['javascript', 'js'],
category: 'dev',
- description: {
- content: 'Evaluate code in a sand boxed environment.',
- usage: ['javascript <code> [--depth #]'],
- examples: ['javascript 9+10']
- },
+ description: 'Evaluate code in a sand boxed environment.',
+ usage: ['javascript <code> [--depth #]'],
+ examples: ['javascript 9+10'],
args: [
- { id: 'sel_depth', match: 'option', type: 'integer', flag: '--depth', default: 0 },
+ {
+ id: 'sel_depth',
+ description: 'How deep to inspect the output.',
+ match: 'option',
+ type: 'integer',
+ flag: '--depth',
+ default: 0,
+ prompt: 'How deep would you like to inspect the output?',
+ slashType: 'INTEGER',
+ optional: true
+ },
{
id: 'code',
+ description: 'The code you would like to run in a sand boxed environment.',
match: 'rest',
- type: 'string',
- prompt: { start: 'What would you like to eval?', retry: '{error} Invalid code to eval.' }
+ prompt: 'What code would you like to run in a sand boxed environment?',
+ retry: '{error} Invalid code to run in a sand boxed environment.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- { name: 'code', description: 'The code you would like to evaluate.', type: 'STRING', required: true },
- { name: 'sel_depth', description: 'How deep to display the output.', type: 'INTEGER', required: false }
- ],
superUserOnly: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts
index f9b1867..6d030b7 100644
--- a/src/commands/dev/reload.ts
+++ b/src/commands/dev/reload.ts
@@ -5,29 +5,23 @@ export default class ReloadCommand extends BushCommand {
super('reload', {
aliases: ['reload'],
category: 'dev',
- description: {
- content: 'Reloads the bot',
- usage: ['reload'],
- examples: ['reload']
- },
+ description: 'Reloads the bot',
+ usage: ['reload'],
+ examples: ['reload'],
// args: [
// {
// id: 'fast',
+ // description: 'Whether or not to use esbuild for fast compiling.',
// match: 'flag',
- // flag: '--fast'
+ // flag: '--fast',
+ // prompt: 'Would you like to use esbuild for fast compiling?',
+ // optional: true,
+ // slashType:'BOOLEAN'
// }
// ],
ownerOnly: true,
typing: true,
slash: true,
- // slashOptions: [
- // {
- // name: 'fast',
- // description: 'Whether to use esbuild for fast compiling or not',
- // type: 'BOOLEAN',
- // required: false
- // }
- // ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/dev/say.ts b/src/commands/dev/say.ts
index 400a132..80cbbe2 100644
--- a/src/commands/dev/say.ts
+++ b/src/commands/dev/say.ts
@@ -5,20 +5,20 @@ export default class SayCommand extends BushCommand {
super('say', {
aliases: ['say'],
category: 'dev',
- description: {
- content: 'A command make the bot say something.',
- usage: ['say <message>'],
- examples: ['say hello']
- },
+ description: 'A command make the bot say something.',
+ usage: ['say <content>'],
+ examples: ['say hello'],
args: [
{
id: 'content',
+ description: 'The content of the message to send.',
type: 'string',
match: 'rest',
- prompt: { start: 'What would you like the bot to say?', retry: '{error} Choose something valid to say.' }
+ prompt: 'What would you like the bot to say?',
+ retry: '{error} Choose something for the bot to send.',
+ slashType: 'STRING'
}
],
- slashOptions: [{ name: 'content', description: 'What would you like the bot to say?', type: 'STRING' }],
ownerOnly: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
diff --git a/src/commands/dev/servers.ts b/src/commands/dev/servers.ts
index e8a2fe4..308d1db 100644
--- a/src/commands/dev/servers.ts
+++ b/src/commands/dev/servers.ts
@@ -6,11 +6,9 @@ export default class ServersCommand extends BushCommand {
super('servers', {
aliases: ['servers', 'guilds'],
category: 'dev',
- description: {
- content: 'Displays all the severs the bot is in',
- usage: ['servers'],
- examples: ['servers']
- },
+ description: 'Displays all the severs the bot is in',
+ usage: ['servers'],
+ examples: ['servers'],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
ownerOnly: true
@@ -25,7 +23,7 @@ export default class ServersCommand extends BushCommand {
title: `Server List [\`${guilds.length.toLocaleString()}\`]`,
color: util.colors.default,
fields: chunk.map((guild) => ({
- name: util.format.bold(guild.name),
+ name: util.format.input(guild.name),
value: [
`**ID:** ${guild.id}`,
`**Owner:** ${client.users.cache.has(guild.ownerId) ? client.users.cache.get(guild.ownerId)!.tag : guild.ownerId}`,
diff --git a/src/commands/dev/sh.ts b/src/commands/dev/sh.ts
index 83432f4..5ef72b1 100644
--- a/src/commands/dev/sh.ts
+++ b/src/commands/dev/sh.ts
@@ -17,20 +17,18 @@ export default class ShCommand extends BushCommand {
super('sh', {
aliases: ['sh', 'shell', 'cmd'],
category: 'dev',
- description: {
- content: 'Run shell commands.',
- usage: ['sh <command>'],
- examples: ['sh git pull']
- },
+ description: 'Run shell commands.',
+ usage: ['sh <command>'],
+ examples: ['sh git pull'],
args: [
{
id: 'command',
+ description: 'The content you would like to run as a shell command.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'What would you like run',
- retry: '{error} Invalid command to run.'
- }
+ prompt: 'What would you like run',
+ retry: '{error} Invalid command to run.',
+ slashType: 'STRING'
}
],
ownerOnly: true,
diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts
index 17d81ac..e0328db 100644
--- a/src/commands/dev/superUser.ts
+++ b/src/commands/dev/superUser.ts
@@ -7,14 +7,27 @@ export default class SuperUserCommand extends BushCommand {
super('superuser', {
aliases: ['superuser', 'su'],
category: 'dev',
- description: {
- content: 'A command to manage superusers.',
- usage: ['superuser <add/remove> <user>'],
- examples: ['superuser add IRONM00N']
- },
+ description: 'A command to manage superusers.',
+ usage: ['superuser <add/remove> <user>'],
+ examples: ['superuser add IRONM00N'],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
- ownerOnly: true
+ ownerOnly: true,
+ helpArgs: [
+ {
+ id: 'action',
+ description: 'Whether to add or remove a user from the superuser list.',
+ readableType: 'add|remove',
+ slashType: false
+ },
+ {
+ id: 'user',
+ description: 'The user to add/remove from the superuser list.',
+ type: 'user',
+ match: 'restContent',
+ slashType: false
+ }
+ ]
});
}
diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts
index 83dd592..f3ac627 100644
--- a/src/commands/dev/test.ts
+++ b/src/commands/dev/test.ts
@@ -13,21 +13,18 @@ export default class TestCommand extends BushCommand {
super('test', {
aliases: ['test'],
category: 'dev',
- description: {
- content: 'A command to stuff.',
- usage: ['test [feature]'],
- examples: ['test lots of buttons', 'test buttons']
- },
+ description: 'A command to test stuff.',
+ usage: ['test [feature]'],
+ examples: ['test lots of buttons', 'test buttons'],
args: [
{
id: 'feature',
- type: 'string',
+ description: 'The feature to test.',
match: 'rest',
- prompt: {
- start: 'start prompt',
- retry: 'retry prompt',
- optional: true
- }
+ prompt: 'start prompt',
+ retry: 'retry prompt',
+ optional: true,
+ slashType: false
}
],
superUserOnly: true,
diff --git a/src/commands/fun/coinflip.ts b/src/commands/fun/coinflip.ts
index 83de5ba..cd436f8 100644
--- a/src/commands/fun/coinflip.ts
+++ b/src/commands/fun/coinflip.ts
@@ -5,11 +5,9 @@ export default class CoinFlipCommand extends BushCommand {
super('coinflip', {
aliases: ['coinflip', 'cf'],
category: 'fun',
- description: {
- content: 'Flip a virtual coin.',
- usage: ['coinflip'],
- examples: ['coinflip']
- },
+ description: 'Flip a virtual coin.',
+ usage: ['coinflip'],
+ examples: ['coinflip'],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
slash: true
diff --git a/src/commands/fun/dice.ts b/src/commands/fun/dice.ts
index 74f387e..2f96e1c 100644
--- a/src/commands/fun/dice.ts
+++ b/src/commands/fun/dice.ts
@@ -5,11 +5,9 @@ export default class EightBallCommand extends BushCommand {
super('dice', {
aliases: ['dice', 'die'],
category: 'fun',
- description: {
- content: 'Roll virtual dice.',
- usage: ['dice'],
- examples: ['dice']
- },
+ description: 'Roll virtual dice.',
+ usage: ['dice'],
+ examples: ['dice'],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
slash: true
diff --git a/src/commands/fun/eightBall.ts b/src/commands/fun/eightBall.ts
index fc662ad..d6b0b8c 100644
--- a/src/commands/fun/eightBall.ts
+++ b/src/commands/fun/eightBall.ts
@@ -5,31 +5,21 @@ export default class EightBallCommand extends BushCommand {
super('eightBall', {
aliases: ['8ball', 'eightball'],
category: 'fun',
- description: {
- content: 'Ask questions for a randomly generated response.',
- usage: ['8Ball <question>'],
- examples: ['8Ball does anyone love me?']
- },
+ description: 'Ask questions for a randomly generated response.',
+ usage: ['8Ball <question>'],
+ examples: ['8Ball does anyone love me?'],
args: [
{
id: 'question',
+ description: 'The question to have answered.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'What question would you like answered?',
- retry: '{error} Invalid question.'
- }
+ prompt: 'What question would you like answered?',
+ retry: '{error} Invalid question.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'question',
- description: 'What question would you like answered?',
- type: 'STRING',
- required: true
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts
index 9b511a3..7ef1de7 100644
--- a/src/commands/fun/minesweeper.ts
+++ b/src/commands/fun/minesweeper.ts
@@ -6,58 +6,60 @@ export default class MinesweeperCommand extends BushCommand {
super('minesweeper', {
aliases: ['minesweeper'],
category: 'fun',
- description: {
- content: 'minesweeper command.',
- usage: ['minesweeper <rows> <columns> <mines> [--spaces] [--revealFirstCell]'],
- examples: ['minesweeper 10 10 2']
- },
+ description: 'minesweeper command.',
+ usage: ['minesweeper <rows> <columns> <mines> [--spaces] [--revealFirstCell]'],
+ examples: ['minesweeper 10 10 2'],
args: [
{
id: 'rows',
+ description: 'The number of rows to generate.',
type: 'integer',
- prompt: {
- start: 'How many rows would you like?',
- retry: '{error} Choose a valid number of rows',
- optional: true
- },
- default: 9
+ prompt: 'How many rows would you like?',
+ retry: '{error} Choose a valid number of rows',
+ optional: true,
+ default: 9,
+ slashType: 'INTEGER'
},
{
id: 'columns',
+ description: 'The number of columns to generate.',
type: 'integer',
- prompt: {
- start: 'How many columns would you like?',
- retry: '{error} Choose a valid number of columns',
- optional: true
- },
- default: 9
+ prompt: 'How many columns would you like?',
+ retry: '{error} Choose a valid number of columns',
+ optional: true,
+ default: 9,
+ slashType: 'INTEGER'
},
{
id: 'mines',
+ description: 'The number of mines to generate.',
type: 'integer',
- prompt: {
- start: 'How many mines would you like?',
- retry: '{error} Choose a valid number of mines',
- optional: true
- },
- default: 10
+ prompt: 'How many mines would you like?',
+ retry: '{error} Choose a valid number of mines',
+ optional: true,
+ default: 10,
+ slashType: 'INTEGER'
},
- { id: 'spaces', match: 'flag', flag: '--spaces' },
- { id: 'reveal_first_cell', match: 'flag', flag: '--revealFirstCell' }
- ],
- slash: true,
- slashOptions: [
- { name: 'rows', description: 'How many rows would you like?', type: 'INTEGER', required: false },
- { name: 'columns', description: 'How many rows would you like?', type: 'INTEGER', required: false },
- { name: 'mines', description: 'How many rows would you like?', type: 'INTEGER', required: false },
- { name: 'spaces', description: 'Would you like there to be spaces?', type: 'BOOLEAN', required: false },
{
- name: 'reveal_first_cell',
- description: 'Would you like to automatically reveal the first cell?',
- type: 'BOOLEAN',
- required: false
+ id: 'spaces',
+ description: 'Whether or not to put a space between cells.',
+ match: 'flag',
+ flag: '--spaces',
+ prompt: 'Would you like there to be spaces?',
+ slashType: 'BOOLEAN',
+ optional: true
+ },
+ {
+ id: 'reveal_first_cell',
+ description: 'Whether or not to reveal the first cell automatically.',
+ match: 'flag',
+ flag: '--revealFirstCell',
+ prompt: 'Would you like to automatically reveal the first cell?',
+ slashType: 'BOOLEAN',
+ optional: true
}
],
+ slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts
index e8b213f..87ea0cc 100644
--- a/src/commands/info/avatar.ts
+++ b/src/commands/info/avatar.ts
@@ -6,33 +6,24 @@ export default class AvatarCommand extends BushCommand {
super('avatar', {
aliases: ['avatar', 'av'],
category: 'info',
- description: {
- content: "A command to get a user's avatar",
- usage: ['avatar [user]'],
- examples: ['avatar', 'av IRONM00N']
- },
+ description: "A command to get a user's avatar",
+ usage: ['avatar [user]'],
+ examples: ['avatar', 'av IRONM00N'],
args: [
{
id: 'user',
+ description: 'The user you would like to find the avatar of.',
customType: util.arg.union('member', 'globalUser'),
- prompt: {
- start: 'Who would you like to see the avatar of?',
- retry: '{error} Choose a valid user.',
- optional: true
- }
+ readableType: 'member|user',
+ prompt: 'Who would you like to see the avatar of?',
+ retry: '{error} Choose a valid user.',
+ optional: true,
+ slashType: 'USER'
}
],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
- slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'The user you would like to find the avatar of.',
- type: 'USER',
- required: false
- }
- ]
+ slash: true
});
}
diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts
index 833ed96..56885c5 100644
--- a/src/commands/info/botInfo.ts
+++ b/src/commands/info/botInfo.ts
@@ -8,11 +8,9 @@ export default class BotInfoCommand extends BushCommand {
super('botInfo', {
aliases: ['bot-info', 'stats'],
category: 'info',
- description: {
- content: 'Shows information about the bot',
- usage: ['bot-info'],
- examples: ['bot-info']
- },
+ description: 'Shows information about the bot',
+ usage: ['bot-info'],
+ examples: ['bot-info'],
slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts
index 8fed7da..cb612b5 100644
--- a/src/commands/info/color.ts
+++ b/src/commands/info/color.ts
@@ -14,20 +14,19 @@ export default class ColorCommand extends BushCommand {
super('color', {
aliases: ['color'],
category: 'info',
- description: {
- content: 'Find the color of a hex code, user, or role.',
- usage: ['color <color|role|user>'],
- examples: ['color #0000FF']
- },
+ description: 'Find the color of a hex code, user, or role.',
+ usage: ['color <color|role|user>'],
+ examples: ['color #0000FF'],
args: [
{
id: 'color',
+ description: 'The color string, role, or member to find the color of.',
customType: Argument.union(isValidTinyColor, 'role', 'member'),
+ readableType: 'color|role|member',
match: 'restContent',
- 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.'
- }
+ prompt: 'What color code, role, or user would you like to find the color of?',
+ retry: '{error} Choose a valid color, role, or member.',
+ slashType: 'STRING'
}
],
channel: 'guild',
@@ -41,16 +40,23 @@ export default class ColorCommand extends BushCommand {
}
public override async exec(message: BushMessage | BushSlashMessage, args: { color: string | BushRole | BushGuildMember }) {
+ const _color = message.util.isSlashMessage(message)
+ ? ((await util.arg.cast(Argument.union(isValidTinyColor, 'role', 'member'), message, args.color as string)) as
+ | string
+ | BushRole
+ | BushGuildMember)
+ : args.color;
+
const color =
- typeof args.color === 'string'
- ? tinycolor(args.color)
- : args.color instanceof Role
- ? tinycolor(args.color.hexColor)
- : tinycolor(args.color.displayHexColor);
+ typeof _color === 'string'
+ ? tinycolor(_color)
+ : _color instanceof Role
+ ? tinycolor(_color.hexColor)
+ : tinycolor(_color.displayHexColor);
- if (args.color instanceof Role && args.color.hexColor === '#000000') {
+ if (_color instanceof Role && _color.hexColor === '#000000') {
return await message.util.reply({
- content: `${util.emojis.error} <@&${args.color.id}> does not have a color.`,
+ content: `${util.emojis.error} <@&${_color.id}> does not have a color.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts
index 47a8281..a38a446 100644
--- a/src/commands/info/guildInfo.ts
+++ b/src/commands/info/guildInfo.ts
@@ -14,31 +14,22 @@ export default class GuildInfoCommand extends BushCommand {
super('guildInfo', {
aliases: ['guild-info', 'serverinfo', 'guild', 'server', 'g'],
category: 'info',
- description: {
- content: 'Get info about a server.',
- usage: ['guild-info [guild]'],
- examples: ['guild-info 516977525906341928']
- },
+ description: 'Get info about a server.',
+ usage: ['guild-info [guild]'],
+ examples: ['guild-info 516977525906341928'],
args: [
{
id: 'guild',
+ description: 'The guild to find information about.',
customType: util.arg.union('guild', 'snowflake'),
- prompt: {
- start: 'What server would you like to find information about?',
- retry: '{error} Choose a valid server to find information about.',
- optional: true
- }
+ readableType: 'guild|snowflake',
+ prompt: 'What server would you like to find information about?',
+ retry: '{error} Choose a valid server to find information about.',
+ optional: true,
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'guild',
- description: 'The id of the guild you would like to find information about.',
- type: 'STRING',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
});
@@ -67,23 +58,15 @@ export default class GuildInfoCommand extends BushCommand {
const guildStats: string[] = [];
const guildSecurity: string[] = [];
const verifiedGuilds = Object.values(client.consts.mappings.guilds);
- if (verifiedGuilds.includes(guild.id)) emojis.push(otherEmojis.BUSH_VERIFIED);
+ if (verifiedGuilds.includes(guild.id as typeof verifiedGuilds[number])) emojis.push(otherEmojis.BUSH_VERIFIED);
if (!isPreview && guild instanceof Guild) {
if (guild.premiumTier !== 'NONE') emojis.push(otherEmojis[`BOOST_${guild.premiumTier}`]);
await guild.fetch();
const channels = guild.channels.cache;
- type ChannelType =
- | 'GUILD_TEXT'
- | 'GUILD_NEWS'
- | 'GUILD_VOICE'
- | 'GUILD_STAGE_VOICE'
- | 'GUILD_STORE'
- | 'GUILD_CATEGORY'
- | 'THREAD';
const channelTypes = (
- ['GUILD_TEXT', 'GUILD_VOICE', 'GUILD_STAGE_VOICE', 'GUILD_STORE', 'GUILD_CATEGORY', 'THREAD'] as ChannelType[]
+ ['GUILD_TEXT', 'GUILD_VOICE', 'GUILD_STAGE_VOICE', 'GUILD_STORE', 'GUILD_CATEGORY', 'THREAD'] as const
).map((type) => `${otherEmojis[type]} ${channels.filter((channel) => channel.type.includes(type)).size.toLocaleString()}`);
const guildRegions = [
@@ -113,18 +96,18 @@ export default class GuildInfoCommand extends BushCommand {
if (guild.banner) guildAbout.push(`**Banner:** [link](${guild.bannerURL({ size: 4096, format: 'png' })})`);
if (guild.splash) guildAbout.push(`**Splash:** [link](${guild.splashURL({ size: 4096, format: 'png' })})`);
- enum EmojiTierMap {
- TIER_3 = 500,
- TIER_2 = 300,
- TIER_1 = 100,
- NONE = 50
- }
- enum StickerTierMap {
- TIER_3 = 60,
- TIER_2 = 30,
- TIER_1 = 15,
- NONE = 0
- }
+ const EmojiTierMap = {
+ TIER_3: 500,
+ TIER_2: 300,
+ TIER_1: 100,
+ NONE: 50
+ } as const;
+ const StickerTierMap = {
+ TIER_3: 60,
+ TIER_2: 30,
+ TIER_1: 15,
+ NONE: 0
+ } as const;
guildStats.push(
`**Channels:** ${guild.channels.cache.size.toLocaleString()} / 500 (${channelTypes.join(', ')})`,
diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts
index 3bf8f5e..3b7883f 100644
--- a/src/commands/info/help.ts
+++ b/src/commands/info/help.ts
@@ -7,33 +7,32 @@ export default class HelpCommand extends BushCommand {
super('help', {
aliases: ['help'],
category: 'info',
- description: {
- content: 'Displays a list of commands, or detailed information for a specific command.',
- usage: ['help [command]'],
- examples: ['help prefix']
- },
+ description: 'Displays a list of commands, or detailed information for a specific command.',
+ usage: ['help [command]'],
+ examples: ['help prefix'],
args: [
{
id: 'command',
+ description: 'The command to show info about.',
type: 'commandAlias',
match: 'content',
- prompt: {
- start: 'What command do you need help with?',
- retry: '{error} Choose a valid command to find help for.',
- optional: true
- }
+ prompt: 'What command do you need help with?',
+ retry: '{error} Choose a valid command to find help for.',
+ slashType: 'STRING',
+ optional: true
},
- { id: 'showHidden', match: 'flag', flag: '--hidden' }
- ],
- slash: true,
- slashOptions: [
{
- name: 'command',
- description: 'What command do you need help with?',
- type: 'STRING',
- required: false
+ id: 'showHidden',
+ description: 'Whether ot not to show hidden commands as well.',
+ match: 'flag',
+ flag: '--hidden',
+ slashType: 'BOOLEAN',
+ ownerOnly: true,
+ only: 'text',
+ optional: true
}
],
+ slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
});
@@ -80,17 +79,17 @@ export default class HelpCommand extends BushCommand {
const embed = new MessageEmbed()
.setColor(util.colors.default)
.setTitle(`${command.id} Command`)
- .setDescription(`${command.description?.content ?? '*This command does not have a description.*'}`);
- if (command.description?.usage?.length) {
+ .setDescription(`${command.description ?? '*This command does not have a description.*'}`);
+ if (command.usage?.length) {
embed.addField(
- `» Usage${command.description.usage.length > 1 ? 's' : ''}`,
- command.description.usage.map((u) => `\`${u}\``).join('\n')
+ `» Usage${command.usage.length > 1 ? 's' : ''}`,
+ command.usage.map((u) => `\`${u}\``).join('\n')
);
}
- if (command.description?.examples?.length) {
+ if (command.examples?.length) {
embed.addField(
- `» Example${command.description.examples.length > 1 ? 's' : ''}`,
- command.description.examples.map((u) => `\`${u}\``).join('\n')
+ `» Example${command.examples.length > 1 ? 's' : ''}`,
+ command.examples.map((u) => `\`${u}\``).join('\n')
);
}
if (command.aliases?.length > 1) embed.addField('» Aliases', `\`${command.aliases.join('` `')}\``);
diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts
index 2a04a65..42b7fa4 100644
--- a/src/commands/info/icon.ts
+++ b/src/commands/info/icon.ts
@@ -6,11 +6,9 @@ export default class IconCommand extends BushCommand {
super('icon', {
aliases: ['icon', 'guildavatar', 'severicon', 'guildicon'],
category: 'info',
- description: {
- content: "A command to get the server's icon",
- usage: ['icon'],
- examples: ['icon']
- },
+ description: "A command to get the server's icon",
+ usage: ['icon'],
+ examples: ['icon'],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
channel: 'guild',
diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts
index 935dca0..3f82245 100644
--- a/src/commands/info/links.ts
+++ b/src/commands/info/links.ts
@@ -7,11 +7,9 @@ export default class LinksCommand extends BushCommand {
super('links', {
aliases: ['links', 'invite', 'support'],
category: 'info',
- description: {
- content: 'Sends bot links',
- usage: ['links'],
- examples: ['links']
- },
+ description: 'Sends bot links',
+ usage: ['links'],
+ examples: ['links'],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
slash: true
diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts
index 1d3f75a..619971f 100644
--- a/src/commands/info/ping.ts
+++ b/src/commands/info/ping.ts
@@ -6,11 +6,9 @@ export default class PingCommand extends BushCommand {
super('ping', {
aliases: ['ping'],
category: 'info',
- description: {
- content: 'Gets the latency of the bot',
- usage: ['ping'],
- examples: ['ping']
- },
+ description: 'Gets the latency of the bot',
+ usage: ['ping'],
+ examples: ['ping'],
slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts
index 3cf27b6..29cd2ce 100644
--- a/src/commands/info/pronouns.ts
+++ b/src/commands/info/pronouns.ts
@@ -6,32 +6,22 @@ export default class PronounsCommand extends BushCommand {
super('pronouns', {
aliases: ['pronouns', 'pronoun'],
category: 'info',
- description: {
- content: 'Finds the pronouns of a user using https://pronoundb.org.',
- usage: ['pronouns <user>'],
- examples: ['pronouns IRONM00N']
- },
+ description: 'Finds the pronouns of a user using https://pronoundb.org.',
+ usage: ['pronouns <user>'],
+ examples: ['pronouns IRONM00N'],
args: [
{
id: 'user',
+ description: 'The user to get pronouns for.',
type: 'globalUser',
- prompt: {
- start: 'Who would you like to view the pronouns of?',
- retry: '{error} Choose a valid user to view the pronouns of.',
- optional: true
- }
+ prompt: 'Who would you like to view the pronouns of?',
+ retry: '{error} Choose a valid user to view the pronouns of.',
+ optional: true,
+ slashType: 'USER'
}
],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
- slashOptions: [
- {
- name: 'user',
- description: 'The user to get pronouns for',
- type: 'USER',
- required: false
- }
- ],
slash: true
});
}
diff --git a/src/commands/info/snowflake.ts b/src/commands/info/snowflake.ts
index deb5692..bd0924f 100644
--- a/src/commands/info/snowflake.ts
+++ b/src/commands/info/snowflake.ts
@@ -21,33 +21,23 @@ export default class SnowflakeCommand extends BushCommand {
super('snowflake', {
aliases: ['snowflake', 'info', 'sf'],
category: 'info',
- description: {
- content: 'Provides information about the specified Snowflake.',
- usage: ['snowflake <snowflake>'],
- examples: ['snowflake 322862723090219008']
- },
+ description: 'Provides information about the specified Snowflake.',
+ usage: ['snowflake <snowflake>'],
+ examples: ['snowflake 322862723090219008'],
args: [
{
id: 'snowflake',
+ description: 'The snowflake you would like to get information about.',
type: 'snowflake',
- prompt: {
- start: 'Enter the snowflake you would like to get information about.',
- retry: '{error} Choose a valid snowflake.',
- optional: false
- }
+ prompt: 'What snowflake would you like to get information about?',
+ retry: '{error} Choose a valid snowflake.',
+ optional: false,
+ slashType: 'STRING'
}
],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
- slash: true,
- slashOptions: [
- {
- name: 'snowflake',
- description: 'The snowflake you would like to get information about.',
- type: 'STRING',
- required: true
- }
- ]
+ slash: true
});
}
public override async exec(message: BushMessage | BushSlashMessage, args: { snowflake: Snowflake }) {
@@ -58,24 +48,26 @@ export default class SnowflakeCommand extends BushCommand {
if (client.channels.cache.has(snowflake)) {
const channel: Channel = client.channels.cache.get(snowflake)!;
const channelInfo = [`**Type:** ${channel.type}`];
- if (['dm', 'group'].includes(channel.type)) {
+ if ((['DM', 'GROUP_DM'] as const).includes(channel.type)) {
const _channel = channel as DMChannel;
channelInfo.push(`**Recipient:** ${util.discord.escapeMarkdown(_channel.recipient.tag)} (${_channel.recipient.id})`);
snowflakeEmbed.setTitle(
`:snowflake: DM with ${util.discord.escapeMarkdown((channel as DMChannel).recipient.tag)} \`[Channel]\``
);
} else if (
- [
- 'GUILD_CATEGORY',
- 'GUILD_NEWS',
- 'GUILD_TEXT',
- 'GUILD_VOICE',
- 'GUILD_STORE',
- 'GUILD_STAGE_VOICE',
- 'GUILD_NEWS_THREAD',
- 'GUILD_PUBLIC_THREAD',
- 'GUILD_PRIVATE_THREAD'
- ].includes(channel.type)
+ (
+ [
+ 'GUILD_CATEGORY',
+ 'GUILD_NEWS',
+ 'GUILD_TEXT',
+ 'GUILD_VOICE',
+ 'GUILD_STORE',
+ 'GUILD_STAGE_VOICE',
+ 'GUILD_NEWS_THREAD',
+ 'GUILD_PUBLIC_THREAD',
+ 'GUILD_PRIVATE_THREAD'
+ ] as const
+ ).includes(channel.type)
) {
const _channel = channel as TextChannel | VoiceChannel | NewsChannel | StageChannel | CategoryChannel | StageChannel;
channelInfo.push(
diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts
index 601e044..8ed6304 100644
--- a/src/commands/info/userInfo.ts
+++ b/src/commands/info/userInfo.ts
@@ -7,31 +7,22 @@ export default class UserInfoCommand extends BushCommand {
super('userInfo', {
aliases: ['user-info', 'user', 'u'],
category: 'info',
- description: {
- content: 'Gives information about a specified user.',
- usage: ['user-info [user]'],
- examples: ['user-info 322862723090219008']
- },
+ description: 'Gives information about a specified user.',
+ usage: ['user-info [user]'],
+ examples: ['user-info 322862723090219008'],
args: [
{
id: 'user',
+ description: 'The user you would like to find information about.',
customType: util.arg.union('user', 'snowflake'),
- prompt: {
- start: 'What user would you like to find information about?',
- retry: '{error} Choose a valid user to find information about.',
- optional: true
- }
+ readableType: 'user|snowflake',
+ prompt: 'What user would you like to find information about?',
+ retry: '{error} Choose a valid user to find information about.',
+ optional: true,
+ slashType: 'USER'
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'The user you would like to find information about.',
- type: 'USER',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
});
@@ -108,7 +99,7 @@ export default class UserInfoCommand extends BushCommand {
if (member?.displayHexColor) serverUserInfo.push(`**Display Color:** ${member.displayHexColor}`);
if (user.id == '322862723090219008' && message.guild?.id == client.consts.mappings.guilds.bush)
serverUserInfo.push(`**General Deletions:** 1â…“`);
- if (['384620942577369088', '496409778822709251'].includes(user.id) && message.guild?.id == client.consts.mappings.guilds.bush)
+ if ((['384620942577369088', '496409778822709251'] as const).includes(user.id) && message.guild?.id == client.consts.mappings.guilds.bush)
serverUserInfo.push(`**General Deletions:** â…“`);
if (member?.nickname) serverUserInfo.push(`**Nickname:** ${util.discord.escapeMarkdown(member?.nickname)}`);
if (serverUserInfo.length)
diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts
index 19387f9..7e6eefd 100644
--- a/src/commands/leveling/leaderboard.ts
+++ b/src/commands/leveling/leaderboard.ts
@@ -6,31 +6,21 @@ export default class LeaderboardCommand extends BushCommand {
super('leaderboard', {
aliases: ['leaderboard', 'lb'],
category: 'leveling',
- description: {
- content: 'Allows you to see the users with the highest levels in the server.',
- usage: ['leaderboard [page]'],
- examples: ['leaderboard 5']
- },
+ description: 'View the users with the highest levels in the server.',
+ usage: ['leaderboard [page]'],
+ examples: ['leaderboard 5'],
args: [
{
id: 'page',
+ description: 'The page of the leaderboard to view.',
type: 'integer',
- prompt: {
- start: 'What would you like to set your first argument to be?',
- retry: '{error} Pick a valid argument.',
- optional: true
- }
+ prompt: 'What page of the leaderboard would you like to view?',
+ retry: '{error} Pick a valid argument.',
+ optional: true,
+ slashType: 'INTEGER',
}
],
slash: true,
- slashOptions: [
- {
- name: 'page',
- description: 'What would you like to set your first argument to be?',
- type: 'INTEGER',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts
index 36fb153..61e5d0b 100644
--- a/src/commands/leveling/level.ts
+++ b/src/commands/leveling/level.ts
@@ -20,31 +20,21 @@ export default class LevelCommand extends BushCommand {
super('level', {
aliases: ['level', 'rank', 'lvl'],
category: 'leveling',
- description: {
- content: 'Shows the level of a user',
- usage: ['level [user]'],
- examples: ['level', 'level @Tyman']
- },
+ description: 'Shows the level of a user',
+ usage: ['level [user]'],
+ examples: ['level', 'level @Tyman'],
args: [
{
id: 'user',
+ description: 'The user to get the level of.',
type: 'user',
- prompt: {
- start: 'What user would you like to see the level of?',
- retry: '{error} Choose a valid user to see the level of.',
- optional: true
- }
+ prompt: 'What user would you like to see the level of?',
+ retry: '{error} Choose a valid user to see the level of.',
+ optional: true,
+ slashType: 'USER'
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'The user to get the level of',
- type: 'USER',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts
index 499463a..69f562d 100644
--- a/src/commands/leveling/setLevel.ts
+++ b/src/commands/leveling/setLevel.ts
@@ -6,41 +6,25 @@ export default class SetLevelCommand extends BushCommand {
super('setLevel', {
aliases: ['set-level'],
category: 'leveling',
- description: {
- content: 'Sets the level of a user',
- usage: ['set-level <user> <level>'],
- examples: ['set-level @Moulberry 69'] //nice
- },
+ description: 'Sets the level of a user',
+ usage: ['set-level <user> <level>'],
+ examples: ['set-level @Moulberry 69'], //nice
args: [
{
id: 'user',
+ description: 'The user to set the level of.',
type: 'user',
- prompt: {
- start: 'What user would you like to change the level of?',
- retry: '{error} Choose a valid user to change the level of.'
- }
+ prompt: 'What user would you like to change the level of?',
+ retry: '{error} Choose a valid user to change the level of.',
+ slashType: 'USER'
},
{
id: 'level',
+ description: 'The level to set the user to.',
type: 'integer',
- prompt: {
- start: 'What level would you like to set the user to?',
- retry: '{error} Choose a valid level to set the user to.'
- }
- }
- ],
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to change the level of?',
- type: 'USER',
- required: true
- },
- {
- name: 'level',
- description: 'What level would you like to set the user to?',
- type: 'INTEGER',
- required: true
+ prompt: 'What level would you like to set the user to?',
+ retry: '{error} Choose a valid level to set the user to.',
+ slashType: 'INTEGER'
}
],
slash: true,
diff --git a/src/commands/leveling/setXp.ts b/src/commands/leveling/setXp.ts
index 2f2a6fa..68be528 100644
--- a/src/commands/leveling/setXp.ts
+++ b/src/commands/leveling/setXp.ts
@@ -6,44 +6,26 @@ export default class SetXpCommand extends BushCommand {
super('setXp', {
aliases: ['set-xp'],
category: 'leveling',
- description: {
- content: 'Sets the xp of a user',
- usage: ['set-xp <user> <xp>'],
- examples: ['set-xp @Moulberry 69k'] //nice
- },
+ description: 'Sets the xp of a user',
+ usage: ['set-xp <user> <xp>'],
+ examples: ['set-xp @Moulberry 69k'], //nice
args: [
{
id: 'user',
+ description: 'The user to set the xp of.',
type: 'user',
- prompt: {
- start: 'What user would you like to change the xp of?',
- retry: '{error} Choose a valid user to change the xp of.',
- required: true
- }
+ prompt: 'What user would you like to change the xp of?',
+ retry: '{error} Choose a valid user to change the xp of.',
+ slashType: 'USER'
},
{
id: 'xp',
+ description: 'The xp to set the user to.',
type: 'abbreviatedNumber',
match: 'restContent',
- prompt: {
- start: 'How much xp should the user have?',
- retry: "{error} Choose a valid number to set the user's xp to.",
- required: true
- }
- }
- ],
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to change the xp of?',
- type: 'USER',
- required: true
- },
- {
- name: 'xp',
- description: 'How much xp should the user have?',
- type: 'INTEGER',
- required: true
+ prompt: 'How much xp should the user have?',
+ retry: "{error} Choose a valid number to set the user's xp to.",
+ slashType: 'INTEGER'
}
],
slash: true,
diff --git a/src/commands/moderation/_lockdown.ts b/src/commands/moderation/_lockdown.ts
index 029db29..08d4011 100644
--- a/src/commands/moderation/_lockdown.ts
+++ b/src/commands/moderation/_lockdown.ts
@@ -5,27 +5,21 @@ export default class LockdownCommand extends BushCommand {
super('lockdown', {
aliases: ['lockdown', 'unlockdown'],
category: 'moderation',
- description: {
- content: 'Allows you to lockdown a channel or all configured channels..',
- usage: ['lockdown [--all]'],
- examples: ['lockdown', 'lockdown --all']
- },
+ description: 'Allows you to lockdown a channel or all configured channels..',
+ usage: ['lockdown [--all]'],
+ examples: ['lockdown', 'lockdown --all'],
args: [
{
id: 'all',
+ description: 'Whether or not to lock all channels',
match: 'flag',
- flag: '--all'
+ flag: '--all',
+ prompt: 'Would you like to lockdown all channels?',
+ slashType: 'BOOLEAN',
+ optional: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'all',
- description: 'Would you like to lockdown all channels?',
- type: 'BOOLEAN',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
@@ -34,6 +28,7 @@ export default class LockdownCommand extends BushCommand {
}
public override async exec(message: BushMessage | BushSlashMessage, args: { all: boolean }) {
+ // todo stop being lazy
return await message.util.reply('Unfortunately my developer is too lazy to implement this command.');
if (!args.all) {
if (!['GUILD_TEXT', 'GUILD_NEWS'].includes(message.channel!.type))
diff --git a/src/commands/moderation/activePunishments.ts b/src/commands/moderation/activePunishments.ts
new file mode 100644
index 0000000..d40f2ba
--- /dev/null
+++ b/src/commands/moderation/activePunishments.ts
@@ -0,0 +1,76 @@
+// import { BushCommand, ModLog, ModLogModel, type BushGuildMember, type BushMessage, type BushSlashMessage } from '#lib';
+// import { FindOptions, Op } from 'sequelize';
+
+// const punishmentTypes = ['ban', 'kick', 'mute', 'warn', 'role'] as const;
+
+// export default class ActivePunishmentsCommand extends BushCommand {
+// public constructor() {
+// super('active-punishments', {
+// aliases: ['active-punishments', 'ap'],
+// category: 'moderation',
+// description: 'Gets a list of all the active punishment in the server.',
+// usage: [`active-punishments [--moderator <user>] [--type <${punishmentTypes.map((v) => `'${v}'`).join('|')}>]`],
+// examples: ['active-punishments'],
+// args: [
+// {
+// id: 'moderator',
+// description: 'Only show active punishments by this moderator.',
+// type: 'user',
+// match: 'option',
+// prompt: 'Only show active punishments from what user?',
+// optional: true,
+// slashType: 'USER',
+// slashResolve: 'member'
+// },
+// {
+// id: 'type',
+// description: 'Only show active punishments of this type.',
+// customType: [...punishmentTypes],
+// readableType: punishmentTypes.map((v) => `'${v}'`).join('|'),
+// match: 'option',
+// optional: true,
+// slashType: 'STRING',
+// choices: punishmentTypes.map((v) => ({ name: v, value: v }))
+// }
+// ],
+// slash: true,
+// channel: 'guild',
+// hidden: true,
+// clientPermissions: (m) => util.clientSendAndPermCheck(m),
+// userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
+// });
+// }
+// public override async exec(
+// message: BushMessage | BushSlashMessage,
+// args: { moderator?: BushGuildMember; type: typeof punishmentTypes[number] }
+// ) {
+// const where: FindOptions<ModLogModel>['where'] = { guild: message.guild!.id };
+// if (args.moderator?.id) where.user = args.moderator.id;
+// if (args.type) {
+// switch (args.type) {
+// case 'ban':
+// where.type = { [Op.or]: ['PERM_BAN', 'TEMP_BAN', 'UNBAN'] };
+// break;
+// case 'kick':
+// where.type = { [Op.or]: ['KICK'] };
+// break;
+// case 'mute':
+// where.type = { [Op.or]: ['PERM_MUTE', 'TEMP_MUTE', 'UNMUTE'] };
+// break;
+// case 'warn':
+// where.type = { [Op.or]: ['WARN'] };
+// break;
+// case 'role':
+// where.type = { [Op.or]: ['PERM_PUNISHMENT_ROLE', 'TEMP_PUNISHMENT_ROLE', 'REMOVE_PUNISHMENT_ROLE'] };
+// break;
+// default:
+// return message.util.reply(`${util.emojis.error} You supplied an invalid case type to filter by.`);
+// }
+// }
+
+// const logs = await ModLog.findAll({
+// where,
+// order: [['createdAt', 'ASC']]
+// });
+// }
+// }
diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts
index 7c0d010..3d68a97 100644
--- a/src/commands/moderation/ban.ts
+++ b/src/commands/moderation/ban.ts
@@ -6,73 +6,52 @@ export default class BanCommand extends BushCommand {
super('ban', {
aliases: ['ban', 'force-ban', 'dban'],
category: 'moderation',
- description: {
- content: 'Ban a member from the server.',
- usage: ['ban <member> <reason> [--delete]'],
- examples: ['ban ironm00n 1 day commands in #general --delete 7']
- },
+ description: 'Ban a member from the server.',
+ usage: ['ban <member> <reason> [--delete]'],
+ examples: ['ban ironm00n 1 day commands in #general --delete 7'],
args: [
{
id: 'user',
+ description: 'The user that will be banned.',
customType: util.arg.union('user', 'snowflake'),
- prompt: {
- start: 'What user would you like to ban?',
- retry: '{error} Choose a valid user to ban.'
- }
+ prompt: 'What user would you like to ban?',
+ retry: '{error} Choose a valid user to ban.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason and duration of the ban.',
type: 'contentWithDuration',
match: 'restContent',
- prompt: {
- start: 'Why should this user be banned and for how long?',
- retry: '{error} Choose a valid ban reason and duration.',
- optional: true
- }
+ prompt: 'Why should this user be banned and for how long?',
+ retry: '{error} Choose a valid ban reason and duration.',
+ slashType: 'STRING',
+ optional: true
},
{
id: 'days',
+ description: 'The number of days of messages to delete when the user is banned, defaults to 0.',
flag: '--days',
match: 'option',
- customType: util.arg.range('integer', 0, 7, true)
+ prompt: "How many days of the user's messages would you like to delete?",
+ retry: '{error} Choose between 0 and 7 days to delete messages from the user for.',
+ customType: util.arg.range('integer', 0, 7, true),
+ optional: true,
+ slashType: 'INTEGER',
+ choices: [...Array(8).keys()].map((v) => ({ name: v.toString(), value: v }))
},
{
id: 'force',
+ description: 'Override permission checks.',
flag: '--force',
- match: 'flag'
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to ban?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be banned and for how long?',
- type: 'STRING',
- required: false
- },
- {
- name: 'days',
- description: "How many days of the user's messages would you like to delete?",
- type: 'INTEGER',
- required: false,
- choices: [
- { name: '0', value: 0 },
- { name: '1', value: 1 },
- { name: '2', value: 2 },
- { name: '3', value: 3 },
- { name: '4', value: 4 },
- { name: '5', value: 5 },
- { name: '6', value: 6 },
- { name: '7', value: 7 }
- ]
- }
- ],
channel: 'guild',
clientPermissions: ['BAN_MEMBERS'],
userPermissions: ['BAN_MEMBERS']
@@ -134,7 +113,7 @@ export default class BanCommand extends BushCommand {
});
const responseMessage = () => {
- const victim = util.format.bold(user.tag);
+ const victim = util.format.input(user.tag);
switch (responseCode) {
case 'missing permissions':
return `${util.emojis.error} Could not ban ${victim} because I am missing the **Ban Members** permission.`;
diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts
index 0204d84..714a2e5 100644
--- a/src/commands/moderation/evidence.ts
+++ b/src/commands/moderation/evidence.ts
@@ -6,26 +6,28 @@ export default class EvidenceCommand extends BushCommand {
super('evidence', {
aliases: ['evidence'],
category: 'moderation',
- description: {
- content: 'Add evidence to a modlog case.',
- usage: ['evidence <case_id> <evidence>'],
- examples: ['evidence ']
- },
- slash: true,
- slashOptions: [
+ description: 'Add evidence to a modlog case.',
+ usage: ['evidence <case_id> <evidence>'],
+ examples: ['evidence 9210b1ea-91f5-4ea2-801b-02b394469c77 was spamming in #general'],
+ args: [
{
- name: 'case_id',
- description: 'What case would you like to modify the evidence of?',
- type: 'STRING',
- required: true
+ id: 'case_id',
+ description: 'The case to modify the evidence of.',
+ type: 'string',
+ prompt: 'What case would you like to modify the evidence of?',
+ slashType: 'STRING',
+ only: 'slash'
},
{
- name: 'evidence',
- description: 'What would you like to modify the evidence to?',
- type: 'STRING',
- required: true
+ id: 'evidence',
+ description: 'The value to set the evidence to.',
+ type: 'string',
+ prompt: 'What would you like to modify the evidence to?',
+ slashType: 'STRING',
+ only: 'slash'
}
],
+ slash: true,
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts
index 9c22e63..de7b310 100644
--- a/src/commands/moderation/hideCase.ts
+++ b/src/commands/moderation/hideCase.ts
@@ -5,30 +5,20 @@ export default class HideCaseCommand extends BushCommand {
super('hideCase', {
aliases: ['hide-case', 'hide_case', 'showcase', 'show_case', 'cover-up-mod-abuse', 'cover_up_mod_abuse'],
category: 'moderation',
- description: {
- content: 'Hide a particular modlog case from the modlog command unless the `--hidden` flag is specified',
- usage: ['hide-case <case_id>'],
- examples: ['hide-case 9210b1ea-91f5-4ea2-801b-02b394469c77']
- },
+ description: 'Hide a particular modlog case from the modlog command unless the `--hidden` flag is specified',
+ usage: ['hide-case <case_id>'],
+ examples: ['hide-case 9210b1ea-91f5-4ea2-801b-02b394469c77'],
args: [
{
id: 'case_id',
+ description: 'The id of the case to be hidden.',
type: 'string',
- prompt: {
- start: 'What modlog case would you like to hide?',
- retry: '{error} Choose a valid case id.'
- }
+ prompt: 'What modlog case would you like to hide?',
+ retry: '{error} Choose a valid case id.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'case_id',
- description: 'What modlog case would you like to hide?',
- type: 'STRING',
- required: true
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']),
channel: 'guild'
diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts
index 1f1c2fb..9463154 100644
--- a/src/commands/moderation/kick.ts
+++ b/src/commands/moderation/kick.ts
@@ -5,51 +5,40 @@ export default class KickCommand extends BushCommand {
super('kick', {
aliases: ['kick'],
category: 'moderation',
- description: {
- content: 'Kick a user.',
- usage: ['kick <member> <reason>'],
- examples: ['kick @user bad']
- },
+ description: 'Kick a user.',
+ usage: ['kick <member> <reason>'],
+ examples: ['kick @user bad'],
args: [
{
id: 'user',
+ description: 'The user to kick.',
type: 'user',
- prompt: {
- start: 'What user would you like to kick?',
- retry: '{error} Choose a valid user to kick.'
- }
+ prompt: 'What user would you like to kick?',
+ retry: '{error} Choose a valid user to kick.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason for the kick.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'Why should this user be kicked?',
- retry: '{error} Choose a valid kick reason.',
- optional: true
- }
+ prompt: 'Why should this user be kicked?',
+ retry: '{error} Choose a valid kick reason.',
+ optional: true,
+ slashType: 'STRING'
},
{
id: 'force',
+ description: 'Override permission checks.',
flag: '--force',
- match: 'flag'
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to kick?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be kicked?',
- type: 'STRING',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['KICK_MEMBERS']),
userPermissions: ['KICK_MEMBERS']
});
@@ -77,7 +66,7 @@ export default class KickCommand extends BushCommand {
});
const responseMessage = () => {
- const victim = util.format.bold(member.user.tag);
+ const victim = util.format.input(member.user.tag);
switch (responseCode) {
case 'missing permissions':
return `${util.emojis.error} Could not kick ${victim} because I am missing the \`Kick Members\` permission.`;
diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts
index 8bdee59..474eaa9 100644
--- a/src/commands/moderation/modlog.ts
+++ b/src/commands/moderation/modlog.ts
@@ -6,48 +6,36 @@ export default class ModlogCommand extends BushCommand {
super('modlog', {
aliases: ['modlog', 'modlogs'],
category: 'moderation',
- description: {
- content: "View a user's modlogs, or view a specific case.",
- usage: ['modlogs <search> [--hidden]'],
- examples: ['modlogs @Tyman']
- },
+ description: "View a user's modlogs, or view a specific case.",
+ usage: ['modlogs <search> [--hidden]'],
+ examples: ['modlogs @Tyman'],
args: [
{
id: 'search',
+ description: 'The case id or user to search for modlogs by.',
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.'
- }
+ prompt: 'What case id or user would you like to see?',
+ retry: '{error} Choose a valid case id or user.',
+ slashType: 'STRING'
},
{
id: 'hidden',
+ description: 'Show hidden modlogs.',
+ prompt: 'Would you like to see hidden modlogs?',
match: 'flag',
flag: ['--hidden', '-h'],
- default: false
+ default: false,
+ optional: true,
+ slashType: 'BOOLEAN'
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
- userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES']),
slash: true,
- slashOptions: [
- {
- name: 'search',
- description: 'What case id or user would you like to see?',
- type: 'STRING',
- required: true
- },
- {
- name: 'hidden',
- description: 'Would you like to see hidden modlogs?',
- type: 'BOOLEAN',
- required: false
- }
- ]
+ clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
});
}
- #generateModlogInfo(log: ModLog, showUser: boolean): string {
+ static generateModlogInfo(log: ModLog, showUser: boolean): string {
const trim = (str: string): string => (str.endsWith('\n') ? str.substring(0, str.length - 1).trim() : str.trim());
const modLog = [`**Case ID**: ${util.discord.escapeMarkdown(log.id)}`, `**Type**: ${log.type.toLowerCase()}`];
if (showUser) modLog.push(`**User**: <@!${log.user}>`);
@@ -75,7 +63,7 @@ export default class ModlogCommand extends BushCommand {
const niceLogs = logs
.filter((log) => !log.pseudo)
.filter((log) => !(log.hidden && hidden))
- .map((log) => this.#generateModlogInfo(log, false));
+ .map((log) => ModlogCommand.generateModlogInfo(log, false));
if (!logs.length || !niceLogs.length)
return message.util.reply(`${util.emojis.error} **${foundUser.tag}** does not have any modlogs.`);
const chunked: string[][] = util.chunk(niceLogs, 4);
@@ -96,7 +84,7 @@ export default class ModlogCommand extends BushCommand {
return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
const embed = {
title: `Case ${entry.id}`,
- description: this.#generateModlogInfo(entry, true),
+ description: ModlogCommand.generateModlogInfo(entry, true),
color: util.colors.default
};
return await ButtonPaginator.send(message, [embed]);
diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts
index 44e1db4..0584d97 100644
--- a/src/commands/moderation/mute.ts
+++ b/src/commands/moderation/mute.ts
@@ -5,51 +5,40 @@ export default class MuteCommand extends BushCommand {
super('mute', {
aliases: ['mute'],
category: 'moderation',
- description: {
- content: 'Mute a user.',
- usage: ['mute <member> [reason] [duration]'],
- examples: ['mute ironm00n 1 day commands in #general']
- },
+ description: 'Mute a user.',
+ usage: ['mute <member> [reason] [duration]'],
+ examples: ['mute ironm00n 1 day commands in #general'],
args: [
{
id: 'user',
+ description: 'The user to mute.',
type: 'user',
- prompt: {
- start: 'What user would you like to mute?',
- retry: '{error} Choose a valid user to mute.'
- }
+ prompt: 'What user would you like to mute?',
+ retry: '{error} Choose a valid user to mute.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason for the mute.',
type: 'contentWithDuration',
match: 'rest',
- prompt: {
- start: 'Why should this user be muted and for how long?',
- retry: '{error} Choose a valid mute reason and duration.',
- optional: true
- }
+ prompt: 'Why should this user be muted and for how long?',
+ retry: '{error} Choose a valid mute reason and duration.',
+ optional: true,
+ slashType:'STRING'
},
{
id: 'force',
+ description: 'Override permission checks.',
flag: '--force',
- match: 'flag'
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to mute?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be muted and for how long?',
- type: 'STRING',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
@@ -95,7 +84,7 @@ export default class MuteCommand extends BushCommand {
const responseMessage = () => {
const prefix = util.prefix(message);
- const victim = util.format.bold(member.user.tag);
+ const victim = util.format.input(member.user.tag);
switch (responseCode) {
case 'missing permissions':
return `${util.emojis.error} Could not mute ${victim} because I am missing the **Manage Roles** permission.`;
diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts
index 4d8db08..6bc62de 100644
--- a/src/commands/moderation/purge.ts
+++ b/src/commands/moderation/purge.ts
@@ -1,4 +1,4 @@
-import { BushCommand, BushMessage } from '#lib';
+import { BushCommand, BushMessage, BushUser } from '#lib';
import { Collection, type Snowflake } from 'discord.js';
export default class PurgeCommand extends BushCommand {
@@ -6,61 +6,56 @@ export default class PurgeCommand extends BushCommand {
super('purge', {
aliases: ['purge'],
category: 'moderation',
- description: {
- content: 'A command to mass delete messages.',
- usage: ['purge <amount>'],
- examples: ['purge 20']
- },
+ description: 'A command to mass delete messages.',
+ usage: ['purge <amount> [--bot] [--user <user>]'],
+ examples: ['purge 20'],
args: [
{
id: 'amount',
+ description: 'The amount of messages to purge.',
customType: util.arg.range('integer', 1, 100, true),
- prompt: {
- start: 'How many messages would you like to purge?',
- retry: '{error} Please pick a number between 1 and 100.'
- }
+ readableType: 'integer',
+ prompt: 'How many messages would you like to purge?',
+ retry: '{error} Please pick a number between 1 and 100.',
+ slashType: 'INTEGER',
+ minValue: 1,
+ maxValue: 100
},
{
id: 'bot',
+ description: 'Filter messages to only include those that are from bots.',
match: 'flag',
- flag: '--bot'
+ flag: '--bot',
+ prompt: 'Would you like to only delete messages that are from bots?',
+ slashType: 'BOOLEAN',
+ optional: true
},
{
id: 'user',
+ description: 'Filter messages to only include those that are from a specified user.',
match: 'option',
- flag: '--user'
+ type: 'user',
+ flag: '--user',
+ slashType: 'BOOLEAN',
+ optional: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'amount',
- description: 'How many messages would you like to purge?',
- type: 'INTEGER',
- required: true
- },
- {
- name: 'bot',
- description: 'Would you like to only delete messages that are from bots?',
- type: 'BOOLEAN',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES', 'EMBED_LINKS'], true),
userPermissions: ['MANAGE_MESSAGES'],
channel: 'guild'
});
}
- public override async exec(message: BushMessage, args: { amount: number; bot: boolean }) {
+ public override async exec(message: BushMessage, args: { amount: number; bot: boolean, user: BushUser }) {
if (message.channel.type === 'DM') return message.util.reply(`${util.emojis.error} You cannot run this command in dms.`);
if (args.amount > 100 || args.amount < 1) return message.util.reply(`${util.emojis.error} `);
const messageFilter = (filterMessage: BushMessage): boolean => {
- const shouldFilter = new Array<boolean>();
- if (args.bot) {
- shouldFilter.push(filterMessage.author.bot);
- }
+ const shouldFilter: boolean[] = [];
+ if (args.bot) shouldFilter.push(filterMessage.author.bot);
+ if (args.user) shouldFilter.push(filterMessage.author.id === args.user.id);
+
return shouldFilter.filter((bool) => bool === false).length === 0 && filterMessage.id !== message.id;
};
const _messages = (await message.channel.messages.fetch({ limit: 100, before: message.id }))
diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts
index 80f2c01..e847aba 100644
--- a/src/commands/moderation/removeReactionEmoji.ts
+++ b/src/commands/moderation/removeReactionEmoji.ts
@@ -1,35 +1,35 @@
import { BushCommand, type BushMessage } from '#lib';
-import { type Emoji, type Snowflake } from 'discord.js';
+import { Message, type Emoji, type Snowflake } from 'discord.js';
export default class RemoveReactionEmojiCommand extends BushCommand {
public constructor() {
super('removeReactionEmoji', {
aliases: ['remove-reaction-emoji', 'rre'],
category: 'moderation',
- description: {
- content: 'Deleted all the reactions of a certain emoji from a message.',
- usage: ['remove-reaction-emoji <message> <emoji>'],
- examples: ['remove-reaction-emoji 791413052347252786 <:omegaclown:782630946435366942>']
- },
+ description: 'Delete all the reactions of a certain emoji from a message.',
+ usage: ['remove-reaction-emoji <message> <emoji>'],
+ examples: ['remove-reaction-emoji 791413052347252786 <:omegaclown:782630946435366942>'],
args: [
{
- id: 'messageToRemoveFrom',
+ id: 'message',
+ description: 'The message to remove all the reactions of a certain emoji from.',
type: 'guildMessage',
- prompt: {
- start: 'What message would you like to remove a reaction from?',
- retry: '{error} Please pick a valid message.'
- }
+ prompt: 'What message would you like to remove a reaction from?',
+ retry: '{error} Please pick a valid message.',
+ slashType: 'STRING'
},
{
id: 'emoji',
+ description: 'The emoji to remove all the reactions of from a message.',
customType: util.arg.union('emoji', 'snowflake'),
+ readableType:'emoji|snowflake',
match: 'restContent',
- prompt: {
- start: 'What emoji would you like to remove?',
- retry: '{error} Please pick a valid emoji.'
- }
+ prompt: 'What emoji would you like to remove?',
+ retry: '{error} Please pick a valid emoji.',
+ slashType: 'STRING'
}
],
+ slash: true,
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES', 'EMBED_LINKS'], true),
userPermissions: ['MANAGE_MESSAGES', 'MANAGE_EMOJIS_AND_STICKERS'] // Can't undo the removal of 1000s of reactions
@@ -38,25 +38,27 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
public override async exec(
message: BushMessage,
- { messageToRemoveFrom, emoji }: { messageToRemoveFrom: BushMessage; emoji: Emoji | Snowflake }
+ args: { message: BushMessage|Snowflake; emoji: Emoji | Snowflake }
) {
- const id = !['string'].includes(typeof emoji);
- const emojiID = !id ? `${emoji}` : (emoji as Emoji).id;
- const success = await messageToRemoveFrom.reactions.cache
+ const resolvedMessage = args.message instanceof Message ? args.message : await message.channel.messages.fetch(args.message )
+
+ const id = !(['string'] as const).includes(typeof args.emoji);
+ const emojiID = !id ? `${args.emoji}` : (args.emoji as Emoji).id;
+ const success = await resolvedMessage.reactions.cache
?.get(emojiID!)
?.remove()
?.catch(() => {});
if (success) {
return await message.util.reply(
- `${util.emojis.success} Removed all reactions of \`${id ? emojiID : emoji}\` from the message with the id of \`${
- messageToRemoveFrom.id
+ `${util.emojis.success} Removed all reactions of \`${id ? emojiID : args.emoji}\` from the message with the id of \`${
+ resolvedMessage.id
}\`.`
);
} else {
return await message.util.reply(
`${util.emojis.error} There was an error removing all reactions of \`${
- id ? emojiID : emoji
- }\` from the message with the id of \`${messageToRemoveFrom.id}\`.`
+ id ? emojiID : args.emoji
+ }\` from the message with the id of \`${resolvedMessage.id}\`.`
);
}
}
diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts
index dd74bb4..7ca0a5d 100644
--- a/src/commands/moderation/role.ts
+++ b/src/commands/moderation/role.ts
@@ -1,47 +1,54 @@
import { AllowedMentions, BushCommand, type BushGuildMember, type BushMessage, type BushRole, type BushSlashMessage } from '#lib';
import { type ArgumentOptions, type Flag } from 'discord-akairo';
+import { Snowflake } from 'discord.js';
export default class RoleCommand extends BushCommand {
public constructor() {
super('role', {
aliases: ['role', 'rr', 'ar', 'ra'],
category: 'moderation',
- description: {
- content: "Manages users' roles.",
- usage: ['role <add|remove> <user> <role> [duration]'],
- examples: ['role add spammer nogiveaways 7days', 'ra tyman muted', 'rr tyman staff']
- },
- slash: true,
- slashOptions: [
+ description: "Manages users' roles.",
+ usage: ['role <add|remove> <member> <role> [duration]'],
+ examples: ['role add spammer nogiveaways 7days', 'ra tyman muted', 'rr tyman staff'],
+ args: [
{
- name: 'action',
- description: 'Would you like to add or remove a role?',
- type: 'STRING',
+ id: 'action',
+ description: 'Whether to add or remove a role for the the user.',
+ prompt: 'Would you like to add or remove a role?',
+ slashType: 'STRING',
choices: [
{ name: 'add', value: 'add' },
{ name: 'remove', value: 'remove' }
],
- required: true
+ only: 'slash'
},
{
- name: 'user',
- description: 'What user do you want to add/remove the role to/from?',
- type: 'USER',
- required: true
+ id: 'member',
+ description: 'The user to add/remove a role to/from.',
+ prompt: 'What user do you want to add/remove a role to/from?',
+ slashType: 'USER',
+ slashResolve: 'member',
+ optional: true,
+ only: 'slash'
},
{
- name: 'role',
+ id: 'role',
description: 'The role you would like to add/remove from the to/from.',
- type: 'ROLE',
- required: true
+ prompt: 'What role would you like to add/remove from the user?',
+ slashType: 'ROLE',
+ optional: true,
+ only: 'slash'
},
{
- name: 'duration',
- description: 'How long would you like to role to last?',
- type: 'STRING',
- required: false
+ id: 'duration',
+ description: 'The time before the role will be removed (ignored if removing a role).',
+ prompt: 'How long would you like to role to last?',
+ slashType: 'STRING',
+ optional: true,
+ only: 'slash'
}
],
+ slash: true,
channel: 'guild',
typing: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES', 'EMBED_LINKS'], true),
@@ -49,10 +56,10 @@ export default class RoleCommand extends BushCommand {
});
}
- override *args(message: BushMessage): IterableIterator<ArgumentOptions | Flag> {
- const action = ['rr'].includes(message.util.parsed?.alias ?? '')
+ override *args(message: BushMessage): Generator<ArgumentOptions | Flag> {
+ const action = (['rr'] as const).includes(message.util.parsed?.alias ?? '')
? 'remove'
- : ['ar', 'ra'].includes(message.util.parsed?.alias ?? '')
+ : (['ar', 'ra'] as const).includes(message.util.parsed?.alias ?? '')
? 'add'
: yield {
id: 'action',
@@ -63,7 +70,7 @@ export default class RoleCommand extends BushCommand {
}
};
- const user = yield {
+ const member = yield {
id: 'user',
type: 'member',
prompt: {
@@ -84,19 +91,21 @@ export default class RoleCommand extends BushCommand {
}
};
- return { action, user, role: (_role as any).role ?? _role, duration: (_role as any).duration };
+ const force = yield {
+ id: 'force',
+ description: 'Override permission checks and ban the user anyway.',
+ flag: '--force',
+ match: 'flag'
+ };
+
+ return { action, member: member, role: (_role as any).role ?? _role, duration: (_role as any).duration, force };
}
public override async exec(
message: BushMessage | BushSlashMessage,
- {
- action,
- user: member,
- role,
- duration
- }: { action: 'add' | 'remove'; user: BushGuildMember; role: BushRole; duration?: number | null }
+ args: { action: 'add' | 'remove'; member: BushGuildMember; role: BushRole; duration?: number | null; force?: boolean }
) {
- if (duration === null) duration = 0;
+ if (args.duration === null) args.duration = 0;
if (
!message.member!.permissions.has('MANAGE_ROLES') &&
message.member!.id !== message.guild?.ownerId &&
@@ -106,11 +115,11 @@ export default class RoleCommand extends BushCommand {
let mappedRole: { name: string; id: string };
for (let i = 0; i < mappings.roleMap.length; i++) {
const a = mappings.roleMap[i];
- if (a.id == role.id) mappedRole = a;
+ if (a.id === args.role.id) mappedRole = a;
}
if (!mappedRole! || !Reflect.has(mappings.roleWhitelist, mappedRole.name)) {
return await message.util.reply({
- content: `${util.emojis.error} <@&${role.id}> is not whitelisted, and you do not have manage roles permission.`,
+ content: `${util.emojis.error} <@&${args.role.id}> is not whitelisted, and you do not have manage roles permission.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -120,44 +129,54 @@ export default class RoleCommand extends BushCommand {
}
return;
});
- if (!message.member!.roles.cache.some((role) => allowedRoles.includes(role.id))) {
+ if (!message.member!.roles.cache.some((role) => (allowedRoles as Snowflake[]).includes(role.id))) {
return await message.util.reply({
- content: `${util.emojis.error} <@&${role.id}> is whitelisted, but you do not have any of the roles required to manage it.`,
+ content: `${util.emojis.error} <@&${args.role.id}> is whitelisted, but you do not have any of the roles required to manage it.`,
allowedMentions: AllowedMentions.none()
});
}
}
- const shouldLog = this.punishmentRoleNames.includes(role.name);
+ const shouldLog = this.punishmentRoleNames.includes(args.role.name);
const responseCode =
- action === 'add'
- ? await member.addRole({ moderator: message.member!, addToModlog: shouldLog, role, duration })
- : await member.removeRole({ moderator: message.member!, addToModlog: shouldLog, role, duration });
+ args.action === 'add'
+ ? await args.member.addRole({
+ moderator: message.member!,
+ addToModlog: shouldLog,
+ role: args.role,
+ duration: args.duration
+ })
+ : await args.member.removeRole({
+ moderator: message.member!,
+ addToModlog: shouldLog,
+ role: args.role,
+ duration: args.duration
+ });
const responseMessage = () => {
- const victim = util.format.bold(member.user.tag);
+ const victim = util.format.input(args.member.user.tag);
switch (responseCode) {
case 'user hierarchy':
- return `${util.emojis.error} <@&${role.id}> is higher or equal to your highest role.`;
+ return `${util.emojis.error} <@&${args.role.id}> is higher or equal to your highest role.`;
case 'role managed':
- return `${util.emojis.error} <@&${role.id}> is managed by an integration and cannot be managed.`;
+ return `${util.emojis.error} <@&${args.role.id}> is managed by an integration and cannot be managed.`;
case 'client hierarchy':
- return `${util.emojis.error} <@&${role.id}> is higher or equal to my highest role.`;
+ return `${util.emojis.error} <@&${args.role.id}> is higher or equal to my highest role.`;
case 'error creating modlog entry':
return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case 'error creating role entry' || 'error removing role entry':
return `${util.emojis.error} There was an error ${
- action === 'add' ? 'creating' : 'removing'
+ args.action === 'add' ? 'creating' : 'removing'
} a punishment entry, please report this to my developers.`;
case 'error adding role' || 'error removing role':
- return `${util.emojis.error} An error occurred while trying to ${action} <@&${role.id}> ${
- action === 'add' ? 'to' : 'from'
+ return `${util.emojis.error} An error occurred while trying to ${args.action} <@&${args.role.id}> ${
+ args.action === 'add' ? 'to' : 'from'
} ${victim}.`;
case 'success':
- return `${util.emojis.success} Successfully ${action === 'add' ? 'added' : 'removed'} <@&${role.id}> ${
- action === 'add' ? 'to' : 'from'
- } ${victim}${duration ? ` for ${util.humanizeDuration(duration)}` : ''}.`;
+ return `${util.emojis.success} Successfully ${args.action === 'add' ? 'added' : 'removed'} <@&${args.role.id}> ${
+ args.action === 'add' ? 'to' : 'from'
+ } ${victim}${args.duration ? ` for ${util.humanizeDuration(args.duration)}` : ''}.`;
}
};
diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts
index e05a409..949038c 100644
--- a/src/commands/moderation/slowmode.ts
+++ b/src/commands/moderation/slowmode.ts
@@ -14,40 +14,32 @@ export default class SlowModeCommand extends BushCommand {
super('slowmode', {
aliases: ['slowmode', 'slow'],
category: 'moderation',
- description: {
- content: 'A command to set the slowmode of a channel.',
- usage: ['slowmode <length>'],
- examples: ['slowmode 3']
- },
+ description: 'A command to set the slowmode of a channel.',
+ usage: ['slowmode <length> [channel]'],
+ examples: ['slowmode 3'],
args: [
{
id: 'length',
+ description: 'The amount of time to set the slowmode of a channel to.',
customType: Argument.union('duration', 'durationSeconds', 'off', 'none', 'disable'),
- prompt: {
- start: 'What would you like to set the slowmode to?',
- retry: '{error} Please set the slowmode to a valid length.',
- optional: true
- }
+ readableType: "duration|durationSeconds|'off'|'none'|'disable'",
+ prompt: 'What would you like to set the slowmode to?',
+ retry: '{error} Please set the slowmode to a valid length.',
+ optional: true,
+ slashType: 'INTEGER'
},
{
id: 'channel',
+ description: 'The channel to change the slowmode of, defaults to the current channel.',
type: 'channel',
- prompt: {
- start: 'What channel would you like to change?',
- retry: '{error} Choose a valid channel.',
- optional: true
- }
+ prompt: 'What channel would you like to change?',
+ retry: '{error} Choose a valid channel.',
+ optional: true,
+ slashType: 'CHANNEL',
+ channelTypes: ['GUILD_TEXT', 'GUILD_PRIVATE_THREAD', 'GUILD_PUBLIC_THREAD']
}
],
slash: true,
- slashOptions: [
- {
- name: 'channel',
- description: 'What channel would you like to change the slowmode of?',
- type: 'CHANNEL',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_CHANNELS', 'EMBED_LINKS'], true),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
@@ -67,16 +59,16 @@ export default class SlowModeCommand extends BushCommand {
if (message.channel!.type === 'DM')
return await message.util.reply(`${util.emojis.error} This command cannot be run in dms.`);
if (!channel) channel = message.channel as any;
- if (!(channel instanceof TextChannel) && !(channel instanceof ThreadChannel))
+ if (!(['GUILD_TEXT', 'GUILD_PRIVATE_THREAD', 'GUILD_PUBLIC_THREAD'] as const).includes(channel.type))
return await message.util.reply(`${util.emojis.error} <#${channel.id}> is not a text or thread channel.`);
if (length) {
length =
- typeof length === 'string' && !['off', 'none', 'disable'].includes(length)
+ typeof length === 'string' && !(['off', 'none', 'disable'] as const).includes(length)
? await util.arg.cast('duration', message, length)
: length;
}
- const length2: number = ['off', 'none', 'disable'].includes(length as string) ? 0 : (length as number);
+ const length2: number = (['off', 'none', 'disable'] as const).includes(length as string) ? 0 : (length as number);
const setSlowmode = await (channel as ThreadChannel | TextChannel)
.setRateLimitPerUser(length2 / 1000, `Changed by ${message.author.tag} (${message.author.id}).`)
diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts
index 1492b63..8444801 100644
--- a/src/commands/moderation/unban.ts
+++ b/src/commands/moderation/unban.ts
@@ -5,46 +5,30 @@ export default class UnbanCommand extends BushCommand {
super('unban', {
aliases: ['unban'],
category: 'moderation',
- description: {
- content: 'Unban a member from the server.',
- usage: ['unban <member> <reason> [--delete]'],
- examples: ['unban 322862723090219008 I changed my mind, commands are allowed in #general']
- },
+ description: 'Unban a member from the server.',
+ usage: ['unban <member> <reason>'],
+ examples: ['unban 322862723090219008 I changed my mind, commands are allowed in #general'],
args: [
{
id: 'user',
+ description: 'The user to unban.',
type: 'globalUser',
- prompt: {
- start: 'What user would you like to unban?',
- retry: '{error} Choose a valid user to unban.'
- }
+ prompt: 'What user would you like to unban?',
+ retry: '{error} Choose a valid user to unban.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason for the unban',
type: 'string',
match: 'restContent',
- prompt: {
- start: 'Why should this user be unbanned?',
- retry: '{error} Choose a valid unban reason.',
- optional: true
- }
+ prompt: 'Why should this user be unbanned?',
+ retry: '{error} Choose a valid unban reason.',
+ optional: true,
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to unban?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be unbanned?',
- type: 'STRING',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: ['BAN_MEMBERS'],
userPermissions: ['BAN_MEMBERS']
@@ -58,7 +42,7 @@ export default class UnbanCommand extends BushCommand {
});
const responseMessage = () => {
- const victim = util.format.bold(user.tag);
+ const victim = util.format.input(user.tag);
switch (responseCode) {
case 'missing permissions':
return `${util.emojis.error} Could not unban ${victim} because I am missing the **Ban Members** permission.`;
diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts
index c31ce21..0c59b1f 100644
--- a/src/commands/moderation/unmute.ts
+++ b/src/commands/moderation/unmute.ts
@@ -13,51 +13,40 @@ export default class UnmuteCommand extends BushCommand {
super('unmute', {
aliases: ['unmute'],
category: 'moderation',
- description: {
- content: 'unmute a user.',
- usage: ['unmute <member> [reason]'],
- examples: ['unmute 322862723090219008 1 day commands in #general']
- },
+ description: 'unmute a user.',
+ usage: ['unmute <member> [reason]'],
+ examples: ['unmute 322862723090219008 1 day commands in #general'],
args: [
{
id: 'user',
+ description: 'The user to unmute.',
type: 'user',
- prompt: {
- start: 'What user would you like to unmute?',
- retry: '{error} Choose a valid user to unmute.'
- }
+ prompt: 'What user would you like to unmute?',
+ retry: '{error} Choose a valid user to unmute.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason for the unmute.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'Why should this user be unmuted?',
- retry: '{error} Choose a valid unmute reason.',
- optional: true
- }
+ prompt: 'Why should this user be unmuted?',
+ retry: '{error} Choose a valid unmute reason.',
+ optional: true,
+ slashType: 'STRING'
},
{
id: 'force',
+ description: 'Override permission checks.',
flag: '--force',
- match: 'flag'
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to unmute?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be unmuted?',
- type: 'STRING',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_ROLES']),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
@@ -87,7 +76,7 @@ export default class UnmuteCommand extends BushCommand {
const responseMessage = () => {
const prefix = util.prefix(message);
- const victim = util.format.bold(member.user.tag);
+ const victim = util.format.input(member.user.tag);
switch (responseCode) {
case 'missing permissions':
return `${error} Could not unmute ${victim} because I am missing the **Manage Roles** permission.`;
diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts
index 9b58cf6..2212548 100644
--- a/src/commands/moderation/warn.ts
+++ b/src/commands/moderation/warn.ts
@@ -13,50 +13,39 @@ export default class WarnCommand extends BushCommand {
super('warn', {
aliases: ['warn'],
category: 'moderation',
- description: {
- content: 'Warn a user.',
- usage: ['warn <member> [reason]'],
- examples: ['warn @Tyman being cool']
- },
+ description: 'Warn a user.',
+ usage: ['warn <member> [reason]'],
+ examples: ['warn @Tyman being cool'],
args: [
{
id: 'user',
+ description: 'The user to warn.',
type: 'user',
- prompt: {
- start: 'What user would you like to warn?',
- retry: '{error} Choose a valid user to warn.'
- }
+ prompt: 'What user would you like to warn?',
+ retry: '{error} Choose a valid user to warn.',
+ slashType: 'USER'
},
{
id: 'reason',
+ description: 'The reason for the warn.',
match: 'rest',
- prompt: {
- start: 'Why should this user be warned?',
- retry: '{error} Choose a valid warn reason.',
- optional: true
- }
+ prompt: 'Why should this user be warned?',
+ retry: '{error} Choose a valid warn reason.',
+ slashType: 'STRING',
+ optional: true
},
{
id: 'force',
+ description: 'Override permission checks.',
flag: '--force',
- match: 'flag'
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'What user would you like to warn?',
- type: 'USER',
- required: true
- },
- {
- name: 'reason',
- description: 'Why should this user be warned?',
- type: 'STRING',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
@@ -83,7 +72,7 @@ export default class WarnCommand extends BushCommand {
});
const responseMessage = () => {
- const victim = util.format.bold(member.user.tag);
+ const victim = util.format.input(member.user.tag);
switch (response) {
case 'error creating modlog entry':
return `${util.emojis.error} While warning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
diff --git a/src/commands/moulberry-bush/capePerms.ts b/src/commands/moulberry-bush/capePerms.ts
index 237ca89..2749430 100644
--- a/src/commands/moulberry-bush/capePerms.ts
+++ b/src/commands/moulberry-bush/capePerms.ts
@@ -7,31 +7,20 @@ export default class CapePermissionsCommand extends BushCommand {
super('capePermissions', {
aliases: ['cape-perms', 'cape-perm', 'cape-permissions'],
category: "Moulberry's Bush",
- description: {
- content: 'A command to see what capes someone has access to.',
- usage: ['cape-perms <user>'],
- examples: ['cape-perms IRONM00N']
- },
+ description: 'A command to see what capes someone has access to.',
+ usage: ['cape-perms <user>'],
+ examples: ['cape-perms IRONM00N'],
args: [
{
id: 'ign',
+ description: 'The ign of the player you would like to view the capes permissions of.',
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.',
- optional: false
- }
+ prompt: 'Who would you like to see the cape permissions of?',
+ retry: '{error} Choose someone to see the capes their available capes.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'ign',
- description: 'The ign of the player you would like to view the capes permissions of.',
- type: 'STRING',
- required: true
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
channel: 'guild'
@@ -51,7 +40,7 @@ export default class CapePermissionsCommand extends BushCommand {
let capePerms: CapePerms | null, uuid: string;
try {
- uuid = await util.findUUID(args.ign);
+ uuid = await util.mcUUID(args.ign);
} catch (e) {
return await message.util.reply(`${util.emojis.error} \`${args.ign}\` doesn't appear to be a valid username.`);
}
diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts
index 0af0125..1734568 100644
--- a/src/commands/moulberry-bush/capes.ts
+++ b/src/commands/moulberry-bush/capes.ts
@@ -7,32 +7,22 @@ export default class CapesCommand extends BushCommand {
super('capes', {
aliases: ['capes', 'cape'],
category: "Moulberry's Bush",
- description: {
- content: 'A command to see what a cape looks like.',
- usage: ['cape [cape]'],
- examples: ['capes', 'cape space']
- },
+ description: 'A command to see what a cape looks like.',
+ usage: ['cape [cape]'],
+ examples: ['capes', 'cape space'],
args: [
{
id: 'cape',
+ description: 'The cape to view.',
type: 'string',
- prompt: {
- start: 'What cape would you like to see?',
- retry: '{error} Choose a cape to see.',
- optional: true
- },
- default: null
+ prompt: 'What cape would you like to see?',
+ retry: '{error} Choose a cape to see.',
+ optional: true,
+ slashType: 'STRING'
+ // choices: client.consts.mappings.capes.map((v) => ({ name: v.name, value: v.name }))
}
],
slash: true,
- slashOptions: [
- {
- name: 'cape',
- description: 'What cape would you like to see?',
- type: 'STRING',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
});
diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts
index d76964c..28f920a 100644
--- a/src/commands/moulberry-bush/giveawayPing.ts
+++ b/src/commands/moulberry-bush/giveawayPing.ts
@@ -5,11 +5,9 @@ export default class GiveawayPingCommand extends BushCommand {
super('giveawayPing', {
aliases: ['giveaway-ping', 'giveaway-pong'],
category: "Moulberry's Bush",
- description: {
- content: 'Pings the giveaway role.',
- usage: ['giveaway-ping'],
- examples: ['giveaway-ping']
- },
+ description: 'Pings the giveaway role.',
+ usage: ['giveaway-ping'],
+ examples: ['giveaway-ping'],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_MESSAGES'], true),
userPermissions: ['MANAGE_GUILD', 'MANAGE_MESSAGES', 'BAN_MEMBERS', 'KICK_MEMBERS', 'VIEW_CHANNEL'],
channel: 'guild',
diff --git a/src/commands/moulberry-bush/moulHammer.ts b/src/commands/moulberry-bush/moulHammer.ts
index 98ef78f..2811f80 100644
--- a/src/commands/moulberry-bush/moulHammer.ts
+++ b/src/commands/moulberry-bush/moulHammer.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type BushMessage } from '#lib';
+import { BushCommand, BushSlashMessage, type BushMessage } from '#lib';
import { MessageEmbed, type User } from 'discord.js';
export default class MoulHammerCommand extends BushCommand {
@@ -6,28 +6,28 @@ export default class MoulHammerCommand extends BushCommand {
super('moulHammer', {
aliases: ['moul-hammer'],
category: "Moulberry's Bush",
- description: {
- content: 'A command to moul hammer members.',
- usage: ['moul-hammer <user>'],
- examples: ['moul-hammer @IRONM00N']
- },
+ description: 'A command to moul hammer members.',
+ usage: ['moul-hammer <user>'],
+ examples: ['moul-hammer @IRONM00N'],
args: [
{
id: 'user',
+ description: 'The user to moul hammer.',
type: 'user',
- prompt: {
- start: 'What user would you like to moul hammer?',
- retry: '{error} Choose a valid user to moul hammer'
- }
+ prompt: 'What user would you like to moul hammer?',
+ retry: '{error} Choose a valid user to moul hammer',
+ slashType: 'USER'
}
],
+ slash: true,
+ slashGuilds: ['516977525906341928'],
restrictedGuilds: ['516977525906341928'],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
});
}
- public override async exec(message: BushMessage, { user }: { user: User }) {
+ public override async exec(message: BushMessage | BushSlashMessage, { user }: { user: User }) {
await message.delete();
const embed = new MessageEmbed()
.setTitle('L')
diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts
index d5e9731..2a0d06f 100644
--- a/src/commands/moulberry-bush/report.ts
+++ b/src/commands/moulberry-bush/report.ts
@@ -7,47 +7,30 @@ export default class ReportCommand extends BushCommand {
super('report', {
aliases: ['report'],
category: "Moulberry's Bush",
- description: {
- content: 'A command to report a user.',
- usage: ['report <user> <reason/evidence>'],
- examples: ['report IRONM00N commands in #general']
- },
+ description: 'A command to report a user.',
+ usage: ['report <user> <reason/evidence>'],
+ examples: ['report IRONM00N commands in #general'],
args: [
{
id: 'member',
+ description: 'The member to report.',
type: 'member',
- prompt: {
- start: 'Who would you like to report?',
- retry: `{error} Choose a valid user to report.`,
- optional: false
- }
+ prompt: 'Who would you like to report?',
+ retry: '{error} Choose a valid user to report.',
+ slashType: 'USER'
},
{
id: 'evidence',
+ description: 'The evidence to report the user for.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'What did the user do wrong?',
- retry: `{error} Provide evidence.`,
- optional: true
- }
+ prompt: 'What did the user do wrong?',
+ retry: '{error} Provide evidence.',
+ optional: true,
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'user',
- description: 'Who would you like to report?',
- type: 'USER',
- required: true
- },
- {
- name: 'evidence',
- description: 'What did the user do wrong?',
- type: 'STRING',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
channel: 'guild'
diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts
index d4820fe..a88b323 100644
--- a/src/commands/moulberry-bush/rule.ts
+++ b/src/commands/moulberry-bush/rule.ts
@@ -55,46 +55,33 @@ export default class RuleCommand extends BushCommand {
super('rule', {
aliases: ['rule', 'rules'],
category: "Moulberry's Bush",
- description: {
- content: 'A command to state a rule.',
- usage: ['rule <rule> [user]'],
- examples: ['rule 1 IRONM00N', 'rule 2', 'rules']
- },
+ description: 'A command to state a rule.',
+ usage: ['rule <rule> [user]'],
+ examples: ['rule 1 IRONM00N', 'rule 2', 'rules'],
args: [
{
id: 'rule',
+ description: 'The rule to view.',
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.',
- optional: true
- }
+ readableType: 'integer',
+ prompt: 'What rule would you like to have cited?',
+ retry: '{error} Choose a valid rule.',
+ optional: true,
+ slashType: 'INTEGER',
+ minValue: 1,
+ maxValue: rules.length
},
{
id: 'user',
+ description: 'The user to mention.',
type: 'user',
- prompt: {
- start: 'What user would you like to mention?',
- retry: '{error} Choose a valid user to mention.',
- optional: true
- }
+ prompt: 'What user would you like to mention?',
+ retry: '{error} Choose a valid user to mention.',
+ optional: true,
+ slashType: 'USER'
}
],
slash: true,
- slashOptions: [
- {
- name: 'rule',
- description: 'The rule you would you like to have cited',
- type: 'INTEGER',
- required: false
- },
- {
- name: 'user',
- description: 'The user you would like to mention.',
- type: 'USER',
- required: false
- }
- ],
slashGuilds: ['516977525906341928'],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
diff --git a/src/commands/moulberry-bush/serverStatus.ts b/src/commands/moulberry-bush/serverStatus.ts
index ff0023e..ac37684 100644
--- a/src/commands/moulberry-bush/serverStatus.ts
+++ b/src/commands/moulberry-bush/serverStatus.ts
@@ -7,11 +7,9 @@ export default class ServerStatusCommand extends BushCommand {
super('serverStatus', {
aliases: ['server-status', 'ss'],
category: "Moulberry's Bush",
- description: {
- content: "Gives the status of moulberry's server",
- usage: ['server-status'],
- examples: ['server-status', 'ss']
- },
+ description: "Gives the status of moulberry's server",
+ usage: ['server-status'],
+ examples: ['server-status', 'ss'],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
slash: true
diff --git a/src/commands/utilities/activity.ts b/src/commands/utilities/activity.ts
index 3fca2b6..6829757 100644
--- a/src/commands/utilities/activity.ts
+++ b/src/commands/utilities/activity.ts
@@ -2,29 +2,62 @@ import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib';
import { DiscordAPIError, Message, VoiceChannel } from 'discord.js';
const activityMap = {
- 'Poker Night': '755827207812677713',
- 'Betrayal.io': '773336526917861400',
- 'Fishington.io': '814288819477020702',
- 'YouTube Together': '755600276941176913',
- 'Chess in the Park': '832012774040141894',
- 'Watch Together': '880218394199220334',
- 'Doodle Crew': '878067389634314250',
- 'Wood Snacks': '879863976006127627',
- 'Letter Tile': '879863686565621790'
+ 'Poker Night': {
+ id: '755827207812677713',
+ aliases: ['poker']
+ },
+ 'Betrayal.io': {
+ id: '773336526917861400',
+ aliases: ['betrayal']
+ },
+ 'Fishington.io': {
+ id: '814288819477020702',
+ aliases: ['fish', 'fishing', 'fishington']
+ },
+ 'YouTube Together': {
+ id: '755600276941176913',
+ aliases: ['youtube-together']
+ },
+ 'Chess In The Park': {
+ id: '832012774040141894',
+ aliases: ['chess']
+ },
+ 'Watch Together': {
+ id: '880218394199220334',
+ aliases: ['watch-together', 'yt', 'youtube']
+ },
+ 'Doodle Crew': {
+ id: '878067389634314250',
+ aliases: ['doodle-crew', 'doodle']
+ },
+ 'Wood Snacks': {
+ id: '879863976006127627',
+ aliases: ['wood-snacks', 'wood']
+ },
+ 'Letter Tile': {
+ id: '879863686565621790',
+ aliases: ['letter-tile', 'letter']
+ },
+ 'Spell Cast': {
+ id: '852509694341283871',
+ aliases: ['spell-cast', 'spell', 'cast']
+ },
+ 'Checkers In The Park': {
+ id: '832013003968348200',
+ aliases: ['checkers']
+ }
};
function map(phase: string) {
if (client.consts.regex.snowflake.test(phase)) return phase;
- else if (Reflect.has(activityMap, phase)) return activityMap[phase as keyof typeof activityMap];
- else if (['yt', 'youtube'].includes(phase)) return activityMap['Watch Together'];
- else if (['chess', 'park'].includes(phase)) return activityMap['Chess in the Park'];
- else if (['poker'].includes(phase)) return activityMap['Poker Night'];
- else if (['fish', 'fishing', 'fishington'].includes(phase)) return activityMap['Fishington.io'];
- else if (['betrayal'].includes(phase)) return activityMap['Betrayal.io'];
- else if (['doodle-crew', 'doodle'].includes(phase)) return activityMap['Doodle Crew'];
- else if (['wood-snacks', 'wood'].includes(phase)) return activityMap['Wood Snacks'];
- else if (['letter-tile', 'letter'].includes(phase)) return activityMap['Letter Tile'];
- else return null;
+ else if (phase in activityMap) return activityMap[phase as keyof typeof activityMap];
+
+ for (const activity in activityMap) {
+ if (activityMap[activity as keyof typeof activityMap].aliases.includes(phase.toLowerCase()))
+ return activityMap[activity as keyof typeof activityMap].id;
+ }
+
+ return null;
}
const activityTypeCaster = (_message: Message | BushMessage | BushSlashMessage, phrase: string) => {
@@ -56,53 +89,43 @@ export default class YouTubeCommand extends BushCommand {
'letter'
],
category: 'utilities',
- description: {
- content: 'Allows you to play discord activities in voice channels.',
- usage: [
- 'activity <channel> <`yt`|`youtube`|`chess`|`park`|`poker`|`fish`|`fishing`|`fishington`|`betrayal`>',
- 'yt <channel>' // you do not need to specify the activity if you use its alias.
- ],
- examples: ['yt 785281831788216364', 'activity 785281831788216364 yt']
- },
+ description: 'Allows you to play discord activities in voice channels.',
+ usage: [
+ `activity <channel> <${Object.values(activityMap)
+ .flatMap((a) => a.aliases)
+ .map((a) => `'${a}'`)
+ .join('|')}>`,
+ 'yt <channel>' // you do not need to specify the activity if you use its alias.
+ ],
+ examples: ['yt 785281831788216364', 'activity 785281831788216364 yt'],
args: [
{
id: 'channel',
+ description: 'The channel to create the activity in.',
type: 'voiceChannel',
- prompt: {
- start: 'What channel would you like to use?',
- retry: '{error} Choose a valid voice channel'
- }
+ prompt: 'What channel would you like to use?',
+ retry: '{error} Choose a valid voice channel',
+ slashType: 'CHANNEL',
+ channelTypes: ['GUILD_VOICE']
},
{
id: 'activity',
+ description: 'The activity to create an invite for.',
match: 'rest',
customType: activityTypeCaster,
- prompt: {
- start: 'What activity would you like to play?',
- retry:
- '{error} You must choose one of the following options: `yt`, `youtube`, `chess`, `park`, `poker`, `fish`, `fishing`, `fishington`, or `betrayal`.'
- }
- }
- ],
- slash: true,
- slashOptions: [
- {
- name: 'channel',
- description: 'What channel would you like to use?',
- type: 'CHANNEL',
- required: true
- },
- {
- name: 'activity',
- description: 'What activity would you like to play?',
- type: 'STRING',
- required: true,
+ prompt: 'What activity would you like to play?',
+ retry: `{error} You must choose one of the following options: ${Object.values(activityMap)
+ .flatMap((a) => a.aliases)
+ .map((a) => `\`${a}\``)
+ .join(', ')}.`,
+ slashType: 'STRING',
choices: Object.keys(activityMap).map((key) => ({
name: key,
- value: activityMap[key as keyof typeof activityMap]
+ value: activityMap[key as keyof typeof activityMap].id
}))
}
],
+ slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/utilities/calculator.ts b/src/commands/utilities/calculator.ts
index 277947b..2c70dcc 100644
--- a/src/commands/utilities/calculator.ts
+++ b/src/commands/utilities/calculator.ts
@@ -7,32 +7,21 @@ export default class CalculatorCommand extends BushCommand {
super('calculator', {
aliases: ['calculator', 'calc', 'math'],
category: 'utilities',
- description: {
- content: 'Calculates math expressions.',
- usage: ['calculator <expression>'],
- examples: ['calculator 9+10']
- },
+ description: 'Calculates math expressions.',
+ usage: ['calculator <expression>'],
+ examples: ['calculator 9+10'],
args: [
{
id: 'expression',
+ description: 'The expression to calculate.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'What would you like to evaluate?',
- retry: '{error} Pick something to evaluate.',
- optional: false
- }
+ prompt: 'What would you like to calculate?',
+ retry: '{error} Pick something to calculate.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'expression',
- description: 'What would you like to evaluate?',
- type: 'STRING',
- required: true
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts
index 7f0c7d4..76f735b 100644
--- a/src/commands/utilities/decode.ts
+++ b/src/commands/utilities/decode.ts
@@ -10,61 +10,39 @@ export default class DecodeCommand extends BushCommand {
super('decode', {
aliases: ['decode', 'encode'],
category: 'utilities',
- description: {
- content: 'Decode / encode.',
- usage: ['decode <from> <to> <data>'],
- examples: ['decode base64 ascii TmVyZApJbWFnaW5lIGRlY29kaW5nIHRoaXMgbG1hbw==']
- },
+ description: 'Decode / encode.',
+ usage: ['decode <from> <to> <data>'],
+ examples: ['decode base64 ascii TmVyZApJbWFnaW5lIGRlY29kaW5nIHRoaXMgbG1hbw=='],
args: [
{
id: 'from',
+ description: 'The type of data you are inputting.',
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.`
- }
+ prompt: 'What is the encoding of the original data?',
+ retry: `{error} Choose one of the following ${encodingTypesString} for the encoding of the original data.`,
+ slashType: 'STRING',
+ choices: encodingTypesArray.map((e) => ({ name: e, value: e }))
},
{
id: 'to',
+ description: 'The type of data you want the output to be.',
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.`
- }
+ prompt: 'What would you like the encoding of the resulting data to be?',
+ retry: `{error} Choose one of the following ${encodingTypesString} for the encoding of the resulting data.`,
+ slashType: 'STRING',
+ choices: encodingTypesArray.map((e) => ({ name: e, value: e }))
},
{
id: 'data',
+ description: 'What you would like to decode.',
type: 'string',
match: 'restContent',
- prompt: {
- start: 'What would you to decode.',
- retry: '{error} Choose a valid string to decode.'
- }
+ prompt: 'What would you to decode.',
+ retry: '{error} Choose a valid string to decode.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'from',
- description: 'The type of data you are inputting.',
- type: 'STRING',
- choices: encodingTypesArray.map((e) => ({ name: e, value: e })),
- required: true
- },
- {
- name: 'to',
- description: 'The type of data you want the output to be.',
- type: 'STRING',
- choices: encodingTypesArray.map((e) => ({ name: e, value: e })),
- required: true
- },
- {
- name: 'data',
- description: 'What you would like to decode.',
- type: 'STRING',
- required: true
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts
index 62791c9..7a1bfa7 100644
--- a/src/commands/utilities/hash.ts
+++ b/src/commands/utilities/hash.ts
@@ -7,19 +7,17 @@ export default class HashCommand extends BushCommand {
super('hash', {
aliases: ['hash'],
category: 'utilities',
- description: {
- content: 'Gets the file hash of the given discord link',
- usage: ['hash <fileUrl>'],
- examples: ['hash https://cdn.discordapp.com/emojis/782630946435366942.png?v=1'] //nice
- },
+ description: 'Gets the file hash of the given discord link',
+ usage: ['hash <fileUrl>'],
+ examples: ['hash https://cdn.discordapp.com/emojis/782630946435366942.png?v=1'], //nice
args: [
{
id: 'url',
+ description: 'The url of the discord link to find the hash of.',
type: 'url',
- prompt: {
- start: 'What url would you like to find the hash of?',
- retry: '{error} Enter a valid url.'
- }
+ prompt: 'What url would you like to find the hash of?',
+ retry: '{error} Enter a valid url.',
+ slashType: 'STRING'
}
],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts
index b852a53..d931dd2 100644
--- a/src/commands/utilities/price.ts
+++ b/src/commands/utilities/price.ts
@@ -8,43 +8,30 @@ export default class PriceCommand extends BushCommand {
super('price', {
aliases: ['price'],
category: 'utilities',
- description: {
- content: 'Finds the price information of an item.',
- usage: ['price <item id>'],
- examples: ['price ASPECT_OF_THE_END']
- },
+ description: 'Finds the price information of an item.',
+ usage: ['price <item id>'],
+ examples: ['price ASPECT_OF_THE_END'],
args: [
{
id: 'item',
+ description: 'The item that you would you like to find the price of.',
type: 'string',
match: 'content',
- prompt: {
- start: 'What item would you like to find the price of?',
- retry: '{error} Choose a valid item.'
- }
+ prompt: 'What item would you like to find the price of?',
+ retry: '{error} Choose a valid item.',
+ slashType: 'STRING'
},
{
id: 'strict',
+ description: 'Whether or not to bypass the fuzzy search.',
match: 'flag',
flag: '--strict',
- default: false
+ prompt: 'Would you like to bypass the fuzzy search?',
+ optional: true,
+ slashType: 'BOOLEAN'
}
],
slash: true,
- slashOptions: [
- {
- name: 'item',
- description: 'The item that you would you like to find the price of.',
- type: 'STRING',
- required: true
- },
- {
- name: 'strict',
- description: 'Whether or not to bypass the fuzzy search.',
- type: 'BOOLEAN',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: [],
typing: true
diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts
index 3d230c5..190277a 100644
--- a/src/commands/utilities/steal.ts
+++ b/src/commands/utilities/steal.ts
@@ -1,65 +1,100 @@
-import { BushCommand, type BushMessage } from '#lib';
+import { BushCommand, BushSlashMessage, type BushMessage } from '#lib';
+import { ArgumentOptions, Flag } from 'discord-akairo';
import { type Snowflake } from 'discord.js';
+import _ from 'lodash';
export default class StealCommand extends BushCommand {
public constructor() {
super('steal', {
aliases: ['steal', 'copy-emoji'],
category: 'utilities',
- description: {
- content: 'Steal an emoji from another server and add it to your own.',
- usage: ['steal <emoji/emojiId/url> [name]'],
- examples: ['steal <:omegaclown:782630946435366942> ironm00n']
- },
+ description: 'Steal an emoji from another server and add it to your own.',
+ usage: ['steal <emoji/emojiId/url> [name]'],
+ examples: ['steal <:omegaclown:782630946435366942> ironm00n'],
args: [
{
- id: 'emojiOrName',
+ id: 'emoji',
+ description: 'The emoji to steal.',
customType: util.arg.union('discordEmoji', 'snowflake', 'url'),
- prompt: {
- start: 'What emoji would you like to steal?',
- retry: '{error} Pick a valid emoji, emoji id, or image url.',
- optional: true
- }
+ readableType: 'discordEmoji|snowflake|url',
+ prompt: 'What emoji would you like to steal?',
+ retry: '{error} Pick a valid emoji, emoji id, or image url.',
+ optional: true,
+ only: 'slash',
+ slashType: 'STRING'
},
{
- id: 'name2'
+ id: 'name',
+ description: 'The name to give the new emoji.',
+ prompt: 'What would you like to name the emoji?',
+ retry: '{error} Choose a valid name fore the emoji.',
+ optional: true,
+ only: 'slash',
+ slashType: 'STRING'
}
],
- slash: false,
+ slash: true,
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['MANAGE_EMOJIS_AND_STICKERS']),
userPermissions: ['MANAGE_EMOJIS_AND_STICKERS']
});
}
+
+ public override *args(message: BushMessage): Generator<ArgumentOptions | Flag> {
+ const hasImage = message.attachments.size && message.attachments.first()?.contentType?.includes('image/');
+
+ const emoji = hasImage
+ ? message.attachments.first()!.url
+ : yield {
+ id: 'emoji',
+ type: util.arg.union('discordEmoji', 'snowflake', 'url'),
+ prompt: {
+ start: 'What emoji would you like to steal?',
+ retry: '{error} Pick a valid emoji, emoji id, or image url.'
+ }
+ };
+
+ const name = yield {
+ id: 'name',
+ prompt: {
+ start: 'What would you like to name the emoji?',
+ retry: '{error} Choose a valid name fore the emoji.',
+ optional: true
+ },
+ default:
+ hasImage && message.attachments.first()?.name
+ ? _.camelCase(message.attachments.first()!.name ?? 'stolen_emoji')
+ : 'stolen_emoji'
+ };
+
+ return { emoji, name };
+ }
+
public override async exec(
- message: BushMessage,
- args?: { emojiOrName?: { name: string; id: Snowflake } | Snowflake | URL | string; name2: string }
+ message: BushMessage | BushSlashMessage,
+ args?: { emoji?: { name: string; id: Snowflake } | Snowflake | URL | string; name: string }
) {
- if ((!args || !args.emojiOrName) && !message.attachments.size)
- return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
+ if (!args || !args.emoji) return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
const image =
- message.attachments.size && message.attachments.first()?.contentType?.includes('image/')
- ? message.attachments.first()!.url
- : args?.emojiOrName instanceof URL
- ? args.emojiOrName.href
- : typeof args?.emojiOrName === 'object'
- ? `https://cdn.discordapp.com/emojis/${args.emojiOrName.id}`
- : client.consts.regex.snowflake.test(args?.emojiOrName ?? '')
- ? `https://cdn.discordapp.com/emojis/${args!.emojiOrName}`
+ args?.emoji instanceof URL
+ ? args.emoji.href
+ : typeof args?.emoji === 'object'
+ ? `https://cdn.discordapp.com/emojis/${args.emoji.id}`
+ : client.consts.regex.snowflake.test(args?.emoji ?? '')
+ ? `https://cdn.discordapp.com/emojis/${args!.emoji}`
+ : (args?.emoji ?? '').match(/https?:\/\//)
+ ? args?.emoji
: undefined;
if (image === undefined) return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
- if (message.attachments.size && typeof args?.emojiOrName !== 'string')
- return await message.util.reply(`${util.emojis.error} You cannot attach an image and provide an argument.`);
- const emojiName = message.attachments.size
- ? (args?.emojiOrName as string) ?? 'stolen_emoji'
- : args?.emojiOrName instanceof URL
- ? args?.name2 ?? 'stolen_emoji'
- : typeof args?.emojiOrName === 'object'
- ? args?.name2 ?? args.emojiOrName.name ?? 'stolen_emoji'
- : 'stolen_emoji';
+ const emojiName =
+ args.name ?? args?.emoji instanceof URL
+ ? args?.name ?? 'stolen_emoji'
+ : typeof args?.emoji === 'object'
+ ? args?.name ?? args.emoji.name ?? 'stolen_emoji'
+ : 'stolen_emoji';
const creationSuccess = await message
.guild!.emojis.create(image, emojiName, {
diff --git a/src/commands/utilities/suicide.ts b/src/commands/utilities/suicide.ts
index 359f914..05f8d47 100644
--- a/src/commands/utilities/suicide.ts
+++ b/src/commands/utilities/suicide.ts
@@ -6,11 +6,9 @@ export default class TemplateCommand extends BushCommand {
super('suicide', {
aliases: ['suicide'],
category: 'utilities',
- description: {
- content: 'Mental Health Resources. Credit to https://github.com/dexbiobot/Zeppelin.',
- usage: ['suicide'],
- examples: ['suicide']
- },
+ description: 'Mental Health Resources. Credit to https://github.com/dexbiobot/Zeppelin.',
+ usage: ['suicide'],
+ examples: ['suicide'],
slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
diff --git a/src/commands/utilities/uuid.ts b/src/commands/utilities/uuid.ts
index 556a4de..e0f6b1c 100644
--- a/src/commands/utilities/uuid.ts
+++ b/src/commands/utilities/uuid.ts
@@ -5,41 +5,40 @@ export default class UuidCommand extends BushCommand {
super('uuid', {
aliases: ['uuid'],
category: 'utilities',
- description: {
- content: "Find someone's minecraft uuid",
- usage: ['uuid <ign>'],
- examples: ['uuid ironm00n']
- },
+ description: "Find someone's minecraft uuid",
+ usage: ['uuid <ign>'],
+ examples: ['uuid ironm00n'],
args: [
{
id: 'ign',
+ description: 'The ign to find the ign of.',
customType: /\w{1,16}/im,
- prompt: {
- start: 'What ign would you like to find the uuid of?',
- retry: '{error} Choose a valid ign.',
- optional: false
- }
- }
- ],
- slash: true,
- slashOptions: [
+ readableType: 'ign',
+ prompt: 'What ign would you like to find the uuid of?',
+ retry: '{error} Choose a valid ign.',
+ slashType: 'STRING'
+ },
{
- name: 'ign',
- description: 'What ign would you like to find the uuid of?',
- type: 'STRING',
- required: false
+ id: 'dashed',
+ description: 'Include dashes in the uuid.',
+ match: 'flag',
+ flag: '--dashed',
+ prompt: 'Would you like to include dashes in the uuid?',
+ slashType: 'BOOLEAN',
+ optional: true
}
],
+ slash: true,
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
}
- public override async exec(message: BushMessage, { ign }: { ign: { match: any[]; matches: any[] } }) {
+ public override async exec(message: BushMessage, { ign, dashed }: { ign: { match: any[]; matches: any[] }; dashed: boolean }) {
if (!ign) return await message.util.reply(`${util.emojis.error} Please enter a valid ign.`);
const readableIGN = ign.match[0];
try {
- const uuid = await util.findUUID(readableIGN);
+ const uuid = await util.mcUUID(readableIGN, dashed);
return await message.util.reply(`The uuid for \`${readableIGN}\` is \`${uuid}\``);
} catch (e) {
return await message.util.reply(`${util.emojis.error} Could not find an uuid for \`${readableIGN}\`.`);
diff --git a/src/commands/utilities/viewRaw.ts b/src/commands/utilities/viewRaw.ts
index 4719da1..c934e2e 100644
--- a/src/commands/utilities/viewRaw.ts
+++ b/src/commands/utilities/viewRaw.ts
@@ -1,73 +1,54 @@
import { BushCommand, type BushMessage, type BushSlashMessage } from '#lib';
-import { MessageEmbed, type DMChannel, type NewsChannel, type Snowflake, type TextChannel } from 'discord.js';
+import { Message, MessageEmbed, type DMChannel, type NewsChannel, type Snowflake, type TextChannel } from 'discord.js';
export default class ViewRawCommand extends BushCommand {
public constructor() {
super('view-raw', {
aliases: ['view-raw', 'vr'],
category: 'utilities',
- description: {
- content: 'Shows raw information about a message.',
- usage: ['viewraw <message id> <channel>'],
- examples: ['viewraw 322862723090219008']
- },
+ description: 'Shows raw information about a message.',
+ usage: ['viewraw <message id> <channel>'],
+ examples: ['viewraw 322862723090219008'],
args: [
{
id: 'message',
- type: 'snowflake',
- prompt: {
- start: 'What message would you like to view?',
- retry: '{error} Choose a valid message.',
- optional: false
- }
+ description: 'The message to view the raw content of.',
+ customType: util.arg.union('guildMessage', 'messageLink'),
+ readableType: 'guildMessage|messageLink',
+ prompt: 'What message would you like to view?',
+ retry: '{error} Choose a valid message.',
+ slashType: 'STRING'
},
{
id: 'channel',
+ description: 'The channel that the message is in.',
type: 'channel',
- prompt: {
- start: 'What channel is the message in?',
- retry: '{error} Choose a valid channel.',
- optional: true
- }
+ prompt: 'What channel is the message in?',
+ retry: '{error} Choose a valid channel.',
+ optional: true,
+ slashType: 'CHANNEL',
+ channelTypes: util.discordConstants.TextBasedChannelTypes
},
{
id: 'json',
+ description: 'Whether or not to view the raw JSON message data.',
match: 'flag',
- flag: '--json'
+ flag: '--json',
+ prompt: 'Would you like to view the raw JSON message data?',
+ slashType: 'BOOLEAN',
+ optional: true
},
{
id: 'js',
+ description: 'Whether or not to view the raw message data.',
match: 'flag',
- flag: '--js'
+ flag: '--js',
+ prompt: 'Would you like to view the raw message data?',
+ slashType: 'BOOLEAN',
+ optional: true
}
],
slash: true,
- slashOptions: [
- {
- name: 'message',
- description: 'What message would you like to view?',
- type: 'STRING',
- required: true
- },
- {
- name: 'channel',
- description: 'What channel is the message in?',
- type: 'CHANNEL',
- required: false
- },
- {
- name: 'json',
- description: 'Would you like to view the raw JSON message data?',
- type: 'BOOLEAN',
- required: false
- },
- {
- name: 'js',
- description: 'Would you like to view the raw message data?',
- type: 'BOOLEAN',
- required: false
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m, ['EMBED_LINKS'], true),
userPermissions: []
@@ -76,10 +57,13 @@ export default class ViewRawCommand extends BushCommand {
public override async exec(
message: BushMessage | BushSlashMessage,
- args: { message: Snowflake; channel: TextChannel | NewsChannel | DMChannel; json?: boolean; js: boolean }
+ args: { message: BushMessage | Snowflake; channel: TextChannel | NewsChannel | DMChannel; json?: boolean; js: boolean }
) {
if (!args.channel) args.channel = (message.channel as TextChannel | NewsChannel | DMChannel)!;
- const newMessage = await args.channel.messages.fetch(`${args.message}` as Snowflake).catch(() => null);
+ const newMessage =
+ args.message instanceof Message
+ ? args.message
+ : await args.channel.messages.fetch(`${args.message}` as Snowflake).catch(() => null);
if (!newMessage)
return await message.util.reply(
`${util.emojis.error} There was an error fetching that message, make sure that is a valid id and if the message is not in this channel, please provide a channel.`
diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts
index a457756..45cf77f 100644
--- a/src/commands/utilities/whoHasRole.ts
+++ b/src/commands/utilities/whoHasRole.ts
@@ -6,31 +6,21 @@ export default class WhoHasRoleCommand extends BushCommand {
super('whoHasRole', {
aliases: ['who-has-role', 'whr', 'dump'],
category: 'utilities',
- description: {
- content: 'Allows you to view what users have a certain role.',
- usage: ['who-has-role <role>'],
- examples: ['who-has-role admin']
- },
+ description: 'Allows you to view what users have a certain role.',
+ usage: ['who-has-role <role>'],
+ examples: ['who-has-role admin'],
args: [
{
id: 'role',
+ description: 'The role to find the users of.',
type: 'role',
- prompt: {
- start: 'What role would you like to find the users of?',
- retry: '{error} Pick a valid role.',
- optional: false
- }
+ prompt: 'What role would you like to find the users of?',
+ retry: '{error} Pick a valid role.',
+ optional: false,
+ slashType: 'ROLE'
}
],
slash: true,
- slashOptions: [
- {
- name: 'role',
- description: 'What role would you like to find the users of?',
- type: 'ROLE',
- required: true
- }
- ],
channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: [],
diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts
index de00620..34b2b90 100644
--- a/src/commands/utilities/wolframAlpha.ts
+++ b/src/commands/utilities/wolframAlpha.ts
@@ -7,43 +7,30 @@ export default class WolframAlphaCommand extends BushCommand {
super('wolframAlpha', {
aliases: ['wolfram-alpha', 'wolfram', 'alpha', 'wolf', 'wa'],
category: 'utilities',
- description: {
- content: 'Queries Wolfram|Alpha for a result.',
- usage: ['wolfram-alpha <expression>'],
- examples: ['wolfram-alpha what is the population of france']
- },
+ description: 'Queries Wolfram|Alpha for a result.',
+ usage: ['wolfram-alpha <expression>'],
+ examples: ['wolfram-alpha what is the population of france'],
args: [
{
id: 'image',
+ description: 'Whether to use the Simple API instead of the Short Answers API.',
match: 'flag',
- flag: '--image'
+ flag: '--image',
+ prompt: 'Would you like to use the Simple API instead of the Short Answers API?',
+ slashType: 'BOOLEAN',
+ optional: true
},
{
id: 'expression',
+ description: 'The expression to query the Wolfram|Alpha api for.',
type: 'string',
match: 'rest',
- prompt: {
- start: 'What would you like to look up?',
- retry: '{error} Pick something to look up.',
- optional: false
- }
+ prompt: 'What would you like to look up?',
+ retry: '{error} Pick something to look up.',
+ slashType: 'STRING'
}
],
slash: true,
- slashOptions: [
- {
- name: 'expression',
- description: 'What would you like to look up?',
- type: 'STRING',
- required: true
- },
- {
- name: 'image',
- description: 'Would you like to use the Simple API instead of the Short Answers API?',
- type: 'BOOLEAN',
- required: false
- }
- ],
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: []
});
diff --git a/src/lib/common/Format.ts b/src/lib/common/Format.ts
index b47be38..6cb6edc 100644
--- a/src/lib/common/Format.ts
+++ b/src/lib/common/Format.ts
@@ -1,5 +1,5 @@
import { type CodeBlockLang } from '#lib';
-import { Formatters, Util } from 'discord.js';
+import { EscapeMarkdownOptions, Formatters, Util } from 'discord.js';
/**
* Formats and escapes content for formatting
@@ -19,8 +19,8 @@ export class Format {
public static codeBlock(language: CodeBlockLang, content: string): string;
public static codeBlock(languageOrContent: string, content?: string): string {
return typeof content === 'undefined'
- ? Formatters.codeBlock(Util.escapeCodeBlock(languageOrContent))
- : Formatters.codeBlock(languageOrContent, Util.escapeCodeBlock(languageOrContent));
+ ? Formatters.codeBlock(Util.escapeCodeBlock(`${languageOrContent}`))
+ : Formatters.codeBlock(`${languageOrContent}`, Util.escapeCodeBlock(`${content}`));
}
/**
@@ -28,7 +28,7 @@ export class Format {
* @param content The content to wrap.
*/
public static inlineCode(content: string): string {
- return Formatters.inlineCode(Util.escapeInlineCode(content));
+ return Formatters.inlineCode(Util.escapeInlineCode(`${content}`));
}
/**
@@ -36,7 +36,7 @@ export class Format {
* @param content The content to wrap.
*/
public static italic(content: string): string {
- return Formatters.italic(Util.escapeItalic(content));
+ return Formatters.italic(Util.escapeItalic(`${content}`));
}
/**
@@ -44,7 +44,7 @@ export class Format {
* @param content The content to wrap.
*/
public static bold(content: string): string {
- return Formatters.bold(Util.escapeBold(content));
+ return Formatters.bold(Util.escapeBold(`${content}`));
}
/**
@@ -52,7 +52,7 @@ export class Format {
* @param content The content to wrap.
*/
public static underscore(content: string): string {
- return Formatters.underscore(Util.escapeUnderline(content));
+ return Formatters.underscore(Util.escapeUnderline(`${content}`));
}
/**
@@ -60,7 +60,7 @@ export class Format {
* @param content The content to wrap.
*/
public static strikethrough(content: string): string {
- return Formatters.strikethrough(Util.escapeStrikethrough(content));
+ return Formatters.strikethrough(Util.escapeStrikethrough(`${content}`));
}
/**
@@ -68,6 +68,40 @@ export class Format {
* @param content The content to wrap.
*/
public static spoiler(content: string): string {
- return Formatters.spoiler(Util.escapeSpoiler(content));
+ return Formatters.spoiler(Util.escapeSpoiler(`${content}`));
+ }
+
+ /**
+ * Escapes any Discord-flavour markdown in a string.
+ * @param text Content to escape
+ * @param options Options for escaping the markdown
+ */
+ public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string {
+ return Util.escapeMarkdown(`${text}`, options);
+ }
+
+ /**
+ * Formats input: makes it bold and escapes any other markdown
+ * @param text The input
+ */
+ public static input(text: string): string {
+ return this.bold(this.escapeMarkdown(this.sanitizeWtlAndControl(`${text}`)));
+ }
+
+ /**
+ * Formats input for logs: makes it highlighted
+ * @param text The input
+ */
+ public static inputLog(text: string): string {
+ return `<<${this.sanitizeWtlAndControl(`${text}`)}>>`;
+ }
+
+ /**
+ * Removes all characters in a string that are either control characters or change the direction of text etc.
+ * @param str The string you would like sanitized
+ */
+ public static sanitizeWtlAndControl(str: string) {
+ // eslint-disable-next-line no-control-regex
+ return `${str}`.replace(/[\u0000-\u001F\u007F-\u009F\u200B]/g, '');
}
}
diff --git a/src/lib/common/util/Arg.ts b/src/lib/common/util/Arg.ts
index ee9aee0..1982f4a 100644
--- a/src/lib/common/util/Arg.ts
+++ b/src/lib/common/util/Arg.ts
@@ -9,7 +9,11 @@ export class Arg {
* @param message - Message that called the command.
* @param phrase - Phrase to process.
*/
- public static cast(type: BushArgumentType, message: BushMessage | BushSlashMessage, phrase: string): Promise<any> {
+ public static cast(
+ type: BushArgumentType | ArgumentTypeCaster,
+ message: BushMessage | BushSlashMessage,
+ phrase: string
+ ): Promise<any> {
return Argument.cast(type, client.commandHandler.resolver, message as Message, phrase);
}
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
index 3339a62..45ad7ca 100644
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ b/src/lib/extensions/discord-akairo/BushClient.ts
@@ -41,6 +41,7 @@ import { discordEmoji } from '../../../arguments/discordEmoji.js';
import { duration } from '../../../arguments/duration.js';
import { durationSeconds } from '../../../arguments/durationSeconds.js';
import { globalUser } from '../../../arguments/globalUser.js';
+import { messageLink } from '../../../arguments/messageLink.js';
import { permission } from '../../../arguments/permission.js';
import { roleWithDuration } from '../../../arguments/roleWithDuration.js';
import { snowflake } from '../../../arguments/snowflake.js';
@@ -289,7 +290,8 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
roleWithDuration,
abbreviatedNumber,
durationSeconds,
- globalUser
+ globalUser,
+ messageLink
});
this.sentry = Sentry;
diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts
index aa64562..889cd6e 100644
--- a/src/lib/extensions/discord-akairo/BushClientUtil.ts
+++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts
@@ -18,9 +18,11 @@ import {
} from '#lib';
import { humanizeDuration } from '@notenoughupdates/humanize-duration';
import { exec } from 'child_process';
+import deepLock from 'deep-lock';
import { ClientUtil, Util as AkairoUtil } from 'discord-akairo';
import { APIMessage } from 'discord-api-types';
import {
+ Constants as DiscordConstants,
GuildMember,
Message,
MessageEmbed,
@@ -37,7 +39,6 @@ import {
} from 'discord.js';
import got from 'got';
import _ from 'lodash';
-import moment from 'moment';
import { inspect, promisify } from 'util';
import CommandErrorListener from '../../../listeners/commands/commandError.js';
import { Format } from '../../common/Format.js';
@@ -105,10 +106,7 @@ export class BushClientUtil extends ClientUtil {
* @param content The text to post
* @returns The url of the posted text
*/
- public async haste(
- content: string,
- substr = false
- ): Promise<{ url?: string; error?: 'content too long' | 'substr' | 'unable to post' }> {
+ public async haste(content: string, substr = false): Promise<HasteResults> {
let isSubstr = false;
if (content.length > 400_000 && !substr) {
void this.handleError('haste', new Error(`content over 400,000 characters (${content.length.toLocaleString()})`));
@@ -119,7 +117,7 @@ export class BushClientUtil extends ClientUtil {
}
for (const url of this.#hasteURLs) {
try {
- const res: hastebinRes = await got.post(`${url}/documents`, { body: content }).json();
+ const res: HastebinRes = await got.post(`${url}/documents`, { body: content }).json();
return { url: `${url}/${res.key}`, error: isSubstr ? 'substr' : undefined };
} catch {
void client.console.error('haste', `Unable to upload haste to ${url}`);
@@ -197,7 +195,10 @@ export class BushClientUtil extends ClientUtil {
}
/**
- * A simple utility to create and embed with the needed style for the bot
+ * A simple utility to create and embed with the needed style for the bot.
+ * @param color The color to set the embed to.
+ * @param author The author to set the embed to.
+ * @returns The generated embed.
*/
public createEmbed(color?: ColorResolvable, author?: User | GuildMember): MessageEmbed {
if (author instanceof GuildMember) {
@@ -214,15 +215,25 @@ export class BushClientUtil extends ClientUtil {
return embed;
}
- public async mcUUID(username: string): Promise<string> {
- const apiRes = (await got.get(`https://api.ashcon.app/mojang/v2/user/${username}`).json()) as uuidRes;
- return apiRes.uuid.replace(/-/g, '');
+ /**
+ * Fetches a user's uuid from the mojang api.
+ * @param username The username to get the uuid of.
+ * @returns The the uuid of the user.
+ */
+ public async mcUUID(username: string, dashed = false): Promise<string> {
+ const apiRes = (await got.get(`https://api.ashcon.app/mojang/v2/user/${username}`).json()) as UuidRes;
+ return dashed ? apiRes.uuid : apiRes.uuid.replace(/-/g, '');
}
/**
* Surrounds text in a code block with the specified language and puts it in a hastebin if its too long.
* * Embed Description Limit = 4096 characters
* * Embed Field Limit = 1024 characters
+ * @param code The content of the code block.
+ * @param length The maximum length of the code block.
+ * @param language The language of the code.
+ * @param substr Whether or not to substring the code if it is too long.
+ * @returns The generated code block
*/
public async codeblock(code: string, length: number, language: CodeBlockLang | '' = '', substr = false): Promise<string> {
let hasteOut = '';
@@ -250,15 +261,21 @@ export class BushClientUtil extends ClientUtil {
}
/**
- * Uses {@link inspect} with custom defaults
- * @param object - The object you would like to inspect
- * @param options - The options you would like to use to inspect the object
+ * Uses {@link inspect} with custom defaults.
+ * @param object - The object you would like to inspect.
+ * @param options - The options you would like to use to inspect the object.
+ * @returns The inspected object.
*/
public inspect(object: any, options?: BushInspectOptions): string {
const optionsWithDefaults = this.getDefaultInspectOptions(options);
return inspect(object, optionsWithDefaults);
}
+ /**
+ * Generate defaults for {@link inspect}.
+ * @param options The options to create defaults with.
+ * @returns The default options combined with the specified options.
+ */
private getDefaultInspectOptions(options?: BushInspectOptions): BushInspectOptions {
const {
showHidden = false,
@@ -288,7 +305,12 @@ export class BushClientUtil extends ClientUtil {
};
}
- #mapCredential(old: string): string {
+ /**
+ * Maps the key of a credential with a readable version when redacting.
+ * @param key The key of the credential.
+ * @returns The readable version of the key or the original key if there isn't a mapping.
+ */
+ #mapCredential(key: string): string {
const mapping = {
token: 'Main Token',
devToken: 'Dev Token',
@@ -297,12 +319,13 @@ export class BushClientUtil extends ClientUtil {
wolframAlphaAppId: 'Wolfram|Alpha App ID',
dbPassword: 'Database Password'
};
- return mapping[old as keyof typeof mapping] || old;
+ return mapping[key as keyof typeof mapping] || key;
}
/**
- * Redacts credentials from a string
- * @param text - The text to redact credentials from
+ * Redacts credentials from a string.
+ * @param text The text to redact credentials from.
+ * @returns The redacted text.
*/
public redact(text: string) {
for (const credentialName in { ...client.config.credentials, dbPassword: client.config.db.password }) {
@@ -321,8 +344,13 @@ export class BushClientUtil extends ClientUtil {
}
/**
- * Takes an any value, inspects it, redacts credentials and puts it in a codeblock
- * (and uploads to hast if the content is too long)
+ * Takes an any value, inspects it, redacts credentials, and puts it in a codeblock
+ * (and uploads to hast if the content is too long).
+ * @param input The object to be inspect, redacted, and put into a codeblock.
+ * @param language The language to make the codeblock.
+ * @param inspectOptions The options for {@link BushClientUtil.inspect}.
+ * @param length The maximum length that the codeblock can be.
+ * @returns The generated codeblock.
*/
public async inspectCleanRedactCodeblock(
input: any,
@@ -338,17 +366,35 @@ export class BushClientUtil extends ClientUtil {
return this.codeblock(input, length, language, true);
}
- public async inspectCleanRedactHaste(input: any, inspectOptions?: BushInspectOptions) {
+ /**
+ * Takes an any value, inspects it, redacts credentials, and uploads it to haste.
+ * @param input The object to be inspect, redacted, and upload.
+ * @param inspectOptions The options for {@link BushClientUtil.inspect}.
+ * @returns The {@link HasteResults}.
+ */
+ public async inspectCleanRedactHaste(input: any, inspectOptions?: BushInspectOptions): Promise<HasteResults> {
input = typeof input !== 'string' ? this.inspect(input, inspectOptions ?? undefined) : input;
input = this.redact(input);
return this.haste(input, true);
}
- public inspectAndRedact(input: any, inspectOptions?: BushInspectOptions) {
+ /**
+ * Takes an any value, inspects it and redacts credentials.
+ * @param input The object to be inspect and redacted.
+ * @param inspectOptions The options for {@link BushClientUtil.inspect}.
+ * @returns The redacted and inspected object.
+ */
+ public inspectAndRedact(input: any, inspectOptions?: BushInspectOptions): string {
input = typeof input !== 'string' ? this.inspect(input, inspectOptions ?? undefined) : input;
return this.redact(input);
}
+ /**
+ * Responds to a slash command interaction.
+ * @param interaction The interaction to respond to.
+ * @param responseOptions The options for the response.
+ * @returns The message sent.
+ */
public async slashRespond(
interaction: CommandInteraction,
responseOptions: BushSlashSendMessageType | BushSlashEditMessageType
@@ -364,7 +410,8 @@ export class BushClientUtil extends ClientUtil {
}
/**
- * Gets a a configured channel as a TextChannel
+ * Gets a a configured channel as a TextChannel.
+ * @channel The channel to retrieve.
*/
public async getConfigChannel(channel: keyof typeof client['config']['channels']): Promise<TextChannel> {
return (await client.channels.fetch(client.config.channels[channel])) as unknown as TextChannel;
@@ -375,7 +422,7 @@ export class BushClientUtil extends ClientUtil {
* @param array The array to combine.
* @param conjunction The conjunction to use.
* @param ifEmpty What to return if the array is empty.
- * @returns The combined elements or `ifEmpty`
+ * @returns The combined elements or `ifEmpty`.
*
* @example
* const permissions = oxford(['ADMINISTRATOR', 'SEND_MESSAGES', 'MANAGE_MESSAGES'], 'and', 'none');
@@ -391,10 +438,16 @@ export class BushClientUtil extends ClientUtil {
return array.join(', ');
}
- public async insertOrRemoveFromGlobal(
+ /**
+ * Add or remove an element from an array stored in the Globals database.
+ * @param action Either `add` or `remove` an element.
+ * @param key The key of the element in the global cache to update.
+ * @param value The value to add/remove from the array.
+ */
+ public async insertOrRemoveFromGlobal<K extends keyof typeof client['cache']['global']>(
action: 'add' | 'remove',
- key: keyof typeof client['cache']['global'],
- value: any
+ key: K,
+ value: typeof client['cache']['global'][K][0]
): Promise<Global | void> {
const row =
(await Global.findByPk(client.config.environment)) ?? (await Global.create({ environment: client.config.environment }));
@@ -406,7 +459,26 @@ export class BushClientUtil extends ClientUtil {
}
/**
+ * Updates an element in the Globals database.
+ * @param key The key in the global cache to update.
+ * @param value The value to set the key to.
+ */
+ public async setGlobal<K extends keyof typeof client['cache']['global']>(
+ key: K,
+ value: typeof client['cache']['global'][K]
+ ): Promise<Global | void> {
+ const row =
+ (await Global.findByPk(client.config.environment)) ?? (await Global.create({ environment: client.config.environment }));
+ row[key] = value;
+ client.cache.global[key] = value;
+ return await row.save().catch((e) => this.handleError('setGlobal', e));
+ }
+
+ /**
* Add or remove an item from an array. All duplicates will be removed.
+ * @param action Either `add` or `remove` an element.
+ * @param array The array to add/remove an element from.
+ * @param value The element to add/remove from the array.
*/
public addOrRemoveFromArray<T>(action: 'add' | 'remove', array: T[], value: T): T[] {
const set = new Set(array);
@@ -416,15 +488,21 @@ export class BushClientUtil extends ClientUtil {
/**
* Surrounds a string to the begging an end of each element in an array.
- * @param array - The array you want to surround.
- * @param surroundChar1 - The character placed in the beginning of the element.
- * @param surroundChar2 - The character placed in the end of the element. Defaults to `surroundChar1`.
+ * @param array The array you want to surround.
+ * @param surroundChar1 The character placed in the beginning of the element.
+ * @param surroundChar2 The character placed in the end of the element. Defaults to `surroundChar1`.
*/
public surroundArray(array: string[], surroundChar1: string, surroundChar2?: string): string[] {
return array.map((a) => `${surroundChar1}${a}${surroundChar2 ?? surroundChar1}`);
}
- public parseDuration(content: string, remove = true): { duration: number | null; contentWithoutTime: string | null } {
+ /**
+ * Gets the duration from a specified string.
+ * @param content The string to look for a duration in.
+ * @param remove Whether or not to remove the duration from the original string.
+ * @returns The {@link ParsedDuration}.
+ */
+ public parseDuration(content: string, remove = true): ParsedDuration {
if (!content) return { duration: 0, contentWithoutTime: null };
// eslint-disable-next-line prefer-const
@@ -434,10 +512,11 @@ export class BushClientUtil extends ClientUtil {
let contentWithoutTime = ` ${content}`;
for (const unit in BushConstants.TimeUnits) {
- const regex = BushConstants.TimeUnits[unit].match;
+ const regex = BushConstants.TimeUnits[unit as keyof typeof BushConstants.TimeUnits].match;
const match = regex.exec(contentWithoutTime);
const value = Number(match?.groups?.[unit]);
- if (!isNaN(value)) (duration as unknown as number) += value * BushConstants.TimeUnits[unit].value;
+ if (!isNaN(value))
+ (duration as unknown as number) += value * BushConstants.TimeUnits[unit as keyof typeof BushConstants.TimeUnits].value;
if (remove) contentWithoutTime = contentWithoutTime.replace(regex, '');
}
@@ -446,16 +525,33 @@ export class BushClientUtil extends ClientUtil {
return { duration, contentWithoutTime };
}
+ /**
+ * Converts a duration in milliseconds to a human readable form.
+ * @param duration The duration in milliseconds to convert.
+ * @param largest The maximum number of units to display for the duration.
+ * @returns A humanized string of the duration.
+ */
public humanizeDuration(duration: number, largest?: number): string {
if (largest) return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2, largest })!;
else return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2 })!;
}
+ /**
+ * Creates a formatted relative timestamp from a duration in milliseconds.
+ * @param duration The duration in milliseconds.
+ * @returns The formatted relative timestamp.
+ */
public timestampDuration(duration: number): string {
- return `<t:${Math.round(duration / 1000)}:R>`;
+ return `<t:${Math.round(new Date().getTime() / 1_000 + duration / 1_000)}:R>`;
}
/**
+ * Creates a timestamp from a date.
+ * @param date The date to create a timestamp from.
+ * @param style The style of the timestamp.
+ * @returns The formatted timestamp.
+ *
+ * @see
* **Styles:**
* - **t**: Short Time
* - **T**: Long Time
@@ -470,33 +566,24 @@ export class BushClientUtil extends ClientUtil {
style: 't' | 'T' | 'd' | 'D' | 'f' | 'F' | 'R' = 'f'
): D extends Date ? string : undefined {
if (!date) return date as unknown as D extends Date ? string : undefined;
- return `<t:${Math.round(date.getTime() / 1000)}:${style}>` as unknown as D extends Date ? string : undefined;
- }
-
- public dateDelta(date: Date, largest?: number) {
- return this.humanizeDuration(moment(date).diff(moment()), largest ?? 3);
+ return `<t:${Math.round(date.getTime() / 1_000)}:${style}>` as unknown as D extends Date ? string : undefined;
}
- public async findUUID(player: string): Promise<string> {
- try {
- const raw = await got.get(`https://api.ashcon.app/mojang/v2/user/${player}`);
- let profile: MojangProfile;
- if (raw.statusCode == 200) {
- profile = JSON.parse(raw.body);
- } else {
- throw new Error('invalid player');
- }
-
- if (raw.statusCode == 200 && profile && profile.uuid) {
- return profile.uuid.replace(/-/g, '');
- } else {
- throw new Error(`Could not fetch the uuid for ${player}.`);
- }
- } catch (e) {
- throw new Error('An error has occurred.');
- }
+ /**
+ * Creates a human readable representation between a date and the current time.
+ * @param date The date to be compared with the current time.
+ * @param largest The maximum number of units to display for the duration.
+ * @returns A humanized string of the delta.
+ */
+ public dateDelta(date: Date, largest?: number): string {
+ return this.humanizeDuration(new Date().getTime() - date.getTime(), largest ?? 3);
}
+ /**
+ * Convert a hex code to an rbg value.
+ * @param hex The hex code to convert.
+ * @returns The rbg value.
+ */
public hexToRgb(hex: string): string {
const arrBuff = new ArrayBuffer(4);
const vw = new DataView(arrBuff);
@@ -507,20 +594,34 @@ export class BushClientUtil extends ClientUtil {
}
/* eslint-disable @typescript-eslint/no-unused-vars */
- public async lockdownChannel(options: { channel: BushTextChannel | BushNewsChannel; moderator: BushUserResolvable }) {}
+ public async lockdownChannel(options: { channel: BushTextChannel | BushNewsChannel; moderator: BushUserResolvable }) {
+ // todo: implement lockdowns
+ }
/* eslint-enable @typescript-eslint/no-unused-vars */
+ /**
+ * Capitalize the first letter of a string.
+ * @param string The string to capitalize the first letter of.
+ * @returns The string with the first letter capitalized.
+ */
public capitalizeFirstLetter(string: string): string {
return string.charAt(0)?.toUpperCase() + string.slice(1);
}
/**
* Wait an amount in seconds.
+ * @param s The number of seconds to wait
+ * @returns A promise that resolves after the specified amount of seconds
*/
public async sleep(s: number) {
return new Promise((resolve) => setTimeout(resolve, s * 1000));
}
+ /**
+ * Send a message in the error logging channel and console for an error.
+ * @param context
+ * @param error
+ */
public async handleError(context: string, error: Error) {
await client.console.error(_.camelCase(context), `An error occurred:\n${error?.stack ?? (error as any)}`, false);
await client.console.channelError({
@@ -553,24 +654,24 @@ export class BushClientUtil extends ClientUtil {
if (!apiRes) return undefined;
if (!apiRes.pronouns) throw new Error('apiRes.pronouns is undefined');
- return client.constants.pronounMapping[apiRes.pronouns];
+ return client.constants.pronounMapping[apiRes.pronouns!]!;
}
- // modified from https://stackoverflow.com/questions/31054910/get-functions-methods-of-a-class
- // answer by Bruno Grieder
- public getMethods(_obj: any): string {
+ public getMethods(obj: Record<string, any>): string {
+ // modified from https://stackoverflow.com/questions/31054910/get-functions-methods-of-a-class
+ // answer by Bruno Grieder
let props: string[] = [];
- let obj: any = new Object(_obj);
+ let obj_: Record<string, any> = new Object(obj);
do {
- const l = Object.getOwnPropertyNames(obj)
- .concat(Object.getOwnPropertySymbols(obj).map((s) => s.toString()))
+ const l = Object.getOwnPropertyNames(obj_)
+ .concat(Object.getOwnPropertySymbols(obj_).map((s) => s.toString()))
.sort()
.filter(
(p, i, arr) =>
- typeof Object.getOwnPropertyDescriptor(obj, p)?.['get'] !== 'function' && // ignore getters
- typeof Object.getOwnPropertyDescriptor(obj, p)?.['set'] !== 'function' && // ignore setters
- typeof obj[p] === 'function' && //only the methods
+ typeof Object.getOwnPropertyDescriptor(obj_, p)?.['get'] !== 'function' && // ignore getters
+ typeof Object.getOwnPropertyDescriptor(obj_, p)?.['set'] !== 'function' && // ignore setters
+ typeof obj_[p] === 'function' && //only the methods
p !== 'constructor' && //not the constructor
(i == 0 || p !== arr[i - 1]) && //not overriding in this prototype
props.indexOf(p) === -1 //not overridden in a child
@@ -580,10 +681,10 @@ export class BushClientUtil extends ClientUtil {
props = props.concat(
l.map(
(p) =>
- `${obj[p] && obj[p][Symbol.toStringTag] === 'AsyncFunction' ? 'async ' : ''}function ${p}(${
- reg.exec(obj[p].toString())?.[1]
+ `${obj_[p] && obj_[p][Symbol.toStringTag] === 'AsyncFunction' ? 'async ' : ''}function ${p}(${
+ reg.exec(obj_[p].toString())?.[1]
? reg
- .exec(obj[p].toString())?.[1]
+ .exec(obj_[p].toString())?.[1]
.split(', ')
.map((arg) => arg.split('=')[0].trim())
.join(', ')
@@ -592,21 +693,13 @@ export class BushClientUtil extends ClientUtil {
)
);
} while (
- (obj = Object.getPrototypeOf(obj)) && //walk-up the prototype chain
- Object.getPrototypeOf(obj) //not the the Object prototype methods (hasOwnProperty, etc...)
+ (obj_ = Object.getPrototypeOf(obj_)) && //walk-up the prototype chain
+ Object.getPrototypeOf(obj_) //not the the Object prototype methods (hasOwnProperty, etc...)
);
return props.join('\n');
}
- /**
- * Removes all characters in a string that are either control characters or change the direction of text etc.
- */
- public sanitizeWtlAndControl(str: string) {
- // eslint-disable-next-line no-control-regex
- return str.replace(/[\u0000-\u001F\u007F-\u009F\u200B]/g, '');
- }
-
public async uploadImageToImgur(image: string) {
const clientId = this.client.config.credentials.imgurClientId;
@@ -667,6 +760,14 @@ export class BushClientUtil extends ClientUtil {
: message.util.parsed?.prefix ?? client.config.prefix;
}
+ public get deepFreeze() {
+ return deepLock;
+ }
+
+ public static get deepFreeze() {
+ return deepLock;
+ }
+
public get arg() {
return Arg;
}
@@ -686,6 +787,13 @@ export class BushClientUtil extends ClientUtil {
}
/**
+ * Discord.js's Util constants
+ */
+ public get discordConstants() {
+ return DiscordConstants
+ }
+
+ /**
* discord-akairo's Util class
*/
public get akairo() {
@@ -693,11 +801,11 @@ export class BushClientUtil extends ClientUtil {
}
}
-interface hastebinRes {
+interface HastebinRes {
key: string;
}
-export interface uuidRes {
+export interface UuidRes {
uuid: string;
username: string;
username_history?: { username: string }[] | null;
@@ -716,7 +824,12 @@ export interface uuidRes {
created_at: string;
}
-interface MojangProfile {
- username: string;
- uuid: string;
+export interface HasteResults {
+ url?: string;
+ error?: 'content too long' | 'substr' | 'unable to post';
+}
+
+export interface ParsedDuration {
+ duration: number | null;
+ contentWithoutTime: string | null;
}
diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts
index 1494aee..8872831 100644
--- a/src/lib/extensions/discord-akairo/BushCommand.ts
+++ b/src/lib/extensions/discord-akairo/BushCommand.ts
@@ -1,13 +1,23 @@
import { type BushClient, type BushCommandHandler, type BushMessage, type BushSlashMessage } from '#lib';
import {
+ AkairoApplicationCommandAutocompleteOption,
+ AkairoApplicationCommandChannelOptionData,
+ AkairoApplicationCommandChoicesData,
+ AkairoApplicationCommandNonOptionsData,
+ AkairoApplicationCommandNumericOptionData,
+ AkairoApplicationCommandOptionData,
+ AkairoApplicationCommandSubCommandData,
+ AkairoApplicationCommandSubGroupData,
Command,
+ MissingPermissionSupplier,
+ SlashOption,
+ SlashResolveTypes,
type ArgumentOptions,
- type ArgumentPromptOptions,
type ArgumentTypeCaster,
type CommandOptions
} from 'discord-akairo';
import { BaseArgumentType } from 'discord-akairo/dist/src/struct/commands/arguments/Argument';
-import { type PermissionResolvable, type Snowflake } from 'discord.js';
+import { ApplicationCommandOptionChoice, type PermissionResolvable, type Snowflake } from 'discord.js';
export type BaseBushArgumentType =
| BaseArgumentType
@@ -18,14 +28,76 @@ export type BaseBushArgumentType =
| 'discordEmoji'
| 'roleWithDuration'
| 'abbreviatedNumber'
- | 'globalUser';
+ | 'globalUser'
+ | 'messageLink'
export type BushArgumentType = BaseBushArgumentType | RegExp;
-interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type'> {
+interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type' | 'prompt'> {
id: string;
- description?: string;
- prompt?: ArgumentPromptOptions;
+ description: string;
+
+ /**
+ * The message sent for the prompt and the slash command description.
+ */
+ prompt?: string;
+
+ /**
+ * The message set for the retry prompt.
+ */
+ retry?: string;
+
+ /**
+ * Whether or not the argument is optional.
+ */
+ optional?: boolean;
+
+ /**
+ * The type used for slash commands. Set to false to disable this argument for slash commands.
+ */
+ slashType: AkairoApplicationCommandOptionData['type'] | false;
+
+ /**
+ * Allows you to get a discord resolved object
+ *
+ * ex. get the resolved member object when the type is `USER`
+ */
+ slashResolve?: SlashResolveTypes;
+
+ /**
+ * The choices of the option for the user to pick from
+ */
+ choices?: ApplicationCommandOptionChoice[];
+
+ /**
+ * Whether the option is an autocomplete option
+ */
+ autocomplete?: boolean;
+
+ /**
+ * When the option type is channel, the allowed types of channels that can be selected
+ */
+ channelTypes?: AkairoApplicationCommandChannelOptionData['channelTypes'];
+
+ /**
+ * The minimum value for an `INTEGER` or `NUMBER` option
+ */
+ minValue?: number;
+
+ /**
+ * The maximum value for an `INTEGER` or `NUMBER` option
+ */
+ maxValue?: number;
+
+ /**
+ * Restrict this argument to only slash or only text commands.
+ */
+ only?: 'slash' | 'text';
+
+ /**
+ * Readable type for the help command.
+ */
+ readableType?: string;
}
export interface BushArgumentOptions extends BaseBushArgumentOptions {
@@ -93,7 +165,7 @@ export interface CustomBushArgumentOptions extends BaseBushArgumentOptions {
export type BushMissingPermissionSupplier = (message: BushMessage | BushSlashMessage) => Promise<any> | any;
-export interface BushCommandOptions extends Omit<CommandOptions, 'userPermissions' | 'clientPermissions'> {
+export interface BaseBushCommandOptions extends Omit<CommandOptions, 'userPermissions' | 'clientPermissions' | 'args'> {
/**
* Whether the command is hidden from the help command.
*/
@@ -109,12 +181,24 @@ export interface BushCommandOptions extends Omit<CommandOptions, 'userPermission
*/
restrictedGuilds?: Snowflake[];
- description: {
- content: string;
- usage: string[];
- examples: string[];
- };
+ /**
+ * The description of the command.
+ */
+ description: string;
+
+ /**
+ * Show how to use the command.
+ */
+ usage: string[];
+ /**
+ * Examples for how to use the command.
+ */
+ examples: string[];
+
+ /**
+ * The arguments for the command.
+ */
args?: BushArgumentOptions[] & CustomBushArgumentOptions[];
category: string;
@@ -138,6 +222,33 @@ export interface BushCommandOptions extends Omit<CommandOptions, 'userPermission
* Permissions required by the user to run this command.
*/
userPermissions: PermissionResolvable | PermissionResolvable[] | BushMissingPermissionSupplier;
+
+ /**
+ * Restrict this argument to owners
+ */
+ ownerOnly?: boolean;
+
+ /**
+ * Restrict this argument to super users.
+ */
+ superUserOnly?: boolean;
+
+ /**
+ * Use instead of {@link BaseBushCommandOptions.args} when using argument generators or custom slashOptions
+ */
+ helpArgs?: BushArgumentOptions[];
+}
+
+export type BushCommandOptions = Omit<BaseBushCommandOptions, 'helpArgs'> | Omit<BaseBushCommandOptions, 'args'>;
+
+export interface ArgsInfo {
+ id: string;
+ description: string;
+ optional?: boolean;
+ slashType: AkairoApplicationCommandOptionData['type'] | false;
+ slashResolve?: SlashResolveTypes;
+ only?: 'slash' | 'text';
+ type: string;
}
export class BushCommand extends Command {
@@ -145,18 +256,29 @@ export class BushCommand extends Command {
public declare handler: BushCommandHandler;
- public declare description: {
- content: string;
- usage: string[];
- examples: string[];
- };
+ public declare description: string;
+
+ /**
+ * Show how to use the command.
+ */
+ public usage: string[];
+
+ /**
+ * Examples for how to use the command.
+ */
+ public examples: string[];
/**
- * The command's options
+ * The options sent to the constructor
*/
public options: BushCommandOptions;
/**
+ * The options sent to the super call
+ */
+ public parsedOptions: CommandOptions;
+
+ /**
* The channels the command is limited to run in.
*/
public restrictedChannels: Snowflake[] | undefined;
@@ -181,24 +303,138 @@ export class BushCommand extends Command {
*/
public bypassChannelBlacklist: boolean;
+ /**
+ * Info about the arguments for the help command.
+ */
+ public argsInfo?: ArgsInfo[];
+
public constructor(id: string, options: BushCommandOptions) {
- if (options.args && typeof options.args !== 'function') {
- options.args.forEach((_, index: number) => {
- if ('customType' in options.args![index]) {
- // @ts-expect-error: shut
- if (!options.args[index]['type']) options.args[index]['type'] = options.args[index]['customType'];
- delete options.args![index]['customType'];
+ const options_ = options as BaseBushCommandOptions;
+
+ if (options_.args && typeof options_.args !== 'function') {
+ options_.args.forEach((_, index: number) => {
+ if ('customType' in (options_.args?.[index] ?? {})) {
+ if (!options_.args![index]['type']) options_.args![index]['type'] = options_.args![index]['customType']! as any;
+ delete options_.args![index]['customType'];
}
});
}
- // incompatible options
- super(id, options as any);
- this.options = options;
- this.hidden = Boolean(options.hidden);
- this.restrictedChannels = options.restrictedChannels;
- this.restrictedGuilds = options.restrictedGuilds;
- this.pseudo = Boolean(options.pseudo);
- this.bypassChannelBlacklist = Boolean(options.bypassChannelBlacklist);
+
+ const newOptions: CommandOptions = {};
+ if ('aliases' in options_) newOptions.aliases = options_.aliases;
+ if ('args' in options_ && typeof options_.args === 'object') {
+ const newTextArgs: ArgumentOptions[] = [];
+ const newSlashArgs: SlashOption[] = [];
+ for (const arg of options_.args) {
+ if (arg.only !== 'slash' && !options_.slashOnly) {
+ const newArg: ArgumentOptions = {};
+ if ('default' in arg) newArg.default = arg.default;
+ if ('description' in arg) newArg.description = arg.description;
+ if ('flag' in arg) newArg.flag = arg.flag;
+ if ('id' in arg) newArg.id = arg.id;
+ if ('index' in arg) newArg.index = arg.index;
+ if ('limit' in arg) newArg.limit = arg.limit;
+ if ('match' in arg) newArg.match = arg.match;
+ if ('modifyOtherwise' in arg) newArg.modifyOtherwise = arg.modifyOtherwise;
+ if ('multipleFlags' in arg) newArg.multipleFlags = arg.multipleFlags;
+ if ('otherwise' in arg) newArg.otherwise = arg.otherwise;
+ if ('prompt' in arg || 'retry' in arg || 'optional' in arg) {
+ newArg.prompt = {};
+ if ('prompt' in arg) newArg.prompt.start = arg.prompt;
+ if ('retry' in arg) newArg.prompt.retry = arg.retry;
+ if ('optional' in arg) newArg.prompt.optional = arg.optional;
+ }
+ if ('type' in arg) newArg.type = arg.type;
+ if ('unordered' in arg) newArg.unordered = arg.unordered;
+ newTextArgs.push(newArg);
+ }
+ if (
+ arg.only !== 'text' &&
+ !('slashOptions' in options_) &&
+ (options_.slash || options_.slashOnly) &&
+ arg.slashType !== false
+ ) {
+ const newArg: {
+ [key in SlashOptionKeys]?: any;
+ } = {
+ name: arg.id,
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ description: arg.prompt || arg.description || 'No description provided.',
+ type: arg.slashType
+ };
+ if ('slashResolve' in arg) newArg.resolve = arg.slashResolve;
+ if ('autocomplete' in arg) newArg.autocomplete = arg.autocomplete;
+ if ('channelTypes' in arg) newArg.channelTypes = arg.channelTypes;
+ if ('choices' in arg) newArg.choices = arg.choices;
+ if ('minValue' in arg) newArg.minValue = arg.minValue;
+ if ('maxValue' in arg) newArg.maxValue = arg.maxValue;
+ newArg.required = 'optional' in arg ? !arg.optional : true;
+ newSlashArgs.push(newArg as SlashOption);
+ }
+ }
+ newOptions.args = newTextArgs;
+ newOptions.slashOptions = options_.slashOptions ?? newSlashArgs;
+ }
+ type perm = PermissionResolvable | PermissionResolvable[] | MissingPermissionSupplier;
+
+ if ('argumentDefaults' in options_) newOptions.argumentDefaults = options_.argumentDefaults;
+ if ('before' in options_) newOptions.before = options_.before;
+ if ('channel' in options_) newOptions.channel = options_.channel;
+ if ('clientPermissions' in options_) newOptions.clientPermissions = options_.clientPermissions as perm;
+ if ('condition' in options_) newOptions.condition = options_.condition;
+ if ('cooldown' in options_) newOptions.cooldown = options_.cooldown;
+ if ('description' in options_) newOptions.description = options_.description;
+ if ('editable' in options_) newOptions.editable = options_.editable;
+ if ('flags' in options_) newOptions.flags = options_.flags;
+ if ('ignoreCooldown' in options_) newOptions.ignoreCooldown = options_.ignoreCooldown;
+ if ('ignorePermissions' in options_) newOptions.ignorePermissions = options_.ignorePermissions;
+ if ('lock' in options_) newOptions.lock = options_.lock;
+ if ('onlyNsfw' in options_) newOptions.onlyNsfw = options_.onlyNsfw;
+ if ('optionFlags' in options_) newOptions.optionFlags = options_.optionFlags;
+ if ('ownerOnly' in options_) newOptions.ownerOnly = options_.ownerOnly;
+ if ('prefix' in options_) newOptions.prefix = options_.prefix;
+ if ('quoted' in options_) newOptions.quoted = options_.quoted;
+ if ('ratelimit' in options_) newOptions.ratelimit = options_.ratelimit;
+ if ('regex' in options_) newOptions.regex = options_.regex;
+ if ('separator' in options_) newOptions.separator = options_.separator;
+ if ('slash' in options_) newOptions.slash = options_.slash;
+ if ('slashEphemeral' in options_) newOptions.slashEphemeral = options_.slashEphemeral;
+ if ('slashGuilds' in options_) newOptions.slashGuilds = options_.slashGuilds;
+ if ('slashOptions' in options_) newOptions.slashOptions = options_.slashOptions;
+ if ('superUserOnly' in options_) newOptions.superUserOnly = options_.superUserOnly;
+ if ('typing' in options_) newOptions.typing = options_.typing;
+ if ('userPermissions' in options_) newOptions.userPermissions = options_.userPermissions as perm;
+
+ super(id, newOptions);
+
+ if (options_.args || options_.helpArgs) {
+ const argsInfo: ArgsInfo[] = [];
+
+ for (const arg of (options_.args ?? options_.helpArgs)!) {
+ argsInfo.push({
+ id: arg.id,
+ description: arg.description,
+ optional: arg.optional,
+ slashType: arg.slashType,
+ slashResolve: arg.slashResolve,
+ only: arg.only,
+ type: (arg.readableType ?? arg.type) as string
+ });
+ }
+
+ this.argsInfo = argsInfo;
+ }
+
+ this.description = options_.description;
+ this.usage = options_.usage;
+ this.examples = options_.examples;
+ this.options = options_;
+ this.parsedOptions = newOptions;
+ this.hidden = !!options_.hidden;
+ this.restrictedChannels = options_.restrictedChannels;
+ this.restrictedGuilds = options_.restrictedGuilds;
+ this.pseudo = !!options_.pseudo;
+ this.bypassChannelBlacklist = !!options_.bypassChannelBlacklist;
}
}
@@ -206,3 +442,12 @@ export interface BushCommand {
exec(message: BushMessage, args: any): any;
exec(message: BushMessage | BushSlashMessage, args: any): any;
}
+
+type SlashOptionKeys =
+ | keyof AkairoApplicationCommandSubGroupData
+ | keyof AkairoApplicationCommandNonOptionsData
+ | keyof AkairoApplicationCommandChannelOptionData
+ | keyof AkairoApplicationCommandChoicesData
+ | keyof AkairoApplicationCommandAutocompleteOption
+ | keyof AkairoApplicationCommandNumericOptionData
+ | keyof AkairoApplicationCommandSubCommandData;
diff --git a/src/lib/extensions/discord.js/BushGuild.ts b/src/lib/extensions/discord.js/BushGuild.ts
index e3b39d3..9c272ff 100644
--- a/src/lib/extensions/discord.js/BushGuild.ts
+++ b/src/lib/extensions/discord.js/BushGuild.ts
@@ -9,8 +9,9 @@ import type {
GuildLogType,
GuildModel
} from '#lib';
-import { Guild, type MessageOptions, type UserResolvable } from 'discord.js';
+import { Guild, MessagePayload, type MessageOptions, type UserResolvable } from 'discord.js';
import type { RawGuildData } from 'discord.js/typings/rawDataTypes';
+import _ from 'lodash';
import { Moderation } from '../../common/Moderation.js';
import { Guild as GuildDB } from '../../models/Guild.js';
import { ModLogType } from '../../models/ModLog.js';
@@ -24,29 +25,52 @@ export class BushGuild extends Guild {
super(client, data);
}
+ /**
+ * Checks if the guild has a certain custom feature.
+ * @param feature The feature to check for
+ */
public async hasFeature(feature: GuildFeatures): Promise<boolean> {
const features = await this.getSetting('enabledFeatures');
return features.includes(feature);
}
+ /**
+ * Adds a custom feature to the guild.
+ * @param feature The feature to add
+ * @param moderator The moderator responsible for adding a feature
+ */
public async addFeature(feature: GuildFeatures, moderator?: BushGuildMember): Promise<GuildModel['enabledFeatures']> {
const features = await this.getSetting('enabledFeatures');
const newFeatures = util.addOrRemoveFromArray('add', features, feature);
return (await this.setSetting('enabledFeatures', newFeatures, moderator)).enabledFeatures;
}
+ /**
+ * Removes a custom feature from the guild.
+ * @param feature The feature to remove
+ * @param moderator The moderator responsible for removing a feature
+ */
public async removeFeature(feature: GuildFeatures, moderator?: BushGuildMember): Promise<GuildModel['enabledFeatures']> {
const features = await this.getSetting('enabledFeatures');
const newFeatures = util.addOrRemoveFromArray('remove', features, feature);
return (await this.setSetting('enabledFeatures', newFeatures, moderator)).enabledFeatures;
}
+ /**
+ * Makes a custom feature the opposite of what it was before
+ * @param feature The feature to toggle
+ * @param moderator The moderator responsible for toggling a feature
+ */
public async toggleFeature(feature: GuildFeatures, moderator?: BushGuildMember): Promise<GuildModel['enabledFeatures']> {
return (await this.hasFeature(feature))
? await this.removeFeature(feature, moderator)
: await this.addFeature(feature, moderator);
}
+ /**
+ * Fetches a custom setting for the guild
+ * @param setting The setting to get
+ */
public async getSetting<K extends keyof GuildModel>(setting: K): Promise<GuildModel[K]> {
return (
client.cache.guilds.get(this.id)?.[setting] ??
@@ -54,6 +78,12 @@ export class BushGuild extends Guild {
);
}
+ /**
+ * Sets a custom setting for the guild
+ * @param setting The setting to change
+ * @param value The value to change the setting to
+ * @param moderator The moderator to responsible for changing the setting
+ */
public async setSetting<K extends Exclude<keyof GuildModel, 'id'>>(
setting: K,
value: GuildDB[K],
@@ -208,13 +238,25 @@ export class BushGuild extends Guild {
}
/**
- * Sends a message to the guild's specified logging channel.
+ * Sends a message to the guild's specified logging channel
+ * @param logType The corresponding channel that the message will be sent to
+ * @param message The parameters for {@link BushTextChannel.send}
*/
- public async sendLogChannel(logType: GuildLogType, message: MessageOptions) {
+ public async sendLogChannel(logType: GuildLogType, message: string | MessagePayload | MessageOptions) {
const logChannel = await this.getLogChannel(logType);
if (!logChannel || logChannel.type !== 'GUILD_TEXT') return;
if (!logChannel.permissionsFor(this.me!.id)?.has(['VIEW_CHANNEL', 'SEND_MESSAGES', 'EMBED_LINKS'])) return;
return await logChannel.send(message).catch(() => null);
}
+
+ /**
+ * Sends a formatted error message in a guild's error log channel
+ * @param title The title of the error embed
+ * @param message The description of the error embed
+ */
+ public async error(title: string, message: string) {
+ void client.console.info(_.camelCase(title), message.replace(/\*\*(.*?)\*\*/g, '<<$1>>'));
+ void this.sendLogChannel('error', { embeds: [{ title: title, description: message, color: util.colors.error }] });
+ }
}
diff --git a/src/lib/extensions/global.d.ts b/src/lib/extensions/global.d.ts
index 1a30056..8427873 100644
--- a/src/lib/extensions/global.d.ts
+++ b/src/lib/extensions/global.d.ts
@@ -4,4 +4,13 @@ declare global {
var client: BushClient;
var util: BushClientUtil;
var __rootdir__: string;
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ interface ReadonlyArray<T> {
+ includes<S, R extends `${Extract<S, string>}`>(
+ this: ReadonlyArray<R>,
+ searchElement: S,
+ fromIndex?: number
+ ): searchElement is R & S;
+ }
}
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
index 52b0f40..434a0a7 100644
--- a/src/lib/utils/BushConstants.ts
+++ b/src/lib/utils/BushConstants.ts
@@ -1,12 +1,28 @@
-import { Constants, type ConstantsColors } from 'discord.js';
+import { Constants } from 'discord.js';
+import { BushClientUtil } from '../extensions/discord-akairo/BushClientUtil.js';
const rawCapeUrl = 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/';
export class BushConstants {
- public static get emojis() {
- return BushEmojis;
- }
+ public static emojis = BushClientUtil.deepFreeze({
+ success: '<:success:837109864101707807>',
+ warn: '<:warn:848726900876247050>',
+ error: '<:error:837123021016924261>',
+ successFull: '<:success_full:850118767576088646>',
+ warnFull: '<:warn_full:850118767391539312>',
+ errorFull: '<:error_full:850118767295201350>',
+ mad: '<:mad:783046135392239626>',
+ join: '<:join:850198029809614858>',
+ leave: '<:leave:850198048205307919>',
+ loading: '<a:Loading:853419254619963392>',
+ offlineCircle: '<:offline:787550565382750239>',
+ dndCircle: '<:dnd:787550487633330176>',
+ idleCircle: '<:idle:787550520956551218>',
+ onlineCircle: '<:online:787550449435803658>',
+ cross: '<:cross:878319362539421777>',
+ check: '<:check:878320135297961995>'
+ } as const);
- public static colors: bushColors = {
+ public static colors = BushClientUtil.deepFreeze({
default: '#1FD8F1',
error: '#EF4947',
warn: '#FEBA12',
@@ -29,11 +45,11 @@ export class BushConstants {
darkGray: '#7a7a7a',
black: '#000000',
orange: '#E86100',
- discord: Constants.Colors
- };
+ discord: Object.assign({}, Constants.Colors)
+ } as const);
// Somewhat stolen from @Mzato0001
- public static TimeUnits: { [key: string]: { match: RegExp; value: number } } = {
+ public static TimeUnits = BushClientUtil.deepFreeze({
milliseconds: {
match: / (?:(?<milliseconds>-?(?:\d+)?\.?\d+) *(?:milliseconds?|msecs?|ms))/im,
value: 1
@@ -66,19 +82,43 @@ export class BushConstants {
match: / (?:(?<years>-?(?:\d+)?\.?\d+) *(?:years?|y))/im,
value: 1000 * 60 * 60 * 24 * 365.25 //leap years
}
- };
+ } as const);
- public static regex = {
+ public static regex = BushClientUtil.deepFreeze({
snowflake: /\d{15,21}/im,
- discordEmoji: /<a?:(?<name>[a-zA-Z0-9_]+):(?<id>\d{15,21})>/im
- };
+ discordEmoji: /<a?:(?<name>[a-zA-Z0-9_]+):(?<id>\d{15,21})>/im,
- public static get pronounMapping() {
- return PronounMap;
- }
+ //stolen from geek
+ messageLink:
+ /(?:ptb\.|canary\.|staging\.|lc\.)?(?:discord(?:app)?|inv)\.(?:com|wtf)?\/channels\/(?<guild_id>\d{15,21}|@me)\/(?<channel_id>\d{15,21})\/(?<message_id>\d{15,21})/im
+ } as const);
+
+ public static pronounMapping = BushClientUtil.deepFreeze({
+ unspecified: 'Unspecified',
+ hh: 'He/Him',
+ hi: 'He/It',
+ hs: 'He/She',
+ ht: 'He/They',
+ ih: 'It/Him',
+ ii: 'It/Its',
+ is: 'It/She',
+ it: 'It/They',
+ shh: 'She/He',
+ sh: 'She/Her',
+ si: 'She/It',
+ st: 'She/They',
+ th: 'They/He',
+ ti: 'They/It',
+ ts: 'They/She',
+ tt: 'They/Them',
+ any: 'Any pronouns',
+ other: 'Other pronouns',
+ ask: 'Ask me my pronouns',
+ avoid: 'Avoid pronouns, use my name'
+ } as const);
/** A bunch of mappings */
- public static mappings = {
+ public static mappings = BushClientUtil.deepFreeze({
guilds: {
bush: '516977525906341928',
tree: '767448775450820639',
@@ -326,25 +366,129 @@ export class BushConstants {
'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
'DJ': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator']
}
- };
+ } as const);
- public static get ArgumentMatches() {
- return ArgumentMatchesEnum;
- }
+ public static ArgumentMatches = BushClientUtil.deepFreeze({
+ PHRASE: 'phrase',
+ FLAG: 'flag',
+ OPTION: 'option',
+ REST: 'rest',
+ SEPARATE: 'separate',
+ TEXT: 'text',
+ CONTENT: 'content',
+ REST_CONTENT: 'restContent',
+ NONE: 'none'
+ } as const);
- public static get ArgumentTypes() {
- return BushArgumentTypesEnum;
- }
+ public static ArgumentTypes = BushClientUtil.deepFreeze({
+ STRING: 'string',
+ LOWERCASE: 'lowercase',
+ UPPERCASE: 'uppercase',
+ CHAR_CODES: 'charCodes',
+ NUMBER: 'number',
+ INTEGER: 'integer',
+ BIGINT: 'bigint',
+ EMOJINT: 'emojint',
+ URL: 'url',
+ DATE: 'date',
+ COLOR: 'color',
+ USER: 'user',
+ USERS: 'users',
+ MEMBER: 'member',
+ MEMBERS: 'members',
+ RELEVANT: 'relevant',
+ RELEVANTS: 'relevants',
+ CHANNEL: 'channel',
+ CHANNELS: 'channels',
+ TEXT_CHANNEL: 'textChannel',
+ TEXT_CHANNELS: 'textChannels',
+ VOICE_CHANNEL: 'voiceChannel',
+ VOICE_CHANNELS: 'voiceChannels',
+ CATEGORY_CHANNEL: 'categoryChannel',
+ CATEGORY_CHANNELS: 'categoryChannels',
+ NEWS_CHANNEL: 'newsChannel',
+ NEWS_CHANNELS: 'newsChannels',
+ STORE_CHANNEL: 'storeChannel',
+ STORE_CHANNELS: 'storeChannels',
+ STAGE_CHANNEL: 'stageChannel',
+ STAGE_CHANNELS: 'stageChannels',
+ THREAD_CHANNEL: 'threadChannel',
+ THREAD_CHANNELS: 'threadChannels',
+ ROLE: 'role',
+ ROLES: 'roles',
+ EMOJI: 'emoji',
+ EMOJIS: 'emojis',
+ GUILD: 'guild',
+ GUILDS: 'guilds',
+ MESSAGE: 'message',
+ GUILD_MESSAGE: 'guildMessage',
+ RELEVANT_MESSAGE: 'relevantMessage',
+ INVITE: 'invite',
+ USER_MENTION: 'userMention',
+ MEMBER_MENTION: 'memberMention',
+ CHANNEL_MENTION: 'channelMention',
+ ROLE_MENTION: 'roleMention',
+ EMOJI_MENTION: 'emojiMention',
+ COMMAND_ALIAS: 'commandAlias',
+ COMMAND: 'command',
+ INHIBITOR: 'inhibitor',
+ LISTENER: 'listener',
+ TASK: 'task',
+ CONTEXT_MENU_COMMAND: 'contextMenuCommand',
+ DURATION: 'duration',
+ CONTENT_WITH_DURATION: 'contentWithDuration',
+ PERMISSION: 'permission',
+ SNOWFLAKE: 'snowflake',
+ DISCORD_EMOJI: 'discordEmoji',
+ ROLE_WITH_DURATION: 'roleWithDuration',
+ ABBREVIATED_NUMBER: 'abbreviatedNumber',
+ GLOBAL_USER: 'globalUser'
+ } as const);
- public static get BlockedReasons() {
- return BushBlockedReasonsEnum;
- }
+ public static BlockedReasons = BushClientUtil.deepFreeze({
+ CLIENT: 'client',
+ BOT: 'bot',
+ OWNER: 'owner',
+ SUPER_USER: 'superUser',
+ GUILD: 'guild',
+ DM: 'dm',
+ AUTHOR_NOT_FOUND: 'authorNotFound',
+ NOT_NSFW: 'notNsfw',
+ DISABLED_GUILD: 'disabledGuild',
+ DISABLED_GLOBAL: 'disabledGlobal',
+ ROLE_BLACKLIST: 'roleBlacklist',
+ USER_GUILD_BLACKLIST: 'userGuildBlacklist',
+ USER_GLOBAL_BLACKLIST: 'userGlobalBlacklist',
+ RESTRICTED_GUILD: 'restrictedGuild',
+ CHANNEL_GUILD_BLACKLIST: 'channelGuildBlacklist',
+ CHANNEL_GLOBAL_BLACKLIST: 'channelGlobalBlacklist',
+ RESTRICTED_CHANNEL: 'restrictedChannel'
+ } as const);
- public static get CommandHandlerEvents() {
- return BushCommandHandlerEventsEnum;
- }
+ public static CommandHandlerEvents = BushClientUtil.deepFreeze({
+ COMMAND_BLOCKED: 'commandBlocked',
+ COMMAND_BREAKOUT: 'commandBreakout',
+ COMMAND_CANCELLED: 'commandCancelled',
+ COMMAND_FINISHED: 'commandFinished',
+ COMMAND_INVALID: 'commandInvalid',
+ COMMAND_LOCKED: 'commandLocked',
+ COMMAND_STARTED: 'commandStarted',
+ COOLDOWN: 'cooldown',
+ ERROR: 'error',
+ IN_PROMPT: 'inPrompt',
+ MESSAGE_BLOCKED: 'messageBlocked',
+ MESSAGE_INVALID: 'messageInvalid',
+ MISSING_PERMISSIONS: 'missingPermissions',
+ SLASH_BLOCKED: 'slashBlocked',
+ SLASH_ERROR: 'slashError',
+ SLASH_FINISHED: 'slashFinished',
+ SLASH_MISSING_PERMISSIONS: 'slashMissingPermissions',
+ SLASH_NOT_FOUND: 'slashNotFound',
+ SLASH_STARTED: 'slashStarted',
+ SLASH_ONLY: 'slashOnly'
+ } as const);
- public static moulberryBushRoleMap = [
+ public static moulberryBushRoleMap = BushClientUtil.deepFreeze([
{ name: '*', id: '792453550768390194' },
{ name: 'Admin Perms', id: '746541309853958186' },
{ name: 'Sr. Moderator', id: '782803470205190164' },
@@ -370,197 +514,8 @@ export class BushConstants {
{ name: 'No VC', id: '788850482554208267' },
{ name: 'No Giveaways', id: '808265422334984203' },
{ name: 'No Support', id: '790247359824396319' }
- ];
-}
-
-export enum PronounMap {
- unspecified = 'Unspecified',
- hh = 'He/Him',
- hi = 'He/It',
- hs = 'He/She',
- ht = 'He/They',
- ih = 'It/Him',
- ii = 'It/Its',
- is = 'It/She',
- it = 'It/They',
- shh = 'She/He',
- sh = 'She/Her',
- si = 'She/It',
- st = 'She/They',
- th = 'They/He',
- ti = 'They/It',
- ts = 'They/She',
- tt = 'They/Them',
- any = 'Any pronouns',
- other = 'Other pronouns',
- ask = 'Ask me my pronouns',
- avoid = 'Avoid pronouns, use my name'
-}
-
-export enum BushEmojis {
- success = '<:success:837109864101707807>',
- warn = '<:warn:848726900876247050>',
- error = '<:error:837123021016924261>',
- successFull = '<:success_full:850118767576088646>',
- warnFull = '<:warn_full:850118767391539312>',
- errorFull = '<:error_full:850118767295201350>',
- mad = '<:mad:783046135392239626>',
- join = '<:join:850198029809614858>',
- leave = '<:leave:850198048205307919>',
- loading = '<a:Loading:853419254619963392>',
- offlineCircle = '<:offline:787550565382750239>',
- dndCircle = '<:dnd:787550487633330176>',
- idleCircle = '<:idle:787550520956551218>',
- onlineCircle = '<:online:787550449435803658>',
- cross = '<:cross:878319362539421777>',
- check = '<:check:878320135297961995>'
-}
-
-export enum ArgumentMatchesEnum {
- PHRASE = 'phrase',
- FLAG = 'flag',
- OPTION = 'option',
- REST = 'rest',
- SEPARATE = 'separate',
- TEXT = 'text',
- CONTENT = 'content',
- REST_CONTENT = 'restContent',
- NONE = 'none'
-}
-
-export enum BushArgumentTypesEnum {
- STRING = 'string',
- LOWERCASE = 'lowercase',
- UPPERCASE = 'uppercase',
- CHAR_CODES = 'charCodes',
- NUMBER = 'number',
- INTEGER = 'integer',
- BIGINT = 'bigint',
- EMOJINT = 'emojint',
- URL = 'url',
- DATE = 'date',
- COLOR = 'color',
- USER = 'user',
- USERS = 'users',
- MEMBER = 'member',
- MEMBERS = 'members',
- RELEVANT = 'relevant',
- RELEVANTS = 'relevants',
- CHANNEL = 'channel',
- CHANNELS = 'channels',
- TEXT_CHANNEL = 'textChannel',
- TEXT_CHANNELS = 'textChannels',
- VOICE_CHANNEL = 'voiceChannel',
- VOICE_CHANNELS = 'voiceChannels',
- CATEGORY_CHANNEL = 'categoryChannel',
- CATEGORY_CHANNELS = 'categoryChannels',
- NEWS_CHANNEL = 'newsChannel',
- NEWS_CHANNELS = 'newsChannels',
- STORE_CHANNEL = 'storeChannel',
- STORE_CHANNELS = 'storeChannels',
- STAGE_CHANNEL = 'stageChannel',
- STAGE_CHANNELS = 'stageChannels',
- THREAD_CHANNEL = 'threadChannel',
- THREAD_CHANNELS = 'threadChannels',
- ROLE = 'role',
- ROLES = 'roles',
- EMOJI = 'emoji',
- EMOJIS = 'emojis',
- GUILD = 'guild',
- GUILDS = 'guilds',
- MESSAGE = 'message',
- GUILD_MESSAGE = 'guildMessage',
- RELEVANT_MESSAGE = 'relevantMessage',
- INVITE = 'invite',
- USER_MENTION = 'userMention',
- MEMBER_MENTION = 'memberMention',
- CHANNEL_MENTION = 'channelMention',
- ROLE_MENTION = 'roleMention',
- EMOJI_MENTION = 'emojiMention',
- COMMAND_ALIAS = 'commandAlias',
- COMMAND = 'command',
- INHIBITOR = 'inhibitor',
- LISTENER = 'listener',
- TASK = 'task',
- CONTEXT_MENU_COMMAND = 'contextMenuCommand',
- DURATION = 'duration',
- CONTENT_WITH_DURATION = 'contentWithDuration',
- PERMISSION = 'permission',
- SNOWFLAKE = 'snowflake',
- DISCORD_EMOJI = 'discordEmoji',
- ROLE_WITH_DURATION = 'roleWithDuration',
- ABBREVIATED_NUMBER = 'abbreviatedNumber',
- GLOBAL_USER = 'globalUser'
-}
-
-export enum BushBlockedReasonsEnum {
- CLIENT = 'client',
- BOT = 'bot',
- OWNER = 'owner',
- SUPER_USER = 'superUser',
- GUILD = 'guild',
- DM = 'dm',
- AUTHOR_NOT_FOUND = 'authorNotFound',
- NOT_NSFW = 'notNsfw',
- DISABLED_GUILD = 'disabledGuild',
- DISABLED_GLOBAL = 'disabledGlobal',
- ROLE_BLACKLIST = 'roleBlacklist',
- USER_GUILD_BLACKLIST = 'userGuildBlacklist',
- USER_GLOBAL_BLACKLIST = 'userGlobalBlacklist',
- RESTRICTED_GUILD = 'restrictedGuild',
- CHANNEL_GUILD_BLACKLIST = 'channelGuildBlacklist',
- CHANNEL_GLOBAL_BLACKLIST = 'channelGlobalBlacklist',
- RESTRICTED_CHANNEL = 'restrictedChannel'
-}
-
-export enum BushCommandHandlerEventsEnum {
- COMMAND_BLOCKED = 'commandBlocked',
- COMMAND_BREAKOUT = 'commandBreakout',
- COMMAND_CANCELLED = 'commandCancelled',
- COMMAND_FINISHED = 'commandFinished',
- COMMAND_INVALID = 'commandInvalid',
- COMMAND_LOCKED = 'commandLocked',
- COMMAND_STARTED = 'commandStarted',
- COOLDOWN = 'cooldown',
- ERROR = 'error',
- IN_PROMPT = 'inPrompt',
- MESSAGE_BLOCKED = 'messageBlocked',
- MESSAGE_INVALID = 'messageInvalid',
- MISSING_PERMISSIONS = 'missingPermissions',
- SLASH_BLOCKED = 'slashBlocked',
- SLASH_ERROR = 'slashError',
- SLASH_FINISHED = 'slashFinished',
- SLASH_MISSING_PERMISSIONS = 'slashMissingPermissions',
- SLASH_NOT_FOUND = 'slashNotFound',
- SLASH_STARTED = 'slashStarted',
- SLASH_ONLY = 'slashOnly'
-}
-
-interface bushColors {
- default: '#1FD8F1';
- error: '#EF4947';
- warn: '#FEBA12';
- success: '#3BB681';
- info: '#3B78FF';
- red: '#ff0000';
- blue: '#0055ff';
- aqua: '#00bbff';
- purple: '#8400ff';
- blurple: '#5440cd';
- newBlurple: '#5865f2';
- pink: '#ff00e6';
- green: '#00ff1e';
- darkGreen: '#008f11';
- gold: '#b59400';
- yellow: '#ffff00';
- white: '#ffffff';
- gray: '#a6a6a6';
- lightGray: '#cfcfcf';
- darkGray: '#7a7a7a';
- black: '#000000';
- orange: '#E86100';
- discord: ConstantsColors;
+ ] as const);
}
-export type PronounCode = keyof typeof PronounMap;
-export type Pronoun = PronounMap;
+export type PronounCode = keyof typeof BushConstants['pronounMapping'];
+export type Pronoun = typeof BushConstants['pronounMapping'][PronounCode];
diff --git a/src/lib/utils/BushLogger.ts b/src/lib/utils/BushLogger.ts
index 4b89622..3421985 100644
--- a/src/lib/utils/BushLogger.ts
+++ b/src/lib/utils/BushLogger.ts
@@ -1,5 +1,6 @@
import chalk from 'chalk';
-import { MessageEmbed, Util, type Message } from 'discord.js';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { MessageEmbed, Util, type Message, type PartialTextBasedChannelFields } from 'discord.js';
import { inspect } from 'util';
import { type BushSendMessageType } from '../extensions/discord-akairo/BushClient';
@@ -52,22 +53,27 @@ export class BushLogger {
/**
* Logs information. Highlight information by surrounding it in `<<>>`.
- * @param header - The header displayed before the content, displayed in cyan.
- * @param content - The content to log, highlights displayed in bright blue.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header displayed before the content, displayed in cyan.
+ * @param content The content to log, highlights displayed in bright blue.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static get log() {
return BushLogger.info;
}
- /** Sends a message to the log channel */
+ /**
+ * Sends a message to the log channel
+ * @param message The parameter to pass to {@link PartialTextBasedChannelFields.send}
+ */
public static async channelLog(message: BushSendMessageType) {
const channel = await util.getConfigChannel('log');
await channel.send(message).catch(() => {});
}
- /** Sends a message to the error channel */
+ /**
+ * Sends a message to the error channel
+ */
public static async channelError(message: BushSendMessageType): Promise<Message> {
const channel = await util.getConfigChannel('error');
return await channel.send(message);
@@ -75,8 +81,8 @@ export class BushLogger {
/**
* Logs debug information. Only works in dev is enabled in the config.
- * @param content - The content to log.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param content The content to log.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static debug(content: any, depth = 0): void {
if (!client.config.isDevelopment) return;
@@ -86,7 +92,7 @@ export class BushLogger {
/**
* Logs raw debug information. Only works in dev is enabled in the config.
- * @param content - The content to log.
+ * @param content The content to log.
*/
public static debugRaw(...content: any): void {
if (!client.config.isDevelopment) return;
@@ -95,10 +101,10 @@ export class BushLogger {
/**
* Logs verbose information. Highlight information by surrounding it in `<<>>`.
- * @param header - The header printed before the content, displayed in grey.
- * @param content - The content to log, highlights displayed in bright black.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header printed before the content, displayed in grey.
+ * @param content The content to log, highlights displayed in bright black.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static async verbose(header: string, content: any, sendChannel = false, depth = 0) {
if (!client.config.logging.verbose) return;
@@ -116,10 +122,10 @@ export class BushLogger {
/**
* Logs information. Highlight information by surrounding it in `<<>>`.
- * @param header - The header displayed before the content, displayed in cyan.
- * @param content - The content to log, highlights displayed in bright blue.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header displayed before the content, displayed in cyan.
+ * @param content The content to log, highlights displayed in bright blue.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static async info(header: string, content: any, sendChannel = true, depth = 0) {
if (!client.config.logging.info) return;
@@ -137,10 +143,10 @@ export class BushLogger {
/**
* Logs warnings. Highlight information by surrounding it in `<<>>`.
- * @param header - The header displayed before the content, displayed in yellow.
- * @param content - The content to log, highlights displayed in bright yellow.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header displayed before the content, displayed in yellow.
+ * @param content The content to log, highlights displayed in bright yellow.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static async warn(header: string, content: any, sendChannel = true, depth = 0) {
const newContent = this.#inspectContent(content, depth, true);
@@ -161,10 +167,10 @@ export class BushLogger {
/**
* Logs errors. Highlight information by surrounding it in `<<>>`.
- * @param header - The header displayed before the content, displayed in bright red.
- * @param content - The content to log, highlights displayed in bright red.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header displayed before the content, displayed in bright red.
+ * @param content The content to log, highlights displayed in bright red.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static async error(header: string, content: any, sendChannel = true, depth = 0) {
const newContent = this.#inspectContent(content, depth, true);
@@ -185,10 +191,10 @@ export class BushLogger {
/**
* Logs successes. Highlight information by surrounding it in `<<>>`.
- * @param header - The header displayed before the content, displayed in green.
- * @param content - The content to log, highlights displayed in bright green.
- * @param sendChannel - Should this also be logged to discord? Defaults to false.
- * @param depth - The depth the content will inspected. Defaults to 0.
+ * @param header The header displayed before the content, displayed in green.
+ * @param content The content to log, highlights displayed in bright green.
+ * @param sendChannel Should this also be logged to discord? Defaults to false.
+ * @param depth The depth the content will inspected. Defaults to 0.
*/
public static async success(header: string, content: any, sendChannel = true, depth = 0) {
const newContent = this.#inspectContent(content, depth, true);
@@ -206,3 +212,5 @@ export class BushLogger {
await this.channelLog({ embeds: [embed] }).catch(() => {});
}
}
+
+/** @typedef {PartialTextBasedChannelFields} vscodeDontDeleteMyImportTy */ \ No newline at end of file
diff --git a/src/listeners/client/ready.ts b/src/listeners/client/ready.ts
index 0b57156..1fb5c4a 100644
--- a/src/listeners/client/ready.ts
+++ b/src/listeners/client/ready.ts
@@ -1,4 +1,4 @@
-import { BushListener, Guild } from '#lib';
+import { BushClientEvents, BushListener, Guild } from '#lib';
import chalk from 'chalk';
export default class ReadyListener extends BushListener {
@@ -10,7 +10,8 @@ export default class ReadyListener extends BushListener {
});
}
- public override async exec() {
+ // eslint-disable-next-line no-empty-pattern
+ public override async exec(...[]: BushClientEvents['ready']) {
client.taskHandler.startAll();
process.emit('ready' as any);
diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts
index 7c5bc67..2243abd 100644
--- a/src/listeners/commands/commandBlocked.ts
+++ b/src/listeners/commands/commandBlocked.ts
@@ -32,25 +32,25 @@ export default class CommandBlockedListener extends BushListener {
switch (reason) {
case reasons.OWNER: {
return await respond({
- content: `${util.emojis.error} Only my developers can run the ${util.format.bold(command!.toString())} command.`,
+ content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.toString())} command.`,
ephemeral: true
});
}
case reasons.SUPER_USER: {
return await respond({
- content: `${util.emojis.error} You must be a superuser to run the ${util.format.bold(command!.toString())} command.`,
+ content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.toString())} command.`,
ephemeral: true
});
}
case reasons.DISABLED_GLOBAL: {
return await respond({
- content: `${util.emojis.error} My developers disabled the ${util.format.bold(command!.toString())} command.`,
+ content: `${util.emojis.error} My developers disabled the ${util.format.input(command!.toString())} command.`,
ephemeral: true
});
}
case reasons.DISABLED_GUILD: {
return await respond({
- content: `${util.emojis.error} The ${util.format.bold(command!.toString())} command is currently disabled in \`${
+ content: `${util.emojis.error} The ${util.format.input(command!.toString())} command is currently disabled in \`${
message.guild?.name
}\`.`,
ephemeral: true
@@ -89,7 +89,7 @@ export default class CommandBlockedListener extends BushListener {
});
const pretty = util.oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.bold(command!.toString())} can only be run in ${pretty}.`,
+ content: `${util.emojis.error} ${util.format.input(command!.toString())} can only be run in ${pretty}.`,
ephemeral: true
});
}
@@ -102,7 +102,7 @@ export default class CommandBlockedListener extends BushListener {
});
const pretty = util.oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.bold(command!.toString())} can only be run in ${pretty}.`,
+ content: `${util.emojis.error} ${util.format.input(command!.toString())} can only be run in ${pretty}.`,
ephemeral: true
});
}
diff --git a/src/listeners/commands/messageBlocked.ts b/src/listeners/commands/messageBlocked.ts
index 6a0eaab..1b969ed 100644
--- a/src/listeners/commands/messageBlocked.ts
+++ b/src/listeners/commands/messageBlocked.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushBlockedReasonsEnum, type BushCommandHandlerEvents } from '#lib';
+import { BushListener, type BushCommandHandlerEvents } from '#lib';
export default class MessageBlockedListener extends BushListener {
public constructor() {
@@ -9,8 +9,7 @@ export default class MessageBlockedListener extends BushListener {
}
public override async exec(...[message, reason]: BushCommandHandlerEvents['messageBlocked']) {
- const reasons = client.consts.BlockedReasons;
- if ([reasons.CLIENT, reasons.BOT].includes(reason as BushBlockedReasonsEnum)) return;
+ if (['client', 'bot'].includes(reason)) return;
// return await CommandBlockedListener.handleBlocked(message as Message, null, reason);
return void client.console.verbose(`messageBlocked`, `<<${message.author.tag}>>'s message was blocked because ${reason}`);
}
diff --git a/src/listeners/custom/bushLevelUpdate.ts b/src/listeners/custom/bushLevelUpdate.ts
index 897def5..4504c45 100644
--- a/src/listeners/custom/bushLevelUpdate.ts
+++ b/src/listeners/custom/bushLevelUpdate.ts
@@ -1,5 +1,5 @@
import { BushListener, type BushClientEvents } from '#lib';
-import { Formatters, type TextChannel } from 'discord.js';
+import { type TextChannel } from 'discord.js';
export default class BushLevelUpdateListener extends BushListener {
public constructor() {
@@ -18,11 +18,7 @@ export default class BushLevelUpdateListener extends BushListener {
.catch(() => null)) ?? message.channel) as TextChannel;
const success = await channel
- .send(
- `${Formatters.bold(util.sanitizeWtlAndControl(member.user.tag))} leveled up to level ${Formatters.bold(
- `${newLevel}`
- )}.`
- )
+ .send(`${util.format.input(member.user.tag)} leveled up to level ${util.format.input(`${newLevel}`)}.`)
.catch(() => null);
if (!success) await client.console.warn('bushLevelUpdate', `Could not send level up message in ${message.guild}`);
diff --git a/src/listeners/guild/guildMemberAdd.ts b/src/listeners/guild/guildMemberAdd.ts
index f10255d..4c7d498 100644
--- a/src/listeners/guild/guildMemberAdd.ts
+++ b/src/listeners/guild/guildMemberAdd.ts
@@ -1,5 +1,5 @@
import { BushListener, StickyRole, type BushClientEvents, type BushGuildMember, type BushTextChannel } from '#lib';
-import { MessageEmbed, Util, type Snowflake } from 'discord.js';
+import { MessageEmbed, type Snowflake } from 'discord.js';
export default class GuildMemberAddListener extends BushListener {
public constructor() {
@@ -24,9 +24,9 @@ export default class GuildMemberAddListener extends BushListener {
if (member.guild.id !== welcome?.guild.id) throw new Error('Welcome channel must be in the guild.');
const embed = new MessageEmbed()
.setDescription(
- `${util.emojis.join} **${util.sanitizeWtlAndControl(
- Util.escapeMarkdown(member.user.tag)
- )}** joined the server. There are now ${member.guild.memberCount.toLocaleString()} members.`
+ `${util.emojis.join} ${util.format.input(
+ member.user.tag
+ )} joined the server. There are now ${member.guild.memberCount.toLocaleString()} members.`
)
.setColor(util.colors.green);
await welcome
@@ -34,13 +34,13 @@ export default class GuildMemberAddListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberAdd',
- `Sent a message for <<${util.sanitizeWtlAndControl(member.user.tag)}>> in <<${member.guild.name}>>.`
+ `Sent a message for ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
)
)
.catch(() =>
client.console.warn(
'guildMemberAdd',
- `Failed to send message for <<${util.sanitizeWtlAndControl(member.user.tag)}>> in <<${member.guild.name}>>.`
+ `Failed to send message for ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
)
);
}
@@ -62,19 +62,21 @@ export default class GuildMemberAddListener extends BushListener {
void member.setNickname(hadRoles.nickname).catch(() => {});
}
if (rolesArray?.length) {
- const addedRoles = await member.roles
- .add(rolesArray, "Returning member's previous roles.")
- .catch(
- () =>
- void client.console.warn(
- 'guildMemberAdd',
- `There was an error returning <<${util.sanitizeWtlAndControl(member.user.tag)}>>'s roles.`
- )
- );
+ const addedRoles = await member.roles.add(rolesArray, "Returning member's previous roles.").catch(() =>
+ member.guild.sendLogChannel('error', {
+ embeds: [
+ {
+ title: 'Sticky Roles Error',
+ description: `There was an error returning ${util.format.input(member.user.tag)}'s roles.`,
+ color: util.colors.error
+ }
+ ]
+ })
+ );
if (addedRoles) {
void client.console.info(
'guildMemberAdd',
- `Assigned sticky roles to <<${util.sanitizeWtlAndControl(member.user.tag)}>> in <<${member.guild.name}>>.`
+ `Assigned sticky roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
);
} else if (!addedRoles) {
const failedRoles: string[] = [];
@@ -88,9 +90,9 @@ export default class GuildMemberAddListener extends BushListener {
} else {
void client.console.info(
'guildMemberAdd',
- `[Fallback] Assigned sticky roles to <<${util.sanitizeWtlAndControl(member.user.tag)}>> in <<${
+ `[Fallback] Assigned sticky roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(
member.guild.name
- }>>.`
+ )}.`
);
}
}
@@ -103,15 +105,14 @@ export default class GuildMemberAddListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberAdd',
- `Assigned join roles to <<${util.sanitizeWtlAndControl(member.user.tag)}>> in <<${member.guild.name}>>.`
+ `Assigned join roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
)
)
- .catch(
- () =>
- void client.console.warn(
- 'guildMemberAdd',
- `Failed to assign join roles to <<${util.sanitizeWtlAndControl(member.user.tag)}>>, in <<${member.guild.name}>>.`
- )
+ .catch(() =>
+ member.guild.error(
+ 'Join Roles Error',
+ `Failed to assign join roles to ${util.format.input(member.user.tag)}, in ${util.format.input(member.guild.name)}.`
+ )
);
}
}
diff --git a/src/listeners/guild/guildMemberRemove.ts b/src/listeners/guild/guildMemberRemove.ts
index 393eea6..6181d52 100644
--- a/src/listeners/guild/guildMemberRemove.ts
+++ b/src/listeners/guild/guildMemberRemove.ts
@@ -6,7 +6,7 @@ import {
type BushClientEvents,
type PartialBushGuildMember
} from '#lib';
-import { MessageEmbed, Util } from 'discord.js';
+import { MessageEmbed } from 'discord.js';
export default class GuildMemberRemoveListener extends BushListener {
public constructor() {
@@ -33,7 +33,7 @@ export default class GuildMemberRemoveListener extends BushListener {
if (member.guild.id !== welcome?.guild.id) throw new Error('Welcome channel must be in the guild.');
const embed: MessageEmbed = new MessageEmbed()
.setDescription(
- `${util.emojis.leave} **${util.sanitizeWtlAndControl(Util.escapeBold(user.tag))}** ${
+ `${util.emojis.leave} ${util.format.input(user.tag)} ${
isBan ? 'got banned from' : 'left'
} the server. There are now ${welcome.guild.memberCount.toLocaleString()} members.`
)
@@ -43,13 +43,13 @@ export default class GuildMemberRemoveListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberRemove',
- `Sent a message for <<${util.sanitizeWtlAndControl(user.tag)}>> in <<${member.guild.name}>>.`
+ `Sent a message for ${util.format.inputLog(user.tag)} in ${util.format.inputLog(member.guild.name)}.`
)
)
.catch(() =>
- client.console.warn(
- 'guildMemberRemove',
- `Failed to send message for <<${util.sanitizeWtlAndControl(user.tag)}>> in <<${member.guild.name}>>.`
+ member.guild.error(
+ 'Welcome Message Error',
+ `Failed to send message for ${util.format.input(user.tag)} in ${util.format.input(member.guild.name)}.`
)
);
}
@@ -81,7 +81,7 @@ export default class GuildMemberRemoveListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberRemove',
- `${isNew ? 'Created' : 'Updated'} info for <<${util.sanitizeWtlAndControl(member.user.tag)}>>.`
+ `${isNew ? 'Created' : 'Updated'} info for ${util.format.inputLog(member.user.tag)}.`
)
);
}
diff --git a/src/listeners/other/promiseRejection.ts b/src/listeners/other/promiseRejection.ts
index f7ca840..699b676 100644
--- a/src/listeners/other/promiseRejection.ts
+++ b/src/listeners/other/promiseRejection.ts
@@ -6,7 +6,8 @@ export default class PromiseRejectionListener extends BushListener {
public constructor() {
super('promiseRejection', {
emitter: 'process',
- event: 'unhandledRejection'
+ event: 'unhandledRejection',
+ type: 'prependListener'
});
}
diff --git a/src/listeners/other/uncaughtException.ts b/src/listeners/other/uncaughtException.ts
index 096c1f0..34dcdd6 100644
--- a/src/listeners/other/uncaughtException.ts
+++ b/src/listeners/other/uncaughtException.ts
@@ -6,7 +6,8 @@ export default class UncaughtExceptionListener extends BushListener {
public constructor() {
super('uncaughtException', {
emitter: 'process',
- event: 'uncaughtException'
+ event: 'uncaughtException',
+ type: 'prependListener'
});
}