aboutsummaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/config/blacklist.ts4
-rw-r--r--src/commands/config/settings.ts142
-rw-r--r--src/commands/dev/superUser.ts11
-rw-r--r--src/commands/info/avatar.ts5
-rw-r--r--src/commands/leveling/leaderboard.ts0
-rw-r--r--src/commands/leveling/level.ts (renamed from src/commands/moulberry-bush/level.ts)105
-rw-r--r--src/commands/moderation/ban.ts3
-rw-r--r--src/commands/moderation/modlog.ts3
-rw-r--r--src/commands/moderation/mute.ts3
-rw-r--r--src/commands/moderation/role.ts90
-rw-r--r--src/commands/moderation/slowmode.ts5
-rw-r--r--src/commands/moulberry-bush/rule.ts2
-rw-r--r--src/commands/utilities/decode.ts3
13 files changed, 242 insertions, 134 deletions
diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts
index 57c3015..ff34567 100644
--- a/src/commands/config/blacklist.ts
+++ b/src/commands/config/blacklist.ts
@@ -68,8 +68,8 @@ export default class BlacklistCommand extends BushCommand {
const global = args.global && message.author.isOwner();
const target =
typeof args.target === 'string'
- ? (await Argument.cast('channel', client.commandHandler.resolver, message as BushMessage, args.target)) ??
- (await Argument.cast('user', client.commandHandler.resolver, message as BushMessage, args.target))
+ ? (await util.arg.cast('channel', client.commandHandler.resolver, message as BushMessage, args.target)) ??
+ (await util.arg.cast('user', client.commandHandler.resolver, message as BushMessage, args.target))
: args.target;
if (!target) return await message.util.reply(`${util.emojis.error} Choose a valid channel or user.`);
const targetID = target.id;
diff --git a/src/commands/config/settings.ts b/src/commands/config/settings.ts
index a8070e2..8a5f290 100644
--- a/src/commands/config/settings.ts
+++ b/src/commands/config/settings.ts
@@ -1,4 +1,5 @@
-import { BushCommand, BushMessage, BushSlashMessage, guildSettingsObj, settingsArr } from '@lib';
+import { BushCommand, BushMessage, BushSlashMessage, GuildSettings, guildSettingsObj, settingsArr } from '@lib';
+import { ArgumentOptions, Flag } from 'discord-akairo';
import {
Message,
MessageActionRow,
@@ -8,6 +9,7 @@ import {
MessageOptions,
MessageSelectMenu
} from 'discord.js';
+import _ from 'lodash';
export default class SettingsCommand extends BushCommand {
public constructor() {
@@ -16,13 +18,15 @@ export default class SettingsCommand extends BushCommand {
category: 'config',
description: {
content: 'Configure server options.',
- usage: 'settings',
+ usage: `settings (${settingsArr.map((s) => `\`${s}\``).join(', ')}) (${['view', 'set', 'add', 'remove'].map(
+ (s) => `\`${s}\``
+ )})`,
examples: ['settings']
},
slash: true,
slashOptions: settingsArr.map((setting) => {
return {
- name: util.camelToSnakeCase(setting),
+ name: _.snakeCase(setting),
description: `Manage the server's ${guildSettingsObj[setting].name.toLowerCase()}`,
type: 'SUB_COMMAND_GROUP',
options: guildSettingsObj[setting].type.includes('-array')
@@ -95,14 +99,122 @@ export default class SettingsCommand extends BushCommand {
});
}
- // *args(): any {}
+ // I make very readable code :)
+ *args(message: BushMessage): IterableIterator<ArgumentOptions | Flag> {
+ const setting = yield {
+ id: 'setting',
+ type: settingsArr,
+ prompt: {
+ start: `What setting would you like to see or change? You can choose one of the following: ${settingsArr
+ .map((s) => `\`${s}\``)
+ .join(', ')}`,
+ retry: `{error} Choose one of the following settings: ${settingsArr.map((s) => `\`${s}\``).join(', ')}`,
+ optional: message.util.parsed!.alias === 'settings'
+ }
+ };
+
+ const action = yield {
+ id: 'action',
+ type: guildSettingsObj[setting as unknown as GuildSettings].type.includes('-array')
+ ? ['view', 'add', 'remove']
+ : ['view', 'set'],
+ prompt: {
+ start: `Would you like to ${util.oxford(
+ (guildSettingsObj[setting as unknown as GuildSettings].type.includes('-array')
+ ? ['view', 'add', 'remove']
+ : ['view', 'set']
+ ).map((a) => `\`${a}\``),
+ 'or'
+ )} the \`${setting}\` setting?`,
+ retry: `{error} Choose one of the following actions to perform on the \`${setting}\` setting: ${util.oxford(
+ (guildSettingsObj[setting as unknown as GuildSettings].type.includes('-array')
+ ? ['view', 'add', 'remove']
+ : ['view', 'set']
+ ).map((a) => `\`${a}\``),
+ 'or'
+ )}`,
+ optional: message.util.parsed!.alias === 'settings'
+ }
+ };
- public override async exec(message: BushMessage | BushSlashMessage, args: unknown): Promise<unknown> {
- client.console.debugRaw(message.interaction);
- client.console.debugRaw(args);
+ const value =
+ action === 'view'
+ ? undefined
+ : yield {
+ id: 'value',
+ type: 'string',
+ match: 'restContent',
+ prompt: {
+ start: `What would you like to ${action} ${
+ (action as unknown as 'add' | 'remove' | 'set') === 'add'
+ ? `to the ${setting} setting`
+ : (action as unknown as 'remove' | 'set') === 'remove'
+ ? `from the ${setting} setting`
+ : `the ${setting} setting to`
+ }?`,
+ retry: `{error} You must choose a value to ${action} ${
+ (action as unknown as 'add' | 'remove' | 'set') === 'add'
+ ? `to the ${setting} setting`
+ : (action as unknown as 'remove' | 'set') === 'remove'
+ ? `from the ${setting} setting`
+ : `the ${setting} setting to`
+ }.`,
+ optional: message.util.parsed!.alias === 'settings'
+ }
+ };
+
+ return { setting, action, value };
+ }
+
+ public override async exec(
+ message: BushMessage | BushSlashMessage,
+ args: { [x in GuildSettings | ('view' | 'set' | 'add' | 'remove') | ('setting' | 'action') | 'value']: string | undefined }
+ ): Promise<unknown> {
if (!message.guild) return await message.util.reply(`${util.emojis.error} This command can only be used in servers.`);
- const messageOptions = await this.generateMessageOptions(message);
- const msg = (await message.util.reply(messageOptions)) as Message;
+ if (!message.member?.permissions.has('MANAGE_GUILD'))
+ return await message.util.reply(
+ `${util.emojis.error} You must have the **MANAGE_GUILD** permissions to run this command.`
+ );
+ const setting = _.camelCase(args[settingsArr.find((s) => args[s]) ?? 'setting']) as GuildSettings | undefined;
+ const action = (args[
+ (['view', 'set', 'add', 'remove'] as ('view' | 'set' | 'add' | 'remove')[]).find((a) => args[a]) ?? 'action'
+ ] ?? 'view') as 'view' | 'set' | 'add' | 'remove';
+ const value = args.value;
+
+ let msg;
+
+ if (!setting || action === 'view') {
+ const messageOptions = await this.generateMessageOptions(message, setting ?? undefined);
+ msg = (await message.util.reply(messageOptions)) as Message;
+ } else {
+ if (!value)
+ return await message.util.reply(
+ `${util.emojis.error} You must choose a value to ${action} ${
+ (action as unknown as 'add' | 'remove' | 'set') === 'add'
+ ? `to the ${setting} setting`
+ : (action as unknown as 'remove' | 'set') === 'remove'
+ ? `from the ${setting} setting`
+ : `the ${setting} setting to`
+ }`
+ );
+ switch (action) {
+ case 'add':
+ case 'remove': {
+ const existing = (await message.guild.getSetting(setting)) as string[];
+ const updated = util.addOrRemoveFromArray('add', existing, value);
+ await message.guild.setSetting(setting, updated);
+ const messageOptions = await this.generateMessageOptions(message);
+ msg = (await message.util.reply(messageOptions)) as Message;
+ break;
+ }
+ case 'set': {
+ await message.guild.setSetting(setting, value);
+ const messageOptions = await this.generateMessageOptions(message);
+ msg = (await message.util.reply(messageOptions)) as Message;
+ break;
+ }
+ }
+ }
const collector = msg.createMessageComponentCollector({
channel: message.channel ?? undefined,
guild: message.guild,
@@ -121,6 +233,11 @@ export default class SettingsCommand extends BushCommand {
await this.generateMessageOptions(message, interaction.values[0] as keyof typeof guildSettingsObj)
);
}
+ case 'command_settingsBack': {
+ if (!interaction.isButton()) return;
+
+ return interaction.update(await this.generateMessageOptions(message));
+ }
}
} else {
return await interaction?.deferUpdate().catch(() => undefined);
@@ -130,7 +247,7 @@ export default class SettingsCommand extends BushCommand {
public async generateMessageOptions(
message: BushMessage | BushSlashMessage,
- feature?: keyof typeof guildSettingsObj
+ feature?: undefined | keyof typeof guildSettingsObj
): Promise<MessageOptions> {
if (!message.guild) throw new Error('message.guild is null');
const settingsEmbed = new MessageEmbed().setTitle(`${message.guild!.name}'s Settings`).setColor(util.colors.default);
@@ -158,6 +275,7 @@ export default class SettingsCommand extends BushCommand {
type: 'string' | 'channel' | 'channel-array' | 'role' | 'role-array'
): Promise<string> => {
const feat = await message.guild!.getSetting(feature);
+ console.debug(feat);
switch (type.replace('-array', '') as 'string' | 'channel' | 'role') {
case 'string': {
return Array.isArray(feat)
@@ -172,6 +290,7 @@ export default class SettingsCommand extends BushCommand {
}
}
};
+
const components = new MessageActionRow().addComponents(
new MessageButton().setStyle('PRIMARY').setCustomId('command_settingsBack').setLabel('Back')
);
@@ -184,7 +303,8 @@ export default class SettingsCommand extends BushCommand {
);
settingsEmbed.addField(
guildSettingsObj[feature].name,
- await generateCurrentValue(feature as 'string' | 'channel' | 'channel-array' | 'role' | 'role-array')
+ (await generateCurrentValue(feature as 'string' | 'channel' | 'channel-array' | 'role' | 'role-array')) ||
+ '[No Value Set]'
);
return { embeds: [settingsEmbed], components: [components] };
}
diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts
index 957e2b7..1b2fd7c 100644
--- a/src/commands/dev/superUser.ts
+++ b/src/commands/dev/superUser.ts
@@ -1,4 +1,5 @@
import { BushCommand, BushMessage, BushSlashMessage, Global } from '@lib';
+import { ArgumentOptions, Flag } from 'discord-akairo';
import { User } from 'discord.js';
export default class SuperUserCommand extends BushCommand {
@@ -15,14 +16,14 @@ export default class SuperUserCommand extends BushCommand {
ownerOnly: true
});
}
- *args(): unknown {
+ *args(): IterableIterator<ArgumentOptions | Flag> {
const action = yield {
id: 'action',
type: ['add', 'remove'],
prompt: {
start: 'Would you like to `add` or `remove` a user from the superuser list?',
retry: '{error} Choose if you would like to `add` or `remove` a user.',
- required: true
+ optional: false
}
};
const user = yield {
@@ -30,9 +31,9 @@ export default class SuperUserCommand extends BushCommand {
type: 'user',
match: 'restContent',
prompt: {
- start: `Who would you like to ${action || 'add/remove'} from the superuser list?`,
- retry: `Choose a valid user to ${action || 'add/remove'} from the superuser list.`,
- required: true
+ start: `Who would you like to ${action ?? 'add/remove'} from the superuser list?`,
+ retry: `Choose a valid user to ${action ?? 'add/remove'} from the superuser list.`,
+ optional: false
}
};
return { action, user };
diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts
index 33393b8..7654d2f 100644
--- a/src/commands/info/avatar.ts
+++ b/src/commands/info/avatar.ts
@@ -1,4 +1,4 @@
-import { CommandInteraction, MessageEmbed, User } from 'discord.js';
+import { MessageEmbed, User } from 'discord.js';
import { BushCommand, BushMessage, BushSlashMessage } from '../../lib';
export default class AvatarCommand extends BushCommand {
@@ -36,9 +36,6 @@ export default class AvatarCommand extends BushCommand {
}
override async exec(message: BushMessage | BushSlashMessage, args: { user: User }): Promise<void> {
- client.console.debugRaw(args);
- client.console.debugRaw(message.interaction);
- client.console.debugRaw((message.interaction as CommandInteraction).options.getUser('user'));
const user = args.user ?? message.author;
const embed = new MessageEmbed()
diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/commands/leveling/leaderboard.ts
diff --git a/src/commands/moulberry-bush/level.ts b/src/commands/leveling/level.ts
index 02d66be..a579df0 100644
--- a/src/commands/moulberry-bush/level.ts
+++ b/src/commands/leveling/level.ts
@@ -1,17 +1,15 @@
-import { BushCommand, BushGuild, BushMessage, BushSlashMessage, BushUser, Level } from '@lib';
-/*
+import { BushCommand, BushGuild, BushMessage, BushSlashMessage, BushUser, CanvasProgressBar, Level } from '@lib';
import canvas from 'canvas';
import { MessageAttachment } from 'discord.js';
-import { join } from 'path';
import got from 'got/dist/source';
-import { CanvasProgressBar } from '@lib';
-*/
+import { join } from 'path';
+import SimplifyNumber from 'simplify-number';
export default class LevelCommand extends BushCommand {
public constructor() {
super('level', {
- aliases: ['level', 'rank'],
- category: "Moulberry's Bush",
+ aliases: ['level', 'rank', 'lvl'],
+ category: 'leveling',
description: {
content: 'Shows the level of a user',
usage: 'level [user]',
@@ -41,71 +39,62 @@ export default class LevelCommand extends BushCommand {
});
}
- /* private simplifyXP(xp: number): string {
-
- }
-
- private async getImage(user: User): Promise<Buffer> {
+ private async getImage(user: BushUser, guild: BushGuild): Promise<Buffer> {
// I added comments because this code is impossible to read
const [userLevelRow] = await Level.findOrBuild({
where: {
- id: user.id
+ user: user.id,
+ guild: guild.id
},
defaults: {
- id: user.id
+ user: user.id,
+ guild: guild.id
}
});
- const userLevel = userLevelRow.level
+ const rank = (await Level.findAll({ where: { guild: guild.id } })).sort((a, b) => b.xp - a.xp);
+ const userLevel = userLevelRow.level;
const currentLevelXP = Level.convertLevelToXp(userLevel);
const currentLevelXPProgress = userLevelRow.xp - currentLevelXP;
- const xpForNextLevel =
- Level.convertLevelToXp(userLevelRow.level + 1) - currentLevelXP;
+ const xpForNextLevel = Level.convertLevelToXp(userLevelRow.level + 1) - currentLevelXP;
+ const white = '#FFFFFF',
+ gray = '#23272A',
+ newBlurple = '#5865F2';
// Load roboto font because yes
- canvas.registerFont(
- join(__dirname, '..', '..', '..', 'Roboto-Regular.ttf'),
- {
- family: 'Roboto'
- }
- );
+ canvas.registerFont(join(__dirname, '..', '..', '..', '..', 'lib', 'assets', 'Roboto-Regular.ttf'), {
+ family: 'Roboto'
+ });
// Create image canvas
const image = canvas.createCanvas(800, 200),
ctx = image.getContext('2d');
// Fill background
- ctx.fillStyle = '#00c7eb';
+ ctx.fillStyle = gray;
ctx.fillRect(0, 0, image.width, image.height);
// Draw avatar
- const avatarBuffer = await got
- .get(user.displayAvatarURL({ format: 'png', size: 128 }))
- .buffer();
+ const avatarBuffer = await got.get(user.displayAvatarURL({ format: 'png', size: 128 })).buffer();
const avatarImage = new canvas.Image();
avatarImage.src = avatarBuffer;
- avatarImage.height = 128
- avatarImage.width = 128
- const imageTopCoord = (image.height / 2) - (avatarImage.height / 2)
+ avatarImage.height = 128;
+ avatarImage.width = 128;
+ const imageTopCoord = image.height / 2 - avatarImage.height / 2;
ctx.drawImage(avatarImage, imageTopCoord, imageTopCoord);
// Write tag of user
ctx.font = '30px Roboto';
- ctx.fillStyle = 'black';
+ ctx.fillStyle = white;
const measuredTag = ctx.measureText(user.tag);
ctx.fillText(user.tag, avatarImage.width + 70, 60);
// Draw line under tag
- ctx.fillStyle = 'yellow';
- ctx.fillRect(
- avatarImage.width + 70,
- 65 + measuredTag.actualBoundingBoxDescent,
- measuredTag.width,
- 3
- );
+ ctx.fillStyle = newBlurple;
+ ctx.fillRect(avatarImage.width + 70, 65 + measuredTag.actualBoundingBoxDescent, measuredTag.width, 3);
// Draw leveling bar
const fullProgressBar = new CanvasProgressBar(
ctx,
{
x: avatarImage.width + 70,
- y: avatarImage.height - 10,
+ y: avatarImage.height - 0,
height: 30,
width: 550
},
- '#6e6e6e',
+ white,
1
);
fullProgressBar.draw();
@@ -113,38 +102,30 @@ export default class LevelCommand extends BushCommand {
ctx,
{
x: avatarImage.width + 70,
- y: avatarImage.height - 10,
+ y: avatarImage.height - 0,
height: 30,
width: 550
},
- 'yellow',
+ newBlurple,
currentLevelXPProgress / xpForNextLevel
);
progressBar.draw();
// Draw level data text
- ctx.fillStyle = 'black'
- ctx.fillText(`Level: ${userLevel} XP: $`, avatarImage.width + 70, avatarImage.height - 20)
+ ctx.fillStyle = white;
+ ctx.fillText(
+ `Level: ${userLevel} XP: ${SimplifyNumber(currentLevelXPProgress)}/${SimplifyNumber(
+ xpForNextLevel
+ )} Rank: ${SimplifyNumber(rank.indexOf(rank.find((x) => x.user === user.id)!) + 1)}`,
+ avatarImage.width + 70,
+ avatarImage.height - 20
+ );
// Return image in buffer form
return image.toBuffer();
- } */
-
- private async getResponse(user: BushUser, guild: BushGuild): Promise<string> {
- const userLevelRow = await Level.findOne({ where: { user: user.id, guild: guild.id } });
- if (userLevelRow) {
- return `${user ? `${user.tag}'s` : 'Your'} level is ${userLevelRow.level} (${userLevelRow.xp} XP)`;
- } else {
- return `${user ? `${user.tag} does` : 'You do'} not have a level yet!`;
- }
}
- public override async exec(message: BushMessage | BushSlashMessage, { user }: { user?: BushUser }): Promise<void> {
- // await message.reply(
- // new MessageAttachment(
- // await this.getImage(user || message.author),
- // 'lel.png'
- // )
- // );
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- await message.reply(await this.getResponse(user || message.author, message.guild!));
+ public override async exec(message: BushMessage | BushSlashMessage, args: { user?: BushUser }): Promise<unknown> {
+ return await message.reply({
+ files: [new MessageAttachment(await this.getImage(args.user ?? message.author, message.guild!), 'level.png')]
+ });
}
}
diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts
index 7f1a67c..c33b39a 100644
--- a/src/commands/moderation/ban.ts
+++ b/src/commands/moderation/ban.ts
@@ -1,5 +1,4 @@
import { AllowedMentions, BushCommand, BushGuildMember, BushMessage, BushSlashMessage } from '@lib';
-import { Argument } from 'discord-akairo';
import { User } from 'discord.js';
export default class BanCommand extends BushCommand {
@@ -110,7 +109,7 @@ export default class BanCommand extends BushCommand {
if (reason) {
time =
typeof reason === 'string'
- ? await Argument.cast('duration', client.commandHandler.resolver, message as BushMessage, reason)
+ ? await util.arg.cast('duration', client.commandHandler.resolver, message as BushMessage, reason)
: reason.duration;
}
const parsedReason = reason?.contentWithoutTime ?? '';
diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts
index 04264b8..ef0a56e 100644
--- a/src/commands/moderation/modlog.ts
+++ b/src/commands/moderation/modlog.ts
@@ -42,8 +42,7 @@ export default class ModlogCommand extends BushCommand {
`**Moderator**: <@!${log.moderator}> (${log.moderator})`
];
if (log.duration) modLog.push(`**Duration**: ${util.humanizeDuration(log.duration)}`);
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- modLog.push(`**Reason**: ${log.reason || 'No Reason Specified.'}`);
+ modLog.push(`**Reason**: ${log.reason ?? 'No Reason Specified.'}`);
if (log.evidence) modLog.push(`**Evidence:** ${log.evidence}`);
return modLog.join(`\n`);
}
diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts
index 7b8689a..915302e 100644
--- a/src/commands/moderation/mute.ts
+++ b/src/commands/moderation/mute.ts
@@ -1,5 +1,4 @@
import { AllowedMentions, BushCommand, BushMessage, BushSlashMessage, BushUser } from '@lib';
-import { Argument } from 'discord-akairo';
export default class MuteCommand extends BushCommand {
public constructor() {
@@ -77,7 +76,7 @@ export default class MuteCommand extends BushCommand {
if (reason) {
time =
typeof reason === 'string'
- ? await Argument.cast('duration', client.commandHandler.resolver, message as BushMessage, reason)
+ ? await util.arg.cast('duration', client.commandHandler.resolver, message as BushMessage, reason)
: reason.duration;
}
const parsedReason = reason?.contentWithoutTime ?? '';
diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts
index 4575a11..ddaefaa 100644
--- a/src/commands/moderation/role.ts
+++ b/src/commands/moderation/role.ts
@@ -1,51 +1,16 @@
-/* eslint-disable @typescript-eslint/no-empty-function */
import { AllowedMentions, BushCommand, BushGuildMember, BushMessage, BushRole, BushSlashMessage } from '@lib';
+import { ArgumentOptions, Flag } from 'discord-akairo';
export default class RoleCommand extends BushCommand {
public constructor() {
super('role', {
- aliases: ['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']
},
- args: [
- {
- id: 'action',
- customType: [['add'], ['remove']],
- prompt: {
- start: 'Would you like to `add` or `remove` a role?',
- retry: '{error} Choose whether you would you like to `add` or `remove` a role.'
- }
- },
- {
- id: 'user',
- type: 'member',
- prompt: {
- start: `What user do you want to add/remove the role to/from?`,
- retry: `{error} Choose a valid user to add/remove the role to/from.`
- }
- },
- {
- id: 'role',
- type: 'role',
- prompt: {
- start: `What role do you want to add/remove to/from the user?`,
- retry: `{error} Choose a valid role to add/remove.`
- }
- },
- {
- id: 'duration',
- type: 'duration',
- prompt: {
- start: 'How long would you like to role to last?',
- retry: '{error} Choose a valid duration.',
- optional: true
- }
- }
- ],
slash: true,
slashOptions: [
{
@@ -90,9 +55,56 @@ export default class RoleCommand extends BushCommand {
});
}
+ *args(message: BushMessage): IterableIterator<ArgumentOptions | Flag> {
+ const action = ['rr'].includes(message.util.parsed?.alias ?? '')
+ ? 'remove'
+ : ['ar', 'ra'].includes(message.util.parsed?.alias ?? '')
+ ? 'add'
+ : yield {
+ id: 'action',
+ type: [['add'], ['remove']],
+ prompt: {
+ start: 'Would you like to `add` or `remove` a role?',
+ retry: (...arg) => {
+ console.debug(...arg);
+ return '{error} Choose whether you would you like to `add` or `remove` a role.';
+ }
+ }
+ };
+ console.debug(action);
+ const user = yield {
+ id: 'user',
+ type: 'member',
+ prompt: {
+ start: `What user do you want to ${action} the role ${action === 'add' ? 'to' : 'from'}?`,
+ retry: (...arg) => {
+ console.debug(...arg);
+ return `{error} Choose a valid user to ${action} the role ${action === 'add' ? 'to' : 'from'}.`;
+ }
+ }
+ };
+ console.debug(user);
+ const _role = yield {
+ id: 'role',
+ type: `${action === 'add' ? 'roleWithDuration' : 'role'}`,
+ match: 'rest',
+ prompt: {
+ start: `What role do you want to ${action} ${action === 'add' ? 'to' : 'from'} the user${
+ action === 'add' ? ', and for how long' : ''
+ }?`,
+ retry: (...arg) => {
+ console.debug(...arg);
+ return `{error} Choose a valid role to ${action}.`;
+ }
+ }
+ };
+ console.debug(_role);
+ return { action, user, role: (_role as any).role ?? _role, duration: (_role as any).duration };
+ }
+
public override async exec(
message: BushMessage | BushSlashMessage,
- { action, user, role, duration }: { action: 'add' | 'remove'; user: BushGuildMember; role: BushRole; duration: number }
+ { action, user, role, duration }: { action: 'add' | 'remove'; user: BushGuildMember; role: BushRole; duration?: number }
): Promise<unknown> {
if (!message.member!.permissions.has('MANAGE_ROLES')) {
const mappings = client.consts.mappings;
@@ -131,6 +143,8 @@ export default class RoleCommand extends BushCommand {
const responseMessage = () => {
switch (responseCode) {
case 'user hierarchy':
+ client.console.debug(role.position);
+ client.console.debug(user.roles.highest.position);
return `${util.emojis.error} <@&${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.`;
diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts
index 1d47616..04fe3e4 100644
--- a/src/commands/moderation/slowmode.ts
+++ b/src/commands/moderation/slowmode.ts
@@ -66,12 +66,11 @@ export default class SlowModeCommand extends BushCommand {
if (length) {
length =
typeof length === 'string' && !['off', 'none', 'disable'].includes(length)
- ? await Argument.cast('duration', client.commandHandler.resolver, message as BushMessage, length)
+ ? await util.arg.cast('duration', client.commandHandler.resolver, message as BushMessage, length)
: length;
}
- // @ts-expect-error: stop being dumb smh
- const length2: number = ['off', 'none', 'disable'].includes(length) ? 0 : length;
+ const length2: number = ['off', 'none', 'disable'].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/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts
index bf44dad..0c1e435 100644
--- a/src/commands/moulberry-bush/rule.ts
+++ b/src/commands/moulberry-bush/rule.ts
@@ -131,7 +131,7 @@ export default class RuleCommand extends BushCommand {
// If the original message was a reply -> imitate it
message.reference?.messageId && !message.util.isSlash
? await message.channel.messages.fetch(message.reference.messageId).then(async (message) => {
- await message.util!.reply({ embeds: [rulesEmbed], allowedMentions: AllowedMentions.users() });
+ await message.reply({ embeds: [rulesEmbed], allowedMentions: AllowedMentions.users() });
})
: await message.util.send({ embeds: [rulesEmbed], allowedMentions: AllowedMentions.users() })
);
diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts
index a5a4c21..e48c644 100644
--- a/src/commands/utilities/decode.ts
+++ b/src/commands/utilities/decode.ts
@@ -95,8 +95,7 @@ export default class DecodeCommand extends BushCommand {
message: BushMessage | AkairoMessage,
{ from, to, data }: { from: BufferEncoding; to: BufferEncoding; data: string }
): Promise<unknown> {
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- const encodeOrDecode = util.capitalizeFirstLetter(message?.util?.parsed?.alias || 'decoded');
+ const encodeOrDecode = util.capitalizeFirstLetter(message?.util?.parsed?.alias ?? 'decoded');
const decodedEmbed = new MessageEmbed()
.setTitle(`${encodeOrDecode} Information`)
.addField('📥 Input', await util.inspectCleanRedactCodeblock(data));