aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-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/lib/utils/Config.ts93
22 files changed, 2219 insertions, 2493 deletions
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.
- */
<