aboutsummaryrefslogtreecommitdiff
path: root/src/commands/moderation
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands/moderation')
-rw-r--r--src/commands/moderation/ban.ts44
-rw-r--r--src/commands/moderation/block.ts30
-rw-r--r--src/commands/moderation/evidence.ts5
-rw-r--r--src/commands/moderation/hideCase.ts5
-rw-r--r--src/commands/moderation/kick.ts7
-rw-r--r--src/commands/moderation/massBan.ts5
-rw-r--r--src/commands/moderation/modlog.ts9
-rw-r--r--src/commands/moderation/mute.ts25
-rw-r--r--src/commands/moderation/purge.ts9
-rw-r--r--src/commands/moderation/removeReactionEmoji.ts18
-rw-r--r--src/commands/moderation/role.ts22
-rw-r--r--src/commands/moderation/slowmode.ts40
-rw-r--r--src/commands/moderation/timeout.ts22
-rw-r--r--src/commands/moderation/unban.ts7
-rw-r--r--src/commands/moderation/unblock.ts15
-rw-r--r--src/commands/moderation/unmute.ts8
-rw-r--r--src/commands/moderation/untimeout.ts3
-rw-r--r--src/commands/moderation/warn.ts8
18 files changed, 116 insertions, 166 deletions
diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts
index 5e3350f..25102e0 100644
--- a/src/commands/moderation/ban.ts
+++ b/src/commands/moderation/ban.ts
@@ -8,7 +8,8 @@ import {
type BushSlashMessage,
type OptionalArgType
} from '#lib';
-import { ApplicationCommandOptionType, PermissionFlagsBits, type User } from 'discord.js';
+import assert from 'assert';
+import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class BanCommand extends BushCommand {
public constructor() {
@@ -71,20 +72,21 @@ export default class BanCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
args: {
user: ArgType<'user'> | ArgType<'snowflake'>;
- reason_and_duration: OptionalArgType<'contentWithDuration'>;
+ reason_and_duration: OptionalArgType<'contentWithDuration'> | string;
days: OptionalArgType<'integer'>;
force: boolean;
}
) {
- if (args.reason_and_duration && typeof args.reason_and_duration === 'object') args.reason_and_duration.duration ??= 0;
- args.days ??= 0;
+ assert(message.inGuild());
+ assert(message.member);
- if (!message.guild) return message.util.reply(`${util.emojis.error} This command cannot be used in dms.`);
- const member = message.guild!.members.cache.get((args.user as User)?.id ?? args.user);
- const user = member?.user ?? (await util.resolveNonCachedUser((args.user as User)?.id ?? args.user));
+ const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
+
+ args.days ??= message.util.parsed?.alias === 'dban' ? 1 : 0;
+ const member = message.guild.members.cache.get(typeof args.user === 'string' ? args.user : args.user.id);
+ const user = member?.user ?? (await util.resolveNonCachedUser(typeof args.user === 'string' ? args.user : args.user.id));
if (!user) return message.util.reply(`${util.emojis.error} Invalid user.`);
const useForce = args.force && message.author.isOwner();
- if (!message.member) throw new Error(`message.member is null`);
const canModerateResponse = member ? await Moderation.permissionCheck(message.member, member, 'ban', true, useForce) : true;
@@ -92,35 +94,13 @@ export default class BanCommand extends BushCommand {
return await message.util.reply(canModerateResponse);
}
- if (message.util.parsed?.alias === 'dban' && !args.days) args.days = 1;
-
if (!Number.isInteger(args.days) || args.days! < 0 || args.days! > 7) {
return message.util.reply(`${util.emojis.error} The delete days must be an integer between 0 and 7.`);
}
- let time: number | null;
- if (args.reason_and_duration) {
- time =
- typeof args.reason_and_duration === 'string'
- ? await util.arg.cast('duration', message, args.reason_and_duration)
- : args.reason_and_duration.duration;
- }
- const parsedReason = args.reason_and_duration?.contentWithoutTime ?? null;
+ const opts = { reason: content, moderator: message.member, duration: duration, deleteDays: args.days };
- const responseCode = member
- ? await member.bushBan({
- reason: parsedReason,
- moderator: message.member,
- duration: time! ?? 0,
- deleteDays: args.days
- })
- : await message.guild.bushBan({
- user,
- reason: parsedReason,
- moderator: message.member,
- duration: time! ?? 0,
- deleteDays: args.days
- });
+ const responseCode = member ? await member.bushBan(opts) : await message.guild.bushBan({ user, ...opts });
const responseMessage = (): string => {
const victim = util.format.input(user.tag);
diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts
index 20c6e86..e6f7849 100644
--- a/src/commands/moderation/block.ts
+++ b/src/commands/moderation/block.ts
@@ -2,8 +2,6 @@ import {
AllowedMentions,
blockResponse,
BushCommand,
- BushTextChannel,
- BushThreadChannel,
Moderation,
type ArgType,
type BushMessage,
@@ -67,21 +65,17 @@ export default class BlockCommand extends BushCommand {
}
) {
assert(message.inGuild());
- if (!(message.channel instanceof BushTextChannel || message.channel instanceof BushThreadChannel))
- return message.util.send(`${util.emojis.error} This command can only be used in text and thread channels.`);
+ assert(message.member);
+
+ if (!message.channel.isTextBased())
+ return message.util.send(`${util.emojis.error} This command can only be used in text based channels.`);
- const reason = args.reason_and_duration
- ? typeof args.reason_and_duration === 'string'
- ? await util.arg.cast('contentWithDuration', message, args.reason_and_duration)
- : args.reason_and_duration
- : { duration: null, contentWithoutTime: '' };
+ const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
- if (reason.duration === null) reason.duration = 0;
- const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ const member = await message.guild.members.fetch(args.user.id).catch(() => null);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
- assert(message.member);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'block', true, useForce);
@@ -89,18 +83,10 @@ export default class BlockCommand extends BushCommand {
return message.util.reply(canModerateResponse);
}
- const time = reason
- ? typeof reason === 'string'
- ? ((await util.arg.cast('duration', message, reason)) as number)
- : reason.duration
- : undefined;
-
- const parsedReason = reason?.contentWithoutTime ?? '';
-
const responseCode = await member.bushBlock({
- reason: parsedReason,
+ reason: content,
moderator: message.member,
- duration: time ?? 0,
+ duration: duration,
channel: message.channel
});
diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts
index 23ccf59..d189e89 100644
--- a/src/commands/moderation/evidence.ts
+++ b/src/commands/moderation/evidence.ts
@@ -1,4 +1,5 @@
import { BushCommand, ModLog, type BushMessage, type BushSlashMessage } from '#lib';
+import assert from 'assert';
import { ArgumentGeneratorReturn } from 'discord-akairo';
import { ArgumentTypeCasterReturn } from 'discord-akairo/dist/src/struct/commands/arguments/Argument.js';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
@@ -65,9 +66,11 @@ export default class EvidenceCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ case_id: caseID, evidence }: { case_id: string; evidence?: string }
) {
+ assert(message.inGuild());
+
const entry = await ModLog.findByPk(caseID);
if (!entry || entry.pseudo) return message.util.send(`${util.emojis.error} Invalid modlog entry.`);
- if (entry.guild !== message.guild!.id) return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
if (evidence && (message as BushMessage).attachments?.size)
return message.util.reply(`${util.emojis.error} Please either attach an image or a reason not both.`);
diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts
index a59380f..d603953 100644
--- a/src/commands/moderation/hideCase.ts
+++ b/src/commands/moderation/hideCase.ts
@@ -1,4 +1,5 @@
import { BushCommand, ModLog, type BushMessage, type BushSlashMessage } from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class HideCaseCommand extends BushCommand {
@@ -27,9 +28,11 @@ export default class HideCaseCommand extends BushCommand {
}
public override async exec(message: BushMessage | BushSlashMessage, { case_id: caseID }: { case_id: string }) {
+ assert(message.inGuild());
+
const entry = await ModLog.findByPk(caseID);
if (!entry || entry.pseudo) return message.util.send(`${util.emojis.error} Invalid entry.`);
- if (entry.guild !== message.guild!.id) return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
const action = entry.hidden ? 'no longer hidden' : 'now hidden';
const oldEntry = entry.hidden;
entry.hidden = !entry.hidden;
diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts
index 6dfb09b..26098b5 100644
--- a/src/commands/moderation/kick.ts
+++ b/src/commands/moderation/kick.ts
@@ -7,6 +7,7 @@ import {
type BushMessage,
type BushSlashMessage
} from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class KickCommand extends BushCommand {
@@ -57,11 +58,13 @@ export default class KickCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ user, reason, force }: { user: ArgType<'user'>; reason: ArgType<'string'>; force: boolean }
) {
- const member = await message.guild!.members.fetch(user.id);
+ assert(message.inGuild());
+ assert(message.member);
+
+ const member = await message.guild.members.fetch(user.id);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
- if (!message.member) throw new Error(`message.member is null`);
const useForce = force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'kick', true, useForce);
diff --git a/src/commands/moderation/massBan.ts b/src/commands/moderation/massBan.ts
index 5621011..e4aeb55 100644
--- a/src/commands/moderation/massBan.ts
+++ b/src/commands/moderation/massBan.ts
@@ -56,6 +56,9 @@ export default class MassBanCommand extends BushCommand {
args: { users: ArgType<'string'>; reason: OptionalArgType<'string'>; days: OptionalArgType<'integer'> }
) {
assert(message.inGuild());
+
+ args.days ??= message.util.parsed?.alias?.includes('dban') ? 1 : 0;
+
const ids = args.users.split(/\n| /).filter((id) => id.length > 0);
if (ids.length === 0) return message.util.send(`${util.emojis.error} You must provide at least one user id.`);
for (const id of ids) {
@@ -67,8 +70,6 @@ export default class MassBanCommand extends BushCommand {
return message.util.reply(`${util.emojis.error} The delete days must be an integer between 0 and 7.`);
}
- if (message.util.parsed?.alias?.includes('dban') && !args.days) args.days = 1;
-
const promises = ids.map((id) =>
message.guild.bushBan({
user: id,
diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts
index 443ffa3..c089d40 100644
--- a/src/commands/moderation/modlog.ts
+++ b/src/commands/moderation/modlog.ts
@@ -1,4 +1,5 @@
import { BushCommand, ButtonPaginator, ModLog, type ArgType, type BushMessage, type BushSlashMessage } from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, Embed, PermissionFlagsBits, User } from 'discord.js';
export default class ModlogCommand extends BushCommand {
@@ -30,6 +31,7 @@ export default class ModlogCommand extends BushCommand {
}
],
slash: true,
+ channel: 'guild',
clientPermissions: (m) => util.clientSendAndPermCheck(m),
userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
@@ -39,11 +41,13 @@ export default class ModlogCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ search, hidden }: { search: ArgType<'user'> | string; hidden: boolean }
) {
+ assert(message.inGuild());
+
const foundUser = search instanceof User ? search : await util.resolveUserAsync(search);
if (foundUser) {
const logs = await ModLog.findAll({
where: {
- guild: message.guild!.id,
+ guild: message.guild.id,
user: foundUser.id
},
order: [['createdAt', 'ASC']]
@@ -68,8 +72,7 @@ export default class ModlogCommand extends BushCommand {
const entry = await ModLog.findByPk(search as string);
if (!entry || entry.pseudo || (entry.hidden && !hidden))
return message.util.send(`${util.emojis.error} That modlog does not exist.`);
- if (entry.guild !== message.guild!.id)
- return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${util.emojis.error} This modlog is from another server.`);
const embed = {
title: `Case ${entry.id}`,
description: ModlogCommand.generateModlogInfo(entry, true),
diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts
index c97ceb7..e32ece2 100644
--- a/src/commands/moderation/mute.ts
+++ b/src/commands/moderation/mute.ts
@@ -64,18 +64,15 @@ export default class MuteCommand extends BushCommand {
force?: ArgType<'boolean'>;
}
) {
- const reason = args.reason_and_duration
- ? typeof args.reason_and_duration === 'string'
- ? await util.arg.cast('contentWithDuration', message, args.reason_and_duration)
- : args.reason_and_duration
- : { duration: null, contentWithoutTime: '' };
+ assert(message.inGuild());
+ assert(message.member);
+
+ const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
- if (reason.duration === null) reason.duration = 0;
- const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ const member = await message.guild.members.fetch(args.user.id).catch(() => null);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
- assert(message.member);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'mute', true, useForce);
@@ -83,18 +80,10 @@ export default class MuteCommand extends BushCommand {
return message.util.reply(canModerateResponse);
}
- const time = reason
- ? typeof reason === 'string'
- ? ((await util.arg.cast('duration', message, reason)) as number)
- : reason.duration
- : undefined;
-
- const parsedReason = reason?.contentWithoutTime ?? '';
-
const responseCode = await member.bushMute({
- reason: parsedReason,
+ reason: content,
moderator: message.member,
- duration: time ?? 0
+ duration
});
const responseMessage = (): string => {
diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts
index c882b7f..2cc9d04 100644
--- a/src/commands/moderation/purge.ts
+++ b/src/commands/moderation/purge.ts
@@ -53,8 +53,8 @@ export default class PurgeCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
args: { amount: number; bot: boolean; user: ArgType<'user'> }
) {
- assert(message.channel);
- if (!message.inGuild()) return message.util.reply(`${util.emojis.error} You cannot run this command in dms.`);
+ assert(message.inGuild());
+
if (args.amount > 100 || args.amount < 1) return message.util.reply(`${util.emojis.error} `);
const messageFilter = (filterMessage: BushMessage): boolean => {
@@ -67,13 +67,12 @@ export default class PurgeCommand extends BushCommand {
const _messages = (await message.channel.messages.fetch({ limit: 100, before: message.id }))
.filter((message) => messageFilter(message))
.first(args.amount);
- const messages = new Collection<Snowflake, BushMessage>();
- _messages.forEach((m) => messages.set(m.id, m));
+ const messages = new Collection<Snowflake, BushMessage>(_messages.map((m) => [m.id, m]));
const purged = await message.channel.bulkDelete(messages, true).catch(() => null);
if (!purged) return message.util.reply(`${util.emojis.error} Failed to purge messages.`).catch(() => null);
else {
- client.emit('bushPurge', message.author, message.guild!, message.channel, messages);
+ client.emit('bushPurge', message.author, message.guild, message.channel, messages);
await message.util.send(`${util.emojis.success} Successfully purged **${purged.size}** messages.`);
/* .then(async (purgeMessage) => {
if (!message.util.isSlashMessage(message)) {
diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts
index 092b8ac..f511007 100644
--- a/src/commands/moderation/removeReactionEmoji.ts
+++ b/src/commands/moderation/removeReactionEmoji.ts
@@ -1,6 +1,6 @@
import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib';
import assert from 'assert';
-import { ApplicationCommandOptionType, Message, PermissionFlagsBits, type Emoji } from 'discord.js';
+import { ApplicationCommandOptionType, Message, PermissionFlagsBits } from 'discord.js';
export default class RemoveReactionEmojiCommand extends BushCommand {
public constructor() {
@@ -45,23 +45,19 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
assert(message.channel);
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
+ const emojiID = typeof args.emoji === 'string' ? `${args.emoji}` : args.emoji.id;
+ const success = !!(await resolvedMessage.reactions.cache
?.get(emojiID!)
?.remove()
- ?.catch(() => {});
+ ?.catch(() => undefined));
+
if (success) {
return await message.util.reply(
- `${util.emojis.success} Removed all reactions of \`${id ? emojiID : args.emoji}\` from the message with the id of \`${
- resolvedMessage.id
- }\`.`
+ `${util.emojis.success} Removed all reactions of \`${emojiID}\` 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 : args.emoji
- }\` from the message with the id of \`${resolvedMessage.id}\`.`
+ `${util.emojis.error} There was an error removing all reactions of \`${emojiID}\` from the message with the id of \`${resolvedMessage.id}\`.`
);
}
}
diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts
index 920ef81..8580f2f 100644
--- a/src/commands/moderation/role.ts
+++ b/src/commands/moderation/role.ts
@@ -128,7 +128,7 @@ export default class RoleCommand extends BushCommand {
}
) {
if (!args.role) return await message.util.reply(`${util.emojis.error} You must specify a role.`);
- if (args.duration === null) args.duration = 0;
+ args.duration ??= 0;
if (
!message.member!.permissions.has(PermissionFlagsBits.ManageRoles) &&
message.member!.id !== message.guild?.ownerId &&
@@ -162,20 +162,12 @@ export default class RoleCommand extends BushCommand {
const shouldLog = this.punishmentRoleNames.includes(args.role.name);
- const responseCode =
- args.action === 'add'
- ? await args.member.bushAddRole({
- moderator: message.member!,
- addToModlog: shouldLog,
- role: args.role,
- duration: args.duration
- })
- : await args.member.bushRemoveRole({
- moderator: message.member!,
- addToModlog: shouldLog,
- role: args.role,
- duration: args.duration
- });
+ const responseCode = await args.member[`bush${args.action === 'add' ? 'Add' : 'Remove'}Role`]({
+ moderator: message.member!,
+ addToModlog: shouldLog,
+ role: args.role,
+ duration: args.duration
+ });
const responseMessage = (): string => {
const victim = util.format.input(args.member.user.tag);
diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts
index fb446d1..c0511f3 100644
--- a/src/commands/moderation/slowmode.ts
+++ b/src/commands/moderation/slowmode.ts
@@ -1,6 +1,7 @@
import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage } from '#lib';
+import assert from 'assert';
import { Argument } from 'discord-akairo';
-import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits, type TextChannel, type ThreadChannel } from 'discord.js';
+import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
export default class SlowmodeCommand extends BushCommand {
public constructor() {
@@ -42,38 +43,33 @@ export default class SlowmodeCommand extends BushCommand {
public override async exec(
message: BushMessage | BushSlashMessage,
- {
- length,
- channel
- }: {
+ args: {
length: ArgType<'duration'> | ArgType<'durationSeconds'> | 'off' | 'none' | 'disable' | null;
channel: ArgType<'channel'>;
}
) {
- if (message.channel!.type === ChannelType.DM)
- return await message.util.reply(`${util.emojis.error} This command cannot be run in dms.`);
- if (!channel) channel = message.channel as any;
- if (![ChannelType.GuildText, ChannelType.GuildPrivateThread, ChannelType.GuildPublicThread].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'] as const).includes(length)
- ? await util.arg.cast('duration', message, length)
- : length;
- }
+ assert(message.inGuild());
+
+ args.channel ??= message.channel;
+
+ if (!args.channel.isTextBased() || args.channel.isNews())
+ return await message.util.reply(`${util.emojis.error} <#${args.channel.id}> is not a text or thread channel.`);
- const length2: number = (['off', 'none', 'disable'] as const).includes(length as string) ? 0 : (length as number);
+ args.length =
+ typeof args.length === 'string' && !(['off', 'none', 'disable'] as const).includes(args.length)
+ ? await util.arg.cast('duration', message, args.length)
+ : args.length;
- const setSlowmode = await (channel as ThreadChannel | TextChannel)
+ const length2: number = (['off', 'none', 'disable'] as const).includes(args.length) || args.length === null ? 0 : args.length;
+
+ const setSlowmode = await args.channel
.setRateLimitPerUser(length2 / 1000, `Changed by ${message.author.tag} (${message.author.id}).`)
.catch(() => {});
if (!setSlowmode)
- return await message.util.reply(
- `${util.emojis.error} There was an error changing the slowmode of <#${(channel as ThreadChannel | TextChannel).id}>.`
- );
+ return await message.util.reply(`${util.emojis.error} There was an error changing the slowmode of <#${args.channel.id}>.`);
else
return await message.util.reply(
- `${util.emojis.success} Successfully changed the slowmode of <#${channel.id}> ${
+ `${util.emojis.success} Successfully changed the slowmode of <#${args.channel.id}> ${
length2 ? `to \`${util.humanizeDuration(length2)}` : '`off'
}\`.`
);
diff --git a/src/commands/moderation/timeout.ts b/src/commands/moderation/timeout.ts
index 32fcf76..b8fb78f 100644
--- a/src/commands/moderation/timeout.ts
+++ b/src/commands/moderation/timeout.ts
@@ -58,19 +58,16 @@ export default class TimeoutCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
args: { user: ArgType<'user'>; reason_and_duration: ArgType<'contentWithDuration'> | string; force?: ArgType<'boolean'> }
) {
- const reason = args.reason_and_duration
- ? typeof args.reason_and_duration === 'string'
- ? await util.arg.cast('contentWithDuration', message, args.reason_and_duration)
- : args.reason_and_duration
- : { duration: null, contentWithoutTime: '' };
+ assert(message.inGuild());
+ assert(message.member);
+
+ const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
- if (reason.duration === null || reason.duration < 1)
- return await message.util.reply(`${util.emojis.error} You must specify a duration for timeouts.`);
- const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ if (!duration) return await message.util.reply(`${util.emojis.error} You must specify a duration for timeouts.`);
+ const member = await message.guild.members.fetch(args.user.id).catch(() => null);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
- assert(message.member);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'timeout', true, useForce);
@@ -78,13 +75,10 @@ export default class TimeoutCommand extends BushCommand {
return message.util.reply(canModerateResponse);
}
- const time = reason.duration;
- const parsedReason = reason.contentWithoutTime ?? '';
-
const responseCode = await member.bushTimeout({
- reason: parsedReason,
+ reason: content,
moderator: message.member,
- duration: time
+ duration: duration
});
const responseMessage = (): string => {
diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts
index 7bdb32e..a6afc0a 100644
--- a/src/commands/moderation/unban.ts
+++ b/src/commands/moderation/unban.ts
@@ -7,6 +7,7 @@ import {
type BushSlashMessage,
type OptionalArgType
} from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class UnbanCommand extends BushCommand {
@@ -21,7 +22,7 @@ export default class UnbanCommand extends BushCommand {
{
id: 'user',
description: 'The user to unban.',
- type: 'globalUser',
+ type: util.arg.compose('user', 'globalUser'),
prompt: 'What user would you like to unban?',
retry: '{error} Choose a valid user to unban.',
slashType: ApplicationCommandOptionType.User
@@ -48,7 +49,9 @@ export default class UnbanCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ user, reason }: { user: ArgType<'user'>; reason: OptionalArgType<'string'> }
) {
- const responseCode = await message.guild!.bushUnban({
+ assert(message.inGuild());
+
+ const responseCode = await message.guild.bushUnban({
user,
moderator: message.author,
reason
diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts
index 7d36e15..34b2075 100644
--- a/src/commands/moderation/unblock.ts
+++ b/src/commands/moderation/unblock.ts
@@ -1,8 +1,6 @@
import {
AllowedMentions,
BushCommand,
- BushTextChannel,
- BushThreadChannel,
Moderation,
unblockResponse,
type ArgType,
@@ -63,14 +61,15 @@ export default class UnblockCommand extends BushCommand {
args: { user: ArgType<'user'>; reason: OptionalArgType<'string'>; force?: ArgType<'boolean'> }
) {
assert(message.inGuild());
- if (!(message.channel instanceof BushTextChannel || message.channel instanceof BushThreadChannel))
- return message.util.send(`${util.emojis.error} This command can only be used in text and thread channels.`);
+ assert(message.member);
+
+ if (!message.channel.isTextBased())
+ return message.util.send(`${util.emojis.error} This command can only be used in text based channels.`);
- const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ const member = await message.guild.members.fetch(args.user.id).catch(() => null);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
- assert(message.member);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'unblock', true, useForce);
@@ -78,10 +77,8 @@ export default class UnblockCommand extends BushCommand {
return message.util.reply(canModerateResponse);
}
- const parsedReason = args.reason ?? '';
-
const responseCode = await member.bushUnblock({
- reason: parsedReason,
+ reason: args.reason ?? '',
moderator: message.member,
channel: message.channel
});
diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts
index fb4bb55..de16cb5 100644
--- a/src/commands/moderation/unmute.ts
+++ b/src/commands/moderation/unmute.ts
@@ -9,6 +9,7 @@ import {
type BushSlashMessage,
type OptionalArgType
} from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class UnmuteCommand extends BushCommand {
@@ -60,10 +61,11 @@ export default class UnmuteCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ user, reason, force = false }: { user: ArgType<'user'>; reason: OptionalArgType<'string'>; force?: boolean }
) {
- const error = util.emojis.error;
- const member = message.guild!.members.cache.get(user.id) as BushGuildMember;
+ assert(message.inGuild());
+ assert(message.member);
- if (!message.member) throw new Error(`message.member is null`);
+ const error = util.emojis.error;
+ const member = message.guild.members.cache.get(user.id) as BushGuildMember;
const useForce = force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'unmute', true, useForce);
diff --git a/src/commands/moderation/untimeout.ts b/src/commands/moderation/untimeout.ts
index 6d3632d..636b178 100644
--- a/src/commands/moderation/untimeout.ts
+++ b/src/commands/moderation/untimeout.ts
@@ -60,9 +60,10 @@ export default class UntimeoutCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
args: { user: ArgType<'user'>; reason: OptionalArgType<'string'>; force?: ArgType<'boolean'> }
) {
+ assert(message.inGuild());
assert(message.member);
- const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ const member = await message.guild.members.fetch(args.user.id).catch(() => null);
if (!member)
return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts
index 27d04b3..3ab4b0b 100644
--- a/src/commands/moderation/warn.ts
+++ b/src/commands/moderation/warn.ts
@@ -4,11 +4,11 @@ import {
Moderation,
warnResponse,
type ArgType,
- type BushGuildMember,
type BushMessage,
type BushSlashMessage,
type OptionalArgType
} from '#lib';
+import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class WarnCommand extends BushCommand {
@@ -59,10 +59,12 @@ export default class WarnCommand extends BushCommand {
message: BushMessage | BushSlashMessage,
{ user, reason, force = false }: { user: ArgType<'user'>; reason: OptionalArgType<'string'>; force?: boolean }
) {
- const member = message.guild!.members.cache.get(user.id) as BushGuildMember;
+ assert(message.inGuild());
+ assert(message.member);
+
+ const member = message.guild.members.cache.get(user.id);
if (!member) return message.util.reply(`${util.emojis.error} I cannot warn users that are not in the server.`);
const useForce = force && message.author.isOwner();
- if (!message.member) throw new Error(`message.member is null`);
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'warn', true, useForce);
if (canModerateResponse !== true) {