aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--config/Config.ts (renamed from src/lib/utils/Config.ts)0
-rw-r--r--config/example-options.ts (renamed from src/config/example-options.ts)2
-rw-r--r--package.json3
-rw-r--r--src/arguments/contentWithDuration.ts4
-rw-r--r--src/arguments/discordEmoji.ts4
-rw-r--r--src/arguments/duration.ts4
-rw-r--r--src/arguments/durationSeconds.ts4
-rw-r--r--src/arguments/messageLink.ts4
-rw-r--r--src/arguments/roleWithDuration.ts6
-rw-r--r--src/arguments/snowflake.ts4
-rw-r--r--src/bot.ts3
-rw-r--r--src/commands/admin/channelPermissions.ts22
-rw-r--r--src/commands/admin/roleAll.ts22
-rw-r--r--src/commands/config/_customAutomodPhrases.ts2
-rw-r--r--src/commands/config/blacklist.ts41
-rw-r--r--src/commands/config/config.ts29
-rw-r--r--src/commands/config/disable.ts39
-rw-r--r--src/commands/config/features.ts10
-rw-r--r--src/commands/config/log.ts20
-rw-r--r--src/commands/dev/__template.ts14
-rw-r--r--src/commands/dev/debug.ts6
-rw-r--r--src/commands/dev/dm.ts8
-rw-r--r--src/commands/dev/eval.ts24
-rw-r--r--src/commands/dev/javascript.ts27
-rw-r--r--src/commands/dev/reload.ts22
-rw-r--r--src/commands/dev/say.ts17
-rw-r--r--src/commands/dev/servers.ts19
-rw-r--r--src/commands/dev/sh.ts42
-rw-r--r--src/commands/dev/superUser.ts30
-rw-r--r--src/commands/dev/syncAutomod.ts8
-rw-r--r--src/commands/dev/test.ts29
-rw-r--r--src/commands/fun/coinFlip.ts4
-rw-r--r--src/commands/fun/dice.ts4
-rw-r--r--src/commands/fun/eightBall.ts4
-rw-r--r--src/commands/fun/minesweeper.ts18
-rw-r--r--src/commands/info/avatar.ts8
-rw-r--r--src/commands/info/botInfo.ts23
-rw-r--r--src/commands/info/color.ts22
-rw-r--r--src/commands/info/guildInfo.ts50
-rw-r--r--src/commands/info/help.ts27
-rw-r--r--src/commands/info/icon.ts10
-rw-r--r--src/commands/info/links.ts6
-rw-r--r--src/commands/info/ping.ts10
-rw-r--r--src/commands/info/pronouns.ts26
-rw-r--r--src/commands/info/snowflake.ts49
-rw-r--r--src/commands/info/userInfo.ts81
-rw-r--r--src/commands/leveling/leaderboard.ts21
-rw-r--r--src/commands/leveling/level.ts11
-rw-r--r--src/commands/leveling/levelRoles.ts33
-rw-r--r--src/commands/leveling/setLevel.ts20
-rw-r--r--src/commands/leveling/setXp.ts24
-rw-r--r--src/commands/moderation/_activePunishments.ts6
-rw-r--r--src/commands/moderation/ban.ts35
-rw-r--r--src/commands/moderation/block.ts33
-rw-r--r--src/commands/moderation/evidence.ts34
-rw-r--r--src/commands/moderation/hideCase.ts21
-rw-r--r--src/commands/moderation/kick.ts21
-rw-r--r--src/commands/moderation/lockdown.ts31
-rw-r--r--src/commands/moderation/massBan.ts23
-rw-r--r--src/commands/moderation/massEvidence.ts29
-rw-r--r--src/commands/moderation/modlog.ts46
-rw-r--r--src/commands/moderation/mute.ts38
-rw-r--r--src/commands/moderation/purge.ts23
-rw-r--r--src/commands/moderation/removeReactionEmoji.ts27
-rw-r--r--src/commands/moderation/role.ts36
-rw-r--r--src/commands/moderation/slowmode.ts27
-rw-r--r--src/commands/moderation/timeout.ts28
-rw-r--r--src/commands/moderation/unban.ts21
-rw-r--r--src/commands/moderation/unblock.ts30
-rw-r--r--src/commands/moderation/unlockdown.ts14
-rw-r--r--src/commands/moderation/unmute.ts27
-rw-r--r--src/commands/moderation/untimeout.ts23
-rw-r--r--src/commands/moderation/warn.ts21
-rw-r--r--src/commands/moulberry-bush/capePermissions.ts31
-rw-r--r--src/commands/moulberry-bush/capes.ts17
-rw-r--r--src/commands/moulberry-bush/giveawayPing.ts6
-rw-r--r--src/commands/moulberry-bush/moulHammer.ts6
-rw-r--r--src/commands/moulberry-bush/report.ts39
-rw-r--r--src/commands/moulberry-bush/rule.ts14
-rw-r--r--src/commands/moulberry-bush/serverStatus.ts18
-rw-r--r--src/commands/utilities/_poll.ts10
-rw-r--r--src/commands/utilities/activity.ts26
-rw-r--r--src/commands/utilities/calculator.ts29
-rw-r--r--src/commands/utilities/decode.ts26
-rw-r--r--src/commands/utilities/hash.ts4
-rw-r--r--src/commands/utilities/highlight-!.ts4
-rw-r--r--src/commands/utilities/highlight-add.ts14
-rw-r--r--src/commands/utilities/highlight-block.ts26
-rw-r--r--src/commands/utilities/highlight-clear.ts8
-rw-r--r--src/commands/utilities/highlight-matches.ts12
-rw-r--r--src/commands/utilities/highlight-remove.ts8
-rw-r--r--src/commands/utilities/highlight-show.ts6
-rw-r--r--src/commands/utilities/highlight-unblock.ts21
-rw-r--r--src/commands/utilities/price.ts18
-rw-r--r--src/commands/utilities/remind.ts31
-rw-r--r--src/commands/utilities/reminders.ts23
-rw-r--r--src/commands/utilities/steal.ts33
-rw-r--r--src/commands/utilities/suicide.ts6
-rw-r--r--src/commands/utilities/uuid.ts22
-rw-r--r--src/commands/utilities/viewRaw.ts28
-rw-r--r--src/commands/utilities/whoHasRole.ts27
-rw-r--r--src/commands/utilities/wolframAlpha.ts33
-rw-r--r--src/context-menu-commands/user/modlog.ts6
-rw-r--r--src/context-menu-commands/user/userInfo.ts3
-rw-r--r--src/inhibitors/blacklist/channelGlobalBlacklist.ts2
-rw-r--r--src/inhibitors/blacklist/channelGuildBlacklist.ts2
-rw-r--r--src/inhibitors/blacklist/guildBlacklist.ts2
-rw-r--r--src/inhibitors/blacklist/userGlobalBlacklist.ts2
-rw-r--r--src/inhibitors/blacklist/userGuildBlacklist.ts2
-rw-r--r--src/inhibitors/checks/fatal.ts2
-rw-r--r--src/inhibitors/checks/guildUnavailable.ts2
-rw-r--r--src/inhibitors/command/dm.ts2
-rw-r--r--src/inhibitors/command/globalDisabledCommand.ts2
-rw-r--r--src/inhibitors/command/guild.ts2
-rw-r--r--src/inhibitors/command/guildDisabledCommand.ts2
-rw-r--r--src/inhibitors/command/nsfw.ts2
-rw-r--r--src/inhibitors/command/owner.ts2
-rw-r--r--src/inhibitors/command/restrictedChannel.ts2
-rw-r--r--src/inhibitors/command/restrictedGuild.ts2
-rw-r--r--src/inhibitors/command/superUser.ts2
-rw-r--r--src/lib/common/AutoMod.ts51
-rw-r--r--src/lib/common/ButtonPaginator.ts47
-rw-r--r--src/lib/common/ConfirmationPrompt.ts27
-rw-r--r--src/lib/common/DeleteButton.ts27
-rw-r--r--src/lib/common/HighlightManager.ts16
-rw-r--r--src/lib/common/Sentry.ts2
-rw-r--r--src/lib/common/util/Arg.ts269
-rw-r--r--src/lib/common/util/Format.ts187
-rw-r--r--src/lib/common/util/Moderation.ts517
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts52
-rw-r--r--src/lib/extensions/discord-akairo/BushClientUtil.ts1187
-rw-r--r--src/lib/extensions/discord-akairo/BushInhibitor.ts8
-rw-r--r--src/lib/extensions/discord-akairo/BushListener.ts15
-rw-r--r--src/lib/extensions/discord-akairo/BushTask.ts2
-rw-r--r--src/lib/extensions/discord.js/ExtendedGuild.ts33
-rw-r--r--src/lib/extensions/discord.js/ExtendedGuildMember.ts26
-rw-r--r--src/lib/extensions/global.ts7
-rw-r--r--src/lib/index.ts19
-rw-r--r--src/lib/utils/BushConstants.ts813
-rw-r--r--src/lib/utils/BushLogger.ts256
-rw-r--r--src/lib/utils/BushUtils.ts1058
-rw-r--r--src/listeners/bush/appealListener.ts10
-rw-r--r--src/listeners/bush/joinAutoBan.ts16
-rw-r--r--src/listeners/bush/supportThread.ts6
-rw-r--r--src/listeners/bush/userUpdateAutoBan.ts16
-rw-r--r--src/listeners/client/akairoDebug.ts2
-rw-r--r--src/listeners/client/dcjsDebug.ts2
-rw-r--r--src/listeners/client/dcjsError.ts2
-rw-r--r--src/listeners/client/dcjsWarn.ts2
-rw-r--r--src/listeners/client/ready.ts2
-rw-r--r--src/listeners/commands/commandBlocked.ts73
-rw-r--r--src/listeners/commands/commandCooldown.ts2
-rw-r--r--src/listeners/commands/commandError.ts38
-rw-r--r--src/listeners/commands/commandLocked.ts6
-rw-r--r--src/listeners/commands/commandMissingPermissions.ts16
-rw-r--r--src/listeners/commands/commandStarted.ts2
-rw-r--r--src/listeners/commands/messageBlocked.ts2
-rw-r--r--src/listeners/commands/slashBlocked.ts2
-rw-r--r--src/listeners/commands/slashCommandError.ts2
-rw-r--r--src/listeners/commands/slashMissingPermissions.ts2
-rw-r--r--src/listeners/commands/slashNotFound.ts2
-rw-r--r--src/listeners/commands/slashStarted.ts2
-rw-r--r--src/listeners/contextCommands/contextCommandBlocked.ts14
-rw-r--r--src/listeners/contextCommands/contextCommandError.ts16
-rw-r--r--src/listeners/contextCommands/contextCommandNotFound.ts2
-rw-r--r--src/listeners/contextCommands/contextCommandStarted.ts2
-rw-r--r--src/listeners/guild-custom/bushLockdown.ts8
-rw-r--r--src/listeners/guild-custom/bushUnlockdown.ts8
-rw-r--r--src/listeners/guild/guildCreate.ts10
-rw-r--r--src/listeners/guild/guildDelete.ts10
-rw-r--r--src/listeners/guild/guildMemberAdd.ts12
-rw-r--r--src/listeners/guild/guildMemberRemove.ts16
-rw-r--r--src/listeners/guild/joinRoles.ts18
-rw-r--r--src/listeners/guild/syncUnbanPunishmentModel.ts2
-rw-r--r--src/listeners/interaction/interactionCreate.ts18
-rw-r--r--src/listeners/member-custom/bushBan.ts8
-rw-r--r--src/listeners/member-custom/bushBlock.ts10
-rw-r--r--src/listeners/member-custom/bushKick.ts6
-rw-r--r--src/listeners/member-custom/bushLevelUpdate.ts6
-rw-r--r--src/listeners/member-custom/bushMute.ts8
-rw-r--r--src/listeners/member-custom/bushPunishRole.ts8
-rw-r--r--src/listeners/member-custom/bushPunishRoleRemove.ts6
-rw-r--r--src/listeners/member-custom/bushPurge.ts10
-rw-r--r--src/listeners/member-custom/bushRemoveTimeout.ts6
-rw-r--r--src/listeners/member-custom/bushTimeout.ts10
-rw-r--r--src/listeners/member-custom/bushUnban.ts6
-rw-r--r--src/listeners/member-custom/bushUnblock.ts6
-rw-r--r--src/listeners/member-custom/bushUnmute.ts6
-rw-r--r--src/listeners/member-custom/bushUpdateModlog.ts10
-rw-r--r--src/listeners/member-custom/bushUpdateSettings.ts10
-rw-r--r--src/listeners/member-custom/bushWarn.ts6
-rw-r--r--src/listeners/member-custom/massBan.ts11
-rw-r--r--src/listeners/member-custom/massEvidence.ts8
-rw-r--r--src/listeners/message/autoPublisher.ts2
-rw-r--r--src/listeners/message/automodCreate.ts2
-rw-r--r--src/listeners/message/automodUpdate.ts2
-rw-r--r--src/listeners/message/blacklistedFile.ts2
-rw-r--r--src/listeners/message/boosterMessage.ts2
-rw-r--r--src/listeners/message/directMessage.ts10
-rw-r--r--src/listeners/message/highlight.ts2
-rw-r--r--src/listeners/message/level.ts6
-rw-r--r--src/listeners/message/quoteCreate.ts6
-rw-r--r--src/listeners/message/quoteEdit.ts2
-rw-r--r--src/listeners/message/verbose.ts2
-rw-r--r--src/listeners/other/consoleListener.ts3
-rw-r--r--src/listeners/other/exit.ts2
-rw-r--r--src/listeners/other/promiseRejection.ts10
-rw-r--r--src/listeners/other/uncaughtException.ts6
-rw-r--r--src/listeners/other/warning.ts8
-rw-r--r--src/listeners/rest/rateLimit.ts2
-rw-r--r--src/listeners/track-manual-punishments/modlogSyncBan.ts12
-rw-r--r--src/listeners/track-manual-punishments/modlogSyncKick.ts12
-rw-r--r--src/listeners/track-manual-punishments/modlogSyncTimeout.ts12
-rw-r--r--src/listeners/track-manual-punishments/modlogSyncUnban.ts12
-rw-r--r--src/listeners/ws/INTERACTION_CREATE.ts16
-rw-r--r--src/tasks/cpuUsage.ts8
-rw-r--r--src/tasks/handleReminders.ts8
-rw-r--r--src/tasks/removeExpiredPunishements.ts6
-rw-r--r--src/tasks/updateCache.ts4
-rw-r--r--src/tasks/updateHighlightCache.ts2
-rw-r--r--src/tasks/updatePriceItemCache.ts2
-rw-r--r--src/tasks/updateStats.ts2
-rw-r--r--tsconfig.json11
-rw-r--r--yarn.lock478
225 files changed, 4325 insertions, 3534 deletions
diff --git a/.gitignore b/.gitignore
index e3672cb..2efc3c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,5 +27,6 @@ dist
# Options and credentials for the bot
src/config/options.ts
+config/options.ts
src/lib/badlinks-secret.ts
diff --git a/src/lib/utils/Config.ts b/config/Config.ts
index ce5ec06..ce5ec06 100644
--- a/src/lib/utils/Config.ts
+++ b/config/Config.ts
diff --git a/src/config/example-options.ts b/config/example-options.ts
index 1b384c4..024b043 100644
--- a/src/config/example-options.ts
+++ b/config/example-options.ts
@@ -1,4 +1,4 @@
-import { Config } from '#lib';
+import { Config } from './Config.js';
export default new Config({
credentials: {
diff --git a/package.json b/package.json
index ea08576..dad7620 100644
--- a/package.json
+++ b/package.json
@@ -113,7 +113,8 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-deprecation": "^1.3.2",
"eslint-plugin-import": "^2.26.0",
- "node-fetch": "^3.2.6"
+ "node-fetch": "^3.2.6",
+ "vitest": "^0.14.2"
},
"packageManager": "yarn@3.2.1"
}
diff --git a/src/arguments/contentWithDuration.ts b/src/arguments/contentWithDuration.ts
index e92997a..0efba39 100644
--- a/src/arguments/contentWithDuration.ts
+++ b/src/arguments/contentWithDuration.ts
@@ -1,5 +1,5 @@
-import type { BushArgumentTypeCaster, ParsedDuration } from '#lib';
+import { parseDuration, type BushArgumentTypeCaster, type ParsedDuration } from '#lib';
export const contentWithDuration: BushArgumentTypeCaster<Promise<ParsedDuration>> = async (_, phrase) => {
- return client.util.parseDuration(phrase);
+ return parseDuration(phrase);
};
diff --git a/src/arguments/discordEmoji.ts b/src/arguments/discordEmoji.ts
index 57710e4..92d6502 100644
--- a/src/arguments/discordEmoji.ts
+++ b/src/arguments/discordEmoji.ts
@@ -1,9 +1,9 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { regex, type BushArgumentTypeCaster } from '#lib';
import type { Snowflake } from 'discord.js';
export const discordEmoji: BushArgumentTypeCaster<DiscordEmojiInfo | null> = (_, phrase) => {
if (!phrase) return null;
- const validEmoji: RegExpExecArray | null = client.consts.regex.discordEmoji.exec(phrase);
+ const validEmoji: RegExpExecArray | null = regex.discordEmoji.exec(phrase);
if (!validEmoji || !validEmoji.groups) return null;
return { name: validEmoji.groups.name, id: validEmoji.groups.id };
};
diff --git a/src/arguments/duration.ts b/src/arguments/duration.ts
index ffd9159..09dd3d5 100644
--- a/src/arguments/duration.ts
+++ b/src/arguments/duration.ts
@@ -1,5 +1,5 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { parseDuration, type BushArgumentTypeCaster } from '#lib';
export const duration: BushArgumentTypeCaster<number | null> = (_, phrase) => {
- return client.util.parseDuration(phrase).duration;
+ return parseDuration(phrase).duration;
};
diff --git a/src/arguments/durationSeconds.ts b/src/arguments/durationSeconds.ts
index 432fd8c..d8d6749 100644
--- a/src/arguments/durationSeconds.ts
+++ b/src/arguments/durationSeconds.ts
@@ -1,6 +1,6 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { parseDuration, type BushArgumentTypeCaster } from '#lib';
export const durationSeconds: BushArgumentTypeCaster<number | null> = (_, phrase) => {
phrase += 's';
- return client.util.parseDuration(phrase).duration;
+ return parseDuration(phrase).duration;
};
diff --git a/src/arguments/messageLink.ts b/src/arguments/messageLink.ts
index 457410e..a473485 100644
--- a/src/arguments/messageLink.ts
+++ b/src/arguments/messageLink.ts
@@ -1,8 +1,8 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { BushArgumentTypeCaster, regex } from '#lib';
import type { Message } from 'discord.js';
export const messageLink: BushArgumentTypeCaster<Promise<Message | null>> = async (_, phrase) => {
- const match = new RegExp(client.consts.regex.messageLink).exec(phrase);
+ const match = new RegExp(regex.messageLink).exec(phrase);
if (!match || !match.groups) return null;
const { guild_id, channel_id, message_id } = match.groups;
diff --git a/src/arguments/roleWithDuration.ts b/src/arguments/roleWithDuration.ts
index e338b79..b97f205 100644
--- a/src/arguments/roleWithDuration.ts
+++ b/src/arguments/roleWithDuration.ts
@@ -1,12 +1,12 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { Arg, BushArgumentTypeCaster, parseDuration } from '#lib';
import type { Role } from 'discord.js';
export const roleWithDuration: BushArgumentTypeCaster<Promise<RoleWithDuration | null>> = async (message, phrase) => {
// eslint-disable-next-line prefer-const
- let { duration, content } = client.util.parseDuration(phrase);
+ let { duration, content } = parseDuration(phrase);
if (content === null || content === undefined) return null;
content = content.trim();
- const role = await util.arg.cast('role', message, content);
+ const role = await Arg.cast('role', message, content);
if (!role) return null;
return { duration, role };
};
diff --git a/src/arguments/snowflake.ts b/src/arguments/snowflake.ts
index dc83909..b98a20f 100644
--- a/src/arguments/snowflake.ts
+++ b/src/arguments/snowflake.ts
@@ -1,8 +1,8 @@
-import type { BushArgumentTypeCaster } from '#lib';
+import { BushArgumentTypeCaster, regex } from '#lib';
import type { Snowflake } from 'discord.js';
export const snowflake: BushArgumentTypeCaster<Snowflake | null> = (_, phrase) => {
if (!phrase) return null;
- if (client.consts.regex.snowflake.test(phrase)) return phrase;
+ if (regex.snowflake.test(phrase)) return phrase;
return null;
};
diff --git a/src/bot.ts b/src/bot.ts
index 752075b..ed0a33f 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -5,7 +5,7 @@ init();
const { dirname } = await import('path');
const { fileURLToPath } = await import('url');
-const { default: config } = await import('./config/options.js');
+const { default: config } = await import('../config/options.js');
const { Sentry } = await import('./lib/common/Sentry.js');
const { BushClient } = await import('./lib/index.js');
@@ -14,7 +14,6 @@ if (!isDry) new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd())
BushClient.extendStructures();
const client = new BushClient(config);
global.client = client;
-global.util = client.util;
if (!isDry) await client.dbPreInit();
await client.init();
if (isDry) {
diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts
index f6240a5..12245a9 100644
--- a/src/commands/admin/channelPermissions.ts
+++ b/src/commands/admin/channelPermissions.ts
@@ -1,4 +1,14 @@
-import { BushCommand, ButtonPaginator, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ ButtonPaginator,
+ clientSendAndPermCheck,
+ emojis,
+ formatError,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
@@ -15,7 +25,7 @@ export default class ChannelPermissionsCommand extends BushCommand {
{
id: 'target',
description: 'The user/role to change the permissions of.',
- type: util.arg.union('member', 'role'),
+ type: 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.',
@@ -48,7 +58,7 @@ export default class ChannelPermissionsCommand extends BushCommand {
]
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
userPermissions: [PermissionFlagsBits.Administrator],
channel: 'guild',
slash: true,
@@ -64,9 +74,9 @@ export default class ChannelPermissionsCommand extends BushCommand {
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
const permission = message.util.isSlashMessage(message)
- ? await util.arg.cast('permission', message, args.permission)
+ ? await Arg.cast('permission', message, args.permission)
: args.permission;
- if (!permission) return await message.util.reply(`${util.emojis.error} Invalid permission.`);
+ if (!permission) return await message.util.reply(`${emojis.error} Invalid permission.`);
const failedChannels = [];
for (const [, channel] of message.guild.channels.cache) {
try {
@@ -79,7 +89,7 @@ export default class ChannelPermissionsCommand extends BushCommand {
{ reason: 'Changing overwrites for mass channel perms command' }
);
} catch (e) {
- void client.console.error('channelPermissions', util.formatError(e, false));
+ void client.console.error('channelPermissions', formatError(e, false));
failedChannels.push(channel);
}
}
diff --git a/src/commands/admin/roleAll.ts b/src/commands/admin/roleAll.ts
index 80952cc..c731f08 100644
--- a/src/commands/admin/roleAll.ts
+++ b/src/commands/admin/roleAll.ts
@@ -1,4 +1,12 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
@@ -32,7 +40,7 @@ export default class RoleAllCommand extends BushCommand {
}
],
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
userPermissions: [PermissionFlagsBits.Administrator],
typing: true,
slash: true,
@@ -43,11 +51,11 @@ export default class RoleAllCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage, args: { role: ArgType<'role'>; bots: ArgType<'flag'> }) {
assert(message.inGuild());
if (!message.member!.permissions.has(PermissionFlagsBits.Administrator) && !message.member!.user.isOwner())
- return await message.util.reply(`${util.emojis.error} You must have admin perms to use this command.`);
+ return await message.util.reply(`${emojis.error} You must have admin perms to use this command.`);
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
if (args.role.comparePositionTo(message.guild.members.me!.roles.highest) >= 0 && !args.role) {
- return await message.util.reply(`${util.emojis.error} I cannot assign a role higher or equal to my highest role.`);
+ return await message.util.reply(`${emojis.error} I cannot assign a role higher or equal to my highest role.`);
}
let members = await message.guild.members.fetch();
@@ -62,7 +70,7 @@ export default class RoleAllCommand extends BushCommand {
return true;
});
- await message.util.reply(`${util.emojis.loading} adding roles to ${members.size} members`);
+ await message.util.reply(`${emojis.loading} adding roles to ${members.size} members`);
const promises = members.map((member: GuildMember) => {
return member.roles.add(args.role, `RoleAll Command - triggered by ${message.author.tag} (${message.author.id})`);
@@ -72,7 +80,7 @@ export default class RoleAllCommand extends BushCommand {
if (!failed.length) {
await message.util.sendNew({
- content: `${util.emojis.success} Finished adding <@&${args.role.id}> to **${members.size}** member${
+ content: `${emojis.success} Finished adding <@&${args.role.id}> to **${members.size}** member${
members.size > 1 ? 's' : ''
}.`,
allowedMentions: AllowedMentions.none()
@@ -80,7 +88,7 @@ export default class RoleAllCommand extends BushCommand {
} else {
const array = [...members.values()];
await message.util.sendNew({
- content: `${util.emojis.warn} Finished adding <@&${args.role.id}> to **${members.size - failed.length}** member${
+ content: `${emojis.warn} Finished adding <@&${args.role.id}> to **${members.size - failed.length}** member${
members.size - failed.length > 1 ? 's' : ''
}! Failed members:\n${failed.map((_, index) => `<@${array[index].id}>`).join(' ')}`,
allowedMentions: AllowedMentions.none()
diff --git a/src/commands/config/_customAutomodPhrases.ts b/src/commands/config/_customAutomodPhrases.ts
index 13887ae..d60688c 100644
--- a/src/commands/config/_customAutomodPhrases.ts
+++ b/src/commands/config/_customAutomodPhrases.ts
@@ -30,7 +30,7 @@
// ],
// slash: true,
// channel: 'guild',
-// clientPermissions: (m) => util.clientSendAndPermCheck(m),
+// clientPermissions: (m) => clientSendAndPermCheck(m),
// userPermissions: [PermissionFlagsBits.ManageGuild]
// });
// }
diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts
index de457c0..80acd0b 100644
--- a/src/commands/config/blacklist.ts
+++ b/src/commands/config/blacklist.ts
@@ -1,4 +1,17 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ addOrRemoveFromArray,
+ AllowedMentions,
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ getGlobal,
+ setGlobal,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, GuildMember, PermissionFlagsBits, User } from 'discord.js';
@@ -23,7 +36,7 @@ export default class BlacklistCommand extends BushCommand {
{
id: 'target',
description: 'The channel/user to blacklist.',
- type: util.arg.union('channel', 'user'),
+ type: Arg.union('channel', 'user'),
readableType: 'channel|user',
prompt: 'What channel or user that you would like to blacklist/unblacklist?',
retry: '{error} Pick a valid user or channel.',
@@ -41,7 +54,7 @@ export default class BlacklistCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.ManageGuild]
});
}
@@ -59,26 +72,26 @@ export default class BlacklistCommand extends BushCommand {
const global = args.global && message.author.isOwner();
const target =
typeof args.target === 'string'
- ? (await util.arg.cast('textChannel', message, args.target)) ?? (await util.arg.cast('user', message, args.target))
+ ? (await Arg.cast('textChannel', message, args.target)) ?? (await Arg.cast('user', message, args.target))
: args.target;
- if (!target) return await message.util.reply(`${util.emojis.error} Choose a valid channel or user.`);
+ if (!target) return await message.util.reply(`${emojis.error} Choose a valid channel or user.`);
const targetID = target.id;
if (!message.inGuild() && !global)
- return await message.util.reply(`${util.emojis.error} You have to be in a guild to disable commands.`);
+ return await message.util.reply(`${emojis.error} You have to be in a guild to disable commands.`);
if (!global) assert(message.inGuild());
const blacklistedUsers = global
- ? util.getGlobal('blacklistedUsers')
+ ? getGlobal('blacklistedUsers')
: (await message.guild!.getSetting('blacklistedChannels')) ?? [];
const blacklistedChannels = global
- ? util.getGlobal('blacklistedChannels')
+ ? getGlobal('blacklistedChannels')
: (await message.guild!.getSetting('blacklistedUsers')) ?? [];
if (action === 'toggle') {
action = blacklistedUsers.includes(targetID) || blacklistedChannels.includes(targetID) ? 'unblacklist' : 'blacklist';
}
- const newValue = util.addOrRemoveFromArray(
+ const newValue = addOrRemoveFromArray(
action === 'blacklist' ? 'add' : 'remove',
target instanceof User ? blacklistedUsers : blacklistedChannels,
targetID
@@ -87,22 +100,22 @@ export default class BlacklistCommand extends BushCommand {
const key = target instanceof User ? 'blacklistedUsers' : 'blacklistedChannels';
const success = await (global
- ? util.setGlobal(key, newValue)
+ ? setGlobal(key, newValue)
: message.guild!.setSetting(key, newValue, message.member as GuildMember)
).catch(() => false);
if (!success)
return await message.util.reply({
- content: `${util.emojis.error} There was an error${global ? ' globally' : ''} ${action}ing ${util.format.input(
+ content: `${emojis.error} There was an error${global ? ' globally' : ''} ${action}ing ${format.input(
target instanceof User ? target.tag : target.name
)}.`,
allowedMentions: AllowedMentions.none()
});
else
return await message.util.reply({
- content: `${util.emojis.success} Successfully ${action}ed ${util.format.input(
- target instanceof User ? target.tag : target.name
- )}${global ? ' globally' : ''}.`,
+ content: `${emojis.success} Successfully ${action}ed ${format.input(target instanceof User ? target.tag : target.name)}${
+ global ? ' globally' : ''
+ }.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts
index 689a3af..f0db467 100644
--- a/src/commands/config/config.ts
+++ b/src/commands/config/config.ts
@@ -1,7 +1,14 @@
import {
+ addOrRemoveFromArray,
BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
GuildNoArraySetting,
guildSettingsObj,
+ inspectAndRedact,
+ oxford,
+ prefix,
settingsArr,
type ArgType,
type CommandMessage,
@@ -145,7 +152,7 @@ export default class ConfigCommand extends BushCommand {
};
}),
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.ManageGuild]
});
}
@@ -171,11 +178,11 @@ export default class ConfigCommand extends BushCommand {
id: 'action',
type: actionType,
prompt: {
- start: `Would you like to ${util.oxford(
+ start: `Would you like to ${oxford(
actionType!.map((a) => `\`${a}\``),
'or'
)} the \`${setting}\` setting?`,
- retry: `{error} Choose one of the following actions to perform on the ${setting} setting: ${util.oxford(
+ retry: `{error} Choose one of the following actions to perform on the ${setting} setting: ${oxford(
actionType!.map((a) => `\`${a}\``),
'or'
)}`,
@@ -219,7 +226,7 @@ export default class ConfigCommand extends BushCommand {
assert(message.member);
if (!message.member.permissions.has(PermissionFlagsBits.ManageGuild) && !message.member?.user.isOwner())
- return await message.util.reply(`${util.emojis.error} You must have the **Manage Server** permission to run this command.`);
+ return await message.util.reply(`${emojis.error} You must have the **Manage Server** permission to run this command.`);
const setting = message.util.isSlash ? (camelCase(args.subcommandGroup)! as GuildSettings) : args.setting!;
const action = message.util.isSlash ? args.subcommand! : args.action!;
const value = args.value;
@@ -238,15 +245,13 @@ export default class ConfigCommand extends BushCommand {
};
if (!value && !(['clear', 'delete'] as const).includes(action))
- return await message.util.reply(
- `${util.emojis.error} You must choose a value to ${action} ${this.grammar(action, setting)}`
- );
+ return await message.util.reply(`${emojis.error} You must choose a value to ${action} ${this.grammar(action, setting)}`);
switch (action) {
case 'add':
case 'remove': {
const existing = (await message.guild.getSetting(setting)) as string[];
- const updated = util.addOrRemoveFromArray(action, existing, parseVal(value));
+ const updated = addOrRemoveFromArray(action, existing, parseVal(value));
await message.guild.setSetting(setting, updated, message.member);
const messageOptions = await this.generateMessageOptions(message, setting);
msg = (await message.util.reply(messageOptions)) as Message;
@@ -311,7 +316,7 @@ export default class ConfigCommand extends BushCommand {
): Promise<MessageOptions & InteractionUpdateOptions> {
assert(message.inGuild());
- const settingsEmbed = new EmbedBuilder().setColor(util.colors.default);
+ const settingsEmbed = new EmbedBuilder().setColor(colors.default);
if (!setting) {
settingsEmbed.setTitle(`${message.guild.name}'s Settings`);
const desc = settingsArr.map((s) => `:wrench: **${guildSettingsObj[s].name}**`).join('\n');
@@ -341,7 +346,7 @@ export default class ConfigCommand extends BushCommand {
const func = ((): ((v: string | any) => string) => {
switch (type.replace('-array', '') as BaseSettingTypes) {
case 'string':
- return (v) => util.inspectAndRedact(v);
+ return (v) => inspectAndRedact(v);
case 'channel':
return (v) => `<#${v}>`;
case 'role':
@@ -349,7 +354,7 @@ export default class ConfigCommand extends BushCommand {
case 'user':
return (v) => `<@${v}>`;
case 'custom':
- return util.inspectAndRedact;
+ return inspectAndRedact;
default:
return (v) => v;
}
@@ -372,7 +377,7 @@ export default class ConfigCommand extends BushCommand {
);
settingsEmbed.setFooter({
- text: `Run "${util.prefix(message)}${message.util.parsed?.alias ?? 'config'} ${
+ text: `Run "${prefix(message)}${message.util.parsed?.alias ?? 'config'} ${
message.util.isSlash ? snakeCase(setting) : setting
} ${guildSettingsObj[setting].type.includes('-array') ? 'add/remove' : 'set'} <value>" to set this setting.`
});
diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts
index 373b5f6..4f52b7c 100644
--- a/src/commands/config/disable.ts
+++ b/src/commands/config/disable.ts
@@ -1,4 +1,16 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ addOrRemoveFromArray,
+ AllowedMentions,
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ getGlobal,
+ setGlobal,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, AutocompleteInteraction, PermissionFlagsBits } from 'discord.js';
import Fuse from 'fuse.js';
@@ -28,7 +40,7 @@ export default class DisableCommand extends BushCommand {
{
id: 'command',
description: 'The command to disable/enable.',
- type: util.arg.union('commandAlias', 'command'),
+ type: Arg.union('commandAlias', 'command'),
readableType: 'command|commandAlias',
prompt: 'What command would you like to enable/disable?',
retry: '{error} Pick a valid command.',
@@ -48,7 +60,7 @@ export default class DisableCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.ManageGuild]
});
}
@@ -62,23 +74,23 @@ export default class DisableCommand extends BushCommand {
let action = (args.action ?? message.util?.parsed?.alias ?? 'toggle') as 'disable' | 'enable' | 'toggle';
const global = args.global && message.author.isOwner();
const commandID =
- args.command instanceof BushCommand ? args.command.id : (await util.arg.cast('commandAlias', message, args.command))?.id;
+ args.command instanceof BushCommand ? args.command.id : (await Arg.cast('commandAlias', message, args.command))?.id;
- if (!commandID) return await message.util.reply(`${util.emojis.error} Invalid command.`);
+ if (!commandID) return await message.util.reply(`${emojis.error} Invalid command.`);
if (DisableCommand.blacklistedCommands.includes(commandID))
- return message.util.send(`${util.emojis.error} the ${commandID} command cannot be disabled.`);
+ return message.util.send(`${emojis.error} the ${commandID} command cannot be disabled.`);
- const disabledCommands = global ? util.getGlobal('disabledCommands') : await message.guild.getSetting('disabledCommands');
+ const disabledCommands = global ? getGlobal('disabledCommands') : await message.guild.getSetting('disabledCommands');
if (action === 'toggle') action = disabledCommands.includes(commandID) ? 'disable' : 'enable';
- const newValue = util.addOrRemoveFromArray(action === 'disable' ? 'add' : 'remove', disabledCommands, commandID);
+ const newValue = addOrRemoveFromArray(action === 'disable' ? 'add' : 'remove', disabledCommands, commandID);
const success = global
- ? await util.setGlobal('disabledCommands', newValue).catch(() => false)
+ ? await 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(
+ content: `${emojis.error} There was an error${global ? ' globally' : ''} **${action.substring(
0,
action.length - 2
)}ing** the **${commandID}** command.`,
@@ -86,10 +98,9 @@ export default class DisableCommand extends BushCommand {
});
else
return await message.util.reply({
- content: `${util.emojis.success} Successfully **${action.substring(
- 0,
- action.length - 2
- )}ed** the **${commandID}** command${global ? ' globally' : ''}.`,
+ content: `${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 95ae544..e88f4b7 100644
--- a/src/commands/config/features.ts
+++ b/src/commands/config/features.ts
@@ -1,5 +1,8 @@
import {
BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
guildFeaturesArr,
guildFeaturesObj,
type CommandMessage,
@@ -27,7 +30,7 @@ export default class FeaturesCommand extends BushCommand {
examples: ['features'],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [PermissionFlagsBits.ManageGuild]
});
}
@@ -35,7 +38,7 @@ export default class FeaturesCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage) {
assert(message.inGuild());
- const featureEmbed = new EmbedBuilder().setTitle(`${message.guild.name}'s Features`).setColor(util.colors.default);
+ const featureEmbed = new EmbedBuilder().setTitle(`${message.guild.name}'s Features`).setColor(colors.default);
const enabledFeatures = await message.guild.getSetting('enabledFeatures');
this.generateDescription(guildFeaturesArr, enabledFeatures, featureEmbed);
@@ -76,8 +79,7 @@ export default class FeaturesCommand extends BushCommand {
embed.setDescription(
allFeatures
.map(
- (feature) =>
- `${currentFeatures.includes(feature) ? util.emojis.check : util.emojis.cross} **${guildFeaturesObj[feature].name}**`
+ (feature) => `${currentFeatures.includes(feature) ? emojis.check : emojis.cross} **${guildFeaturesObj[feature].name}**`
)
.join('\n')
);
diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts
index 7c76bdf..3726105 100644
--- a/src/commands/config/log.ts
+++ b/src/commands/config/log.ts
@@ -1,4 +1,14 @@
-import { BushCommand, guildLogsArr, type ArgType, type CommandMessage, type GuildLogType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ guildLogsArr,
+ oxford,
+ type ArgType,
+ type CommandMessage,
+ type GuildLogType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ArgumentGeneratorReturn } from 'discord-akairo';
import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
@@ -38,7 +48,7 @@ export default class LogCommand extends BushCommand {
}
],
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.ManageGuild]
});
}
@@ -49,7 +59,7 @@ export default class LogCommand extends BushCommand {
type: guildLogsArr,
prompt: {
start: 'What log type would you like to change?',
- retry: `{error} Choose either ${util.oxford(
+ retry: `{error} Choose either ${oxford(
guildLogsArr.map((l) => `\`${l}\``),
'or'
)}`,
@@ -87,8 +97,8 @@ export default class LogCommand extends BushCommand {
return await message.util.reply(
`${
success
- ? `${util.emojis.success} Successfully ${oldChannel ? 'changed' : 'set'}`
- : `${util.emojis.error} Unable to ${oldChannel ? 'change' : 'set'}`
+ ? `${emojis.success} Successfully ${oldChannel ? 'changed' : 'set'}`
+ : `${emojis.error} Unable to ${oldChannel ? 'change' : 'set'}`
} ${
oldChannel ? `the **${args.log_type}** log channel from <#${oldChannel}>` : `the **${args.log_type}** log channel`
} to ${args.channel ? `<#${args.channel.id}>` : '`disabled`'}`
diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts
index 7bcce32..df4d146 100644
--- a/src/commands/dev/__template.ts
+++ b/src/commands/dev/__template.ts
@@ -1,4 +1,12 @@
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class TemplateCommand extends BushCommand {
@@ -33,7 +41,7 @@ export default class TemplateCommand extends BushCommand {
ownerOnly: true,
channel: 'guild',
hidden: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -42,7 +50,7 @@ export default class TemplateCommand extends BushCommand {
message: CommandMessage | SlashMessage,
args: { required_argument: ArgType<'string'>; optional_argument: OptArgType<'string'> }
) {
- return await message.util.reply(`${util.emojis.error} Do not use the template command.`);
+ return await message.util.reply(`${emojis.error} Do not use the template command.`);
args;
}
}
diff --git a/src/commands/dev/debug.ts b/src/commands/dev/debug.ts
index 682a93d..dd9109c 100644
--- a/src/commands/dev/debug.ts
+++ b/src/commands/dev/debug.ts
@@ -1,4 +1,4 @@
-// import { BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+// import { BushCommand, clientSendAndPermCheck, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
// import { ApplicationCommandOptionType, AutocompleteInteraction, ChatInputCommandInteraction } from 'discord.js';
// import Fuse from 'fuse.js';
@@ -24,7 +24,7 @@
// slash: true,
// slashGuilds: ['516977525906341928'],
// superUserOnly: true,
-// clientPermissions: (m) => util.clientSendAndPermCheck(m),
+// clientPermissions: (m) => clientSendAndPermCheck(m),
// userPermissions: []
// });
// }
@@ -52,7 +52,7 @@
// embeds: [{ description: 'And an embed' }]
// });
// } else {
-// return await message.util.reply(`${util.emojis.error} Invalid action.`);
+// return await message.util.reply(`${emojis.error} Invalid action.`);
// }
// }
diff --git a/src/commands/dev/dm.ts b/src/commands/dev/dm.ts
index 468fb20..f1e2bce 100644
--- a/src/commands/dev/dm.ts
+++ b/src/commands/dev/dm.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class DMCommand extends BushCommand {
@@ -31,7 +31,7 @@ export default class DMCommand extends BushCommand {
slash: false,
ownerOnly: true,
hidden: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -43,8 +43,8 @@ export default class DMCommand extends BushCommand {
try {
await client.users.send(args.user.id, 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(`${emojis.error} There was an error sending ${format.input(args.user.tag)} a dm.`);
}
- return message.util.reply(`${util.emojis.success} Successfully sent ${util.format.input(args.user.tag)} a dm.`);
+ return message.util.reply(`${emojis.success} Successfully sent ${format.input(args.user.tag)} a dm.`);
}
}
diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts
index b8ee9e4..239a06a 100644
--- a/src/commands/dev/eval.ts
+++ b/src/commands/dev/eval.ts
@@ -1,11 +1,17 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
ActivePunishment,
+ assertAll,
BushCommand,
BushInspectOptions,
+ clientSendAndPermCheck,
CodeBlockLang,
+ colors,
+ emojis,
+ getMethods,
Global,
Guild,
+ inspectCleanRedactCodeblock,
Level,
ModLog,
Shared,
@@ -40,8 +46,7 @@ import {
PermissionFlagsBits,
PermissionsBitField,
ReactionCollector,
- SelectMenuComponent,
- Util
+ SelectMenuComponent
} from 'discord.js';
import got from 'got';
import path from 'path';
@@ -49,15 +54,13 @@ import ts from 'typescript';
import { fileURLToPath } from 'url';
import { promisify } from 'util';
const { transpile } = ts,
- emojis = util.emojis,
- colors = util.colors,
sh = promisify(exec),
SnowflakeUtil = new Snowflake_(1420070400000n),
__dirname = path.dirname(fileURLToPath(import.meta.url));
/* eslint-enable @typescript-eslint/no-unused-vars */
// prettier-ignore
-util.assertAll(ActivePunishment, BushCommand, Global, Guild, Level, ModLog, Shared, StickyRole, Snowflake_, Canvas, exec, ActionRow, ButtonComponent, ButtonInteraction, Collection, Collector, CommandInteraction, ContextMenuCommandInteraction, DMChannel, Embed, Emoji, Interaction, InteractionCollector, Message, Attachment, MessageCollector, OAuth2Scopes, PermissionFlagsBits, PermissionsBitField, ReactionCollector, SelectMenuComponent, Util, path, ts, fileURLToPath, promisify, assert, got, transpile, emojis, colors, sh, SnowflakeUtil, __dirname);
+assertAll(ActivePunishment, BushCommand, Global, Guild, Level, ModLog, Shared, StickyRole, Snowflake_, Canvas, exec, ActionRow, ButtonComponent, ButtonInteraction, Collection, Collector, CommandInteraction, ContextMenuCommandInteraction, DMChannel, Embed, Emoji, Interaction, InteractionCollector, Message, Attachment, MessageCollector, OAuth2Scopes, PermissionFlagsBits, PermissionsBitField, ReactionCollector, SelectMenuComponent, path, ts, fileURLToPath, promisify, assert, got, transpile, sh, SnowflakeUtil, __dirname);
export default class EvalCommand extends BushCommand {
public constructor() {
@@ -174,7 +177,7 @@ export default class EvalCommand extends BushCommand {
],
slash: true,
ownerOnly: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -207,12 +210,11 @@ export default class EvalCommand extends BushCommand {
no_inspect_strings: ArgType<'flag'>;
}
) {
- if (!message.author.isOwner())
- return await message.util.reply(`${util.emojis.error} Only my developers can run this command.`);
+ if (!message.author.isOwner()) return await message.util.reply(`${emojis.error} Only my developers can run this command.`);
if (message.util.isSlashMessage(message)) await message.interaction.deferReply({ ephemeral: silent });
if (!sudo && ['delete', 'destroy'].some((p) => argCode.includes(p))) {
- return await message.util.send(`${util.emojis.error} This eval was blocked by smooth brain protection™.`);
+ return await message.util.send(`${emojis.error} This eval was blocked by smooth brain protection™.`);
}
const isTypescript = typescript || argCode.includes('```ts');
@@ -308,12 +310,12 @@ export default class EvalCommand extends BushCommand {
private async codeblock(obj: any, language: CodeBlockLang, options: CodeBlockCustomOptions = {}) {
if (options.prototype) obj = Object.getPrototypeOf(obj);
- if (options.methods) obj = util.getMethods(obj);
+ if (options.methods) obj = getMethods(obj);
options.depth ??= 1;
options.getters ??= true;
- return util.inspectCleanRedactCodeblock(obj, language, options);
+ return inspectCleanRedactCodeblock(obj, language, options);
}
}
diff --git a/src/commands/dev/javascript.ts b/src/commands/dev/javascript.ts
index fd1894b..7c47f2f 100644
--- a/src/commands/dev/javascript.ts
+++ b/src/commands/dev/javascript.ts
@@ -1,4 +1,14 @@
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ inspectCleanRedactCodeblock,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
import { VM } from 'vm2';
@@ -35,7 +45,7 @@ export default class JavascriptCommand extends BushCommand {
],
slash: true,
superUserOnly: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -44,36 +54,35 @@ export default class JavascriptCommand extends BushCommand {
message: CommandMessage | SlashMessage,
args: { code: ArgType<'string'>; sel_depth: OptArgType<'integer'> }
) {
- if (!message.author.isSuperUser())
- return await message.util.reply(`${util.emojis.error} Only super users can run this command.`);
+ if (!message.author.isSuperUser()) return await message.util.reply(`${emojis.error} Only super users can run this command.`);
if (message.util.isSlashMessage(message)) {
await message.interaction.deferReply({ ephemeral: false });
}
const code = args.code.replace(/[“”]/g, '"').replace(/```*(?:js)?/g, '');
const embed = new EmbedBuilder();
- const input = await util.inspectCleanRedactCodeblock(code, 'js');
+ const input = await inspectCleanRedactCodeblock(code, 'js');
try {
const rawOutput = /^(9\s*?\+\s*?10)|(10\s*?\+\s*?9)$/.test(code)
? '21'
: new VM({ eval: true, wasm: true, timeout: 1_000, fixAsync: true }).run(`${code}`);
- const output = await util.inspectCleanRedactCodeblock(rawOutput, 'js', {
+ const output = await inspectCleanRedactCodeblock(rawOutput, 'js', {
depth: args.sel_depth ?? 0,
getters: true,
inspectStrings: true,
colors: false
});
- embed.setTitle(`${util.emojis.successFull} Successfully Evaluated Expression`).setColor(util.colors.success);
+ embed.setTitle(`${emojis.successFull} Successfully Evaluated Expression`).setColor(colors.success);
embed.addFields([
{ name: '📥 Input', value: input },
{ name: '📤 Output', value: output }
]);
} catch (e) {
- embed.setTitle(`${util.emojis.errorFull} Unable to Evaluate Expression`).setColor(util.colors.error);
+ embed.setTitle(`${emojis.errorFull} Unable to Evaluate Expression`).setColor(colors.error);
embed.addFields([
{ name: '📥 Input', value: input },
- { name: '📤 Error', value: await util.inspectCleanRedactCodeblock(e, 'js', { colors: false }) }
+ { name: '📤 Error', value: await inspectCleanRedactCodeblock(e, 'js', { colors: false }) }
]);
}
diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts
index 96c395f..8c2000f 100644
--- a/src/commands/dev/reload.ts
+++ b/src/commands/dev/reload.ts
@@ -1,4 +1,13 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ codeblock,
+ emojis,
+ formatError,
+ shell,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
export default class ReloadCommand extends BushCommand {
public constructor() {
@@ -22,19 +31,18 @@ export default class ReloadCommand extends BushCommand {
ownerOnly: true,
typing: true,
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
public override async exec(message: CommandMessage | SlashMessage /* args: { fast: ArgType<'flag'> } */) {
- if (!message.author.isOwner())
- return await message.util.reply(`${util.emojis.error} Only my developers can run this command.`);
+ if (!message.author.isOwner()) return await message.util.reply(`${emojis.error} Only my developers can run this command.`);
let output: { stdout: string; stderr: string };
try {
const s = new Date();
- output = await util.shell(`yarn build:${/* args.fast ? 'esbuild' : */ 'tsc'}`);
+ output = await shell(`yarn build:${/* args.fast ? 'esbuild' : */ 'tsc'}`);
await Promise.all([
client.commandHandler.reloadAll(),
client.listenerHandler.reloadAll(),
@@ -46,9 +54,7 @@ export default class ReloadCommand extends BushCommand {
return message.util.send(`🔁 Successfully reloaded! (${new Date().getTime() - s.getTime()}ms)`);
} catch (e) {
if (output!) void client.logger.error('reloadCommand', output);
- return message.util.send(
- `An error occurred while reloading:\n${await util.codeblock(util.formatError(e), 2048 - 34, 'js', true)}`
- );
+ return message.util.send(`An error occurred while reloading:\n${await codeblock(formatError(e), 2048 - 34, 'js', true)}`);
}
}
}
diff --git a/src/commands/dev/say.ts b/src/commands/dev/say.ts
index a452126..6ec52a1 100644
--- a/src/commands/dev/say.ts
+++ b/src/commands/dev/say.ts
@@ -1,4 +1,12 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class SayCommand extends BushCommand {
@@ -21,15 +29,14 @@ export default class SayCommand extends BushCommand {
}
],
ownerOnly: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
slash: true
});
}
public override async exec(message: CommandMessage | SlashMessage, args: { content: ArgType<'string'> }) {
- if (!message.author.isOwner())
- return await message.util.reply(`${util.emojis.error} Only my developers can run this command.`);
+ if (!message.author.isOwner()) return await message.util.reply(`${emojis.error} Only my developers can run this command.`);
await message.delete().catch(() => null);
await message.util.send({ content: args.content, allowedMentions: AllowedMentions.none() }).catch(() => null);
@@ -38,7 +45,7 @@ export default class SayCommand extends BushCommand {
public override async execSlash(message: SlashMessage, args: { content: string }) {
if (!client.config.owners.includes(message.author.id)) {
return await message.interaction.reply({
- content: `${util.emojis.error} Only my developers can run this command.`,
+ content: `${emojis.error} Only my developers can run this command.`,
ephemeral: true
});
}
diff --git a/src/commands/dev/servers.ts b/src/commands/dev/servers.ts
index e99bcda..28a4e5d 100644
--- a/src/commands/dev/servers.ts
+++ b/src/commands/dev/servers.ts
@@ -1,4 +1,13 @@
-import { BushCommand, ButtonPaginator, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ ButtonPaginator,
+ chunk,
+ clientSendAndPermCheck,
+ colors,
+ format,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { stripIndent } from '#tags';
import { type APIEmbed, type Guild } from 'discord.js';
@@ -10,7 +19,7 @@ export default class ServersCommand extends BushCommand {
description: 'Displays all the severs the bot is in',
usage: ['servers'],
examples: ['servers'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
ownerOnly: true
});
@@ -18,13 +27,13 @@ export default class ServersCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage) {
const guilds = [...client.guilds.cache.sort((a, b) => (a.memberCount < b.memberCount ? 1 : -1)).values()];
- const chunkedGuilds: Guild[][] = util.chunk(guilds, 10);
+ const chunkedGuilds: Guild[][] = chunk(guilds, 10);
const embeds: APIEmbed[] = chunkedGuilds.map((chunk) => {
return {
title: `Server List [\`${guilds.length.toLocaleString()}\`]`,
- color: util.colors.default,
+ color: colors.default,
fields: chunk.map((guild) => ({
- name: util.format.input(guild.name),
+ name: format.input(guild.name),
value: stripIndent`
**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 8c62f5d..f7c17bd 100644
--- a/src/commands/dev/sh.ts
+++ b/src/commands/dev/sh.ts
@@ -1,8 +1,18 @@
-import { ArgType, BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ ArgType,
+ BushCommand,
+ clientSendAndPermCheck,
+ codeblock,
+ colors,
+ emojis,
+ formatError,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import chalk from 'chalk';
import { exec } from 'child_process';
-import { ApplicationCommandOptionType, EmbedBuilder, Util } from 'discord.js';
+import { ApplicationCommandOptionType, cleanCodeBlockContent, EmbedBuilder } from 'discord.js';
import { promisify } from 'util';
assert(chalk);
@@ -11,7 +21,7 @@ const sh = promisify(exec);
const clean = (text: string | any) => {
chalk.toString;
if (typeof text === 'string') {
- return (text = Util.cleanCodeBlockContent(text));
+ return (text = cleanCodeBlockContent(text));
} else return text;
};
@@ -35,24 +45,24 @@ export default class ShCommand extends BushCommand {
}
],
ownerOnly: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
public override async exec(message: CommandMessage | SlashMessage, args: { command: ArgType<'string'> }) {
if (!client.config.owners.includes(message.author.id))
- return await message.util.reply(`${util.emojis.error} Only my developers can run this command.`);
+ return await message.util.reply(`${emojis.error} Only my developers can run this command.`);
const input = clean(args.command);
const embed = new EmbedBuilder()
- .setColor(util.colors.gray)
+ .setColor(colors.gray)
.setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined })
.setTimestamp()
.setTitle('Shell Command')
.addFields([
- { name: '📥 Input', value: await util.codeblock(input, 1024, 'sh', true) },
- { name: 'Running', value: util.emojis.loading }
+ { name: '📥 Input', value: await codeblock(input, 1024, 'sh', true) },
+ { name: 'Running', value: emojis.loading }
]);
await message.util.reply({ embeds: [embed] });
@@ -69,20 +79,14 @@ export default class ShCommand extends BushCommand {
const stdout = /* strip( */ clean(output.stdout); /* ) */
const stderr = /* strip( */ clean(output.stderr); /* ) */
- embed
- .setTitle(`${util.emojis.successFull} Executed command successfully.`)
- .setColor(util.colors.success)
- .spliceFields(1, 1);
+ embed.setTitle(`${emojis.successFull} Executed command successfully.`).setColor(colors.success).spliceFields(1, 1);
- if (stdout) embed.addFields([{ name: '📤 stdout', value: await util.codeblock(stdout, 1024, 'ansi', true) }]);
- if (stderr) embed.addFields([{ name: '📤 stderr', value: await util.codeblock(stderr, 1024, 'ansi', true) }]);
+ if (stdout) embed.addFields([{ name: '📤 stdout', value: await codeblock(stdout, 1024, 'ansi', true) }]);
+ if (stderr) embed.addFields([{ name: '📤 stderr', value: await codeblock(stderr, 1024, 'ansi', true) }]);
} catch (e) {
- embed
- .setTitle(`${util.emojis.errorFull} An error occurred while executing.`)
- .setColor(util.colors.error)
- .spliceFields(1, 1);
+ embed.setTitle(`${emojis.errorFull} An error occurred while executing.`).setColor(colors.error).spliceFields(1, 1);
- embed.addFields([{ name: '📤 Output', value: await util.codeblock(util.formatError(e, true), 1024, 'ansi', true) }]);
+ embed.addFields([{ name: '📤 Output', value: await codeblock(formatError(e, true), 1024, 'ansi', true) }]);
}
await message.util.edit({ embeds: [embed] });
}
diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts
index 6a2b745..3de04bf 100644
--- a/src/commands/dev/superUser.ts
+++ b/src/commands/dev/superUser.ts
@@ -1,4 +1,13 @@
-import { BushCommand, type ArgType, type CommandMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ getShared,
+ insertOrRemoveFromShared,
+ type ArgType,
+ type CommandMessage
+} from '#lib';
import { type ArgumentGeneratorReturn, type ArgumentTypeCasterReturn } from 'discord-akairo';
export default class SuperUserCommand extends BushCommand {
@@ -9,7 +18,7 @@ export default class SuperUserCommand extends BushCommand {
description: 'A command to manage superusers.',
usage: ['superuser <add/remove> <user>'],
examples: ['superuser add IRONM00N'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
ownerOnly: true,
helpArgs: [
@@ -54,29 +63,28 @@ export default class SuperUserCommand extends BushCommand {
}
public override async exec(message: CommandMessage, args: { action: 'add' | 'remove'; user: ArgType<'user'> }) {
- if (!message.author.isOwner())
- return await message.util.reply(`${util.emojis.error} Only my developers can run this command.`);
+ if (!message.author.isOwner()) return await message.util.reply(`${emojis.error} Only my developers can run this command.`);
- const superUsers: string[] = util.getShared('superUsers');
+ const superUsers: string[] = getShared('superUsers');
if (args.action === 'add' ? superUsers.includes(args.user.id) : !superUsers.includes(args.user.id))
return message.util.reply(
- `${util.emojis.warn} ${util.format.input(args.user.tag)} is ${args.action === 'add' ? 'already' : 'not'} a superuser.`
+ `${emojis.warn} ${format.input(args.user.tag)} is ${args.action === 'add' ? 'already' : 'not'} a superuser.`
);
- const success = await util.insertOrRemoveFromShared(args.action, 'superUsers', args.user.id).catch(() => false);
+ const success = await insertOrRemoveFromShared(args.action, 'superUsers', args.user.id).catch(() => false);
if (success) {
return await message.util.reply(
- `${util.emojis.success} ${args.action == 'remove' ? '' : 'made'} ${util.format.input(args.user.tag)} ${
+ `${emojis.success} ${args.action == 'remove' ? '' : 'made'} ${format.input(args.user.tag)} ${
args.action == 'remove' ? 'is no longer ' : ''
}a superuser.`
);
} else {
return await message.util.reply(
- `${util.emojis.error} There was an error ${args.action == 'remove' ? `removing` : 'making'} ${util.format.input(
- args.user.tag
- )} ${args.action == 'remove' ? `from` : 'to'} the superuser list.`
+ `${emojis.error} There was an error ${args.action == 'remove' ? `removing` : 'making'} ${format.input(args.user.tag)} ${
+ args.action == 'remove' ? `from` : 'to'
+ } the superuser list.`
);
}
}
diff --git a/src/commands/dev/syncAutomod.ts b/src/commands/dev/syncAutomod.ts
index 9954e70..c78e6c0 100644
--- a/src/commands/dev/syncAutomod.ts
+++ b/src/commands/dev/syncAutomod.ts
@@ -1,4 +1,4 @@
-import { BushCommand, Shared, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, emojis, Shared, type CommandMessage, type SlashMessage } from '#lib';
import got from 'got';
import typescript from 'typescript';
import { NodeVM } from 'vm2';
@@ -13,14 +13,14 @@ export default class SyncAutomodCommand extends BushCommand {
examples: ['sync-automod'],
slash: false,
hidden: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
public override async exec(message: CommandMessage | SlashMessage) {
if (!message.author.isOwner() && message.author.id !== '497789163555389441')
- return await message.util.reply(`${util.emojis.error} Only a very select few may use this command.`);
+ return await message.util.reply(`${emojis.error} Only a very select few may use this command.`);
const badLinks = (await got.get('https://raw.githubusercontent.com/NotEnoughUpdates/bush-bot/master/src/lib/badlinks.ts'))
.body;
@@ -38,6 +38,6 @@ export default class SyncAutomodCommand extends BushCommand {
row.badWords = badWordsParsed;
await row.save();
- return await message.util.reply(`${util.emojis.success} Automod info synced.`);
+ return await message.util.reply(`${emojis.success} Automod info synced.`);
}
}
diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts
index d54d544..9491d19 100644
--- a/src/commands/dev/test.ts
+++ b/src/commands/dev/test.ts
@@ -1,4 +1,13 @@
-import { BushCommand, ButtonPaginator, OptArgType, Shared, type CommandMessage } from '#lib';
+import {
+ BushCommand,
+ ButtonPaginator,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ OptArgType,
+ Shared,
+ type CommandMessage
+} from '#lib';
import {
ActionRowBuilder,
ButtonBuilder,
@@ -33,7 +42,7 @@ export default class TestCommand extends BushCommand {
}
],
superUserOnly: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -65,7 +74,7 @@ export default class TestCommand extends BushCommand {
const embed = new EmbedBuilder()
.addFields([{ name: 'Field Name', value: 'Field Content' }])
.setAuthor({ name: 'Author', iconURL: 'https://www.w3schools.com/w3css/img_snowtops.jpg', url: 'https://google.com/' })
- .setColor(message.member?.displayColor ?? util.colors.default)
+ .setColor(message.member?.displayColor ?? colors.default)
.setDescription('Description')
.setFooter({ text: 'Footer', iconURL: message.author.avatarURL() ?? undefined })
.setURL('https://duckduckgo.com/')
@@ -106,12 +115,12 @@ export default class TestCommand extends BushCommand {
const fields = Array(25)
.fill(0)
.map((_, i) => ({ name: `Field ${i}`, value: 'Field Value' }));
- const c = util.colors;
const o = { description, author, footer, fields, time: Date.now() };
- const colors = [c.red, c.orange, c.gold, c.yellow, c.green, c.darkGreen, c.aqua, c.blue, c.purple, c.pink];
+ const c = colors;
+ const embedColors = [c.red, c.orange, c.gold, c.yellow, c.green, c.darkGreen, c.aqua, c.blue, c.purple, c.pink];
- const embeds = colors.map((c, i) => ({ ...o, title: `Embed Title ${i}`, color: c }));
+ const embeds = embedColors.map((c, i) => ({ ...o, title: `Embed Title ${i}`, color: c }));
const ButtonRows: ActionRowBuilder<ButtonBuilder>[] = [];
for (let a = 1; a <= 5; a++) {
@@ -125,7 +134,7 @@ export default class TestCommand extends BushCommand {
}
return await message.util.reply({ content: 'this is content', components: ButtonRows, embeds });
} else if (['delete slash commands'].includes(args.feature?.toLowerCase())) {
- if (!message.guild) return await message.util.reply(`${util.emojis.error} This test can only be run in a guild.`);
+ if (!message.guild) return await message.util.reply(`${emojis.error} This test can only be run in a guild.`);
await client.guilds.fetch();
const promises: Promise<Collection<string, ApplicationCommand>>[] = [];
client.guilds.cache.each((guild) => {
@@ -136,16 +145,16 @@ export default class TestCommand extends BushCommand {
await client.application!.commands.fetch();
await client.application!.commands.set([]);
- return await message.util.reply(`${util.emojis.success} Removed guild commands and global commands.`);
+ return await message.util.reply(`${emojis.success} Removed guild commands and global commands.`);
} else if (['drop down', 'drop downs', 'select menu', 'select menus'].includes(args.feature?.toLowerCase())) {
- return message.util.reply(`${util.emojis.error} no`);
+ return message.util.reply(`${emojis.error} no`);
} else if (['sync automod'].includes(args.feature?.toLowerCase())) {
const row = (await Shared.findByPk(0))!;
row.badLinks = badLinksArray;
row.badLinksSecret = badLinksSecretArray;
row.badWords = badWords;
await row.save();
- return await message.util.reply(`${util.emojis.success} Synced automod.`);
+ return await message.util.reply(`${emojis.success} Synced automod.`);
} else if (['modal'].includes(args.feature?.toLowerCase())) {
const m = await message.util.reply({
content: 'Click for modal',
diff --git a/src/commands/fun/coinFlip.ts b/src/commands/fun/coinFlip.ts
index fea5cb5..3adf7f2 100644
--- a/src/commands/fun/coinFlip.ts
+++ b/src/commands/fun/coinFlip.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib';
export default class CoinFlipCommand extends BushCommand {
public constructor() {
@@ -8,7 +8,7 @@ export default class CoinFlipCommand extends BushCommand {
description: 'Flip a virtual coin.',
usage: ['coinflip'],
examples: ['coinflip'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
slash: true
});
diff --git a/src/commands/fun/dice.ts b/src/commands/fun/dice.ts
index b2bc7e4..e7e5927 100644
--- a/src/commands/fun/dice.ts
+++ b/src/commands/fun/dice.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib';
export default class DiceCommand extends BushCommand {
public constructor() {
@@ -8,7 +8,7 @@ export default class DiceCommand extends BushCommand {
description: 'Roll virtual dice.',
usage: ['dice'],
examples: ['dice'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
slash: true
});
diff --git a/src/commands/fun/eightBall.ts b/src/commands/fun/eightBall.ts
index 66fcc45..eb5aee8 100644
--- a/src/commands/fun/eightBall.ts
+++ b/src/commands/fun/eightBall.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class EightBallCommand extends BushCommand {
@@ -21,7 +21,7 @@ export default class EightBallCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts
index d25cb5d..c2fdccf 100644
--- a/src/commands/fun/minesweeper.ts
+++ b/src/commands/fun/minesweeper.ts
@@ -1,4 +1,12 @@
-import { BushCommand, OptArgType, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ OptArgType,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { Minesweeper } from '@notenoughupdates/discord.js-minesweeper';
import assert from 'assert';
import { ApplicationCommandOptionType } from 'discord.js';
@@ -63,7 +71,7 @@ export default class MinesweeperCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -95,14 +103,14 @@ export default class MinesweeperCommand extends BushCommand {
if (args.rows * args.columns <= args.mines * 2)
return message.util.reply(
- `${util.emojis.error} The number of roles multiplied by the number of columns must be greater than or equal to the number of mines multiplied by two.`
+ `${emojis.error} The number of roles multiplied by the number of columns must be greater than or equal to the number of mines multiplied by two.`
);
- if (!matrix) return await message.util.reply(`${util.emojis.error} Something went wrong.`);
+ if (!matrix) return await message.util.reply(`${emojis.error} Something went wrong.`);
const res = matrix.toString().replaceAll(':zero:', ':blue_square:');
- if (res.length > 2000) return message.util.reply(`${util.emojis.error} The minesweeper generated is over 2,000 characters.`);
+ if (res.length > 2000) return message.util.reply(`${emojis.error} The minesweeper generated is over 2,000 characters.`);
return await message.util.reply(res);
}
diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts
index 544c30a..3eae98c 100644
--- a/src/commands/info/avatar.ts
+++ b/src/commands/info/avatar.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import { Arg, BushCommand, clientSendAndPermCheck, colors, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, PermissionFlagsBits } from 'discord.js';
export default class AvatarCommand extends BushCommand {
@@ -13,7 +13,7 @@ export default class AvatarCommand extends BushCommand {
{
id: 'user',
description: 'The user you would like to find the avatar of.',
- type: util.arg.union('member', 'globalUser'),
+ type: Arg.union('member', 'globalUser'),
readableType: 'member|user',
prompt: 'Who would you like to see the avatar of?',
retry: '{error} Choose a valid user.',
@@ -21,7 +21,7 @@ export default class AvatarCommand extends BushCommand {
slashType: ApplicationCommandOptionType.User
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
slash: true
});
@@ -37,7 +37,7 @@ export default class AvatarCommand extends BushCommand {
const guildAvatar = member?.avatarURL(params);
- const embed = new EmbedBuilder().setTimestamp().setColor(util.colors.default).setTitle(`${user.tag}'s Avatar`);
+ const embed = new EmbedBuilder().setTimestamp().setColor(colors.default).setTitle(`${user.tag}'s Avatar`);
guildAvatar
? embed.setImage(guildAvatar).setThumbnail(user.avatarURL(params) ?? defaultAvatar)
: embed.setImage(user.avatarURL(params) ?? defaultAvatar);
diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts
index 4a8a36a..decbe04 100644
--- a/src/commands/info/botInfo.ts
+++ b/src/commands/info/botInfo.ts
@@ -1,4 +1,13 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ humanizeDuration,
+ mapIDs,
+ shell,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { EmbedBuilder, PermissionFlagsBits, version as discordJSVersion } from 'discord.js';
import * as os from 'os';
@@ -15,7 +24,7 @@ export default class BotInfoCommand extends BushCommand {
usage: ['bot-info'],
examples: ['bot-info'],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -35,14 +44,14 @@ export default class BotInfoCommand extends BushCommand {
haiku = 'Haiku'
}
- const developers = (await util.mapIDs(client.config.owners)).map((u) => u?.tag).join('\n');
- const currentCommit = (await util.shell('git rev-parse HEAD')).stdout.replace('\n', '');
- let repoUrl = (await util.shell('git remote get-url origin')).stdout.replace('\n', '');
+ const developers = (await mapIDs(client.config.owners)).map((u) => u?.tag).join('\n');
+ const currentCommit = (await shell('git rev-parse HEAD')).stdout.replace('\n', '');
+ let repoUrl = (await shell('git remote get-url origin')).stdout.replace('\n', '');
if (repoUrl.includes('.git')) repoUrl = repoUrl.substring(0, repoUrl.length - 4);
const embed = new EmbedBuilder()
.setTitle('Bot Info:')
.addFields([
- { name: '**Uptime**', value: util.humanizeDuration(client.uptime!, 2), inline: true },
+ { name: '**Uptime**', value: humanizeDuration(client.uptime!, 2), inline: true },
{
name: '**Memory Usage**',
value: `System: ${prettyBytes(os.totalmem() - os.freemem(), { binary: true })}/${prettyBytes(os.totalmem(), {
@@ -73,7 +82,7 @@ export default class BotInfoCommand extends BushCommand {
{ name: '**Developers**', value: developers, inline: true }
])
.setTimestamp()
- .setColor(util.colors.default);
+ .setColor(colors.default);
await message.util.reply({ embeds: [embed] });
}
}
diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts
index f60e28a..84c4b3c 100644
--- a/src/commands/info/color.ts
+++ b/src/commands/info/color.ts
@@ -1,4 +1,13 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, PermissionFlagsBits, Role } from 'discord.js';
import tinycolor from 'tinycolor2';
@@ -16,7 +25,7 @@ export default class ColorCommand extends BushCommand {
{
id: 'color',
description: 'The color string, role, or member to find the color of.',
- type: util.arg.union('tinyColor', 'role', 'member'),
+ type: Arg.union('tinyColor', 'role', 'member'),
readableType: 'color|role|member',
match: 'restContent',
prompt: 'What color code, role, or user would you like to find the color of?',
@@ -25,7 +34,7 @@ export default class ColorCommand extends BushCommand {
}
],
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -36,10 +45,7 @@ export default class ColorCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage, args: { color: ArgType<'tinyColor' | 'role' | 'member'> }) {
const _color = message.util.isSlashMessage(message)
- ? ((await util.arg.cast(util.arg.union('tinyColor', 'role', 'member'), message, args.color as string)) as
- | string
- | Role
- | GuildMember)
+ ? ((await Arg.cast(Arg.union('tinyColor', 'role', 'member'), message, args.color as string)) as string | Role | GuildMember)
: args.color;
const color =
@@ -51,7 +57,7 @@ export default class ColorCommand extends BushCommand {
if (_color instanceof Role && _color.hexColor === '#000000') {
return await message.util.reply({
- content: `${util.emojis.error} <@&${_color.id}> does not have a color.`,
+ content: `${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 572cf06..92999a5 100644
--- a/src/commands/info/guildInfo.ts
+++ b/src/commands/info/guildInfo.ts
@@ -1,9 +1,23 @@
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ akairo,
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ mappings,
+ timestampAndDelta,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import {
ApplicationCommandOptionType,
ChannelType,
EmbedBuilder,
+ escapeMarkdown,
Guild,
GuildDefaultMessageNotifications,
GuildExplicitContentFilter,
@@ -29,7 +43,7 @@ export default class GuildInfoCommand extends BushCommand {
{
id: 'guild',
description: 'The guild to find information about.',
- type: util.arg.union('guild', 'snowflake'),
+ type: Arg.union('guild', 'snowflake'),
readableType: 'guild|snowflake',
prompt: 'What server would you like to find information about?',
retry: '{error} Choose a valid server to find information about.',
@@ -38,7 +52,7 @@ export default class GuildInfoCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -46,7 +60,7 @@ export default class GuildInfoCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage, args: { guild: OptArgType<'guild' | 'snowflake'> }) {
if (!args.guild && !message.inGuild()) {
return await message.util.reply(
- `${util.emojis.error} You must either provide an server to provide info about or run this command in a server.`
+ `${emojis.error} You must either provide an server to provide info about or run this command in a server.`
);
}
@@ -54,7 +68,7 @@ export default class GuildInfoCommand extends BushCommand {
if (typeof guild === 'string') {
const preview = await client.fetchGuildPreview(`${args.guild}` as Snowflake).catch(() => undefined);
if (preview) guild = preview;
- else return await message.util.reply(`${util.emojis.error} That guild is not discoverable or does not exist.`);
+ else return await message.util.reply(`${emojis.error} That guild is not discoverable or does not exist.`);
}
assert(guild);
@@ -63,7 +77,7 @@ export default class GuildInfoCommand extends BushCommand {
await guild.fetch();
}
- const guildInfoEmbed = new EmbedBuilder().setTitle(guild.name).setColor(util.colors.default);
+ const guildInfoEmbed = new EmbedBuilder().setTitle(guild.name).setColor(colors.default);
if (guild.icon) guildInfoEmbed.setThumbnail(guild.iconURL({ size: 2048, extension: 'png' }));
await this.generateAboutField(guildInfoEmbed, guild);
@@ -79,16 +93,16 @@ export default class GuildInfoCommand extends BushCommand {
private generateDescription(embed: EmbedBuilder, guild: Guild | GuildPreview) {
const description: string[] = [];
- const otherEmojis = client.consts.mappings.otherEmojis;
+ const otherEmojis = mappings.otherEmojis;
- const verifiedGuilds = Object.values(client.consts.mappings.guilds);
+ const verifiedGuilds = Object.values(mappings.guilds);
if (verifiedGuilds.includes(guild.id as typeof verifiedGuilds[number])) description.push(otherEmojis.BushVerified);
if (guild instanceof Guild) {
if (guild.premiumTier !== GuildPremiumTier.None) description.push(otherEmojis[`BoostTier${guild.premiumTier}`]);
}
- const features = client.consts.mappings.features;
+ const features = mappings.features;
const guildFeatures = guild.features.sort((a, b): number => {
const aWeight = features[a]?.weight;
const bWeight = features[b]?.weight;
@@ -103,7 +117,7 @@ export default class GuildInfoCommand extends BushCommand {
guildFeatures.forEach((feature) => {
if (features[feature]?.emoji) description.push(`${features[feature].emoji}`);
else if (features[feature]?.name) description.push(`\`${features[feature].name}\``);
- else description.push(`\`${feature.charAt(0) + util.akairo.snakeToCamelCase(feature).substring(1)}\``);
+ else description.push(`\`${feature.charAt(0) + akairo.snakeToCamelCase(feature).substring(1)}\``);
});
}
@@ -125,12 +139,12 @@ export default class GuildInfoCommand extends BushCommand {
] as RTCRegion[];
guildAbout.push(
- `**Owner:** ${util.discord.escapeMarkdown(guild.members.cache.get(guild.ownerId)?.user.tag ?? '¯\\_(ツ)_/¯')}`,
- `**Created** ${util.timestampAndDelta(guild.createdAt, 'd')}`,
- `**Members:** ${guild.memberCount.toLocaleString() ?? 0} (${util.emojis.onlineCircle} ${
+ `**Owner:** ${escapeMarkdown(guild.members.cache.get(guild.ownerId)?.user.tag ?? '¯\\_(ツ)_/¯')}`,
+ `**Created** ${timestampAndDelta(guild.createdAt, 'd')}`,
+ `**Members:** ${guild.memberCount.toLocaleString() ?? 0} (${emojis.onlineCircle} ${
guild.approximatePresenceCount?.toLocaleString() ?? 0
- }, ${util.emojis.offlineCircle} ${(guild.memberCount - (guild.approximatePresenceCount ?? 0)).toLocaleString() ?? 0})`,
- `**Regions:** ${guildRegions.map((region) => client.consts.mappings.regions[region] || region).join(', ')}`
+ }, ${emojis.offlineCircle} ${(guild.memberCount - (guild.approximatePresenceCount ?? 0)).toLocaleString() ?? 0})`,
+ `**Regions:** ${guildRegions.map((region) => mappings.regions[region] || region).join(', ')}`
);
if (guild.premiumSubscriptionCount)
guildAbout.push(`**Boosts:** Level ${guild.premiumTier} with ${guild.premiumSubscriptionCount ?? 0} boosts`);
@@ -144,9 +158,9 @@ export default class GuildInfoCommand extends BushCommand {
if (guild.splash) guildAbout.push(`**Splash:** [link](${guild.splashURL({ size: 4096, extension: 'png' })})`);
} else {
guildAbout.push(
- `**Members:** ${guild.approximateMemberCount?.toLocaleString() ?? 0} (${util.emojis.onlineCircle} ${
+ `**Members:** ${guild.approximateMemberCount?.toLocaleString() ?? 0} (${emojis.onlineCircle} ${
guild.approximatePresenceCount?.toLocaleString() ?? 0
- }, ${util.emojis.offlineCircle} ${(
+ }, ${emojis.offlineCircle} ${(
(guild.approximateMemberCount ?? 0) - (guild.approximatePresenceCount ?? 0)
).toLocaleString()})`,
`**Emojis:** ${(guild as GuildPreview).emojis.size?.toLocaleString() ?? 0}`,
@@ -173,7 +187,7 @@ export default class GuildInfoCommand extends BushCommand {
] as const
).map(
(type) =>
- `${client.consts.mappings.otherEmojis[`Channel${type[0]}`]} ${guild.channels.cache
+ `${mappings.otherEmojis[`Channel${type[0]}`]} ${guild.channels.cache
.filter((channel) => type[1].some((type) => channel.type === type))
.size.toLocaleString()}`
);
diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts
index af44980..051fce5 100644
--- a/src/commands/info/help.ts
+++ b/src/commands/info/help.ts
@@ -1,4 +1,15 @@
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ format,
+ invite,
+ prefix,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import {
ActionRowBuilder,
@@ -48,7 +59,7 @@ export default class HelpCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -71,11 +82,11 @@ export default class HelpCommand extends BushCommand {
}
private helpAll(message: CommandMessage | SlashMessage, args: HelpArgs, row: ActionRowBuilder<ButtonBuilder>) {
- const prefix = util.prefix(message);
+ const prefix_ = prefix(message);
const embed = new EmbedBuilder()
- .setColor(util.colors.default)
+ .setColor(colors.default)
.setTimestamp()
- .setFooter({ text: `For more information about a command use ${prefix}help <command>` });
+ .setFooter({ text: `For more information about a command use ${prefix_}help <command>` });
for (const [, category] of this.handler.categories) {
const categoryFilter = category.filter((command) => {
if (command.pseudo) return false;
@@ -100,7 +111,7 @@ export default class HelpCommand extends BushCommand {
}
private helpIndividual(message: CommandMessage | SlashMessage, row: ActionRowBuilder<ButtonBuilder>, command: BushCommand) {
- const embed = new EmbedBuilder().setColor(util.colors.default).setTitle(`${command.id} Command`);
+ const embed = new EmbedBuilder().setColor(colors.default).setTitle(`${command.id} Command`);
let description = `${command.description ?? '*This command does not have a description.*'}`;
if (command.note) description += `\n\n${command.note}`;
@@ -200,7 +211,7 @@ export default class HelpCommand extends BushCommand {
if (command.restrictedGuilds?.length)
restrictions.push(
`__Restricted Servers__: ${command.restrictedGuilds
- .map((g) => util.format.inlineCode(client.guilds.cache.find((g1) => g1.id === g)?.name ?? 'Unknown'))
+ .map((g) => format.inlineCode(client.guilds.cache.find((g1) => g1.id === g)?.name ?? 'Unknown'))
.join(' ')}`
);
if (restrictions.length) embed.addFields([{ name: '» Restrictions', value: restrictions.join('\n') }]);
@@ -211,7 +222,7 @@ export default class HelpCommand extends BushCommand {
const row = new ActionRowBuilder<ButtonBuilder>();
if (!client.config.isDevelopment && !client.guilds.cache.some((guild) => guild.ownerId === message.author.id)) {
- row.addComponents([new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: util.invite })]);
+ row.addComponents([new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: invite(this.client) })]);
}
if (!client.guilds.cache.get(client.config.supportGuild.id)?.members.cache.has(message.author.id)) {
row.addComponents([
diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts
index 9c9556b..e66f900 100644
--- a/src/commands/info/icon.ts
+++ b/src/commands/info/icon.ts
@@ -1,6 +1,6 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
-import { EmbedBuilder, PermissionFlagsBits } from 'discord.js';
+import { EmbedBuilder, escapeMarkdown, PermissionFlagsBits } from 'discord.js';
export default class IconCommand extends BushCommand {
public constructor() {
@@ -10,7 +10,7 @@ export default class IconCommand extends BushCommand {
description: "A command to get the server's icon",
usage: ['icon'],
examples: ['icon'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
channel: 'guild',
slash: true
@@ -22,14 +22,14 @@ export default class IconCommand extends BushCommand {
const embed = new EmbedBuilder()
.setTimestamp()
- .setColor(util.colors.default)
+ .setColor(colors.default)
.setImage(
message.guild.iconURL({
size: 2048,
extension: 'png'
})!
)
- .setTitle(util.discord.escapeMarkdown(message.guild.name));
+ .setTitle(escapeMarkdown(message.guild.name));
await message.util.reply({ embeds: [embed] });
}
}
diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts
index 0d5bd15..a7ff30e 100644
--- a/src/commands/info/links.ts
+++ b/src/commands/info/links.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, invite, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
import packageDotJSON from '../../../package.json' assert { type: 'json' };
@@ -13,7 +13,7 @@ export default class LinksCommand extends BushCommand {
description: 'Sends bot links',
usage: ['links'],
examples: ['links'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
slash: true
});
@@ -22,7 +22,7 @@ export default class LinksCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage) {
const buttonRow = new ActionRowBuilder<ButtonBuilder>();
if (!client.config.isDevelopment || message.author.isOwner()) {
- buttonRow.addComponents([new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: util.invite })]);
+ buttonRow.addComponents([new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: invite(this.client) })]);
}
buttonRow.addComponents([
new ButtonBuilder({ style: ButtonStyle.Link, label: 'Support Server', url: client.config.supportGuild.invite }),
diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts
index ad7fdcc..060b1f6 100644
--- a/src/commands/info/ping.ts
+++ b/src/commands/info/ping.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, colors, format, type CommandMessage, type SlashMessage } from '#lib';
import { EmbedBuilder, PermissionFlagsBits, type Message } from 'discord.js';
export default class PingCommand extends BushCommand {
@@ -10,7 +10,7 @@ export default class PingCommand extends BushCommand {
usage: ['ping'],
examples: ['ping'],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -30,8 +30,8 @@ export default class PingCommand extends BushCommand {
}
private command(message: CommandMessage | SlashMessage, msgLatency: number) {
- const botLatency = util.format.codeBlock(`${Math.round(msgLatency)}ms`);
- const apiLatency = util.format.codeBlock(`${Math.round(message.client.ws.ping)}ms`);
+ const botLatency = format.codeBlock(`${Math.round(msgLatency)}ms`);
+ const apiLatency = format.codeBlock(`${Math.round(message.client.ws.ping)}ms`);
const embed = new EmbedBuilder()
.setTitle('Pong! 🏓')
.addFields([
@@ -39,7 +39,7 @@ export default class PingCommand extends BushCommand {
{ name: 'API Latency', value: apiLatency, inline: true }
])
.setFooter({ text: message.author.username, iconURL: message.author.displayAvatarURL() })
- .setColor(util.colors.default)
+ .setColor(colors.default)
.setTimestamp();
return message.util.reply({
content: null,
diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts
index f916687..e87ca1f 100644
--- a/src/commands/info/pronouns.ts
+++ b/src/commands/info/pronouns.ts
@@ -1,5 +1,13 @@
-import { AllowedMentions, BushCommand, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
-import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ getPronounsOf,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
+import { ApplicationCommandOptionType, EmbedBuilder, escapeMarkdown, PermissionFlagsBits } from 'discord.js';
export default class PronounsCommand extends BushCommand {
public constructor() {
@@ -20,7 +28,7 @@ export default class PronounsCommand extends BushCommand {
slashType: ApplicationCommandOptionType.User
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
slash: true
});
@@ -32,21 +40,19 @@ export default class PronounsCommand extends BushCommand {
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
- const pronouns = await util.getPronounsOf(user);
+ const pronouns = await getPronounsOf(user);
if (!pronouns) {
return await message.util.reply({
- content: `${
- author ? 'You do' : `${util.discord.escapeMarkdown(user.tag)} does`
- } not appear to have any pronouns set. Please${author ? '' : ' tell them to'} go to https://pronoundb.org/ and set ${
- author ? 'your' : 'their'
- } pronouns.`,
+ content: `${author ? 'You do' : `${escapeMarkdown(user.tag)} does`} not appear to have any pronouns set. Please${
+ author ? '' : ' tell them to'
+ } go to https://pronoundb.org/ and set ${author ? 'your' : 'their'} pronouns.`,
allowedMentions: AllowedMentions.none()
});
} else {
return await message.util.reply({
embeds: [
new EmbedBuilder({
- title: `${author ? 'Your' : `${util.discord.escapeMarkdown(user.tag)}'s`} pronouns:`,
+ title: `${author ? 'Your' : `${escapeMarkdown(user.tag)}'s`} pronouns:`,
description: pronouns,
footer: {
text: 'Data provided by https://pronoundb.org/'
diff --git a/src/commands/info/snowflake.ts b/src/commands/info/snowflake.ts
index e74756f..a28f4c5 100644
--- a/src/commands/info/snowflake.ts
+++ b/src/commands/info/snowflake.ts
@@ -1,9 +1,18 @@
-import { BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ timestamp,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { stripIndent } from '#tags';
import {
ApplicationCommandOptionType,
ChannelType,
EmbedBuilder,
+ escapeMarkdown,
PermissionFlagsBits,
SnowflakeUtil,
type DeconstructedSnowflake,
@@ -31,7 +40,7 @@ export default class SnowflakeCommand extends BushCommand {
slashType: ApplicationCommandOptionType.String
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
slash: true
});
@@ -39,7 +48,7 @@ export default class SnowflakeCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage, args: { snowflake: ArgType<'snowflake'> }) {
const snowflake = `${args.snowflake}` as Snowflake;
- const snowflakeEmbed = new EmbedBuilder().setTitle('Unknown :snowflake:').setColor(util.colors.default);
+ const snowflakeEmbed = new EmbedBuilder().setTitle('Unknown :snowflake:').setColor(colors.default);
// Channel
if (client.channels.cache.has(snowflake)) {
@@ -47,13 +56,9 @@ export default class SnowflakeCommand extends BushCommand {
const channelInfo = [`**Type:** ${BushChannelType[channel.type] ?? ChannelType[channel.type]}`];
if (channel.type === ChannelType.DM) {
channelInfo.push(
- `**Recipient:** ${util.discord.escapeMarkdown(channel.recipient?.tag ?? '¯\\_(ツ)_/¯')} (${
- channel.recipient?.id ?? '¯\\_(ツ)_/¯'
- })`
- );
- snowflakeEmbed.setTitle(
- `:snowflake: DM with ${util.discord.escapeMarkdown(channel.recipient?.tag ?? '¯\\_(ツ)_/¯')} \`[Channel]\``
+ `**Recipient:** ${escapeMarkdown(channel.recipient?.tag ?? '¯\\_(ツ)_/¯')} (${channel.recipient?.id ?? '¯\\_(ツ)_/¯'})`
);
+ snowflakeEmbed.setTitle(`:snowflake: DM with ${escapeMarkdown(channel.recipient?.tag ?? '¯\\_(ツ)_/¯')} \`[Channel]\``);
} else if (
channel.type === ChannelType.GuildCategory ||
channel.type === ChannelType.GuildNews ||
@@ -63,10 +68,10 @@ export default class SnowflakeCommand extends BushCommand {
channel.isThread()
) {
channelInfo.push(
- `**Channel Name:** <#${channel.id}> (${util.discord.escapeMarkdown(channel.name)})`,
- `**Channel's Server:** ${util.discord.escapeMarkdown(channel.guild.name)} (${channel.guild.id})`
+ `**Channel Name:** <#${channel.id}> (${escapeMarkdown(channel.name)})`,
+ `**Channel's Server:** ${escapeMarkdown(channel.guild.name)} (${channel.guild.id})`
);
- snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(channel.name)} \`[Channel]\``);
+ snowflakeEmbed.setTitle(`:snowflake: ${escapeMarkdown(channel.name)} \`[Channel]\``);
}
snowflakeEmbed.addFields([{ name: '» Channel Info', value: channelInfo.join('\n') }]);
}
@@ -75,12 +80,12 @@ export default class SnowflakeCommand extends BushCommand {
if (client.guilds.cache.has(snowflake)) {
const guild: Guild = client.guilds.cache.get(snowflake)!;
const guildInfo = stripIndent`
- **Name:** ${util.discord.escapeMarkdown(guild.name)}
- **Owner:** ${util.discord.escapeMarkdown(client.users.cache.get(guild.ownerId)?.tag ?? '¯\\_(ツ)_/¯')} (${guild.ownerId})
+ **Name:** ${escapeMarkdown(guild.name)}
+ **Owner:** ${escapeMarkdown(client.users.cache.get(guild.ownerId)?.tag ?? '¯\\_(ツ)_/¯')} (${guild.ownerId})
**Members:** ${guild.memberCount?.toLocaleString()}`;
if (guild.icon) snowflakeEmbed.setThumbnail(guild.iconURL({ size: 2048 })!);
snowflakeEmbed.addFields([{ name: '» Server Info', value: guildInfo }]);
- snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(guild.name)} \`[Server]\``);
+ snowflakeEmbed.setTitle(`:snowflake: ${escapeMarkdown(guild.name)} \`[Server]\``);
}
// User
@@ -88,28 +93,28 @@ export default class SnowflakeCommand extends BushCommand {
if (client.users.cache.has(snowflake) || fetchedUser) {
const user: User = (client.users.cache.get(snowflake) ?? fetchedUser)!;
const userInfo = stripIndent`
- **Name:** <@${user.id}> (${util.discord.escapeMarkdown(user.tag)})`;
+ **Name:** <@${user.id}> (${escapeMarkdown(user.tag)})`;
if (user.avatar) snowflakeEmbed.setThumbnail(user.avatarURL({ size: 2048 })!);
snowflakeEmbed.addFields([{ name: '» User Info', value: userInfo }]);
- snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(user.tag)} \`[User]\``);
+ snowflakeEmbed.setTitle(`:snowflake: ${escapeMarkdown(user.tag)} \`[User]\``);
}
// Emoji
if (client.emojis.cache.has(snowflake)) {
const emoji = client.emojis.cache.get(snowflake)!;
const emojiInfo = stripIndent`
- **Name:** ${util.discord.escapeMarkdown(emoji.name ?? '¯\\_(ツ)_/¯')}
+ **Name:** ${escapeMarkdown(emoji.name ?? '¯\\_(ツ)_/¯')}
**Animated:** ${emoji.animated}`;
if (emoji.url) snowflakeEmbed.setThumbnail(emoji.url);
snowflakeEmbed.addFields([{ name: '» Emoji Info', value: emojiInfo }]);
- snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(emoji.name ?? '¯\\_(ツ)_/¯')} \`[Emoji]\``);
+ snowflakeEmbed.setTitle(`:snowflake: ${escapeMarkdown(emoji.name ?? '¯\\_(ツ)_/¯')} \`[Emoji]\``);
}
// Role
if (message.guild && message.guild.roles.cache.has(snowflake)) {
const role: Role = message.guild.roles.cache.get(snowflake)!;
const roleInfo = stripIndent`
- **Name:** <@&${role.id}> (${util.discord.escapeMarkdown(role.name)})
+ **Name:** <@&${role.id}> (${escapeMarkdown(role.name)})
**Members:** ${role.members.size}
**Hoisted:** ${role.hoist}
**Managed:** ${role.managed}
@@ -117,14 +122,14 @@ export default class SnowflakeCommand extends BushCommand {
**Hex Color:** ${role.hexColor}`;
if (role.color) snowflakeEmbed.setColor(role.color);
snowflakeEmbed.addFields([{ name: '» Role Info', value: roleInfo }]);
- snowflakeEmbed.setTitle(`:snowflake: ${util.discord.escapeMarkdown(role.name)} \`[Role]\``);
+ snowflakeEmbed.setTitle(`:snowflake: ${escapeMarkdown(role.name)} \`[Role]\``);
}
// SnowflakeInfo
const deconstructedSnowflake: DeconstructedSnowflake = SnowflakeUtil.deconstruct(snowflake);
const snowflakeInfo = stripIndent`
**Timestamp:** ${deconstructedSnowflake.timestamp}
- **Created:** ${util.timestamp(new Date(Number(deconstructedSnowflake.timestamp)))}
+ **Created:** ${timestamp(new Date(Number(deconstructedSnowflake.timestamp)))}
**Worker ID:** ${deconstructedSnowflake.workerId}
**Process ID:** ${deconstructedSnowflake.processId}
**Increment:** ${deconstructedSnowflake.increment}`;
diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts
index d617756..a39e28a 100644
--- a/src/commands/info/userInfo.ts
+++ b/src/commands/info/userInfo.ts
@@ -1,9 +1,26 @@
-import { BushCommand, Time, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ getPronounsOf,
+ getShared,
+ mappings,
+ oxford,
+ sleep,
+ Time,
+ timestampAndDelta,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import {
ActivityType,
ApplicationCommandOptionType,
ApplicationFlagsBitField,
EmbedBuilder,
+ escapeMarkdown,
PermissionFlagsBits,
TeamMemberMembershipState,
UserFlags,
@@ -26,7 +43,7 @@ export default class UserInfoCommand extends BushCommand {
{
id: 'user',
description: 'The user you would like to find information about.',
- type: util.arg.union('user', 'snowflake'),
+ type: Arg.union('user', 'snowflake'),
readableType: 'user|snowflake',
prompt: 'What user would you like to find information about?',
retry: '{error} Choose a valid user to find information about.',
@@ -35,7 +52,7 @@ export default class UserInfoCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -47,7 +64,7 @@ export default class UserInfoCommand extends BushCommand {
: typeof args.user === 'object'
? args.user
: await client.users.fetch(`${args.user}`).catch(() => undefined);
- if (user === undefined) return message.util.reply(`${util.emojis.error} Invalid user.`);
+ if (user === undefined) return message.util.reply(`${emojis.error} Invalid user.`);
const member = message.guild ? await message.guild.members.fetch(user.id).catch(() => undefined) : undefined;
await user.fetch(true); // gets banner info and accent color
@@ -58,23 +75,23 @@ export default class UserInfoCommand extends BushCommand {
public static async makeUserInfoEmbed(user: User, member?: GuildMember, guild?: Guild | null) {
const emojis = [];
- const superUsers = util.getShared('superUsers');
+ const superUsers = getShared('superUsers');
const userEmbed = new EmbedBuilder()
- .setTitle(util.discord.escapeMarkdown(user.tag))
+ .setTitle(escapeMarkdown(user.tag))
.setThumbnail(user.displayAvatarURL({ size: 2048, extension: 'png' }))
.setTimestamp()
.setFooter({ text: user.tag })
- .setColor(member?.displayColor ?? util.colors.default);
+ .setColor(member?.displayColor ?? colors.default);
// Flags
- if (client.config.owners.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.Developer);
- if (superUsers.includes(user.id)) emojis.push(client.consts.mappings.otherEmojis.Superuser);
+ if (client.config.owners.includes(user.id)) emojis.push(mappings.otherEmojis.Developer);
+ if (superUsers.includes(user.id)) emojis.push(mappings.otherEmojis.Superuser);
const flags = user.flags?.toArray();
if (flags) {
flags.forEach((f) => {
- if (client.consts.mappings.userFlags[f] !== undefined) {
- emojis.push(client.consts.mappings.userFlags[f]);
+ if (mappings.userFlags[f] !== undefined) {
+ emojis.push(mappings.userFlags[f]);
} else emojis.push(`\`${f}\``);
});
}
@@ -82,18 +99,18 @@ export default class UserInfoCommand extends BushCommand {
// Since discord bald I just guess if someone has nitro
if (
Number(user.discriminator) < 10 ||
- client.consts.mappings.maybeNitroDiscrims.includes(user.discriminator) ||
+ mappings.maybeNitroDiscrims.includes(user.discriminator) ||
user.displayAvatarURL()?.endsWith('.gif') ||
user.flags?.has(UserFlags.Partner) ||
user.flags?.has(UserFlags.Staff) ||
member?.avatar // server avatar
) {
- emojis.push(client.consts.mappings.otherEmojis.Nitro);
+ emojis.push(mappings.otherEmojis.Nitro);
}
- if (guild?.ownerId == user.id) emojis.push(client.consts.mappings.otherEmojis.Owner);
- else if (member?.permissions.has(PermissionFlagsBits.Administrator)) emojis.push(client.consts.mappings.otherEmojis.Admin);
- if (member?.premiumSinceTimestamp) emojis.push(client.consts.mappings.otherEmojis.Booster);
+ if (guild?.ownerId == user.id) emojis.push(mappings.otherEmojis.Owner);
+ else if (member?.permissions.has(PermissionFlagsBits.Administrator)) emojis.push(mappings.otherEmojis.Admin);
+ if (member?.premiumSinceTimestamp) emojis.push(mappings.otherEmojis.Booster);
await this.generateGeneralInfoField(userEmbed, user);
@@ -121,12 +138,12 @@ export default class UserInfoCommand extends BushCommand {
const generalInfo = [
`**Mention:** <@${user.id}>`,
`**ID:** ${user.id}`,
- `**Created:** ${util.timestampAndDelta(user.createdAt, 'd')}`
+ `**Created:** ${timestampAndDelta(user.createdAt, 'd')}`
];
if (user.accentColor !== null) generalInfo.push(`**Accent Color:** ${user.hexAccentColor}`);
if (user.banner) generalInfo.push(`**Banner:** [link](${user.bannerURL({ extension: 'png', size: 4096 })})`);
- const pronouns = await Promise.race([util.getPronounsOf(user), util.sleep(2 * Time.Second)]); // cut off request after 2 seconds
+ const pronouns = await Promise.race([getPronounsOf(user), sleep(2 * Time.Second)]); // cut off request after 2 seconds
if (pronouns && typeof pronouns === 'string' && pronouns !== 'Unspecified') generalInfo.push(`**Pronouns:** ${pronouns}`);
@@ -140,21 +157,21 @@ export default class UserInfoCommand extends BushCommand {
const serverUserInfo = [];
if (member.joinedTimestamp)
serverUserInfo.push(
- `**${member.guild!.ownerId == member.user.id ? 'Created Server' : 'Joined'}:** ${util.timestampAndDelta(
+ `**${member.guild!.ownerId == member.user.id ? 'Created Server' : 'Joined'}:** ${timestampAndDelta(
member.joinedAt!,
'd'
)}`
);
- if (member.premiumSince) serverUserInfo.push(`**Booster Since:** ${util.timestampAndDelta(member.premiumSince, 'd')}`);
+ if (member.premiumSince) serverUserInfo.push(`**Booster Since:** ${timestampAndDelta(member.premiumSince, 'd')}`);
if (member.displayHexColor) serverUserInfo.push(`**Display Color:** ${member.displayHexColor}`);
- if (member.user.id == '322862723090219008' && member.guild?.id == client.consts.mappings.guilds.bush)
+ if (member.user.id == '322862723090219008' && member.guild?.id == mappings.guilds.bush)
serverUserInfo.push(`**General Deletions:** 1⅓`);
if (
(['384620942577369088', '496409778822709251'] as const).includes(member.user.id) &&
- member.guild.id == client.consts.mappings.guilds.bush
+ member.guild.id == mappings.guilds.bush
)
serverUserInfo.push(`**General Deletions:** ⅓`);
- if (member?.nickname) serverUserInfo.push(`**Nickname:** ${util.discord.escapeMarkdown(member?.nickname)}`);
+ if (member?.nickname) serverUserInfo.push(`**Nickname:** ${escapeMarkdown(member?.nickname)}`);
if (serverUserInfo.length) embed.addFields([{ name: title, value: serverUserInfo.join('\n') }]);
}
@@ -179,10 +196,10 @@ export default class UserInfoCommand extends BushCommand {
const presenceInfo = [];
if (member?.presence.status) presenceInfo.push(`**Status:** ${member.presence.status}`);
if (devices && devices.length)
- presenceInfo.push(`**${devices.length - 1 ? 'Devices' : 'Device'}:** ${util.oxford(devices, 'and', '')}`);
+ presenceInfo.push(`**${devices.length - 1 ? 'Devices' : 'Device'}:** ${oxford(devices, 'and', '')}`);
if (activitiesNames.length)
- presenceInfo.push(`**Activit${activitiesNames.length - 1 ? 'ies' : 'y'}:** ${util.oxford(activitiesNames, 'and', '')}`);
- if (customStatus && customStatus.length) presenceInfo.push(`**Custom Status:** ${util.discord.escapeMarkdown(customStatus)}`);
+ presenceInfo.push(`**Activit${activitiesNames.length - 1 ? 'ies' : 'y'}:** ${oxford(activitiesNames, 'and', '')}`);
+ if (customStatus && customStatus.length) presenceInfo.push(`**Custom Status:** ${escapeMarkdown(customStatus)}`);
embed.addFields([{ name: title, value: presenceInfo.join('\n') }]);
enum statusEmojis {
@@ -229,8 +246,8 @@ export default class UserInfoCommand extends BushCommand {
perms.push('`Administrator`');
} else if (member?.permissions.toArray().length) {
member.permissions.toArray().forEach((permission) => {
- if (client.consts.mappings.permissions[permission]?.important) {
- perms.push(`\`${client.consts.mappings.permissions[permission].name}\``);
+ if (mappings.permissions[permission]?.important) {
+ perms.push(`\`${mappings.permissions[permission].name}\``);
}
});
}
@@ -247,14 +264,14 @@ export default class UserInfoCommand extends BushCommand {
const flags = new ApplicationFlagsBitField(applicationInfo.flags);
const intent = (check: ApplicationFlagsString, warn: ApplicationFlagsString) => {
- if (flags.has(check)) return util.emojis.check;
- if (flags.has(warn)) return util.emojis.warn;
- return util.emojis.cross;
+ if (flags.has(check)) return emojis.check;
+ if (flags.has(warn)) return emojis.warn;
+ return emojis.cross;
};
const botInfo = [
`**Publicity:** ${applicationInfo.bot_public ? 'Public' : 'Private'}`,
- `**Requires Code Grant:** ${applicationInfo.bot_require_code_grant ? util.emojis.check : util.emojis.cross}`,
+ `**Requires Code Grant:** ${applicationInfo.bot_require_code_grant ? emojis.check : emojis.cross}`,
`**Server Members Intent:** ${intent('GatewayGuildMembers', 'GatewayGuildMembersLimited')}`,
`**Presence Intent:** ${intent('GatewayPresence', 'GatewayPresenceLimited')}`,
`**Message Content Intent:** ${intent('GatewayMessageContent', 'GatewayMessageContentLimited')}`
diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts
index 040ed4a..d81d88b 100644
--- a/src/commands/leveling/leaderboard.ts
+++ b/src/commands/leveling/leaderboard.ts
@@ -1,4 +1,15 @@
-import { BushCommand, ButtonPaginator, Level, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ ButtonPaginator,
+ chunk,
+ clientSendAndPermCheck,
+ emojis,
+ Level,
+ prefix,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
@@ -23,7 +34,7 @@ export default class LeaderboardCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -33,9 +44,9 @@ export default class LeaderboardCommand extends BushCommand {
if (!(await message.guild.hasFeature('leveling')))
return await message.util.reply(
- `${util.emojis.error} This command can only be run in servers with the leveling feature enabled.${
+ `${emojis.error} This command can only be run in servers with the leveling feature enabled.${
message.member?.permissions.has(PermissionFlagsBits.ManageGuild)
- ? ` You can toggle features using the \`${util.prefix(message)}features\` command.`
+ ? ` You can toggle features using the \`${prefix(message)}features\` command.`
: ''
}`
);
@@ -44,7 +55,7 @@ export default class LeaderboardCommand extends BushCommand {
const mappedRanks = ranks.map(
(val, index) => `\`${index + 1}\` <@${val.user}> - Level ${val.level} (${val.xp.toLocaleString()} xp)`
);
- const chunked = util.chunk(mappedRanks, 25);
+ const chunked = chunk(mappedRanks, 25);
const embeds = chunked.map((c) =>
new EmbedBuilder().setTitle(`${message.guild.name}'s Leaderboard`).setDescription(c.join('\n'))
);
diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts
index 34a839a..df3e5b2 100644
--- a/src/commands/leveling/level.ts
+++ b/src/commands/leveling/level.ts
@@ -2,7 +2,10 @@ import {
AllowedMentions,
BushCommand,
CanvasProgressBar,
+ clientSendAndPermCheck,
+ emojis,
Level,
+ prefix,
type CommandMessage,
type OptArgType,
type SlashMessage
@@ -39,7 +42,7 @@ export default class LevelCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -49,9 +52,9 @@ export default class LevelCommand extends BushCommand {
if (!(await message.guild.hasFeature('leveling')))
return await message.util.reply(
- `${util.emojis.error} This command can only be run in servers with the leveling feature enabled.${
+ `${emojis.error} This command can only be run in servers with the leveling feature enabled.${
message.member?.permissions.has(PermissionFlagsBits.ManageGuild)
- ? ` You can toggle features using the \`${util.prefix(message)}features\` command.`
+ ? ` You can toggle features using the \`${prefix(message)}features\` command.`
: ''
}`
);
@@ -63,7 +66,7 @@ export default class LevelCommand extends BushCommand {
} catch (e) {
if (e instanceof Error && e.message === 'User does not have a level') {
return await message.util.reply({
- content: `${util.emojis.error} ${user} does not have a level.`,
+ content: `${emojis.error} ${user} does not have a level.`,
allowedMentions: AllowedMentions.none()
});
} else throw e;
diff --git a/src/commands/leveling/levelRoles.ts b/src/commands/leveling/levelRoles.ts
index afa4ab6..470cf58 100644
--- a/src/commands/leveling/levelRoles.ts
+++ b/src/commands/leveling/levelRoles.ts
@@ -1,4 +1,13 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
@@ -33,7 +42,7 @@ export default class LevelRolesCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
userPermissions: [PermissionFlagsBits.ManageGuild, PermissionFlagsBits.ManageRoles]
});
}
@@ -46,20 +55,20 @@ export default class LevelRolesCommand extends BushCommand {
assert(message.member);
if (!(await message.guild.hasFeature('leveling'))) {
- return await reply(`${util.emojis.error} This command can only be run in servers with the leveling feature enabled.`);
+ return await reply(`${emojis.error} This command can only be run in servers with the leveling feature enabled.`);
}
- if (args.level < 1) return await reply(`${util.emojis.error} You cannot set a level role less than **1**.`);
+ if (args.level < 1) return await reply(`${emojis.error} You cannot set a level role less than **1**.`);
if (args.role) {
if (args.role.managed)
- return await reply(`${util.emojis.error} You cannot set <@${args.role.id}> as a level role since it is managed.`);
+ return await reply(`${emojis.error} You cannot set <@${args.role.id}> as a level role since it is managed.`);
else if (args.role.id === message.guild.id)
- return await reply(`${util.emojis.error} You cannot set the @everyone role as a level role.`);
+ return await reply(`${emojis.error} You cannot set the @everyone role as a level role.`);
else if (args.role.comparePositionTo(message.member.roles.highest) >= 0)
- return await reply(`${util.emojis.error} <@${args.role.id}> is higher or equal to your highest role.`);
+ return await reply(`${emojis.error} <@${args.role.id}> is higher or equal to your highest role.`);
else if (args.role.comparePositionTo(message.guild.members.me!.roles.highest) >= 0)
- return await reply(`${util.emojis.error} <@${args.role.id}> is higher or equal to my highest role.`);
+ return await reply(`${emojis.error} <@${args.role.id}> is higher or equal to my highest role.`);
}
const oldRoles = Object.freeze(await message.guild.getSetting('levelRoles'));
@@ -74,17 +83,17 @@ export default class LevelRolesCommand extends BushCommand {
const success = await message.guild.setSetting('levelRoles', newRoles, message.member).catch(() => false);
- if (!success) return await reply(`${util.emojis.error} An error occurred while setting the level roles.`);
+ if (!success) return await reply(`${emojis.error} An error occurred while setting the level roles.`);
if (!oldRoles[args.level] && newRoles[args.level]) {
- return await reply(`${util.emojis.success} The level role for **${args.level}** is now <@&${newRoles[args.level]}>.`);
+ return await reply(`${emojis.success} The level role for **${args.level}** is now <@&${newRoles[args.level]}>.`);
} else if (oldRoles[args.level] && !newRoles[args.level]) {
return await reply(
- `${util.emojis.success} The level role for **${args.level}** was <@&${oldRoles[args.level]}> but is now disabled.`
+ `${emojis.success} The level role for **${args.level}** was <@&${oldRoles[args.level]}> but is now disabled.`
);
} else if (oldRoles[args.level] && newRoles[args.level]) {
return await reply(
- `${util.emojis.success} The level role for **${args.level}** has been updated from <@&${oldRoles[args.level]}> to <@&${
+ `${emojis.success} The level role for **${args.level}** has been updated from <@&${oldRoles[args.level]}> to <@&${
newRoles[args.level]
}>.`
);
diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts
index 8abdb57..b1d9516 100644
--- a/src/commands/leveling/setLevel.ts
+++ b/src/commands/leveling/setLevel.ts
@@ -1,4 +1,14 @@
-import { AllowedMentions, BushCommand, Level, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ Level,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
@@ -30,7 +40,7 @@ export default class SetLevelCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.Administrator]
});
}
@@ -43,9 +53,9 @@ export default class SetLevelCommand extends BushCommand {
assert(user.id);
if (isNaN(level) || !Number.isInteger(level))
- return await message.util.reply(`${util.emojis.error} Provide a valid number to set the user's level to.`);
+ return await message.util.reply(`${emojis.error} Provide a valid number to set the user's level to.`);
if (level > 6553 || level < 0)
- return await message.util.reply(`${util.emojis.error} You cannot set a level higher than **6,553**.`);
+ return await message.util.reply(`${emojis.error} You cannot set a level higher than **6,553**.`);
const [levelEntry] = await Level.findOrBuild({
where: { user: user.id, guild: message.guild.id },
@@ -53,7 +63,7 @@ export default class SetLevelCommand extends BushCommand {
});
await levelEntry.update({ xp: Level.convertLevelToXp(level), user: user.id, guild: message.guild.id });
return await message.util.send({
- content: `Successfully set level of <@${user.id}> to ${util.format.input(level.toLocaleString())} (${util.format.input(
+ content: `Successfully set level of <@${user.id}> to ${format.input(level.toLocaleString())} (${format.input(
levelEntry.xp.toLocaleString()
)} XP)`,
allowedMentions: AllowedMentions.none()
diff --git a/src/commands/leveling/setXp.ts b/src/commands/leveling/setXp.ts
index 60e0b94..96b3ad7 100644
--- a/src/commands/leveling/setXp.ts
+++ b/src/commands/leveling/setXp.ts
@@ -1,4 +1,14 @@
-import { AllowedMentions, BushCommand, Level, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ Level,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
@@ -31,7 +41,7 @@ export default class SetXpCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.Administrator]
});
}
@@ -43,10 +53,10 @@ export default class SetXpCommand extends BushCommand {
assert(message.inGuild());
assert(user.id);
- if (isNaN(xp)) return await message.util.reply(`${util.emojis.error} Provide a valid number.`);
+ if (isNaN(xp)) return await message.util.reply(`${emojis.error} Provide a valid number.`);
if (xp > 2147483647 || xp < 0)
return await message.util.reply(
- `${util.emojis.error} Provide an positive integer under **2,147,483,647** to set the user's xp to.`
+ `${emojis.error} Provide an positive integer under **2,147,483,647** to set the user's xp to.`
);
const [levelEntry] = await Level.findOrBuild({
@@ -57,9 +67,9 @@ export default class SetXpCommand extends BushCommand {
await levelEntry.update({ xp: xp, user: user.id, guild: message.guild.id });
return await message.util.send({
- content: `Successfully set <@${user.id}>'s xp to ${util.format.input(
- levelEntry.xp.toLocaleString()
- )} (level ${util.format.input(Level.convertXpToLevel(levelEntry.xp).toLocaleString())}).`,
+ content: `Successfully set <@${user.id}>'s xp to ${format.input(levelEntry.xp.toLocaleString())} (level ${format.input(
+ Level.convertXpToLevel(levelEntry.xp).toLocaleString()
+ )}).`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/moderation/_activePunishments.ts b/src/commands/moderation/_activePunishments.ts
index 92b4242..80cecf2 100644
--- a/src/commands/moderation/_activePunishments.ts
+++ b/src/commands/moderation/_activePunishments.ts
@@ -37,8 +37,8 @@
// slash: true,
// channel: 'guild',
// hidden: true,
-// clientPermissions: (m) => util.clientSendAndPermCheck(m),
-// userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+// clientPermissions: (m) => clientSendAndPermCheck(m),
+// userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
// });
// }
@@ -66,7 +66,7 @@
// 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.`);
+// return message.util.reply(`${emojis.error} You supplied an invalid case type to filter by.`);
// }
// }
diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts
index f4bd52b..e301fb2 100644
--- a/src/commands/moderation/ban.ts
+++ b/src/commands/moderation/ban.ts
@@ -1,8 +1,13 @@
import {
AllowedMentions,
+ Arg,
banResponse,
BushCommand,
+ castDurationContent,
+ emojis,
+ format,
Moderation,
+ resolveNonCachedUser,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -23,7 +28,7 @@ export default class BanCommand extends BushCommand {
{
id: 'user',
description: 'The user that will be banned.',
- type: util.arg.union('user', 'snowflake'),
+ type: Arg.union('user', 'snowflake'),
readableType: 'user|snowflake',
prompt: 'What user would you like to ban?',
retry: '{error} Choose a valid user to ban.',
@@ -46,7 +51,7 @@ export default class BanCommand extends BushCommand {
match: 'option',
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.',
- type: util.arg.range('integer', 0, 7, true),
+ type: Arg.range('integer', 0, 7, true),
readableType: 'integer [0, 7]',
optional: true,
slashType: ApplicationCommandOptionType.Integer,
@@ -82,12 +87,12 @@ export default class BanCommand extends BushCommand {
assert(message.inGuild());
assert(message.member);
- const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
+ const { duration, content } = await 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 user = member?.user ?? (await resolveNonCachedUser(typeof args.user === 'string' ? args.user : args.user.id));
+ if (!user) return message.util.reply(`${emojis.error} Invalid user.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = member ? await Moderation.permissionCheck(message.member, member, 'ban', true, useForce) : true;
@@ -97,7 +102,7 @@ export default class BanCommand extends BushCommand {
}
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.`);
+ return message.util.reply(`${emojis.error} The delete days must be an integer between 0 and 7.`);
}
const opts = { reason: content, moderator: message.member, duration: duration, deleteDays: args.days };
@@ -105,24 +110,24 @@ export default class BanCommand extends BushCommand {
const responseCode = member ? await member.bushBan(opts) : await message.guild.bushBan({ user, ...opts });
const responseMessage = (): string => {
- const victim = util.format.input(user.tag);
+ const victim = format.input(user.tag);
switch (responseCode) {
case banResponse.ALREADY_BANNED:
- return `${util.emojis.error} ${victim} is already banned.`;
+ return `${emojis.error} ${victim} is already banned.`;
case banResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not ban ${victim} because I am missing the **Ban Members** permission.`;
+ return `${emojis.error} Could not ban ${victim} because I am missing the **Ban Members** permission.`;
case banResponse.ACTION_ERROR:
- return `${util.emojis.error} An error occurred while trying to ban ${victim}.`;
+ return `${emojis.error} An error occurred while trying to ban ${victim}.`;
case banResponse.PUNISHMENT_ENTRY_ADD_ERROR:
- return `${util.emojis.error} While banning ${victim}, there was an error creating a ban entry, please report this to my developers.`;
+ return `${emojis.error} While banning ${victim}, there was an error creating a ban entry, please report this to my developers.`;
case banResponse.MODLOG_ERROR:
- return `${util.emojis.error} While banning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} While banning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
case banResponse.DM_ERROR:
- return `${util.emojis.warn} Banned ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Banned ${victim} however I could not send them a dm.`;
case banResponse.SUCCESS:
- return `${util.emojis.success} Successfully banned ${victim}.`;
+ return `${emojis.success} Successfully banned ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts
index 16beb6f..fc93fb1 100644
--- a/src/commands/moderation/block.ts
+++ b/src/commands/moderation/block.ts
@@ -2,7 +2,12 @@ import {
AllowedMentions,
blockResponse,
BushCommand,
+ castDurationContent,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
+ userGuildPermCheck,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -51,8 +56,8 @@ export default class BlockCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]),
lock: 'channel'
});
}
@@ -70,13 +75,13 @@ export default class BlockCommand extends BushCommand {
assert(message.channel);
if (!message.channel.isTextBased())
- return message.util.send(`${util.emojis.error} This command can only be used in text based channels.`);
+ return message.util.send(`${emojis.error} This command can only be used in text based channels.`);
- const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
+ const { duration, content } = await castDurationContent(args.reason_and_duration, message);
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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'block', true, useForce);
@@ -93,24 +98,24 @@ export default class BlockCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case blockResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not block ${victim} because I am missing the **Manage Channel** permission.`;
+ return `${emojis.error} Could not block ${victim} because I am missing the **Manage Channel** permission.`;
case blockResponse.INVALID_CHANNEL:
- return `${util.emojis.error} Could not block ${victim}, you can only block users in text or thread channels.`;
+ return `${emojis.error} Could not block ${victim}, you can only block users in text or thread channels.`;
case blockResponse.ACTION_ERROR:
- return `${util.emojis.error} An unknown error occurred while trying to block ${victim}.`;
+ return `${emojis.error} An unknown error occurred while trying to block ${victim}.`;
case blockResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case blockResponse.PUNISHMENT_ENTRY_ADD_ERROR:
- return `${util.emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
case blockResponse.DM_ERROR:
- return `${util.emojis.warn} Blocked ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Blocked ${victim} however I could not send them a dm.`;
case blockResponse.SUCCESS:
- return `${util.emojis.success} Successfully blocked ${victim}.`;
+ return `${emojis.success} Successfully blocked ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts
index f1fac0d..3c9e726 100644
--- a/src/commands/moderation/evidence.ts
+++ b/src/commands/moderation/evidence.ts
@@ -1,4 +1,16 @@
-import { BushCommand, ModLog, OptArgType, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ ModLog,
+ OptArgType,
+ regex,
+ userGuildPermCheck,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { ApplicationCommandOptionType, PermissionFlagsBits, type Message } from 'discord.js';
@@ -42,8 +54,8 @@ export default class EvidenceCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -89,18 +101,18 @@ export default class EvidenceCommand extends BushCommand {
assert(message.inGuild());
if (message.interaction && !caseID && !user)
- return message.util.send(`${util.emojis.error} You must provide either a user or a case ID.`);
+ return message.util.send(`${emojis.error} You must provide either a user or a case ID.`);
const entry = messageCommandTarget
- ? util.consts.regex.snowflake.test(messageCommandTarget)
+ ? regex.snowflake.test(messageCommandTarget)
? await ModLog.findOne({ where: { user: messageCommandTarget }, order: [['createdAt', 'DESC']] })
: await ModLog.findByPk(messageCommandTarget)
: caseID
? await ModLog.findByPk(caseID)
: await ModLog.findOne({ where: { user: user!.id }, order: [['createdAt', 'DESC']] });
- 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 || entry.pseudo) return message.util.send(`${emojis.error} Invalid modlog entry.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${emojis.error} This modlog is from another server.`);
const oldEntry = entry.evidence;
@@ -112,14 +124,12 @@ export default class EvidenceCommand extends BushCommand {
client.emit('bushUpdateModlog', message.member!, entry.id, 'evidence', oldEntry, entry.evidence);
- return message.util.reply(
- `${util.emojis.success} Successfully updated the evidence for case ${util.format.input(entry.id)}.`
- );
+ return message.util.reply(`${emojis.success} Successfully updated the evidence for case ${format.input(entry.id)}.`);
}
public static getEvidence(message: CommandMessage | SlashMessage, evidenceArg: OptArgType<'string'>): null | string {
if (evidenceArg && (message as Message).attachments?.size) {
- void message.util.reply(`${util.emojis.error} Please either attach an image or a reason not both.`);
+ void message.util.reply(`${emojis.error} Please either attach an image or a reason not both.`);
return null;
}
@@ -129,7 +139,7 @@ export default class EvidenceCommand extends BushCommand {
? (message as Message).attachments.first()?.url
: undefined;
if (!_evidence) {
- void message.util.reply(`${util.emojis.error} You must provide evidence for this modlog.`);
+ void message.util.reply(`${emojis.error} You must provide evidence for this modlog.`);
return null;
}
diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts
index fc5baf4..0cc3de4 100644
--- a/src/commands/moderation/hideCase.ts
+++ b/src/commands/moderation/hideCase.ts
@@ -1,4 +1,13 @@
-import { BushCommand, ModLog, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ ModLog,
+ userGuildPermCheck,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
@@ -21,8 +30,8 @@ export default class HideCaseCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]),
channel: 'guild'
});
}
@@ -31,8 +40,8 @@ export default class HideCaseCommand extends BushCommand {
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 || entry.pseudo) return message.util.send(`${emojis.error} Invalid entry.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${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;
@@ -40,6 +49,6 @@ export default class HideCaseCommand extends BushCommand {
client.emit('bushUpdateModlog', message.member!, entry.id, 'hidden', oldEntry, entry.hidden);
- return await message.util.reply(`${util.emojis.success} CaseID ${util.format.input(caseID)} is ${action}.`);
+ return await message.util.reply(`${emojis.success} CaseID ${format.input(caseID)} is ${action}.`);
}
}
diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts
index a9a0336..bf079f3 100644
--- a/src/commands/moderation/kick.ts
+++ b/src/commands/moderation/kick.ts
@@ -1,6 +1,9 @@
import {
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
kickResponse,
Moderation,
type ArgType,
@@ -50,7 +53,7 @@ export default class KickCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.KickMembers]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.KickMembers]),
userPermissions: [PermissionFlagsBits.KickMembers]
});
}
@@ -65,7 +68,7 @@ export default class KickCommand extends BushCommand {
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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
const useForce = force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'kick', true, useForce);
@@ -79,20 +82,20 @@ export default class KickCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case kickResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not kick ${victim} because I am missing the **Kick Members** permission.`;
+ return `${emojis.error} Could not kick ${victim} because I am missing the **Kick Members** permission.`;
case kickResponse.ACTION_ERROR:
- return `${util.emojis.error} An error occurred while trying to kick ${victim}.`;
+ return `${emojis.error} An error occurred while trying to kick ${victim}.`;
case kickResponse.MODLOG_ERROR:
- return `${util.emojis.error} While muting ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} While muting ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
case kickResponse.DM_ERROR:
- return `${util.emojis.warn} Kicked ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Kicked ${victim} however I could not send them a dm.`;
case kickResponse.SUCCESS:
- return `${util.emojis.success} Successfully kicked ${victim}.`;
+ return `${emojis.success} Successfully kicked ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/lockdown.ts b/src/commands/moderation/lockdown.ts
index 7d8211c..76d61d0 100644
--- a/src/commands/moderation/lockdown.ts
+++ b/src/commands/moderation/lockdown.ts
@@ -1,7 +1,12 @@
import {
AllowedMentions,
+ Arg,
BushCommand,
+ clientSendAndPermCheck,
+ colors,
ConfirmationPrompt,
+ emojis,
+ format,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -31,7 +36,7 @@ export default class LockdownCommand extends BushCommand {
{
id: 'channel',
description: 'Specify a different channel to lockdown instead of the one you trigger the command in.',
- type: util.arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
+ type: Arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
prompt: 'What channel would you like to lockdown?',
slashType: ApplicationCommandOptionType.Channel,
channelTypes: [
@@ -65,7 +70,7 @@ export default class LockdownCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
userPermissions: [PermissionFlagsBits.ManageChannels],
lock: 'channel'
});
@@ -95,7 +100,7 @@ export default class LockdownCommand extends BushCommand {
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
if (args.channel && args.all)
- return await message.util.reply(`${util.emojis.error} You can't specify a channel and set all to true at the same time.`);
+ return await message.util.reply(`${emojis.error} You can't specify a channel and set all to true at the same time.`);
const channel = args.channel ?? message.channel;
@@ -108,14 +113,14 @@ export default class LockdownCommand extends BushCommand {
)
)
return await message.util.reply(
- `${util.emojis.error} You can only ${action} text channels, news channels, and thread channels.`
+ `${emojis.error} You can only ${action} text channels, news channels, and thread channels.`
);
if (args.all) {
const confirmation = await ConfirmationPrompt.send(message, {
content: `Are you sure you want to ${action} all channels?`
});
- if (!confirmation) return message.util.sendNew(`${util.emojis.error} Lockdown cancelled.`);
+ if (!confirmation) return message.util.sendNew(`${emojis.error} Lockdown cancelled.`);
}
const response = await message.guild.lockdown({
@@ -128,33 +133,33 @@ export default class LockdownCommand extends BushCommand {
if (response instanceof Collection) {
return await message.util.sendNew({
- content: `${util.emojis.error} The following channels failed to ${action}:`,
+ content: `${emojis.error} The following channels failed to ${action}:`,
embeds: [
{
description: response.map((e, c) => `<#${c}> : ${e.message}`).join('\n'),
- color: util.colors.warn
+ color: colors.warn
}
]
});
} else {
let messageResponse;
if (response === 'all not chosen and no channel specified') {
- messageResponse = `${util.emojis.error} You must specify a channel to ${action}.`;
+ messageResponse = `${emojis.error} You must specify a channel to ${action}.`;
} else if (response.startsWith('invalid channel configured: ')) {
const channels = response.replace('invalid channel configured: ', '');
const actionFormatted = `${action.replace('down', '')}ed`;
- messageResponse = `${util.emojis.error} Some of the channels configured to be ${actionFormatted} cannot be resolved: ${channels}}`;
+ messageResponse = `${emojis.error} Some of the channels configured to be ${actionFormatted} cannot be resolved: ${channels}}`;
} else if (response === 'no channels configured') {
- messageResponse = `${util.emojis.error} The all option is selected but there are no channels configured to be locked down.`;
+ messageResponse = `${emojis.error} The all option is selected but there are no channels configured to be locked down.`;
} else if (response === 'moderator not found') {
- messageResponse = `${util.emojis.error} For some reason I could not resolve you?`;
+ messageResponse = `${emojis.error} For some reason I could not resolve you?`;
} else if (response.startsWith('success: ')) {
const num = Number.parseInt(response.replace('success: ', ''));
- messageResponse = `${util.emojis.success} Successfully ${
+ messageResponse = `${emojis.success} Successfully ${
action === 'lockdown' ? 'locked down' : 'unlocked'
} **${num}** channel${num > 0 ? 's' : ''}.`;
} else {
- return `${util.emojis.error} An error occurred: ${util.format.input(response)}}`;
+ return `${emojis.error} An error occurred: ${format.input(response)}}`;
}
assert(messageResponse);
diff --git a/src/commands/moderation/massBan.ts b/src/commands/moderation/massBan.ts
index a25c64f..ab9fbc8 100644
--- a/src/commands/moderation/massBan.ts
+++ b/src/commands/moderation/massBan.ts
@@ -1,7 +1,13 @@
import {
+ Arg,
BanResponse,
banResponse,
BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ overflowEmbed,
+ regex,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -45,7 +51,7 @@ export default class MassBanCommand extends BushCommand {
match: 'option',
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.',
- type: util.arg.range('integer', 0, 7, true),
+ type: Arg.range('integer', 0, 7, true),
optional: true,
slashType: ApplicationCommandOptionType.Integer,
choices: [...Array(8).keys()].map((v) => ({ name: v.toString(), value: v }))
@@ -54,7 +60,7 @@ export default class MassBanCommand extends BushCommand {
quoted: true,
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.BanMembers],
lock: 'user'
});
@@ -69,14 +75,13 @@ export default class MassBanCommand extends BushCommand {
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.`);
+ if (ids.length === 0) return message.util.send(`${emojis.error} You must provide at least one user id.`);
for (const id of ids) {
- if (!client.constants.regex.snowflake.test(id))
- return message.util.send(`${util.emojis.error} ${id} is not a valid snowflake.`);
+ if (!regex.snowflake.test(id)) return message.util.send(`${emojis.error} ${id} is not a valid snowflake.`);
}
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.`);
+ return message.util.reply(`${emojis.error} The delete days must be an integer between 0 and 7.`);
}
const promises = ids.map((id) =>
@@ -99,13 +104,13 @@ export default class MassBanCommand extends BushCommand {
const id = ids[i];
const status = res[i];
const isSuccess = success(status);
- const emoji = isSuccess ? util.emojis.success : util.emojis.error;
+ const emoji = isSuccess ? emojis.success : emojis.error;
return `${emoji} ${id}${isSuccess ? '' : ` - ${status}`}`;
});
- const embeds = util.overflowEmbed(
+ const embeds = overflowEmbed(
{
- color: util.colors.DarkRed,
+ color: colors.DarkRed,
title: 'Mass Ban Results'
},
lines
diff --git a/src/commands/moderation/massEvidence.ts b/src/commands/moderation/massEvidence.ts
index 468d43c..ffe85d2 100644
--- a/src/commands/moderation/massEvidence.ts
+++ b/src/commands/moderation/massEvidence.ts
@@ -1,4 +1,16 @@
-import { BushCommand, ModLog, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ ModLog,
+ overflowEmbed,
+ regex,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
import { EvidenceCommand } from '../index.js';
@@ -37,7 +49,7 @@ export default class MassEvidenceCommand extends BushCommand {
quoted: true,
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.ManageMessages],
lock: 'user'
});
@@ -53,10 +65,9 @@ export default class MassEvidenceCommand extends BushCommand {
if (!evidence) return;
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.`);
+ if (ids.length === 0) return message.util.send(`${emojis.error} You must provide at least one user id.`);
for (const id of ids) {
- if (!client.constants.regex.snowflake.test(id))
- return message.util.send(`${util.emojis.error} ${id} is not a valid snowflake.`);
+ if (!regex.snowflake.test(id)) return message.util.send(`${emojis.error} ${id} is not a valid snowflake.`);
}
const caseMap = (
@@ -78,15 +89,15 @@ export default class MassEvidenceCommand extends BushCommand {
const lines = ids.map((id, i) => {
const case_ = res[i];
- if (!case_) return `${util.emojis.error} ${id} - no case found.`;
- return `${util.emojis.success} ${id} - ${case_.id}`;
+ if (!case_) return `${emojis.error} ${id} - no case found.`;
+ return `${emojis.success} ${id} - ${case_.id}`;
});
client.emit('massEvidence', message.member!, message.guild, evidence, lines);
- const embeds = util.overflowEmbed(
+ const embeds = overflowEmbed(
{
- color: util.colors.DarkRed,
+ color: colors.DarkRed,
title: 'Mass Evidence'
},
lines
diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts
index 71ed975..2c0e33a 100644
--- a/src/commands/moderation/modlog.ts
+++ b/src/commands/moderation/modlog.ts
@@ -1,6 +1,22 @@
-import { BushCommand, ButtonPaginator, ModLog, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ ButtonPaginator,
+ chunk,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ humanizeDuration,
+ ModLog,
+ resolveUserAsync,
+ timestamp,
+ userGuildPermCheck,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
-import { ApplicationCommandOptionType, PermissionFlagsBits, User } from 'discord.js';
+import { ApplicationCommandOptionType, escapeMarkdown, PermissionFlagsBits, User } from 'discord.js';
export default class ModlogCommand extends BushCommand {
public static separator = '\n━━━━━━━━━━━━━━━\n';
@@ -16,7 +32,7 @@ export default class ModlogCommand extends BushCommand {
{
id: 'search',
description: 'The case id or user to search for modlogs by.',
- type: util.arg.union('user', 'string'),
+ type: Arg.union('user', 'string'),
prompt: 'What case id or user would you like to see?',
retry: '{error} Choose a valid case id or user.',
slashType: ApplicationCommandOptionType.String
@@ -34,8 +50,8 @@ export default class ModlogCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -45,7 +61,7 @@ export default class ModlogCommand extends BushCommand {
) {
assert(message.inGuild());
- const foundUser = search instanceof User ? search : await util.resolveUserAsync(search);
+ const foundUser = search instanceof User ? search : await resolveUserAsync(search);
if (foundUser) {
const logs = await ModLog.findAll({
where: {
@@ -59,23 +75,23 @@ export default class ModlogCommand extends BushCommand {
.filter((log) => !(log.hidden && hidden))
.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);
+ return message.util.reply(`${emojis.error} **${foundUser.tag}** does not have any modlogs.`);
+ const chunked: string[][] = chunk(niceLogs, 4);
const embedPages = chunked.map((chunk) => ({
title: `${foundUser.tag}'s Mod Logs`,
description: chunk.join(ModlogCommand.separator),
- color: util.colors.default
+ color: colors.default
}));
return await ButtonPaginator.send(message, embedPages, undefined, true);
} else if (search) {
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.`);
+ return message.util.send(`${emojis.error} That modlog does not exist.`);
+ if (entry.guild !== message.guild.id) return message.util.reply(`${emojis.error} This modlog is from another server.`);
const embed = {
title: `Case ${entry.id}`,
description: ModlogCommand.generateModlogInfo(entry, true),
- color: util.colors.default
+ color: colors.default
};
return await ButtonPaginator.send(message, [embed]);
}
@@ -83,12 +99,12 @@ export default class ModlogCommand extends BushCommand {
public 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()}`];
+ const modLog = [`**Case ID:** ${escapeMarkdown(log.id)}`, `**Type:** ${log.type.toLowerCase()}`];
if (showUser) modLog.push(`**User:** <@!${log.user}>`);
modLog.push(`**Moderator:** <@!${log.moderator}>`);
- if (log.duration) modLog.push(`**Duration:** ${util.humanizeDuration(log.duration)}`);
+ if (log.duration) modLog.push(`**Duration:** ${humanizeDuration(log.duration)}`);
modLog.push(`**Reason:** ${trim(log.reason ?? 'No Reason Specified.')}`);
- modLog.push(`**Date:** ${util.timestamp(log.createdAt)}`);
+ modLog.push(`**Date:** ${timestamp(log.createdAt)}`);
if (log.evidence) modLog.push(`**Evidence:** ${trim(log.evidence)}`);
return modLog.join(`\n`);
}
diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts
index a665670..7ad023a 100644
--- a/src/commands/moderation/mute.ts
+++ b/src/commands/moderation/mute.ts
@@ -1,8 +1,14 @@
import {
AllowedMentions,
BushCommand,
+ castDurationContent,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
muteResponse,
+ prefix,
+ userGuildPermCheck,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -51,8 +57,8 @@ export default class MuteCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -67,11 +73,11 @@ export default class MuteCommand extends BushCommand {
assert(message.inGuild());
assert(message.member);
- const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
+ const { duration, content } = await castDurationContent(args.reason_and_duration, message);
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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'mute', true, useForce);
@@ -87,29 +93,29 @@ export default class MuteCommand extends BushCommand {
});
const responseMessage = (): string => {
- const prefix = util.prefix(message);
- const victim = util.format.input(member.user.tag);
+ const prefix_ = prefix(message);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case muteResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not mute ${victim} because I am missing the **Manage Roles** permission.`;
+ return `${emojis.error} Could not mute ${victim} because I am missing the **Manage Roles** permission.`;
case muteResponse.NO_MUTE_ROLE:
- return `${util.emojis.error} Could not mute ${victim}, you must set a mute role with \`${prefix}config muteRole\`.`;
+ return `${emojis.error} Could not mute ${victim}, you must set a mute role with \`${prefix_}config muteRole\`.`;
case muteResponse.MUTE_ROLE_INVALID:
- return `${util.emojis.error} Could not mute ${victim} because the current mute role no longer exists. Please set a new mute role with \`${prefix}config muteRole\`.`;
+ return `${emojis.error} Could not mute ${victim} because the current mute role no longer exists. Please set a new mute role with \`${prefix_}config muteRole\`.`;
case muteResponse.MUTE_ROLE_NOT_MANAGEABLE:
- return `${util.emojis.error} Could not mute ${victim} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix}config muteRole\`.`;
+ return `${emojis.error} Could not mute ${victim} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix_}config muteRole\`.`;
case muteResponse.ACTION_ERROR:
- return `${util.emojis.error} Could not mute ${victim}, there was an error assigning them the mute role.`;
+ return `${emojis.error} Could not mute ${victim}, there was an error assigning them the mute role.`;
case muteResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case muteResponse.PUNISHMENT_ENTRY_ADD_ERROR:
- return `${util.emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
case muteResponse.DM_ERROR:
- return `${util.emojis.warn} Muted ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Muted ${victim} however I could not send them a dm.`;
case muteResponse.SUCCESS:
- return `${util.emojis.success} Successfully muted ${victim}.`;
+ return `${emojis.success} Successfully muted ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts
index 1652f6f..acf3897 100644
--- a/src/commands/moderation/purge.ts
+++ b/src/commands/moderation/purge.ts
@@ -1,4 +1,13 @@
-import { BushCommand, OptArgType, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ OptArgType,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, Collection, PermissionFlagsBits, type Message } from 'discord.js';
@@ -14,7 +23,7 @@ export default class PurgeCommand extends BushCommand {
{
id: 'amount',
description: 'The amount of messages to purge.',
- type: util.arg.range('integer', 1, 100, true),
+ type: Arg.range('integer', 1, 100, true),
readableType: 'integer',
prompt: 'How many messages would you like to purge?',
retry: '{error} Please pick a number between 1 and 100.',
@@ -43,7 +52,7 @@ export default class PurgeCommand extends BushCommand {
],
slash: true,
clientPermissions: (m) =>
- util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true),
+ clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true),
userPermissions: [PermissionFlagsBits.ManageMessages],
channel: 'guild'
});
@@ -55,7 +64,7 @@ export default class PurgeCommand extends BushCommand {
) {
assert(message.inGuild());
- if (args.amount > 100 || args.amount < 1) return message.util.reply(`${util.emojis.error} `);
+ if (args.amount > 100 || args.amount < 1) return message.util.reply(`${emojis.error} `);
const messageFilter = (filterMessage: Message): boolean => {
const shouldFilter: boolean[] = [];
@@ -72,13 +81,13 @@ export default class PurgeCommand extends BushCommand {
);
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);
+ if (!purged) return message.util.reply(`${emojis.error} Failed to purge messages.`).catch(() => null);
else {
client.emit('bushPurge', message.author, message.guild, message.channel!, messages);
- await message.util.send(`${util.emojis.success} Successfully purged **${purged.size}** messages.`);
+ await message.util.send(`${emojis.success} Successfully purged **${purged.size}** messages.`);
/* .then(async (purgeMessage) => {
if (!message.util.isSlashMessage(message)) {
- await util.sleep(5);
+ await sleep(5);
await purgeMessage.delete().catch(() => {});
}
}); */
diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts
index 4359c5b..a088287 100644
--- a/src/commands/moderation/removeReactionEmoji.ts
+++ b/src/commands/moderation/removeReactionEmoji.ts
@@ -1,4 +1,13 @@
-import { BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, Message, PermissionFlagsBits } from 'discord.js';
@@ -14,7 +23,7 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
{
id: 'message',
description: 'The message to remove all the reactions of a certain emoji from.',
- type: util.arg.union('message', 'messageLink'),
+ type: Arg.union('message', 'messageLink'),
readableType: 'message|messageLink',
prompt: 'What message would you like to remove a reaction from?',
retry: '{error} Please pick a valid message.',
@@ -23,7 +32,7 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
{
id: 'emoji',
description: 'The emoji to remove all the reactions of from a message.',
- type: util.arg.union('emoji', 'snowflake'),
+ type: Arg.union('emoji', 'snowflake'),
readableType: 'emoji|snowflake',
match: 'restContent',
prompt: 'What emoji would you like to remove?',
@@ -34,7 +43,7 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
slash: true,
channel: 'guild',
clientPermissions: (m) =>
- util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true),
+ clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true),
userPermissions: [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.ManageEmojisAndStickers] // Can't undo the removal of 1000s of reactions
});
}
@@ -54,15 +63,15 @@ export default class RemoveReactionEmojiCommand extends BushCommand {
if (success) {
return await message.util.reply(
- `${util.emojis.success} Removed all reactions of ${util.format.input(
- emojiID!
- )} from the message with the id of ${util.format.input(resolvedMessage.id)}.`
+ `${emojis.success} Removed all reactions of ${format.input(emojiID!)} from the message with the id of ${format.input(
+ resolvedMessage.id
+ )}.`
);
} else {
return await message.util.reply(
- `${util.emojis.error} There was an error removing all reactions of ${util.format.input(
+ `${emojis.error} There was an error removing all reactions of ${format.input(
emojiID!
- )} from the message with the id of ${util.format.input(resolvedMessage.id)}.`
+ )} from the message with the id of ${format.input(resolvedMessage.id)}.`
);
}
}
diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts
index b9e1490..6febaa6 100644
--- a/src/commands/moderation/role.ts
+++ b/src/commands/moderation/role.ts
@@ -2,6 +2,11 @@ import {
addRoleResponse,
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ humanizeDuration,
+ mappings,
removeRoleResponse,
type ArgType,
type CommandMessage,
@@ -63,7 +68,7 @@ export default class RoleCommand extends BushCommand {
flags: ['--force'],
typing: true,
clientPermissions: (m) =>
- util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles, PermissionFlagsBits.EmbedLinks], true),
+ clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles, PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -130,14 +135,13 @@ export default class RoleCommand extends BushCommand {
}
) {
assert(message.inGuild());
- if (!args.role) return await message.util.reply(`${util.emojis.error} You must specify a role.`);
+ if (!args.role) return await message.util.reply(`${emojis.error} You must specify a role.`);
args.duration ??= 0;
if (
!message.member!.permissions.has(PermissionFlagsBits.ManageRoles) &&
message.member!.id !== message.guild?.ownerId &&
!message.member!.user.isOwner()
) {
- const mappings = client.consts.mappings;
let mappedRole: { name: string; id: string };
for (let i = 0; i < mappings.roleMap.length; i++) {
const a = mappings.roleMap[i];
@@ -145,7 +149,7 @@ export default class RoleCommand extends BushCommand {
}
if (!mappedRole! || !(mappedRole.name in mappings.roleWhitelist)) {
return await message.util.reply({
- content: `${util.emojis.error} <@&${args.role.id}> is not whitelisted, and you do not have manage roles permission.`,
+ content: `${emojis.error} <@&${args.role.id}> is not whitelisted, and you do not have manage roles permission.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -157,7 +161,7 @@ export default class RoleCommand extends BushCommand {
});
if (!message.member!.roles.cache.some((role) => (allowedRoles as Snowflake[]).includes(role.id))) {
return await message.util.reply({
- content: `${util.emojis.error} <@&${args.role.id}> is whitelisted, but you do not have any of the roles required to manage it.`,
+ content: `${emojis.error} <@&${args.role.id}> is whitelisted, but you do not have any of the roles required to manage it.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -173,33 +177,33 @@ export default class RoleCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(args.member.user.tag);
+ const victim = format.input(args.member.user.tag);
switch (responseCode) {
case addRoleResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} I don't have the **Manage Roles** permission.`;
+ return `${emojis.error} I don't have the **Manage Roles** permission.`;
case addRoleResponse.USER_HIERARCHY:
- return `${util.emojis.error} <@&${args.role.id}> is higher or equal to your highest role.`;
+ return `${emojis.error} <@&${args.role.id}> is higher or equal to your highest role.`;
case addRoleResponse.ROLE_MANAGED:
- return `${util.emojis.error} <@&${args.role.id}> is managed by an integration and cannot be managed.`;
+ return `${emojis.error} <@&${args.role.id}> is managed by an integration and cannot be managed.`;
case addRoleResponse.CLIENT_HIERARCHY:
- return `${util.emojis.error} <@&${args.role.id}> is higher or equal to my highest role.`;
+ return `${emojis.error} <@&${args.role.id}> is higher or equal to my highest role.`;
case addRoleResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case addRoleResponse.PUNISHMENT_ENTRY_ADD_ERROR:
case removeRoleResponse.PUNISHMENT_ENTRY_REMOVE_ERROR:
- return `${util.emojis.error} There was an error ${
+ return `${emojis.error} There was an error ${
args.action === 'add' ? 'creating' : 'removing'
} a punishment entry, please report this to my developers.`;
case addRoleResponse.ACTION_ERROR:
- return `${util.emojis.error} An error occurred while trying to ${args.action} <@&${args.role.id}> ${
+ return `${emojis.error} An error occurred while trying to ${args.action} <@&${args.role.id}> ${
args.action === 'add' ? 'to' : 'from'
} ${victim}.`;
case addRoleResponse.SUCCESS:
- return `${util.emojis.success} Successfully ${args.action === 'add' ? 'added' : 'removed'} <@&${args.role.id}> ${
+ return `${emojis.success} Successfully ${args.action === 'add' ? 'added' : 'removed'} <@&${args.role.id}> ${
args.action === 'add' ? 'to' : 'from'
- } ${victim}${args.duration ? ` for ${util.humanizeDuration(args.duration)}` : ''}.`;
+ } ${victim}${args.duration ? ` for ${humanizeDuration(args.duration)}` : ''}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts
index e657b76..641f88e 100644
--- a/src/commands/moderation/slowmode.ts
+++ b/src/commands/moderation/slowmode.ts
@@ -1,4 +1,15 @@
-import { BushCommand, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ humanizeDuration,
+ userGuildPermCheck,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { Argument } from 'discord-akairo';
import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
@@ -36,8 +47,8 @@ export default class SlowmodeCommand extends BushCommand {
slash: true,
channel: 'guild',
clientPermissions: (m) =>
- util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels, PermissionFlagsBits.EmbedLinks], true),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels, PermissionFlagsBits.EmbedLinks], true),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -58,11 +69,11 @@ export default class SlowmodeCommand extends BushCommand {
args.channel.type !== ChannelType.GuildVoice &&
!args.channel.isThread()
)
- return await message.util.reply(`${util.emojis.error} <#${args.channel.id}> is not a text or thread channel.`);
+ return await message.util.reply(`${emojis.error} <#${args.channel.id}> is not a text or thread channel.`);
args.length =
typeof args.length === 'string' && !(['off', 'none', 'disable'] as const).includes(args.length)
- ? await util.arg.cast('duration', message, args.length)
+ ? await Arg.cast('duration', message, args.length)
: args.length;
const length2: number = (['off', 'none', 'disable'] as const).includes(args.length) || args.length === null ? 0 : args.length;
@@ -71,11 +82,11 @@ export default class SlowmodeCommand extends BushCommand {
.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 <#${args.channel.id}>.`);
+ return await message.util.reply(`${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 <#${args.channel.id}> ${
- length2 ? `to ${util.format.input(util.humanizeDuration(length2))}` : '**off**'
+ `${emojis.success} Successfully changed the slowmode of <#${args.channel.id}> ${
+ length2 ? `to ${format.input(humanizeDuration(length2))}` : '**off**'
}.`
);
}
diff --git a/src/commands/moderation/timeout.ts b/src/commands/moderation/timeout.ts
index ed3562d..7be8ecb 100644
--- a/src/commands/moderation/timeout.ts
+++ b/src/commands/moderation/timeout.ts
@@ -1,6 +1,10 @@
import {
AllowedMentions,
BushCommand,
+ castDurationContent,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
timeoutResponse,
type ArgType,
@@ -49,7 +53,7 @@ export default class TimeoutCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]),
userPermissions: [PermissionFlagsBits.ModerateMembers]
});
}
@@ -61,12 +65,12 @@ export default class TimeoutCommand extends BushCommand {
assert(message.inGuild());
assert(message.member);
- const { duration, content } = await util.castDurationContent(args.reason_and_duration, message);
+ const { duration, content } = await castDurationContent(args.reason_and_duration, message);
- if (!duration) return await message.util.reply(`${util.emojis.error} You must specify a duration for timeouts.`);
+ if (!duration) return await message.util.reply(`${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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'timeout', true, useForce);
@@ -82,22 +86,22 @@ export default class TimeoutCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case timeoutResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not timeout ${victim} because I am missing the **Timeout Members** permission.`;
+ return `${emojis.error} Could not timeout ${victim} because I am missing the **Timeout Members** permission.`;
case timeoutResponse.INVALID_DURATION:
- return `${util.emojis.error} The duration you specified is too long, the longest you can timeout someone for is 28 days.`;
+ return `${emojis.error} The duration you specified is too long, the longest you can timeout someone for is 28 days.`;
case timeoutResponse.ACTION_ERROR:
- return `${util.emojis.error} An unknown error occurred while trying to timeout ${victim}.`;
+ return `${emojis.error} An unknown error occurred while trying to timeout ${victim}.`;
case timeoutResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case timeoutResponse.DM_ERROR:
- return `${util.emojis.warn} Timed out ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Timed out ${victim} however I could not send them a dm.`;
case timeoutResponse.SUCCESS:
- return `${util.emojis.success} Successfully timed out ${victim}.`;
+ return `${emojis.success} Successfully timed out ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts
index d7549ab..a4c4992 100644
--- a/src/commands/moderation/unban.ts
+++ b/src/commands/moderation/unban.ts
@@ -1,6 +1,9 @@
import {
AllowedMentions,
+ Arg,
BushCommand,
+ emojis,
+ format,
unbanResponse,
type ArgType,
type CommandMessage,
@@ -22,7 +25,7 @@ export default class UnbanCommand extends BushCommand {
{
id: 'user',
description: 'The user to unban.',
- type: util.arg.union('user', 'globalUser'),
+ type: Arg.union('user', 'globalUser'),
prompt: 'What user would you like to unban?',
retry: '{error} Choose a valid user to unban.',
slashType: ApplicationCommandOptionType.User
@@ -58,23 +61,23 @@ export default class UnbanCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(user.tag);
+ const victim = format.input(user.tag);
switch (responseCode) {
case unbanResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not unban ${victim} because I am missing the **Ban Members** permission.`;
+ return `${emojis.error} Could not unban ${victim} because I am missing the **Ban Members** permission.`;
case unbanResponse.ACTION_ERROR:
- return `${util.emojis.error} An error occurred while trying to unban ${victim}.`;
+ return `${emojis.error} An error occurred while trying to unban ${victim}.`;
case unbanResponse.PUNISHMENT_ENTRY_REMOVE_ERROR:
- return `${util.emojis.error} While unbanning ${victim}, there was an error removing their ban entry, please report this to my developers.`;
+ return `${emojis.error} While unbanning ${victim}, there was an error removing their ban entry, please report this to my developers.`;
case unbanResponse.MODLOG_ERROR:
- return `${util.emojis.error} While unbanning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} While unbanning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
case unbanResponse.NOT_BANNED:
- return `${util.emojis.warn} ${victim} is not banned but I tried to unban them anyways.`;
+ return `${emojis.warn} ${victim} is not banned but I tried to unban them anyways.`;
case unbanResponse.DM_ERROR:
case unbanResponse.SUCCESS:
- return `${util.emojis.success} Successfully unbanned ${victim}.`;
+ return `${emojis.success} Successfully unbanned ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts
index 886d546..09ec281 100644
--- a/src/commands/moderation/unblock.ts
+++ b/src/commands/moderation/unblock.ts
@@ -1,8 +1,12 @@
import {
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
unblockResponse,
+ userGuildPermCheck,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -51,8 +55,8 @@ export default class UnblockCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -65,11 +69,11 @@ export default class UnblockCommand extends BushCommand {
assert(message.channel);
if (!message.channel.isTextBased())
- return message.util.send(`${util.emojis.error} This command can only be used in text based channels.`);
+ return message.util.send(`${emojis.error} This command can only be used in text based channels.`);
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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'unblock', true, useForce);
@@ -85,24 +89,24 @@ export default class UnblockCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case unblockResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not unblock ${victim} because I am missing the **Manage Channel** permission.`;
+ return `${emojis.error} Could not unblock ${victim} because I am missing the **Manage Channel** permission.`;
case unblockResponse.INVALID_CHANNEL:
- return `${util.emojis.error} Could not unblock ${victim}, you can only unblock users in text or thread channels.`;
+ return `${emojis.error} Could not unblock ${victim}, you can only unblock users in text or thread channels.`;
case unblockResponse.ACTION_ERROR:
- return `${util.emojis.error} An unknown error occurred while trying to unblock ${victim}.`;
+ return `${emojis.error} An unknown error occurred while trying to unblock ${victim}.`;
case unblockResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case unblockResponse.PUNISHMENT_ENTRY_REMOVE_ERROR:
- return `${util.emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
case unblockResponse.DM_ERROR:
- return `${util.emojis.warn} Unblocked ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} Unblocked ${victim} however I could not send them a dm.`;
case unblockResponse.SUCCESS:
- return `${util.emojis.success} Successfully unblocked ${victim}.`;
+ return `${emojis.success} Successfully unblocked ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/unlockdown.ts b/src/commands/moderation/unlockdown.ts
index dbcd429..db1a09d 100644
--- a/src/commands/moderation/unlockdown.ts
+++ b/src/commands/moderation/unlockdown.ts
@@ -1,5 +1,13 @@
import { LockdownCommand } from '#commands';
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
export default class UnlockdownCommand extends BushCommand {
@@ -14,7 +22,7 @@ export default class UnlockdownCommand extends BushCommand {
{
id: 'channel',
description: 'Specify a different channel to unlockdown instead of the one you trigger the command in.',
- type: util.arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
+ type: Arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
prompt: 'What channel would you like to unlockdown?',
slashType: ApplicationCommandOptionType.Channel,
channelTypes: [
@@ -48,7 +56,7 @@ export default class UnlockdownCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]),
userPermissions: [PermissionFlagsBits.ManageChannels]
});
}
diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts
index 202e341..9ac13ce 100644
--- a/src/commands/moderation/unmute.ts
+++ b/src/commands/moderation/unmute.ts
@@ -1,8 +1,13 @@
import {
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
+ prefix,
unmuteResponse,
+ userGuildPermCheck,
type ArgType,
type CommandMessage,
type OptArgType,
@@ -51,8 +56,8 @@ export default class UnmuteCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -63,7 +68,7 @@ export default class UnmuteCommand extends BushCommand {
assert(message.inGuild());
assert(message.member);
- const error = util.emojis.error;
+ const error = emojis.error;
const member = message.guild.members.cache.get(user.id)!;
const useForce = force && message.author.isOwner();
@@ -79,17 +84,17 @@ export default class UnmuteCommand extends BushCommand {
});
const responseMessage = (): string => {
- const prefix = util.prefix(message);
- const victim = util.format.input(member.user.tag);
+ const prefix_ = prefix(message);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case unmuteResponse.MISSING_PERMISSIONS:
return `${error} Could not unmute ${victim} because I am missing the **Manage Roles** permission.`;
case unmuteResponse.NO_MUTE_ROLE:
- return `${error} Could not unmute ${victim}, you must set a mute role with \`${prefix}config muteRole\`.`;
+ return `${error} Could not unmute ${victim}, you must set a mute role with \`${prefix_}config muteRole\`.`;
case unmuteResponse.MUTE_ROLE_INVALID:
- return `${error} Could not unmute ${victim} because the current mute role no longer exists. Please set a new mute role with \`${prefix}config muteRole\`.`;
+ return `${error} Could not unmute ${victim} because the current mute role no longer exists. Please set a new mute role with \`${prefix_}config muteRole\`.`;
case unmuteResponse.MUTE_ROLE_NOT_MANAGEABLE:
- return `${error} Could not unmute ${victim} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix}config muteRole\`.`;
+ return `${error} Could not unmute ${victim} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix_}config muteRole\`.`;
case unmuteResponse.ACTION_ERROR:
return `${error} Could not unmute ${victim}, there was an error removing their mute role.`;
case unmuteResponse.MODLOG_ERROR:
@@ -97,11 +102,11 @@ export default class UnmuteCommand extends BushCommand {
case unmuteResponse.PUNISHMENT_ENTRY_REMOVE_ERROR:
return `${error} While muting ${victim}, there was an error removing their mute entry, please report this to my developers.`;
case unmuteResponse.DM_ERROR:
- return `${util.emojis.warn} unmuted ${victim} however I could not send them a dm.`;
+ return `${emojis.warn} unmuted ${victim} however I could not send them a dm.`;
case unmuteResponse.SUCCESS:
- return `${util.emojis.success} Successfully unmuted ${victim}.`;
+ return `${emojis.success} Successfully unmuted ${victim}.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/untimeout.ts b/src/commands/moderation/untimeout.ts
index 7622f29..c6860c5 100644
--- a/src/commands/moderation/untimeout.ts
+++ b/src/commands/moderation/untimeout.ts
@@ -1,6 +1,9 @@
import {
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
removeTimeoutResponse,
type ArgType,
@@ -51,7 +54,7 @@ export default class UntimeoutCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]),
userPermissions: [PermissionFlagsBits.ModerateMembers]
});
}
@@ -65,9 +68,9 @@ export default class UntimeoutCommand extends BushCommand {
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.`);
+ return await message.util.reply(`${emojis.error} The user you selected is not in the server or is not a valid user.`);
- if (!member.isCommunicationDisabled()) return message.util.reply(`${util.emojis.error} That user is not timed out.`);
+ if (!member.isCommunicationDisabled()) return message.util.reply(`${emojis.error} That user is not timed out.`);
const useForce = args.force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'timeout', true, useForce);
@@ -82,20 +85,20 @@ export default class UntimeoutCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (responseCode) {
case removeTimeoutResponse.MISSING_PERMISSIONS:
- return `${util.emojis.error} Could not untimeout ${victim} because I am missing the **Timeout Members** permission.`;
+ return `${emojis.error} Could not untimeout ${victim} because I am missing the **Timeout Members** permission.`;
case removeTimeoutResponse.ACTION_ERROR:
- return `${util.emojis.error} An unknown error occurred while trying to timeout ${victim}.`;
+ return `${emojis.error} An unknown error occurred while trying to timeout ${victim}.`;
case removeTimeoutResponse.MODLOG_ERROR:
- return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
case removeTimeoutResponse.DM_ERROR:
- return `${util.emojis.warn} Removed ${victim}'s timeout however I could not send them a dm.`;
+ return `${emojis.warn} Removed ${victim}'s timeout however I could not send them a dm.`;
case removeTimeoutResponse.SUCCESS:
- return `${util.emojis.success} Successfully removed ${victim}'s timeout.`;
+ return `${emojis.success} Successfully removed ${victim}'s timeout.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(responseCode)}}`;
+ return `${emojis.error} An error occurred: ${format.input(responseCode)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts
index b3bf965..81b2937 100644
--- a/src/commands/moderation/warn.ts
+++ b/src/commands/moderation/warn.ts
@@ -1,7 +1,12 @@
import {
AllowedMentions,
BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
Moderation,
+ ordinal,
+ userGuildPermCheck,
warnResponse,
type ArgType,
type CommandMessage,
@@ -50,8 +55,8 @@ export default class WarnCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
- userPermissions: (m) => util.userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages])
});
}
@@ -63,7 +68,7 @@ export default class WarnCommand extends BushCommand {
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.`);
+ if (!member) return message.util.reply(`${emojis.error} I cannot warn users that are not in the server.`);
const useForce = force && message.author.isOwner();
const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'warn', true, useForce);
@@ -77,19 +82,19 @@ export default class WarnCommand extends BushCommand {
});
const responseMessage = (): string => {
- const victim = util.format.input(member.user.tag);
+ const victim = format.input(member.user.tag);
switch (response) {
case warnResponse.MODLOG_ERROR:
- return `${util.emojis.error} While warning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
+ return `${emojis.error} While warning ${victim}, there was an error creating a modlog entry, please report this to my developers.`;
case warnResponse.ACTION_ERROR:
case warnResponse.DM_ERROR:
- return `${util.emojis.warn} ${victim} has been warned for the ${util.ordinal(
+ return `${emojis.warn} ${victim} has been warned for the ${ordinal(
caseNum ?? 0
)} time, however I could not send them a dm.`;
case warnResponse.SUCCESS:
- return `${util.emojis.success} Successfully warned ${victim} for the ${util.ordinal(caseNum ?? 0)} time.`;
+ return `${emojis.success} Successfully warned ${victim} for the ${ordinal(caseNum ?? 0)} time.`;
default:
- return `${util.emojis.error} An error occurred: ${util.format.input(response)}}`;
+ return `${emojis.error} An error occurred: ${format.input(response)}}`;
}
};
return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
diff --git a/src/commands/moulberry-bush/capePermissions.ts b/src/commands/moulberry-bush/capePermissions.ts
index 5f15d9e..3ad9602 100644
--- a/src/commands/moulberry-bush/capePermissions.ts
+++ b/src/commands/moulberry-bush/capePermissions.ts
@@ -1,4 +1,15 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ format,
+ mcUUID,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import got from 'got';
@@ -21,7 +32,7 @@ export default class CapePermissionsCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
channel: 'guild'
});
@@ -30,10 +41,10 @@ export default class CapePermissionsCommand extends BushCommand {
public override async exec(message: CommandMessage | SlashMessage, args: { ign: ArgType<'string'> }) {
let capePerms: CapePerms | null, uuid: string;
try {
- uuid = await util.mcUUID(args.ign);
+ uuid = await mcUUID(args.ign);
} catch (e) {
return await message.util.reply({
- content: `${util.emojis.error} ${util.format.input(args.ign)} doesn't appear to be a valid username.`,
+ content: `${emojis.error} ${format.input(args.ign)} doesn't appear to be a valid username.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -44,9 +55,7 @@ export default class CapePermissionsCommand extends BushCommand {
capePerms = null;
}
if (capePerms == null) {
- return await message.util.reply(
- `${util.emojis.error} There was an error finding cape perms for ${util.format.input(args.ign)}.`
- );
+ return await message.util.reply(`${emojis.error} There was an error finding cape perms for ${format.input(args.ign)}.`);
} else {
if (capePerms?.perms) {
let index = null;
@@ -59,17 +68,15 @@ export default class CapePermissionsCommand extends BushCommand {
continue;
}
if (index == null)
- return await message.util.reply(
- `${util.emojis.error} ${util.format.input(args.ign)} does not appear to have any capes.`
- );
+ return await message.util.reply(`${emojis.error} ${format.input(args.ign)} does not appear to have any capes.`);
const userPerm: string[] = capePerms.perms[index].perms;
const embed = new EmbedBuilder()
.setTitle(`${args.ign}'s Capes`)
.setDescription(userPerm.join('\n'))
- .setColor(util.colors.default);
+ .setColor(colors.default);
await message.util.reply({ embeds: [embed] });
} else {
- return await message.util.reply(`${util.emojis.error} There was an error finding cape perms for ${args.ign}.`);
+ return await message.util.reply(`${emojis.error} There was an error finding cape perms for ${args.ign}.`);
}
}
}
diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts
index 6bf7854..c2dae4d 100644
--- a/src/commands/moulberry-bush/capes.ts
+++ b/src/commands/moulberry-bush/capes.ts
@@ -2,7 +2,12 @@ import {
AllowedMentions,
BushCommand,
ButtonPaginator,
+ clientSendAndPermCheck,
+ colors,
DeleteButton,
+ emojis,
+ format,
+ mappings,
type CommandMessage,
type OptArgType,
type SlashMessage
@@ -36,7 +41,7 @@ export default class CapesCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -53,11 +58,11 @@ export default class CapesCommand extends BushCommand {
.filter((f) => f.match !== null);
const capes: { name: string; url: string; index: number; purchasable?: boolean }[] = [
- ...client.consts.mappings.capes
+ ...mappings.capes
.filter((c) => !rawCapes.some((gitCape) => gitCape.match!.groups!.name === c.name) && c.custom)
.map((c) => ({ name: c.name, url: c.custom!, index: c.index, purchasable: c.purchasable })),
...rawCapes.map((c) => {
- const mapCape = client.consts.mappings.capes.find((a) => a.name === c.match!.groups!.name);
+ const mapCape = mappings.capes.find((a) => a.name === c.match!.groups!.name);
const url = mapCape?.custom ?? `https://github.com/Moulberry/NotEnoughUpdates/raw/master/${c.f.path}`;
const index = mapCape?.index !== undefined ? mapCape.index : null;
return { name: c.match!.groups!.name, url, index: index!, purchasable: mapCape?.purchasable };
@@ -76,7 +81,7 @@ export default class CapesCommand extends BushCommand {
await DeleteButton.send(message, { embeds: [embed] });
} else {
await message.util.reply({
- content: `${util.emojis.error} Cannot find a cape called ${util.format.input(args.cape)}.`,
+ content: `${emojis.error} Cannot find a cape called ${format.input(args.cape)}.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -89,7 +94,7 @@ export default class CapesCommand extends BushCommand {
private makeEmbed(cape: { name: string; url: string; index: number; purchasable?: boolean | undefined }): APIEmbed {
return {
title: `${cape.name} cape`,
- color: util.colors.default,
+ color: colors.default,
timestamp: new Date().toISOString(),
image: { url: cape.url },
description: cape.purchasable
@@ -99,7 +104,7 @@ export default class CapesCommand extends BushCommand {
}
public override autocomplete(interaction: AutocompleteInteraction) {
- const capes = client.consts.mappings.capes.map((v) => v.name);
+ const capes = mappings.capes.map((v) => v.name);
const fuzzy = new Fuse(capes, {
threshold: 0.5,
diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts
index 23a6a20..0cadd6a 100644
--- a/src/commands/moulberry-bush/giveawayPing.ts
+++ b/src/commands/moulberry-bush/giveawayPing.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushCommand, type CommandMessage } from '#lib';
+import { AllowedMentions, BushCommand, clientSendAndPermCheck, emojis, type CommandMessage } from '#lib';
import { PermissionFlagsBits } from 'discord.js';
export default class GiveawayPingCommand extends BushCommand {
@@ -9,7 +9,7 @@ export default class GiveawayPingCommand extends BushCommand {
description: 'Pings the giveaway role.',
usage: ['giveaway-ping'],
examples: ['giveaway-ping'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages], true),
userPermissions: [
PermissionFlagsBits.ManageGuild,
PermissionFlagsBits.ManageMessages,
@@ -30,7 +30,7 @@ export default class GiveawayPingCommand extends BushCommand {
public override async exec(message: CommandMessage) {
if (!message.member!.permissions.has(PermissionFlagsBits.ManageGuild) && !message.member!.user.isOwner())
- await message.util.reply(`${util.emojis.error} You are missing the **ManageGuild** permission.`);
+ await message.util.reply(`${emojis.error} You are missing the **ManageGuild** permission.`);
await message.delete().catch(() => {});
diff --git a/src/commands/moulberry-bush/moulHammer.ts b/src/commands/moulberry-bush/moulHammer.ts
index f07511a..0eeb769 100644
--- a/src/commands/moulberry-bush/moulHammer.ts
+++ b/src/commands/moulberry-bush/moulHammer.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, colors, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
@@ -24,7 +24,7 @@ export default class MoulHammerCommand extends BushCommand {
channel: 'guild',
slashGuilds: ['516977525906341928'],
restrictedGuilds: ['516977525906341928'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -37,7 +37,7 @@ export default class MoulHammerCommand extends BushCommand {
const embed = new EmbedBuilder()
.setTitle('L')
.setDescription(`${user.username} got moul'ed <:wideberry1:756223352598691942><:wideberry2:756223336832303154>`)
- .setColor(util.colors.purple);
+ .setColor(colors.purple);
await message.util.send({ embeds: [embed] });
}
}
diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts
index 29eee76..06c1ad2 100644
--- a/src/commands/moulberry-bush/report.ts
+++ b/src/commands/moulberry-bush/report.ts
@@ -1,4 +1,13 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ timestampAndDelta,
+ type ArgType,
+ type CommandMessage
+} from '#lib';
import { stripIndent } from '#tags';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
@@ -32,7 +41,7 @@ export default class ReportCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
channel: 'guild'
});
@@ -42,23 +51,21 @@ export default class ReportCommand extends BushCommand {
assert(message.inGuild());
if (!(await message.guild.hasFeature('reporting')))
- return await message.util.reply(
- `${util.emojis.error} This command can only be used in servers where reporting is enabled.`
- );
+ return await message.util.reply(`${emojis.error} This command can only be used in servers where reporting is enabled.`);
- if (!member) return await message.util.reply(`${util.emojis.error} Choose someone to report`);
+ if (!member) return await message.util.reply(`${emojis.error} Choose someone to report`);
if (member.user.id === '322862723090219008')
return await message.util.reply({
content: `Thank you for your report! We take these allegations very seriously and have reported <@${member.user.id}> to the FBI!`,
allowedMentions: AllowedMentions.none()
});
if (member.user.bot)
- return await message.util.reply(`${util.emojis.error} You cannot report a bot <:WeirdChamp:756283321301860382>.`);
+ return await message.util.reply(`${emojis.error} You cannot report a bot <:WeirdChamp:756283321301860382>.`);
const reportChannel = await message.guild.getLogChannel('report');
if (!reportChannel)
return await message.util.reply(
- `${util.emojis.error} This server has not setup a report logging channel or the channel no longer exists.`
+ `${emojis.error} This server has not setup a report logging channel or the channel no longer exists.`
);
//The formatting of the report is mostly copied from carl since it is pretty good when it actually works
@@ -70,24 +77,24 @@ export default class ReportCommand extends BushCommand {
iconURL: message.author.avatarURL() ?? undefined
})
.setTitle('New Report')
- .setColor(util.colors.red)
+ .setColor(colors.red)
.setDescription(evidence)
.addFields([
{
name: 'Reporter',
value: stripIndent`
**Name:**${message.author.tag} <@${message.author.id}>
- **Joined:** $${util.timestampAndDelta(message.member!.joinedAt!)}
- **Created:** ${util.timestampAndDelta(message.author.createdAt)}
+ **Joined:** $${timestampAndDelta(message.member!.joinedAt!)}
+ **Created:** ${timestampAndDelta(message.author.createdAt)}
**Sent From**: <#${message.channel.id}> [Jump to context](${message.url})`,
inline: true
},
{
name: 'Reported User',
value: stripIndent`
- **Name:**${member.user.tag} <@${member.user.id}>
- **Joined:** $${util.timestampAndDelta(member.joinedAt!)}
- **Created:** ${util.timestampAndDelta(member.user.createdAt)}`,
+ **Name:** ${member.user.tag} <@${member.user.id}>
+ **Joined:** ${timestampAndDelta(member.joinedAt!)}
+ **Created:** ${timestampAndDelta(member.user.createdAt)}`,
inline: true
}
]);
@@ -102,8 +109,8 @@ export default class ReportCommand extends BushCommand {
}
await reportChannel.send({ embeds: [reportEmbed] }).then(async (ReportMessage) => {
try {
- await ReportMessage.react(util.emojis.check);
- await ReportMessage.react(util.emojis.cross);
+ await ReportMessage.react(emojis.check);
+ await ReportMessage.react(emojis.cross);
} catch {
void client.console.warn('ReportCommand', 'Could not react to report message.');
}
diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts
index 17f1bd8..574334a 100644
--- a/src/commands/moulberry-bush/rule.ts
+++ b/src/commands/moulberry-bush/rule.ts
@@ -1,4 +1,12 @@
-import { AllowedMentions, BushCommand, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import { stripIndent } from '../../lib/common/tags.js';
@@ -70,7 +78,7 @@ export default class RuleCommand extends BushCommand {
{
id: 'rule',
description: 'The rule to view.',
- type: util.arg.range('integer', 1, rules.length, true),
+ type: Arg.range('integer', 1, rules.length, true),
readableType: 'integer',
prompt: 'What rule would you like to have cited?',
retry: '{error} Choose a valid rule.',
@@ -92,7 +100,7 @@ export default class RuleCommand extends BushCommand {
slash: true,
slashGuilds: ['516977525906341928'],
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
restrictedGuilds: ['516977525906341928']
});
diff --git a/src/commands/moulberry-bush/serverStatus.ts b/src/commands/moulberry-bush/serverStatus.ts
index ad3903a..c0c0518 100644
--- a/src/commands/moulberry-bush/serverStatus.ts
+++ b/src/commands/moulberry-bush/serverStatus.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, colors, emojis, type CommandMessage } from '#lib';
import assert from 'assert';
import { EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import got from 'got';
@@ -13,7 +13,7 @@ export default class ServerStatusCommand extends BushCommand {
description: "Gives the status of moulberry's server",
usage: ['server-status'],
examples: ['server-status', 'ss'],
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
slash: true
});
@@ -22,24 +22,24 @@ export default class ServerStatusCommand extends BushCommand {
public override async exec(message: CommandMessage) {
const msgEmbed = new EmbedBuilder()
.setTitle('Server status')
- .setDescription(`Checking server:\n${util.emojis.loading}`)
- .setColor(util.colors.default)
+ .setDescription(`Checking server:\n${emojis.loading}`)
+ .setColor(colors.default)
.setFooter({ text: 'Checking https://moulberry.codes/lowestbin.json' });
await message.util.reply({ embeds: [msgEmbed] });
let main;
try {
await got.get('https://moulberry.codes/lowestbin.json').json();
- main = util.emojis.success;
+ main = emojis.success;
} catch (e) {
- main = util.emojis.error;
+ main = emojis.error;
}
await message.util.edit({ embeds: [msgEmbed.setDescription(`Checking server:\n${main}`)] });
- if (main == util.emojis.success) {
+ if (main == emojis.success) {
await message.util.edit({
embeds: [
msgEmbed
.addFields([{ name: 'Status', value: 'The server is online, all features related to prices will likely work.' }])
- .setColor(util.colors.success)
+ .setColor(colors.success)
]
});
} else {
@@ -53,7 +53,7 @@ export default class ServerStatusCommand extends BushCommand {
"It appears Moulberry's server is offline, this means that everything related to prices will likely not work."
}
])
- .setColor(util.colors.error)
+ .setColor(colors.error)
]
});
}
diff --git a/src/commands/utilities/_poll.ts b/src/commands/utilities/_poll.ts
index a843561..fdf6381 100644
--- a/src/commands/utilities/_poll.ts
+++ b/src/commands/utilities/_poll.ts
@@ -29,7 +29,7 @@
// }
// ],
// slash: true,
-// clientPermissions: (m) => util.clientSendAndPermCheck(m),
+// clientPermissions: (m) => clientSendAndPermCheck(m),
// userPermissions: []
// });
// }
@@ -38,8 +38,8 @@
// const { question, options } = this.parseArgs(message, args);
// if (!question || !options.length) return;
-// if (question.length > 256) return await message.util.reply(`${util.emojis.error} Question must be 256 characters or less.`);
-// if (options.length > 10) return await message.util.reply(`${util.emojis.error} You can only have upto 10 options.`);
+// if (question.length > 256) return await message.util.reply(`${emojis.error} Question must be 256 characters or less.`);
+// if (options.length > 10) return await message.util.reply(`${emojis.error} You can only have upto 10 options.`);
// return message.util.send({
// embeds: [
@@ -64,13 +64,13 @@
// const split = args.options.split(/[,|]/).filter((s) => s.trim().length > 0);
// if (message.util.isSlash) {
// if (split.length < 2) {
-// void message.util.reply(`${util.emojis.error} You must provide at least two options.`);
+// void message.util.reply(`${emojis.error} You must provide at least two options.`);
// return { question: '', options: [] };
// }
// return { question: args.question!, options: split };
// } else {
// if (split.length < 3) {
-// void message.util.reply(`${util.emojis.error} You must provide a question and at least two options.`);
+// void message.util.reply(`${emojis.error} You must provide a question and at least two options.`);
// return { question: '', options: [] };
// }
diff --git a/src/commands/utilities/activity.ts b/src/commands/utilities/activity.ts
index 14cc5a0..dfbccfb 100644
--- a/src/commands/utilities/activity.ts
+++ b/src/commands/utilities/activity.ts
@@ -1,4 +1,13 @@
-import { BushCommand, type ArgType, type BushArgumentTypeCaster, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ regex,
+ type ArgType,
+ type BushArgumentTypeCaster,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { type ArgumentGeneratorReturn, type ArgumentTypeCaster } from 'discord-akairo';
import { ApplicationCommandOptionType, ChannelType, type DiscordAPIError, type Snowflake } from 'discord.js';
@@ -55,7 +64,7 @@ interface Activity {
}
function map(phase: string): Activity | null {
- if (client.consts.regex.snowflake.test(phase)) return { id: phase, aliases: [] };
+ if (regex.snowflake.test(phase)) return { id: phase, aliases: [] };
else if (phase in activityMap) return activityMap[phase as keyof typeof activityMap];
for (const activity in activityMap) {
@@ -115,7 +124,7 @@ export default class ActivityCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -155,8 +164,7 @@ export default class ActivityCommand extends BushCommand {
args: { channel: ArgType<'voiceChannel'>; activity: string }
) {
const channel = typeof args.channel === 'string' ? message.guild?.channels.cache.get(args.channel) : args.channel;
- if (channel?.type !== ChannelType.GuildVoice)
- return await message.util.reply(`${util.emojis.error} Choose a valid voice channel`);
+ if (channel?.type !== ChannelType.GuildVoice) return await message.util.reply(`${emojis.error} Choose a valid voice channel`);
const target_application_id = message.util.isSlashMessage(message)
? args.activity
@@ -177,14 +185,12 @@ export default class ActivityCommand extends BushCommand {
.catch((e: Error | DiscordAPIError) => {
if ((e as DiscordAPIError)?.code === 50013) {
- response = `${util.emojis.error} I am missing permissions to make an invite in that channel.`;
+ response = `${emojis.error} I am missing permissions to make an invite in that channel.`;
return;
- } else response = `${util.emojis.error} An error occurred while generating your invite: ${e?.message ?? e}`;
+ } else response = `${emojis.error} An error occurred while generating your invite: ${e?.message ?? e}`;
});
if (response! || !invite || !invite.code)
- return await message.util.reply(
- response! ?? `${util.emojis.error} An unknown error occurred while generating your invite.`
- );
+ return await message.util.reply(response! ?? `${emojis.error} An unknown error occurred while generating your invite.`);
else return await message.util.send(`https://discord.gg/${invite.code}`);
}
}
diff --git a/src/commands/utilities/calculator.ts b/src/commands/utilities/calculator.ts
index a318a79..75d63a1 100644
--- a/src/commands/utilities/calculator.ts
+++ b/src/commands/utilities/calculator.ts
@@ -1,4 +1,13 @@
-import { AllowedMentions, BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ inspectCleanRedactCodeblock,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
import { evaluate } from 'mathjs';
@@ -25,7 +34,7 @@ export default class CalculatorCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -34,22 +43,20 @@ export default class CalculatorCommand extends BushCommand {
const decodedEmbed = new EmbedBuilder().addFields([
{
name: '📥 Input',
- value: await util.inspectCleanRedactCodeblock(args.expression, 'mma')
+ value: await inspectCleanRedactCodeblock(args.expression, 'mma')
}
]);
try {
const calculated = /^(9\s*?\+\s*?10)|(10\s*?\+\s*?9)$/.test(args.expression) ? '21' : evaluate(args.expression);
decodedEmbed
- .setTitle(`${util.emojis.successFull} Successfully Calculated Expression`)
- .setColor(util.colors.success)
- .addFields([{ name: '📤 Output', value: await util.inspectCleanRedactCodeblock(calculated.toString(), 'mma') }]);
+ .setTitle(`${emojis.successFull} Successfully Calculated Expression`)
+ .setColor(colors.success)
+ .addFields([{ name: '📤 Output', value: await inspectCleanRedactCodeblock(calculated.toString(), 'mma') }]);
} catch (error) {
decodedEmbed
- .setTitle(`${util.emojis.errorFull} Unable to Calculate Expression`)
- .setColor(util.colors.error)
- .addFields([
- { name: `📤 Error`, value: await util.inspectCleanRedactCodeblock(`${error.name}: ${error.message}`, 'js') }
- ]);
+ .setTitle(`${emojis.errorFull} Unable to Calculate Expression`)
+ .setColor(colors.error)
+ .addFields([{ name: `📤 Error`, value: await inspectCleanRedactCodeblock(`${error.name}: ${error.message}`, 'js') }]);
}
return await message.util.reply({ embeds: [decodedEmbed], allowedMentions: AllowedMentions.none() });
}
diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts
index 8c82fcc..cc742c8 100644
--- a/src/commands/utilities/decode.ts
+++ b/src/commands/utilities/decode.ts
@@ -1,4 +1,14 @@
-import { AllowedMentions, BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ capitalize,
+ clientSendAndPermCheck,
+ colors,
+ formatError,
+ inspectCleanRedactCodeblock,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
const encodingTypesArray = ['ascii', 'utf8', 'utf-8', 'utf16le', 'ucs2', 'ucs-2', 'base64', 'latin1', 'binary', 'hex'];
@@ -42,7 +52,7 @@ export default class DecodeCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -51,20 +61,18 @@ export default class DecodeCommand extends BushCommand {
message: CommandMessage | SlashMessage,
{ from, to, data }: { from: BufferEncoding; to: BufferEncoding; data: string }
) {
- const encodeOrDecode = util.capitalizeFirstLetter(message?.util?.parsed?.alias ?? 'decoded');
+ const encodeOrDecode = capitalize(message?.util?.parsed?.alias ?? 'decoded');
const decodedEmbed = new EmbedBuilder()
.setTitle(`${encodeOrDecode} Information`)
- .addFields([{ name: '📥 Input', value: await util.inspectCleanRedactCodeblock(data) }]);
+ .addFields([{ name: '📥 Input', value: await inspectCleanRedactCodeblock(data) }]);
try {
const decoded = Buffer.from(data, from).toString(to);
- decodedEmbed
- .setColor(util.colors.success)
- .addFields([{ name: '📤 Output', value: await util.inspectCleanRedactCodeblock(decoded) }]);
+ decodedEmbed.setColor(colors.success).addFields([{ name: '📤 Output', value: await inspectCleanRedactCodeblock(decoded) }]);
} catch (error) {
- decodedEmbed.setColor(util.colors.error).addFields([
+ decodedEmbed.setColor(colors.error).addFields([
{
name: `📤 Error ${encodeOrDecode.slice(1)}ing`,
- value: await util.inspectCleanRedactCodeblock(util.formatError(error))
+ value: await inspectCleanRedactCodeblock(formatError(error))
}
]);
}
diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts
index f47c388..6e8c37f 100644
--- a/src/commands/utilities/hash.ts
+++ b/src/commands/utilities/hash.ts
@@ -1,4 +1,4 @@
-import { BushCommand, type CommandMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, type CommandMessage } from '#lib';
import assert from 'assert';
import crypto from 'crypto';
import { ApplicationCommandOptionType } from 'discord.js';
@@ -25,7 +25,7 @@ export default class HashCommand extends BushCommand {
slashType: ApplicationCommandOptionType.String
}
],
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
diff --git a/src/commands/utilities/highlight-!.ts b/src/commands/utilities/highlight-!.ts
index 6dca545..6847737 100644
--- a/src/commands/utilities/highlight-!.ts
+++ b/src/commands/utilities/highlight-!.ts
@@ -1,4 +1,4 @@
-import { BushCommand, Highlight, HighlightWord, type SlashMessage } from '#lib';
+import { BushCommand, clientSendAndPermCheck, Highlight, HighlightWord, type SlashMessage } from '#lib';
import { Flag, type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo';
import {
ApplicationCommandOptionType,
@@ -123,7 +123,7 @@ export default class HighlightCommand extends BushCommand {
}),
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
diff --git a/src/commands/utilities/highlight-add.ts b/src/commands/utilities/highlight-add.ts
index 726b887..9624a7e 100644
--- a/src/commands/utilities/highlight-add.ts
+++ b/src/commands/utilities/highlight-add.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import { AllowedMentions, BushCommand, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { highlightCommandArgs, highlightSubcommands } from './highlight-!.js';
@@ -44,16 +44,16 @@ export default class HighlightAddCommand extends BushCommand {
if (!args.regex) {
if (args.word.length < 2)
- return message.util.send(`${util.emojis.error} You can only highlight words that are longer than 2 characters.`);
+ return message.util.send(`${emojis.error} You can only highlight words that are longer than 2 characters.`);
if (args.word.length > 50)
- return await message.util.reply(`${util.emojis.error} You can only highlight words that are shorter than 50 characters.`);
+ return await message.util.reply(`${emojis.error} You can only highlight words that are shorter than 50 characters.`);
} else {
try {
new RegExp(args.word);
} catch (e) {
assert(e instanceof SyntaxError);
return message.util.send({
- content: `${util.emojis.error} Invalid regex ${util.format.inlineCode(e.message)}.`,
+ content: `${emojis.error} Invalid regex ${format.inlineCode(e.message)}.`,
allowedMentions: AllowedMentions.none()
});
}
@@ -65,15 +65,15 @@ export default class HighlightAddCommand extends BushCommand {
});
if (typeof res === 'string')
- return await message.util.reply({ content: `${util.emojis.error} ${res}`, allowedMentions: AllowedMentions.none() });
+ return await message.util.reply({ content: `${emojis.error} ${res}`, allowedMentions: AllowedMentions.none() });
else if (!res)
return await message.util.reply({
- content: `${util.emojis.error} There was an error highlighting "${args.word}".`,
+ content: `${emojis.error} There was an error highlighting "${args.word}".`,
allowedMentions: AllowedMentions.none()
});
return await message.util.reply({
- content: `${util.emojis.success} Successfully added "${args.word}" to your highlight list.`,
+ content: `${emojis.success} Successfully added "${args.word}" to your highlight list.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/utilities/highlight-block.ts b/src/commands/utilities/highlight-block.ts
index 61e1254..5429071 100644
--- a/src/commands/utilities/highlight-block.ts
+++ b/src/commands/utilities/highlight-block.ts
@@ -1,4 +1,14 @@
-import { AllowedMentions, BushCommand, Highlight, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ addToArray,
+ AllowedMentions,
+ Arg,
+ BushCommand,
+ emojis,
+ Highlight,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { Channel, GuildMember } from 'discord.js';
@@ -35,15 +45,13 @@ export default class HighlightBlockCommand extends BushCommand {
assert(message.inGuild());
args.target =
- typeof args.target === 'string'
- ? (await util.arg.cast(util.arg.union('member', 'channel'), message, args.target))!
- : args.target;
+ typeof args.target === 'string' ? (await Arg.cast(Arg.union('member', 'channel'), message, args.target))! : args.target;
if (!args.target || !(args.target instanceof GuildMember || args.target instanceof Channel))
- return await message.util.reply(`${util.emojis.error} You can only block users or channels.`);
+ return await message.util.reply(`${emojis.error} You can only block users or channels.`);
if (args.target instanceof Channel && !args.target.isTextBased())
- return await message.util.reply(`${util.emojis.error} You can only block text-based channels.`);
+ return await message.util.reply(`${emojis.error} You can only block text-based channels.`);
const [highlight] = await Highlight.findOrCreate({
where: { guild: message.guild.id, user: message.author.id }
@@ -54,16 +62,16 @@ export default class HighlightBlockCommand extends BushCommand {
if (highlight[key].includes(args.target.id))
return await message.util.reply({
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- content: `${util.emojis.error} You have already blocked ${args.target}.`,
+ content: `${emojis.error} You have already blocked ${args.target}.`,
allowedMentions: AllowedMentions.none()
});
- highlight[key] = util.addToArray(highlight[key], args.target.id);
+ highlight[key] = addToArray(highlight[key], args.target.id);
await highlight.save();
return await message.util.reply({
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- content: `${util.emojis.success} Successfully blocked ${args.target} from triggering your highlights.`,
+ content: `${emojis.success} Successfully blocked ${args.target} from triggering your highlights.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/utilities/highlight-clear.ts b/src/commands/utilities/highlight-clear.ts
index b905f3b..df9f387 100644
--- a/src/commands/utilities/highlight-clear.ts
+++ b/src/commands/utilities/highlight-clear.ts
@@ -1,4 +1,4 @@
-import { BushCommand, ConfirmationPrompt, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, ConfirmationPrompt, emojis, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { highlightSubcommands } from './highlight-!.js';
@@ -21,11 +21,11 @@ export default class HighlightClearCommand extends BushCommand {
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
const confirm = await ConfirmationPrompt.send(message, { content: `Are you sure you want to clear your highlight list?` });
- if (!confirm) return await message.util.reply(`${util.emojis.warn} You decided not to clear your highlight list.`);
+ if (!confirm) return await message.util.reply(`${emojis.warn} You decided not to clear your highlight list.`);
const success = await client.highlightManager.removeAllHighlights(message.guild.id, message.author.id);
- if (!success) return await message.util.reply(`${util.emojis.error} There was an error clearing your highlight list.`);
+ if (!success) return await message.util.reply(`${emojis.error} There was an error clearing your highlight list.`);
- return await message.util.reply(`${util.emojis.success} Successfully cleared your highlight list.`);
+ return await message.util.reply(`${emojis.success} Successfully cleared your highlight list.`);
}
}
diff --git a/src/commands/utilities/highlight-matches.ts b/src/commands/utilities/highlight-matches.ts
index 40020cd..b458550 100644
--- a/src/commands/utilities/highlight-matches.ts
+++ b/src/commands/utilities/highlight-matches.ts
@@ -1,4 +1,4 @@
-import { BushCommand, ButtonPaginator, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import { BushCommand, ButtonPaginator, chunk, colors, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { type ArgumentGeneratorReturn } from 'discord-akairo';
import { type APIEmbed } from 'discord.js';
@@ -36,18 +36,16 @@ export default class HighlightMatchesCommand extends BushCommand {
const res = await client.highlightManager.checkPhrase(message.guild.id, message.author.id, args.phrase);
- if (!res.size) return await message.util.reply(`${util.emojis.error} You are not highlighting any words`);
+ if (!res.size) return await message.util.reply(`${emojis.error} You are not highlighting any words`);
- const lines = res.map(
- (passed, hl) => `${passed ? util.emojis.check : util.emojis.cross} ${hl.regex ? `/${hl.word}/gi` : hl.word}`
- );
- const chunked = util.chunk(lines, 10);
+ const lines = res.map((passed, hl) => `${passed ? emojis.check : emojis.cross} ${hl.regex ? `/${hl.word}/gi` : hl.word}`);
+ const chunked = chunk(lines, 10);
const pages = chunked.map(
(chunk): APIEmbed => ({
title: `Matches`,
description: chunk.join('\n'),
- color: util.colors.default
+ color: colors.default
})
);
diff --git a/src/commands/utilities/highlight-remove.ts b/src/commands/utilities/highlight-remove.ts
index a2f2367..bb1300a 100644
--- a/src/commands/utilities/highlight-remove.ts
+++ b/src/commands/utilities/highlight-remove.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import { AllowedMentions, BushCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { highlightCommandArgs, highlightSubcommands } from './highlight-!.js';
@@ -34,15 +34,15 @@ export default class HighlightRemoveCommand extends BushCommand {
const res = await client.highlightManager.removeHighlight(message.guild.id, message.author.id, args.word);
if (typeof res === 'string')
- return await message.util.reply({ content: `${util.emojis.error} ${res}`, allowedMentions: AllowedMentions.none() });
+ return await message.util.reply({ content: `${emojis.error} ${res}`, allowedMentions: AllowedMentions.none() });
else if (!res)
return await message.util.reply({
- content: `${util.emojis.error} There was an error unhighlighting "${args.word}".`,
+ content: `${emojis.error} There was an error unhighlighting "${args.word}".`,
allowedMentions: AllowedMentions.none()
});
return await message.util.reply({
- content: `${util.emojis.success} Successfully removed "${args.word}" from your highlight list.`,
+ content: `${emojis.success} Successfully removed "${args.word}" from your highlight list.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/utilities/highlight-show.ts b/src/commands/utilities/highlight-show.ts
index 80ba4ca..d966f3a 100644
--- a/src/commands/utilities/highlight-show.ts
+++ b/src/commands/utilities/highlight-show.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushCommand, Highlight, type CommandMessage, type SlashMessage } from '#lib';
+import { AllowedMentions, BushCommand, colors, emojis, Highlight, type CommandMessage, type SlashMessage } from '#lib';
import assert from 'assert';
import { EmbedBuilder } from 'discord.js';
import { highlightSubcommands } from './highlight-!.js';
@@ -25,7 +25,7 @@ export default class HighlightShowCommand extends BushCommand {
void client.highlightManager.syncCache();
- if (!highlight.words.length) return message.util.reply(`${util.emojis.error} You are not highlighting any words.`);
+ if (!highlight.words.length) return message.util.reply(`${emojis.error} You are not highlighting any words.`);
const embed = new EmbedBuilder()
.setTitle('Highlight List')
@@ -35,7 +35,7 @@ export default class HighlightShowCommand extends BushCommand {
.join('\n')
.substring(0, 4096)
)
- .setColor(util.colors.default);
+ .setColor(colors.default);
if (highlight.blacklistedChannels.length)
embed.addFields([
diff --git a/src/commands/utilities/highlight-unblock.ts b/src/commands/utilities/highlight-unblock.ts
index b738ee9..7f416eb 100644
--- a/src/commands/utilities/highlight-unblock.ts
+++ b/src/commands/utilities/highlight-unblock.ts
@@ -1,4 +1,13 @@
-import { AllowedMentions, BushCommand, Highlight, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ emojis,
+ Highlight,
+ removeFromArray,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { Channel, GuildMember } from 'discord.js';
@@ -35,10 +44,10 @@ export default class HighlightUnblockCommand extends BushCommand {
assert(message.inGuild());
if (!(args.target instanceof GuildMember || args.target instanceof Channel))
- return await message.util.reply(`${util.emojis.error} You can only unblock users or channels.`);
+ return await message.util.reply(`${emojis.error} You can only unblock users or channels.`);
if (args.target instanceof Channel && !args.target.isTextBased())
- return await message.util.reply(`${util.emojis.error} You can only unblock text-based channels.`);
+ return await message.util.reply(`${emojis.error} You can only unblock text-based channels.`);
const [highlight] = await Highlight.findOrCreate({
where: { guild: message.guild.id, user: message.author.id }
@@ -48,15 +57,15 @@ export default class HighlightUnblockCommand extends BushCommand {
if (!highlight[key].includes(args.target.id))
return await message.util.reply({
- content: `${util.emojis.error} ${args.target} is not blocked so cannot be unblock.`,
+ content: `${emojis.error} ${args.target} is not blocked so cannot be unblock.`,
allowedMentions: AllowedMentions.none()
});
- highlight[key] = util.removeFromArray(highlight[key], args.target.id);
+ highlight[key] = removeFromArray(highlight[key], args.target.id);
await highlight.save();
return await message.util.reply({
- content: `${util.emojis.success} Successfully allowed ${args.target} to trigger your highlights.`,
+ content: `${emojis.success} Successfully allowed ${args.target} to trigger your highlights.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts
index a4f4c03..c569437 100644
--- a/src/commands/utilities/price.ts
+++ b/src/commands/utilities/price.ts
@@ -1,4 +1,4 @@
-import { ArgType, BushCommand, type CommandMessage } from '#lib';
+import { ArgType, BushCommand, clientSendAndPermCheck, colors, emojis, format, oxford, type CommandMessage } from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, AutocompleteInteraction, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import Fuse from 'fuse.js';
@@ -39,7 +39,7 @@ export default class PriceCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
typing: true
});
@@ -58,12 +58,12 @@ export default class PriceCommand extends BushCommand {
])) as [Bazaar | undefined, LowestBIN | undefined, LowestBIN | undefined, AuctionAverages | undefined];
let parsedItem = args.item.toString().toUpperCase().replace(/ /g, '_').replace(/'S/g, '');
- const priceEmbed = new EmbedBuilder().setColor(errors?.length ? util.colors.warn : util.colors.success).setTimestamp();
+ const priceEmbed = new EmbedBuilder().setColor(errors?.length ? colors.warn : colors.success).setTimestamp();
if (bazaar?.success === false) errors.push('bazaar');
if (errors.length) {
- priceEmbed.setFooter({ text: `Could not fetch data for ${util.oxford(errors, 'and')}` });
+ priceEmbed.setFooter({ text: `Could not fetch data for ${oxford(errors, 'and')}` });
}
// create a set from all the item names so that there are no duplicates for the fuzzy search
@@ -86,7 +86,7 @@ export default class PriceCommand extends BushCommand {
// if its a bazaar item then it there should not be any ah data
if (bazaar?.products?.[parsedItem]) {
- priceEmbed.setTitle(`Bazaar Information for ${util.format.input(parsedItem)}`).addFields([
+ priceEmbed.setTitle(`Bazaar Information for ${format.input(parsedItem)}`).addFields([
{ name: 'Sell Price', value: addBazaarInformation('sellPrice', 2, true) },
{ name: 'Buy Price', value: addBazaarInformation('buyPrice', 2, true) },
{
@@ -103,7 +103,7 @@ export default class PriceCommand extends BushCommand {
// checks if the item exists in any of the action information otherwise it is not a valid item
if (currentLowestBIN?.[parsedItem] || averageLowestBIN?.[parsedItem] || auctionAverages?.[parsedItem]) {
- priceEmbed.setTitle(`Price Information for ${util.format.input(parsedItem)}`).setFooter({
+ priceEmbed.setTitle(`Price Information for ${format.input(parsedItem)}`).setFooter({
text: `${
priceEmbed.data.footer?.text ? `${priceEmbed.data.footer.text} | ` : ''
}All information is based on the last 3 days.`
@@ -111,10 +111,8 @@ export default class PriceCommand extends BushCommand {
} else {
const errorEmbed = new EmbedBuilder();
errorEmbed
- .setColor(util.colors.error)
- .setDescription(
- `${util.emojis.error} ${util.format.input(parsedItem)} is not a valid item id, or it has no auction data.`
- );
+ .setColor(colors.error)
+ .setDescription(`${emojis.error} ${format.input(parsedItem)} is not a valid item id, or it has no auction data.`);
return await message.util.reply({ embeds: [errorEmbed] });
}
diff --git a/src/commands/utilities/remind.ts b/src/commands/utilities/remind.ts
index 8727879..3a1cd18 100644
--- a/src/commands/utilities/remind.ts
+++ b/src/commands/utilities/remind.ts
@@ -1,4 +1,17 @@
-import { BushCommand, Reminder, Time, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ castDurationContent,
+ clientSendAndPermCheck,
+ dateDelta,
+ emojis,
+ format,
+ Reminder,
+ Time,
+ timestamp,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class RemindCommand extends BushCommand {
@@ -22,7 +35,7 @@ export default class RemindCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -31,13 +44,13 @@ export default class RemindCommand extends BushCommand {
message: CommandMessage | SlashMessage,
args: { reminder: OptArgType<'contentWithDuration'> | string }
) {
- const { duration, content } = await util.castDurationContent(args.reminder, message);
+ const { duration, content } = await castDurationContent(args.reminder, message);
- if (!content.trim()) return await message.util.reply(`${util.emojis.error} Please enter a reason to be reminded about.`);
- if (!duration) return await message.util.reply(`${util.emojis.error} Please enter a time to remind you in.`);
+ if (!content.trim()) return await message.util.reply(`${emojis.error} Please enter a reason to be reminded about.`);
+ if (!duration) return await message.util.reply(`${emojis.error} Please enter a time to remind you in.`);
if (duration < Time.Second * 30)
- return await message.util.reply(`${util.emojis.error} You cannot be reminded in less than 30 seconds.`);
+ return await message.util.reply(`${emojis.error} You cannot be reminded in less than 30 seconds.`);
const expires = new Date(Date.now() + duration);
@@ -49,10 +62,10 @@ export default class RemindCommand extends BushCommand {
expires: expires
}).catch(() => false);
- if (!success) return await message.util.reply(`${util.emojis.error} Could not create a reminder.`);
+ if (!success) return await message.util.reply(`${emojis.error} Could not create a reminder.`);
// This isn't technically accurate, but it prevents it from being .99 seconds
- const delta = util.format.bold(util.dateDelta(new Date(Date.now() + duration)));
- return await message.util.reply(`${util.emojis.success} I will remind you in ${delta} (${util.timestamp(expires, 'T')}).`);
+ const delta = format.bold(dateDelta(new Date(Date.now() + duration)));
+ return await message.util.reply(`${emojis.success} I will remind you in ${delta} (${timestamp(expires, 'T')}).`);
}
}
diff --git a/src/commands/utilities/reminders.ts b/src/commands/utilities/reminders.ts
index 79284ac..18243fe 100644
--- a/src/commands/utilities/reminders.ts
+++ b/src/commands/utilities/reminders.ts
@@ -1,4 +1,15 @@
-import { BushCommand, ButtonPaginator, Reminder, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ ButtonPaginator,
+ chunk,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ Reminder,
+ timestamp,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { PermissionFlagsBits, type APIEmbed } from 'discord.js';
import { Op } from 'sequelize';
@@ -14,22 +25,22 @@ export default class RemindersCommand extends BushCommand {
usage: ['reminder'],
examples: ['reminders'],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks]),
userPermissions: []
});
}
public override async exec(message: CommandMessage | SlashMessage) {
const reminders = await Reminder.findAll({ where: { user: message.author.id, expires: { [Op.gt]: new Date() } } });
- if (!reminders.length) return message.util.send(`${util.emojis.error} You don't have any reminders set.`);
+ if (!reminders.length) return message.util.send(`${emojis.error} You don't have any reminders set.`);
- const formattedReminders = reminders.map((reminder) => `${util.timestamp(reminder.expires, 't')} - ${reminder.content}`);
+ const formattedReminders = reminders.map((reminder) => `${timestamp(reminder.expires, 't')} - ${reminder.content}`);
- const chunked = util.chunk(formattedReminders, 15);
+ const chunked = chunk(formattedReminders, 15);
const embeds: APIEmbed[] = chunked.map((chunk) => ({
title: `Reminders`,
description: chunk.join('\n'),
- color: util.colors.default
+ color: colors.default
}));
return await ButtonPaginator.send(message, embeds);
}
diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts
index 69d3054..83ec338 100644
--- a/src/commands/utilities/steal.ts
+++ b/src/commands/utilities/steal.ts
@@ -1,4 +1,13 @@
-import { BushCommand, OptArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ OptArgType,
+ regex,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { type ArgumentGeneratorReturn, type ArgumentType, type ArgumentTypeCaster } from 'discord-akairo';
import { ApplicationCommandOptionType, Attachment, PermissionFlagsBits } from 'discord.js';
@@ -36,7 +45,7 @@ export default class StealCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.ManageEmojisAndStickers]),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageEmojisAndStickers]),
userPermissions: [PermissionFlagsBits.ManageEmojisAndStickers]
});
}
@@ -47,7 +56,7 @@ export default class StealCommand extends BushCommand {
const emoji = hasImage
? message.attachments.first()!.url
: yield {
- type: util.arg.union('discordEmoji', 'snowflake', 'url') as ArgumentType | ArgumentTypeCaster,
+ type: Arg.union('discordEmoji', 'snowflake', 'url') as ArgumentType | ArgumentTypeCaster,
prompt: { start: lang.emojiStart, retry: lang.emojiRetry }
};
@@ -65,20 +74,20 @@ export default class StealCommand extends BushCommand {
) {
assert(message.inGuild());
- if (!args.emoji) return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
+ if (!args.emoji) return await message.util.reply(`${emojis.error} You must provide an emoji to steal.`);
const image =
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 ?? '')
+ : 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 (image === undefined) return await message.util.reply(`${emojis.error} You must provide an emoji to steal.`);
const emojiName =
args.name ?? args.emoji instanceof URL
@@ -96,11 +105,9 @@ export default class StealCommand extends BushCommand {
.catch((e: Error) => e);
if (!(creationSuccess instanceof Error))
- return await message.util.reply(`${util.emojis.success} You successfully stole ${creationSuccess}.`);
+ return await message.util.reply(`${emojis.success} You successfully stole ${creationSuccess}.`);
else {
- return await message.util.reply(
- `${util.emojis.error} The was an error stealing that emoji \`${creationSuccess.message}\`.`
- );
+ return await message.util.reply(`${emojis.error} The was an error stealing that emoji \`${creationSuccess.message}\`.`);
}
}
@@ -129,11 +136,9 @@ export default class StealCommand extends BushCommand {
.catch((e: Error) => e);
if (!(creationSuccess instanceof Error))
- return await message.util.reply(`${util.emojis.success} You successfully stole ${creationSuccess}.`);
+ return await message.util.reply(`${emojis.success} You successfully stole ${creationSuccess}.`);
else {
- return await message.util.reply(
- `${util.emojis.error} The was an error stealing that emoji \`${creationSuccess.message}\`.`
- );
+ return await message.util.reply(`${emojis.error} The was an error stealing that emoji \`${creationSuccess.message}\`.`);
}
}
}
diff --git a/src/commands/utilities/suicide.ts b/src/commands/utilities/suicide.ts
index c4151e8..d2510cc 100644
--- a/src/commands/utilities/suicide.ts
+++ b/src/commands/utilities/suicide.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import { AllowedMentions, BushCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib';
import { stripIndent } from '#tags';
import { EmbedBuilder } from 'discord.js';
@@ -11,7 +11,7 @@ export default class SuicideCommand extends BushCommand {
usage: ['suicide'],
examples: ['suicide'],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
bypassChannelBlacklist: true
});
@@ -21,7 +21,7 @@ export default class SuicideCommand extends BushCommand {
// stolen from https://github.com/dexbiobot/Zeppelin
const suicideEmbed = new EmbedBuilder()
.setTitle('Mental Health Resources')
- .setColor(util.colors.red)
+ .setColor(colors.red)
.setAuthor({
name: 'Remember, You Matter <3',
iconURL:
diff --git a/src/commands/utilities/uuid.ts b/src/commands/utilities/uuid.ts
index 1e70e91..44cfeda 100644
--- a/src/commands/utilities/uuid.ts
+++ b/src/commands/utilities/uuid.ts
@@ -1,4 +1,14 @@
-import { AllowedMentions, ArgType, BushCommand, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ ArgType,
+ BushCommand,
+ clientSendAndPermCheck,
+ emojis,
+ format,
+ mcUUID,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { ApplicationCommandOptionType } from 'discord.js';
export default class UuidCommand extends BushCommand {
@@ -30,7 +40,7 @@ export default class UuidCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -41,17 +51,17 @@ export default class UuidCommand extends BushCommand {
) {
if (typeof args.ign === 'string') args.ign = { match: /\w{1,16}/im.exec(args.ign)!, matches: [] };
- if (!args.ign.match) return await message.util.reply(`${util.emojis.error} Please enter a valid ign.`);
+ if (!args.ign.match) return await message.util.reply(`${emojis.error} Please enter a valid ign.`);
const readableIGN = args.ign.match[0];
try {
- const uuid = await util.mcUUID(readableIGN, args.dashed);
+ const uuid = await mcUUID(readableIGN, args.dashed);
return await message.util.reply({
- content: `The uuid for ${util.format.input(readableIGN)} is ${util.format.input(uuid)}`,
+ content: `The uuid for ${format.input(readableIGN)} is ${format.input(uuid)}`,
allowedMentions: AllowedMentions.none()
});
} catch (e) {
return await message.util.reply({
- content: `${util.emojis.error} Could not find an uuid for ${util.format.input(readableIGN)}.`,
+ content: `${emojis.error} Could not find an uuid for ${format.input(readableIGN)}.`,
allowedMentions: AllowedMentions.none()
});
}
diff --git a/src/commands/utilities/viewRaw.ts b/src/commands/utilities/viewRaw.ts
index 5c2c146..8114cef 100644
--- a/src/commands/utilities/viewRaw.ts
+++ b/src/commands/utilities/viewRaw.ts
@@ -1,4 +1,16 @@
-import { BushCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib';
+import {
+ Arg,
+ BushCommand,
+ clientSendAndPermCheck,
+ codeblock,
+ colors,
+ emojis,
+ inspect,
+ type ArgType,
+ type CommandMessage,
+ type OptArgType,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
import { ApplicationCommandOptionType, ChannelType, EmbedBuilder, Message, PermissionFlagsBits } from 'discord.js';
@@ -14,7 +26,7 @@ export default class ViewRawCommand extends BushCommand {
{
id: 'message',
description: 'The message to view the raw content of.',
- type: util.arg.union('message', 'messageLink'),
+ type: Arg.union('message', 'messageLink'),
readableType: 'message|messageLink',
prompt: 'What message would you like to view?',
retry: '{error} Choose a valid message.',
@@ -23,7 +35,7 @@ export default class ViewRawCommand extends BushCommand {
{
id: 'channel',
description: 'The channel that the message is in.',
- type: util.arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
+ type: Arg.union('textChannel', 'newsChannel', 'threadChannel', 'voiceChannel'),
prompt: 'What channel is the message in?',
retry: '{error} Choose a valid channel.',
optional: true,
@@ -59,7 +71,7 @@ export default class ViewRawCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
}
@@ -81,7 +93,7 @@ export default class ViewRawCommand extends BushCommand {
args.message instanceof Message ? args.message : await args.channel!.messages.fetch(`${args.message}`).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.`
+ `${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.`
);
const Embed = await ViewRawCommand.getRawData(newMessage, { json: args.json, js: args.js });
@@ -94,14 +106,14 @@ export default class ViewRawCommand extends BushCommand {
options.json || options.js
? options.json
? JSON.stringify(message.toJSON(), undefined, 2)
- : util.inspect(message.toJSON()) || '[No Content]'
+ : inspect(message.toJSON()) || '[No Content]'
: message.content || '[No Content]';
const lang = options.json ? 'json' : options.js ? 'js' : undefined;
return new EmbedBuilder()
.setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined })
.setTimestamp(message.createdTimestamp)
- .setColor(message.member?.roles?.color?.color ?? util.colors.default)
+ .setColor(message.member?.roles?.color?.color ?? colors.default)
.setTitle('Raw Message Information')
- .setDescription(await util.codeblock(content, 2048, lang));
+ .setDescription(await codeblock(content, 2048, lang));
}
}
diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts
index ae96a65..851411a 100644
--- a/src/commands/utilities/whoHasRole.ts
+++ b/src/commands/utilities/whoHasRole.ts
@@ -1,6 +1,17 @@
-import { BushCommand, ButtonPaginator, OptArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BushCommand,
+ ButtonPaginator,
+ chunk,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ OptArgType,
+ oxford,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import assert from 'assert';
-import { ApplicationCommandOptionType, Util, type CommandInteraction, type Role } from 'discord.js';
+import { ApplicationCommandOptionType, escapeMarkdown, type CommandInteraction, type Role } from 'discord.js';
export default class WhoHasRoleCommand extends BushCommand {
public constructor() {
@@ -24,7 +35,7 @@ export default class WhoHasRoleCommand extends BushCommand {
),
slash: true,
channel: 'guild',
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [],
typing: true
});
@@ -44,18 +55,18 @@ export default class WhoHasRoleCommand extends BushCommand {
const members = message.guild.members.cache.filter((m) => roles.every((r) => m.roles.cache.has(r)));
- const roleMembers = members.map((member) => `${member.user} (${Util.escapeMarkdown(member.user.tag)})`);
- const chunkedRoleMembers = util.chunk(roleMembers, 30);
+ const roleMembers = members.map((member) => `${member.user} (${escapeMarkdown(member.user.tag)})`);
+ const chunkedRoleMembers = chunk(roleMembers, 30);
const title = `Members with ${
roles.length < 4
- ? util.oxford(
+ ? oxford(
rawRoles.map((r) => r.name),
'and'
)
: `${rawRoles.length} Roles`
} [\`${members.size.toLocaleString()}\`]`;
- const color = util.colors.default;
+ const color = colors.default;
const embedPages = chunkedRoleMembers.map((chunk) => ({
title,
description: chunk.join('\n'),
@@ -63,7 +74,7 @@ export default class WhoHasRoleCommand extends BushCommand {
}));
if (embedPages.length === 0) {
- return await message.util.reply(`${util.emojis.error} No members found matching the given roles.`);
+ return await message.util.reply(`${emojis.error} No members found matching the given roles.`);
}
return await ButtonPaginator.send(message, embedPages, null, true);
diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts
index 98cac69..b682c85 100644
--- a/src/commands/utilities/wolframAlpha.ts
+++ b/src/commands/utilities/wolframAlpha.ts
@@ -1,4 +1,15 @@
-import { AllowedMentions, BushCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ AllowedMentions,
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ emojis,
+ inspectCleanRedactCodeblock,
+ uploadImageToImgur,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { initializeClass as WolframAlphaAPI } from '@notenoughupdates/wolfram-alpha-api';
import assert from 'assert';
import { ApplicationCommandOptionType, EmbedBuilder, type MessageOptions } from 'discord.js';
@@ -34,7 +45,7 @@ export default class WolframAlphaCommand extends BushCommand {
}
],
slash: true,
- clientPermissions: (m) => util.clientSendAndPermCheck(m),
+ clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: []
});
}
@@ -45,13 +56,13 @@ export default class WolframAlphaCommand extends BushCommand {
) {
if (message.util.isSlashMessage(message)) await message.interaction.deferReply();
- args.image && void message.util.reply({ content: `${util.emojis.loading} Loading...`, embeds: [] });
+ args.image && void message.util.reply({ content: `${emojis.loading} Loading...`, embeds: [] });
const waApi = WolframAlphaAPI(client.config.credentials.wolframAlphaAppId);
const decodedEmbed = new EmbedBuilder().addFields([
{
name: '📥 Input',
- value: await util.inspectCleanRedactCodeblock(args.expression)
+ value: await inspectCleanRedactCodeblock(args.expression)
}
]);
const sendOptions: MessageOptions = { content: null, allowedMentions: AllowedMentions.none() };
@@ -59,21 +70,19 @@ export default class WolframAlphaCommand extends BushCommand {
const calculated = await (args.image
? waApi.getSimple({ i: args.expression, timeout: 1, background: '2C2F33', foreground: 'white' })
: waApi.getShort(args.expression));
- decodedEmbed.setTitle(`${util.emojis.successFull} Successfully Queried Expression`).setColor(util.colors.success);
+ decodedEmbed.setTitle(`${emojis.successFull} Successfully Queried Expression`).setColor(colors.success);
if (args.image) {
- decodedEmbed.setImage(await util.uploadImageToImgur(calculated.split(',')[1]));
+ decodedEmbed.setImage(await uploadImageToImgur(calculated.split(',')[1]));
decodedEmbed.addFields([{ name: '📤 Output', value: '​' }]);
} else {
- decodedEmbed.addFields([{ name: '📤 Output', value: await util.inspectCleanRedactCodeblock(calculated.toString()) }]);
+ decodedEmbed.addFields([{ name: '📤 Output', value: await inspectCleanRedactCodeblock(calculated.toString()) }]);
}
} catch (error) {
decodedEmbed
- .setTitle(`${util.emojis.errorFull} Unable to Query Expression`)
- .setColor(util.colors.error)
- .addFields([
- { name: `📤 Error`, value: await util.inspectCleanRedactCodeblock(`${error.name}: ${error.message}`, 'js') }
- ]);
+ .setTitle(`${emojis.errorFull} Unable to Query Expression`)
+ .setColor(colors.error)
+ .addFields([{ name: `📤 Error`, value: await inspectCleanRedactCodeblock(`${error.name}: ${error.message}`, 'js') }]);
}
sendOptions.embeds = [decodedEmbed];
diff --git a/src/context-menu-commands/user/modlog.ts b/src/context-menu-commands/user/modlog.ts
index bdb311f..7f3103d 100644
--- a/src/context-menu-commands/user/modlog.ts
+++ b/src/context-menu-commands/user/modlog.ts
@@ -1,5 +1,5 @@
import { ModlogCommand } from '#commands';
-import { SlashMessage } from '#lib';
+import { emojis, SlashMessage } from '#lib';
import { CommandUtil, ContextMenuCommand } from 'discord-akairo';
import { ApplicationCommandType, type ContextMenuCommandInteraction } from 'discord.js';
@@ -15,12 +15,12 @@ export default class ModlogContextMenuCommand extends ContextMenuCommand {
public override async exec(interaction: ContextMenuCommandInteraction) {
if (!interaction.inCachedGuild())
return interaction.reply({
- content: `${util.emojis.error} You can't use this command outside of a server.`,
+ content: `${emojis.error} You can't use this command outside of a server.`,
ephemeral: true
});
if (!interaction.member?.permissions.has('ManageMessages'))
return interaction.reply({
- content: `${util.emojis.error} You can't use this command because you have the **Manage Messages** permission.`,
+ content: `${emojis.error} You can't use this command because you have the **Manage Messages** permission.`,
ephemeral: true
});
diff --git a/src/context-menu-commands/user/userInfo.ts b/src/context-menu-commands/user/userInfo.ts
index 80e9883..075b681 100644
--- a/src/context-menu-commands/user/userInfo.ts
+++ b/src/context-menu-commands/user/userInfo.ts
@@ -1,4 +1,5 @@
import { UserInfoCommand } from '#commands';
+import { format } from '#lib';
import { ContextMenuCommand } from 'discord-akairo';
import { ApplicationCommandType, type ContextMenuCommandInteraction, type Guild } from 'discord.js';
@@ -20,7 +21,7 @@ export default class UserInfoContextMenuCommand extends ContextMenuCommand {
const guild = interaction.guild as Guild;
const member = await guild.members.fetch(interaction.targetId).catch(() => null);
- if (!member) return interaction.reply(`${util.format.input(user.tag)} doesn't appear to be a member of this server anymore.`);
+ if (!member) return interaction.reply(`${format.input(user.tag)} doesn't appear to be a member of this server anymore.`);
const userEmbed = await UserInfoCommand.makeUserInfoEmbed(user, member, guild);
diff --git a/src/inhibitors/blacklist/channelGlobalBlacklist.ts b/src/inhibitors/blacklist/channelGlobalBlacklist.ts
index 1ac26f1..86ab21f 100644
--- a/src/inhibitors/blacklist/channelGlobalBlacklist.ts
+++ b/src/inhibitors/blacklist/channelGlobalBlacklist.ts
@@ -10,7 +10,7 @@ export default class UserGlobalBlacklistInhibitor extends BushInhibitor {
});
}
- public override exec(message: CommandMessage | SlashMessage, command: BushCommand): boolean {
+ public exec(message: CommandMessage | SlashMessage, command: BushCommand): boolean {
if (!message.author || !message.inGuild()) return false;
// do not change to message.author.isOwner()
if (client.isOwner(message.author) || client.user!.id === message.author.id) return false;
diff --git a/src/inhibitors/blacklist/channelGuildBlacklist.ts b/src/inhibitors/blacklist/channelGuildBlacklist.ts
index a634015..8cf35ec 100644
--- a/src/inhibitors/blacklist/channelGuildBlacklist.ts
+++ b/src/inhibitors/blacklist/channelGuildBlacklist.ts
@@ -10,7 +10,7 @@ export default class ChannelGuildBlacklistInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (!message.author || !message.inGuild()) return false;
// do not change to message.author.isOwner()
if (client.isOwner(message.author) || client.user!.id === message.author.id) return false;
diff --git a/src/inhibitors/blacklist/guildBlacklist.ts b/src/inhibitors/blacklist/guildBlacklist.ts
index 087bdb7..60c5755 100644
--- a/src/inhibitors/blacklist/guildBlacklist.ts
+++ b/src/inhibitors/blacklist/guildBlacklist.ts
@@ -10,7 +10,7 @@ export default class GuildBlacklistInhibitor extends BushInhibitor {
});
}
- public override exec(message: CommandMessage | SlashMessage): boolean {
+ public exec(message: CommandMessage | SlashMessage): boolean {
if (!message.author || !message.inGuild()) return false;
// do not change to message.author.isOwner()
if (client.isOwner(message.author) || client.isSuperUser(message.author) || client.user!.id === message.author.id)
diff --git a/src/inhibitors/blacklist/userGlobalBlacklist.ts b/src/inhibitors/blacklist/userGlobalBlacklist.ts
index ae488c8..bf0d4bd 100644
--- a/src/inhibitors/blacklist/userGlobalBlacklist.ts
+++ b/src/inhibitors/blacklist/userGlobalBlacklist.ts
@@ -10,7 +10,7 @@ export default class UserGlobalBlacklistInhibitor extends BushInhibitor {
});
}
- public override exec(message: CommandMessage | SlashMessage): boolean {
+ public exec(message: CommandMessage | SlashMessage): boolean {
if (!message.author) return false;
// do not change to message.author.isOwner()
if (client.isOwner(message.author) || client.user!.id === message.author.id) return false;
diff --git a/src/inhibitors/blacklist/userGuildBlacklist.ts b/src/inhibitors/blacklist/userGuildBlacklist.ts
index c4fa527..a2ac1aa 100644
--- a/src/inhibitors/blacklist/userGuildBlacklist.ts
+++ b/src/inhibitors/blacklist/userGuildBlacklist.ts
@@ -10,7 +10,7 @@ export default class UserGuildBlacklistInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage): Promise<boolean> {
if (!message.author || !message.inGuild()) return false;
// do not change to message.author.isOwner()
if (client.isOwner(message.author) || client.isSuperUser(message.author) || client.user!.id === message.author.id)
diff --git a/src/inhibitors/checks/fatal.ts b/src/inhibitors/checks/fatal.ts
index 520754a..a3601b5 100644
--- a/src/inhibitors/checks/fatal.ts
+++ b/src/inhibitors/checks/fatal.ts
@@ -11,7 +11,7 @@ export default class FatalInhibitor extends BushInhibitor {
});
}
- public override async exec(message: Message | SlashMessage): Promise<boolean> {
+ public async exec(message: Message | SlashMessage): Promise<boolean> {
if (client.isOwner(message.author)) return false;
for (const property in client.cache.global) {
if (!client.cache.global[property as keyof typeof client.cache.global]) {
diff --git a/src/inhibitors/checks/guildUnavailable.ts b/src/inhibitors/checks/guildUnavailable.ts
index 45ec0da..6c741a1 100644
--- a/src/inhibitors/checks/guildUnavailable.ts
+++ b/src/inhibitors/checks/guildUnavailable.ts
@@ -11,7 +11,7 @@ export default class GuildUnavailableInhibitor extends BushInhibitor {
});
}
- public override async exec(message: Message | SlashMessage): Promise<boolean> {
+ public async exec(message: Message | SlashMessage): Promise<boolean> {
if (message.inGuild() && !message.guild.available) {
void client.console.verbose(
'guildUnavailable',
diff --git a/src/inhibitors/command/dm.ts b/src/inhibitors/command/dm.ts
index d6c13a9..1fc43c6 100644
--- a/src/inhibitors/command/dm.ts
+++ b/src/inhibitors/command/dm.ts
@@ -10,7 +10,7 @@ export default class DMInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.channel === 'dm' && message.guild) {
void client.console.verbose(
'dm',
diff --git a/src/inhibitors/command/globalDisabledCommand.ts b/src/inhibitors/command/globalDisabledCommand.ts
index ada9716..7e855ae 100644
--- a/src/inhibitors/command/globalDisabledCommand.ts
+++ b/src/inhibitors/command/globalDisabledCommand.ts
@@ -10,7 +10,7 @@ export default class DisabledGuildCommandInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (message.author.isOwner()) return false;
if (client.cache.global.disabledCommands.includes(command?.id)) {
void client.console.verbose(
diff --git a/src/inhibitors/command/guild.ts b/src/inhibitors/command/guild.ts
index 8b249ff..6ea4e6a 100644
--- a/src/inhibitors/command/guild.ts
+++ b/src/inhibitors/command/guild.ts
@@ -10,7 +10,7 @@ export default class GuildInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.channel === 'guild' && !message.guild) {
void client.console.verbose(
'guild',
diff --git a/src/inhibitors/command/guildDisabledCommand.ts b/src/inhibitors/command/guildDisabledCommand.ts
index a97f5cc..7d63093 100644
--- a/src/inhibitors/command/guildDisabledCommand.ts
+++ b/src/inhibitors/command/guildDisabledCommand.ts
@@ -10,7 +10,7 @@ export default class DisabledGuildCommandInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (!message.guild || !message.guild) return false;
if (message.author.isOwner() || message.author.isSuperUser()) return false; // super users bypass guild disabled commands
diff --git a/src/inhibitors/command/nsfw.ts b/src/inhibitors/command/nsfw.ts
index 6eb2878..f8f2180 100644
--- a/src/inhibitors/command/nsfw.ts
+++ b/src/inhibitors/command/nsfw.ts
@@ -11,7 +11,7 @@ export default class NsfwInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.onlyNsfw && !(message.channel as TextChannel).nsfw) {
void client.console.verbose(
'notNsfw',
diff --git a/src/inhibitors/command/owner.ts b/src/inhibitors/command/owner.ts
index 2331e04..3769d84 100644
--- a/src/inhibitors/command/owner.ts
+++ b/src/inhibitors/command/owner.ts
@@ -10,7 +10,7 @@ export default class OwnerInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.ownerOnly) {
if (!client.isOwner(message.author)) {
void client.console.verbose(
diff --git a/src/inhibitors/command/restrictedChannel.ts b/src/inhibitors/command/restrictedChannel.ts
index 6b06f95..867756d 100644
--- a/src/inhibitors/command/restrictedChannel.ts
+++ b/src/inhibitors/command/restrictedChannel.ts
@@ -10,7 +10,7 @@ export default class RestrictedChannelInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.restrictedChannels?.length && message.channel) {
if (!command.restrictedChannels.includes(message.channel.id)) {
void client.console.verbose(
diff --git a/src/inhibitors/command/restrictedGuild.ts b/src/inhibitors/command/restrictedGuild.ts
index 47c61ce..4d43c21 100644
--- a/src/inhibitors/command/restrictedGuild.ts
+++ b/src/inhibitors/command/restrictedGuild.ts
@@ -10,7 +10,7 @@ export default class RestrictedGuildInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.restrictedChannels?.length && message.channel) {
if (!command.restrictedChannels.includes(message.channel.id)) {
void client.console.verbose(
diff --git a/src/inhibitors/command/superUser.ts b/src/inhibitors/command/superUser.ts
index 23b1c64..2e44b67 100644
--- a/src/inhibitors/command/superUser.ts
+++ b/src/inhibitors/command/superUser.ts
@@ -10,7 +10,7 @@ export default class SuperUserInhibitor extends BushInhibitor {
});
}
- public override async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
+ public async exec(message: CommandMessage | SlashMessage, command: BushCommand): Promise<boolean> {
if (command.superUserOnly) {
if (!client.isSuperUser(message.author)) {
void client.console.verbose(
diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts
index 982e0e8..7f19e63 100644
--- a/src/lib/common/AutoMod.ts
+++ b/src/lib/common/AutoMod.ts
@@ -1,4 +1,4 @@
-import { banResponse, Moderation } from '#lib';
+import { banResponse, codeblock, colors, emojis, format, formatError, getShared, Moderation, resolveNonCachedUser } from '#lib';
import assert from 'assert';
import chalk from 'chalk';
import {
@@ -18,11 +18,6 @@ import {
*/
export class AutoMod {
/**
- * The message to check for blacklisted phrases on
- */
- private message: Message;
-
- /**
* Whether or not a punishment has already been given to the user
*/
private punished = false;
@@ -30,8 +25,12 @@ export class AutoMod {
/**
* @param message The message to check and potentially perform automod actions to
*/
- public constructor(message: Message) {
- this.message = message;
+ public constructor(
+ /**
+ * The message to check for blacklisted phrases on
+ */
+ private message: Message
+ ) {
if (message.author.id === client.user?.id) return;
void this.handle();
}
@@ -57,9 +56,9 @@ export class AutoMod {
traditional: {
if (this.isImmune) break traditional;
- const badLinksArray = util.getShared('badLinks');
- const badLinksSecretArray = util.getShared('badLinksSecret');
- const badWordsRaw = util.getShared('badWords');
+ const badLinksArray = getShared('badLinks');
+ const badLinksSecretArray = getShared('badLinksSecret');
+ const badWordsRaw = getShared('badWords');
const customAutomodPhrases = (await this.message.guild.getSetting('autoModPhases')) ?? [];
const uniqueLinks = [...new Set([...badLinksArray, ...badLinksSecretArray])];
@@ -90,8 +89,8 @@ export class AutoMod {
embeds: [
{
title: 'AutoMod Error',
- description: `Unable to find severity information for ${util.format.inlineCode(highestOffence.match)}`,
- color: util.colors.error
+ description: `Unable to find severity information for ${format.inlineCode(highestOffence.match)}`,
+ color: colors.error
}
]
});
@@ -168,7 +167,7 @@ export class AutoMod {
.setDescription(
`**User:** ${this.message.author} (${this.message.author.tag})\n**Sent From:** <#${this.message.channel.id}> [Jump to context](${this.message.url})`
)
- .addFields([{ name: 'Message Content', value: `${await util.codeblock(this.message.content, 1024)}` }])
+ .addFields([{ name: 'Message Content', value: `${await codeblock(this.message.content, 1024)}` }])
.setColor(color)
.setTimestamp()
],
@@ -252,13 +251,13 @@ export class AutoMod {
let color;
switch (highestOffence.severity) {
case Severity.DELETE: {
- color = util.colors.lightGray;
+ color = colors.lightGray;
void this.message.delete().catch((e) => deleteError.bind(this, e));
this.punished = true;
break;
}
case Severity.WARN: {
- color = util.colors.yellow;
+ color = colors.yellow;
void this.message.delete().catch((e) => deleteError.bind(this, e));
void this.message.member?.bushWarn({
moderator: this.message.guild!.members.me!,
@@ -268,7 +267,7 @@ export class AutoMod {
break;
}
case Severity.TEMP_MUTE: {
- color = util.colors.orange;
+ color = colors.orange;
void this.message.delete().catch((e) => deleteError.bind(this, e));
void this.message.member?.bushMute({
moderator: this.message.guild!.members.me!,
@@ -279,7 +278,7 @@ export class AutoMod {
break;
}
case Severity.PERM_MUTE: {
- color = util.colors.red;
+ color = colors.red;
void this.message.delete().catch((e) => deleteError.bind(this, e));
void this.message.member?.bushMute({
moderator: this.message.guild!.members.me!,
@@ -302,8 +301,8 @@ export class AutoMod {
{
title: 'AutoMod Error',
description: `Unable to delete triggered message.`,
- fields: [{ name: 'Error', value: await util.codeblock(`${util.formatError(e)}`, 1024, 'js', true) }],
- color: util.colors.error
+ fields: [{ name: 'Error', value: await codeblock(`${formatError(e)}`, 1024, 'js', true) }],
+ color: colors.error
}
]
});
@@ -333,7 +332,7 @@ export class AutoMod {
this.message.channel.id
}> [Jump to context](${this.message.url})\n**Blacklisted Words:** ${offences.map((o) => `\`${o.match}\``).join(', ')}`
)
- .addFields([{ name: 'Message Content', value: `${await util.codeblock(this.message.content, 1024)}` }])
+ .addFields([{ name: 'Message Content', value: `${await codeblock(this.message.content, 1024)}` }])
.setColor(color)
.setTimestamp()
.setAuthor({ name: this.message.author.tag, url: this.message.author.displayAvatarURL() })
@@ -360,7 +359,7 @@ export class AutoMod {
public static async handleInteraction(interaction: ButtonInteraction) {
if (!interaction.memberPermissions?.has(PermissionFlagsBits.BanMembers))
return interaction.reply({
- content: `${util.emojis.error} You are missing the **Ban Members** permission.`,
+ content: `${emojis.error} You are missing the **Ban Members** permission.`,
ephemeral: true
});
const [action, userId, reason] = interaction.customId.replace('automod;', '').split(';');
@@ -387,20 +386,20 @@ export class AutoMod {
evidence: (interaction.message as Message).url ?? undefined
});
- const victimUserFormatted = (await util.resolveNonCachedUser(userId))?.tag ?? userId;
+ const victimUserFormatted = (await resolveNonCachedUser(userId))?.tag ?? userId;
if (result === banResponse.SUCCESS)
return interaction.reply({
- content: `${util.emojis.success} Successfully banned **${victimUserFormatted}**.`,
+ content: `${emojis.success} Successfully banned **${victimUserFormatted}**.`,
ephemeral: true
});
else if (result === banResponse.DM_ERROR)
return interaction.reply({
- content: `${util.emojis.warn} Banned ${victimUserFormatted} however I could not send them a dm.`,
+ content: `${emojis.warn} Banned ${victimUserFormatted} however I could not send them a dm.`,
ephemeral: true
});
else
return interaction.reply({
- content: `${util.emojis.error} Could not ban **${victimUserFormatted}**: \`${result}\` .`,
+ content: `${emojis.error} Could not ban **${victimUserFormatted}**: \`${result}\` .`,
ephemeral: true
});
}
diff --git a/src/lib/common/ButtonPaginator.ts b/src/lib/common/ButtonPaginator.ts
index 64870cf..9560247 100644
--- a/src/lib/common/ButtonPaginator.ts
+++ b/src/lib/common/ButtonPaginator.ts
@@ -15,26 +15,6 @@ import {
*/
export class ButtonPaginator {
/**
- * The message that triggered the command
- */
- protected message: CommandMessage | SlashMessage;
-
- /**
- * The embeds to paginate
- */
- protected embeds: EmbedBuilder[] | APIEmbed[];
-
- /**
- * The optional text to send with the paginator
- */
- protected text: string | null;
-
- /**
- * Whether the paginator message gets deleted when the exit button is pressed
- */
- protected deleteOnExit: boolean;
-
- /**
* The current page of the paginator
*/
protected curPage: number;
@@ -52,16 +32,27 @@ export class ButtonPaginator {
* @param startOn The page to start from (**not** the index)
*/
protected constructor(
- message: CommandMessage | SlashMessage,
- embeds: EmbedBuilder[] | APIEmbed[],
- text: string | null,
- deleteOnExit: boolean,
+ /**
+ * The message that triggered the command
+ */
+ protected message: CommandMessage | SlashMessage,
+
+ /**
+ * The embeds to paginate
+ */
+ protected embeds: EmbedBuilder[] | APIEmbed[],
+
+ /**
+ * The optional text to send with the paginator
+ */
+ protected text: string | null,
+
+ /**
+ * Whether the paginator message gets deleted when the exit button is pressed
+ */
+ protected deleteOnExit: boolean,
startOn: number
) {
- this.message = message;
- this.embeds = embeds;
- this.text = text ? text : null;
- this.deleteOnExit = deleteOnExit;
this.curPage = startOn - 1;
// add footers
diff --git a/src/lib/common/ConfirmationPrompt.ts b/src/lib/common/ConfirmationPrompt.ts
index c95dbbc..4593d24 100644
--- a/src/lib/common/ConfirmationPrompt.ts
+++ b/src/lib/common/ConfirmationPrompt.ts
@@ -6,23 +6,20 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, type MessageComponentInte
*/
export class ConfirmationPrompt {
/**
- * Options for sending the message
- */
- protected messageOptions: MessageOptions;
-
- /**
- * The message that triggered the command
- */
- protected message: CommandMessage | SlashMessage;
-
- /**
* @param message The message to respond to
- * @param options The send message options
+ * @param messageOptions The send message options
*/
- protected constructor(message: CommandMessage | SlashMessage, messageOptions: MessageOptions) {
- this.message = message;
- this.messageOptions = messageOptions;
- }
+ protected constructor(
+ /**
+ * The message that triggered the command
+ */
+ protected message: CommandMessage | SlashMessage,
+
+ /**
+ * Options for sending the message
+ */
+ protected messageOptions: MessageOptions
+ ) {}
/**
* Sends a message with buttons for the user to confirm or cancel the action.
diff --git a/src/lib/common/DeleteButton.ts b/src/lib/common/DeleteButton.ts
index 91f4bfa..b561d94 100644
--- a/src/lib/common/DeleteButton.ts
+++ b/src/lib/common/DeleteButton.ts
@@ -15,23 +15,20 @@ import {
*/
export class DeleteButton {
/**
- * Options for sending the message
- */
- protected messageOptions: MessageOptions;
-
- /**
- * The message that triggered the command
- */
- protected message: CommandMessage | SlashMessage;
-
- /**
* @param message The message to respond to
- * @param options The send message options
+ * @param messageOptions The send message options
*/
- protected constructor(message: CommandMessage | SlashMessage, options: MessageOptions) {
- this.message = message;
- this.messageOptions = options;
- }
+ protected constructor(
+ /**
+ * The message that triggered the command
+ */
+ protected message: CommandMessage | SlashMessage,
+
+ /**
+ * Options for sending the message
+ */
+ protected messageOptions: MessageOptions
+ ) {}
/**
* Sends a message with a button for the user to delete it.
diff --git a/src/lib/common/HighlightManager.ts b/src/lib/common/HighlightManager.ts
index fdec322..caaa6a5 100644
--- a/src/lib/common/HighlightManager.ts
+++ b/src/lib/common/HighlightManager.ts
@@ -1,7 +1,7 @@
-import { Highlight, type HighlightWord } from '#lib';
+import { addToArray, format, Highlight, removeFromArray, timestamp, type HighlightWord } from '#lib';
import assert from 'assert';
import { Collection, type Message, type Snowflake } from 'discord.js';
-import { Time } from '../utils/BushConstants.js';
+import { colors, Time } from '../utils/BushConstants.js';
const NOTIFY_COOLDOWN = 5 * Time.Minute;
const OWNER_NOTIFY_COOLDOWN = 1 * Time.Minute;
@@ -162,7 +162,7 @@ export class HighlightManager {
if (highlight.words.some((w) => w.word === hl.word)) return `You have already highlighted "${hl.word}".`;
- highlight.words = util.addToArray(highlight.words, hl);
+ highlight.words = addToArray(highlight.words, hl);
return Boolean(await highlight.save().catch(() => false));
}
@@ -189,7 +189,7 @@ export class HighlightManager {
const toRemove = highlight.words.find((w) => w.word === hl);
if (!toRemove) return `Uhhhhh... This shouldn't happen.`;
- highlight.words = util.removeFromArray(highlight.words, toRemove);
+ highlight.words = removeFromArray(highlight.words, toRemove);
return Boolean(await highlight.save().catch(() => false));
}
@@ -271,20 +271,18 @@ export class HighlightManager {
return client.users
.send(user, {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- content: `In ${util.format.input(message.guild.name)} ${message.channel}, your highlight "${hl.word}" was matched:`,
+ content: `In ${format.input(message.guild.name)} ${message.channel}, your highlight "${hl.word}" was matched:`,
embeds: [
{
description: [...recentMessages, message]
.map(
(m) =>
- `${util.timestamp(m.createdAt, 't')} ${util.format.input(`${m.author.tag}:`)} ${m.cleanContent
- .trim()
- .substring(0, 512)}`
+ `${timestamp(m.createdAt, 't')} ${format.input(`${m.author.tag}:`)} ${m.cleanContent.trim().substring(0, 512)}`
)
.join('\n'),
author: { name: hl.regex ? `/${hl.word}/gi` : hl.word },
fields: [{ name: 'Source message', value: `[Jump to message](${message.url})` }],
- color: util.colors.default,
+ color: colors.default,
footer: { text: 'Triggered' },
timestamp: message.createdAt.toISOString()
}
diff --git a/src/lib/common/Sentry.ts b/src/lib/common/Sentry.ts
index e18555b..34bc06f 100644
--- a/src/lib/common/Sentry.ts
+++ b/src/lib/common/Sentry.ts
@@ -1,7 +1,7 @@
import { RewriteFrames } from '@sentry/integrations';
import * as SentryNode from '@sentry/node';
import { Integrations } from '@sentry/node';
-import config from './../../config/options.js';
+import config from '../../../config/options.js';
export class Sentry {
public constructor(rootdir: string) {
diff --git a/src/lib/common/util/Arg.ts b/src/lib/common/util/Arg.ts
index 51d8065..a7795b1 100644
--- a/src/lib/common/util/Arg.ts
+++ b/src/lib/common/util/Arg.ts
@@ -9,155 +9,150 @@ import { Argument, type Flag, type ParsedValuePredicate } from 'discord-akairo';
import { type Message } from 'discord.js';
/**
- * A wrapper for the {@link Argument} class that adds custom typings.
+ * Casts a phrase to this argument's type.
+ * @param type - The type to cast to.
+ * @param message - Message that called the command.
+ * @param phrase - Phrase to process.
*/
-export class Arg {
- /**
- * Casts a phrase to this argument's type.
- * @param type - The type to cast to.
- * @param message - Message that called the command.
- * @param phrase - Phrase to process.
- */
- public static async cast<T extends ATC>(type: T, message: CommandMessage | SlashMessage, phrase: string): Promise<ATCR<T>>;
- public static async cast<T extends KBAT>(type: T, message: CommandMessage | SlashMessage, phrase: string): Promise<BAT[T]>;
- public static async cast(type: AT | ATC, message: CommandMessage | SlashMessage, phrase: string): Promise<any>;
- public static async cast(type: ATC | AT, message: CommandMessage | SlashMessage, phrase: string): Promise<any> {
- return Argument.cast(type as any, client.commandHandler.resolver, message as Message, phrase);
- }
+export async function cast<T extends ATC>(type: T, message: CommandMessage | SlashMessage, phrase: string): Promise<ATCR<T>>;
+export async function cast<T extends KBAT>(type: T, message: CommandMessage | SlashMessage, phrase: string): Promise<BAT[T]>;
+export async function cast(type: AT | ATC, message: CommandMessage | SlashMessage, phrase: string): Promise<any>;
+export async function cast(type: ATC | AT, message: CommandMessage | SlashMessage, phrase: string): Promise<any> {
+ return Argument.cast(type as any, client.commandHandler.resolver, message as Message, phrase);
+}
- /**
- * Creates a type that is the left-to-right composition of the given types.
- * If any of the types fails, the entire composition fails.
- * @param types - Types to use.
- */
- public static compose<T extends ATC>(...types: T[]): ATCATCR<T>;
- public static compose<T extends KBAT>(...types: T[]): ATCBAT<T>;
- public static compose(...types: (AT | ATC)[]): ATC;
- public static compose(...types: (AT | ATC)[]): ATC {
- return Argument.compose(...(types as any));
- }
+/**
+ * Creates a type that is the left-to-right composition of the given types.
+ * If any of the types fails, the entire composition fails.
+ * @param types - Types to use.
+ */
+export function compose<T extends ATC>(...types: T[]): ATCATCR<T>;
+export function compose<T extends KBAT>(...types: T[]): ATCBAT<T>;
+export function compose(...types: (AT | ATC)[]): ATC;
+export function compose(...types: (AT | ATC)[]): ATC {
+ return Argument.compose(...(types as any));
+}
- /**
- * Creates a type that is the left-to-right composition of the given types.
- * If any of the types fails, the composition still continues with the failure passed on.
- * @param types - Types to use.
- */
- public static composeWithFailure<T extends ATC>(...types: T[]): ATCATCR<T>;
- public static composeWithFailure<T extends KBAT>(...types: T[]): ATCBAT<T>;
- public static composeWithFailure(...types: (AT | ATC)[]): ATC;
- public static composeWithFailure(...types: (AT | ATC)[]): ATC {
- return Argument.composeWithFailure(...(types as any));
- }
+/**
+ * Creates a type that is the left-to-right composition of the given types.
+ * If any of the types fails, the composition still continues with the failure passed on.
+ * @param types - Types to use.
+ */
+export function composeWithFailure<T extends ATC>(...types: T[]): ATCATCR<T>;
+export function composeWithFailure<T extends KBAT>(...types: T[]): ATCBAT<T>;
+export function composeWithFailure(...types: (AT | ATC)[]): ATC;
+export function composeWithFailure(...types: (AT | ATC)[]): ATC {
+ return Argument.composeWithFailure(...(types as any));
+}
- /**
- * Checks if something is null, undefined, or a fail flag.
- * @param value - Value to check.
- */
- public static isFailure(value: any): value is null | undefined | (Flag & { value: any }) {
- return Argument.isFailure(value);
- }
+/**
+ * Checks if something is null, undefined, or a fail flag.
+ * @param value - Value to check.
+ */
+export function isFailure(value: any): value is null | undefined | (Flag & { value: any }) {
+ return Argument.isFailure(value);
+}
- /**
- * Creates a type from multiple types (product type).
- * Only inputs where each type resolves with a non-void value are valid.
- * @param types - Types to use.
- */
- public static product<T extends ATC>(...types: T[]): ATCATCR<T>;
- public static product<T extends KBAT>(...types: T[]): ATCBAT<T>;
- public static product(...types: (AT | ATC)[]): ATC;
- public static product(...types: (AT | ATC)[]): ATC {
- return Argument.product(...(types as any));
- }
+/**
+ * Creates a type from multiple types (product type).
+ * Only inputs where each type resolves with a non-void value are valid.
+ * @param types - Types to use.
+ */
+export function product<T extends ATC>(...types: T[]): ATCATCR<T>;
+export function product<T extends KBAT>(...types: T[]): ATCBAT<T>;
+export function product(...types: (AT | ATC)[]): ATC;
+export function product(...types: (AT | ATC)[]): ATC {
+ return Argument.product(...(types as any));
+}
- /**
- * Creates a type where the parsed value must be within a range.
- * @param type - The type to use.
- * @param min - Minimum value.
- * @param max - Maximum value.
- * @param inclusive - Whether or not to be inclusive on the upper bound.
- */
- public static range<T extends ATC>(type: T, min: number, max: number, inclusive?: boolean): ATCATCR<T>;
- public static range<T extends KBAT>(type: T, min: number, max: number, inclusive?: boolean): ATCBAT<T>;
- public static range(type: AT | ATC, min: number, max: number, inclusive?: boolean): ATC;
- public static range(type: AT | ATC, min: number, max: number, inclusive?: boolean): ATC {
- return Argument.range(type as any, min, max, inclusive);
- }
+/**
+ * Creates a type where the parsed value must be within a range.
+ * @param type - The type to use.
+ * @param min - Minimum value.
+ * @param max - Maximum value.
+ * @param inclusive - Whether or not to be inclusive on the upper bound.
+ */
+export function range<T extends ATC>(type: T, min: number, max: number, inclusive?: boolean): ATCATCR<T>;
+export function range<T extends KBAT>(type: T, min: number, max: number, inclusive?: boolean): ATCBAT<T>;
+export function range(type: AT | ATC, min: number, max: number, inclusive?: boolean): ATC;
+export function range(type: AT | ATC, min: number, max: number, inclusive?: boolean): ATC {
+ return Argument.range(type as any, min, max, inclusive);
+}
- /**
- * Creates a type that parses as normal but also tags it with some data.
- * Result is in an object `{ tag, value }` and wrapped in `Flag.fail` when failed.
- * @param type - The type to use.
- * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string.
- */
- public static tagged<T extends ATC>(type: T, tag?: any): ATCATCR<T>;
- public static tagged<T extends KBAT>(type: T, tag?: any): ATCBAT<T>;
- public static tagged(type: AT | ATC, tag?: any): ATC;
- public static tagged(type: AT | ATC, tag?: any): ATC {
- return Argument.tagged(type as any, tag);
- }
+/**
+ * Creates a type that parses as normal but also tags it with some data.
+ * Result is in an object `{ tag, value }` and wrapped in `Flag.fail` when failed.
+ * @param type - The type to use.
+ * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string.
+ */
+export function tagged<T extends ATC>(type: T, tag?: any): ATCATCR<T>;
+export function tagged<T extends KBAT>(type: T, tag?: any): ATCBAT<T>;
+export function tagged(type: AT | ATC, tag?: any): ATC;
+export function tagged(type: AT | ATC, tag?: any): ATC {
+ return Argument.tagged(type as any, tag);
+}
- /**
- * Creates a type from multiple types (union type).
- * The first type that resolves to a non-void value is used.
- * Each type will also be tagged using `tagged` with themselves.
- * @param types - Types to use.
- */
- public static taggedUnion<T extends ATC>(...types: T[]): ATCATCR<T>;
- public static taggedUnion<T extends KBAT>(...types: T[]): ATCBAT<T>;
- public static taggedUnion(...types: (AT | ATC)[]): ATC;
- public static taggedUnion(...types: (AT | ATC)[]): ATC {
- return Argument.taggedUnion(...(types as any));
- }
+/**
+ * Creates a type from multiple types (union type).
+ * The first type that resolves to a non-void value is used.
+ * Each type will also be tagged using `tagged` with themselves.
+ * @param types - Types to use.
+ */
+export function taggedUnion<T extends ATC>(...types: T[]): ATCATCR<T>;
+export function taggedUnion<T extends KBAT>(...types: T[]): ATCBAT<T>;
+export function taggedUnion(...types: (AT | ATC)[]): ATC;
+export function taggedUnion(...types: (AT | ATC)[]): ATC {
+ return Argument.taggedUnion(...(types as any));
+}
- /**
- * Creates a type that parses as normal but also tags it with some data and carries the original input.
- * Result is in an object `{ tag, input, value }` and wrapped in `Flag.fail` when failed.
- * @param type - The type to use.
- * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string.
- */
- public static taggedWithInput<T extends ATC>(type: T, tag?: any): ATCATCR<T>;
- public static taggedWithInput<T extends KBAT>(type: T, tag?: any): ATCBAT<T>;
- public static taggedWithInput(type: AT | ATC, tag?: any): ATC;
- public static taggedWithInput(type: AT | ATC, tag?: any): ATC {
- return Argument.taggedWithInput(type as any, tag);
- }
+/**
+ * Creates a type that parses as normal but also tags it with some data and carries the original input.
+ * Result is in an object `{ tag, input, value }` and wrapped in `Flag.fail` when failed.
+ * @param type - The type to use.
+ * @param tag - Tag to add. Defaults to the `type` argument, so useful if it is a string.
+ */
+export function taggedWithInput<T extends ATC>(type: T, tag?: any): ATCATCR<T>;
+export function taggedWithInput<T extends KBAT>(type: T, tag?: any): ATCBAT<T>;
+export function taggedWithInput(type: AT | ATC, tag?: any): ATC;
+export function taggedWithInput(type: AT | ATC, tag?: any): ATC {
+ return Argument.taggedWithInput(type as any, tag);
+}
- /**
- * Creates a type from multiple types (union type).
- * The first type that resolves to a non-void value is used.
- * @param types - Types to use.
- */
- public static union<T extends ATC>(...types: T[]): ATCATCR<T>;
- public static union<T extends KBAT>(...types: T[]): ATCBAT<T>;
- public static union(...types: (AT | ATC)[]): ATC;
- public static union(...types: (AT | ATC)[]): ATC {
- return Argument.union(...(types as any));
- }
+/**
+ * Creates a type from multiple types (union type).
+ * The first type that resolves to a non-void value is used.
+ * @param types - Types to use.
+ */
+export function union<T extends ATC>(...types: T[]): ATCATCR<T>;
+export function union<T extends KBAT>(...types: T[]): ATCBAT<T>;
+export function union(...types: (AT | ATC)[]): ATC;
+export function union(...types: (AT | ATC)[]): ATC {
+ return Argument.union(...(types as any));
+}
- /**
- * Creates a type with extra validation.
- * If the predicate is not true, the value is considered invalid.
- * @param type - The type to use.
- * @param predicate - The predicate function.
- */
- public static validate<T extends ATC>(type: T, predicate: ParsedValuePredicate): ATCATCR<T>;
- public static validate<T extends KBAT>(type: T, predicate: ParsedValuePredicate): ATCBAT<T>;
- public static validate(type: AT | ATC, predicate: ParsedValuePredicate): ATC;
- public static validate(type: AT | ATC, predicate: ParsedValuePredicate): ATC {
- return Argument.validate(type as any, predicate);
- }
+/**
+ * Creates a type with extra validation.
+ * If the predicate is not true, the value is considered invalid.
+ * @param type - The type to use.
+ * @param predicate - The predicate function.
+ */
+export function validate<T extends ATC>(type: T, predicate: ParsedValuePredicate): ATCATCR<T>;
+export function validate<T extends KBAT>(type: T, predicate: ParsedValuePredicate): ATCBAT<T>;
+export function validate(type: AT | ATC, predicate: ParsedValuePredicate): ATC;
+export function validate(type: AT | ATC, predicate: ParsedValuePredicate): ATC {
+ return Argument.validate(type as any, predicate);
+}
- /**
- * Creates a type that parses as normal but also carries the original input.
- * Result is in an object `{ input, value }` and wrapped in `Flag.fail` when failed.
- * @param type - The type to use.
- */
- public static withInput<T extends ATC>(type: T): ATC<ATCR<T>>;
- public static withInput<T extends KBAT>(type: T): ATCBAT<T>;
- public static withInput(type: AT | ATC): ATC;
- public static withInput(type: AT | ATC): ATC {
- return Argument.withInput(type as any);
- }
+/**
+ * Creates a type that parses as normal but also carries the original input.
+ * Result is in an object `{ input, value }` and wrapped in `Flag.fail` when failed.
+ * @param type - The type to use.
+ */
+export function withInput<T extends ATC>(type: T): ATC<ATCR<T>>;
+export function withInput<T extends KBAT>(type: T): ATCBAT<T>;
+export function withInput(type: AT | ATC): ATC;
+export function withInput(type: AT | ATC): ATC {
+ return Argument.withInput(type as any);
}
type BushArgumentTypeCasterReturn<R> = R extends BushArgumentTypeCaster<infer S> ? S : R;
diff --git a/src/lib/common/util/Format.ts b/src/lib/common/util/Format.ts
index 6cb6edc..260a0be 100644
--- a/src/lib/common/util/Format.ts
+++ b/src/lib/common/util/Format.ts
@@ -1,107 +1,112 @@
import { type CodeBlockLang } from '#lib';
-import { EscapeMarkdownOptions, Formatters, Util } from 'discord.js';
+import {
+ escapeBold,
+ escapeCodeBlock,
+ escapeInlineCode,
+ escapeItalic,
+ EscapeMarkdownOptions,
+ escapeSpoiler,
+ escapeStrikethrough,
+ escapeUnderline,
+ Formatters
+} from 'discord.js';
/**
- * Formats and escapes content for formatting
+ * Wraps the content inside a codeblock with no language.
+ * @param content The content to wrap.
*/
-export class Format {
- /**
- * Wraps the content inside a codeblock with no language.
- * @param content The content to wrap.
- */
- public static codeBlock(content: string): string;
+export function codeBlock(content: string): string;
- /**
- * Wraps the content inside a codeblock with the specified language.
- * @param language The language for the codeblock.
- * @param content The content to wrap.
- */
- 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(`${content}`));
- }
+/**
+ * Wraps the content inside a codeblock with the specified language.
+ * @param language The language for the codeblock.
+ * @param content The content to wrap.
+ */
+export function codeBlock(language: CodeBlockLang, content: string): string;
+export function codeBlock(languageOrContent: string, content?: string): string {
+ return typeof content === 'undefined'
+ ? Formatters.codeBlock(escapeCodeBlock(`${languageOrContent}`))
+ : Formatters.codeBlock(`${languageOrContent}`, escapeCodeBlock(`${content}`));
+}
- /**
- * Wraps the content inside \`backticks\`, which formats it as inline code.
- * @param content The content to wrap.
- */
- public static inlineCode(content: string): string {
- return Formatters.inlineCode(Util.escapeInlineCode(`${content}`));
- }
+/**
+ * Wraps the content inside \`backticks\`, which formats it as inline code.
+ * @param content The content to wrap.
+ */
+export function inlineCode(content: string): string {
+ return Formatters.inlineCode(escapeInlineCode(`${content}`));
+}
- /**
- * Formats the content into italic text.
- * @param content The content to wrap.
- */
- public static italic(content: string): string {
- return Formatters.italic(Util.escapeItalic(`${content}`));
- }
+/**
+ * Formats the content into italic text.
+ * @param content The content to wrap.
+ */
+export function italic(content: string): string {
+ return Formatters.italic(escapeItalic(`${content}`));
+}
- /**
- * Formats the content into bold text.
- * @param content The content to wrap.
- */
- public static bold(content: string): string {
- return Formatters.bold(Util.escapeBold(`${content}`));
- }
+/**
+ * Formats the content into bold text.
+ * @param content The content to wrap.
+ */
+export function bold(content: string): string {
+ return Formatters.bold(escapeBold(`${content}`));
+}
- /**
- * Formats the content into underscored text.
- * @param content The content to wrap.
- */
- public static underscore(content: string): string {
- return Formatters.underscore(Util.escapeUnderline(`${content}`));
- }
+/**
+ * Formats the content into underscored text.
+ * @param content The content to wrap.
+ */
+export function underscore(content: string): string {
+ return Formatters.underscore(escapeUnderline(`${content}`));
+}
- /**
- * Formats the content into strike-through text.
- * @param content The content to wrap.
- */
- public static strikethrough(content: string): string {
- return Formatters.strikethrough(Util.escapeStrikethrough(`${content}`));
- }
+/**
+ * Formats the content into strike-through text.
+ * @param content The content to wrap.
+ */
+export function strikethrough(content: string): string {
+ return Formatters.strikethrough(escapeStrikethrough(`${content}`));
+}
- /**
- * Wraps the content inside spoiler (hidden text).
- * @param content The content to wrap.
- */
- public static spoiler(content: string): string {
- return Formatters.spoiler(Util.escapeSpoiler(`${content}`));
- }
+/**
+ * Wraps the content inside spoiler (hidden text).
+ * @param content The content to wrap.
+ */
+export function spoiler(content: string): string {
+ return Formatters.spoiler(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);
- }
+/**
+ * Escapes any Discord-flavour markdown in a string.
+ * @param text Content to escape
+ * @param options Options for escaping the markdown
+ */
+export function escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string {
+ return 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: makes it bold and escapes any other markdown
+ * @param text The input
+ */
+export function input(text: string): string {
+ return bold(escapeMarkdown(sanitizeWtlAndControl(`${text}`)));
+}
- /**
- * Formats input for logs: makes it highlighted
- * @param text The input
- */
- public static inputLog(text: string): string {
- return `<<${this.sanitizeWtlAndControl(`${text}`)}>>`;
- }
+/**
+ * Formats input for logs: makes it highlighted
+ * @param text The input
+ */
+export function inputLog(text: string): string {
+ return `<<${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, '');
- }
+/**
+ * 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
+ */
+export function 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/Moderation.ts b/src/lib/common/util/Moderation.ts
index 6cdc141..a08dfa4 100644
--- a/src/lib/common/util/Moderation.ts
+++ b/src/lib/common/util/Moderation.ts
@@ -1,4 +1,16 @@
-import { ActivePunishment, ActivePunishmentType, Guild as GuildDB, ModLog, type ModLogType } from '#lib';
+import {
+ ActivePunishment,
+ ActivePunishmentType,
+ colors,
+ emojis,
+ format,
+ Guild as GuildDB,
+ handleError,
+ humanizeDuration,
+ ModLog,
+ resolveNonCachedUser,
+ type ModLogType
+} from '#lib';
import assert from 'assert';
import {
ActionRowBuilder,
@@ -40,275 +52,270 @@ enum reversedPunishMap {
}
/**
- * A utility class with moderation-related methods.
+ * Checks if a moderator can perform a moderation action on another user.
+ * @param moderator The person trying to perform the action.
+ * @param victim The person getting punished.
+ * @param type The type of punishment - used to format the response.
+ * @param checkModerator Whether or not to check if the victim is a moderator.
+ * @param force Override permissions checks.
+ * @returns `true` if the moderator can perform the action otherwise a reason why they can't.
*/
-export class Moderation {
- /**
- * Checks if a moderator can perform a moderation action on another user.
- * @param moderator The person trying to perform the action.
- * @param victim The person getting punished.
- * @param type The type of punishment - used to format the response.
- * @param checkModerator Whether or not to check if the victim is a moderator.
- * @param force Override permissions checks.
- * @returns `true` if the moderator can perform the action otherwise a reason why they can't.
- */
- public static async permissionCheck(
- moderator: GuildMember,
- victim: GuildMember,
- type:
- | 'mute'
- | 'unmute'
- | 'warn'
- | 'kick'
- | 'ban'
- | 'unban'
- | 'add a punishment role to'
- | 'remove a punishment role from'
- | 'block'
- | 'unblock'
- | 'timeout'
- | 'untimeout',
- checkModerator = true,
- force = false
- ): Promise<true | string> {
- if (force) return true;
-
- // If the victim is not in the guild anymore it will be undefined
- if ((!victim || !victim.guild) && !['ban', 'unban'].includes(type)) return true;
-
- if (moderator.guild.id !== victim.guild.id) {
- throw new Error('moderator and victim not in same guild');
- }
-
- const isOwner = moderator.guild.ownerId === moderator.id;
- if (moderator.id === victim.id && !type.startsWith('un')) {
- return `${util.emojis.error} You cannot ${type} yourself.`;
- }
- if (
- moderator.roles.highest.position <= victim.roles.highest.position &&
- !isOwner &&
- !(type.startsWith('un') && moderator.id === victim.id)
- ) {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as you do.`;
- }
- if (
- victim.roles.highest.position >= victim.guild.members.me!.roles.highest.position &&
- !(type.startsWith('un') && moderator.id === victim.id)
- ) {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as I do.`;
- }
- if (
- checkModerator &&
- victim.permissions.has(PermissionFlagsBits.ManageMessages) &&
- !(type.startsWith('un') && moderator.id === victim.id)
- ) {
- if (await moderator.guild.hasFeature('modsCanPunishMods')) {
- return true;
- } else {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they are a moderator.`;
- }
- }
- return true;
+export async function permissionCheck(
+ moderator: GuildMember,
+ victim: GuildMember,
+ type:
+ | 'mute'
+ | 'unmute'
+ | 'warn'
+ | 'kick'
+ | 'ban'
+ | 'unban'
+ | 'add a punishment role to'
+ | 'remove a punishment role from'
+ | 'block'
+ | 'unblock'
+ | 'timeout'
+ | 'untimeout',
+ checkModerator = true,
+ force = false
+): Promise<true | string> {
+ if (force) return true;
+
+ // If the victim is not in the guild anymore it will be undefined
+ if ((!victim || !victim.guild) && !['ban', 'unban'].includes(type)) return true;
+
+ if (moderator.guild.id !== victim.guild.id) {
+ throw new Error('moderator and victim not in same guild');
}
- /**
- * Creates a modlog entry for a punishment.
- * @param options Options for creating a modlog entry.
- * @param getCaseNumber Whether or not to get the case number of the entry.
- * @returns An object with the modlog and the case number.
- */
- public static async createModLogEntry(
- options: CreateModLogEntryOptions,
- getCaseNumber = false
- ): Promise<{ log: ModLog | null; caseNum: number | null }> {
- const user = (await util.resolveNonCachedUser(options.user))!.id;
- const moderator = (await util.resolveNonCachedUser(options.moderator))!.id;
- const guild = client.guilds.resolveId(options.guild)!;
-
- return this.createModLogEntrySimple(
- {
- ...options,
- user: user,
- moderator: moderator,
- guild: guild
- },
- getCaseNumber
- );
+ const isOwner = moderator.guild.ownerId === moderator.id;
+ if (moderator.id === victim.id && !type.startsWith('un')) {
+ return `${emojis.error} You cannot ${type} yourself.`;
}
-
- /**
- * Creates a modlog entry with already resolved ids.
- * @param options Options for creating a modlog entry.
- * @param getCaseNumber Whether or not to get the case number of the entry.
- * @returns An object with the modlog and the case number.
- */
- public static async createModLogEntrySimple(
- options: SimpleCreateModLogEntryOptions,
- getCaseNumber = false
- ): Promise<{ log: ModLog | null; caseNum: number | null }> {
- // If guild does not exist create it so the modlog can reference a guild.
- await GuildDB.findOrCreate({
- where: { id: options.guild },
- defaults: { id: options.guild }
- });
-
- const modLogEntry = ModLog.build({
- type: options.type,
- user: options.user,
- moderator: options.moderator,
- reason: options.reason,
- duration: options.duration ? options.duration : undefined,
- guild: options.guild,
- pseudo: options.pseudo ?? false,
- evidence: options.evidence,
- hidden: options.hidden ?? false
- });
- const saveResult: ModLog | null = await modLogEntry.save().catch(async (e) => {
- await util.handleError('createModLogEntry', e);
- return null;
- });
-
- if (!getCaseNumber) return { log: saveResult, caseNum: null };
-
- const caseNum = (
- await ModLog.findAll({ where: { type: options.type, user: options.user, guild: options.guild, hidden: false } })
- )?.length;
- return { log: saveResult, caseNum };
+ if (
+ moderator.roles.highest.position <= victim.roles.highest.position &&
+ !isOwner &&
+ !(type.startsWith('un') && moderator.id === victim.id)
+ ) {
+ return `${emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as you do.`;
}
-
- /**
- * Creates a punishment entry.
- * @param options Options for creating the punishment entry.
- * @returns The database entry, or null if no entry is created.
- */
- public static async createPunishmentEntry(options: CreatePunishmentEntryOptions): Promise<ActivePunishment | null> {
- const expires = options.duration ? new Date(+new Date() + options.duration ?? 0) : undefined;
- const user = (await util.resolveNonCachedUser(options.user))!.id;
- const guild = client.guilds.resolveId(options.guild)!;
- const type = this.findTypeEnum(options.type)!;
-
- const entry = ActivePunishment.build(
- options.extraInfo
- ? { user, type, guild, expires, modlog: options.modlog, extraInfo: options.extraInfo }
- : { user, type, guild, expires, modlog: options.modlog }
- );
- return await entry.save().catch(async (e) => {
- await util.handleError('createPunishmentEntry', e);
- return null;
- });
+ if (
+ victim.roles.highest.position >= victim.guild.members.me!.roles.highest.position &&
+ !(type.startsWith('un') && moderator.id === victim.id)
+ ) {
+ return `${emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as I do.`;
}
-
- /**
- * Destroys a punishment entry.
- * @param options Options for destroying the punishment entry.
- * @returns Whether or not the entry was destroyed.
- */
- public static async removePunishmentEntry(options: RemovePunishmentEntryOptions): Promise<boolean> {
- const user = await util.resolveNonCachedUser(options.user);
- const guild = client.guilds.resolveId(options.guild);
- const type = this.findTypeEnum(options.type);
-
- if (!user || !guild) return false;
-
- let success = true;
-
- const entries = await ActivePunishment.findAll({
- // finding all cases of a certain type incase there were duplicates or something
- where: options.extraInfo
- ? { user: user.id, guild: guild, type, extraInfo: options.extraInfo }
- : { user: user.id, guild: guild, type }
- }).catch(async (e) => {
- await util.handleError('removePunishmentEntry', e);
- success = false;
- });
- if (entries) {
- const promises = entries.map(async (entry) =>
- entry.destroy().catch(async (e) => {
- await util.handleError('removePunishmentEntry', e);
- success = false;
- })
- );
-
- await Promise.all(promises);
+ if (
+ checkModerator &&
+ victim.permissions.has(PermissionFlagsBits.ManageMessages) &&
+ !(type.startsWith('un') && moderator.id === victim.id)
+ ) {
+ if (await moderator.guild.hasFeature('modsCanPunishMods')) {
+ return true;
+ } else {
+ return `${emojis.error} You cannot ${type} **${victim.user.tag}** because they are a moderator.`;
}
- return success;
}
+ return true;
+}
- /**
- * Returns the punishment type enum for the given type.
- * @param type The type of the punishment.
- * @returns The punishment type enum.
- */
- private static findTypeEnum(type: 'mute' | 'ban' | 'role' | 'block') {
- const typeMap = {
- ['mute']: ActivePunishmentType.MUTE,
- ['ban']: ActivePunishmentType.BAN,
- ['role']: ActivePunishmentType.ROLE,
- ['block']: ActivePunishmentType.BLOCK
- };
- return typeMap[type];
- }
+/**
+ * Creates a modlog entry for a punishment.
+ * @param options Options for creating a modlog entry.
+ * @param getCaseNumber Whether or not to get the case number of the entry.
+ * @returns An object with the modlog and the case number.
+ */
+export async function createModLogEntry(
+ options: CreateModLogEntryOptions,
+ getCaseNumber = false
+): Promise<{ log: ModLog | null; caseNum: number | null }> {
+ const user = (await resolveNonCachedUser(options.user))!.id;
+ const moderator = (await resolveNonCachedUser(options.moderator))!.id;
+ const guild = client.guilds.resolveId(options.guild)!;
+
+ return createModLogEntrySimple(
+ {
+ ...options,
+ user: user,
+ moderator: moderator,
+ guild: guild
+ },
+ getCaseNumber
+ );
+}
- public static punishmentToPresentTense(punishment: PunishmentTypeDM): PunishmentTypePresent {
- return punishMap[punishment];
- }
+/**
+ * Creates a modlog entry with already resolved ids.
+ * @param options Options for creating a modlog entry.
+ * @param getCaseNumber Whether or not to get the case number of the entry.
+ * @returns An object with the modlog and the case number.
+ */
+export async function createModLogEntrySimple(
+ options: SimpleCreateModLogEntryOptions,
+ getCaseNumber = false
+): Promise<{ log: ModLog | null; caseNum: number | null }> {
+ // If guild does not exist create it so the modlog can reference a guild.
+ await GuildDB.findOrCreate({
+ where: { id: options.guild },
+ defaults: { id: options.guild }
+ });
+
+ const modLogEntry = ModLog.build({
+ type: options.type,
+ user: options.user,
+ moderator: options.moderator,
+ reason: options.reason,
+ duration: options.duration ? options.duration : undefined,
+ guild: options.guild,
+ pseudo: options.pseudo ?? false,
+ evidence: options.evidence,
+ hidden: options.hidden ?? false
+ });
+ const saveResult: ModLog | null = await modLogEntry.save().catch(async (e) => {
+ await handleError('createModLogEntry', e);
+ return null;
+ });
+
+ if (!getCaseNumber) return { log: saveResult, caseNum: null };
+
+ const caseNum = (
+ await ModLog.findAll({ where: { type: options.type, user: options.user, guild: options.guild, hidden: false } })
+ )?.length;
+ return { log: saveResult, caseNum };
+}
- public static punishmentToPastTense(punishment: PunishmentTypePresent): PunishmentTypeDM {
- return reversedPunishMap[punishment];
- }
+/**
+ * Creates a punishment entry.
+ * @param options Options for creating the punishment entry.
+ * @returns The database entry, or null if no entry is created.
+ */
+export async function createPunishmentEntry(options: CreatePunishmentEntryOptions): Promise<ActivePunishment | null> {
+ const expires = options.duration ? new Date(+new Date() + options.duration ?? 0) : undefined;
+ const user = (await resolveNonCachedUser(options.user))!.id;
+ const guild = client.guilds.resolveId(options.guild)!;
+ const type = findTypeEnum(options.type)!;
+
+ const entry = ActivePunishment.build(
+ options.extraInfo
+ ? { user, type, guild, expires, modlog: options.modlog, extraInfo: options.extraInfo }
+ : { user, type, guild, expires, modlog: options.modlog }
+ );
+ return await entry.save().catch(async (e) => {
+ await handleError('createPunishmentEntry', e);
+ return null;
+ });
+}
- /**
- * Notifies the specified user of their punishment.
- * @param options Options for notifying the user.
- * @returns Whether or not the dm was successfully sent.
- */
- public static async punishDM(options: PunishDMOptions): Promise<boolean> {
- const ending = await options.guild.getSetting('punishmentEnding');
- const dmEmbed =
- ending && ending.length && options.sendFooter
- ? new EmbedBuilder().setDescription(ending).setColor(util.colors.newBlurple)
- : undefined;
-
- const appealsEnabled = !!(
- (await options.guild.hasFeature('punishmentAppeals')) && (await options.guild.getLogChannel('appeals'))
+/**
+ * Destroys a punishment entry.
+ * @param options Options for destroying the punishment entry.
+ * @returns Whether or not the entry was destroyed.
+ */
+export async function removePunishmentEntry(options: RemovePunishmentEntryOptions): Promise<boolean> {
+ const user = await resolveNonCachedUser(options.user);
+ const guild = client.guilds.resolveId(options.guild);
+ const type = findTypeEnum(options.type);
+
+ if (!user || !guild) return false;
+
+ let success = true;
+
+ const entries = await ActivePunishment.findAll({
+ // finding all cases of a certain type incase there were duplicates or something
+ where: options.extraInfo
+ ? { user: user.id, guild: guild, type, extraInfo: options.extraInfo }
+ : { user: user.id, guild: guild, type }
+ }).catch(async (e) => {
+ await handleError('removePunishmentEntry', e);
+ success = false;
+ });
+ if (entries) {
+ const promises = entries.map(async (entry) =>
+ entry.destroy().catch(async (e) => {
+ await handleError('removePunishmentEntry', e);
+ success = false;
+ })
);
- let content = `You have been ${options.punishment} `;
- if (options.punishment.includes('blocked')) {
- assert(options.channel);
- content += `from <#${options.channel}> `;
- }
- content += `in ${util.format.input(options.guild.name)} `;
- if (options.duration !== null && options.duration !== undefined)
- content += options.duration ? `for ${util.humanizeDuration(options.duration)} ` : 'permanently ';
- const reason = options.reason?.trim() ? options.reason?.trim() : 'No reason provided';
- content += `for ${util.format.input(reason)}.`;
-
- let components;
- if (appealsEnabled && options.modlog)
- components = [
- new ActionRowBuilder<ButtonBuilder>({
- components: [
- new ButtonBuilder({
- customId: `appeal;${this.punishmentToPresentTense(options.punishment)};${options.guild.id};${client.users.resolveId(
- options.user
- )};${options.modlog}`,
- style: ButtonStyle.Primary,
- label: 'Appeal'
- }).toJSON()
- ]
- })
- ];
-
- const dmSuccess = await client.users
- .send(options.user, {
- content,
- embeds: dmEmbed ? [dmEmbed] : undefined,
- components
- })
- .catch(() => false);
- return !!dmSuccess;
+ await Promise.all(promises);
}
+ return success;
+}
+
+/**
+ * Returns the punishment type enum for the given type.
+ * @param type The type of the punishment.
+ * @returns The punishment type enum.
+ */
+function findTypeEnum(type: 'mute' | 'ban' | 'role' | 'block') {
+ const typeMap = {
+ ['mute']: ActivePunishmentType.MUTE,
+ ['ban']: ActivePunishmentType.BAN,
+ ['role']: ActivePunishmentType.ROLE,
+ ['block']: ActivePunishmentType.BLOCK
+ };
+ return typeMap[type];
+}
+
+export function punishmentToPresentTense(punishment: PunishmentTypeDM): PunishmentTypePresent {
+ return punishMap[punishment];
+}
+
+export function punishmentToPastTense(punishment: PunishmentTypePresent): PunishmentTypeDM {
+ return reversedPunishMap[punishment];
+}
+
+/**
+ * Notifies the specified user of their punishment.
+ * @param options Options for notifying the user.
+ * @returns Whether or not the dm was successfully sent.
+ */
+export async function punishDM(options: PunishDMOptions): Promise<boolean> {
+ const ending = await options.guild.getSetting('punishmentEnding');
+ const dmEmbed =
+ ending && ending.length && options.sendFooter
+ ? new EmbedBuilder().setDescription(ending).setColor(colors.newBlurple)
+ : undefined;
+
+ const appealsEnabled = !!(
+ (await options.guild.hasFeature('punishmentAppeals')) && (await options.guild.getLogChannel('appeals'))
+ );
+
+ let content = `You have been ${options.punishment} `;
+ if (options.punishment.includes('blocked')) {
+ assert(options.channel);
+ content += `from <#${options.channel}> `;
+ }
+ content += `in ${format.input(options.guild.name)} `;
+ if (options.duration !== null && options.duration !== undefined)
+ content += options.duration ? `for ${humanizeDuration(options.duration)} ` : 'permanently ';
+ const reason = options.reason?.trim() ? options.reason?.trim() : 'No reason provided';
+ content += `for ${format.input(reason)}.`;
+
+ let components;
+ if (appealsEnabled && options.modlog)
+ components = [
+ new ActionRowBuilder<ButtonBuilder>({
+ components: [
+ new ButtonBuilder({
+ customId: `appeal;${punishmentToPresentTense(options.punishment)};${options.guild.id};${client.users.resolveId(
+ options.user
+ )};${options.modlog}`,
+ style: ButtonStyle.Primary,
+ label: 'Appeal'
+ }).toJSON()
+ ]
+ })
+ ];
+
+ const dmSuccess = await client.users
+ .send(options.user, {
+ content,
+ embeds: dmEmbed ? [dmEmbed] : undefined,
+ components
+ })
+ .catch(() => false);
+ return !!dmSuccess;
}
interface BaseCreateModLogEntryOptions {
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
index 2644231..b382121 100644
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ b/src/lib/extensions/discord-akairo/BushClient.ts
@@ -10,7 +10,7 @@ import {
roleWithDuration,
snowflake
} from '#args';
-import type { BushClientEvents, Config } from '#lib';
+import { BushClientEvents, emojis, formatError, inspect } from '#lib';
import { patch, type PatchedElements } from '@notenoughupdates/events-intercept';
import * as Sentry from '@sentry/node';
import {
@@ -18,7 +18,6 @@ import {
ContextMenuCommandHandler,
version as akairoVersion,
type ArgumentPromptData,
- type ClientUtil,
type OtherwiseContentSupplier
} from 'discord-akairo';
import {
@@ -46,6 +45,7 @@ import path from 'path';
import readline from 'readline';
import type { Options as SequelizeOptions, Sequelize as SequelizeType } from 'sequelize';
import { fileURLToPath } from 'url';
+import type { Config } from '../../../../config/Config.js';
import { tinyColor } from '../../../arguments/tinyColor.js';
import UpdateCacheTask from '../../../tasks/updateCache.js';
import UpdateStatsTask from '../../../tasks/updateStats.js';
@@ -63,13 +63,11 @@ import { Shared } from '../../models/shared/Shared.js';
import { Stat } from '../../models/shared/Stat.js';
import { AllowedMentions } from '../../utils/AllowedMentions.js';
import { BushCache } from '../../utils/BushCache.js';
-import { BushConstants } from '../../utils/BushConstants.js';
-import { BushLogger } from '../../utils/BushLogger.js';
+import BushLogger from '../../utils/BushLogger.js';
import { ExtendedGuild } from '../discord.js/ExtendedGuild.js';
import { ExtendedGuildMember } from '../discord.js/ExtendedGuildMember.js';
import { ExtendedMessage } from '../discord.js/ExtendedMessage.js';
import { ExtendedUser } from '../discord.js/ExtendedUser.js';
-import { BushClientUtil } from './BushClientUtil.js';
import { BushCommandHandler } from './BushCommandHandler.js';
import { BushInhibitorHandler } from './BushInhibitorHandler.js';
import { BushListenerHandler } from './BushListenerHandler.js';
@@ -86,10 +84,6 @@ declare module 'discord.js' {
* The ID of the superUser(s).
*/
superUserID: Snowflake | Snowflake[];
- /**
- * Utility methods.
- */
- util: ClientUtil | BushClientUtil;
on<K extends keyof BushClientEvents>(event: K, listener: (...args: BushClientEvents[K]) => Awaitable<void>): this;
once<K extends keyof BushClientEvents>(event: K, listener: (...args: BushClientEvents[K]) => Awaitable<void>): this;
emit<K extends keyof BushClientEvents>(event: K, ...args: BushClientEvents[K]): boolean;
@@ -128,7 +122,6 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Ready> {
public declare ownerID: Snowflake[];
public declare superUserID: Snowflake[];
- public declare util: BushClientUtil;
/**
* Whether or not the client is ready.
@@ -141,11 +134,6 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
public stats: BushStats = { cpu: undefined, commandsUsed: 0n, slashCommandsUsed: 0n };
/**
- * The configuration for the client.
- */
- public config: Config;
-
- /**
* The handler for the bot's listeners.
*/
public listenerHandler: BushListenerHandler;
@@ -186,11 +174,6 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
public logger = BushLogger;
/**
- * Constants for the bot.
- */
- public constants = BushConstants;
-
- /**
* Cached global and guild database data.
*/
public cache = new BushCache();
@@ -213,7 +196,12 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
/**
* @param config The configuration for the bot.
*/
- public constructor(config: Config) {
+ public constructor(
+ /**
+ * The configuration for the client.
+ */
+ public config: Config
+ ) {
super({
ownerID: config.owners,
intents: Object.keys(GatewayIntentBits)
@@ -233,7 +221,6 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
this.token = config.token as If<Ready, string, string | null>;
this.config = config;
- this.util = new BushClientUtil(this);
/* =-=-= handlers =-=-= */
this.listenerHandler = new BushListenerHandler(this, {
@@ -258,7 +245,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
const ending = '\n\n Type **cancel** to cancel the command';
const options = typeof text === 'function' ? await text(message, data) : text;
const search = '{error}',
- replace = this.consts.emojis.error;
+ replace = emojis.error;
if (typeof options === 'string') return (replaceError ? options.replace(search, replace) : options) + ending;
@@ -338,13 +325,6 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
}
/**
- * Constants for the bot.
- */
- public get consts(): typeof BushConstants {
- return this.constants;
- }
-
- /**
* Extends discord.js structures before the client is instantiated.
*/
public static extendStructures(): void {
@@ -422,11 +402,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
void this.logger.success('startup', `Successfully loaded <<${handlerName}>>.`, false);
})
.catch((e) => {
- void this.logger.error(
- 'startup',
- `Unable to load loader <<${handlerName}>> with error:\n${util.formatError(e)}`,
- false
- );
+ void this.logger.error('startup', `Unable to load loader <<${handlerName}>> with error:\n${formatError(e)}`, false);
if (process.argv.includes('dry')) process.exit(1);
})
);
@@ -451,7 +427,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
} catch (e) {
await this.console.error(
'startup',
- `Failed to connect to <<instance database>> with error:\n${util.inspect(e, { colors: true, depth: 1 })}`,
+ `Failed to connect to <<instance database>> with error:\n${inspect(e, { colors: true, depth: 1 })}`,
false
);
process.exit(2);
@@ -471,7 +447,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
} catch (e) {
await this.console.error(
'startup',
- `Failed to connect to <<shared database>> with error:\n${util.inspect(e, { colors: true, depth: 1 })}`,
+ `Failed to connect to <<shared database>> with error:\n${inspect(e, { colors: true, depth: 1 })}`,
false
);
process.exit(2);
@@ -503,7 +479,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
this.stats.slashCommandsUsed = stats.slashCommandsUsed;
await this.login(this.token!);
} catch (e) {
- await this.console.error('start', util.inspect(e, { colors: true, depth: 1 }), false);
+ await this.console.error('start', inspect(e, { colors: true, depth: 1 }), false);
process.exit(1);
}
}
diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts
deleted file mode 100644
index 19810bd..0000000
--- a/src/lib/extensions/discord-akairo/BushClientUtil.ts
+++ /dev/null
@@ -1,1187 +0,0 @@
-import {
- Arg,
- BushConstants,
- CommandMessage,
- Global,
- Shared,
- type BaseBushArgumentType,
- type BushClient,
- type BushInspectOptions,
- type CodeBlockLang,
- type GlobalCache,
- type Pronoun,
- type PronounCode,
- type SharedCache,
- type SlashEditMessageType,
- type SlashMessage,
- type SlashSendMessageType
-} from '#lib';
-import { humanizeDuration } from '@notenoughupdates/humanize-duration';
-import assert from 'assert';
-import { exec } from 'child_process';
-import deepLock from 'deep-lock';
-import { ClientUtil, Util as AkairoUtil } from 'discord-akairo';
-import {
- Constants as DiscordConstants,
- EmbedBuilder,
- GuildMember,
- Message,
- OAuth2Scopes,
- PermissionFlagsBits,
- PermissionsBitField,
- Routes,
- ThreadMember,
- User,
- Util as DiscordUtil,
- type APIEmbed,
- type APIMessage,
- type CommandInteraction,
- type InteractionReplyOptions,
- type PermissionsString,
- type Snowflake,
- type TextChannel,
- type UserResolvable
-} from 'discord.js';
-import got from 'got';
-import _ from 'lodash';
-import { inspect, promisify } from 'util';
-import CommandErrorListener from '../../../listeners/commands/commandError.js';
-import { Format } from '../../common/util/Format.js';
-
-export type StripPrivate<T> = { [K in keyof T]: T[K] extends Record<string, any> ? StripPrivate<T[K]> : T[K] };
-
-export class BushClientUtil extends ClientUtil {
- /**
- * The client.
- */
- public declare readonly client: BushClient;
-
- /**
- * The hastebin urls used to post to hastebin, attempts to post in order
- */
- #hasteURLs: string[] = [
- 'https://hst.sh',
- // 'https://hasteb.in',
- 'https://hastebin.com',
- 'https://mystb.in',
- 'https://haste.clicksminuteper.net',
- 'https://paste.pythondiscord.com',
- 'https://haste.unbelievaboat.com'
- // 'https://haste.tyman.tech'
- ];
-
- /**
- * Creates this client util
- * @param client The client to initialize with
- */
- public constructor(client: BushClient) {
- super(client);
- }
-
- /**
- * Maps an array of user ids to user objects.
- * @param ids The list of IDs to map
- * @returns The list of users mapped
- */
- public async mapIDs(ids: Snowflake[]): Promise<User[]> {
- return await Promise.all(ids.map((id) => client.users.fetch(id)));
- }
-
- /**
- * Capitalizes the first letter of the given text
- * @param text The text to capitalize
- * @returns The capitalized text
- */
- public capitalize(text: string): string {
- return text.charAt(0).toUpperCase() + text.slice(1);
- }
-
- /**
- * Runs a shell command and gives the output
- * @param command The shell command to run
- * @returns The stdout and stderr of the shell command
- */
- public async shell(command: string): Promise<{
- stdout: string;
- stderr: string;
- }> {
- return await promisify(exec)(command);
- }
-
- /**
- * Posts text to hastebin
- * @param content The text to post
- * @returns The url of the posted text
- */
- 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()})`));
- return { error: 'content too long' };
- } else if (content.length > 400_000) {
- content = content.substring(0, 400_000);
- isSubstr = true;
- }
- for (const url of this.#hasteURLs) {
- try {
- 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}`);
- }
- }
- return { error: 'unable to post' };
- }
-
- /**
- * Resolves a user-provided string into a user object, if possible
- * @param text The text to try and resolve
- * @returns The user resolved or null
- */
- public async resolveUserAsync(text: string): Promise<User | null> {
- const idReg = /\d{17,19}/;
- const idMatch = text.match(idReg);
- if (idMatch) {
- try {
- return await client.users.fetch(text as Snowflake);
- } catch {
- // pass
- }
- }
- const mentionReg = /<@!?(?<id>\d{17,19})>/;
- const mentionMatch = text.match(mentionReg);
- if (mentionMatch) {
- try {
- return await client.users.fetch(mentionMatch.groups!.id as Snowflake);
- } catch {
- // pass
- }
- }
- const user = client.users.cache.find((u) => u.username === text);
- if (user) return user;
- return null;
- }
-
- /**
- * Appends the correct ordinal to the given number
- * @param n The number to append an ordinal to
- * @returns The number with the ordinal
- */
- public ordinal(n: number): string {
- const s = ['th', 'st', 'nd', 'rd'],
- v = n % 100;
- return n + (s[(v - 20) % 10] || s[v] || s[0]);
- }
-
- /**
- * Chunks an array to the specified size
- * @param arr The array to chunk
- * @param perChunk The amount of items per chunk
- * @returns The chunked array
- */
- public chunk<T>(arr: T[], perChunk: number): T[][] {
- return arr.reduce((all, one, i) => {
- const ch: number = Math.floor(i / perChunk);
- (all as any[])[ch] = [].concat(all[ch] || [], one as any);
- return all;
- }, []);
- }
-
- /**
- * Commonly Used Colors
- */
- public get colors() {
- return client.consts.colors;
- }
-
- /**
- * Commonly Used Emojis
- */
- public get emojis() {
- return client.consts.emojis;
- }
-
- /**
- * Just the ids of Commonly Used Emojis
- */
- public get emojisRaw() {
- return client.consts.emojisRaw;
- }
-
- /**
- * 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 = '';
- code = this.discord.escapeCodeBlock(code);
- const prefix = `\`\`\`${language}\n`;
- const suffix = '\n```';
- if (code.length + (prefix + suffix).length >= length) {
- const haste = await this.haste(code, substr);
- hasteOut = `Too large to display. ${
- haste.url
- ? `Hastebin: ${haste.url}${language ? `.${language}` : ''}${haste.error ? ` - ${haste.error}` : ''}`
- : `${this.emojis.error} Hastebin: ${haste.error}`
- }`;
- }
-
- const FormattedHaste = hasteOut.length ? `\n${hasteOut}` : '';
- const shortenedCode = hasteOut ? code.substring(0, length - (prefix + FormattedHaste + suffix).length) : code;
- const code3 = code.length ? prefix + shortenedCode + suffix + FormattedHaste : prefix + suffix;
- if (code3.length > length) {
- void client.console.warn(`codeblockError`, `Required Length: ${length}. Actual Length: ${code3.length}`, true);
- void client.console.warn(`codeblockError`, code3, true);
- throw new Error('code too long');
- }
- return code3;
- }
-
- /**
- * Generate defaults for {@link inspect}.
- * @param options The options to create defaults with.
- * @returns The default options combined with the specified options.
- */
- #getDefaultInspectOptions(options?: BushInspectOptions): BushInspectOptions {
- return {
- showHidden: options?.showHidden ?? false,
- depth: options?.depth ?? 2,
- colors: options?.colors ?? false,
- customInspect: options?.customInspect ?? true,
- showProxy: options?.showProxy ?? false,
- maxArrayLength: options?.maxArrayLength ?? Infinity,
- maxStringLength: options?.maxStringLength ?? Infinity,
- breakLength: options?.breakLength ?? 80,
- compact: options?.compact ?? 3,
- sorted: options?.sorted ?? false,
- getters: options?.getters ?? true
- };
- }
-
- /**
- * 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',
- betaToken: 'Beta Token',
- hypixelApiKey: 'Hypixel Api Key',
- wolframAlphaAppId: 'Wolfram|Alpha App ID',
- dbPassword: 'Database Password'
- };
- return mapping[key as keyof typeof mapping] || key;
- }
-
- /**
- * 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 }) {
- const credential = { ...client.config.credentials, dbPassword: client.config.db.password }[
- credentialName as keyof typeof client.config.credentials
- ];
- const replacement = this.#mapCredential(credentialName);
- const escapeRegex = /[.*+?^${}()|[\]\\]/g;
- text = text.replace(new RegExp(credential.toString().replace(escapeRegex, '\\$&'), 'g'), `[${replacement} Omitted]`);
- text = text.replace(
- new RegExp([...credential.toString()].reverse().join('').replace(escapeRegex, '\\$&'), 'g'),
- `[${replacement} Omitted]`
- );
- }
- return text;
- }
-
- /**
- * 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);
-
- if (!optionsWithDefaults.inspectStrings && typeof object === 'string') return object;
-
- return inspect(object, optionsWithDefaults);
- }
-
- /**
- * 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,
- language?: CodeBlockLang | '',
- inspectOptions?: BushInspectOptions,
- length = 1024
- ) {
- input = this.inspect(input, inspectOptions ?? undefined);
- if (inspectOptions) inspectOptions.inspectStrings = undefined;
- input = this.discord.cleanCodeBlockContent(input);
- input = this.redact(input);
- return this.codeblock(input, length, language, true);
- }
-
- /**
- * 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 = this.inspect(input, inspectOptions ?? undefined);
- input = this.redact(input);
- return this.haste(input, true);
- }
-
- /**
- * 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 = this.inspect(input, inspectOptions ?? undefined);
- 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: SlashSendMessageType | SlashEditMessageType
- ): Promise<Message | APIMessage | undefined> {
- const newResponseOptions = typeof responseOptions === 'string' ? { content: responseOptions } : responseOptions;
- if (interaction.replied || interaction.deferred) {
- delete (newResponseOptions as InteractionReplyOptions).ephemeral; // Cannot change a preexisting message to be ephemeral
- return (await interaction.editReply(newResponseOptions)) as Message | APIMessage;
- } else {
- await interaction.reply(newResponseOptions);
- return await interaction.fetchReply().catch(() => undefined);
- }
- }
-
- /**
- * 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;
- }
-
- /**
- * Takes an array and combines the elements using the supplied conjunction.
- * @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`.
- *
- * @example
- * const permissions = oxford(['Administrator', 'SendMessages', 'ManageMessages'], 'and', 'none');
- * console.log(permissions); // Administrator, SendMessages and ManageMessages
- */
- public oxford(array: string[], conjunction: string, ifEmpty?: string): string | undefined {
- const l = array.length;
- if (!l) return ifEmpty;
- if (l < 2) return array[0];
- if (l < 3) return array.join(` ${conjunction} `);
- array = array.slice();
- array[l - 1] = `${conjunction} ${array[l - 1]}`;
- return array.join(', ');
- }
-
- /**
- * Get the global cache.
- */
- public getGlobal(): GlobalCache;
- /**
- * Get a key from the global cache.
- * @param key The key to get in the global cache.
- */
- public getGlobal<K extends keyof GlobalCache>(key: K): GlobalCache[K];
- public getGlobal(key?: keyof GlobalCache) {
- return key ? client.cache.global[key] : client.cache.global;
- }
-
- public getShared(): SharedCache;
- public getShared<K extends keyof SharedCache>(key: K): SharedCache[K];
- public getShared(key?: keyof SharedCache) {
- return key ? client.cache.shared[key] : client.cache.shared;
- }
-
- /**
- * 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: 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 }));
- const oldValue: any[] = row[key];
- const newValue = this.addOrRemoveFromArray(action, oldValue, value);
- row[key] = newValue;
- client.cache.global[key] = newValue;
- return await row.save().catch((e) => this.handleError('insertOrRemoveFromGlobal', e));
- }
-
- /**
- * Add or remove an element from an array stored in the Shared database.
- * @param action Either `add` or `remove` an element.
- * @param key The key of the element in the shared cache to update.
- * @param value The value to add/remove from the array.
- */
- public async insertOrRemoveFromShared<K extends Exclude<keyof typeof client['cache']['shared'], 'badWords' | 'autoBanCode'>>(
- action: 'add' | 'remove',
- key: K,
- value: typeof client['cache']['shared'][K][0]
- ): Promise<Shared | void> {
- const row = (await Shared.findByPk(0)) ?? (await Shared.create());
- const oldValue: any[] = row[key];
- const newValue = this.addOrRemoveFromArray(action, oldValue, value);
- row[key] = newValue;
- client.cache.shared[key] = newValue;
- return await row.save().catch((e) => this.handleError('insertOrRemoveFromShared', e));
- }
-
- /**
- * 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));
- }
-
- /**
- * Updates an element in the Shared database.
- * @param key The key in the shared cache to update.
- * @param value The value to set the key to.
- */
- public async setShared<K extends Exclude<keyof typeof client['cache']['shared'], 'badWords' | 'autoBanCode'>>(
- key: K,
- value: typeof client['cache']['shared'][K]
- ): Promise<Shared | void> {
- const row = (await Shared.findByPk(0)) ?? (await Shared.create());
- row[key] = value;
- client.cache.shared[key] = value;
- return await row.save().catch((e) => this.handleError('setShared', 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);
- action === 'add' ? set.add(value) : set.delete(value);
- return [...set];
- }
-
- /**
- * Remove an item from an array. All duplicates will be removed.
- * @param array The array to remove an element from.
- * @param value The element to remove from the array.
- */
- public removeFromArray<T>(array: T[], value: T): T[] {
- return this.addOrRemoveFromArray('remove', array, value);
- }
-
- /**
- * Add an item from an array. All duplicates will be removed.
- * @param array The array to add an element to.
- * @param value The element to add to the array.
- */
- public addToArray<T>(array: T[], value: T): T[] {
- return this.addOrRemoveFromArray('add', array, value);
- }
-
- /**
- * 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`.
- */
- public surroundArray(array: string[], surroundChar1: string, surroundChar2?: string): string[] {
- return array.map((a) => `${surroundChar1}${a}${surroundChar2 ?? surroundChar1}`);
- }
-
- /**
- * 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, content: null };
-
- // eslint-disable-next-line prefer-const
- let duration: number | null = null;
- // Try to reduce false positives by requiring a space before the duration, this makes sure it still matches if it is
- // in the beginning of the argument
- let contentWithoutTime = ` ${content}`;
-
- for (const unit in BushConstants.timeUnits) {
- 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! += value * BushConstants.timeUnits[unit as keyof typeof BushConstants.timeUnits].value;
-
- if (remove) contentWithoutTime = contentWithoutTime.replace(regex, '');
- }
- // remove the space added earlier
- if (contentWithoutTime.startsWith(' ')) contentWithoutTime.replace(' ', '');
- return { duration, content: 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.
- * @param round Whether or not to round the smallest unit displayed.
- * @returns A humanized string of the duration.
- */
- public humanizeDuration(duration: number, largest?: number, round = true): string {
- if (largest) return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2, largest, round })!;
- else return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2, round })!;
- }
-
- /**
- * 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(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 ex. `16:20`
- * - **T**: Long Time ex. `16:20:30 `
- * - **d**: Short Date ex. `20/04/2021`
- * - **D**: Long Date ex. `20 April 2021`
- * - **f**: Short Date/Time ex. `20 April 2021 16:20`
- * - **F**: Long Date/Time ex. `Tuesday, 20 April 2021 16:20`
- * - **R**: Relative Time ex. `2 months ago`
- */
- public timestamp<D extends Date | undefined | null>(date: D, style: TimestampStyle = 'f'): D extends Date ? string : undefined {
- if (!date) return date as unknown as D extends Date ? string : undefined;
- return `<t:${Math.round(date.getTime() / 1_000)}:${style}>` as unknown as D extends Date ? string : undefined;
- }
-
- /**
- * 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.
- * @param round Whether or not to round the smallest unit displayed.
- * @returns A humanized string of the delta.
- */
- public dateDelta(date: Date, largest?: number, round = true): string {
- return this.humanizeDuration(new Date().getTime() - date.getTime(), largest ?? 3, round);
- }
-
- /**
- * Combines {@link timestamp} and {@link dateDelta}
- * @param date The date to be compared with the current time.
- * @param style The style of the timestamp.
- * @returns The formatted timestamp.
- *
- * @see
- * **Styles:**
- * - **t**: Short Time ex. `16:20`
- * - **T**: Long Time ex. `16:20:30 `
- * - **d**: Short Date ex. `20/04/2021`
- * - **D**: Long Date ex. `20 April 2021`
- * - **f**: Short Date/Time ex. `20 April 2021 16:20`
- * - **F**: Long Date/Time ex. `Tuesday, 20 April 2021 16:20`
- * - **R**: Relative Time ex. `2 months ago`
- */
- public timestampAndDelta(date: Date, style: TimestampStyle = 'D'): string {
- return `${this.timestamp(date, style)} (${this.dateDelta(date)} ago)`;
- }
-
- /**
- * 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);
- vw.setUint32(0, parseInt(hex, 16), false);
- const arrByte = new Uint8Array(arrBuff);
-
- return `${arrByte[1]}, ${arrByte[2]}, ${arrByte[3]}`;
- }
-
- /**
- * 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 milliseconds.
- * @returns A promise that resolves after the specified amount of milliseconds
- */
- public get sleep() {
- return promisify(setTimeout);
- }
-
- /**
- * 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${util.formatError(error, false)}`, false);
- await client.console.channelError({
- embeds: await CommandErrorListener.generateErrorEmbed({ type: 'unhandledRejection', error: error, context })
- });
- }
-
- /**
- * Fetches a user from discord.
- * @param user The user to fetch
- * @returns Undefined if the user is not found, otherwise the user.
- */
- public async resolveNonCachedUser(user: UserResolvable | undefined | null): Promise<User | undefined> {
- if (user == null) return undefined;
- const resolvedUser =
- user instanceof User
- ? user
- : user instanceof GuildMember
- ? user.user
- : user instanceof ThreadMember
- ? user.user
- : user instanceof Message
- ? user.author
- : undefined;
-
- return resolvedUser ?? (await client.users.fetch(user as Snowflake).catch(() => undefined));
- }
-
- /**
- * Get the pronouns of a discord user from pronoundb.org
- * @param user The user to retrieve the promises of.
- * @returns The human readable pronouns of the user, or undefined if they do not have any.
- */
- public async getPronounsOf(user: User | Snowflake): Promise<Pronoun | undefined> {
- const _user = await this.resolveNonCachedUser(user);
- if (!_user) throw new Error(`Cannot find user ${user}`);
- const apiRes = (await got
- .get(`https://pronoundb.org/api/v1/lookup?platform=discord&id=${_user.id}`)
- .json()
- .catch(() => undefined)) as { pronouns: PronounCode } | undefined;
-
- if (!apiRes) return undefined;
- assert(apiRes.pronouns);
-
- return client.constants.pronounMapping[apiRes.pronouns!]!;
- }
-
- /**
- * List the methods of an object.
- * @param obj The object to get the methods of.
- * @returns A string with each method on a new line.
- */
- public getMethods(obj: Record<string, any>): string {
- // modified from https://stackoverflow.com/questions/31054910/get-functions-methods-of-a-class/31055217#31055217
- let props: string[] = [];
- let obj_: Record<string, any> = new Object(obj);
-
- do {
- 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
- 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
- );
-
- const reg = /\(([\s\S]*?)\)/;
- props = props.concat(
- l.map(
- (p) =>
- `${obj_[p] && obj_[p][Symbol.toStringTag] === 'AsyncFunction' ? 'async ' : ''}function ${p}(${
- reg.exec(obj_[p].toString())?.[1]
- ? reg
- .exec(obj_[p].toString())?.[1]
- .split(', ')
- .map((arg) => arg.split('=')[0].trim())
- .join(', ')
- : ''
- });`
- )
- );
- } while (
- (obj_ = Object.getPrototypeOf(obj_)) && // walk-up the prototype chain
- Object.getPrototypeOf(obj_) // not the the Object prototype methods (hasOwnProperty, etc...)
- );
-
- return props.join('\n');
- }
-
- /**
- * List the symbols of an object.
- * @param obj The object to get the symbols of.
- * @returns An array of the symbols of the object.
- */
- public getSymbols(obj: Record<string, any>): symbol[] {
- let symbols: symbol[] = [];
- let obj_: Record<string, any> = new Object(obj);
-
- do {
- const l = Object.getOwnPropertySymbols(obj_).sort();
-
- symbols = [...symbols, ...l];
- } while (
- (obj_ = Object.getPrototypeOf(obj_)) && // walk-up the prototype chain
- Object.getPrototypeOf(obj_) // not the the Object prototype methods (hasOwnProperty, etc...)
- );
-
- return symbols;
- }
-
- /**
- * Uploads an image to imgur.
- * @param image The image to upload.
- * @returns The url of the imgur.
- */
- public async uploadImageToImgur(image: string) {
- const clientId = this.client.config.credentials.imgurClientId;
-
- const resp = (await got
- .post('https://api.imgur.com/3/upload', {
- headers: {
- Authorization: `Client-ID ${clientId}`,
- Accept: 'application/json'
- },
- form: {
- image: image,
- type: 'base64'
- },
- followRedirect: true
- })
- .json()) as { data: { link: string } };
-
- return resp.data.link;
- }
-
- /**
- * Checks if a user has a certain guild permission (doesn't check channel permissions).
- * @param message The message to check the user from.
- * @param permissions The permissions to check for.
- * @returns The missing permissions or null if none are missing.
- */
- public userGuildPermCheck(
- message: CommandMessage | SlashMessage,
- permissions: typeof PermissionFlagsBits[keyof typeof PermissionFlagsBits][]
- ): PermissionsString[] | null {
- if (!message.inGuild()) return null;
- const missing = message.member?.permissions.missing(permissions) ?? [];
-
- return missing.length ? missing : null;
- }
-
- /**
- * Check if the client has certain permissions in the guild (doesn't check channel permissions).
- * @param message The message to check the client user from.
- * @param permissions The permissions to check for.
- * @returns The missing permissions or null if none are missing.
- */
- public clientGuildPermCheck(message: CommandMessage | SlashMessage, permissions: bigint[]): PermissionsString[] | null {
- const missing = message.guild?.members.me?.permissions.missing(permissions) ?? [];
-
- return missing.length ? missing : null;
- }
-
- /**
- * Check if the client has permission to send messages in the channel as well as check if they have other permissions
- * in the guild (or the channel if `checkChannel` is `true`).
- * @param message The message to check the client user from.
- * @param permissions The permissions to check for.
- * @param checkChannel Whether to check the channel permissions instead of the guild permissions.
- * @returns The missing permissions or null if none are missing.
- */
- public clientSendAndPermCheck(
- message: CommandMessage | SlashMessage,
- permissions: bigint[] = [],
- checkChannel = false
- ): PermissionsString[] | null {
- const missing: PermissionsString[] = [];
- const sendPerm = message.channel!.isThread() ? 'SendMessages' : 'SendMessagesInThreads';
- if (!message.inGuild()) return null;
-
- if (!message.guild.members.me!.permissionsIn(message.channel!.id).has(sendPerm)) missing.push(sendPerm);
-
- missing.push(
- ...(checkChannel
- ? message.guild!.members.me!.permissionsIn(message.channel!.id!).missing(permissions)
- : this.clientGuildPermCheck(message, permissions) ?? [])
- );
-
- return missing.length ? missing : null;
- }
-
- /**
- * Gets the prefix based off of the message.
- * @param message The message to get the prefix from.
- * @returns The prefix.
- */
- public prefix(message: CommandMessage | SlashMessage): string {
- return message.util.isSlash
- ? '/'
- : client.config.isDevelopment
- ? 'dev '
- : message.util.parsed?.prefix ?? client.config.prefix;
- }
-
- /**
- * Recursively apply provided options operations on object
- * and all of the object properties that are either object or function.
- *
- * By default freezes object.
- *
- * @param obj - The object to which will be applied `freeze`, `seal` or `preventExtensions`
- * @param options default `{ action: 'freeze' }`
- * @param options.action
- * ```
- * | action | Add | Modify | Delete | Reconfigure |
- * | ----------------- | --- | ------ | ------ | ----------- |
- * | preventExtensions | - | + | + | + |
- * | seal | - | + | - | - |
- * | freeze | - | - | - | - |
- * ```
- *
- * @returns Initial object with applied options action
- */
- public get deepFreeze() {
- return deepLock;
- }
-
- /**
- * Recursively apply provided options operations on object
- * and all of the object properties that are either object or function.
- *
- * By default freezes object.
- *
- * @param obj - The object to which will be applied `freeze`, `seal` or `preventExtensions`
- * @param options default `{ action: 'freeze' }`
- * @param options.action
- * ```
- * | action | Add | Modify | Delete | Reconfigure |
- * | ----------------- | --- | ------ | ------ | ----------- |
- * | preventExtensions | - | + | + | + |
- * | seal | - | + | - | - |
- * | freeze | - | - | - | - |
- * ```
- *
- * @returns Initial object with applied options action
- */
- public static get deepFreeze() {
- return deepLock;
- }
-
- /**
- * The link to invite the bot with all permissions.
- */
- public get invite() {
- return client.generateInvite({
- permissions:
- PermissionsBitField.All -
- PermissionFlagsBits.UseEmbeddedActivities -
- PermissionFlagsBits.ViewGuildInsights -
- PermissionFlagsBits.Stream,
- scopes: [OAuth2Scopes.Bot, OAuth2Scopes.ApplicationsCommands]
- });
- }
-
- /**
- * Asset multiple statements at a time.
- * @param args
- */
- public assertAll(...args: any[]): void {
- for (let i = 0; i < args.length; i++) {
- assert(args[i], `assertAll index ${i} failed`);
- }
- }
-
- /**
- * Casts a string to a duration and reason for slash commands.
- * @param arg The argument received.
- * @param message The message that triggered the command.
- * @returns The casted argument.
- */
- public async castDurationContent(
- arg: string | ParsedDuration | null,
- message: CommandMessage | SlashMessage
- ): Promise<ParsedDurationRes> {
- const res = typeof arg === 'string' ? await util.arg.cast('contentWithDuration', message, arg) : arg;
-
- return { duration: res?.duration ?? 0, content: res?.content ?? '' };
- }
-
- /**
- * Casts a string to a the specified argument type.
- * @param type The type of the argument to cast to.
- * @param arg The argument received.
- * @param message The message that triggered the command.
- * @returns The casted argument.
- */
- public async cast<T extends keyof BaseBushArgumentType>(
- type: T,
- arg: BaseBushArgumentType[T] | string,
- message: CommandMessage | SlashMessage
- ) {
- return typeof arg === 'string' ? await util.arg.cast(type, message, arg) : arg;
- }
-
- /**
- * Overflows the description of an embed into multiple embeds.
- * @param embed The options to be applied to the (first) embed.
- * @param lines Each line of the description as an element in an array.
- */
- public overflowEmbed(embed: Omit<APIEmbed, 'description'>, lines: string[], maxLength = 4096): EmbedBuilder[] {
- const embeds: EmbedBuilder[] = [];
-
- const makeEmbed = () => {
- embeds.push(new EmbedBuilder().setColor(embed.color ?? null));
- return embeds.at(-1)!;
- };
-
- for (const line of lines) {
- let current = embeds.length ? embeds.at(-1)! : makeEmbed();
- let joined = current.data.description ? `${current.data.description}\n${line}` : line;
- if (joined.length > maxLength) {
- current = makeEmbed();
- joined = line;
- }
-
- current.setDescription(joined);
- }
-
- if (!embeds.length) makeEmbed();
-
- if (embed.author) embeds.at(0)?.setAuthor(embed.author);
- if (embed.title) embeds.at(0)?.setTitle(embed.title);
- if (embed.url) embeds.at(0)?.setURL(embed.url);
- if (embed.fields) embeds.at(-1)?.setFields(embed.fields);
- if (embed.thumbnail) embeds.at(-1)?.setThumbnail(embed.thumbnail.url);
- if (embed.footer) embeds.at(-1)?.setFooter(embed.footer);
- if (embed.image) embeds.at(-1)?.setImage(embed.image.url);
- if (embed.timestamp) embeds.at(-1)?.setTimestamp(new Date(embed.timestamp));
-
- return embeds;
- }
-
- public async resolveMessageLinks(content: string | null): Promise<MessageLinkParts[]> {
- const res: MessageLinkParts[] = [];
-
- if (!content) return res;
-
- const regex = new RegExp(this.regex.messageLink);
- let match: RegExpExecArray | null;
- while (((match = regex.exec(content)), match !== null)) {
- const input = match.input;
- if (!match.groups || !input) continue;
- if (input.startsWith('<') && input.endsWith('>')) continue;
-
- const { guild_id, channel_id, message_id } = match.groups;
- if (!guild_id || !channel_id || !message_id) continue;
-
- res.push({ guild_id, channel_id, message_id });
- }
-
- return res;
- }
-
- public async resolveMessagesFromLinks(content: string): Promise<APIMessage[]> {
- const res: APIMessage[] = [];
-
- const links = await this.resolveMessageLinks(content);
- if (!links.length) return [];
-
- for (const { guild_id, channel_id, message_id } of links) {
- const guild = client.guilds.cache.get(guild_id);
- if (!guild) continue;
- const channel = guild.channels.cache.get(channel_id);
- if (!channel || (!channel.isTextBased() && !channel.isThread())) continue;
-
- const message = (await client.rest
- .get(Routes.channelMessage(channel_id, message_id))
- .catch(() => null)) as APIMessage | null;
- if (!message) continue;
-
- res.push(message);
- }
-
- return res;
- }
-
- /**
- * Formats an error into a string.
- * @param error The error to format.
- * @param colors Whether to use colors in the output.
- * @returns The formatted error.
- */
- public formatError(error: Error | any, colors = false): string {
- if (!error) return error;
- if (typeof error !== 'object') return String.prototype.toString.call(error);
- if (
- this.getSymbols(error)
- .map((s) => s.toString())
- .includes('Symbol(nodejs.util.inspect.custom)')
- )
- return this.inspect(error, { colors });
-
- return error.stack;
- }
-
- /**
- * A wrapper for the Argument class that adds custom typings.
- */
- public get arg() {
- return Arg;
- }
-
- /**
- * Formats and escapes content for formatting
- */
- public get format() {
- return Format;
- }
-
- /**
- * Discord.js's Util class
- */
- public get discord() {
- return DiscordUtil;
- }
-
- /**
- * Discord.js's Util constants
- */
- public get discordConstants() {
- return DiscordConstants;
- }
-
- /**
- * discord-akairo's Util class
- */
- public get akairo() {
- return AkairoUtil;
- }
-
- public get consts() {
- return client.consts;
- }
-
- public get regex() {
- return client.consts.regex;
- }
-}
-
-interface HastebinRes {
- key: string;
-}
-
-export interface UuidRes {
- uuid: string;
- username: string;
- username_history?: { username: string }[] | null;
- textures: {
- custom: boolean;
- slim: boolean;
- skin: {
- url: string;
- data: string;
- };
- raw: {
- value: string;
- signature: string;
- };
- };
- created_at: string;
-}
-
-export interface HasteResults {
- url?: string;
- error?: 'content too long' | 'substr' | 'unable to post';
-}
-
-export interface ParsedDuration {
- duration: number | null;
- content: string | null;
-}
-
-export interface ParsedDurationRes {
- duration: number;
- content: string;
-}
-
-export type TimestampStyle = 't' | 'T' | 'd' | 'D' | 'f' | 'F' | 'R';
-
-export interface MessageLinkParts {
- guild_id: Snowflake;
- channel_id: Snowflake;
- message_id: Snowflake;
-}
diff --git a/src/lib/extensions/discord-akairo/BushInhibitor.ts b/src/lib/extensions/discord-akairo/BushInhibitor.ts
index 12b2baf..b4e6797 100644
--- a/src/lib/extensions/discord-akairo/BushInhibitor.ts
+++ b/src/lib/extensions/discord-akairo/BushInhibitor.ts
@@ -1,11 +1,9 @@
import { type BushClient, type BushCommand, type CommandMessage, type SlashMessage } from '#lib';
import { Inhibitor } from 'discord-akairo';
-export class BushInhibitor extends Inhibitor {
+export abstract class BushInhibitor extends Inhibitor {
public declare client: BushClient;
-}
-export interface BushInhibitor {
/**
* Checks if message should be blocked.
* A return value of true will block the message.
@@ -16,6 +14,6 @@ export interface BushInhibitor {
* @param message - Message being handled.
* @param command - Command to check.
*/
- exec(message: CommandMessage, command: BushCommand): any;
- exec(message: CommandMessage | SlashMessage, command: BushCommand): any;
+ public abstract override exec(message: CommandMessage, command: BushCommand): any;
+ public abstract override exec(message: CommandMessage | SlashMessage, command: BushCommand): any;
}
diff --git a/src/lib/extensions/discord-akairo/BushListener.ts b/src/lib/extensions/discord-akairo/BushListener.ts
index 3efe527..6917641 100644
--- a/src/lib/extensions/discord-akairo/BushListener.ts
+++ b/src/lib/extensions/discord-akairo/BushListener.ts
@@ -1,16 +1,3 @@
import { Listener } from 'discord-akairo';
-import type EventEmitter from 'events';
-export class BushListener extends Listener {
- public constructor(
- id: string,
- options: {
- emitter: string | EventEmitter;
- event: string;
- type?: 'on' | 'once' | 'prependListener' | 'prependOnceListener';
- category?: string;
- }
- ) {
- super(id, options);
- }
-}
+export abstract class BushListener extends Listener {}
diff --git a/src/lib/extensions/discord-akairo/BushTask.ts b/src/lib/extensions/discord-akairo/BushTask.ts
index 9f5c0cd..1b70c88 100644
--- a/src/lib/extensions/discord-akairo/BushTask.ts
+++ b/src/lib/extensions/discord-akairo/BushTask.ts
@@ -1,3 +1,3 @@
import { Task } from 'discord-akairo';
-export class BushTask extends Task {}
+export abstract class BushTask extends Task {}
diff --git a/src/lib/extensions/discord.js/ExtendedGuild.ts b/src/lib/extensions/discord.js/ExtendedGuild.ts
index b8b7b22..c199899 100644
--- a/src/lib/extensions/discord.js/ExtendedGuild.ts
+++ b/src/lib/extensions/discord.js/ExtendedGuild.ts
@@ -1,7 +1,9 @@
import {
AllowedMentions,
banResponse,
+ colors,
dmResponse,
+ emojis,
permissionsResponse,
punishmentEntryRemove,
type BanResponse,
@@ -36,9 +38,10 @@ import {
type WebhookMessageOptions
} from 'discord.js';
import _ from 'lodash';
-import { Moderation } from '../../common/util/Moderation.js';
+import * as Moderation from '../../common/util/Moderation.js';
import { Guild as GuildDB } from '../../models/instance/Guild.js';
import { ModLogType } from '../../models/instance/ModLog.js';
+import { addOrRemoveFromArray, resolveNonCachedUser } from '../../utils/BushUtils.js';
declare module 'discord.js' {
export interface Guild {
@@ -152,7 +155,7 @@ export class ExtendedGuild extends Guild {
*/
public override async addFeature(feature: GuildFeatures, moderator?: GuildMember): Promise<GuildModel['enabledFeatures']> {
const features = await this.getSetting('enabledFeatures');
- const newFeatures = util.addOrRemoveFromArray('add', features, feature);
+ const newFeatures = addOrRemoveFromArray('add', features, feature);
return (await this.setSetting('enabledFeatures', newFeatures, moderator)).enabledFeatures;
}
@@ -163,7 +166,7 @@ export class ExtendedGuild extends Guild {
*/
public override async removeFeature(feature: GuildFeatures, moderator?: GuildMember): Promise<GuildModel['enabledFeatures']> {
const features = await this.getSetting('enabledFeatures');
- const newFeatures = util.addOrRemoveFromArray('remove', features, feature);
+ const newFeatures = addOrRemoveFromArray('remove', features, feature);
return (await this.setSetting('enabledFeatures', newFeatures, moderator)).enabledFeatures;
}
@@ -251,7 +254,7 @@ export class ExtendedGuild extends Guild {
*/
public override async error(title: string, message: string): Promise<void> {
void client.console.info(_.camelCase(title), message.replace(/\*\*(.*?)\*\*/g, '<<$1>>'));
- void this.sendLogChannel('error', { embeds: [{ title: title, description: message, color: util.colors.error }] });
+ void this.sendLogChannel('error', { embeds: [{ title: title, description: message, color: colors.error }] });
}
/**
@@ -265,7 +268,7 @@ export class ExtendedGuild extends Guild {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const user = await util.resolveNonCachedUser(options.user);
+ const user = await resolveNonCachedUser(options.user);
const moderator = client.users.resolve(options.moderator ?? client.user!);
if (!user || !moderator) return banResponse.CANNOT_RESOLVE_USER;
@@ -408,7 +411,7 @@ export class ExtendedGuild extends Guild {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const user = await util.resolveNonCachedUser(options.user);
+ const user = await resolveNonCachedUser(options.user);
const moderator = client.users.resolve(options.moderator ?? client.user!);
if (!user || !moderator) return unbanResponse.CANNOT_RESOLVE_USER;
@@ -534,7 +537,7 @@ export class ExtendedGuild extends Guild {
author: { name: moderator.user.tag, icon_url: moderator.displayAvatarURL() },
title: `This channel has been ${options.unlock ? 'un' : ''}locked`,
description: options.reason ?? 'No reason provided',
- color: options.unlock ? util.colors.Green : util.colors.Red,
+ color: options.unlock ? colors.Green : colors.Red,
timestamp: new Date().toISOString()
}
]
@@ -600,16 +603,16 @@ export class ExtendedGuild extends Guild {
case MessageType.RecipientAdd: {
const recipient = rawQuote.mentions[0];
if (!recipient) {
- sendOptions.content = `${util.emojis.error} Cannot resolve recipient.`;
+ sendOptions.content = `${emojis.error} Cannot resolve recipient.`;
break;
}
if (quote.channel.isThread()) {
const recipientDisplay = quote.guild?.members.cache.get(recipient.id)?.displayName ?? recipient.username;
- sendOptions.content = `${util.emojis.join} ${displayName} added ${recipientDisplay} to the thread.`;
+ sendOptions.content = `${emojis.join} ${displayName} added ${recipientDisplay} to the thread.`;
} else {
// this should never happen
- sendOptions.content = `${util.emojis.join} ${displayName} added ${recipient.username} to the group.`;
+ sendOptions.content = `${emojis.join} ${displayName} added ${recipient.username} to the group.`;
}
break;
@@ -617,16 +620,16 @@ export class ExtendedGuild extends Guild {
case MessageType.RecipientRemove: {
const recipient = rawQuote.mentions[0];
if (!recipient) {
- sendOptions.content = `${util.emojis.error} Cannot resolve recipient.`;
+ sendOptions.content = `${emojis.error} Cannot resolve recipient.`;
break;
}
if (quote.channel.isThread()) {
const recipientDisplay = quote.guild?.members.cache.get(recipient.id)?.displayName ?? recipient.username;
- sendOptions.content = `${util.emojis.leave} ${displayName} removed ${recipientDisplay} from the thread.`;
+ sendOptions.content = `${emojis.leave} ${displayName} removed ${recipientDisplay} from the thread.`;
} else {
// this should never happen
- sendOptions.content = `${util.emojis.leave} ${displayName} removed ${recipient.username} from the group.`;
+ sendOptions.content = `${emojis.leave} ${displayName} removed ${recipient.username} from the group.`;
}
break;
@@ -661,7 +664,7 @@ export class ExtendedGuild extends Guild {
// this is the same way that the discord client decides what message to use.
const message = messages[timestamp % messages.length].replace(/{username}/g, displayName);
- sendOptions.content = `${util.emojis.join} ${message}`;
+ sendOptions.content = `${emojis.join} ${message}`;
break;
}
case MessageType.UserPremiumGuildSubscription:
@@ -717,7 +720,7 @@ export class ExtendedGuild extends Guild {
case MessageType.ChannelIconChange:
case MessageType.Call:
default:
- sendOptions.content = `${util.emojis.error} I cannot quote **${
+ sendOptions.content = `${emojis.error} I cannot quote **${
MessageType[quote.type] || quote.type
}** messages, please report this to my developers.`;
diff --git a/src/lib/extensions/discord.js/ExtendedGuildMember.ts b/src/lib/extensions/discord.js/ExtendedGuildMember.ts
index 28acc1a..ad29236 100644
--- a/src/lib/extensions/discord.js/ExtendedGuildMember.ts
+++ b/src/lib/extensions/discord.js/ExtendedGuildMember.ts
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
-import { BushClientEvents, Moderation, ModLogType, PunishmentTypeDM, Time } from '#lib';
+import { BushClientEvents, formatError, Moderation, ModLogType, PunishmentTypeDM, resolveNonCachedUser, Time } from '#lib';
import {
ChannelType,
GuildChannelResolvable,
@@ -148,7 +148,7 @@ export class ExtendedGuildMember extends GuildMember {
public override async bushWarn(options: BushPunishmentOptions): Promise<{ result: WarnResponse; caseNum: number | null }> {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return { result: warnResponse.CANNOT_RESOLVE_USER, caseNum: null };
const ret = await (async (): Promise<{ result: WarnResponse; caseNum: number | null }> => {
@@ -195,7 +195,7 @@ export class ExtendedGuildMember extends GuildMember {
if (ifShouldAddRole !== true) return ifShouldAddRole;
let caseID: string | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return addRoleResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -266,7 +266,7 @@ export class ExtendedGuildMember extends GuildMember {
if (ifShouldAddRole !== true) return ifShouldAddRole;
let caseID: string | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return removeRoleResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -362,7 +362,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return muteResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -448,7 +448,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return unmuteResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -456,7 +456,7 @@ export class ExtendedGuildMember extends GuildMember {
const muteSuccess = await this.roles
.remove(muteRole, `[Unmute] ${moderator.tag} | ${options.reason ?? 'No reason provided.'}`)
.catch(async (e) => {
- await client.console.warn('muteRoleAddError', util.formatError(e, true));
+ await client.console.warn('muteRoleAddError', formatError(e, true));
return false;
});
if (!muteSuccess) return unmuteResponse.ACTION_ERROR;
@@ -526,7 +526,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return kickResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
// add modlog entry
@@ -580,7 +580,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return banResponse.CANNOT_RESOLVE_USER;
// ignore result, they should still be banned even if their mute cannot be removed
@@ -663,7 +663,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return blockResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -754,7 +754,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return unblockResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -839,7 +839,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return timeoutResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
@@ -901,7 +901,7 @@ export class ExtendedGuildMember extends GuildMember {
let caseID: string | undefined = undefined;
let dmSuccessEvent: boolean | undefined = undefined;
- const moderator = await util.resolveNonCachedUser(options.moderator ?? this.guild.members.me);
+ const moderator = await resolveNonCachedUser(options.moderator ?? this.guild.members.me);
if (!moderator) return removeTimeoutResponse.CANNOT_RESOLVE_USER;
const ret = await (async () => {
diff --git a/src/lib/extensions/global.ts b/src/lib/extensions/global.ts
index a6f2b5a..d9cfaec 100644
--- a/src/lib/extensions/global.ts
+++ b/src/lib/extensions/global.ts
@@ -1,16 +1,11 @@
/* eslint-disable no-var */
-import type { BushClient, BushClientUtil } from '#lib';
+import type { BushClient } from '#lib';
declare global {
/**
* The bushbot client.
*/
var client: BushClient;
- /**
- * The bushbot client util.
- */
- var util: BushClientUtil;
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface ReadonlyArray<T> {
includes<S, R extends `${Extract<S, string>}`>(
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 221f360..3e57f9e 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -4,12 +4,21 @@ export * from './common/ConfirmationPrompt.js';
export * from './common/DeleteButton.js';
export type { BushInspectOptions } from './common/typings/BushInspectOptions.js';
export type { CodeBlockLang } from './common/typings/CodeBlockLang.js';
-export * from './common/util/Arg.js';
-export * from './common/util/Format.js';
-export * from './common/util/Moderation.js';
+export * as Arg from './common/util/Arg.js';
+export * as Format from './common/util/Format.js';
+export * as Moderation from './common/util/Moderation.js';
+export type {
+ AppealButtonId,
+ CreateModLogEntryOptions,
+ CreatePunishmentEntryOptions,
+ PunishDMOptions,
+ PunishmentTypeDM,
+ PunishmentTypePresent,
+ RemovePunishmentEntryOptions,
+ SimpleCreateModLogEntryOptions
+} from './common/util/Moderation.js';
export * from './extensions/discord-akairo/BushArgumentTypeCaster.js';
export * from './extensions/discord-akairo/BushClient.js';
-export * from './extensions/discord-akairo/BushClientUtil.js';
export * from './extensions/discord-akairo/BushCommand.js';
export * from './extensions/discord-akairo/BushCommandHandler.js';
export * from './extensions/discord-akairo/BushInhibitor.js';
@@ -40,5 +49,5 @@ export * from './utils/AllowedMentions.js';
export * from './utils/BushCache.js';
export * from './utils/BushConstants.js';
export * from './utils/BushLogger.js';
+export * from './utils/BushUtils.js';
export * from './utils/CanvasProgressBar.js';
-export * from './utils/Config.js';
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
index 8c3d27f..0f9311f 100644
--- a/src/lib/utils/BushConstants.ts
+++ b/src/lib/utils/BushConstants.ts
@@ -1,6 +1,11 @@
-import { ArgumentMatches, ArgumentTypes, BuiltInReasons, CommandHandlerEvents } from 'discord-akairo/dist/src/util/Constants.js';
+import deepLock from 'deep-lock';
+import {
+ ArgumentMatches as AkairoArgumentMatches,
+ ArgumentTypes as AkairoArgumentTypes,
+ BuiltInReasons,
+ CommandHandlerEvents as AkairoCommandHandlerEvents
+} from 'discord-akairo/dist/src/util/Constants.js';
import { Colors, GuildFeature } from 'discord.js';
-import { BushClientUtil } from '../extensions/discord-akairo/BushClientUtil.js';
const rawCapeUrl = 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/';
@@ -49,207 +54,206 @@ export const enum Time {
Year = Day * 365.25 // average with leap years
}
-export class BushConstants {
- public static emojis = Object.freeze({
- 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 emojisRaw = Object.freeze({
- success: '837109864101707807',
- warn: '848726900876247050',
- error: '837123021016924261',
- successFull: '850118767576088646',
- warnFull: '850118767391539312',
- errorFull: '850118767295201350',
- mad: '783046135392239626',
- join: '850198029809614858',
- leave: '850198048205307919',
- loading: '853419254619963392',
- offlineCircle: '787550565382750239',
- dndCircle: '787550487633330176',
- idleCircle: '787550520956551218',
- onlineCircle: '787550449435803658',
- cross: '878319362539421777',
- check: '878320135297961995'
- } as const);
-
- public static colors = Object.freeze({
- default: 0x1fd8f1,
- error: 0xef4947,
- warn: 0xfeba12,
- success: 0x3bb681,
- info: 0x3b78ff,
- red: 0xff0000,
- blue: 0x0055ff,
- aqua: 0x00bbff,
- purple: 0x8400ff,
- blurple: 0x5440cd,
- newBlurple: 0x5865f2,
- pink: 0xff00e6,
- green: 0x00ff1e,
- darkGreen: 0x008f11,
- gold: 0xb59400,
- yellow: 0xffff00,
- white: 0xffffff,
- gray: 0xa6a6a6,
- lightGray: 0xcfcfcf,
- darkGray: 0x7a7a7a,
- black: 0x000000,
- orange: 0xe86100,
- ...Colors
- } as const);
-
- // Somewhat stolen from @Mzato0001
- public static timeUnits = BushClientUtil.deepFreeze({
- milliseconds: {
- match: / (?:(?<milliseconds>-?(?:\d+)?\.?\d+) *(?:milliseconds?|msecs?|ms))/im,
- value: Time.Millisecond
- },
- seconds: {
- match: / (?:(?<seconds>-?(?:\d+)?\.?\d+) *(?:seconds?|secs?|s))/im,
- value: Time.Second
- },
- minutes: {
- match: / (?:(?<minutes>-?(?:\d+)?\.?\d+) *(?:minutes?|mins?|m))/im,
- value: Time.Minute
- },
- hours: {
- match: / (?:(?<hours>-?(?:\d+)?\.?\d+) *(?:hours?|hrs?|h))/im,
- value: Time.Hour
- },
- days: {
- match: / (?:(?<days>-?(?:\d+)?\.?\d+) *(?:days?|d))/im,
- value: Time.Day
- },
- weeks: {
- match: / (?:(?<weeks>-?(?:\d+)?\.?\d+) *(?:weeks?|w))/im,
- value: Time.Week
- },
- months: {
- match: / (?:(?<months>-?(?:\d+)?\.?\d+) *(?:months?|mon|mo))/im,
- value: Time.Month
- },
- years: {
- match: / (?:(?<years>-?(?:\d+)?\.?\d+) *(?:years?|y))/im,
- value: Time.Year
- }
- } as const);
-
- public static regex = BushClientUtil.deepFreeze({
- snowflake: /^\d{15,21}$/im,
-
- discordEmoji: /<a?:(?<name>[a-zA-Z0-9_]+):(?<id>\d{15,21})>/im,
-
- /*
- * Taken with permission from Geek:
- * https://github.com/FireDiscordBot/bot/blob/5d1990e5f8b52fcc72261d786aa3c7c7c65ab5e8/lib/util/constants.ts#L276
- */
- /** **This has the global flag, make sure to handle it correctly.** */
- messageLink:
- /<?(?:ptb\.|canary\.|staging\.)?discord(?:app)?\.com?\/channels\/(?<guild_id>\d{15,21})\/(?<channel_id>\d{15,21})\/(?<message_id>\d{15,21})>?/gim
- } as const);
-
- /**
- * Maps the response from pronoundb.org to a readable format
+export const emojis = Object.freeze({
+ 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);
+
+export const emojisRaw = Object.freeze({
+ success: '837109864101707807',
+ warn: '848726900876247050',
+ error: '837123021016924261',
+ successFull: '850118767576088646',
+ warnFull: '850118767391539312',
+ errorFull: '850118767295201350',
+ mad: '783046135392239626',
+ join: '850198029809614858',
+ leave: '850198048205307919',
+ loading: '853419254619963392',
+ offlineCircle: '787550565382750239',
+ dndCircle: '787550487633330176',
+ idleCircle: '787550520956551218',
+ onlineCircle: '787550449435803658',
+ cross: '878319362539421777',
+ check: '878320135297961995'
+} as const);
+
+export const colors = Object.freeze({
+ default: 0x1fd8f1,
+ error: 0xef4947,
+ warn: 0xfeba12,
+ success: 0x3bb681,
+ info: 0x3b78ff,
+ red: 0xff0000,
+ blue: 0x0055ff,
+ aqua: 0x00bbff,
+ purple: 0x8400ff,
+ blurple: 0x5440cd,
+ newBlurple: 0x5865f2,
+ pink: 0xff00e6,
+ green: 0x00ff1e,
+ darkGreen: 0x008f11,
+ gold: 0xb59400,
+ yellow: 0xffff00,
+ white: 0xffffff,
+ gray: 0xa6a6a6,
+ lightGray: 0xcfcfcf,
+ darkGray: 0x7a7a7a,
+ black: 0x000000,
+ orange: 0xe86100,
+ ...Colors
+} as const);
+
+// Somewhat stolen from @Mzato0001
+export const timeUnits = deepLock({
+ milliseconds: {
+ match: / (?:(?<milliseconds>-?(?:\d+)?\.?\d+) *(?:milliseconds?|msecs?|ms))/im,
+ value: Time.Millisecond
+ },
+ seconds: {
+ match: / (?:(?<seconds>-?(?:\d+)?\.?\d+) *(?:seconds?|secs?|s))/im,
+ value: Time.Second
+ },
+ minutes: {
+ match: / (?:(?<minutes>-?(?:\d+)?\.?\d+) *(?:minutes?|mins?|m))/im,
+ value: Time.Minute
+ },
+ hours: {
+ match: / (?:(?<hours>-?(?:\d+)?\.?\d+) *(?:hours?|hrs?|h))/im,
+ value: Time.Hour
+ },
+ days: {
+ match: / (?:(?<days>-?(?:\d+)?\.?\d+) *(?:days?|d))/im,
+ value: Time.Day
+ },
+ weeks: {
+ match: / (?:(?<weeks>-?(?:\d+)?\.?\d+) *(?:weeks?|w))/im,
+ value: Time.Week
+ },
+ months: {
+ match: / (?:(?<months>-?(?:\d+)?\.?\d+) *(?:months?|mon|mo))/im,
+ value: Time.Month
+ },
+ years: {
+ match: / (?:(?<years>-?(?:\d+)?\.?\d+) *(?:years?|y))/im,
+ value: Time.Year
+ }
+} as const);
+
+export const regex = deepLock({
+ snowflake: /^\d{15,21}$/im,
+
+ discordEmoji: /<a?:(?<name>[a-zA-Z0-9_]+):(?<id>\d{15,21})>/im,
+
+ /*
+ * Taken with permission from Geek:
+ * https://github.com/FireDiscordBot/bot/blob/5d1990e5f8b52fcc72261d786aa3c7c7c65ab5e8/lib/util/constants.ts#L276
*/
- public static pronounMapping = Object.freeze({
- 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);
+ /** **This has the global flag, make sure to handle it correctly.** */
+ messageLink:
+ /<?(?:ptb\.|canary\.|staging\.)?discord(?:app)?\.com?\/channels\/(?<guild_id>\d{15,21})\/(?<channel_id>\d{15,21})\/(?<message_id>\d{15,21})>?/gim
+} as const);
- /**
- * A bunch of mappings
- */
- public static mappings = BushClientUtil.deepFreeze({
- guilds: {
- bush: '516977525906341928',
- tree: '767448775450820639',
- staff: '784597260465995796',
- space_ship: '717176538717749358',
- sbr: '839287012409999391'
- },
-
- permissions: {
- CreateInstantInvite: { name: 'Create Invite', important: false },
- KickMembers: { name: 'Kick Members', important: true },
- BanMembers: { name: 'Ban Members', important: true },
- Administrator: { name: 'Administrator', important: true },
- ManageChannels: { name: 'Manage Channels', important: true },
- ManageGuild: { name: 'Manage Server', important: true },
- AddReactions: { name: 'Add Reactions', important: false },
- ViewAuditLog: { name: 'View Audit Log', important: true },
- PrioritySpeaker: { name: 'Priority Speaker', important: true },
- Stream: { name: 'Video', important: false },
- ViewChannel: { name: 'View Channel', important: false },
- SendMessages: { name: 'Send Messages', important: false },
- SendTTSMessages: { name: 'Send Text-to-Speech Messages', important: true },
- ManageMessages: { name: 'Manage Messages', important: true },
- EmbedLinks: { name: 'Embed Links', important: false },
- AttachFiles: { name: 'Attach Files', important: false },
- ReadMessageHistory: { name: 'Read Message History', important: false },
- MentionEveryone: { name: 'Mention @\u200Beveryone, @\u200Bhere, and All Roles', important: true }, // name has a zero-width space to prevent accidents
- UseExternalEmojis: { name: 'Use External Emoji', important: false },
- ViewGuildInsights: { name: 'View Server Insights', important: true },
- Connect: { name: 'Connect', important: false },
- Speak: { name: 'Speak', important: false },
- MuteMembers: { name: 'Mute Members', important: true },
- DeafenMembers: { name: 'Deafen Members', important: true },
- MoveMembers: { name: 'Move Members', important: true },
- UseVAD: { name: 'Use Voice Activity', important: false },
- ChangeNickname: { name: 'Change Nickname', important: false },
- ManageNicknames: { name: 'Change Nicknames', important: true },
- ManageRoles: { name: 'Manage Roles', important: true },
- ManageWebhooks: { name: 'Manage Webhooks', important: true },
- ManageEmojisAndStickers: { name: 'Manage Emojis and Stickers', important: true },
- UseApplicationCommands: { name: 'Use Slash Commands', important: false },
- RequestToSpeak: { name: 'Request to Speak', important: false },
- ManageEvents: { name: 'Manage Events', important: true },
- ManageThreads: { name: 'Manage Threads', important: true },
- CreatePublicThreads: { name: 'Create Public Threads', important: false },
- CreatePrivateThreads: { name: 'Create Private Threads', important: false },
- UseExternalStickers: { name: 'Use External Stickers', important: false },
- SendMessagesInThreads: { name: 'Send Messages In Threads', important: false },
- StartEmbeddedActivities: { name: 'Start Activities', important: false },
- ModerateMembers: { name: 'Timeout Members', important: true },
- UseEmbeddedActivities: { name: 'Use Activities', important: false }
- },
+/**
+ * Maps the response from pronoundb.org to a readable format
+ */
+export const pronounMapping = Object.freeze({
+ 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);
- // prettier-ignore
- features: {
+/**
+ * A bunch of mappings
+ */
+export const mappings = deepLock({
+ guilds: {
+ bush: '516977525906341928',
+ tree: '767448775450820639',
+ staff: '784597260465995796',
+ space_ship: '717176538717749358',
+ sbr: '839287012409999391'
+ },
+
+ permissions: {
+ CreateInstantInvite: { name: 'Create Invite', important: false },
+ KickMembers: { name: 'Kick Members', important: true },
+ BanMembers: { name: 'Ban Members', important: true },
+ Administrator: { name: 'Administrator', important: true },
+ ManageChannels: { name: 'Manage Channels', important: true },
+ ManageGuild: { name: 'Manage Server', important: true },
+ AddReactions: { name: 'Add Reactions', important: false },
+ ViewAuditLog: { name: 'View Audit Log', important: true },
+ PrioritySpeaker: { name: 'Priority Speaker', important: true },
+ Stream: { name: 'Video', important: false },
+ ViewChannel: { name: 'View Channel', important: false },
+ SendMessages: { name: 'Send Messages', important: false },
+ SendTTSMessages: { name: 'Send Text-to-Speech Messages', important: true },
+ ManageMessages: { name: 'Manage Messages', important: true },
+ EmbedLinks: { name: 'Embed Links', important: false },
+ AttachFiles: { name: 'Attach Files', important: false },
+ ReadMessageHistory: { name: 'Read Message History', important: false },
+ MentionEveryone: { name: 'Mention @\u200Beveryone, @\u200Bhere, and All Roles', important: true }, // name has a zero-width space to prevent accidents
+ UseExternalEmojis: { name: 'Use External Emoji', important: false },
+ ViewGuildInsights: { name: 'View Server Insights', important: true },
+ Connect: { name: 'Connect', important: false },
+ Speak: { name: 'Speak', important: false },
+ MuteMembers: { name: 'Mute Members', important: true },
+ DeafenMembers: { name: 'Deafen Members', important: true },
+ MoveMembers: { name: 'Move Members', important: true },
+ UseVAD: { name: 'Use Voice Activity', important: false },
+ ChangeNickname: { name: 'Change Nickname', important: false },
+ ManageNicknames: { name: 'Change Nicknames', important: true },
+ ManageRoles: { name: 'Manage Roles', important: true },
+ ManageWebhooks: { name: 'Manage Webhooks', important: true },
+ ManageEmojisAndStickers: { name: 'Manage Emojis and Stickers', important: true },
+ UseApplicationCommands: { name: 'Use Slash Commands', important: false },
+ RequestToSpeak: { name: 'Request to Speak', important: false },
+ ManageEvents: { name: 'Manage Events', important: true },
+ ManageThreads: { name: 'Manage Threads', important: true },
+ CreatePublicThreads: { name: 'Create Public Threads', important: false },
+ CreatePrivateThreads: { name: 'Create Private Threads', important: false },
+ UseExternalStickers: { name: 'Use External Stickers', important: false },
+ SendMessagesInThreads: { name: 'Send Messages In Threads', important: false },
+ StartEmbeddedActivities: { name: 'Start Activities', important: false },
+ ModerateMembers: { name: 'Timeout Members', important: true },
+ UseEmbeddedActivities: { name: 'Use Activities', important: false }
+ },
+
+ // prettier-ignore
+ features: {
[GuildFeature.Verified]: { name: 'Verified', important: true, emoji: '<:verified:850795049817473066>', weight: 0 },
[GuildFeature.Partnered]: { name: 'Partnered', important: true, emoji: '<:partneredServer:850794851955507240>', weight: 1 },
[GuildFeature.MoreStickers]: { name: 'More Stickers', important: true, emoji: null, weight: 2 },
@@ -283,206 +287,123 @@ export class BushConstants {
[GuildFeature.LinkedToHub]: { name: 'Linked To Hub', important: false, emoji: null, weight: 31 },
},
- regions: {
- 'automatic': ':united_nations: Automatic',
- 'brazil': ':flag_br: Brazil',
- 'europe': ':flag_eu: Europe',
- 'hongkong': ':flag_hk: Hongkong',
- 'india': ':flag_in: India',
- 'japan': ':flag_jp: Japan',
- 'russia': ':flag_ru: Russia',
- 'singapore': ':flag_sg: Singapore',
- 'southafrica': ':flag_za: South Africa',
- 'sydney': ':flag_au: Sydney',
- 'us-central': ':flag_us: US Central',
- 'us-east': ':flag_us: US East',
- 'us-south': ':flag_us: US South',
- 'us-west': ':flag_us: US West'
- },
-
- otherEmojis: {
- ServerBooster1: '<:serverBooster1:848740052091142145>',
- ServerBooster2: '<:serverBooster2:848740090506510388>',
- ServerBooster3: '<:serverBooster3:848740124992077835>',
- ServerBooster6: '<:serverBooster6:848740155245461514>',
- ServerBooster9: '<:serverBooster9:848740188846030889>',
- ServerBooster12: '<:serverBooster12:848740304365551668>',
- ServerBooster15: '<:serverBooster15:848740354890137680>',
- ServerBooster18: '<:serverBooster18:848740402886606868>',
- ServerBooster24: '<:serverBooster24:848740444628320256>',
- Nitro: '<:nitro:848740498054971432>',
- Booster: '<:booster:848747775020892200>',
- Owner: '<:owner:848746439311753286>',
- Admin: '<:admin:848963914628333598>',
- Superuser: '<:superUser:848947986326224926>',
- Developer: '<:developer:848954538111139871>',
- BushVerified: '<:verfied:853360152090771497>',
- BoostTier1: '<:boostitle:853363736679940127>',
- BoostTier2: '<:boostitle:853363752728789075>',
- BoostTier3: '<:boostitle:853363769132056627>',
- ChannelText: '<:text:853375537791893524>',
- ChannelNews: '<:announcements:853375553531674644>',
- ChannelVoice: '<:voice:853375566735212584>',
- ChannelStage: '<:stage:853375583521210468>',
- // ChannelStore: '<:store:853375601175691266>',
- ChannelCategory: '<:category:853375615260819476>',
- ChannelThread: '<:thread:865033845753249813>'
- },
-
- userFlags: {
- Staff: '<:discordEmployee:848742947826434079>',
- Partner: '<:partneredServerOwner:848743051593777152>',
- Hypesquad: '<:hypeSquadEvents:848743108283072553>',
- BugHunterLevel1: '<:bugHunter:848743239850393640>',
- HypeSquadOnlineHouse1: '<:hypeSquadBravery:848742910563844127>',
- HypeSquadOnlineHouse2: '<:hypeSquadBrilliance:848742840649646101>',
- HypeSquadOnlineHouse3: '<:hypeSquadBalance:848742877537370133>',
- PremiumEarlySupporter: '<:earlySupporter:848741030102171648>',
- TeamPseudoUser: 'TeamPseudoUser',
- BugHunterLevel2: '<:bugHunterGold:848743283080822794>',
- VerifiedBot: '<:verifiedbot_rebrand1:938928232667947028><:verifiedbot_rebrand2:938928355707879475>',
- VerifiedDeveloper: '<:earlyVerifiedBotDeveloper:848741079875846174>',
- CertifiedModerator: '<:discordCertifiedModerator:877224285901582366>',
- BotHTTPInteractions: 'BotHTTPInteractions',
- Spammer: 'Spammer'
- },
-
- status: {
- online: '<:online:848937141639577690>',
- idle: '<:idle:848937158261211146>',
- dnd: '<:dnd:848937173780135986>',
- offline: '<:offline:848939387277672448>',
- streaming: '<:streaming:848937187479519242>'
- },
-
- maybeNitroDiscrims: ['1111', '2222', '3333', '4444', '5555', '6666', '6969', '7777', '8888', '9999'],
-
- capes: [
- /* supporter capes */
- { name: 'patreon1', purchasable: false /* moulberry no longer offers */ },
- { name: 'patreon2', purchasable: false /* moulberry no longer offers */ },
- { name: 'fade', custom: `${rawCapeUrl}fade.gif`, purchasable: true },
- { name: 'lava', custom: `${rawCapeUrl}lava.gif`, purchasable: true },
- { name: 'mcworld', custom: `${rawCapeUrl}mcworld_compressed.gif`, purchasable: true },
- { name: 'negative', custom: `${rawCapeUrl}negative_compressed.gif`, purchasable: true },
- { name: 'space', custom: `${rawCapeUrl}space_compressed.gif`, purchasable: true },
- { name: 'void', custom: `${rawCapeUrl}void.gif`, purchasable: true },
- { name: 'tunnel', custom: `${rawCapeUrl}tunnel.gif`, purchasable: true },
- /* Staff capes */
- { name: 'contrib' },
- { name: 'mbstaff' },
- { name: 'ironmoon' },
- { name: 'gravy' },
- { name: 'nullzee' },
- /* partner capes */
- { name: 'thebakery' },
- { name: 'dsm' },
- { name: 'packshq' },
- { name: 'furf' },
- { name: 'skytils' },
- { name: 'sbp' },
- { name: 'subreddit_light' },
- { name: 'subreddit_dark' },
- { name: 'skyclient' },
- { name: 'sharex' },
- { name: 'sharex_white' },
- /* streamer capes */
- { name: 'alexxoffi' },
- { name: 'jakethybro' },
- { name: 'krusty' },
- { name: 'krusty_day' },
- { name: 'krusty_night' },
- { name: 'krusty_sunset' },
- { name: 'soldier' },
- { name: 'zera' },
- { name: 'secondpfirsisch' },
- { name: 'stormy_lh' }
- ].map((value, index) => ({ ...value, index })),
-
- roleMap: [
- { name: '*', id: '792453550768390194' },
- { name: 'Admin Perms', id: '746541309853958186' },
- { name: 'Sr. Moderator', id: '782803470205190164' },
- { name: 'Moderator', id: '737308259823910992' },
- { name: 'Helper', id: '737440116230062091' },
- { name: 'Trial Helper', id: '783537091946479636' },
- { name: 'Contributor', id: '694431057532944425' },
- { name: 'Giveaway Donor', id: '784212110263451649' },
- { name: 'Giveaway (200m)', id: '810267756426690601' },
- { name: 'Giveaway (100m)', id: '801444430522613802' },
- { name: 'Giveaway (50m)', id: '787497512981757982' },
- { name: 'Giveaway (25m)', id: '787497515771232267' },
- { name: 'Giveaway (10m)', id: '787497518241153025' },
- { name: 'Giveaway (5m)', id: '787497519768403989' },
- { name: 'Giveaway (1m)', id: '787497521084891166' },
- { name: 'Suggester', id: '811922322767609877' },
- { name: 'Partner', id: '767324547312779274' },
- { name: 'Level Locked', id: '784248899044769792' },
- { name: 'No Files', id: '786421005039173633' },
- { name: 'No Reactions', id: '786421270924361789' },
- { name: 'No Links', id: '786421269356740658' },
- { name: 'No Bots', id: '786804858765312030' },
- { name: 'No VC', id: '788850482554208267' },
- { name: 'No Giveaways', id: '808265422334984203' },
- { name: 'No Support', id: '790247359824396319' }
- ],
-
- roleWhitelist: {
- 'Partner': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Suggester': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper', 'Trial Helper', 'Contributor'],
- 'Level Locked': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No Files': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No Reactions': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No Links': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No Bots': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No VC': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'No Giveaways': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper'],
- 'No Support': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway Donor': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (200m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (100m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (50m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (25m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (10m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (5m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
- 'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator']
- }
- } as const);
-
- public static ArgumentMatches = Object.freeze({
- ...ArgumentMatches
- } as const);
-
- public static ArgumentTypes = Object.freeze({
- ...ArgumentTypes,
- 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 BlockedReasons = Object.freeze({
- ...BuiltInReasons,
- 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 CommandHandlerEvents = Object.freeze({
- ...CommandHandlerEvents
- } as const);
-
- public static moulberryBushRoleMap = BushClientUtil.deepFreeze([
+ regions: {
+ 'automatic': ':united_nations: Automatic',
+ 'brazil': ':flag_br: Brazil',
+ 'europe': ':flag_eu: Europe',
+ 'hongkong': ':flag_hk: Hongkong',
+ 'india': ':flag_in: India',
+ 'japan': ':flag_jp: Japan',
+ 'russia': ':flag_ru: Russia',
+ 'singapore': ':flag_sg: Singapore',
+ 'southafrica': ':flag_za: South Africa',
+ 'sydney': ':flag_au: Sydney',
+ 'us-central': ':flag_us: US Central',
+ 'us-east': ':flag_us: US East',
+ 'us-south': ':flag_us: US South',
+ 'us-west': ':flag_us: US West'
+ },
+
+ otherEmojis: {
+ ServerBooster1: '<:serverBooster1:848740052091142145>',
+ ServerBooster2: '<:serverBooster2:848740090506510388>',
+ ServerBooster3: '<:serverBooster3:848740124992077835>',
+ ServerBooster6: '<:serverBooster6:848740155245461514>',
+ ServerBooster9: '<:serverBooster9:848740188846030889>',
+ ServerBooster12: '<:serverBooster12:848740304365551668>',
+ ServerBooster15: '<:serverBooster15:848740354890137680>',
+ ServerBooster18: '<:serverBooster18:848740402886606868>',
+ ServerBooster24: '<:serverBooster24:848740444628320256>',
+ Nitro: '<:nitro:848740498054971432>',
+ Booster: '<:booster:848747775020892200>',
+ Owner: '<:owner:848746439311753286>',
+ Admin: '<:admin:848963914628333598>',
+ Superuser: '<:superUser:848947986326224926>',
+ Developer: '<:developer:848954538111139871>',
+ BushVerified: '<:verfied:853360152090771497>',
+ BoostTier1: '<:boostitle:853363736679940127>',
+ BoostTier2: '<:boostitle:853363752728789075>',
+ BoostTier3: '<:boostitle:853363769132056627>',
+ ChannelText: '<:text:853375537791893524>',
+ ChannelNews: '<:announcements:853375553531674644>',
+ ChannelVoice: '<:voice:853375566735212584>',
+ ChannelStage: '<:stage:853375583521210468>',
+ // ChannelStore: '<:store:853375601175691266>',
+ ChannelCategory: '<:category:853375615260819476>',
+ ChannelThread: '<:thread:865033845753249813>'
+ },
+
+ userFlags: {
+ Staff: '<:discordEmployee:848742947826434079>',
+ Partner: '<:partneredServerOwner:848743051593777152>',
+ Hypesquad: '<:hypeSquadEvents:848743108283072553>',
+ BugHunterLevel1: '<:bugHunter:848743239850393640>',
+ HypeSquadOnlineHouse1: '<:hypeSquadBravery:848742910563844127>',
+ HypeSquadOnlineHouse2: '<:hypeSquadBrilliance:848742840649646101>',
+ HypeSquadOnlineHouse3: '<:hypeSquadBalance:848742877537370133>',
+ PremiumEarlySupporter: '<:earlySupporter:848741030102171648>',
+ TeamPseudoUser: 'TeamPseudoUser',
+ BugHunterLevel2: '<:bugHunterGold:848743283080822794>',
+ VerifiedBot: '<:verifiedbot_rebrand1:938928232667947028><:verifiedbot_rebrand2:938928355707879475>',
+ VerifiedDeveloper: '<:earlyVerifiedBotDeveloper:848741079875846174>',
+ CertifiedModerator: '<:discordCertifiedModerator:877224285901582366>',
+ BotHTTPInteractions: 'BotHTTPInteractions',
+ Spammer: 'Spammer'
+ },
+
+ status: {
+ online: '<:online:848937141639577690>',
+ idle: '<:idle:848937158261211146>',
+ dnd: '<:dnd:848937173780135986>',
+ offline: '<:offline:848939387277672448>',
+ streaming: '<:streaming:848937187479519242>'
+ },
+
+ maybeNitroDiscrims: ['1111', '2222', '3333', '4444', '5555', '6666', '6969', '7777', '8888', '9999'],
+
+ capes: [
+ /* supporter capes */
+ { name: 'patreon1', purchasable: false /* moulberry no longer offers */ },
+ { name: 'patreon2', purchasable: false /* moulberry no longer offers */ },
+ { name: 'fade', custom: `${rawCapeUrl}fade.gif`, purchasable: true },
+ { name: 'lava', custom: `${rawCapeUrl}lava.gif`, purchasable: true },
+ { name: 'mcworld', custom: `${rawCapeUrl}mcworld_compressed.gif`, purchasable: true },
+ { name: 'negative', custom: `${rawCapeUrl}negative_compressed.gif`, purchasable: true },
+ { name: 'space', custom: `${rawCapeUrl}space_compressed.gif`, purchasable: true },
+ { name: 'void', custom: `${rawCapeUrl}void.gif`, purchasable: true },
+ { name: 'tunnel', custom: `${rawCapeUrl}tunnel.gif`, purchasable: true },
+ /* Staff capes */
+ { name: 'contrib' },
+ { name: 'mbstaff' },
+ { name: 'ironmoon' },
+ { name: 'gravy' },
+ { name: 'nullzee' },
+ /* partner capes */
+ { name: 'thebakery' },
+ { name: 'dsm' },
+ { name: 'packshq' },
+ { name: 'furf' },
+ { name: 'skytils' },
+ { name: 'sbp' },
+ { name: 'subreddit_light' },
+ { name: 'subreddit_dark' },
+ { name: 'skyclient' },
+ { name: 'sharex' },
+ { name: 'sharex_white' },
+ /* streamer capes */
+ { name: 'alexxoffi' },
+ { name: 'jakethybro' },
+ { name: 'krusty' },
+ { name: 'krusty_day' },
+ { name: 'krusty_night' },
+ { name: 'krusty_sunset' },
+ { name: 'soldier' },
+ { name: 'zera' },
+ { name: 'secondpfirsisch' },
+ { name: 'stormy_lh' }
+ ].map((value, index) => ({ ...value, index })),
+
+ roleMap: [
{ name: '*', id: '792453550768390194' },
{ name: 'Admin Perms', id: '746541309853958186' },
{ name: 'Sr. Moderator', id: '782803470205190164' },
@@ -508,8 +429,90 @@ export class BushConstants {
{ name: 'No VC', id: '788850482554208267' },
{ name: 'No Giveaways', id: '808265422334984203' },
{ name: 'No Support', id: '790247359824396319' }
- ] as const);
-}
-
-export type PronounCode = keyof typeof BushConstants['pronounMapping'];
-export type Pronoun = typeof BushConstants['pronounMapping'][PronounCode];
+ ],
+
+ roleWhitelist: {
+ 'Partner': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Suggester': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper', 'Trial Helper', 'Contributor'],
+ 'Level Locked': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No Files': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No Reactions': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No Links': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No Bots': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No VC': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'No Giveaways': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper'],
+ 'No Support': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway Donor': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (200m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (100m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (50m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (25m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (10m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (5m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'],
+ 'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator']
+ }
+} as const);
+
+export const ArgumentMatches = Object.freeze({
+ ...AkairoArgumentMatches
+} as const);
+
+export const ArgumentTypes = Object.freeze({
+ ...AkairoArgumentTypes,
+ 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);
+
+export const BlockedReasons = Object.freeze({
+ ...BuiltInReasons,
+ 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);
+
+export const CommandHandlerEvents = Object.freeze({
+ ...AkairoCommandHandlerEvents
+} as const);
+
+export const moulberryBushRoleMap = deepLock([
+ { name: '*', id: '792453550768390194' },
+ { name: 'Admin Perms', id: '746541309853958186' },
+ { name: 'Sr. Moderator', id: '782803470205190164' },
+ { name: 'Moderator', id: '737308259823910992' },
+ { name: 'Helper', id: '737440116230062091' },
+ { name: 'Trial Helper', id: '783537091946479636' },
+ { name: 'Contributor', id: '694431057532944425' },
+ { name: 'Giveaway Donor', id: '784212110263451649' },
+ { name: 'Giveaway (200m)', id: '810267756426690601' },
+ { name: 'Giveaway (100m)', id: '801444430522613802' },
+ { name: 'Giveaway (50m)', id: '787497512981757982' },
+ { name: 'Giveaway (25m)', id: '787497515771232267' },
+ { name: 'Giveaway (10m)', id: '787497518241153025' },
+ { name: 'Giveaway (5m)', id: '787497519768403989' },
+ { name: 'Giveaway (1m)', id: '787497521084891166' },
+ { name: 'Suggester', id: '811922322767609877' },
+ { name: 'Partner', id: '767324547312779274' },
+ { name: 'Level Locked', id: '784248899044769792' },
+ { name: 'No Files', id: '786421005039173633' },
+ { name: 'No Reactions', id: '786421270924361789' },
+ { name: 'No Links', id: '786421269356740658' },
+ { name: 'No Bots', id: '786804858765312030' },
+ { name: 'No VC', id: '788850482554208267' },
+ { name: 'No Giveaways', id: '808265422334984203' },
+ { name: 'No Support', id: '790247359824396319' }
+] as const);
+
+export type PronounCode = keyof typeof pronounMapping;
+export type Pronoun = typeof pronounMapping[PronounCode];
diff --git a/src/lib/utils/BushLogger.ts b/src/lib/utils/BushLogger.ts
index 073b8e2..7d42574 100644
--- a/src/lib/utils/BushLogger.ts
+++ b/src/lib/utils/BushLogger.ts
@@ -1,10 +1,11 @@
import chalk from 'chalk';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { EmbedBuilder, Util, type Message, type PartialTextBasedChannelFields } from 'discord.js';
+import { EmbedBuilder, escapeMarkdown, PartialTextBasedChannelFields, type Message } from 'discord.js';
import repl, { REPLServer, REPL_MODE_STRICT } from 'repl';
import { WriteStream } from 'tty';
-import { inspect } from 'util';
import { type SendMessageType } from '../extensions/discord-akairo/BushClient.js';
+import { colors } from './BushConstants.js';
+import { getConfigChannel, inspect } from './BushUtils.js';
let REPL: REPLServer;
let replGone = false;
@@ -59,78 +60,78 @@ export function init() {
}
/**
- * Custom logging utility for the bot.
+ * Parses the content surrounding by `<<>>` and emphasizes it with the given color or by making it bold.
+ * @param content The content to parse.
+ * @param color The color to emphasize the content with.
+ * @param discordFormat Whether or not to format the content for discord.
+ * @returns The formatted content.
*/
-export class BushLogger {
- /**
- * Parses the content surrounding by `<<>>` and emphasizes it with the given color or by making it bold.
- * @param content The content to parse.
- * @param color The color to emphasize the content with.
- * @param discordFormat Whether or not to format the content for discord.
- * @returns The formatted content.
- */
- static #parseFormatting(
- content: any,
- color: 'blueBright' | 'blackBright' | 'redBright' | 'yellowBright' | 'greenBright' | '',
- discordFormat = false
- ): string | typeof content {
- if (typeof content !== 'string') return content;
- const newContent: Array<string> = content.split(/<<|>>/);
- const tempParsedArray: Array<string> = [];
- newContent.forEach((value, index) => {
- if (index % 2 !== 0) {
- tempParsedArray.push(discordFormat ? `**${Util.escapeMarkdown(value)}**` : color ? chalk[color](value) : value);
- } else {
- tempParsedArray.push(discordFormat ? Util.escapeMarkdown(value) : value);
- }
- });
- return tempParsedArray.join('');
- }
-
- /**
- * Inspects the content and returns a string.
- * @param content The content to inspect.
- * @param depth The depth the content will inspected. Defaults to `2`.
- * @param colors Whether or not to use colors in the output. Defaults to `true`.
- * @returns The inspected content.
- */
- static #inspectContent(content: any, depth = 2, colors = true): string {
- if (typeof content !== 'string') {
- return inspect(content, { depth, colors });
+function parseFormatting(
+ content: any,
+ color: 'blueBright' | 'blackBright' | 'redBright' | 'yellowBright' | 'greenBright' | '',
+ discordFormat = false
+): string | typeof content {
+ if (typeof content !== 'string') return content;
+ const newContent: Array<string> = content.split(/<<|>>/);
+ const tempParsedArray: Array<string> = [];
+ newContent.forEach((value, index) => {
+ if (index % 2 !== 0) {
+ tempParsedArray.push(discordFormat ? `**${escapeMarkdown(value)}**` : color ? chalk[color](value) : value);
+ } else {
+ tempParsedArray.push(discordFormat ? escapeMarkdown(value) : value);
}
- return content;
- }
+ });
+ return tempParsedArray.join('');
+}
- /**
- * Strips ANSI color codes from a string.
- * @param text The string to strip color codes from.
- * @returns A string without ANSI color codes.
- */
- static #stripColor(text: string): string {
- return text.replace(
- // eslint-disable-next-line no-control-regex
- /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
- ''
- );
+/**
+ * Inspects the content and returns a string.
+ * @param content The content to inspect.
+ * @param depth The depth the content will inspected. Defaults to `2`.
+ * @param colors Whether or not to use colors in the output. Defaults to `true`.
+ * @returns The inspected content.
+ */
+function inspectContent(content: any, depth = 2, colors = true): string {
+ if (typeof content !== 'string') {
+ return inspect(content, { depth, colors });
}
+ return content;
+}
- /**
- * Generates a formatted timestamp for logging.
- * @returns The formatted timestamp.
- */
- static #getTimeStamp(): string {
- const now = new Date();
- const hours = now.getHours();
- const minute = now.getMinutes();
- let hour = hours;
- let amOrPm: 'AM' | 'PM' = 'AM';
- if (hour > 12) {
- amOrPm = 'PM';
- hour = hour - 12;
- }
- return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}`;
+/**
+ * Strips ANSI color codes from a string.
+ * @param text The string to strip color codes from.
+ * @returns A string without ANSI color codes.
+ */
+function stripColor(text: string): string {
+ return text.replace(
+ // eslint-disable-next-line no-control-regex
+ /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
+ ''
+ );
+}
+
+/**
+ * Generates a formatted timestamp for logging.
+ * @returns The formatted timestamp.
+ */
+function getTimeStamp(): string {
+ const now = new Date();
+ const hours = now.getHours();
+ const minute = now.getMinutes();
+ let hour = hours;
+ let amOrPm: 'AM' | 'PM' = 'AM';
+ if (hour > 12) {
+ amOrPm = 'PM';
+ hour = hour - 12;
}
+ return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}`;
+}
+/**
+ * Custom logging utility for the bot.
+ */
+export default {
/**
* Logs information. Highlight information by surrounding it in `<<>>`.
* @param header The header displayed before the content, displayed in cyan.
@@ -138,31 +139,31 @@ export class BushLogger {
* @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;
- }
+ get log() {
+ return this.info;
+ },
/**
* Sends a message to the log channel.
* @param message The parameter to pass to {@link PartialTextBasedChannelFields.send}.
* @returns The message sent.
*/
- public static async channelLog(message: SendMessageType): Promise<Message | null> {
- const channel = await util.getConfigChannel('log');
+ async channelLog(message: SendMessageType): Promise<Message | null> {
+ const channel = await getConfigChannel('log');
return await channel.send(message).catch(() => null);
- }
+ },
/**
* Sends a message to the error channel.
* @param message The parameter to pass to {@link PartialTextBasedChannelFields.send}.
* @returns The message sent.
*/
- public static async channelError(message: SendMessageType): Promise<Message | null> {
- const channel = await util.getConfigChannel('error');
+ async channelError(message: SendMessageType): Promise<Message | null> {
+ const channel = await getConfigChannel('error');
if (!channel) {
void this.error(
'BushLogger',
- `Could not find error channel, was originally going to send: \n${util.inspect(message, {
+ `Could not find error channel, was originally going to send: \n${inspect(message, {
colors: true
})}\n${new Error().stack?.substring(8)}`,
false
@@ -170,27 +171,27 @@ export class BushLogger {
return null;
}
return await channel.send(message);
- }
+ },
/**
* 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`.
*/
- public static debug(content: any, depth = 0): void {
+ debug(content: any, depth = 0): void {
if (!client.config.isDevelopment) return;
- const newContent = this.#inspectContent(content, depth, true);
- console.log(`${chalk.bgMagenta(this.#getTimeStamp())} ${chalk.magenta('[Debug]')} ${newContent}`);
- }
+ const newContent = inspectContent(content, depth, true);
+ console.log(`${chalk.bgMagenta(getTimeStamp())} ${chalk.magenta('[Debug]')} ${newContent}`);
+ },
/**
* Logs raw debug information. Only works in dev is enabled in the config.
* @param content The content to log.
*/
- public static debugRaw(...content: any): void {
+ debugRaw(...content: any): void {
if (!client.config.isDevelopment) return;
- console.log(`${chalk.bgMagenta(this.#getTimeStamp())} ${chalk.magenta('[Debug]')}`, ...content);
- }
+ console.log(`${chalk.bgMagenta(getTimeStamp())} ${chalk.magenta('[Debug]')}`, ...content);
+ },
/**
* Logs verbose information. Highlight information by surrounding it in `<<>>`.
@@ -199,19 +200,17 @@ export class BushLogger {
* @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): Promise<void> {
+ async verbose(header: string, content: any, sendChannel = false, depth = 0): Promise<void> {
if (!client.config.logging.verbose) return;
- const newContent = this.#inspectContent(content, depth, true);
- console.log(
- `${chalk.bgGrey(this.#getTimeStamp())} ${chalk.grey(`[${header}]`)} ${this.#parseFormatting(newContent, 'blackBright')}`
- );
+ const newContent = inspectContent(content, depth, true);
+ console.log(`${chalk.bgGrey(getTimeStamp())} ${chalk.grey(`[${header}]`)} ${parseFormatting(newContent, 'blackBright')}`);
if (!sendChannel) return;
const embed = new EmbedBuilder()
- .setDescription(`**[${header}]** ${this.#parseFormatting(this.#stripColor(newContent), '', true)}`)
- .setColor(util.colors.gray)
+ .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`)
+ .setColor(colors.gray)
.setTimestamp();
await this.channelLog({ embeds: [embed] });
- }
+ },
/**
* Logs very verbose information. Highlight information by surrounding it in `<<>>`.
@@ -219,23 +218,23 @@ export class BushLogger {
* @param content The content to log, highlights displayed in bright black.
* @param depth The depth the content will inspected. Defaults to `0`.
*/
- public static async superVerbose(header: string, content: any, depth = 0): Promise<void> {
+ async superVerbose(header: string, content: any, depth = 0): Promise<void> {
if (!client.config.logging.verbose) return;
- const newContent = this.#inspectContent(content, depth, true);
+ const newContent = inspectContent(content, depth, true);
console.log(
- `${chalk.bgHex('#949494')(this.#getTimeStamp())} ${chalk.hex('#949494')(`[${header}]`)} ${chalk.hex('#b3b3b3')(newContent)}`
+ `${chalk.bgHex('#949494')(getTimeStamp())} ${chalk.hex('#949494')(`[${header}]`)} ${chalk.hex('#b3b3b3')(newContent)}`
);
- }
+ },
/**
* Logs raw very verbose information.
* @param header The header printed before the content, displayed in purple.
* @param content The content to log.
*/
- public static async superVerboseRaw(header: string, ...content: any[]): Promise<void> {
+ async superVerboseRaw(header: string, ...content: any[]): Promise<void> {
if (!client.config.logging.verbose) return;
- console.log(`${chalk.bgHex('#a3a3a3')(this.#getTimeStamp())} ${chalk.hex('#a3a3a3')(`[${header}]`)}`, ...content);
- }
+ console.log(`${chalk.bgHex('#a3a3a3')(getTimeStamp())} ${chalk.hex('#a3a3a3')(`[${header}]`)}`, ...content);
+ },
/**
* Logs information. Highlight information by surrounding it in `<<>>`.
@@ -244,19 +243,17 @@ export class BushLogger {
* @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): Promise<void> {
+ async info(header: string, content: any, sendChannel = true, depth = 0): Promise<void> {
if (!client.config.logging.info) return;
- const newContent = this.#inspectContent(content, depth, true);
- console.log(
- `${chalk.bgCyan(this.#getTimeStamp())} ${chalk.cyan(`[${header}]`)} ${this.#parseFormatting(newContent, 'blueBright')}`
- );
+ const newContent = inspectContent(content, depth, true);
+ console.log(`${chalk.bgCyan(getTimeStamp())} ${chalk.cyan(`[${header}]`)} ${parseFormatting(newContent, 'blueBright')}`);
if (!sendChannel) return;
const embed = new EmbedBuilder()
- .setDescription(`**[${header}]** ${this.#parseFormatting(this.#stripColor(newContent), '', true)}`)
- .setColor(util.colors.info)
+ .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`)
+ .setColor(colors.info)
.setTimestamp();
await this.channelLog({ embeds: [embed] });
- }
+ },
/**
* Logs warnings. Highlight information by surrounding it in `<<>>`.
@@ -265,22 +262,19 @@ export class BushLogger {
* @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): Promise<void> {
- const newContent = this.#inspectContent(content, depth, true);
+ async warn(header: string, content: any, sendChannel = true, depth = 0): Promise<void> {
+ const newContent = inspectContent(content, depth, true);
console.warn(
- `${chalk.bgYellow(this.#getTimeStamp())} ${chalk.yellow(`[${header}]`)} ${this.#parseFormatting(
- newContent,
- 'yellowBright'
- )}`
+ `${chalk.bgYellow(getTimeStamp())} ${chalk.yellow(`[${header}]`)} ${parseFormatting(newContent, 'yellowBright')}`
);
if (!sendChannel) return;
const embed = new EmbedBuilder()
- .setDescription(`**[${header}]** ${this.#parseFormatting(this.#stripColor(newContent), '', true)}`)
- .setColor(util.colors.warn)
+ .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`)
+ .setColor(colors.warn)
.setTimestamp();
await this.channelError({ embeds: [embed] });
- }
+ },
/**
* Logs errors. Highlight information by surrounding it in `<<>>`.
@@ -289,22 +283,19 @@ export class BushLogger {
* @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): Promise<void> {
- const newContent = this.#inspectContent(content, depth, true);
+ async error(header: string, content: any, sendChannel = true, depth = 0): Promise<void> {
+ const newContent = inspectContent(content, depth, true);
console.warn(
- `${chalk.bgRedBright(this.#getTimeStamp())} ${chalk.redBright(`[${header}]`)} ${this.#parseFormatting(
- newContent,
- 'redBright'
- )}`
+ `${chalk.bgRedBright(getTimeStamp())} ${chalk.redBright(`[${header}]`)} ${parseFormatting(newContent, 'redBright')}`
);
if (!sendChannel) return;
const embed = new EmbedBuilder()
- .setDescription(`**[${header}]** ${this.#parseFormatting(this.#stripColor(newContent), '', true)}`)
- .setColor(util.colors.error)
+ .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`)
+ .setColor(colors.error)
.setTimestamp();
await this.channelError({ embeds: [embed] });
return;
- }
+ },
/**
* Logs successes. Highlight information by surrounding it in `<<>>`.
@@ -313,21 +304,18 @@ export class BushLogger {
* @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): Promise<void> {
- const newContent = this.#inspectContent(content, depth, true);
+ async success(header: string, content: any, sendChannel = true, depth = 0): Promise<void> {
+ const newContent = inspectContent(content, depth, true);
console.log(
- `${chalk.bgGreen(this.#getTimeStamp())} ${chalk.greenBright(`[${header}]`)} ${this.#parseFormatting(
- newContent,
- 'greenBright'
- )}`
+ `${chalk.bgGreen(getTimeStamp())} ${chalk.greenBright(`[${header}]`)} ${parseFormatting(newContent, 'greenBright')}`
);
if (!sendChannel) return;
const embed = new EmbedBuilder()
- .setDescription(`**[${header}]** ${this.#parseFormatting(this.#stripColor(newContent), '', true)}`)
- .setColor(util.colors.success)
+ .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`)
+ .setColor(colors.success)
.setTimestamp();
await this.channelLog({ embeds: [embed] }).catch(() => {});
}
-}
+};
/** @typedef {PartialTextBasedChannelFields} vscodeDontDeleteMyImportTy */
diff --git a/src/lib/utils/BushUtils.ts b/src/lib/utils/BushUtils.ts
new file mode 100644
index 0000000..8a84d80
--- /dev/null
+++ b/src/lib/utils/BushUtils.ts
@@ -0,0 +1,1058 @@
+import {
+ Arg,
+ BushClient,
+ CodeBlockLang,
+ CommandMessage,
+ emojis,
+ Global,
+ Pronoun,
+ pronounMapping,
+ regex,
+ Shared,
+ SlashEditMessageType,
+ SlashSendMessageType,
+ timeUnits,
+ type BaseBushArgumentType,
+ type BushInspectOptions,
+ type GlobalCache,
+ type PronounCode,
+ type SharedCache,
+ type SlashMessage
+} from '#lib';
+import { humanizeDuration as humanizeDurationMod } from '@notenoughupdates/humanize-duration';
+import assert from 'assert';
+import { exec } from 'child_process';
+import deepLock from 'deep-lock';
+import { Util as AkairoUtil } from 'discord-akairo';
+import {
+ cleanCodeBlockContent,
+ Constants as DiscordConstants,
+ EmbedBuilder,
+ escapeCodeBlock,
+ GuildMember,
+ Message,
+ OAuth2Scopes,
+ PermissionFlagsBits,
+ PermissionsBitField,
+ Routes,
+ ThreadMember,
+ User,
+ UserResolvable,
+ type APIEmbed,
+ type APIMessage,
+ type CommandInteraction,
+ type InteractionReplyOptions,
+ type PermissionsString,
+ type Snowflake,
+ type TextChannel
+} from 'discord.js';
+import got from 'got';
+import _ from 'lodash';
+import { inspect as inspectUtil, promisify } from 'util';
+import CommandErrorListener from '../../listeners/commands/commandError.js';
+import * as Format from '../common/util/Format.js';
+
+export type StripPrivate<T> = { [K in keyof T]: T[K] extends Record<string, any> ? StripPrivate<T[K]> : T[K] };
+
+/**
+ * The hastebin urls used to post to hastebin, attempts to post in order
+ */
+const hasteURLs: string[] = [
+ 'https://hst.sh',
+ // 'https://hasteb.in',
+ 'https://hastebin.com',
+ 'https://mystb.in',
+ 'https://haste.clicksminuteper.net',
+ 'https://paste.pythondiscord.com',
+ 'https://haste.unbelievaboat.com'
+ // 'https://haste.tyman.tech'
+];
+
+/**
+ * Maps an array of user ids to user objects.
+ * @param ids The list of IDs to map
+ * @returns The list of users mapped
+ */
+export async function mapIDs(ids: Snowflake[]): Promise<User[]> {
+ return await Promise.all(ids.map((id) => client.users.fetch(id)));
+}
+
+/**
+ * Capitalizes the first letter of the given text
+ * @param text The text to capitalize
+ * @returns The capitalized text
+ */
+export function capitalize(text: string): string {
+ return text.charAt(0).toUpperCase() + text.slice(1);
+}
+
+/**
+ * Runs a shell command and gives the output
+ * @param command The shell command to run
+ * @returns The stdout and stderr of the shell command
+ */
+export async function shell(command: string): Promise<{ stdout: string; stderr: string }> {
+ return await promisify(exec)(command);
+}
+
+/**
+ * Posts text to hastebin
+ * @param content The text to post
+ * @returns The url of the posted text
+ */
+export async function haste(content: string, substr = false): Promise<HasteResults> {
+ let isSubstr = false;
+ if (content.length > 400_000 && !substr) {
+ void handleError('haste', new Error(`content over 400,000 characters (${content.length.toLocaleString()})`));
+ return { error: 'content too long' };
+ } else if (content.length > 400_000) {
+ content = content.substring(0, 400_000);
+ isSubstr = true;
+ }
+ for (const url of hasteURLs) {
+ try {
+ 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}`);
+ }
+ }
+ return { error: 'unable to post' };
+}
+
+/**
+ * Resolves a user-provided string into a user object, if possible
+ * @param text The text to try and resolve
+ * @returns The user resolved or null
+ */
+export async function resolveUserAsync(text: string): Promise<User | null> {
+ const idReg = /\d{17,19}/;
+ const idMatch = text.match(idReg);
+ if (idMatch) {
+ try {
+ return await client.users.fetch(text as Snowflake);
+ } catch {
+ // pass
+ }
+ }
+ const mentionReg = /<@!?(?<id>\d{17,19})>/;
+ const mentionMatch = text.match(mentionReg);
+ if (mentionMatch) {
+ try {
+ return await client.users.fetch(mentionMatch.groups!.id as Snowflake);
+ } catch {
+ // pass
+ }
+ }
+ const user = client.users.cache.find((u) => u.username === text);
+ if (user) return user;
+ return null;
+}
+
+/**
+ * Appends the correct ordinal to the given number
+ * @param n The number to append an ordinal to
+ * @returns The number with the ordinal
+ */
+export function ordinal(n: number): string {
+ const s = ['th', 'st', 'nd', 'rd'],
+ v = n % 100;
+ return n + (s[(v - 20) % 10] || s[v] || s[0]);
+}
+
+/**
+ * Chunks an array to the specified size
+ * @param arr The array to chunk
+ * @param perChunk The amount of items per chunk
+ * @returns The chunked array
+ */
+export function chunk<T>(arr: T[], perChunk: number): T[][] {
+ return arr.reduce((all, one, i) => {
+ const ch: number = Math.floor(i / perChunk);
+ (all as any[])[ch] = [].concat(all[ch] || [], one as any);
+ return all;
+ }, []);
+}
+
+/**
+ * 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.
+ */
+export async function 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
+ */
+export async function codeblock(
+ code: string,
+ length: number,
+ language: CodeBlockLang | '' = '',
+ substr = false
+): Promise<string> {
+ let hasteOut = '';
+ code = escapeCodeBlock(code);
+ const prefix = `\`\`\`${language}\n`;
+ const suffix = '\n```';
+ if (code.length + (prefix + suffix).length >= length) {
+ const haste_ = await haste(code, substr);
+ hasteOut = `Too large to display. ${
+ haste_.url
+ ? `Hastebin: ${haste_.url}${language ? `.${language}` : ''}${haste_.error ? ` - ${haste_.error}` : ''}`
+ : `${emojis.error} Hastebin: ${haste_.error}`
+ }`;
+ }
+
+ const FormattedHaste = hasteOut.length ? `\n${hasteOut}` : '';
+ const shortenedCode = hasteOut ? code.substring(0, length - (prefix + FormattedHaste + suffix).length) : code;
+ const code3 = code.length ? prefix + shortenedCode + suffix + FormattedHaste : prefix + suffix;
+ if (code3.length > length) {
+ void client.console.warn(`codeblockError`, `Required Length: ${length}. Actual Length: ${code3.length}`, true);
+ void client.console.warn(`codeblockError`, code3, true);
+ throw new Error('code too long');
+ }
+ return code3;
+}
+
+/**
+ * Generate defaults for {@link inspect}.
+ * @param options The options to create defaults with.
+ * @returns The default options combined with the specified options.
+ */
+function getDefaultInspectOptions(options?: BushInspectOptions): BushInspectOptions {
+ return {
+ showHidden: options?.showHidden ?? false,
+ depth: options?.depth ?? 2,
+ colors: options?.colors ?? false,
+ customInspect: options?.customInspect ?? true,
+ showProxy: options?.showProxy ?? false,
+ maxArrayLength: options?.maxArrayLength ?? Infinity,
+ maxStringLength: options?.maxStringLength ?? Infinity,
+ breakLength: options?.breakLength ?? 80,
+ compact: options?.compact ?? 3,
+ sorted: options?.sorted ?? false,
+ getters: options?.getters ?? true
+ };
+}
+
+/**
+ * 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.
+ */
+function mapCredential(key: string): string {
+ const mapping = {
+ token: 'Main Token',
+ devToken: 'Dev Token',
+ betaToken: 'Beta Token',
+ hypixelApiKey: 'Hypixel Api Key',
+ wolframAlphaAppId: 'Wolfram|Alpha App ID',
+ dbPassword: 'Database Password'
+ };
+ return mapping[key as keyof typeof mapping] || key;
+}
+
+/**
+ * Redacts credentials from a string.
+ * @param text The text to redact credentials from.
+ * @returns The redacted text.
+ */
+export function redact(text: string) {
+ for (const credentialName in { ...client.config.credentials, dbPassword: client.config.db.password }) {
+ const credential = { ...client.config.credentials, dbPassword: client.config.db.password }[
+ credentialName as keyof typeof client.config.credentials
+ ];
+ const replacement = mapCredential(credentialName);
+ const escapeRegex = /[.*+?^${}()|[\]\\]/g;
+ text = text.replace(new RegExp(credential.toString().replace(escapeRegex, '\\$&'), 'g'), `[${replacement} Omitted]`);
+ text = text.replace(
+ new RegExp([...credential.toString()].reverse().join('').replace(escapeRegex, '\\$&'), 'g'),
+ `[${replacement} Omitted]`
+ );
+ }
+ return text;
+}
+
+/**
+ * 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.
+ */
+export function inspect(object: any, options?: BushInspectOptions): string {
+ const optionsWithDefaults = getDefaultInspectOptions(options);
+
+ if (!optionsWithDefaults.inspectStrings && typeof object === 'string') return object;
+
+ return inspectUtil(object, optionsWithDefaults);
+}
+
+/**
+ * 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.
+ */
+export async function inspectCleanRedactCodeblock(
+ input: any,
+ language?: CodeBlockLang | '',
+ inspectOptions?: BushInspectOptions,
+ length = 1024
+) {
+ input = inspect(input, inspectOptions ?? undefined);
+ if (inspectOptions) inspectOptions.inspectStrings = undefined;
+ input = cleanCodeBlockContent(input);
+ input = redact(input);
+ return codeblock(input, length, language, true);
+}
+
+/**
+ * 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}.
+ */
+export async function inspectCleanRedactHaste(input: any, inspectOptions?: BushInspectOptions): Promise<HasteResults> {
+ input = inspect(input, inspectOptions ?? undefined);
+ input = redact(input);
+ return haste(input, true);
+}
+
+/**
+ * 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.
+ */
+export function inspectAndRedact(input: any, inspectOptions?: BushInspectOptions): string {
+ input = inspect(input, inspectOptions ?? undefined);
+ return 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.
+ */
+export async function slashRespond(
+ interaction: CommandInteraction,
+ responseOptions: SlashSendMessageType | SlashEditMessageType
+): Promise<Message | APIMessage | undefined> {
+ const newResponseOptions = typeof responseOptions === 'string' ? { content: responseOptions } : responseOptions;
+ if (interaction.replied || interaction.deferred) {
+ delete (newResponseOptions as InteractionReplyOptions).ephemeral; // Cannot change a preexisting message to be ephemeral
+ return (await interaction.editReply(newResponseOptions)) as Message | APIMessage;
+ } else {
+ await interaction.reply(newResponseOptions);
+ return await interaction.fetchReply().catch(() => undefined);
+ }
+}
+
+/**
+ * Gets a a configured channel as a TextChannel.
+ * @channel The channel to retrieve.
+ */
+export async function getConfigChannel(channel: keyof typeof client['config']['channels']): Promise<TextChannel> {
+ return (await client.channels.fetch(client.config.channels[channel])) as unknown as TextChannel;
+}
+
+/**
+ * Takes an array and combines the elements using the supplied conjunction.
+ * @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`.
+ *
+ * @example
+ * const permissions = oxford(['Administrator', 'SendMessages', 'ManageMessages'], 'and', 'none');
+ * console.log(permissions); // Administrator, SendMessages and ManageMessages
+ */
+export function oxford(array: string[], conjunction: string, ifEmpty?: string): string | undefined {
+ const l = array.length;
+ if (!l) return ifEmpty;
+ if (l < 2) return array[0];
+ if (l < 3) return array.join(` ${conjunction} `);
+ array = array.slice();
+ array[l - 1] = `${conjunction} ${array[l - 1]}`;
+ return array.join(', ');
+}
+
+/**
+ * Get the global cache.
+ */
+export function getGlobal(): GlobalCache;
+/**
+ * Get a key from the global cache.
+ * @param key The key to get in the global cache.
+ */
+export function getGlobal<K extends keyof GlobalCache>(key: K): GlobalCache[K];
+export function getGlobal(key?: keyof GlobalCache) {
+ return key ? client.cache.global[key] : client.cache.global;
+}
+
+export function getShared(): SharedCache;
+export function getShared<K extends keyof SharedCache>(key: K): SharedCache[K];
+export function getShared(key?: keyof SharedCache) {
+ return key ? client.cache.shared[key] : client.cache.shared;
+}
+
+/**
+ * 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.
+ */
+export async function insertOrRemoveFromGlobal<K extends keyof typeof client['cache']['global']>(
+ action: 'add' | 'remove',
+ 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 }));
+ const oldValue: any[] = row[key];
+ const newValue = addOrRemoveFromArray(action, oldValue, value);
+ row[key] = newValue;
+ client.cache.global[key] = newValue;
+ return await row.save().catch((e) => handleError('insertOrRemoveFromGlobal', e));
+}
+
+/**
+ * Add or remove an element from an array stored in the Shared database.
+ * @param action Either `add` or `remove` an element.
+ * @param key The key of the element in the shared cache to update.
+ * @param value The value to add/remove from the array.
+ */
+export async function insertOrRemoveFromShared<
+ K extends Exclude<keyof typeof client['cache']['shared'], 'badWords' | 'autoBanCode'>
+>(action: 'add' | 'remove', key: K, value: typeof client['cache']['shared'][K][0]): Promise<Shared | void> {
+ const row = (await Shared.findByPk(0)) ?? (await Shared.create());
+ const oldValue: any[] = row[key];
+ const newValue = addOrRemoveFromArray(action, oldValue, value);
+ row[key] = newValue;
+ client.cache.shared[key] = newValue;
+ return await row.save().catch((e) => handleError('insertOrRemoveFromShared', e));
+}
+
+/**
+ * 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.
+ */
+export async function 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) => handleError('setGlobal', e));
+}
+
+/**
+ * Updates an element in the Shared database.
+ * @param key The key in the shared cache to update.
+ * @param value The value to set the key to.
+ */
+export async function setShared<K extends Exclude<keyof typeof client['cache']['shared'], 'badWords' | 'autoBanCode'>>(
+ key: K,
+ value: typeof client['cache']['shared'][K]
+): Promise<Shared | void> {
+ const row = (await Shared.findByPk(0)) ?? (await Shared.create());
+ row[key] = value;
+ client.cache.shared[key] = value;
+ return await row.save().catch((e) => handleError('setShared', 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.
+ */
+export function addOrRemoveFromArray<T>(action: 'add' | 'remove', array: T[], value: T): T[] {
+ const set = new Set(array);
+ action === 'add' ? set.add(value) : set.delete(value);
+ return [...set];
+}
+
+/**
+ * Remove an item from an array. All duplicates will be removed.
+ * @param array The array to remove an element from.
+ * @param value The element to remove from the array.
+ */
+export function removeFromArray<T>(array: T[], value: T): T[] {
+ return addOrRemoveFromArray('remove', array, value);
+}
+
+/**
+ * Add an item from an array. All duplicates will be removed.
+ * @param array The array to add an element to.
+ * @param value The element to add to the array.
+ */
+export function addToArray<T>(array: T[], value: T): T[] {
+ return addOrRemoveFromArray('add', array, value);
+}
+
+/**
+ * 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`.
+ */
+export function surroundArray(array: string[], surroundChar1: string, surroundChar2?: string): string[] {
+ return array.map((a) => `${surroundChar1}${a}${surroundChar2 ?? surroundChar1}`);
+}
+
+/**
+ * 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}.
+ */
+export function parseDuration(content: string, remove = true): ParsedDuration {
+ if (!content) return { duration: 0, content: null };
+
+ // eslint-disable-next-line prefer-const
+ let duration: number | null = null;
+ // Try to reduce false positives by requiring a space before the duration, this makes sure it still matches if it is
+ // in the beginning of the argument
+ let contentWithoutTime = ` ${content}`;
+
+ for (const unit in timeUnits) {
+ const regex = timeUnits[unit as keyof typeof timeUnits].match;
+ const match = regex.exec(contentWithoutTime);
+ const value = Number(match?.groups?.[unit]);
+ if (!isNaN(value)) duration! += value * timeUnits[unit as keyof typeof timeUnits].value;
+
+ if (remove) contentWithoutTime = contentWithoutTime.replace(regex, '');
+ }
+ // remove the space added earlier
+ if (contentWithoutTime.startsWith(' ')) contentWithoutTime.replace(' ', '');
+ return { duration, content: 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.
+ * @param round Whether or not to round the smallest unit displayed.
+ * @returns A humanized string of the duration.
+ */
+export function humanizeDuration(duration: number, largest?: number, round = true): string {
+ if (largest) return humanizeDurationMod(duration, { language: 'en', maxDecimalPoints: 2, largest, round })!;
+ else return humanizeDurationMod(duration, { language: 'en', maxDecimalPoints: 2, round })!;
+}
+
+/**
+ * Creates a formatted relative timestamp from a duration in milliseconds.
+ * @param duration The duration in milliseconds.
+ * @returns The formatted relative timestamp.
+ */
+export function timestampDuration(duration: number): string {
+ 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 ex. `16:20`
+ * - **T**: Long Time ex. `16:20:30 `
+ * - **d**: Short Date ex. `20/04/2021`
+ * - **D**: Long Date ex. `20 April 2021`
+ * - **f**: Short Date/Time ex. `20 April 2021 16:20`
+ * - **F**: Long Date/Time ex. `Tuesday, 20 April 2021 16:20`
+ * - **R**: Relative Time ex. `2 months ago`
+ */
+export function timestamp<D extends Date | undefined | null>(
+ date: D,
+ style: TimestampStyle = 'f'
+): D extends Date ? string : undefined {
+ if (!date) return date as unknown as D extends Date ? string : undefined;
+ return `<t:${Math.round(date.getTime() / 1_000)}:${style}>` as unknown as D extends Date ? string : undefined;
+}
+
+/**
+ * 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.
+ * @param round Whether or not to round the smallest unit displayed.
+ * @returns A humanized string of the delta.
+ */
+export function dateDelta(date: Date, largest?: number, round = true): string {
+ return humanizeDuration(new Date().getTime() - date.getTime(), largest ?? 3, round);
+}
+
+/**
+ * Combines {@link timestamp} and {@link dateDelta}
+ * @param date The date to be compared with the current time.
+ * @param style The style of the timestamp.
+ * @returns The formatted timestamp.
+ *
+ * @see
+ * **Styles:**
+ * - **t**: Short Time ex. `16:20`
+ * - **T**: Long Time ex. `16:20:30 `
+ * - **d**: Short Date ex. `20/04/2021`
+ * - **D**: Long Date ex. `20 April 2021`
+ * - **f**: Short Date/Time ex. `20 April 2021 16:20`
+ * - **F**: Long Date/Time ex. `Tuesday, 20 April 2021 16:20`
+ * - **R**: Relative Time ex. `2 months ago`
+ */
+export function timestampAndDelta(date: Date, style: TimestampStyle = 'D'): string {
+ return `${timestamp(date, style)} (${dateDelta(date)} ago)`;
+}
+
+/**
+ * Convert a hex code to an rbg value.
+ * @param hex The hex code to convert.
+ * @returns The rbg value.
+ */
+export function hexToRgb(hex: string): string {
+ const arrBuff = new ArrayBuffer(4);
+ const vw = new DataView(arrBuff);
+ vw.setUint32(0, parseInt(hex, 16), false);
+ const arrByte = new Uint8Array(arrBuff);
+
+ return `${arrByte[1]}, ${arrByte[2]}, ${arrByte[3]}`;
+}
+
+/**
+ * Wait an amount in milliseconds.
+ * @returns A promise that resolves after the specified amount of milliseconds
+ */
+export const sleep = promisify(setTimeout);
+
+/**
+ * Send a message in the error logging channel and console for an error.
+ * @param context
+ * @param error
+ */
+export async function handleError(context: string, error: Error) {
+ await client.console.error(_.camelCase(context), `An error occurred:\n${formatError(error, false)}`, false);
+ await client.console.channelError({
+ embeds: await CommandErrorListener.generateErrorEmbed({ type: 'unhandledRejection', error: error, context })
+ });
+}
+
+/**
+ * Fetches a user from discord.
+ * @param user The user to fetch
+ * @returns Undefined if the user is not found, otherwise the user.
+ */
+export async function resolveNonCachedUser(user: UserResolvable | undefined | null): Promise<User | undefined> {
+ if (user == null) return undefined;
+ const resolvedUser =
+ user instanceof User
+ ? user
+ : user instanceof GuildMember
+ ? user.user
+ : user instanceof ThreadMember
+ ? user.user
+ : user instanceof Message
+ ? user.author
+ : undefined;
+
+ return resolvedUser ?? (await client.users.fetch(user as Snowflake).catch(() => undefined));
+}
+
+/**
+ * Get the pronouns of a discord user from pronoundb.org
+ * @param user The user to retrieve the promises of.
+ * @returns The human readable pronouns of the user, or undefined if they do not have any.
+ */
+export async function getPronounsOf(user: User | Snowflake): Promise<Pronoun | undefined> {
+ const _user = await resolveNonCachedUser(user);
+ if (!_user) throw new Error(`Cannot find user ${user}`);
+ const apiRes = (await got
+ .get(`https://pronoundb.org/api/v1/lookup?platform=discord&id=${_user.id}`)
+ .json()
+ .catch(() => undefined)) as { pronouns: PronounCode } | undefined;
+
+ if (!apiRes) return undefined;
+ assert(apiRes.pronouns);
+
+ return pronounMapping[apiRes.pronouns!]!;
+}
+
+/**
+ * List the methods of an object.
+ * @param obj The object to get the methods of.
+ * @returns A string with each method on a new line.
+ */
+export function getMethods(obj: Record<string, any>): string {
+ // modified from https://stackoverflow.com/questions/31054910/get-functions-methods-of-a-class/31055217#31055217
+ let props: string[] = [];
+ let obj_: Record<string, any> = new Object(obj);
+
+ do {
+ 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
+ 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
+ );
+
+ const reg = /\(([\s\S]*?)\)/;
+ props = props.concat(
+ l.map(
+ (p) =>
+ `${obj_[p] && obj_[p][Symbol.toStringTag] === 'AsyncFunction' ? 'async ' : ''}function ${p}(${
+ reg.exec(obj_[p].toString())?.[1]
+ ? reg
+ .exec(obj_[p].toString())?.[1]
+ .split(', ')
+ .map((arg) => arg.split('=')[0].trim())
+ .join(', ')
+ : ''
+ });`
+ )
+ );
+ } while (
+ (obj_ = Object.getPrototypeOf(obj_)) && // walk-up the prototype chain
+ Object.getPrototypeOf(obj_) // not the the Object prototype methods (hasOwnProperty, etc...)
+ );
+
+ return props.join('\n');
+}
+
+/**
+ * List the symbols of an object.
+ * @param obj The object to get the symbols of.
+ * @returns An array of the symbols of the object.
+ */
+export function getSymbols(obj: Record<string, any>): symbol[] {
+ let symbols: symbol[] = [];
+ let obj_: Record<string, any> = new Object(obj);
+
+ do {
+ const l = Object.getOwnPropertySymbols(obj_).sort();
+
+ symbols = [...symbols, ...l];
+ } while (
+ (obj_ = Object.getPrototypeOf(obj_)) && // walk-up the prototype chain
+ Object.getPrototypeOf(obj_) // not the the Object prototype methods (hasOwnProperty, etc...)
+ );
+
+ return symbols;
+}
+
+/**
+ * Uploads an image to imgur.
+ * @param image The image to upload.
+ * @returns The url of the imgur.
+ */
+export async function uploadImageToImgur(image: string) {
+ const clientId = client.config.credentials.imgurClientId;
+
+ const resp = (await got
+ .post('https://api.imgur.com/3/upload', {
+ headers: {
+ Authorization: `Client-ID ${clientId}`,
+ Accept: 'application/json'
+ },
+ form: {
+ image: image,
+ type: 'base64'
+ },
+ followRedirect: true
+ })
+ .json()) as { data: { link: string } };
+
+ return resp.data.link;
+}
+
+/**
+ * Checks if a user has a certain guild permission (doesn't check channel permissions).
+ * @param message The message to check the user from.
+ * @param permissions The permissions to check for.
+ * @returns The missing permissions or null if none are missing.
+ */
+export function userGuildPermCheck(
+ message: CommandMessage | SlashMessage,
+ permissions: typeof PermissionFlagsBits[keyof typeof PermissionFlagsBits][]
+): PermissionsString[] | null {
+ if (!message.inGuild()) return null;
+ const missing = message.member?.permissions.missing(permissions) ?? [];
+
+ return missing.length ? missing : null;
+}
+
+/**
+ * Check if the client has certain permissions in the guild (doesn't check channel permissions).
+ * @param message The message to check the client user from.
+ * @param permissions The permissions to check for.
+ * @returns The missing permissions or null if none are missing.
+ */
+export function clientGuildPermCheck(message: CommandMessage | SlashMessage, permissions: bigint[]): PermissionsString[] | null {
+ const missing = message.guild?.members.me?.permissions.missing(permissions) ?? [];
+
+ return missing.length ? missing : null;
+}
+
+/**
+ * Check if the client has permission to send messages in the channel as well as check if they have other permissions
+ * in the guild (or the channel if `checkChannel` is `true`).
+ * @param message The message to check the client user from.
+ * @param permissions The permissions to check for.
+ * @param checkChannel Whether to check the channel permissions instead of the guild permissions.
+ * @returns The missing permissions or null if none are missing.
+ */
+export function clientSendAndPermCheck(
+ message: CommandMessage | SlashMessage,
+ permissions: bigint[] = [],
+ checkChannel = false
+): PermissionsString[] | null {
+ const missing: PermissionsString[] = [];
+ const sendPerm = message.channel!.isThread() ? 'SendMessages' : 'SendMessagesInThreads';
+ if (!message.inGuild()) return null;
+
+ if (!message.guild.members.me!.permissionsIn(message.channel!.id).has(sendPerm)) missing.push(sendPerm);
+
+ missing.push(
+ ...(checkChannel
+ ? message.guild!.members.me!.permissionsIn(message.channel!.id!).missing(permissions)
+ : clientGuildPermCheck(message, permissions) ?? [])
+ );
+
+ return missing.length ? missing : null;
+}
+
+/**
+ * Gets the prefix based off of the message.
+ * @param message The message to get the prefix from.
+ * @returns The prefix.
+ */
+export function prefix(message: CommandMessage | SlashMessage): string {
+ return message.util.isSlash ? '/' : client.config.isDevelopment ? 'dev ' : message.util.parsed?.prefix ?? client.config.prefix;
+}
+
+export { deepLock as deepFreeze };
+export { Arg as arg };
+export { Format as format };
+export { DiscordConstants as discordConstants };
+export { AkairoUtil as akairo };
+
+/**
+ * The link to invite the bot with all permissions.
+ */
+export function invite(client: BushClient) {
+ return client.generateInvite({
+ permissions:
+ PermissionsBitField.All -
+ PermissionFlagsBits.UseEmbeddedActivities -
+ PermissionFlagsBits.ViewGuildInsights -
+ PermissionFlagsBits.Stream,
+ scopes: [OAuth2Scopes.Bot, OAuth2Scopes.ApplicationsCommands]
+ });
+}
+
+/**
+ * Asset multiple statements at a time.
+ * @param args
+ */
+export function assertAll(...args: any[]): void {
+ for (let i = 0; i < args.length; i++) {
+ assert(args[i], `assertAll index ${i} failed`);
+ }
+}
+
+/**
+ * Casts a string to a duration and reason for slash commands.
+ * @param arg The argument received.
+ * @param message The message that triggered the command.
+ * @returns The casted argument.
+ */
+export async function castDurationContent(
+ arg: string | ParsedDuration | null,
+ message: CommandMessage | SlashMessage
+): Promise<ParsedDurationRes> {
+ const res = typeof arg === 'string' ? await Arg.cast('contentWithDuration', message, arg) : arg;
+
+ return { duration: res?.duration ?? 0, content: res?.content ?? '' };
+}
+
+/**
+ * Casts a string to a the specified argument type.
+ * @param type The type of the argument to cast to.
+ * @param arg The argument received.
+ * @param message The message that triggered the command.
+ * @returns The casted argument.
+ */
+export async function cast<T extends keyof BaseBushArgumentType>(
+ type: T,
+ arg: BaseBushArgumentType[T] | string,
+ message: CommandMessage | SlashMessage
+) {
+ return typeof arg === 'string' ? await Arg.cast(type, message, arg) : arg;
+}
+
+/**
+ * Overflows the description of an embed into multiple embeds.
+ * @param embed The options to be applied to the (first) embed.
+ * @param lines Each line of the description as an element in an array.
+ */
+export function overflowEmbed(embed: Omit<APIEmbed, 'description'>, lines: string[], maxLength = 4096): EmbedBuilder[] {
+ const embeds: EmbedBuilder[] = [];
+
+ const makeEmbed = () => {
+ embeds.push(new EmbedBuilder().setColor(embed.color ?? null));
+ return embeds.at(-1)!;
+ };
+
+ for (const line of lines) {
+ let current = embeds.length ? embeds.at(-1)! : makeEmbed();
+ let joined = current.data.description ? `${current.data.description}\n${line}` : line;
+ if (joined.length > maxLength) {
+ current = makeEmbed();
+ joined = line;
+ }
+
+ current.setDescription(joined);
+ }
+
+ if (!embeds.length) makeEmbed();
+
+ if (embed.author) embeds.at(0)?.setAuthor(embed.author);
+ if (embed.title) embeds.at(0)?.setTitle(embed.title);
+ if (embed.url) embeds.at(0)?.setURL(embed.url);
+ if (embed.fields) embeds.at(-1)?.setFields(embed.fields);
+ if (embed.thumbnail) embeds.at(-1)?.setThumbnail(embed.thumbnail.url);
+ if (embed.footer) embeds.at(-1)?.setFooter(embed.footer);
+ if (embed.image) embeds.at(-1)?.setImage(embed.image.url);
+ if (embed.timestamp) embeds.at(-1)?.setTimestamp(new Date(embed.timestamp));
+
+ return embeds;
+}
+
+export async function resolveMessageLinks(content: string | null): Promise<MessageLinkParts[]> {
+ const res: MessageLinkParts[] = [];
+
+ if (!content) return res;
+
+ const regex_ = new RegExp(regex.messageLink);
+ let match: RegExpExecArray | null;
+ while (((match = regex_.exec(content)), match !== null)) {
+ const input = match.input;
+ if (!match.groups || !input) continue;
+ if (input.startsWith('<') && input.endsWith('>')) continue;
+
+ const { guild_id, channel_id, message_id } = match.groups;
+ if (!guild_id || !channel_id || !message_id) continue;
+
+ res.push({ guild_id, channel_id, message_id });
+ }
+
+ return res;
+}
+
+export async function resolveMessagesFromLinks(content: string): Promise<APIMessage[]> {
+ const res: APIMessage[] = [];
+
+ const links = await resolveMessageLinks(content);
+ if (!links.length) return [];
+
+ for (const { guild_id, channel_id, message_id } of links) {
+ const guild = client.guilds.cache.get(guild_id);
+ if (!guild) continue;
+ const channel = guild.channels.cache.get(channel_id);
+ if (!channel || (!channel.isTextBased() && !channel.isThread())) continue;
+
+ const message = (await client.rest.get(Routes.channelMessage(channel_id, message_id)).catch(() => null)) as APIMessage | null;
+ if (!message) continue;
+
+ res.push(message);
+ }
+
+ return res;
+}
+
+/**
+ * Formats an error into a string.
+ * @param error The error to format.
+ * @param colors Whether to use colors in the output.
+ * @returns The formatted error.
+ */
+export function formatError(error: Error | any, colors = false): string {
+ if (!error) return error;
+ if (typeof error !== 'object') return String.prototype.toString.call(error);
+ if (
+ getSymbols(error)
+ .map((s) => s.toString())
+ .includes('Symbol(nodejs.util.inspect.custom)')
+ )
+ return inspect(error, { colors });
+
+ return error.stack;
+}
+
+interface HastebinRes {
+ key: string;
+}
+
+export interface UuidRes {
+ uuid: string;
+ username: string;
+ username_history?: { username: string }[] | null;
+ textures: {
+ custom: boolean;
+ slim: boolean;
+ skin: {
+ url: string;
+ data: string;
+ };
+ raw: {
+ value: string;
+ signature: string;
+ };
+ };
+ created_at: string;
+}
+
+export interface HasteResults {
+ url?: string;
+ error?: 'content too long' | 'substr' | 'unable to post';
+}
+
+export interface ParsedDuration {
+ duration: number | null;
+ content: string | null;
+}
+
+export interface ParsedDurationRes {
+ duration: number;
+ content: string;
+}
+
+export type TimestampStyle = 't' | 'T' | 'd' | 'D' | 'f' | 'F' | 'R';
+
+export interface MessageLinkParts {
+ guild_id: Snowflake;
+ channel_id: Snowflake;
+ message_id: Snowflake;
+}
diff --git a/src/listeners/bush/appealListener.ts b/src/listeners/bush/appealListener.ts
index 64979b5..06eb245 100644
--- a/src/listeners/bush/appealListener.ts
+++ b/src/listeners/bush/appealListener.ts
@@ -1,5 +1,5 @@
/* eslint-disable no-control-regex */
-import { BushListener, ModLog, type BushClientEvents } from '#lib';
+import { BushListener, colors, mappings, ModLog, type BushClientEvents } from '#lib';
import assert from 'assert';
import { EmbedBuilder } from 'discord.js';
import UserInfoCommand from '../../commands/info/userInfo.js';
@@ -14,8 +14,8 @@ export default class AppealListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']): Promise<any> {
- if (!client.config.isProduction || !message.inGuild() || message.guildId !== client.consts.mappings.guilds.bush) return;
+ public async exec(...[message]: BushClientEvents['messageCreate']): Promise<any> {
+ if (!client.config.isProduction || !message.inGuild() || message.guildId !== mappings.guilds.bush) return;
if (message.author.id !== '855446927688335370' || message.embeds.length < 1) return;
const userId = message.embeds[0].fields?.find?.((f) => f.name === 'What is your discord ID?')?.value;
@@ -32,7 +32,7 @@ export default class AppealListener extends BushListener {
embeds: [
new EmbedBuilder()
.setTimestamp()
- .setColor(util.colors.error)
+ .setColor(colors.error)
.setTitle(
`${message.embeds[0].fields!.find((f) => f.name === 'What type of punishment are you appealing?')!.value} appeal`
)
@@ -54,7 +54,7 @@ export default class AppealListener extends BushListener {
const embed = new EmbedBuilder()
.setTimestamp()
- .setColor(util.colors.default)
+ .setColor(colors.default)
.setTitle(`${message.embeds[0].fields!.find((f) => f.name === 'What type of punishment are you appealing?')!.value} appeal`)
.setThumbnail(user.displayAvatarURL());
diff --git a/src/listeners/bush/joinAutoBan.ts b/src/listeners/bush/joinAutoBan.ts
index 83efa06..eae18d3 100644
--- a/src/listeners/bush/joinAutoBan.ts
+++ b/src/listeners/bush/joinAutoBan.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushListener, type BushClientEvents } from '#lib';
+import { AllowedMentions, BushListener, colors, emojis, format, getShared, mappings, type BushClientEvents } from '#lib';
import { TextChannel } from 'discord.js';
export default class JoinAutoBanListener extends BushListener {
@@ -10,14 +10,14 @@ export default class JoinAutoBanListener extends BushListener {
});
}
- public override async exec(...[member]: BushClientEvents['guildMemberAdd']): Promise<void> {
+ public async exec(...[member]: BushClientEvents['guildMemberAdd']): Promise<void> {
if (!client.config.isProduction) return;
- if (member.guild.id !== client.consts.mappings.guilds.bush) return;
+ if (member.guild.id !== mappings.guilds.bush) return;
const guild = member.guild;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const user = member.user;
- const code = util.getShared('autoBanCode');
+ const code = getShared('autoBanCode');
if (!code) return;
if (eval(code)) {
const res = await member.bushBan({
@@ -28,7 +28,7 @@ export default class JoinAutoBanListener extends BushListener {
if (!['success', 'failed to dm'].includes(res)) {
return await guild.error(
'nameAutoBan',
- `Failed to auto ban ${util.format.input(member.user.tag)} for blacklisted name, with error: ${util.format.input(res)}.`
+ `Failed to auto ban ${format.input(member.user.tag)} for blacklisted name, with error: ${format.input(res)}.`
);
}
@@ -38,7 +38,7 @@ export default class JoinAutoBanListener extends BushListener {
{
title: 'Name Auto Ban - User Join',
description: `**User:** ${member.user} (${member.user.tag})\n **Action:** Banned for blacklisted name.`,
- color: util.colors.red,
+ color: colors.red,
author: {
name: member.user.tag,
icon_url: member.displayAvatarURL()
@@ -50,8 +50,8 @@ export default class JoinAutoBanListener extends BushListener {
const content =
res === 'failed to dm'
- ? `${util.emojis.warn} Banned ${util.format.input(member.user.tag)} however I could not send them a dm.`
- : `${util.emojis.success} Successfully banned ${util.format.input(member.user.tag)}.`;
+ ? `${emojis.warn} Banned ${format.input(member.user.tag)} however I could not send them a dm.`
+ : `${emojis.success} Successfully banned ${format.input(member.user.tag)}.`;
(<TextChannel>guild.channels.cache.find((c) => c.name === 'general'))
?.send({ content, allowedMentions: AllowedMentions.none() })
diff --git a/src/listeners/bush/supportThread.ts b/src/listeners/bush/supportThread.ts
index 46ac96f..3651409 100644
--- a/src/listeners/bush/supportThread.ts
+++ b/src/listeners/bush/supportThread.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { stripIndent } from '#tags';
import assert from 'assert';
import { EmbedBuilder, MessageType, PermissionFlagsBits, TextChannel } from 'discord.js';
@@ -12,7 +12,7 @@ export default class SupportThreadListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']): Promise<void | undefined> {
+ public async exec(...[message]: BushClientEvents['messageCreate']): Promise<void | undefined> {
if (!client.config.isProduction || !message.inGuild()) return;
if (![MessageType.Default, MessageType.Reply].includes(message.type)) return;
if (message.thread) return;
@@ -50,7 +50,7 @@ export default class SupportThreadListener extends BushListener {
Please make sure you have the latest version found in <#693586404256645231>.
Additionally if you need help installing the mod be sure to read <#737444942724726915> for a guide on how to do so.`
)
- .setColor(util.colors.Blurple);
+ .setColor(colors.Blurple);
void thread
.send({ embeds: [embed] })
.then(() =>
diff --git a/src/listeners/bush/userUpdateAutoBan.ts b/src/listeners/bush/userUpdateAutoBan.ts
index b9485b3..07381e0 100644
--- a/src/listeners/bush/userUpdateAutoBan.ts
+++ b/src/listeners/bush/userUpdateAutoBan.ts
@@ -1,4 +1,4 @@
-import { AllowedMentions, BushListener, type BushClientEvents } from '#lib';
+import { AllowedMentions, BushListener, colors, emojis, format, getShared, mappings, type BushClientEvents } from '#lib';
import { GuildMember, type TextChannel } from 'discord.js';
export default class UserUpdateAutoBanListener extends BushListener {
@@ -10,16 +10,16 @@ export default class UserUpdateAutoBanListener extends BushListener {
});
}
- public override async exec(...[_oldUser, newUser]: BushClientEvents['userUpdate']): Promise<void> {
+ public async exec(...[_oldUser, newUser]: BushClientEvents['userUpdate']): Promise<void> {
if (!client.config.isProduction) return;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const user = newUser;
- const code = util.getShared('autoBanCode');
+ const code = getShared('autoBanCode');
if (!code) return;
if (eval(code)) {
const member = await client.guilds.cache
- .get(client.consts.mappings.guilds.bush)
+ .get(mappings.guilds.bush)
?.members.fetch(newUser.id)
.catch(() => undefined);
if (!member || !(member instanceof GuildMember)) return;
@@ -34,7 +34,7 @@ export default class UserUpdateAutoBanListener extends BushListener {
if (!['success', 'failed to dm'].includes(res)) {
return await guild.error(
'nameAutoBan',
- `Failed to auto ban ${util.format.input(member.user.tag)} for blacklisted name, with error: ${util.format.input(res)}.`
+ `Failed to auto ban ${format.input(member.user.tag)} for blacklisted name, with error: ${format.input(res)}.`
);
}
@@ -44,7 +44,7 @@ export default class UserUpdateAutoBanListener extends BushListener {
{
title: 'Name Auto Ban - User Update',
description: `**User:** ${member.user} (${member.user.tag})\n **Action:** Banned for using blacklisted name.`,
- color: util.colors.red,
+ color: colors.red,
author: {
name: member.user.tag,
icon_url: member.displayAvatarURL()
@@ -56,8 +56,8 @@ export default class UserUpdateAutoBanListener extends BushListener {
const content =
res === 'failed to dm'
- ? `${util.emojis.warn} Banned ${util.format.input(member.user.tag)} however I could not send them a dm.`
- : `${util.emojis.success} Successfully banned ${util.format.input(member.user.tag)}.`;
+ ? `${emojis.warn} Banned ${format.input(member.user.tag)} however I could not send them a dm.`
+ : `${emojis.success} Successfully banned ${format.input(member.user.tag)}.`;
(<TextChannel>guild.channels.cache.find((c) => c.name === 'general'))
?.send({ content, allowedMentions: AllowedMentions.none() })
diff --git a/src/listeners/client/akairoDebug.ts b/src/listeners/client/akairoDebug.ts
index 0cb57a5..208e289 100644
--- a/src/listeners/client/akairoDebug.ts
+++ b/src/listeners/client/akairoDebug.ts
@@ -9,7 +9,7 @@ export default class DiscordJsDebugListener extends BushListener {
});
}
- public override async exec(...[message, ...other]: BushClientEvents['debug']): Promise<void> {
+ public async exec(...[message, ...other]: BushClientEvents['debug']): Promise<void> {
if (other.length && !message.includes('[registerInteractionCommands]'))
void client.console.superVerboseRaw('akairoDebug', message, ...other);
else void client.console.superVerbose('akairoDebug', message);
diff --git a/src/listeners/client/dcjsDebug.ts b/src/listeners/client/dcjsDebug.ts
index 52406c1..56a9eab 100644
--- a/src/listeners/client/dcjsDebug.ts
+++ b/src/listeners/client/dcjsDebug.ts
@@ -9,7 +9,7 @@ export default class DiscordJsDebugListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['debug']): Promise<void> {
+ public async exec(...[message]: BushClientEvents['debug']): Promise<void> {
void client.console.superVerbose('dc.js-debug', message);
}
}
diff --git a/src/listeners/client/dcjsError.ts b/src/listeners/client/dcjsError.ts
index 4908720..c3cf8f0 100644
--- a/src/listeners/client/dcjsError.ts
+++ b/src/listeners/client/dcjsError.ts
@@ -9,7 +9,7 @@ export default class DiscordJsErrorListener extends BushListener {
});
}
- public override async exec(...[error]: BushClientEvents['error']): Promise<void> {
+ public async exec(...[error]: BushClientEvents['error']): Promise<void> {
void client.console.superVerbose('dc.js-error', error);
}
}
diff --git a/src/listeners/client/dcjsWarn.ts b/src/listeners/client/dcjsWarn.ts
index cc2b30f..6c13630 100644
--- a/src/listeners/client/dcjsWarn.ts
+++ b/src/listeners/client/dcjsWarn.ts
@@ -9,7 +9,7 @@ export default class DiscordJsWarnListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['warn']): Promise<void> {
+ public async exec(...[message]: BushClientEvents['warn']): Promise<void> {
void client.console.superVerbose('dc.js-warn', message);
}
}
diff --git a/src/listeners/client/ready.ts b/src/listeners/client/ready.ts
index c550c6b..ae9919c 100644
--- a/src/listeners/client/ready.ts
+++ b/src/listeners/client/ready.ts
@@ -11,7 +11,7 @@ export default class ReadyListener extends BushListener {
}
// eslint-disable-next-line no-empty-pattern
- public override async exec(...[]: BushClientEvents['ready']) {
+ public async exec(...[]: BushClientEvents['ready']) {
process.emit('ready' as any);
const tag = `<<${client.user?.tag}>>`,
diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts
index feb85d1..8a05d39 100644
--- a/src/listeners/commands/commandBlocked.ts
+++ b/src/listeners/commands/commandBlocked.ts
@@ -1,4 +1,14 @@
-import { BushListener, type BushCommand, type BushCommandHandlerEvents, type CommandMessage, type SlashMessage } from '#lib';
+import {
+ BlockedReasons,
+ BushListener,
+ emojis,
+ format,
+ oxford,
+ type BushCommand,
+ type BushCommandHandlerEvents,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
import { type InteractionReplyOptions, type MessagePayload, type ReplyMessageOptions } from 'discord.js';
export default class CommandBlockedListener extends BushListener {
@@ -10,7 +20,7 @@ export default class CommandBlockedListener extends BushListener {
});
}
- public override async exec(...[message, command, reason]: BushCommandHandlerEvents['commandBlocked']) {
+ public async exec(...[message, command, reason]: BushCommandHandlerEvents['commandBlocked']) {
return await CommandBlockedListener.handleBlocked(message, command, reason);
}
@@ -24,85 +34,84 @@ export default class CommandBlockedListener extends BushListener {
} was blocked because <<${reason}>>.`,
true
);
- const reasons = client.consts.BlockedReasons;
switch (reason) {
- case reasons.OWNER: {
+ case BlockedReasons.OWNER: {
return await respond({
- content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.id)} command.`,
+ content: `${emojis.error} Only my developers can run the ${format.input(command!.id)} command.`,
ephemeral: true
});
}
- case reasons.SUPER_USER: {
+ case BlockedReasons.SUPER_USER: {
return await respond({
- content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.id)} command.`,
+ content: `${emojis.error} You must be a superuser to run the ${format.input(command!.id)} command.`,
ephemeral: true
});
}
- case reasons.DISABLED_GLOBAL: {
+ case BlockedReasons.DISABLED_GLOBAL: {
return await respond({
- content: `${util.emojis.error} My developers disabled the ${util.format.input(command!.id)} command.`,
+ content: `${emojis.error} My developers disabled the ${format.input(command!.id)} command.`,
ephemeral: true
});
}
- case reasons.DISABLED_GUILD: {
+ case BlockedReasons.DISABLED_GUILD: {
return await respond({
- content: `${util.emojis.error} The ${util.format.input(
- command!.id
- )} command is currently disabled in ${util.format.input(message.guild!.name)}.`,
+ content: `${emojis.error} The ${format.input(command!.id)} command is currently disabled in ${format.input(
+ message.guild!.name
+ )}.`,
ephemeral: true
});
}
- case reasons.CHANNEL_GLOBAL_BLACKLIST:
- case reasons.CHANNEL_GUILD_BLACKLIST:
+ case BlockedReasons.CHANNEL_GLOBAL_BLACKLIST:
+ case BlockedReasons.CHANNEL_GUILD_BLACKLIST:
return isSlash
? await respond({
- content: `${util.emojis.error} You cannot use this bot in this channel.`,
+ content: `${emojis.error} You cannot use this bot in this channel.`,
ephemeral: true
})
- : await (message as CommandMessage).react(util.emojis.cross);
- case reasons.USER_GLOBAL_BLACKLIST:
- case reasons.USER_GUILD_BLACKLIST:
+ : await (message as CommandMessage).react(emojis.cross);
+ case BlockedReasons.USER_GLOBAL_BLACKLIST:
+ case BlockedReasons.USER_GUILD_BLACKLIST:
return isSlash
? await respond({
- content: `${util.emojis.error} You are blacklisted from using this bot.`,
+ content: `${emojis.error} You are blacklisted from using this bot.`,
ephemeral: true
})
- : await (message as CommandMessage).react(util.emojis.cross);
- case reasons.ROLE_BLACKLIST: {
+ : await (message as CommandMessage).react(emojis.cross);
+ case BlockedReasons.ROLE_BLACKLIST: {
return isSlash
? await respond({
- content: `${util.emojis.error} One of your roles blacklists you from using this bot.`,
+ content: `${emojis.error} One of your roles blacklists you from using this bot.`,
ephemeral: true
})
- : await (message as CommandMessage).react(util.emojis.cross);
+ : await (message as CommandMessage).react(emojis.cross);
}
- case reasons.RESTRICTED_CHANNEL: {
+ case BlockedReasons.RESTRICTED_CHANNEL: {
if (!command) break;
const channels = command.restrictedChannels;
const names: string[] = [];
channels!.forEach((c) => {
names.push(`<#${c}>`);
});
- const pretty = util.oxford(names, 'and');
+ const pretty = oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.input(command!.id)} can only be run in ${pretty}.`,
+ content: `${emojis.error} ${format.input(command!.id)} can only be run in ${pretty}.`,
ephemeral: true
});
}
- case reasons.RESTRICTED_GUILD: {
+ case BlockedReasons.RESTRICTED_GUILD: {
if (!command) break;
const guilds = command.restrictedGuilds;
- const names = guilds!.map((g) => util.format.input(client.guilds.cache.get(g)?.name ?? g));
- const pretty = util.oxford(names, 'and');
+ const names = guilds!.map((g) => format.input(client.guilds.cache.get(g)?.name ?? g));
+ const pretty = oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.input(command!.id)} can only be run in ${pretty}.`,
+ content: `${emojis.error} ${format.input(command!.id)} can only be run in ${pretty}.`,
ephemeral: true
});
}
default: {
return await respond({
- content: `${util.emojis.error} Command blocked with reason ${util.format.input(reason ?? 'unknown')}.`,
+ content: `${emojis.error} Command blocked with reason ${format.input(reason ?? 'unknown')}.`,
ephemeral: true
});
}
diff --git a/src/listeners/commands/commandCooldown.ts b/src/listeners/commands/commandCooldown.ts
index 92b0abe..74dd4eb 100644
--- a/src/listeners/commands/commandCooldown.ts
+++ b/src/listeners/commands/commandCooldown.ts
@@ -9,7 +9,7 @@ export default class CommandCooldownListener extends BushListener {
});
}
- public override async exec(...[message, command, remaining]: BushCommandHandlerEvents['cooldown']) {
+ public async exec(...[message, command, remaining]: BushCommandHandlerEvents['cooldown']) {
void client.console.info(
'commandCooldown',
`<<${message.author.tag}>> tried to run <<${
diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts
index 878e459..ca6565e 100644
--- a/src/listeners/commands/commandError.ts
+++ b/src/listeners/commands/commandError.ts
@@ -1,6 +1,16 @@
-import { SlashMessage, type BushCommandHandlerEvents } from '#lib';
+import {
+ capitalize,
+ colors,
+ format,
+ formatError,
+ inspectAndRedact,
+ inspectCleanRedactCodeblock,
+ inspectCleanRedactHaste,
+ SlashMessage,
+ type BushCommandHandlerEvents
+} from '#lib';
import { type AkairoMessage, type Command } from 'discord-akairo';
-import { ChannelType, EmbedBuilder, Formatters, GuildTextBasedChannel, type Message } from 'discord.js';
+import { ChannelType, EmbedBuilder, escapeInlineCode, Formatters, GuildTextBasedChannel, type Message } from 'discord.js';
import { BushListener } from '../../lib/extensions/discord-akairo/BushListener.js';
export default class CommandErrorListener extends BushListener {
@@ -12,7 +22,7 @@ export default class CommandErrorListener extends BushListener {
});
}
- public override exec(...[error, message, command]: BushCommandHandlerEvents['error']) {
+ public exec(...[error, message, command]: BushCommandHandlerEvents['error']) {
return CommandErrorListener.handleError(error, message, command);
}
@@ -49,7 +59,7 @@ export default class CommandErrorListener extends BushListener {
`${isSlash ? 'slashC' : 'c'}ommandError`,
`an error occurred with the <<${command}>> ${isSlash ? 'slash ' : ''}command in <<${channel}>> triggered by <<${
message?.author?.tag
- }>>:\n${util.formatError(error, true)})}`,
+ }>>:\n${formatError(error, true)})}`,
false
);
@@ -127,16 +137,16 @@ export default class CommandErrorListener extends BushListener {
stack: string;
}
): EmbedBuilder[] {
- const embeds = [new EmbedBuilder().setColor(util.colors.error)];
+ const embeds = [new EmbedBuilder().setColor(colors.error)];
if (options.type === 'command-user') {
embeds[0]
.setTitle('An Error Occurred')
.setDescription(
`Oh no! ${
options.command
- ? `While running the ${options.isSlash ? 'slash ' : ''}command ${util.format.input(options.command.id)}, a`
+ ? `While running the ${options.isSlash ? 'slash ' : ''}command ${format.input(options.command.id)}, a`
: 'A'
- }n error occurred. Please give the developers code ${util.format.input(`${options.errorNum}`)}.`
+ }n error occurred. Please give the developers code ${format.input(`${options.errorNum}`)}.`
)
.setTimestamp();
return embeds;
@@ -155,11 +165,11 @@ export default class CommandErrorListener extends BushListener {
description.push(...options.haste);
- embeds.push(new EmbedBuilder().setColor(util.colors.error).setTimestamp().setDescription(options.stack.substring(0, 4000)));
+ embeds.push(new EmbedBuilder().setColor(colors.error).setTimestamp().setDescription(options.stack.substring(0, 4000)));
if (description.length) embeds[0].setDescription(description.join('\n').substring(0, 4000));
if (options.type === 'command-dev' || options.type === 'command-log')
- embeds[0].setTitle(`${options.isSlash ? 'Slash ' : ''}CommandError #${util.format.input(`${options.errorNum}`)}`);
+ embeds[0].setTitle(`${options.isSlash ? 'Slash ' : ''}CommandError #${format.input(`${options.errorNum}`)}`);
else if (options.type === 'uncaughtException')
embeds[0].setTitle(`${options.context ? `[${Formatters.bold(options.context)}] An Error Occurred` : 'Uncaught Exception'}`);
else if (options.type === 'unhandledRejection')
@@ -199,7 +209,7 @@ export default class CommandErrorListener extends BushListener {
for (const element in error) {
if (['stack', 'name', 'message'].includes(element)) continue;
else if (typeof (error as any)[element] === 'object') {
- promises.push(util.inspectCleanRedactHaste((error as any)[element], inspectOptions));
+ promises.push(inspectCleanRedactHaste((error as any)[element], inspectOptions));
}
}
@@ -218,14 +228,14 @@ export default class CommandErrorListener extends BushListener {
if (['stack', 'name', 'message'].includes(element)) continue;
else {
ret.push(
- `**Error ${util.capitalizeFirstLetter(element)}:** ${
- typeof (error as any)[element] === 'object'
+ `**Error ${capitalize(element)}:** ${
+ typeof error[element] === 'object'
? `${
pair[element].url
? `[haste](${pair[element].url})${pair[element].error ? ` - ${pair[element].error}` : ''}`
: pair[element].error
}`
- : `\`${util.discord.escapeInlineCode(util.inspectAndRedact((error as any)[element], inspectOptions))}\``
+ : `\`${escapeInlineCode(inspectAndRedact((error as any)[element], inspectOptions))}\``
}`
);
}
@@ -234,7 +244,7 @@ export default class CommandErrorListener extends BushListener {
}
public static async getErrorStack(error: Error | any): Promise<string> {
- return await util.inspectCleanRedactCodeblock(error, 'js', { colors: false }, 4000);
+ return await inspectCleanRedactCodeblock(error, 'js', { colors: false }, 4000);
}
}
diff --git a/src/listeners/commands/commandLocked.ts b/src/listeners/commands/commandLocked.ts
index 285eb50..22ed8e1 100644
--- a/src/listeners/commands/commandLocked.ts
+++ b/src/listeners/commands/commandLocked.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushCommandHandlerEvents } from '#lib';
+import { BushListener, emojis, format, type BushCommandHandlerEvents } from '#lib';
export default class CommandLockedListener extends BushListener {
public constructor() {
@@ -9,9 +9,9 @@ export default class CommandLockedListener extends BushListener {
});
}
- public override async exec(...[message, command]: BushCommandHandlerEvents['commandLocked']) {
+ public async exec(...[message, command]: BushCommandHandlerEvents['commandLocked']) {
return message.util.reply(
- `${util.emojis.error} You cannot use the ${util.format.input(command.id)} command because it is already in use.`
+ `${emojis.error} You cannot use the ${format.input(command.id)} command because it is already in use.`
);
}
}
diff --git a/src/listeners/commands/commandMissingPermissions.ts b/src/listeners/commands/commandMissingPermissions.ts
index 2cbf17c..352899d 100644
--- a/src/listeners/commands/commandMissingPermissions.ts
+++ b/src/listeners/commands/commandMissingPermissions.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushCommandHandlerEvents } from '#lib';
+import { BushListener, emojis, format, mappings, oxford, surroundArray, type BushCommandHandlerEvents } from '#lib';
import { type PermissionsString } from 'discord.js';
export default class CommandMissingPermissionsListener extends BushListener {
@@ -10,7 +10,7 @@ export default class CommandMissingPermissionsListener extends BushListener {
});
}
- public override async exec(...[message, command, type, missing]: BushCommandHandlerEvents['missingPermissions']) {
+ public async exec(...[message, command, type, missing]: BushCommandHandlerEvents['missingPermissions']) {
return await CommandMissingPermissionsListener.handleMissing(message, command, type, missing);
}
@@ -20,11 +20,11 @@ export default class CommandMissingPermissionsListener extends BushListener {
| BushCommandHandlerEvents['slashMissingPermissions']
) {
const niceMissing = (missing.includes('Administrator') ? (['Administrator'] as PermissionsString[]) : missing).map(
- (perm) => client.consts.mappings.permissions[perm]?.name ?? missing
+ (perm) => mappings.permissions[perm]?.name ?? missing
);
- const discordFormat = util.oxford(util.surroundArray(niceMissing, '**'), 'and', '');
- const consoleFormat = util.oxford(util.surroundArray(niceMissing, '<<', '>>'), 'and', '');
+ const discordFormat = oxford(surroundArray(niceMissing, '**'), 'and', '');
+ const consoleFormat = oxford(surroundArray(niceMissing, '<<', '>>'), 'and', '');
void client.console.info(
'commandMissingPermissions',
`<<${message.author.tag}>> tried to run <<${
@@ -34,15 +34,15 @@ export default class CommandMissingPermissionsListener extends BushListener {
if (type == 'client') {
return await message.util
.reply(
- `${util.emojis.error} I am missing the ${discordFormat} permission${
+ `${emojis.error} I am missing the ${discordFormat} permission${
missing.length ? 's' : ''
- } required for the ${util.format.input(command?.id)} command.`
+ } required for the ${format.input(command?.id)} command.`
)
.catch(() => {});
} else if (type == 'user') {
return await message.util
.reply(
- `${util.emojis.error} You are missing the ${discordFormat} permission${missing.length ? 's' : ''} required for the **${
+ `${emojis.error} You are missing the ${discordFormat} permission${missing.length ? 's' : ''} required for the **${
command?.id
}** command.`
)
diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts
index 02a0b75..89fea28 100644
--- a/src/listeners/commands/commandStarted.ts
+++ b/src/listeners/commands/commandStarted.ts
@@ -10,7 +10,7 @@ export default class CommandStartedListener extends BushListener {
});
}
- public override exec(...[message, command]: BushCommandHandlerEvents['commandStarted']): void {
+ public exec(...[message, command]: BushCommandHandlerEvents['commandStarted']): void {
client.sentry.addBreadcrumb({
message: `[commandStarted] The ${command.id} was started by ${message.author.tag}.`,
level: 'info',
diff --git a/src/listeners/commands/messageBlocked.ts b/src/listeners/commands/messageBlocked.ts
index 5a2b10d..997579c 100644
--- a/src/listeners/commands/messageBlocked.ts
+++ b/src/listeners/commands/messageBlocked.ts
@@ -9,7 +9,7 @@ export default class MessageBlockedListener extends BushListener {
});
}
- public override async exec(...[message, reason]: BushCommandHandlerEvents['messageBlocked']) {
+ public async exec(...[message, reason]: BushCommandHandlerEvents['messageBlocked']) {
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/commands/slashBlocked.ts b/src/listeners/commands/slashBlocked.ts
index 6c0ed14..915b953 100644
--- a/src/listeners/commands/slashBlocked.ts
+++ b/src/listeners/commands/slashBlocked.ts
@@ -10,7 +10,7 @@ export default class SlashBlockedListener extends BushListener {
});
}
- public override async exec(...[message, command, reason]: BushCommandHandlerEvents['slashBlocked']) {
+ public async exec(...[message, command, reason]: BushCommandHandlerEvents['slashBlocked']) {
return await CommandBlockedListener.handleBlocked(message, command, reason);
}
}
diff --git a/src/listeners/commands/slashCommandError.ts b/src/listeners/commands/slashCommandError.ts
index 25c0f3e..f851f4f 100644
--- a/src/listeners/commands/slashCommandError.ts
+++ b/src/listeners/commands/slashCommandError.ts
@@ -10,7 +10,7 @@ export default class SlashCommandErrorListener extends BushListener {
});
}
- public override async exec(...[error, message, command]: BushCommandHandlerEvents['slashError']) {
+ public async exec(...[error, message, command]: BushCommandHandlerEvents['slashError']) {
return await CommandErrorListener.handleError(error, message, command);
}
}
diff --git a/src/listeners/commands/slashMissingPermissions.ts b/src/listeners/commands/slashMissingPermissions.ts
index 296f44b..3ae03e3 100644
--- a/src/listeners/commands/slashMissingPermissions.ts
+++ b/src/listeners/commands/slashMissingPermissions.ts
@@ -10,7 +10,7 @@ export default class SlashMissingPermissionsListener extends BushListener {
});
}
- public override async exec(...[message, command, type, missing]: BushCommandHandlerEvents['slashMissingPermissions']) {
+ public async exec(...[message, command, type, missing]: BushCommandHandlerEvents['slashMissingPermissions']) {
return await CommandMissingPermissionsListener.handleMissing(message, command, type, missing);
}
}
diff --git a/src/listeners/commands/slashNotFound.ts b/src/listeners/commands/slashNotFound.ts
index a8e4267..8c6d2d4 100644
--- a/src/listeners/commands/slashNotFound.ts
+++ b/src/listeners/commands/slashNotFound.ts
@@ -9,7 +9,7 @@ export default class SlashNotFoundListener extends BushListener {
});
}
- public override async exec(...[interaction]: BushCommandHandlerEvents['slashNotFound']) {
+ public async exec(...[interaction]: BushCommandHandlerEvents['slashNotFound']) {
void client.console.info('slashNotFound', `<<${interaction?.commandName}>> could not be found.`);
}
}
diff --git a/src/listeners/commands/slashStarted.ts b/src/listeners/commands/slashStarted.ts
index 3d8334d..e2c8a47 100644
--- a/src/listeners/commands/slashStarted.ts
+++ b/src/listeners/commands/slashStarted.ts
@@ -10,7 +10,7 @@ export default class SlashStartedListener extends BushListener {
});
}
- public override async exec(...[message, command]: BushCommandHandlerEvents['slashStarted']) {
+ public async exec(...[message, command]: BushCommandHandlerEvents['slashStarted']) {
client.sentry.addBreadcrumb({
message: `[slashStarted] The ${command.id} was started by ${message.author.tag}.`,
level: 'info',
diff --git a/src/listeners/contextCommands/contextCommandBlocked.ts b/src/listeners/contextCommands/contextCommandBlocked.ts
index ba4af8c..a9397b6 100644
--- a/src/listeners/contextCommands/contextCommandBlocked.ts
+++ b/src/listeners/contextCommands/contextCommandBlocked.ts
@@ -1,4 +1,4 @@
-import { BushListener } from '#lib';
+import { BlockedReasons, BushListener, emojis, format } from '#lib';
import { type ContextMenuCommandHandlerEvents } from 'discord-akairo';
export default class ContextCommandBlockedListener extends BushListener {
@@ -10,7 +10,7 @@ export default class ContextCommandBlockedListener extends BushListener {
});
}
- public override async exec(...[interaction, command, reason]: ContextMenuCommandHandlerEvents['blocked']) {
+ public async exec(...[interaction, command, reason]: ContextMenuCommandHandlerEvents['blocked']) {
void client.console.info(
`ContextCommandBlocked`,
`<<${interaction.user.tag}>> tried to run <<${command}>> but was blocked because <<${reason}>>.`,
@@ -18,21 +18,21 @@ export default class ContextCommandBlockedListener extends BushListener {
);
switch (reason) {
- case client.consts.BlockedReasons.OWNER: {
+ case BlockedReasons.OWNER: {
return await interaction.reply({
- content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.id)} command.`,
+ content: `${emojis.error} Only my developers can run the ${format.input(command!.id)} command.`,
ephemeral: true
});
}
- case client.consts.BlockedReasons.SUPER_USER: {
+ case BlockedReasons.SUPER_USER: {
return await interaction.reply({
- content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.id)} command.`,
+ content: `${emojis.error} You must be a superuser to run the ${format.input(command!.id)} command.`,
ephemeral: true
});
}
default: {
return await interaction.reply({
- content: `${util.emojis.error} Command blocked with reason ${util.format.input(reason ?? 'unknown')}.`,
+ content: `${emojis.error} Command blocked with reason ${format.input(reason ?? 'unknown')}.`,
ephemeral: true
});
}
diff --git a/src/listeners/contextCommands/contextCommandError.ts b/src/listeners/contextCommands/contextCommandError.ts
index 19b5708..e69ed4e 100644
--- a/src/listeners/contextCommands/contextCommandError.ts
+++ b/src/listeners/contextCommands/contextCommandError.ts
@@ -1,4 +1,4 @@
-import { BushListener } from '#lib';
+import { BushListener, colors, format, formatError } from '#lib';
import { type ContextMenuCommand, type ContextMenuCommandHandlerEvents } from 'discord-akairo';
import { ChannelType, ContextMenuCommandInteraction, EmbedBuilder, GuildTextBasedChannel } from 'discord.js';
import CommandErrorListener, { IFuckedUpError } from '../commands/commandError.js';
@@ -12,7 +12,7 @@ export default class ContextCommandErrorListener extends BushListener {
});
}
- public override exec(...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) {
+ public exec(...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) {
return ContextCommandErrorListener.handleError(error, interaction, command);
}
@@ -45,7 +45,7 @@ export default class ContextCommandErrorListener extends BushListener {
`contextCommandError`,
`an error occurred with the <<${command}>> context command in <<${channel}>> triggered by <<${
interaction?.user?.tag
- }>>:\n${util.formatError(error, true)}`,
+ }>>:\n${formatError(error, true)}`,
false
);
@@ -92,14 +92,14 @@ export default class ContextCommandErrorListener extends BushListener {
haste: string[];
stack: string;
}): EmbedBuilder[] {
- const embeds = [new EmbedBuilder().setColor(util.colors.error)];
+ const embeds = [new EmbedBuilder().setColor(colors.error)];
if (options.type === 'command-user') {
embeds[0]
.setTitle('An Error Occurred')
.setDescription(
`Oh no! ${
- options.command ? `While running the command ${util.format.input(options.command.id)}, a` : 'A'
- }n error occurred. Please give the developers code ${util.format.input(`${options.errorNum}`)}.`
+ options.command ? `While running the command ${format.input(options.command.id)}, a` : 'A'
+ }n error occurred. Please give the developers code ${format.input(`${options.errorNum}`)}.`
)
.setTimestamp();
return embeds;
@@ -116,11 +116,11 @@ export default class ContextCommandErrorListener extends BushListener {
description.push(...options.haste);
- embeds.push(new EmbedBuilder().setColor(util.colors.error).setTimestamp().setDescription(options.stack.substring(0, 4000)));
+ embeds.push(new EmbedBuilder().setColor(colors.error).setTimestamp().setDescription(options.stack.substring(0, 4000)));
if (description.length) embeds[0].setDescription(description.join('\n').substring(0, 4000));
if (options.type === 'command-dev' || options.type === 'command-log')
- embeds[0].setTitle(`ContextCommandError #${util.format.input(`${options.errorNum}`)}`);
+ embeds[0].setTitle(`ContextCommandError #${format.input(`${options.errorNum}`)}`);
return embeds;
}
}
diff --git a/src/listeners/contextCommands/contextCommandNotFound.ts b/src/listeners/contextCommands/contextCommandNotFound.ts
index ca97ad1..65954a2 100644
--- a/src/listeners/contextCommands/contextCommandNotFound.ts
+++ b/src/listeners/contextCommands/contextCommandNotFound.ts
@@ -10,7 +10,7 @@ export default class ContextCommandNotFoundListener extends BushListener {
});
}
- public override async exec(...[interaction]: ContextMenuCommandHandlerEvents['notFound']) {
+ public async exec(...[interaction]: ContextMenuCommandHandlerEvents['notFound']) {
void client.console.info('contextCommandNotFound', `<<${interaction?.commandName}>> could not be found.`);
}
}
diff --git a/src/listeners/contextCommands/contextCommandStarted.ts b/src/listeners/contextCommands/contextCommandStarted.ts
index 965b8b9..3aab07a 100644
--- a/src/listeners/contextCommands/contextCommandStarted.ts
+++ b/src/listeners/contextCommands/contextCommandStarted.ts
@@ -11,7 +11,7 @@ export default class ContextCommandStartedListener extends BushListener {
});
}
- public override async exec(...[interaction, command]: ContextMenuCommandHandlerEvents['started']) {
+ public async exec(...[interaction, command]: ContextMenuCommandHandlerEvents['started']) {
client.sentry.addBreadcrumb({
message: `[contextCommandStarted] The ${command.id} was started by ${interaction.user.tag}.`,
level: 'info',
diff --git a/src/listeners/guild-custom/bushLockdown.ts b/src/listeners/guild-custom/bushLockdown.ts
index 85890cf..930a8d2 100644
--- a/src/listeners/guild-custom/bushLockdown.ts
+++ b/src/listeners/guild-custom/bushLockdown.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, type BushClientEvents } from '#lib';
import { EmbedBuilder } from 'discord.js';
export default class BushLockdownListener extends BushListener {
@@ -10,12 +10,12 @@ export default class BushLockdownListener extends BushListener {
});
}
- public override async exec(...[moderator, reason, channelsSuccessMap, _all]: BushClientEvents['bushLockdown']) {
+ public async exec(...[moderator, reason, channelsSuccessMap, _all]: BushClientEvents['bushLockdown']) {
const logChannel = await moderator.guild.getLogChannel('moderation');
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Blurple)
+ .setColor(colors.Blurple)
.setTimestamp()
.addFields([
{ name: '**Action**', value: `${'Lockdown'}` },
@@ -24,7 +24,7 @@ export default class BushLockdownListener extends BushListener {
{
name: `**Channel${channelsSuccessMap.size > 1 ? 's' : ''}**`,
value: channelsSuccessMap
- .map((success, channel) => `<#${channel}> ${success ? util.emojis.success : util.emojis.error}`)
+ .map((success, channel) => `<#${channel}> ${success ? emojis.success : emojis.error}`)
.join('\n')
}
]);
diff --git a/src/listeners/guild-custom/bushUnlockdown.ts b/src/listeners/guild-custom/bushUnlockdown.ts
index 26217d8..b5a4482 100644
--- a/src/listeners/guild-custom/bushUnlockdown.ts
+++ b/src/listeners/guild-custom/bushUnlockdown.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, type BushClientEvents } from '#lib';
import { EmbedBuilder } from 'discord.js';
export default class BushUnlockdownListener extends BushListener {
@@ -10,12 +10,12 @@ export default class BushUnlockdownListener extends BushListener {
});
}
- public override async exec(...[moderator, reason, channelsSuccessMap, _all]: BushClientEvents['bushUnlockdown']) {
+ public async exec(...[moderator, reason, channelsSuccessMap, _all]: BushClientEvents['bushUnlockdown']) {
const logChannel = await moderator.guild.getLogChannel('moderation');
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Blurple)
+ .setColor(colors.Blurple)
.setTimestamp()
.addFields([
{ name: '**Action**', value: `${'Unlockdown'}` },
@@ -24,7 +24,7 @@ export default class BushUnlockdownListener extends BushListener {
{
name: `**Channel${channelsSuccessMap.size > 1 ? 's' : ''}**`,
value: channelsSuccessMap
- .map((success, channel) => `<#${channel}> ${success ? util.emojis.success : util.emojis.error}`)
+ .map((success, channel) => `<#${channel}> ${success ? emojis.success : emojis.error}`)
.join('\n')
}
]);
diff --git a/src/listeners/guild/guildCreate.ts b/src/listeners/guild/guildCreate.ts
index 56cd5df..fe23979 100644
--- a/src/listeners/guild/guildCreate.ts
+++ b/src/listeners/guild/guildCreate.ts
@@ -1,4 +1,4 @@
-import { BushListener, Guild, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, format, getConfigChannel, Guild, type BushClientEvents } from '#lib';
export default class GuildCreateListener extends BushListener {
public constructor() {
@@ -9,18 +9,18 @@ export default class GuildCreateListener extends BushListener {
});
}
- public override async exec(...[guild]: BushClientEvents['guildCreate']) {
+ public async exec(...[guild]: BushClientEvents['guildCreate']) {
void client.console.info('guildCreate', `Joined <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.`);
const g = await Guild.findByPk(guild.id);
if (!g) void Guild.create({ id: guild.id });
- const channel = await util.getConfigChannel('servers');
+ const channel = await getConfigChannel('servers');
if (!channel) return;
return await channel.send({
embeds: [
{
- color: util.colors.Green,
- description: `${util.emojis.join} Joined ${util.format.input(
+ color: colors.Green,
+ description: `${emojis.join} Joined ${format.input(
guild.name
)} with **${guild.memberCount?.toLocaleString()}** members. I am now in **${client.guilds.cache.size}** guilds.`,
timestamp: new Date().toISOString(),
diff --git a/src/listeners/guild/guildDelete.ts b/src/listeners/guild/guildDelete.ts
index 054c5e0..5efbe9b 100644
--- a/src/listeners/guild/guildDelete.ts
+++ b/src/listeners/guild/guildDelete.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, format, getConfigChannel, type BushClientEvents } from '#lib';
export default class GuildDeleteListener extends BushListener {
public constructor() {
@@ -9,16 +9,16 @@ export default class GuildDeleteListener extends BushListener {
});
}
- public override async exec(...[guild]: BushClientEvents['guildDelete']) {
+ public async exec(...[guild]: BushClientEvents['guildDelete']) {
void client.console.info('guildDelete', `Left <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.`);
- const channel = await util.getConfigChannel('servers');
+ const channel = await getConfigChannel('servers');
if (!channel) return;
return await channel.send({
embeds: [
{
- color: util.colors.Red,
- description: `${util.emojis.leave} Left ${util.format.input(
+ color: colors.Red,
+ description: `${emojis.leave} Left ${format.input(
guild.name
)} with **${guild.memberCount?.toLocaleString()}** members. I am now in **${client.guilds.cache.size}** guilds.`,
timestamp: new Date().toISOString(),
diff --git a/src/listeners/guild/guildMemberAdd.ts b/src/listeners/guild/guildMemberAdd.ts
index de1f859..004a2c2 100644
--- a/src/listeners/guild/guildMemberAdd.ts
+++ b/src/listeners/guild/guildMemberAdd.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, format, type BushClientEvents } from '#lib';
import { EmbedBuilder, type GuildMember, type TextChannel } from 'discord.js';
export default class GuildMemberAddListener extends BushListener {
@@ -10,7 +10,7 @@ export default class GuildMemberAddListener extends BushListener {
});
}
- public override async exec(...[member]: BushClientEvents['guildMemberAdd']) {
+ public async exec(...[member]: BushClientEvents['guildMemberAdd']) {
void this.sendWelcomeMessage(member);
}
@@ -30,24 +30,24 @@ export default class GuildMemberAddListener extends BushListener {
const embed = new EmbedBuilder()
.setDescription(
- `${util.emojis.join} ${util.format.input(
+ `${emojis.join} ${format.input(
member.user.tag
)} joined the server. There are now ${member.guild.memberCount.toLocaleString()} members.`
)
- .setColor(util.colors.green);
+ .setColor(colors.green);
await welcome
.send({ embeds: [embed] })
.then(() =>
client.console.info(
'guildMemberAdd',
- `Sent a message for ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
+ `Sent a message for ${format.inputLog(member.user.tag)} in ${format.inputLog(member.guild.name)}.`
)
)
.catch(() =>
welcome.guild.error(
'Welcome Message',
- `Failed to send message for ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
+ `Failed to send message for ${format.inputLog(member.user.tag)} in ${format.inputLog(member.guild.name)}.`
)
);
}
diff --git a/src/listeners/guild/guildMemberRemove.ts b/src/listeners/guild/guildMemberRemove.ts
index 59f8800..80e9ee8 100644
--- a/src/listeners/guild/guildMemberRemove.ts
+++ b/src/listeners/guild/guildMemberRemove.ts
@@ -1,4 +1,4 @@
-import { BushListener, StickyRole, Time, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, format, sleep, StickyRole, Time, type BushClientEvents } from '#lib';
import { EmbedBuilder, type GuildMember, type PartialGuildMember, type TextChannel } from 'discord.js';
export default class GuildMemberRemoveListener extends BushListener {
@@ -10,7 +10,7 @@ export default class GuildMemberRemoveListener extends BushListener {
});
}
- public override async exec(...[member]: BushClientEvents['guildMemberRemove']) {
+ public async exec(...[member]: BushClientEvents['guildMemberRemove']) {
void this.sendWelcomeMessage(member);
void this.stickyRoles(member);
}
@@ -18,7 +18,7 @@ export default class GuildMemberRemoveListener extends BushListener {
private async sendWelcomeMessage(member: GuildMember | PartialGuildMember) {
if (client.config.isDevelopment) return;
const user = member.partial ? await client.users.fetch(member.id) : member.user;
- await util.sleep(50 * Time.Millisecond); // ban usually triggers after member leave
+ await sleep(50 * Time.Millisecond); // ban usually triggers after member leave
const isBan = member.guild.bans.cache.has(member.id);
const welcomeChannel = await member.guild.getSetting('welcomeChannel');
if (!welcomeChannel) return;
@@ -26,23 +26,23 @@ 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: EmbedBuilder = new EmbedBuilder()
.setDescription(
- `${util.emojis.leave} ${util.format.input(user.tag)} ${
+ `${emojis.leave} ${format.input(user.tag)} ${
isBan ? 'got banned from' : 'left'
} the server. There are now ${welcome.guild.memberCount.toLocaleString()} members.`
)
- .setColor(isBan ? util.colors.orange : util.colors.red);
+ .setColor(isBan ? colors.orange : colors.red);
welcome
.send({ embeds: [embed] })
.then(() =>
client.console.info(
'guildMemberRemove',
- `Sent a message for ${util.format.inputLog(user.tag)} in ${util.format.inputLog(member.guild.name)}.`
+ `Sent a message for ${format.inputLog(user.tag)} in ${format.inputLog(member.guild.name)}.`
)
)
.catch(() =>
member.guild.error(
'Welcome Message Error',
- `Failed to send message for ${util.format.input(user.tag)} in ${util.format.input(member.guild.name)}.`
+ `Failed to send message for ${format.input(user.tag)} in ${format.input(member.guild.name)}.`
)
);
}
@@ -74,7 +74,7 @@ export default class GuildMemberRemoveListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberRemove',
- `${isNew ? 'Created' : 'Updated'} info for ${util.format.inputLog(member.user.tag)}.`
+ `${isNew ? 'Created' : 'Updated'} info for ${format.inputLog(member.user.tag)}.`
)
);
}
diff --git a/src/listeners/guild/joinRoles.ts b/src/listeners/guild/joinRoles.ts
index dab623f..f2922c8 100644
--- a/src/listeners/guild/joinRoles.ts
+++ b/src/listeners/guild/joinRoles.ts
@@ -1,4 +1,4 @@
-import { BushListener, StickyRole, type BushClientEvents } from '#lib';
+import { BushListener, colors, format, StickyRole, type BushClientEvents } from '#lib';
import { type GuildMember, type Snowflake } from 'discord.js';
export default class JoinRolesListener extends BushListener {
@@ -10,7 +10,7 @@ export default class JoinRolesListener extends BushListener {
});
}
- public override async exec(...[oldMember, newMember]: BushClientEvents['guildMemberUpdate']) {
+ public async exec(...[oldMember, newMember]: BushClientEvents['guildMemberUpdate']) {
if (client.config.isDevelopment) return;
if (oldMember.pending && !newMember.pending) {
const feat = {
@@ -58,8 +58,8 @@ export default class JoinRolesListener extends BushListener {
embeds: [
{
title: 'Sticky Roles Error',
- description: `There was an error returning ${util.format.input(member.user.tag)}'s roles.`,
- color: util.colors.error
+ description: `There was an error returning ${format.input(member.user.tag)}'s roles.`,
+ color: colors.error
}
]
});
@@ -68,7 +68,7 @@ export default class JoinRolesListener extends BushListener {
if (addedRoles) {
void client.console.info(
'guildMemberAdd',
- `Assigned sticky roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
+ `Assigned sticky roles to ${format.inputLog(member.user.tag)} in ${format.inputLog(member.guild.name)}.`
);
} else if (!addedRoles) {
const failedRoles: string[] = [];
@@ -82,9 +82,7 @@ export default class JoinRolesListener extends BushListener {
} else {
void client.console.info(
'guildMemberAdd',
- `[Fallback] Assigned sticky roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(
- member.guild.name
- )}.`
+ `[Fallback] Assigned sticky roles to ${format.inputLog(member.user.tag)} in ${format.inputLog(member.guild.name)}.`
);
}
}
@@ -106,13 +104,13 @@ export default class JoinRolesListener extends BushListener {
.then(() =>
client.console.info(
'guildMemberAdd',
- `Assigned join roles to ${util.format.inputLog(member.user.tag)} in ${util.format.inputLog(member.guild.name)}.`
+ `Assigned join roles to ${format.inputLog(member.user.tag)} in ${format.inputLog(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)}.`
+ `Failed to assign join roles to ${format.input(member.user.tag)}, in ${format.input(member.guild.name)}.`
)
);
}
diff --git a/src/listeners/guild/syncUnbanPunishmentModel.ts b/src/listeners/guild/syncUnbanPunishmentModel.ts
index 44f5bb4..80a8ce2 100644
--- a/src/listeners/guild/syncUnbanPunishmentModel.ts
+++ b/src/listeners/guild/syncUnbanPunishmentModel.ts
@@ -9,7 +9,7 @@ export default class SyncUnbanListener extends BushListener {
});
}
- public override async exec(...[ban]: BushClientEvents['guildBanRemove']) {
+ public async exec(...[ban]: BushClientEvents['guildBanRemove']) {
const bans = await ActivePunishment.findAll({
where: {
user: ban.user.id,
diff --git a/src/listeners/interaction/interactionCreate.ts b/src/listeners/interaction/interactionCreate.ts
index 48a2149..6c421d1 100644
--- a/src/listeners/interaction/interactionCreate.ts
+++ b/src/listeners/interaction/interactionCreate.ts
@@ -1,4 +1,4 @@
-import { AutoMod, BushListener, type BushClientEvents } from '#lib';
+import { AutoMod, BushListener, emojis, format, oxford, surroundArray, type BushClientEvents } from '#lib';
import { InteractionType } from 'discord.js';
export default class InteractionCreateListener extends BushListener {
@@ -10,7 +10,7 @@ export default class InteractionCreateListener extends BushListener {
});
}
- public override async exec(...[interaction]: BushClientEvents['interactionCreate']) {
+ public async exec(...[interaction]: BushClientEvents['interactionCreate']) {
if (!interaction) return;
if ('customId' in interaction && (interaction as any)['customId'].startsWith('test')) return;
void client.console.verbose(
@@ -26,31 +26,31 @@ export default class InteractionCreateListener extends BushListener {
else if (id.startsWith('button-role;') && interaction.inCachedGuild()) {
const [, roleId] = id.split(';');
const role = interaction.guild.roles.cache.get(roleId);
- if (!role) return interaction.reply({ content: `${util.emojis.error} That role does not exist.`, ephemeral: true });
+ if (!role) return interaction.reply({ content: `${emojis.error} That role does not exist.`, ephemeral: true });
const has = interaction.member.roles.cache.has(roleId);
await interaction.deferReply({ ephemeral: true });
if (has) {
const success = await interaction.member.roles.remove(roleId).catch(() => false);
if (success)
return interaction.editReply({
- content: `${util.emojis.success} Removed the ${role} role from you.`,
+ content: `${emojis.success} Removed the ${role} role from you.`,
allowedMentions: {}
});
else
return interaction.editReply({
- content: `${util.emojis.error} Failed to remove ${role} from you.`,
+ content: `${emojis.error} Failed to remove ${role} from you.`,
allowedMentions: {}
});
} else {
const success = await interaction.member.roles.add(roleId).catch(() => false);
if (success)
return interaction.editReply({
- content: `${util.emojis.success} Added the ${role} role to you.`,
+ content: `${emojis.success} Added the ${role} role to you.`,
allowedMentions: {}
});
else
return interaction.editReply({
- content: `${util.emojis.error} Failed to add ${role} to you.`,
+ content: `${emojis.error} Failed to add ${role} to you.`,
allowedMentions: {}
});
}
@@ -60,8 +60,8 @@ export default class InteractionCreateListener extends BushListener {
return await interaction.reply({
content: `You selected ${
Array.isArray(interaction.values)
- ? util.oxford(util.surroundArray(interaction.values, '`'), 'and', '')
- : util.format.input(interaction.values)
+ ? oxford(surroundArray(interaction.values, '`'), 'and', '')
+ : format.input(interaction.values)
}.`,
ephemeral: true
});
diff --git a/src/listeners/member-custom/bushBan.ts b/src/listeners/member-custom/bushBan.ts
index 1727433..32610ea 100644
--- a/src/listeners/member-custom/bushBan.ts
+++ b/src/listeners/member-custom/bushBan.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushBanListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushBanListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushBan']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushBan']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Red)
+ .setColor(colors.Red)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -26,7 +26,7 @@ export default class BushBanListener extends BushListener {
{ name: '**Moderator**', value: `${moderator} (${moderator.tag})` },
{ name: '**Reason**', value: `${reason ? reason : '[No Reason Provided]'}` }
]);
- if (duration) logEmbed.addFields([{ name: '**Duration**', value: util.humanizeDuration(duration) }]);
+ if (duration) logEmbed.addFields([{ name: '**Duration**', value: humanizeDuration(duration) }]);
if (dmSuccess === false) logEmbed.addFields([{ name: '**Additional Info**', value: 'Could not dm user.' }]);
return await logChannel.send({ embeds: [logEmbed] });
}
diff --git a/src/listeners/member-custom/bushBlock.ts b/src/listeners/member-custom/bushBlock.ts
index 7cc33d2..6d15a2b 100644
--- a/src/listeners/member-custom/bushBlock.ts
+++ b/src/listeners/member-custom/bushBlock.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushBlockListener extends BushListener {
@@ -10,15 +10,13 @@ export default class BushBlockListener extends BushListener {
});
}
- public override async exec(
- ...[victim, moderator, guild, reason, caseID, duration, dmSuccess, channel]: BushClientEvents['bushBlock']
- ) {
+ public async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess, channel]: BushClientEvents['bushBlock']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Purple)
+ .setColor(colors.Purple)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -30,7 +28,7 @@ export default class BushBlockListener extends BushListener {
{ name: '**Reason**', value: `${reason ? reason : '[No Reason Provided]'}` }
]);
- if (duration) logEmbed.addFields([{ name: '**Duration**', value: `${util.humanizeDuration(duration) || duration}` }]);
+ if (duration) logEmbed.addFields([{ name: '**Duration**', value: `${humanizeDuration(duration) || duration}` }]);
if (dmSuccess === false) logEmbed.addFields([{ name: '**Additional Info**', value: 'Could not dm user.' }]);
return await logChannel.send({ embeds: [logEmbed] });
}
diff --git a/src/listeners/member-custom/bushKick.ts b/src/listeners/member-custom/bushKick.ts
index 1be7bf9..65a6942 100644
--- a/src/listeners/member-custom/bushKick.ts
+++ b/src/listeners/member-custom/bushKick.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushKickListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushKickListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushKick']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushKick']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Red)
+ .setColor(colors.Red)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushLevelUpdate.ts b/src/listeners/member-custom/bushLevelUpdate.ts
index 2a7b75b..a9c0820 100644
--- a/src/listeners/member-custom/bushLevelUpdate.ts
+++ b/src/listeners/member-custom/bushLevelUpdate.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, format, type BushClientEvents } from '#lib';
import assert from 'assert';
import { type TextChannel } from 'discord.js';
@@ -13,7 +13,7 @@ export default class BushLevelUpdateListener extends BushListener {
});
}
- public override async exec(...[member, _oldLevel, newLevel, _currentXp, message]: Args) {
+ public async exec(...[member, _oldLevel, newLevel, _currentXp, message]: Args) {
void this.sendLevelUpMessages(member, newLevel, message);
void this.assignLevelRoles(member, newLevel, message);
}
@@ -27,7 +27,7 @@ export default class BushLevelUpdateListener extends BushListener {
.catch(() => null)) ?? message.channel) as TextChannel;
const success = await channel
- .send(`${util.format.input(member.user.tag)} leveled up to level ${util.format.input(`${newLevel}`)}.`)
+ .send(`${format.input(member.user.tag)} leveled up to level ${format.input(`${newLevel}`)}.`)
.catch(() => null);
if (!success)
diff --git a/src/listeners/member-custom/bushMute.ts b/src/listeners/member-custom/bushMute.ts
index a0aa37d..77ea74c 100644
--- a/src/listeners/member-custom/bushMute.ts
+++ b/src/listeners/member-custom/bushMute.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushMuteListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushMuteListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushMute']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushMute']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Orange)
+ .setColor(colors.Orange)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -26,7 +26,7 @@ export default class BushMuteListener extends BushListener {
{ name: '**Moderator**', value: `${moderator} (${moderator.tag})` },
{ name: '**Reason**', value: `${reason ? reason : '[No Reason Provided]'}` }
]);
- if (duration) logEmbed.addFields([{ name: '**Duration**', value: `${util.humanizeDuration(duration) || duration}` }]);
+ if (duration) logEmbed.addFields([{ name: '**Duration**', value: `${humanizeDuration(duration) || duration}` }]);
if (dmSuccess === false) logEmbed.addFields([{ name: '**Additional Info**', value: 'Could not dm user.' }]);
return await logChannel.send({ embeds: [logEmbed] });
}
diff --git a/src/listeners/member-custom/bushPunishRole.ts b/src/listeners/member-custom/bushPunishRole.ts
index 5604bac..2e5b17b 100644
--- a/src/listeners/member-custom/bushPunishRole.ts
+++ b/src/listeners/member-custom/bushPunishRole.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushPunishRoleListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushPunishRoleListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, duration]: BushClientEvents['bushPunishRole']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, duration]: BushClientEvents['bushPunishRole']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Yellow)
+ .setColor(colors.Yellow)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -26,7 +26,7 @@ export default class BushPunishRoleListener extends BushListener {
{ name: '**Moderator**', value: `${moderator} (${moderator.tag})` },
{ name: '**Reason**', value: `${reason ? reason : '[No Reason Provided]'}` }
]);
- if (duration) logEmbed.addFields([{ name: '**Duration**', value: util.humanizeDuration(duration) }]);
+ if (duration) logEmbed.addFields([{ name: '**Duration**', value: humanizeDuration(duration) }]);
return await logChannel.send({ embeds: [logEmbed] });
}
}
diff --git a/src/listeners/member-custom/bushPunishRoleRemove.ts b/src/listeners/member-custom/bushPunishRoleRemove.ts
index 1a13de0..7bc9863 100644
--- a/src/listeners/member-custom/bushPunishRoleRemove.ts
+++ b/src/listeners/member-custom/bushPunishRoleRemove.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushPunishRoleRemoveListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushPunishRoleRemoveListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, role]: BushClientEvents['bushPunishRoleRemove']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, role]: BushClientEvents['bushPunishRoleRemove']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Green)
+ .setColor(colors.Green)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushPurge.ts b/src/listeners/member-custom/bushPurge.ts
index 3334bad..ea30bc5 100644
--- a/src/listeners/member-custom/bushPurge.ts
+++ b/src/listeners/member-custom/bushPurge.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, emojis, inspectCleanRedactHaste, type BushClientEvents } from '#lib';
import { EmbedBuilder } from 'discord.js';
export default class BushPurgeListener extends BushListener {
@@ -10,7 +10,7 @@ export default class BushPurgeListener extends BushListener {
});
}
- public override async exec(...[moderator, guild, channel, messages]: BushClientEvents['bushPurge']) {
+ public async exec(...[moderator, guild, channel, messages]: BushClientEvents['bushPurge']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
@@ -21,10 +21,10 @@ export default class BushPurgeListener extends BushListener {
embeds: m.embeds,
attachments: [...m.attachments.values()]
}));
- const haste = await util.inspectCleanRedactHaste(mappedMessages);
+ const haste = await inspectCleanRedactHaste(mappedMessages);
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.DarkPurple)
+ .setColor(colors.DarkPurple)
.setTimestamp()
.setFooter({ text: `${messages.size.toLocaleString()} Messages` })
.setAuthor({ name: moderator.tag, iconURL: moderator.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -35,7 +35,7 @@ export default class BushPurgeListener extends BushListener {
{
name: '**Messages**',
value: `${
- haste.url ? `[haste](${haste.url})${haste.error ? `- ${haste.error}` : ''}` : `${util.emojis.error} ${haste.error}`
+ haste.url ? `[haste](${haste.url})${haste.error ? `- ${haste.error}` : ''}` : `${emojis.error} ${haste.error}`
}`
}
]);
diff --git a/src/listeners/member-custom/bushRemoveTimeout.ts b/src/listeners/member-custom/bushRemoveTimeout.ts
index aafa11e..742d407 100644
--- a/src/listeners/member-custom/bushRemoveTimeout.ts
+++ b/src/listeners/member-custom/bushRemoveTimeout.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushRemoveTimeoutListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushRemoveTimeoutListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushRemoveTimeout']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushRemoveTimeout']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Green)
+ .setColor(colors.Green)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushTimeout.ts b/src/listeners/member-custom/bushTimeout.ts
index 07a7105..4621921 100644
--- a/src/listeners/member-custom/bushTimeout.ts
+++ b/src/listeners/member-custom/bushTimeout.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushTimeoutListener extends BushListener {
@@ -10,15 +10,13 @@ export default class BushTimeoutListener extends BushListener {
});
}
- public override async exec(
- ...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushTimeout']
- ) {
+ public async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushTimeout']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Orange)
+ .setColor(colors.Orange)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
@@ -27,7 +25,7 @@ export default class BushTimeoutListener extends BushListener {
{ name: '**User**', value: `${user} (${user.tag})` },
{ name: '**Moderator**', value: `${moderator} (${moderator.tag})` },
{ name: '**Reason**', value: `${reason ? reason : '[No Reason Provided]'}` },
- { name: '**Duration**', value: `${util.humanizeDuration(duration) || duration}` }
+ { name: '**Duration**', value: `${humanizeDuration(duration) || duration}` }
]);
if (dmSuccess === false) logEmbed.addFields([{ name: '**Additional Info**', value: 'Could not dm user.' }]);
return await logChannel.send({ embeds: [logEmbed] });
diff --git a/src/listeners/member-custom/bushUnban.ts b/src/listeners/member-custom/bushUnban.ts
index 2628d36..463ce6c 100644
--- a/src/listeners/member-custom/bushUnban.ts
+++ b/src/listeners/member-custom/bushUnban.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushUnbanListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushUnbanListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnban']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnban']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Green)
+ .setColor(colors.Green)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushUnblock.ts b/src/listeners/member-custom/bushUnblock.ts
index 238c5b5..43b7b2b 100644
--- a/src/listeners/member-custom/bushUnblock.ts
+++ b/src/listeners/member-custom/bushUnblock.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushUnblockListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushUnblockListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess, channel]: BushClientEvents['bushUnblock']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess, channel]: BushClientEvents['bushUnblock']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Green)
+ .setColor(colors.Green)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushUnmute.ts b/src/listeners/member-custom/bushUnmute.ts
index e7f6793..614a826 100644
--- a/src/listeners/member-custom/bushUnmute.ts
+++ b/src/listeners/member-custom/bushUnmute.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushUnmuteListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushUnmuteListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnmute']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnmute']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Green)
+ .setColor(colors.Green)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/bushUpdateModlog.ts b/src/listeners/member-custom/bushUpdateModlog.ts
index f49defe..5e29b9a 100644
--- a/src/listeners/member-custom/bushUpdateModlog.ts
+++ b/src/listeners/member-custom/bushUpdateModlog.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, inspectCleanRedactCodeblock, type BushClientEvents } from '#lib';
import { EmbedBuilder } from 'discord.js';
export default class BushUpdateModlogListener extends BushListener {
@@ -10,12 +10,12 @@ export default class BushUpdateModlogListener extends BushListener {
});
}
- public override async exec(...[moderator, modlogID, key, oldModlog, newModlog]: BushClientEvents['bushUpdateModlog']) {
+ public async exec(...[moderator, modlogID, key, oldModlog, newModlog]: BushClientEvents['bushUpdateModlog']) {
const logChannel = await moderator.guild.getLogChannel('moderation');
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Blurple)
+ .setColor(colors.Blurple)
.setTimestamp()
.setAuthor({
name: moderator.user.tag,
@@ -26,8 +26,8 @@ export default class BushUpdateModlogListener extends BushListener {
{ name: '**Moderator**', value: `${moderator} (${moderator.user.tag})` },
{ name: '**ModLog Changed**', value: modlogID },
{ name: '**Value Changed**', value: key },
- { name: '**Old Value**', value: await util.inspectCleanRedactCodeblock(oldModlog, undefined, undefined, 1024) },
- { name: '**New Value**', value: await util.inspectCleanRedactCodeblock(newModlog, undefined, undefined, 1024) }
+ { name: '**Old Value**', value: await inspectCleanRedactCodeblock(oldModlog, undefined, undefined, 1024) },
+ { name: '**New Value**', value: await inspectCleanRedactCodeblock(newModlog, undefined, undefined, 1024) }
]);
return await logChannel.send({ embeds: [logEmbed] });
diff --git a/src/listeners/member-custom/bushUpdateSettings.ts b/src/listeners/member-custom/bushUpdateSettings.ts
index 948bbe7..e367c4e 100644
--- a/src/listeners/member-custom/bushUpdateSettings.ts
+++ b/src/listeners/member-custom/bushUpdateSettings.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, inspectCleanRedactCodeblock, type BushClientEvents } from '#lib';
import { EmbedBuilder } from 'discord.js';
export default class BushUpdateSettingsListener extends BushListener {
@@ -10,11 +10,11 @@ export default class BushUpdateSettingsListener extends BushListener {
});
}
- public override async exec(...[setting, guild, oldSettings, newSettings, moderator]: BushClientEvents['bushUpdateSettings']) {
+ public async exec(...[setting, guild, oldSettings, newSettings, moderator]: BushClientEvents['bushUpdateSettings']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
- const logEmbed = new EmbedBuilder().setColor(util.colors.Blurple).setTimestamp();
+ const logEmbed = new EmbedBuilder().setColor(colors.Blurple).setTimestamp();
if (moderator)
logEmbed.setAuthor({
@@ -25,8 +25,8 @@ export default class BushUpdateSettingsListener extends BushListener {
if (moderator) logEmbed.addFields([{ name: '**Moderator**', value: `${moderator} (${moderator.user.tag})` }]);
logEmbed.addFields([
{ name: '**Setting Changed**', value: setting },
- { name: '**Old Value**', value: await util.inspectCleanRedactCodeblock(oldSettings, 'js', undefined, 1024) },
- { name: '**New Value**', value: await util.inspectCleanRedactCodeblock(newSettings, 'js', undefined, 1024) }
+ { name: '**Old Value**', value: await inspectCleanRedactCodeblock(oldSettings, 'js', undefined, 1024) },
+ { name: '**New Value**', value: await inspectCleanRedactCodeblock(newSettings, 'js', undefined, 1024) }
]);
return await logChannel.send({ embeds: [logEmbed] });
diff --git a/src/listeners/member-custom/bushWarn.ts b/src/listeners/member-custom/bushWarn.ts
index ede56fd..b9c1868 100644
--- a/src/listeners/member-custom/bushWarn.ts
+++ b/src/listeners/member-custom/bushWarn.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, type BushClientEvents } from '#lib';
import { EmbedBuilder, GuildMember } from 'discord.js';
export default class BushWarnListener extends BushListener {
@@ -10,13 +10,13 @@ export default class BushWarnListener extends BushListener {
});
}
- public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushWarn']) {
+ public async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushWarn']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const user = victim instanceof GuildMember ? victim.user : victim;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Yellow)
+ .setColor(colors.Yellow)
.setTimestamp()
.setFooter({ text: `CaseID: ${caseID}` })
.setAuthor({ name: user.tag, iconURL: user.avatarURL({ extension: 'png', size: 4096 }) ?? undefined })
diff --git a/src/listeners/member-custom/massBan.ts b/src/listeners/member-custom/massBan.ts
index 29f7ce3..ca41f29 100644
--- a/src/listeners/member-custom/massBan.ts
+++ b/src/listeners/member-custom/massBan.ts
@@ -1,4 +1,4 @@
-import { BanResponse, banResponse, BushListener, type BushClientEvents } from '#lib';
+import { BanResponse, banResponse, BushListener, colors, emojis, overflowEmbed, type BushClientEvents } from '#lib';
export default class MassBanListener extends BushListener {
public constructor() {
@@ -9,20 +9,19 @@ export default class MassBanListener extends BushListener {
});
}
- public override async exec(...[moderator, guild, reason, results]: BushClientEvents['massBan']) {
+ public async exec(...[moderator, guild, reason, results]: BushClientEvents['massBan']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
const success = (res: BanResponse): boolean => [banResponse.SUCCESS, banResponse.DM_ERROR].includes(res as any);
const lines = results.map(
- (reason, user) =>
- `${success(reason) ? util.emojis.success : util.emojis.error} ${user}${success(reason) ? '' : ` - ${reason}`}`
+ (reason, user) => `${success(reason) ? emojis.success : emojis.error} ${user}${success(reason) ? '' : ` - ${reason}`}`
);
- const embeds = util.overflowEmbed(
+ const embeds = overflowEmbed(
{
- color: util.colors.DarkRed,
+ color: colors.DarkRed,
title: 'Mass Ban',
timestamp: new Date().toISOString(),
fields: [
diff --git a/src/listeners/member-custom/massEvidence.ts b/src/listeners/member-custom/massEvidence.ts
index 4a45ee7..f0f75df 100644
--- a/src/listeners/member-custom/massEvidence.ts
+++ b/src/listeners/member-custom/massEvidence.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, overflowEmbed, type BushClientEvents } from '#lib';
export default class MassEvidenceListener extends BushListener {
public constructor() {
@@ -9,13 +9,13 @@ export default class MassEvidenceListener extends BushListener {
});
}
- public override async exec(...[moderator, guild, evidence, lines]: BushClientEvents['massEvidence']) {
+ public async exec(...[moderator, guild, evidence, lines]: BushClientEvents['massEvidence']) {
const logChannel = await guild.getLogChannel('moderation');
if (!logChannel) return;
- const embeds = util.overflowEmbed(
+ const embeds = overflowEmbed(
{
- color: util.colors.DarkRed,
+ color: colors.DarkRed,
title: 'Mass Evidence',
timestamp: new Date().toISOString(),
fields: [
diff --git a/src/listeners/message/autoPublisher.ts b/src/listeners/message/autoPublisher.ts
index 8f3462f..c669930 100644
--- a/src/listeners/message/autoPublisher.ts
+++ b/src/listeners/message/autoPublisher.ts
@@ -10,7 +10,7 @@ export default class autoPublisherListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (!message.guild || !(await message.guild.hasFeature('autoPublish'))) return;
const autoPublishChannels = await message.guild.getSetting('autoPublishChannels');
if (autoPublishChannels) {
diff --git a/src/listeners/message/automodCreate.ts b/src/listeners/message/automodCreate.ts
index 8824c72..0f089a3 100644
--- a/src/listeners/message/automodCreate.ts
+++ b/src/listeners/message/automodCreate.ts
@@ -9,7 +9,7 @@ export default class AutomodMessageCreateListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
return new AutoMod(message);
}
}
diff --git a/src/listeners/message/automodUpdate.ts b/src/listeners/message/automodUpdate.ts
index d2e6f40..fa00f92 100644
--- a/src/listeners/message/automodUpdate.ts
+++ b/src/listeners/message/automodUpdate.ts
@@ -9,7 +9,7 @@ export default class AutomodMessageUpdateListener extends BushListener {
});
}
- public override async exec(...[_, newMessage]: BushClientEvents['messageUpdate']) {
+ public async exec(...[_, newMessage]: BushClientEvents['messageUpdate']) {
const fullMessage = newMessage.partial ? await newMessage.fetch().catch(() => null) : newMessage;
if (!fullMessage) return;
return new AutoMod(fullMessage);
diff --git a/src/listeners/message/blacklistedFile.ts b/src/listeners/message/blacklistedFile.ts
index 122f289..15d97e3 100644
--- a/src/listeners/message/blacklistedFile.ts
+++ b/src/listeners/message/blacklistedFile.ts
@@ -65,7 +65,7 @@ export default class BlacklistedFileListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (!message.guild || !(await message.guild.hasFeature('blacklistedFile'))) return;
// const embedAttachments = message.embeds.filter((e) => ['image', 'video', 'gifv'].includes(e.type));
const foundEmojis = [...message.content.matchAll(/<(?<animated>a?):\w+:(?<id>\d+)>/g)];
diff --git a/src/listeners/message/boosterMessage.ts b/src/listeners/message/boosterMessage.ts
index 989f671..e33abfb 100644
--- a/src/listeners/message/boosterMessage.ts
+++ b/src/listeners/message/boosterMessage.ts
@@ -10,7 +10,7 @@ export default class BoosterMessageListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (!message.guild || !(await message.guild?.hasFeature('boosterMessageReact'))) return;
if (message.type === MessageType.UserPremiumGuildSubscription) {
return await message.react('<:nitroboost:785160348885975062>').catch(() => {
diff --git a/src/listeners/message/directMessage.ts b/src/listeners/message/directMessage.ts
index 87480b0..463e4d8 100644
--- a/src/listeners/message/directMessage.ts
+++ b/src/listeners/message/directMessage.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, colors, getConfigChannel, type BushClientEvents } from '#lib';
import { ChannelType, EmbedBuilder } from 'discord.js';
export default class DirectMessageListener extends BushListener {
@@ -10,7 +10,7 @@ export default class DirectMessageListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (message.channel.type === ChannelType.DM) {
if (!(message.author.id == client.user!.id) && message.author.bot) return;
if (client.cache.global.blacklistedUsers.includes(message.author.id)) return;
@@ -23,7 +23,7 @@ export default class DirectMessageListener extends BushListener {
iconURL: `${message.author.displayAvatarURL()}`
})
.setDescription(`**DM:**\n${message}`)
- .setColor(util.colors.blue);
+ .setColor(colors.blue);
} else {
dmLogEmbed
.setAuthor({
@@ -31,7 +31,7 @@ export default class DirectMessageListener extends BushListener {
iconURL: `${message.channel.recipient?.displayAvatarURL()}`
})
.setDescription(`**DM:**\n${message}`)
- .setColor(util.colors.red)
+ .setColor(colors.red)
.setTimestamp();
}
if (message.attachments.filter((a) => typeof a.size == 'number').size == 1) {
@@ -39,7 +39,7 @@ export default class DirectMessageListener extends BushListener {
} else if (message.attachments.size > 0) {
dmLogEmbed.addFields([{ name: 'Attachments', value: message.attachments.map((a) => a.proxyURL).join('\n') }]);
}
- const dmChannel = await util.getConfigChannel('dm');
+ const dmChannel = await getConfigChannel('dm');
await dmChannel.send({ embeds: [dmLogEmbed] });
}
}
diff --git a/src/listeners/message/highlight.ts b/src/listeners/message/highlight.ts
index d7965c5..d68337c 100644
--- a/src/listeners/message/highlight.ts
+++ b/src/listeners/message/highlight.ts
@@ -9,7 +9,7 @@ export default class HighlightListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (!message.inGuild()) return;
if (message.author.bot || message.system) return;
if (!(await message.guild.hasFeature('highlight'))) return; // allows highlighting to be disabled on a guild-by-guild basis
diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts
index 08a8a7c..a72ae02 100644
--- a/src/listeners/message/level.ts
+++ b/src/listeners/message/level.ts
@@ -1,4 +1,4 @@
-import { BushListener, Level, type BushCommandHandlerEvents } from '#lib';
+import { BushListener, handleError, Level, type BushCommandHandlerEvents } from '#lib';
import { MessageType } from 'discord.js';
export default class LevelListener extends BushListener {
@@ -11,7 +11,7 @@ export default class LevelListener extends BushListener {
});
}
- public override async exec(...[message]: BushCommandHandlerEvents['messageInvalid']) {
+ public async exec(...[message]: BushCommandHandlerEvents['messageInvalid']) {
if (message.author.bot || !message.author || !message.inGuild()) return;
if (!(await message.guild.hasFeature('leveling'))) return;
if (this.#levelCooldowns.has(`${message.guildId}-${message.author.id}`)) return;
@@ -33,7 +33,7 @@ export default class LevelListener extends BushListener {
const xpToGive = Level.genRandomizedXp();
user.xp = user.xp + xpToGive;
const success = await user.save().catch((e) => {
- void util.handleError('level', e);
+ void handleError('level', e);
return false;
});
const newLevel = Level.convertXpToLevel(user.xp);
diff --git a/src/listeners/message/quoteCreate.ts b/src/listeners/message/quoteCreate.ts
index 0d8b464..d43eef7 100644
--- a/src/listeners/message/quoteCreate.ts
+++ b/src/listeners/message/quoteCreate.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, resolveMessagesFromLinks, type BushClientEvents } from '#lib';
export default class QuoteCreateListener extends BushListener {
public constructor() {
@@ -9,11 +9,11 @@ export default class QuoteCreateListener extends BushListener {
});
}
- public override async exec(...[message]: BushClientEvents['messageCreate']) {
+ public async exec(...[message]: BushClientEvents['messageCreate']) {
if (message.author.id !== '322862723090219008' || !client.config.isProduction) return;
if (!message.inGuild()) return;
- const messages = await util.resolveMessagesFromLinks(message.content);
+ const messages = await resolveMessagesFromLinks(message.content);
if (!messages.length) return;
for (const msg of messages) {
diff --git a/src/listeners/message/quoteEdit.ts b/src/listeners/message/quoteEdit.ts
index 790f05a..7da0d95 100644
--- a/src/listeners/message/quoteEdit.ts
+++ b/src/listeners/message/quoteEdit.ts
@@ -9,7 +9,7 @@
// });
// }
-// public override async exec(...[_, newMessage]: BushClientEvents['messageUpdate']) {
+// public async exec(...[_, newMessage]: BushClientEvents['messageUpdate']) {
// return;
// // if (newMessage.partial) newMessage = await newMessage.fetch();
// // return new QuoteCreateListener().exec(newMessage);
diff --git a/src/listeners/message/verbose.ts b/src/listeners/message/verbose.ts
index 1225412..e3ef04f 100644
--- a/src/listeners/message/verbose.ts
+++ b/src/listeners/message/verbose.ts
@@ -10,7 +10,7 @@ export default class MessageVerboseListener extends BushListener {
});
}
- public override exec(...[message]: BushClientEvents['messageCreate']): void {
+ public exec(...[message]: BushClientEvents['messageCreate']): void {
if (client.customReady) {
if (message.channel?.type === ChannelType.DM) return;
void client.console.verbose(
diff --git a/src/listeners/other/consoleListener.ts b/src/listeners/other/consoleListener.ts
index 0c30724..543f459 100644
--- a/src/listeners/other/consoleListener.ts
+++ b/src/listeners/other/consoleListener.ts
@@ -11,7 +11,7 @@ import { promisify } from 'util';
});
}
- public override async exec(line: string) {
+ public async exec(line: string) {
if (line.startsWith('eval ') || line.startsWith('ev ')) {
/* eslint-disable @typescript-eslint/no-unused-vars */
const sh = promisify(exec),
@@ -32,7 +32,6 @@ import { promisify } from 'util';
Embed,
SelectMenuComponent,
ReactionCollector,
- Util,
Collection
} = await import('discord.js');
/* eslint-enable @typescript-eslint/no-unused-vars */
diff --git a/src/listeners/other/exit.ts b/src/listeners/other/exit.ts
index 26ed36f..e16aeb7 100644
--- a/src/listeners/other/exit.ts
+++ b/src/listeners/other/exit.ts
@@ -8,7 +8,7 @@ export default class ExitListener extends BushListener {
});
}
- public override async exec(code: number) {
+ public async exec(code: number) {
await client.console.error('processExit', `Process ended with code <<${code}>>.`);
}
}
diff --git a/src/listeners/other/promiseRejection.ts b/src/listeners/other/promiseRejection.ts
index ad82469..79bf5de 100644
--- a/src/listeners/other/promiseRejection.ts
+++ b/src/listeners/other/promiseRejection.ts
@@ -1,4 +1,4 @@
-import { BushListener } from '#lib';
+import { BushListener, formatError } from '#lib';
import CommandErrorListener from '../commands/commandError.js';
export default class PromiseRejectionListener extends BushListener {
@@ -10,7 +10,7 @@ export default class PromiseRejectionListener extends BushListener {
});
}
- public override async exec(error: Error) {
+ public async exec(error: Error) {
process.listeners('unhandledRejection').forEach((listener) => {
if (listener.toString() === this.exec.toString()) return;
process.removeListener('unhandledRejection', listener);
@@ -20,11 +20,7 @@ export default class PromiseRejectionListener extends BushListener {
level: 'error'
});
- void client.console.error(
- 'promiseRejection',
- `An unhanded promise rejection occurred:\n${util.formatError(error, true)}`,
- false
- );
+ void client.console.error('promiseRejection', `An unhanded promise rejection occurred:\n${formatError(error, true)}`, false);
if (!error.message.includes('reason: getaddrinfo ENOTFOUND canary.discord.com'))
void client.console.channelError({
embeds: await CommandErrorListener.generateErrorEmbed({ type: 'unhandledRejection', error: error })
diff --git a/src/listeners/other/uncaughtException.ts b/src/listeners/other/uncaughtException.ts
index 8eb326f..3e80feb 100644
--- a/src/listeners/other/uncaughtException.ts
+++ b/src/listeners/other/uncaughtException.ts
@@ -1,4 +1,4 @@
-import { BushListener } from '#lib';
+import { BushListener, formatError } from '#lib';
import CommandErrorListener from '../commands/commandError.js';
export default class UncaughtExceptionListener extends BushListener {
@@ -10,7 +10,7 @@ export default class UncaughtExceptionListener extends BushListener {
});
}
- public override async exec(error: Error) {
+ public async exec(error: Error) {
process.listeners('uncaughtException').forEach((listener) => {
if (listener.toString() === this.exec.toString()) return;
process.removeListener('uncaughtException', listener);
@@ -19,7 +19,7 @@ export default class UncaughtExceptionListener extends BushListener {
level: 'error'
});
- void client.console.error('uncaughtException', `An uncaught exception occurred:\n${util.formatError(error, true)}`, false);
+ void client.console.error('uncaughtException', `An uncaught exception occurred:\n${formatError(error, true)}`, false);
void client.console.channelError({
embeds: await CommandErrorListener.generateErrorEmbed({ type: 'uncaughtException', error: error })
});
diff --git a/src/listeners/other/warning.ts b/src/listeners/other/warning.ts
index 800472a..ba38f5f 100644
--- a/src/listeners/other/warning.ts
+++ b/src/listeners/other/warning.ts
@@ -1,4 +1,4 @@
-import { BushListener } from '#lib';
+import { BushListener, colors, formatError } from '#lib';
import CommandErrorListener from '../commands/commandError.js';
export default class WarningListener extends BushListener {
@@ -9,17 +9,17 @@ export default class WarningListener extends BushListener {
});
}
- public override async exec(error: Error) {
+ public async exec(error: Error) {
if (error.name === 'ExperimentalWarning') return;
client.sentry.captureException(error, {
level: 'warning'
});
- void client.console.warn('warning', `A warning occurred:\n${util.formatError(error, true)}`, false);
+ void client.console.warn('warning', `A warning occurred:\n${formatError(error, true)}`, false);
const embeds = await CommandErrorListener.generateErrorEmbed({ type: 'unhandledRejection', error: error });
- embeds[0].setColor(util.colors.warn).setTitle('A Warning Occurred');
+ embeds[0].setColor(colors.warn).setTitle('A Warning Occurred');
void client.console.channelError({ embeds });
}
diff --git a/src/listeners/rest/rateLimit.ts b/src/listeners/rest/rateLimit.ts
index 4884e9f..5878d81 100644
--- a/src/listeners/rest/rateLimit.ts
+++ b/src/listeners/rest/rateLimit.ts
@@ -10,7 +10,7 @@ export default class RateLimitedListener extends BushListener {
});
}
- public override async exec(...[message]: RestEvents['rateLimited']): Promise<void> {
+ public async exec(...[message]: RestEvents['rateLimited']): Promise<void> {
void client.console.superVerboseRaw('rateLimited', message);
}
}
diff --git a/src/listeners/track-manual-punishments/modlogSyncBan.ts b/src/listeners/track-manual-punishments/modlogSyncBan.ts
index be937b9..45d6f51 100644
--- a/src/listeners/track-manual-punishments/modlogSyncBan.ts
+++ b/src/listeners/track-manual-punishments/modlogSyncBan.ts
@@ -1,4 +1,4 @@
-import { BushListener, Moderation, ModLogType, Time, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BushClientEvents } from '#lib';
import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ModlogSyncBanListener extends BushListener {
@@ -10,7 +10,7 @@ export default class ModlogSyncBanListener extends BushListener {
});
}
- public override async exec(...[ban]: BushClientEvents['guildBanAdd']) {
+ public async exec(...[ban]: BushClientEvents['guildBanAdd']) {
if (!(await ban.guild.hasFeature('logManualPunishments'))) return;
if (!ban.guild.members.me) return; // bot was banned
if (!ban.guild.members.me.permissions.has(PermissionFlagsBits.ViewAuditLog)) {
@@ -21,7 +21,7 @@ export default class ModlogSyncBanListener extends BushListener {
}
const now = new Date();
- await util.sleep(500 * Time.Millisecond); // wait for audit log entry
+ await sleep(500 * Time.Millisecond); // wait for audit log entry
const logs = (await ban.guild.fetchAuditLogs({ type: AuditLogEvent.MemberBanAdd })).entries.filter(
(entry) => entry.target?.id === ban.user.id
@@ -33,9 +33,7 @@ export default class ModlogSyncBanListener extends BushListener {
if (!first.executor || first.executor?.bot) return;
if (Math.abs(first.createdAt.getTime() - now.getTime()) > Time.Minute) {
- throw new Error(
- `Time is off by over a minute: ${util.humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`
- );
+ throw new Error(`Time is off by over a minute: ${humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`);
}
const { log } = await Moderation.createModLogEntry({
@@ -51,7 +49,7 @@ export default class ModlogSyncBanListener extends BushListener {
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Red)
+ .setColor(colors.Red)
.setTimestamp()
.setFooter({ text: `CaseID: ${log.id}` })
.setAuthor({
diff --git a/src/listeners/track-manual-punishments/modlogSyncKick.ts b/src/listeners/track-manual-punishments/modlogSyncKick.ts
index d136780..d901f5f 100644
--- a/src/listeners/track-manual-punishments/modlogSyncKick.ts
+++ b/src/listeners/track-manual-punishments/modlogSyncKick.ts
@@ -1,4 +1,4 @@
-import { BushListener, Moderation, ModLogType, Time, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BushClientEvents } from '#lib';
import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ModlogSyncKickListener extends BushListener {
@@ -10,7 +10,7 @@ export default class ModlogSyncKickListener extends BushListener {
});
}
- public override async exec(...[member]: BushClientEvents['guildMemberRemove']) {
+ public async exec(...[member]: BushClientEvents['guildMemberRemove']) {
if (!(await member.guild.hasFeature('logManualPunishments'))) return;
if (!member.guild.members.me) return; // bot was removed from guild
if (!member.guild.members.me.permissions.has(PermissionFlagsBits.ViewAuditLog)) {
@@ -21,7 +21,7 @@ export default class ModlogSyncKickListener extends BushListener {
}
const now = new Date();
- await util.sleep(500 * Time.Millisecond); // wait for audit log entry
+ await sleep(500 * Time.Millisecond); // wait for audit log entry
const logs = (await member.guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick })).entries.filter(
(entry) => entry.target?.id === member.user.id
@@ -33,9 +33,7 @@ export default class ModlogSyncKickListener extends BushListener {
if (!first.executor || first.executor?.bot) return;
if (Math.abs(first.createdAt.getTime() - now.getTime()) > Time.Minute) {
- throw new Error(
- `Time is off by over a minute: ${util.humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`
- );
+ throw new Error(`Time is off by over a minute: ${humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`);
}
const { log } = await Moderation.createModLogEntry({
@@ -51,7 +49,7 @@ export default class ModlogSyncKickListener extends BushListener {
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Red)
+ .setColor(colors.Red)
.setTimestamp()
.setFooter({ text: `CaseID: ${log.id}` })
.setAuthor({
diff --git a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts
index adcd7fe..4619edd 100644
--- a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts
+++ b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts
@@ -1,4 +1,4 @@
-import { BushListener, Moderation, ModLogType, Time, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BushClientEvents } from '#lib';
import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ModlogSyncTimeoutListener extends BushListener {
@@ -10,7 +10,7 @@ export default class ModlogSyncTimeoutListener extends BushListener {
});
}
- public override async exec(...[_oldMember, newMember]: BushClientEvents['guildMemberUpdate']) {
+ public async exec(...[_oldMember, newMember]: BushClientEvents['guildMemberUpdate']) {
if (!(await newMember.guild.hasFeature('logManualPunishments'))) return;
if (!newMember.guild.members.me!.permissions.has(PermissionFlagsBits.ViewAuditLog)) {
return newMember.guild.error(
@@ -20,7 +20,7 @@ export default class ModlogSyncTimeoutListener extends BushListener {
}
const now = new Date();
- await util.sleep(500 * Time.Millisecond); // wait for audit log entry
+ await sleep(500 * Time.Millisecond); // wait for audit log entry
const logs = (await newMember.guild.fetchAuditLogs({ type: AuditLogEvent.MemberUpdate })).entries.filter(
(entry) => entry.target?.id === newMember.user.id
@@ -35,9 +35,7 @@ export default class ModlogSyncTimeoutListener extends BushListener {
if (!timeOut) return;
if (Math.abs(first.createdAt.getTime() - now.getTime()) > Time.Minute) {
- throw new Error(
- `Time is off by over a minute: ${util.humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`
- );
+ throw new Error(`Time is off by over a minute: ${humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`);
}
const newTime = <string | null>timeOut.new ? new Date(<string>timeOut.new) : null;
@@ -56,7 +54,7 @@ export default class ModlogSyncTimeoutListener extends BushListener {
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors[newTime ? 'Orange' : 'Green'])
+ .setColor(colors[newTime ? 'Orange' : 'Green'])
.setTimestamp()
.setFooter({ text: `CaseID: ${log.id}` })
.setAuthor({
diff --git a/src/listeners/track-manual-punishments/modlogSyncUnban.ts b/src/listeners/track-manual-punishments/modlogSyncUnban.ts
index af0b21f..34979a5 100644
--- a/src/listeners/track-manual-punishments/modlogSyncUnban.ts
+++ b/src/listeners/track-manual-punishments/modlogSyncUnban.ts
@@ -1,4 +1,4 @@
-import { BushListener, Moderation, ModLogType, Time, type BushClientEvents } from '#lib';
+import { BushListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BushClientEvents } from '#lib';
import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ModlogSyncUnbanListener extends BushListener {
@@ -10,7 +10,7 @@ export default class ModlogSyncUnbanListener extends BushListener {
});
}
- public override async exec(...[ban]: BushClientEvents['guildBanRemove']) {
+ public async exec(...[ban]: BushClientEvents['guildBanRemove']) {
if (!(await ban.guild.hasFeature('logManualPunishments'))) return;
if (!ban.guild.members.me!.permissions.has(PermissionFlagsBits.ViewAuditLog)) {
return ban.guild.error(
@@ -20,7 +20,7 @@ export default class ModlogSyncUnbanListener extends BushListener {
}
const now = new Date();
- await util.sleep(500 * Time.Millisecond); // wait for audit log entry
+ await sleep(500 * Time.Millisecond); // wait for audit log entry
const logs = (await ban.guild.fetchAuditLogs({ type: AuditLogEvent.MemberBanRemove })).entries.filter(
(entry) => entry.target?.id === ban.user.id
@@ -32,9 +32,7 @@ export default class ModlogSyncUnbanListener extends BushListener {
if (!first.executor || first.executor?.bot) return;
if (Math.abs(first.createdAt.getTime() - now.getTime()) > Time.Minute) {
- throw new Error(
- `Time is off by over a minute: ${util.humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`
- );
+ throw new Error(`Time is off by over a minute: ${humanizeDuration(Math.abs(first.createdAt.getTime() - now.getTime()))}`);
}
const { log } = await Moderation.createModLogEntry({
@@ -50,7 +48,7 @@ export default class ModlogSyncUnbanListener extends BushListener {
if (!logChannel) return;
const logEmbed = new EmbedBuilder()
- .setColor(util.colors.Orange)
+ .setColor(colors.Orange)
.setTimestamp()
.setFooter({ text: `CaseID: ${log.id}` })
.setAuthor({
diff --git a/src/listeners/ws/INTERACTION_CREATE.ts b/src/listeners/ws/INTERACTION_CREATE.ts
index 408e7e5..5f479ad 100644
--- a/src/listeners/ws/INTERACTION_CREATE.ts
+++ b/src/listeners/ws/INTERACTION_CREATE.ts
@@ -1,4 +1,4 @@
-import { BushListener, Moderation, PunishmentTypePresent } from '#lib';
+import { BushListener, capitalize, colors, emojis, Moderation, PunishmentTypePresent } from '#lib';
import assert from 'assert';
import {
ActionRowBuilder,
@@ -30,7 +30,7 @@ export default class WsInteractionCreateListener extends BushListener {
});
}
- public override async exec(interaction: APIInteraction) {
+ public async exec(interaction: APIInteraction) {
// console.dir(interaction);
const respond = (
@@ -67,7 +67,7 @@ export default class WsInteractionCreateListener extends BushListener {
return respond({
type: InteractionResponseType.ChannelMessageWithSource,
data: {
- content: `${util.emojis.error} I am no longer in that server.`
+ content: `${emojis.error} I am no longer in that server.`
}
});
@@ -75,7 +75,7 @@ export default class WsInteractionCreateListener extends BushListener {
type: InteractionResponseType.Modal,
data: {
custom_id: `appeal_submit;${punishment};${guildId};${userId};${modlogCase}`,
- title: `${util.capitalize(punishment)} Appeal`,
+ title: `${capitalize(punishment)} Appeal`,
components: [
{
type: ComponentType.ActionRow,
@@ -177,7 +177,7 @@ export default class WsInteractionCreateListener extends BushListener {
return respond({
type: InteractionResponseType.ChannelMessageWithSource,
data: {
- content: `${util.emojis.error} I am no longer in that server.`
+ content: `${emojis.error} I am no longer in that server.`
}
});
@@ -186,7 +186,7 @@ export default class WsInteractionCreateListener extends BushListener {
return respond({
type: InteractionResponseType.ChannelMessageWithSource,
data: {
- content: `${util.emojis.error} ${guild.name} has misconfigured their appeals channel.`
+ content: `${emojis.error} ${guild.name} has misconfigured their appeals channel.`
}
});
@@ -197,8 +197,8 @@ export default class WsInteractionCreateListener extends BushListener {
// const caseId = await ModLog.findOne({ where: { user: userId, guild: guildId, id: modlogCase } });
const embed = new EmbedBuilder()
- .setTitle(`${util.capitalize(punishment)} Appeal`)
- .setColor(util.colors.newBlurple)
+ .setTitle(`${capitalize(punishment)} Appeal`)
+ .setColor(colors.newBlurple)
.setTimestamp()
.setFooter({ text: `CaseID: ${modlogCase}` })
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() })
diff --git a/src/tasks/cpuUsage.ts b/src/tasks/cpuUsage.ts
index e5cfc00..6ce6671 100644
--- a/src/tasks/cpuUsage.ts
+++ b/src/tasks/cpuUsage.ts
@@ -1,5 +1,5 @@
import { BushTask, Time } from '#lib';
-import osu from 'node-os-utils';
+import { cpu } from 'node-os-utils';
export default class CpuUsageTask extends BushTask {
public constructor() {
@@ -9,8 +9,8 @@ export default class CpuUsageTask extends BushTask {
});
}
- public override async exec() {
- const cpu = await osu.cpu.usage(client.stats.cpu === undefined ? 100 * Time.Millisecond : Time.Minute);
- client.stats.cpu = cpu;
+ public async exec() {
+ const cpuStats = await cpu.usage(client.stats.cpu === undefined ? 100 * Time.Millisecond : Time.Minute);
+ client.stats.cpu = cpuStats;
}
}
diff --git a/src/tasks/handleReminders.ts b/src/tasks/handleReminders.ts
index e281903..79693f5 100644
--- a/src/tasks/handleReminders.ts
+++ b/src/tasks/handleReminders.ts
@@ -1,4 +1,4 @@
-import { BushTask, Reminder, Time } from '#lib';
+import { BushTask, dateDelta, format, Reminder, Time } from '#lib';
const { Op } = (await import('sequelize')).default;
export default class HandlerRemindersTask extends BushTask {
@@ -9,7 +9,7 @@ export default class HandlerRemindersTask extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
const expiredEntries = await Reminder.findAll({
where: {
expires: {
@@ -26,9 +26,7 @@ export default class HandlerRemindersTask extends BushTask {
void client.users
.send(
entry.user,
- `The reminder you set ${util.dateDelta(entry.created)} ago has expired: ${util.format.bold(entry.content)}\n${
- entry.messageUrl
- }`
+ `The reminder you set ${dateDelta(entry.created)} ago has expired: ${format.bold(entry.content)}\n${entry.messageUrl}`
)
.catch(() => false);
void entry.update({ notified: true });
diff --git a/src/tasks/removeExpiredPunishements.ts b/src/tasks/removeExpiredPunishements.ts
index 6b36473..3f6f6dd 100644
--- a/src/tasks/removeExpiredPunishements.ts
+++ b/src/tasks/removeExpiredPunishements.ts
@@ -1,4 +1,4 @@
-import { ActivePunishment, ActivePunishmentType, BushTask, Time } from '#lib';
+import { ActivePunishment, ActivePunishmentType, BushTask, resolveNonCachedUser, Time } from '#lib';
import assert from 'assert';
const { Op } = (await import('sequelize')).default;
@@ -10,7 +10,7 @@ export default class RemoveExpiredPunishmentsTask extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
const expiredEntries = await ActivePunishment.findAll({
where: {
expires: {
@@ -31,7 +31,7 @@ export default class RemoveExpiredPunishmentsTask extends BushTask {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
setTimeout(async () => {
const member = guild.members.cache.get(entry.user);
- const user = await util.resolveNonCachedUser(entry.user);
+ const user = await resolveNonCachedUser(entry.user);
assert(guild);
switch (entry.type) {
diff --git a/src/tasks/updateCache.ts b/src/tasks/updateCache.ts
index 3794f76..487b9bc 100644
--- a/src/tasks/updateCache.ts
+++ b/src/tasks/updateCache.ts
@@ -1,7 +1,7 @@
import { Time } from '#constants';
import { Global, Guild, Shared, type BushClient } from '#lib';
+import config from '../../config/options.js';
import { BushTask } from '../lib/extensions/discord-akairo/BushTask.js';
-import config from './../config/options.js';
export default class UpdateCacheTask extends BushTask {
public constructor() {
@@ -11,7 +11,7 @@ export default class UpdateCacheTask extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
await Promise.all([
UpdateCacheTask.#updateGlobalCache(client),
UpdateCacheTask.#updateSharedCache(client),
diff --git a/src/tasks/updateHighlightCache.ts b/src/tasks/updateHighlightCache.ts
index 22289ce..d4fca71 100644
--- a/src/tasks/updateHighlightCache.ts
+++ b/src/tasks/updateHighlightCache.ts
@@ -9,7 +9,7 @@ export default class UpdateHighlightCacheTask extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
return client.highlightManager.syncCache();
}
}
diff --git a/src/tasks/updatePriceItemCache.ts b/src/tasks/updatePriceItemCache.ts
index 6414eb0..e6d2db4 100644
--- a/src/tasks/updatePriceItemCache.ts
+++ b/src/tasks/updatePriceItemCache.ts
@@ -10,7 +10,7 @@ export default class UpdatePriceItemCache extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
//prettier-ignore
const [bazaar, currentLowestBIN, averageLowestBIN, auctionAverages] = (await Promise.all([
got.get('https://api.hypixel.net/skyblock/bazaar').json().catch(() => {}),
diff --git a/src/tasks/updateStats.ts b/src/tasks/updateStats.ts
index f27841f..0e50c23 100644
--- a/src/tasks/updateStats.ts
+++ b/src/tasks/updateStats.ts
@@ -8,7 +8,7 @@ export default class UpdateStatsTask extends BushTask {
});
}
- public override async exec() {
+ public async exec() {
const row =
(await Stat.findByPk(client.config.environment)) ?? (await Stat.create({ environment: client.config.environment }));
row.commandsUsed = client.stats.commandsUsed;
diff --git a/tsconfig.json b/tsconfig.json
index 7e49a42..9046efe 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -27,6 +27,15 @@
"#tags": ["./src/lib/common/tags.js"]
}
},
- "include": ["src/**/*.ts", "src/**/*d.ts", "lib/**/*.ts", "ecosystem.config.cjs", ".eslintrc.cjs"],
+ "include": [
+ "src/**/*.ts",
+ "src/**/*d.ts",
+ "lib/**/*.ts",
+ "ecosystem.config.cjs",
+ ".eslintrc.cjs",
+ "config/**/*.ts",
+ "tests/**/*.ts",
+ "vitest.config.ts"
+ ],
"exclude": ["dist", "node_modules"]
}
diff --git a/yarn.lock b/yarn.lock
index a07ae63..a50ca88 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -373,6 +373,22 @@ __metadata:
languageName: node
linkType: hard
+"@types/chai-subset@npm:^1.3.3":
+ version: 1.3.3
+ resolution: "@types/chai-subset@npm:1.3.3"
+ dependencies:
+ "@types/chai": "*"
+ checksum: 4481da7345022995f5a105e6683744f7203d2c3d19cfe88d8e17274d045722948abf55e0adfd97709e0f043dade37a4d4e98cd4c660e2e8a14f23e6ecf79418f
+ languageName: node
+ linkType: hard
+
+"@types/chai@npm:*, @types/chai@npm:^4.3.1":
+ version: 4.3.1
+ resolution: "@types/chai@npm:4.3.1"
+ checksum: 2ee246b76c469cd620a7a1876a73bc597074361b67d547b4bd96a0c1adb43597ede2d8589ab626192e14349d83cbb646cc11e2c179eeeb43ff11596de94d82c4
+ languageName: node
+ linkType: hard
+
"@types/connect@npm:*":
version: 3.4.35
resolution: "@types/connect@npm:3.4.35"
@@ -409,13 +425,13 @@ __metadata:
linkType: hard
"@types/express-serve-static-core@npm:^4.17.18":
- version: 4.17.28
- resolution: "@types/express-serve-static-core@npm:4.17.28"
+ version: 4.17.29
+ resolution: "@types/express-serve-static-core@npm:4.17.29"
dependencies:
"@types/node": "*"
"@types/qs": "*"
"@types/range-parser": "*"
- checksum: 826489811a5b371c10f02443b4ca894ffc05813bfdf2b60c224f5c18ac9a30a2e518cb9ef9fdfcaa2a1bb17f8bfa4ed1859ccdb252e879c9276271b4ee2df5a9
+ checksum: ec4194dc59276ec6dd906887fc377be0cadf4aaa4d535d9052ab9624937ef2b984a8d9da2c11c96979e21f3d9f78f1da93e767dbcec637f7f13d2e3003151145
languageName: node
linkType: hard
@@ -513,10 +529,17 @@ __metadata:
languageName: node
linkType: hard
-"@types/node@npm:*, @types/node@npm:^17.0.42":
- version: 17.0.42
- resolution: "@types/node@npm:17.0.42"
- checksum: a200cd87e4f12d4d5682a893ad6e1140720c6c074a2cd075f254b3b8306d6174f5a3630e5d2347efb5e9b80d420404b5fafc8fe3c7d4c81998cd914c50b19f75
+"@types/node@npm:*":
+ version: 18.0.0
+ resolution: "@types/node@npm:18.0.0"
+ checksum: aab2b325727a2599f6d25ebe0dedf58c40fb66a51ce4ca9c0226ceb70fcda2d3afccdca29db5942eb48b158ee8585a274a1e3750c718bbd5399d7f41d62dfdcc
+ languageName: node
+ linkType: hard
+
+"@types/node@npm:^17.0.42":
+ version: 17.0.45
+ resolution: "@types/node@npm:17.0.45"
+ checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8
languageName: node
linkType: hard
@@ -911,6 +934,13 @@ __metadata:
languageName: node
linkType: hard
+"assertion-error@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "assertion-error@npm:1.1.0"
+ checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf
+ languageName: node
+ linkType: hard
+
"balanced-match@npm:^1.0.0":
version: 1.0.2
resolution: "balanced-match@npm:1.0.2"
@@ -1082,6 +1112,7 @@ __metadata:
sequelize: 6.20.1
tinycolor2: ^1.4.2
typescript: ^4.7.3
+ vitest: ^0.14.2
vm2: ^3.9.9
languageName: unknown
linkType: soft
@@ -1163,6 +1194,21 @@ __metadata:
languageName: node
linkType: hard
+"chai@npm:^4.3.6":
+ version: 4.3.6
+ resolution: "chai@npm:4.3.6"
+ dependencies:
+ assertion-error: ^1.1.0
+ check-error: ^1.0.2
+ deep-eql: ^3.0.1
+ get-func-name: ^2.0.0
+ loupe: ^2.3.1
+ pathval: ^1.1.1
+ type-detect: ^4.0.5
+ checksum: acff93fd537f96d4a4d62dd83810285dffcfccb5089e1bf2a1205b28ec82d93dff551368722893cf85004282df10ee68802737c33c90c5493957ed449ed7ce71
+ languageName: node
+ linkType: hard
+
"chalk@npm:^4.0.0":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
@@ -1180,6 +1226,13 @@ __metadata:
languageName: node
linkType: hard
+"check-error@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "check-error@npm:1.0.2"
+ checksum: d9d106504404b8addd1ee3f63f8c0eaa7cd962a1a28eb9c519b1c4a1dc7098be38007fc0060f045ee00f075fbb7a2a4f42abcf61d68323677e11ab98dc16042e
+ languageName: node
+ linkType: hard
+
"chownr@npm:^2.0.0":
version: 2.0.0
resolution: "chownr@npm:2.0.0"
@@ -1427,6 +1480,15 @@ __metadata:
languageName: node
linkType: hard
+"deep-eql@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "deep-eql@npm:3.0.1"
+ dependencies:
+ type-detect: ^4.0.0
+ checksum: 4f4c9fb79eb994fb6e81d4aa8b063adc40c00f831588aa65e20857d5d52f15fb23034a6576ecf886f7ff6222d5ae42e71e9b7d57113e0715b1df7ea1e812b125
+ languageName: node
+ linkType: hard
+
"deep-is@npm:^0.1.3":
version: 0.1.4
resolution: "deep-is@npm:0.1.4"
@@ -1489,9 +1551,9 @@ __metadata:
linkType: hard
"discord-akairo@npm:@notenoughupdates/discord-akairo@dev":
- version: 9.1.3-dev.1655212954.1d6b00f
- resolution: "@notenoughupdates/discord-akairo@npm:9.1.3-dev.1655212954.1d6b00f"
- checksum: 0d17ecd941d594723dd1d82f75bf48a007c030798466400d47d88352766d46b25ed310fb5b946da363cd7b6d84727cf65ea1035883caf4ed35f25dbd7e8d30e4
+ version: 9.1.3-dev.1655341685.1230a9d
+ resolution: "@notenoughupdates/discord-akairo@npm:9.1.3-dev.1655341685.1230a9d"
+ checksum: 4bd037175eb8eeb129e27dd6d52e3c60bdf918a024e28adcefd27d3bd0ad2d9b503f70c87b4fd03a08ee5c2bf8f9b44dd87ab1d6e2cae5d4bff76fcb151dad70
languageName: node
linkType: hard
@@ -1510,8 +1572,8 @@ __metadata:
linkType: hard
"discord.js@npm:@notenoughupdates/discord.js@dev":
- version: 14.0.0-dev.1655126646-6dfc4f06d
- resolution: "@notenoughupdates/discord.js@npm:14.0.0-dev.1655126646-6dfc4f06d"
+ version: 14.0.0-dev.1655248959-627886d
+ resolution: "@notenoughupdates/discord.js@npm:14.0.0-dev.1655248959-627886d"
dependencies:
"@discordjs/builders": ^0.16.0-dev
"@discordjs/collection": ^0.8.0-dev
@@ -1524,7 +1586,7 @@ __metadata:
tslib: ^2.4.0
undici: ^5.4.0
ws: ^8.8.0
- checksum: ad0e12b2c99232a7e5b8f728b0a29c61832e5ad9507b5fa24835a593b7ba0639107d16eb15d4354bd20296127331af4fdfe0617640224b8433f775cfd126cf63
+ checksum: e5450f82918cfb9f558ab9fd8aad93b4e9120af26600a3301601f93c89563773143d2960373a5ef299e59c6a6c08ab221267409ce8f9a48078d908b0ac443e38
languageName: node
linkType: hard
@@ -1652,6 +1714,217 @@ __metadata:
languageName: node
linkType: hard
+"esbuild-android-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-android-64@npm:0.14.44"
+ conditions: os=android & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-android-arm64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-android-arm64@npm:0.14.44"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"esbuild-darwin-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-darwin-64@npm:0.14.44"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-darwin-arm64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-darwin-arm64@npm:0.14.44"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"esbuild-freebsd-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-freebsd-64@npm:0.14.44"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-freebsd-arm64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-freebsd-arm64@npm:0.14.44"
+ conditions: os=freebsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-32@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-32@npm:0.14.44"
+ conditions: os=linux & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-64@npm:0.14.44"
+ conditions: os=linux & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-arm64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-arm64@npm:0.14.44"
+ conditions: os=linux & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-arm@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-arm@npm:0.14.44"
+ conditions: os=linux & cpu=arm
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-mips64le@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-mips64le@npm:0.14.44"
+ conditions: os=linux & cpu=mips64el
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-ppc64le@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-ppc64le@npm:0.14.44"
+ conditions: os=linux & cpu=ppc64
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-riscv64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-riscv64@npm:0.14.44"
+ conditions: os=linux & cpu=riscv64
+ languageName: node
+ linkType: hard
+
+"esbuild-linux-s390x@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-linux-s390x@npm:0.14.44"
+ conditions: os=linux & cpu=s390x
+ languageName: node
+ linkType: hard
+
+"esbuild-netbsd-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-netbsd-64@npm:0.14.44"
+ conditions: os=netbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-openbsd-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-openbsd-64@npm:0.14.44"
+ conditions: os=openbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-sunos-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-sunos-64@npm:0.14.44"
+ conditions: os=sunos & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-windows-32@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-windows-32@npm:0.14.44"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"esbuild-windows-64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-windows-64@npm:0.14.44"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
+"esbuild-windows-arm64@npm:0.14.44":
+ version: 0.14.44
+ resolution: "esbuild-windows-arm64@npm:0.14.44"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"esbuild@npm:^0.14.27":
+ version: 0.14.44
+ resolution: "esbuild@npm:0.14.44"
+ dependencies:
+ esbuild-android-64: 0.14.44
+ esbuild-android-arm64: 0.14.44
+ esbuild-darwin-64: 0.14.44
+ esbuild-darwin-arm64: 0.14.44
+ esbuild-freebsd-64: 0.14.44
+ esbuild-freebsd-arm64: 0.14.44
+ esbuild-linux-32: 0.14.44
+ esbuild-linux-64: 0.14.44
+ esbuild-linux-arm: 0.14.44
+ esbuild-linux-arm64: 0.14.44
+ esbuild-linux-mips64le: 0.14.44
+ esbuild-linux-ppc64le: 0.14.44
+ esbuild-linux-riscv64: 0.14.44
+ esbuild-linux-s390x: 0.14.44
+ esbuild-netbsd-64: 0.14.44
+ esbuild-openbsd-64: 0.14.44
+ esbuild-sunos-64: 0.14.44
+ esbuild-windows-32: 0.14.44
+ esbuild-windows-64: 0.14.44
+ esbuild-windows-arm64: 0.14.44
+ dependenciesMeta:
+ esbuild-android-64:
+ optional: true
+ esbuild-android-arm64:
+ optional: true
+ esbuild-darwin-64:
+ optional: true
+ esbuild-darwin-arm64:
+ optional: true
+ esbuild-freebsd-64:
+ optional: true
+ esbuild-freebsd-arm64:
+ optional: true
+ esbuild-linux-32:
+ optional: true
+ esbuild-linux-64:
+ optional: true
+ esbuild-linux-arm:
+ optional: true
+ esbuild-linux-arm64:
+ optional: true
+ esbuild-linux-mips64le:
+ optional: true
+ esbuild-linux-ppc64le:
+ optional: true
+ esbuild-linux-riscv64:
+ optional: true
+ esbuild-linux-s390x:
+ optional: true
+ esbuild-netbsd-64:
+ optional: true
+ esbuild-openbsd-64:
+ optional: true
+ esbuild-sunos-64:
+ optional: true
+ esbuild-windows-32:
+ optional: true
+ esbuild-windows-64:
+ optional: true
+ esbuild-windows-arm64:
+ optional: true
+ bin:
+ esbuild: bin/esbuild
+ checksum: e6f41e22c0a005c3785e123f8d41d7f84421f4ae6fa259f95d6b2449922787bede46d23682d7758c12bd4d7af04d21f0e4eb0291409814f8726fe7db77973354
+ languageName: node
+ linkType: hard
+
"escape-latex@npm:^1.2.0":
version: 1.2.0
resolution: "escape-latex@npm:1.2.0"
@@ -2083,6 +2356,25 @@ __metadata:
languageName: node
linkType: hard
+"fsevents@npm:~2.3.2":
+ version: 2.3.2
+ resolution: "fsevents@npm:2.3.2"
+ dependencies:
+ node-gyp: latest
+ checksum: 97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f
+ conditions: os=darwin
+ languageName: node
+ linkType: hard
+
+"fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>":
+ version: 2.3.2
+ resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=18f3a7"
+ dependencies:
+ node-gyp: latest
+ conditions: os=darwin
+ languageName: node
+ linkType: hard
+
"function-bind@npm:^1.1.1":
version: 1.1.1
resolution: "function-bind@npm:1.1.1"
@@ -2192,6 +2484,13 @@ __metadata:
languageName: node
linkType: hard
+"get-func-name@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "get-func-name@npm:2.0.0"
+ checksum: 8d82e69f3e7fab9e27c547945dfe5cc0c57fc0adf08ce135dddb01081d75684a03e7a0487466f478872b341d52ac763ae49e660d01ab83741f74932085f693c3
+ languageName: node
+ linkType: hard
+
"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.0, get-intrinsic@npm:^1.1.1":
version: 1.1.2
resolution: "get-intrinsic@npm:1.1.2"
@@ -2907,6 +3206,13 @@ __metadata:
languageName: node
linkType: hard
+"local-pkg@npm:^0.4.1":
+ version: 0.4.1
+ resolution: "local-pkg@npm:0.4.1"
+ checksum: 4ab3b4853ffbc3b292a3ae2e22618dbc348418a2ebf60ada55fdcc5a8583f9167c89fc7977194ffa39d0a4c5078f9c421d246afdd252fea7a840f7a8f3b5f96b
+ languageName: node
+ linkType: hard
+
"localforage@npm:^1.8.1":
version: 1.10.0
resolution: "localforage@npm:1.10.0"
@@ -2947,6 +3253,15 @@ __metadata:
languageName: node
linkType: hard
+"loupe@npm:^2.3.1":
+ version: 2.3.4
+ resolution: "loupe@npm:2.3.4"
+ dependencies:
+ get-func-name: ^2.0.0
+ checksum: 5af91db61aa18530f1749a64735ee194ac263e65e9f4d1562bf3036c591f1baa948289c193e0e34c7b5e2c1b75d3c1dc4fce87f5edb3cee10b0c0df46bc9ffb3
+ languageName: node
+ linkType: hard
+
"lowercase-keys@npm:^2.0.0":
version: 2.0.0
resolution: "lowercase-keys@npm:2.0.0"
@@ -3243,6 +3558,15 @@ __metadata:
languageName: node
linkType: hard
+"nanoid@npm:^3.3.4":
+ version: 3.3.4
+ resolution: "nanoid@npm:3.3.4"
+ bin:
+ nanoid: bin/nanoid.cjs
+ checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c
+ languageName: node
+ linkType: hard
+
"nanoid@npm:^4.0.0":
version: 4.0.0
resolution: "nanoid@npm:4.0.0"
@@ -3563,6 +3887,13 @@ __metadata:
languageName: node
linkType: hard
+"pathval@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "pathval@npm:1.1.1"
+ checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6
+ languageName: node
+ linkType: hard
+
"pend@npm:~1.2.0":
version: 1.2.0
resolution: "pend@npm:1.2.0"
@@ -3651,6 +3982,13 @@ __metadata:
languageName: node
linkType: hard
+"picocolors@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "picocolors@npm:1.0.0"
+ checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981
+ languageName: node
+ linkType: hard
+
"picomatch@npm:^2.3.1":
version: 2.3.1
resolution: "picomatch@npm:2.3.1"
@@ -3688,6 +4026,17 @@ __metadata:
languageName: node
linkType: hard
+"postcss@npm:^8.4.13":
+ version: 8.4.14
+ resolution: "postcss@npm:8.4.14"
+ dependencies:
+ nanoid: ^3.3.4
+ picocolors: ^1.0.0
+ source-map-js: ^1.0.2
+ checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816
+ languageName: node
+ linkType: hard
+
"postgres-array@npm:~2.0.0":
version: 2.0.0
resolution: "postgres-array@npm:2.0.0"
@@ -3944,6 +4293,20 @@ __metadata:
languageName: node
linkType: hard
+"rollup@npm:^2.59.0":
+ version: 2.75.6
+ resolution: "rollup@npm:2.75.6"
+ dependencies:
+ fsevents: ~2.3.2
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ bin:
+ rollup: dist/bin/rollup
+ checksum: df83c6d43a144a296daf82bed7f12f2dfcc6c495a64245e840d15fd21f2ab8b66bb3423e61c974875b33ccf53fb659d2ed099f272937ecf23af48815277c6cd5
+ languageName: node
+ linkType: hard
+
"run-parallel@npm:^1.1.9":
version: 1.2.0
resolution: "run-parallel@npm:1.2.0"
@@ -4171,6 +4534,13 @@ __metadata:
languageName: node
linkType: hard
+"source-map-js@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "source-map-js@npm:1.0.2"
+ checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c
+ languageName: node
+ linkType: hard
+
"split2@npm:^4.1.0":
version: 4.1.0
resolution: "split2@npm:4.1.0"
@@ -4350,6 +4720,20 @@ __metadata:
languageName: node
linkType: hard
+"tinypool@npm:^0.1.3":
+ version: 0.1.3
+ resolution: "tinypool@npm:0.1.3"
+ checksum: 13ac687a23c03b02c2bf0b9711a3bb191d2c37941775a001b9617aac541c11ba144fb08de74f3f9723ec2649410f5d4fa7f0398fedd462b39fe3b30d19615ad8
+ languageName: node
+ linkType: hard
+
+"tinyspy@npm:^0.3.2":
+ version: 0.3.3
+ resolution: "tinyspy@npm:0.3.3"
+ checksum: 1beb8f04c100d9ac769ff85266594f07d6f08f41cfb95c4bef9da3e59988b42e8d4e66c2ec455d3ecad80027347920e87d7a7098c5a2a28637f9fee25e11a8f1
+ languageName: node
+ linkType: hard
+
"to-buffer@npm:^1.1.1":
version: 1.1.1
resolution: "to-buffer@npm:1.1.1"
@@ -4433,6 +4817,13 @@ __metadata:
languageName: node
linkType: hard
+"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5":
+ version: 4.0.8
+ resolution: "type-detect@npm:4.0.8"
+ checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15
+ languageName: node
+ linkType: hard
+
"type-fest@npm:^0.20.2":
version: 0.20.2
resolution: "type-fest@npm:0.20.2"
@@ -4567,6 +4958,67 @@ __metadata:
languageName: node
linkType: hard
+"vite@npm:^2.9.9":
+ version: 2.9.12
+ resolution: "vite@npm:2.9.12"
+ dependencies:
+ esbuild: ^0.14.27
+ fsevents: ~2.3.2
+ postcss: ^8.4.13
+ resolve: ^1.22.0
+ rollup: ^2.59.0
+ peerDependencies:
+ less: "*"
+ sass: "*"
+ stylus: "*"
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ peerDependenciesMeta:
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ bin:
+ vite: bin/vite.js
+ checksum: 33cf8b6bfbbcae4b7f856d739ae519bed6b1ce23fc652ca98db1d4878bf35424885951c13e0d2536248423a0836d91ef7cae744ff40cbcbd6e7ffe495bd15ea5
+ languageName: node
+ linkType: hard
+
+"vitest@npm:^0.14.2":
+ version: 0.14.2
+ resolution: "vitest@npm:0.14.2"
+ dependencies:
+ "@types/chai": ^4.3.1
+ "@types/chai-subset": ^1.3.3
+ chai: ^4.3.6
+ debug: ^4.3.4
+ local-pkg: ^0.4.1
+ tinypool: ^0.1.3
+ tinyspy: ^0.3.2
+ vite: ^2.9.9
+ peerDependencies:
+ "@vitest/ui": "*"
+ c8: "*"
+ happy-dom: "*"
+ jsdom: "*"
+ peerDependenciesMeta:
+ "@vitest/ui":
+ optional: true
+ c8:
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+ bin:
+ vitest: vitest.mjs
+ checksum: 9678822b0ccc4b31f93e4454972177df85b9857355affbc2e9f3b8f54507d0f9500783c3788c9f39681718a59f5a5bd7848bc7198a2a906a0a28d9328a2bb9cb
+ languageName: node
+ linkType: hard
+
"vm2@npm:^3.9.9":
version: 3.9.9
resolution: "vm2@npm:3.9.9"