aboutsummaryrefslogtreecommitdiff
path: root/src/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils')
-rw-r--r--src/lib/utils/AllowedMentions.ts68
-rw-r--r--src/lib/utils/BushCache.ts26
-rw-r--r--src/lib/utils/BushClientUtils.ts498
-rw-r--r--src/lib/utils/BushConstants.ts531
-rw-r--r--src/lib/utils/BushLogger.ts315
-rw-r--r--src/lib/utils/BushUtils.ts612
-rw-r--r--src/lib/utils/CanvasProgressBar.ts83
7 files changed, 0 insertions, 2133 deletions
diff --git a/src/lib/utils/AllowedMentions.ts b/src/lib/utils/AllowedMentions.ts
deleted file mode 100644
index d2eb030..0000000
--- a/src/lib/utils/AllowedMentions.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { type MessageMentionOptions, type MessageMentionTypes } from 'discord.js';
-
-/**
- * A utility class for creating allowed mentions.
- */
-export class AllowedMentions {
- /**
- * @param everyone Whether everyone and here should be mentioned.
- * @param roles Whether roles should be mentioned.
- * @param users Whether users should be mentioned.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public constructor(public everyone = false, public roles = false, public users = true, public repliedUser = true) {}
-
- /**
- * Don't mention anyone.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public static none(repliedUser = true): MessageMentionOptions {
- return { parse: [], repliedUser };
- }
-
- /**
- * Mention @everyone and @here, roles, and users.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public static all(repliedUser = true): MessageMentionOptions {
- return { parse: ['everyone', 'roles', 'users'], repliedUser };
- }
-
- /**
- * Mention users.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public static users(repliedUser = true): MessageMentionOptions {
- return { parse: ['users'], repliedUser };
- }
-
- /**
- * Mention everyone and here.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public static everyone(repliedUser = true): MessageMentionOptions {
- return { parse: ['everyone'], repliedUser };
- }
-
- /**
- * Mention roles.
- * @param repliedUser Whether the author of the Message being replied to should be mentioned.
- */
- public static roles(repliedUser = true): MessageMentionOptions {
- return { parse: ['roles'], repliedUser };
- }
-
- /**
- * Converts this into a MessageMentionOptions object.
- */
- public toObject(): MessageMentionOptions {
- return {
- parse: [
- ...(this.users ? ['users'] : []),
- ...(this.roles ? ['roles'] : []),
- ...(this.everyone ? ['everyone'] : [])
- ] as MessageMentionTypes[],
- repliedUser: this.repliedUser
- };
- }
-}
diff --git a/src/lib/utils/BushCache.ts b/src/lib/utils/BushCache.ts
deleted file mode 100644
index 22a13ef..0000000
--- a/src/lib/utils/BushCache.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { BadWords, GlobalModel, SharedModel, type Guild } from '#lib';
-import { Collection, type Snowflake } from 'discord.js';
-
-export class BushCache {
- public global = new GlobalCache();
- public shared = new SharedCache();
- public guilds = new GuildCache();
-}
-
-export class GlobalCache implements Omit<GlobalModel, 'environment'> {
- public disabledCommands: string[] = [];
- public blacklistedChannels: Snowflake[] = [];
- public blacklistedGuilds: Snowflake[] = [];
- public blacklistedUsers: Snowflake[] = [];
-}
-
-export class SharedCache implements Omit<SharedModel, 'primaryKey'> {
- public superUsers: Snowflake[] = [];
- public privilegedUsers: Snowflake[] = [];
- public badLinksSecret: string[] = [];
- public badLinks: string[] = [];
- public badWords: BadWords = {};
- public autoBanCode: string | null = null;
-}
-
-export class GuildCache extends Collection<Snowflake, Guild> {}
diff --git a/src/lib/utils/BushClientUtils.ts b/src/lib/utils/BushClientUtils.ts
deleted file mode 100644
index 920ff40..0000000
--- a/src/lib/utils/BushClientUtils.ts
+++ /dev/null
@@ -1,498 +0,0 @@
-import assert from 'assert/strict';
-import {
- cleanCodeBlockContent,
- DMChannel,
- escapeCodeBlock,
- GuildMember,
- Message,
- PartialDMChannel,
- Routes,
- TextBasedChannel,
- ThreadMember,
- User,
- type APIMessage,
- type Client,
- type Snowflake,
- type UserResolvable
-} from 'discord.js';
-import got from 'got';
-import _ from 'lodash';
-import { ConfigChannelKey } from '../../../config/Config.js';
-import CommandErrorListener from '../../listeners/commands/commandError.js';
-import { BushInspectOptions } from '../common/typings/BushInspectOptions.js';
-import { CodeBlockLang } from '../common/typings/CodeBlockLang.js';
-import { CommandMessage } from '../extensions/discord-akairo/BushCommand.js';
-import { SlashMessage } from '../extensions/discord-akairo/SlashMessage.js';
-import { Global } from '../models/shared/Global.js';
-import { Shared } from '../models/shared/Shared.js';
-import { GlobalCache, SharedCache } from './BushCache.js';
-import { emojis, Pronoun, PronounCode, pronounMapping, regex } from './BushConstants.js';
-import { addOrRemoveFromArray, formatError, inspect } from './BushUtils.js';
-
-/**
- * Utilities that require access to the client.
- */
-export class BushClientUtils {
- /**
- * 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'
- ];
-
- public constructor(private readonly client: 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) => this.client.users.fetch(id)));
- }
-
- /**
- * 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 this.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 this.client.users.fetch(text as Snowflake);
- } catch {}
- }
- const mentionReg = /<@!?(?<id>\d{17,19})>/;
- const mentionMatch = text.match(mentionReg);
- if (mentionMatch) {
- try {
- return await this.client.users.fetch(mentionMatch.groups!.id as Snowflake);
- } catch {}
- }
- const user = this.client.users.cache.find((u) => u.username === text);
- if (user) return user;
- return null;
- }
-
- /**
- * 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 = 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}` : ''}`
- : `${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 this.client.console.warn(`codeblockError`, `Required Length: ${length}. Actual Length: ${code3.length}`, true);
- void this.client.console.warn(`codeblockError`, code3, true);
- throw new Error('code too long');
- }
- return code3;
- }
-
- /**
- * 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 {
- return (
- {
- token: 'Main Token',
- devToken: 'Dev Token',
- betaToken: 'Beta Token',
- hypixelApiKey: 'Hypixel Api Key',
- wolframAlphaAppId: 'Wolfram|Alpha App ID',
- dbPassword: 'Database Password'
- }[key] ?? 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 { ...this.client.config.credentials, dbPassword: this.client.config.db.password }) {
- const credential = { ...this.client.config.credentials, dbPassword: this.client.config.db.password }[
- credentialName as keyof typeof this.client.config.credentials
- ];
- if (credential === null || credential === '') continue;
- 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;
- }
-
- /**
- * 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 = inspect(input, inspectOptions ?? undefined);
- if (inspectOptions) inspectOptions.inspectStrings = undefined;
- input = 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 = 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 = inspect(input, inspectOptions ?? undefined);
- return this.redact(input);
- }
-
- /**
- * 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 ? this.client.cache.global[key] : this.client.cache.global;
- }
-
- /**
- * Get the shared cache.
- */
- public getShared(): SharedCache;
- /**
- * Get a key from the shared cache.
- * @param key The key to get in the shared cache.
- */
- public getShared<K extends keyof SharedCache>(key: K): SharedCache[K];
- public getShared(key?: keyof SharedCache) {
- return key ? this.client.cache.shared[key] : this.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 Client['cache']['global']>(
- action: 'add' | 'remove',
- key: K,
- value: Client['cache']['global'][K][0]
- ): Promise<Global | void> {
- const row =
- (await Global.findByPk(this.client.config.environment)) ??
- (await Global.create({ environment: this.client.config.environment }));
- const oldValue: any[] = row[key];
- const newValue = addOrRemoveFromArray(action, oldValue, value);
- row[key] = newValue;
- this.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 Client['cache']['shared'], 'badWords' | 'autoBanCode'>>(
- action: 'add' | 'remove',
- key: K,
- value: 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;
- this.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 Client['cache']['global']>(
- key: K,
- value: Client['cache']['global'][K]
- ): Promise<Global | void> {
- const row =
- (await Global.findByPk(this.client.config.environment)) ??
- (await Global.create({ environment: this.client.config.environment }));
- row[key] = value;
- this.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 Client['cache']['shared'], 'badWords' | 'autoBanCode'>>(
- key: K,
- value: Client['cache']['shared'][K]
- ): Promise<Shared | void> {
- const row = (await Shared.findByPk(0)) ?? (await Shared.create());
- row[key] = value;
- this.client.cache.shared[key] = value;
- return await row.save().catch((e) => this.handleError('setShared', e));
- }
-
- /**
- * 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 this.client.console.error(_.camelCase(context), `An error occurred:\n${formatError(error, false)}`, false);
- await this.client.console.channelError({
- embeds: await CommandErrorListener.generateErrorEmbed(this.client, { 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 this.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 pronounMapping[apiRes.pronouns!]!;
- }
-
- /**
- * 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;
- }
-
- /**
- * 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
- ? '/'
- : this.client.config.isDevelopment
- ? 'dev '
- : message.util.parsed?.prefix ?? this.client.config.prefix;
- }
-
- public async 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;
- }
-
- 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 = this.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 this.client.rest
- .get(Routes.channelMessage(channel_id, message_id))
- .catch(() => null)) as APIMessage | null;
- if (!message) continue;
-
- res.push(message);
- }
-
- return res;
- }
-
- /**
- * Resolves a channel from the config and ensures it is a non-dm-based-text-channel.
- * @param channel The channel to retrieve.
- */
- public async getConfigChannel(
- channel: ConfigChannelKey
- ): Promise<Exclude<TextBasedChannel, DMChannel | PartialDMChannel> | null> {
- const channels = this.client.config.channels;
- if (!(channel in channels))
- throw new TypeError(`Invalid channel provided (${channel}), must be one of ${Object.keys(channels).join(' ')}`);
-
- const channelId = channels[channel];
- if (channelId === '') return null;
-
- const res = await this.client.channels.fetch(channelId);
-
- if (!res?.isTextBased() || res.isDMBased()) return null;
-
- return res;
- }
-}
-
-interface HastebinRes {
- key: string;
-}
-
-export interface HasteResults {
- url?: string;
- error?: 'content too long' | 'substr' | 'unable to post';
-}
-
-export interface MessageLinkParts {
- guild_id: Snowflake;
- channel_id: Snowflake;
- message_id: Snowflake;
-}
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
deleted file mode 100644
index 090616c..0000000
--- a/src/lib/utils/BushConstants.ts
+++ /dev/null
@@ -1,531 +0,0 @@
-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';
-
-const rawCapeUrl = 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/';
-
-/**
- * Time units in milliseconds
- */
-export const enum Time {
- /**
- * One millisecond (1 ms).
- */
- Millisecond = 1,
-
- /**
- * One second (1,000 ms).
- */
- Second = Millisecond * 1000,
-
- /**
- * One minute (60,000 ms).
- */
- Minute = Second * 60,
-
- /**
- * One hour (3,600,000 ms).
- */
- Hour = Minute * 60,
-
- /**
- * One day (86,400,000 ms).
- */
- Day = Hour * 24,
-
- /**
- * One week (604,800,000 ms).
- */
- Week = Day * 7,
-
- /**
- * One month (2,629,800,000 ms).
- */
- Month = Day * 30.4375, // average of days in a month (including leap years)
-
- /**
- * One year (31,557,600,000 ms).
- */
- Year = Day * 365.25 // average with leap years
-}
-
-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
- */
- /** **This has the global flag, make sure to handle it correctly.** */
- messageLink:
- /<?https:\/\/(?: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 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);
-
-/**
- * A bunch of mappings
- */
-export const mappings = deepLock({
- guilds: {
- "Moulberry's Bush": '516977525906341928',
- "Moulberry's Tree": '767448775450820639',
- 'MB Staff': '784597260465995796',
- "IRONM00N's Space Ship": '717176538717749358'
- },
-
- channels: {
- 'neu-support': '714332750156660756',
- 'giveaways': '767782084981817344'
- },
-
- users: {
- IRONM00N: '322862723090219008',
- Moulberry: '211288288055525376',
- nopo: '384620942577369088',
- Bestower: '496409778822709251'
- },
-
- 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 },
- MORE_EMOJIS: { name: 'More Emoji', important: true, emoji: '<:moreEmoji:850786853497602080>', weight: 3 },
- [GuildFeature.Featurable]: { name: 'Featurable', important: true, emoji: '<:featurable:850786776372084756>', weight: 4 },
- [GuildFeature.RelayEnabled]: { name: 'Relay Enabled', important: true, emoji: '<:relayEnabled:850790531441229834>', weight: 5 },
- [GuildFeature.Discoverable]: { name: 'Discoverable', important: true, emoji: '<:discoverable:850786735360966656>', weight: 6 },
- ENABLED_DISCOVERABLE_BEFORE: { name: 'Enabled Discovery Before', important: false, emoji: '<:enabledDiscoverableBefore:850786754670624828>', weight: 7 },
- [GuildFeature.MonetizationEnabled]: { name: 'Monetization Enabled', important: true, emoji: null, weight: 8 },
- [GuildFeature.TicketedEventsEnabled]: { name: 'Ticketed Events Enabled', important: true, emoji: null, weight: 9 },
- [GuildFeature.PreviewEnabled]: { name: 'Preview Enabled', important: true, emoji: '<:previewEnabled:850790508266913823>', weight: 10 },
- COMMERCE: { name: 'Store Channels', important: true, emoji: '<:storeChannels:850786692432396338>', weight: 11 },
- [GuildFeature.VanityURL]: { name: 'Vanity URL', important: false, emoji: '<:vanityURL:850790553079644160>', weight: 12 },
- [GuildFeature.VIPRegions]: { name: 'VIP Regions', important: false, emoji: '<:VIPRegions:850794697496854538>', weight: 13 },
- [GuildFeature.AnimatedIcon]: { name: 'Animated Icon', important: false, emoji: '<:animatedIcon:850774498071412746>', weight: 14 },
- [GuildFeature.Banner]: { name: 'Banner', important: false, emoji: '<:banner:850786673150787614>', weight: 15 },
- [GuildFeature.InviteSplash]: { name: 'Invite Splash', important: false, emoji: '<:inviteSplash:850786798246559754>', weight: 16 },
- [GuildFeature.PrivateThreads]: { name: 'Private Threads', important: false, emoji: '<:privateThreads:869763711894700093>', weight: 17 },
- THREE_DAY_THREAD_ARCHIVE: { name: 'Three Day Thread Archive', important: false, emoji: '<:threeDayThreadArchive:869767841652564008>', weight: 19 },
- SEVEN_DAY_THREAD_ARCHIVE: { name: 'Seven Day Thread Archive', important: false, emoji: '<:sevenDayThreadArchive:869767896123998288>', weight: 20 },
- [GuildFeature.RoleIcons]: { name: 'Role Icons', important: false, emoji: '<:roleIcons:876993381929222175>', weight: 21 },
- [GuildFeature.News]: { name: 'Announcement Channels', important: false, emoji: '<:announcementChannels:850790491796013067>', weight: 22 },
- [GuildFeature.MemberVerificationGateEnabled]: { name: 'Membership Verification Gate', important: false, emoji: '<:memberVerificationGateEnabled:850786829984858212>', weight: 23 },
- [GuildFeature.WelcomeScreenEnabled]: { name: 'Welcome Screen Enabled', important: false, emoji: '<:welcomeScreenEnabled:850790575875817504>', weight: 24 },
- [GuildFeature.Community]: { name: 'Community', important: false, emoji: '<:community:850786714271875094>', weight: 25 },
- THREADS_ENABLED: {name: 'Threads Enabled', important: false, emoji: '<:threadsEnabled:869756035345317919>', weight: 26 },
- THREADS_ENABLED_TESTING: {name: 'Threads Enabled Testing', important: false, emoji: null, weight: 27 },
- [GuildFeature.AnimatedBanner]: { name: 'Animated Banner', important: false, emoji: null, weight: 28 },
- [GuildFeature.HasDirectoryEntry]: { name: 'Has Directory Entry', important: true, emoji: null, weight: 29 },
- [GuildFeature.Hub]: { name: 'Hub', important: true, emoji: null, weight: 30 },
- [GuildFeature.LinkedToHub]: { name: 'Linked To Hub', important: true, 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>',
- Bot: '<:bot:1006929813203853427>',
- 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:8487429478264