aboutsummaryrefslogtreecommitdiff
path: root/src/lib/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/extensions')
-rw-r--r--src/lib/extensions/discord-akairo/BushArgumentTypeCaster.ts3
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts586
-rw-r--r--src/lib/extensions/discord-akairo/BushCommand.ts586
-rw-r--r--src/lib/extensions/discord-akairo/BushCommandHandler.ts37
-rw-r--r--src/lib/extensions/discord-akairo/BushInhibitor.ts19
-rw-r--r--src/lib/extensions/discord-akairo/BushInhibitorHandler.ts3
-rw-r--r--src/lib/extensions/discord-akairo/BushListener.ts3
-rw-r--r--src/lib/extensions/discord-akairo/BushListenerHandler.ts3
-rw-r--r--src/lib/extensions/discord-akairo/BushTask.ts3
-rw-r--r--src/lib/extensions/discord-akairo/BushTaskHandler.ts3
-rw-r--r--src/lib/extensions/discord-akairo/SlashMessage.ts3
-rw-r--r--src/lib/extensions/discord.js/BushClientEvents.ts200
-rw-r--r--src/lib/extensions/discord.js/ExtendedGuild.ts916
-rw-r--r--src/lib/extensions/discord.js/ExtendedGuildMember.ts1255
-rw-r--r--src/lib/extensions/discord.js/ExtendedMessage.ts12
-rw-r--r--src/lib/extensions/discord.js/ExtendedUser.ts35
-rw-r--r--src/lib/extensions/global.ts13
17 files changed, 0 insertions, 3680 deletions
diff --git a/src/lib/extensions/discord-akairo/BushArgumentTypeCaster.ts b/src/lib/extensions/discord-akairo/BushArgumentTypeCaster.ts
deleted file mode 100644
index def7ad6..0000000
--- a/src/lib/extensions/discord-akairo/BushArgumentTypeCaster.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { type CommandMessage } from '#lib';
-
-export type BushArgumentTypeCaster<R = unknown> = (message: CommandMessage, phrase: string) => R;
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
deleted file mode 100644
index 9ca02a2..0000000
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ /dev/null
@@ -1,586 +0,0 @@
-import {
- abbreviatedNumber,
- contentWithDuration,
- discordEmoji,
- duration,
- durationSeconds,
- globalUser,
- messageLink,
- permission,
- roleWithDuration,
- snowflake
-} from '#args';
-import { BushClientEvents, emojis, formatError, inspect } from '#lib';
-import { patch, type PatchedElements } from '@notenoughupdates/events-intercept';
-import * as Sentry from '@sentry/node';
-import {
- AkairoClient,
- ArgumentTypeCaster,
- ContextMenuCommandHandler,
- version as akairoVersion,
- type ArgumentPromptData,
- type OtherwiseContentSupplier
-} from 'discord-akairo';
-import {
- ActivityType,
- GatewayIntentBits,
- MessagePayload,
- Options,
- Partials,
- Structures,
- version as discordJsVersion,
- type Awaitable,
- type If,
- type InteractionReplyOptions,
- type Message,
- type MessageEditOptions,
- type MessageOptions,
- type ReplyMessageOptions,
- type Snowflake,
- type UserResolvable,
- type WebhookEditMessageOptions
-} from 'discord.js';
-import type EventEmitter from 'events';
-import { google } from 'googleapis';
-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/cache/updateCache.js';
-import UpdateStatsTask from '../../../tasks/feature/updateStats.js';
-import { HighlightManager } from '../../common/HighlightManager.js';
-import { ActivePunishment } from '../../models/instance/ActivePunishment.js';
-import { Guild as GuildDB } from '../../models/instance/Guild.js';
-import { Highlight } from '../../models/instance/Highlight.js';
-import { Level } from '../../models/instance/Level.js';
-import { ModLog } from '../../models/instance/ModLog.js';
-import { Reminder } from '../../models/instance/Reminder.js';
-import { StickyRole } from '../../models/instance/StickyRole.js';
-import { Global } from '../../models/shared/Global.js';
-import { GuildCount } from '../../models/shared/GuildCount.js';
-import { MemberCount } from '../../models/shared/MemberCount.js';
-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 { BushClientUtils } from '../../utils/BushClientUtils.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 { BushCommandHandler } from './BushCommandHandler.js';
-import { BushInhibitorHandler } from './BushInhibitorHandler.js';
-import { BushListenerHandler } from './BushListenerHandler.js';
-import { BushTaskHandler } from './BushTaskHandler.js';
-const { Sequelize } = (await import('sequelize')).default;
-
-declare module 'discord.js' {
- export interface Client extends EventEmitter {
- /** The ID of the owner(s). */
- ownerID: Snowflake | Snowflake[];
- /** The ID of the superUser(s). */
- superUserID: Snowflake | Snowflake[];
- /** Whether or not the client is ready. */
- customReady: boolean;
- /** The configuration for the client. */
- readonly config: Config;
- /** Stats for the client. */
- readonly stats: BushStats;
- /** The handler for the bot's listeners. */
- readonly listenerHandler: BushListenerHandler;
- /** The handler for the bot's command inhibitors. */
- readonly inhibitorHandler: BushInhibitorHandler;
- /** The handler for the bot's commands. */
- readonly commandHandler: BushCommandHandler;
- /** The handler for the bot's tasks. */
- readonly taskHandler: BushTaskHandler;
- /** The handler for the bot's context menu commands. */
- readonly contextMenuCommandHandler: ContextMenuCommandHandler;
- /** The database connection for this instance of the bot (production, beta, or development). */
- readonly instanceDB: SequelizeType;
- /** The database connection that is shared between all instances of the bot. */
- readonly sharedDB: SequelizeType;
- /** A custom logging system for the bot. */
- readonly logger: BushLogger;
- /** Cached global and guild database data. */
- readonly cache: BushCache;
- /** Sentry error reporting for the bot. */
- readonly sentry: typeof Sentry;
- /** Manages most aspects of the highlight command */
- readonly highlightManager: HighlightManager;
- /** The perspective api */
- perspective: any;
- /** Client utilities. */
- readonly utils: BushClientUtils;
- /** A custom logging system for the bot. */
- get console(): BushLogger;
- 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;
- off<K extends keyof BushClientEvents>(event: K, listener: (...args: BushClientEvents[K]) => Awaitable<void>): this;
- removeAllListeners<K extends keyof BushClientEvents>(event?: K): this;
- /**
- * Checks if a user is the owner of this bot.
- * @param user - User to check.
- */
- isOwner(user: UserResolvable): boolean;
- /**
- * Checks if a user is a super user of this bot.
- * @param user - User to check.
- */
- isSuperUser(user: UserResolvable): boolean;
- }
-}
-
-export type ReplyMessageType = string | MessagePayload | ReplyMessageOptions;
-export type EditMessageType = string | MessageEditOptions | MessagePayload;
-export type SlashSendMessageType = string | MessagePayload | InteractionReplyOptions;
-export type SlashEditMessageType = string | MessagePayload | WebhookEditMessageOptions;
-export type SendMessageType = string | MessagePayload | MessageOptions;
-
-const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: false
-});
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
-
-/**
- * The main hub for interacting with the Discord API.
- */
-export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Ready> {
- public declare ownerID: Snowflake[];
- public declare superUserID: Snowflake[];
-
- /**
- * Whether or not the client is ready.
- */
- public override customReady = false;
-
- /**
- * Stats for the client.
- */
- public override readonly stats: BushStats = { cpu: undefined, commandsUsed: 0n, slashCommandsUsed: 0n };
-
- /**
- * The handler for the bot's listeners.
- */
- public override readonly listenerHandler: BushListenerHandler;
-
- /**
- * The handler for the bot's command inhibitors.
- */
- public override readonly inhibitorHandler: BushInhibitorHandler;
-
- /**
- * The handler for the bot's commands.
- */
- public override readonly commandHandler: BushCommandHandler;
-
- /**
- * The handler for the bot's tasks.
- */
- public override readonly taskHandler: BushTaskHandler;
-
- /**
- * The handler for the bot's context menu commands.
- */
- public override readonly contextMenuCommandHandler: ContextMenuCommandHandler;
-
- /**
- * The database connection for this instance of the bot (production, beta, or development).
- */
- public override readonly instanceDB: SequelizeType;
-
- /**
- * The database connection that is shared between all instances of the bot.
- */
- public override readonly sharedDB: SequelizeType;
-
- /**
- * A custom logging system for the bot.
- */
- public override readonly logger: BushLogger = new BushLogger(this);
-
- /**
- * Cached global and guild database data.
- */
- public override readonly cache = new BushCache();
-
- /**
- * Sentry error reporting for the bot.
- */
- public override readonly sentry!: typeof Sentry;
-
- /**
- * Manages most aspects of the highlight command
- */
- public override readonly highlightManager: HighlightManager = new HighlightManager(this);
-
- /**
- * The perspective api
- */
- public override perspective: any;
-
- /**
- * Client utilities.
- */
- public override readonly utils: BushClientUtils = new BushClientUtils(this);
-
- /**
- * @param config The configuration for the client.
- */
- public constructor(
- /**
- * The configuration for the client.
- */
- public override readonly config: Config
- ) {
- super({
- ownerID: config.owners,
- intents: Object.keys(GatewayIntentBits)
- .map((i) => (typeof i === 'string' ? GatewayIntentBits[i as keyof typeof GatewayIntentBits] : i))
- .reduce((acc, p) => acc | p, 0),
- partials: Object.keys(Partials).map((p) => Partials[p as keyof typeof Partials]),
- presence: {
- activities: [{ name: 'Beep Boop', type: ActivityType.Watching }],
- status: 'online'
- },
- allowedMentions: AllowedMentions.none(), // no mentions by default
- makeCache: Options.cacheWithLimits({}),
- failIfNotExists: false,
- rest: { api: 'https://canary.discord.com/api' }
- });
- patch(this);
-
- this.token = config.token as If<Ready, string, string | null>;
-
- /* =-=-= handlers =-=-= */
- this.listenerHandler = new BushListenerHandler(this, {
- directory: path.join(__dirname, '..', '..', '..', 'listeners'),
- automateCategories: true
- });
- this.inhibitorHandler = new BushInhibitorHandler(this, {
- directory: path.join(__dirname, '..', '..', '..', 'inhibitors'),
- automateCategories: true
- });
- this.taskHandler = new BushTaskHandler(this, {
- directory: path.join(__dirname, '..', '..', '..', 'tasks'),
- automateCategories: true
- });
-
- const modify = async (
- message: Message,
- text: string | MessagePayload | MessageOptions | OtherwiseContentSupplier,
- data: ArgumentPromptData,
- replaceError: boolean
- ) => {
- const ending = '\n\n Type **cancel** to cancel the command';
- const options = typeof text === 'function' ? await text(message, data) : text;
- const search = '{error}',
- replace = emojis.error;
-
- if (typeof options === 'string') return (replaceError ? options.replace(search, replace) : options) + ending;
-
- if (options instanceof MessagePayload) {
- if (options.options.content) {
- if (replaceError) options.options.content = options.options.content.replace(search, replace);
- options.options.content += ending;
- }
- } else if (options.content) {
- if (replaceError) options.content = options.content.replace(search, replace);
- options.content += ending;
- }
- return options;
- };
-
- this.commandHandler = new BushCommandHandler(this, {
- directory: path.join(__dirname, '..', '..', '..', 'commands'),
- prefix: async ({ guild }: Message) => {
- if (this.config.isDevelopment) return 'dev ';
- if (!guild) return this.config.prefix;
- const prefix = await guild.getSetting('prefix');
- return (prefix ?? this.config.prefix) as string;
- },
- allowMention: true,
- handleEdits: true,
- commandUtil: true,
- commandUtilLifetime: 300_000, // 5 minutes
- argumentDefaults: {
- prompt: {
- start: 'Placeholder argument prompt. **If you see this please tell my developers**.',
- retry: 'Placeholder failed argument prompt. **If you see this please tell my developers**.',
- modifyStart: (message, text, data) => modify(message, text, data, false),
- modifyRetry: (message, text, data) => modify(message, text, data, true),
- timeout: ':hourglass: You took too long the command has been cancelled.',
- ended: 'You exceeded the maximum amount of tries the command has been cancelled',
- cancel: 'The command has been cancelled',
- retries: 3,
- time: 3e4
- },
- otherwise: ''
- },
- automateCategories: false,
- autoRegisterSlashCommands: true,
- skipBuiltInPostInhibitors: true,
- aliasReplacement: /-/g
- });
- this.contextMenuCommandHandler = new ContextMenuCommandHandler(this, {
- directory: path.join(__dirname, '..', '..', '..', 'context-menu-commands'),
- automateCategories: true
- });
-
- /* =-=-= databases =-=-= */
- const sharedDBOptions: SequelizeOptions = {
- username: this.config.db.username,
- password: this.config.db.password,
- dialect: 'postgres',
- host: this.config.db.host,
- port: this.config.db.port,
- logging: this.config.logging.db ? (sql) => this.logger.debug(sql) : false,
- timezone: 'America/New_York'
- };
- this.instanceDB = new Sequelize({
- ...sharedDBOptions,
- database: this.config.isDevelopment ? 'bushbot-dev' : this.config.isBeta ? 'bushbot-beta' : 'bushbot'
- });
- this.sharedDB = new Sequelize({
- ...sharedDBOptions,
- database: 'bushbot-shared'
- });
-
- this.sentry = Sentry;
- }
-
- /**
- * A custom logging system for the bot.
- */
- public override get console(): BushLogger {
- return this.logger;
- }
-
- /**
- * Extends discord.js structures before the client is instantiated.
- */
- public static extendStructures(): void {
- Structures.extend('GuildMember', () => ExtendedGuildMember);
- Structures.extend('Guild', () => ExtendedGuild);
- Structures.extend('Message', () => ExtendedMessage);
- Structures.extend('User', () => ExtendedUser);
- }
-
- /**
- * Initializes the bot.
- */
- public async init() {
- if (parseInt(process.versions.node.split('.')[0]) < 17) {
- void (await this.console.error('version', `Please use node <<v17.x.x>>, not <<${process.version}>>.`, false));
- process.exit(2);
- }
-
- this.setMaxListeners(20);
-
- this.perspective = await google.discoverAPI<any>('https://commentanalyzer.googleapis.com/$discovery/rest?version=v1alpha1');
-
- this.commandHandler.useInhibitorHandler(this.inhibitorHandler);
- this.commandHandler.useListenerHandler(this.listenerHandler);
- this.commandHandler.useTaskHandler(this.taskHandler);
- this.commandHandler.useContextMenuCommandHandler(this.contextMenuCommandHandler);
- this.commandHandler.ignorePermissions = this.config.owners;
- this.commandHandler.ignoreCooldown = [...new Set([...this.config.owners, ...this.cache.shared.superUsers])];
- const emitters: Emitters = {
- client: this,
- commandHandler: this.commandHandler,
- inhibitorHandler: this.inhibitorHandler,
- listenerHandler: this.listenerHandler,
- taskHandler: this.taskHandler,
- contextMenuCommandHandler: this.contextMenuCommandHandler,
- process,
- stdin: rl,
- gateway: this.ws,
- rest: this.rest,
- ws: this.ws
- };
- this.listenerHandler.setEmitters(emitters);
- this.commandHandler.resolver.addTypes({
- duration: <ArgumentTypeCaster>duration,
- contentWithDuration: <ArgumentTypeCaster>contentWithDuration,
- permission: <ArgumentTypeCaster>permission,
- snowflake: <ArgumentTypeCaster>snowflake,
- discordEmoji: <ArgumentTypeCaster>discordEmoji,
- roleWithDuration: <ArgumentTypeCaster>roleWithDuration,
- abbreviatedNumber: <ArgumentTypeCaster>abbreviatedNumber,
- durationSeconds: <ArgumentTypeCaster>durationSeconds,
- globalUser: <ArgumentTypeCaster>globalUser,
- messageLink: <ArgumentTypeCaster>messageLink,
- tinyColor: <ArgumentTypeCaster>tinyColor
- });
-
- this.sentry.setTag('process', process.pid.toString());
- this.sentry.setTag('discord.js', discordJsVersion);
- this.sentry.setTag('discord-akairo', akairoVersion);
- void this.logger.success('startup', `Successfully connected to <<Sentry>>.`, false);
-
- // loads all the handlers
- const handlers = {
- commands: this.commandHandler,
- contextMenuCommands: this.contextMenuCommandHandler,
- listeners: this.listenerHandler,
- inhibitors: this.inhibitorHandler,
- tasks: this.taskHandler
- };
- const handlerPromises = Object.entries(handlers).map(([handlerName, handler]) =>
- handler
- .loadAll()
- .then(() => {
- void this.logger.success('startup', `Successfully loaded <<${handlerName}>>.`, false);
- })
- .catch((e) => {
- void this.logger.error('startup', `Unable to load loader <<${handlerName}>> with error:\n${formatError(e)}`, false);
- if (process.argv.includes('dry')) process.exit(1);
- })
- );
- await Promise.allSettled(handlerPromises);
- }
-
- /**
- * Connects to the database, initializes models, and creates tables if they do not exist.
- */
- public async dbPreInit() {
- try {
- await this.instanceDB.authenticate();
- GuildDB.initModel(this.instanceDB, this);
- ModLog.initModel(this.instanceDB);
- ActivePunishment.initModel(this.instanceDB);
- Level.initModel(this.instanceDB);
- StickyRole.initModel(this.instanceDB);
- Reminder.initModel(this.instanceDB);
- Highlight.initModel(this.instanceDB);
- await this.instanceDB.sync({ alter: true }); // Sync all tables to fix everything if updated
- await this.console.success('startup', `Successfully connected to <<instance database>>.`, false);
- } catch (e) {
- await this.console.error(
- 'startup',
- `Failed to connect to <<instance database>> with error:\n${inspect(e, { colors: true, depth: 1 })}`,
- false
- );
- process.exit(2);
- }
- try {
- await this.sharedDB.authenticate();
- Stat.initModel(this.sharedDB);
- Global.initModel(this.sharedDB);
- Shared.initModel(this.sharedDB);
- MemberCount.initModel(this.sharedDB);
- GuildCount.initModel(this.sharedDB);
- await this.sharedDB.sync({
- // Sync all tables to fix everything if updated
- // if another instance restarts we don't want to overwrite new changes made in development
- alter: this.config.isDevelopment
- });
- await this.console.success('startup', `Successfully connected to <<shared database>>.`, false);
- } catch (e) {
- await this.console.error(
- 'startup',
- `Failed to connect to <<shared database>> with error:\n${inspect(e, { colors: true, depth: 1 })}`,
- false
- );
- process.exit(2);
- }
- }
-
- /**
- * Starts the bot
- */
- public async start() {
- this.intercept('ready', async (arg, done) => {
- const promises = this.guilds.cache
- .filter((g) => g.large)
- .map((guild) => {
- return guild.members.fetch();
- });
- await Promise.all(promises);
- this.customReady = true;
- this.taskHandler.startAll();
- return done(null, `intercepted ${arg}`);
- });
-
- try {
- await this.highlightManager.syncCache();
- await UpdateCacheTask.init(this);
- void this.console.success('startup', `Successfully created <<cache>>.`, false);
- const stats = await UpdateStatsTask.init(this);
- this.stats.commandsUsed = stats.commandsUsed;
- this.stats.slashCommandsUsed = stats.slashCommandsUsed;
- await this.login(this.token!);
- } catch (e) {
- await this.console.error('start', inspect(e, { colors: true, depth: 1 }), false);
- process.exit(1);
- }
- }
-
- /**
- * Logs out, terminates the connection to Discord, and destroys the client.
- */
- public override destroy(relogin = false): void | Promise<string> {
- super.destroy();
- if (relogin) {
- return this.login(this.token!);
- }
- }
-
- public override isOwner(user: UserResolvable): boolean {
- return this.config.owners.includes(this.users.resolveId(user!)!);
- }
-
- public override isSuperUser(user: UserResolvable): boolean {
- const userID = this.users.resolveId(user)!;
- return this.cache.shared.superUsers.includes(userID) || this.config.owners.includes(userID);
- }
-}
-
-export interface BushClient<Ready extends boolean = boolean> extends EventEmitter, PatchedElements, AkairoClient<Ready> {
- 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;
- off<K extends keyof BushClientEvents>(event: K, listener: (...args: BushClientEvents[K]) => Awaitable<void>): this;
- removeAllListeners<K extends keyof BushClientEvents>(event?: K): this;
-}
-
-/**
- * Various statistics
- */
-export interface BushStats {
- /**
- * The average cpu usage of the bot from the past 60 seconds.
- */
- cpu: number | undefined;
-
- /**
- * The total number of times any command has been used.
- */
- commandsUsed: bigint;
-
- /**
- * The total number of times any slash command has been used.
- */
- slashCommandsUsed: bigint;
-}
-
-export interface Emitters {
- client: BushClient;
- commandHandler: BushClient['commandHandler'];
- inhibitorHandler: BushClient['inhibitorHandler'];
- listenerHandler: BushClient['listenerHandler'];
- taskHandler: BushClient['taskHandler'];
- contextMenuCommandHandler: BushClient['contextMenuCommandHandler'];
- process: NodeJS.Process;
- stdin: readline.Interface;
- gateway: BushClient['ws'];
- rest: BushClient['rest'];
- ws: BushClient['ws'];
-}
diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts
deleted file mode 100644
index dc2295f..0000000
--- a/src/lib/extensions/discord-akairo/BushCommand.ts
+++ /dev/null
@@ -1,586 +0,0 @@
-import { type DiscordEmojiInfo, type RoleWithDuration } from '#args';
-import {
- type BushArgumentTypeCaster,
- type BushClient,
- type BushCommandHandler,
- type BushInhibitor,
- type BushListener,
- type BushTask,
- type ParsedDuration
-} from '#lib';
-import {
- ArgumentMatch,
- Command,
- CommandUtil,
- type AkairoApplicationCommandAutocompleteOption,
- type AkairoApplicationCommandChannelOptionData,
- type AkairoApplicationCommandChoicesData,
- type AkairoApplicationCommandNonOptionsData,
- type AkairoApplicationCommandNumericOptionData,
- type AkairoApplicationCommandOptionData,
- type AkairoApplicationCommandSubCommandData,
- type AkairoApplicationCommandSubGroupData,
- type ArgumentOptions,
- type ArgumentType,
- type ArgumentTypeCaster,
- type BaseArgumentType,
- type CommandOptions,
- type ContextMenuCommand,
- type MissingPermissionSupplier,
- type SlashOption,
- type SlashResolveType
-} from 'discord-akairo';
-import {
- Message,
- User,
- type ApplicationCommandOptionChoiceData,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- type ApplicationCommandOptionType,
- type PermissionResolvable,
- type PermissionsString,
- type Snowflake
-} from 'discord.js';
-import _ from 'lodash';
-import { SlashMessage } from './SlashMessage.js';
-
-export interface OverriddenBaseArgumentType extends BaseArgumentType {
- commandAlias: BushCommand | null;
- command: BushCommand | null;
- inhibitor: BushInhibitor | null;
- listener: BushListener | null;
- task: BushTask | null;
- contextMenuCommand: ContextMenuCommand | null;
-}
-
-export interface BaseBushArgumentType extends OverriddenBaseArgumentType {
- duration: number | null;
- contentWithDuration: ParsedDuration;
- permission: PermissionsString | null;
- snowflake: Snowflake | null;
- discordEmoji: DiscordEmojiInfo | null;
- roleWithDuration: RoleWithDuration | null;
- abbreviatedNumber: number | null;
- globalUser: User | null;
- messageLink: Message | null;
- durationSeconds: number | null;
- tinyColor: string | null;
-}
-
-export type BushArgumentType = keyof BaseBushArgumentType | RegExp;
-
-interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type' | 'prompt'>, ExtraArgumentOptions {
- id: string;
- description: string;
-
- /**
- * The message sent for the prompt and the slash command description.
- */
- prompt?: string;
-
- /**
- * The message set for the retry prompt.
- */
- retry?: string;
-
- /**
- * Whether or not the argument is optional.
- */
- optional?: boolean;
-
- /**
- * The type used for slash commands. Set to false to disable this argument for slash commands.
- */
- slashType: AkairoApplicationCommandOptionData['type'] | false;
-
- /**
- * Allows you to get a discord resolved object
- *
- * ex. get the resolved member object when the type is {@link ApplicationCommandOptionType.User User}
- */
- slashResolve?: SlashResolveType;
-
- /**
- * The choices of the option for the user to pick from
- */
- choices?: ApplicationCommandOptionChoiceData[];
-
- /**
- * Whether the option is an autocomplete option
- */
- autocomplete?: boolean;
-
- /**
- * When the option type is channel, the allowed types of channels that can be selected
- */
- channelTypes?: AkairoApplicationCommandChannelOptionData['channelTypes'];
-
- /**
- * The minimum value for an {@link ApplicationCommandOptionType.Integer Integer} or {@link ApplicationCommandOptionType.Number Number} option
- */
- minValue?: number;
-
- /**
- * The maximum value for an {@link ApplicationCommandOptionType.Integer Integer} or {@link ApplicationCommandOptionType.Number Number} option
- */
- maxValue?: number;
-}
-
-interface ExtraArgumentOptions {
- /**
- * Restrict this argument to only slash or only text commands.
- */
- only?: 'slash' | 'text';
-
- /**
- * Readable type for the help command.
- */
- readableType?: string;
-
- /**
- * Whether the argument is only accessible to the owners.
- * @default false
- */
- ownerOnly?: boolean;
-
- /**
- * Whether the argument is only accessible to the super users.
- * @default false
- */
- superUserOnly?: boolean;
-}
-
-export interface BushArgumentOptions extends BaseBushArgumentOptions {
- /**
- * The type that the argument should be cast to.
- * - `string` does not cast to any type.
- * - `lowercase` makes the input lowercase.
- * - `uppercase` makes the input uppercase.
- * - `charCodes` transforms the input to an array of char codes.
- * - `number` casts to a number.
- * - `integer` casts to an integer.
- * - `bigint` casts to a big integer.
- * - `url` casts to an `URL` object.
- * - `date` casts to a `Date` object.
- * - `color` casts a hex code to an integer.
- * - `commandAlias` tries to resolve to a command from an alias.
- * - `command` matches the ID of a command.
- * - `inhibitor` matches the ID of an inhibitor.
- * - `listener` matches the ID of a listener.
- *
- * Possible Discord-related types.
- * These types can be plural (add an 's' to the end) and a collection of matching objects will be used.
- * - `user` tries to resolve to a user.
- * - `member` tries to resolve to a member.
- * - `relevant` tries to resolve to a relevant user, works in both guilds and DMs.
- * - `channel` tries to resolve to a channel.
- * - `textChannel` tries to resolve to a text channel.
- * - `voiceChannel` tries to resolve to a voice channel.
- * - `stageChannel` tries to resolve to a stage channel.
- * - `threadChannel` tries to resolve a thread channel.
- * - `role` tries to resolve to a role.
- * - `emoji` tries to resolve to a custom emoji.
- * - `guild` tries to resolve to a guild.
- * - `permission` tries to resolve to a permissions.
- *
- * Other Discord-related types:
- * - `message` tries to fetch a message from an ID within the channel.
- * - `guildMessage` tries to fetch a message from an ID within the guild.
- * - `relevantMessage` is a combination of the above, works in both guilds and DMs.
- * - `invite` tries to fetch an invite object from a link.
- * - `userMention` matches a mention of a user.
- * - `memberMention` matches a mention of a guild member.
- * - `channelMention` matches a mention of a channel.
- * - `roleMention` matches a mention of a role.
- * - `emojiMention` matches a mention of an emoji.
- *
- * Misc:
- * - `duration` tries to parse duration in milliseconds
- * - `contentWithDuration` tries to parse duration in milliseconds and returns the remaining content with the duration
- * removed
- */
- type?: BushArgumentType | (keyof BaseBushArgumentType)[] | BushArgumentTypeCaster;
-}
-
-export interface CustomBushArgumentOptions extends BaseBushArgumentOptions {
- /**
- * An array of strings can be used to restrict input to only those strings, case insensitive.
- * The array can also contain an inner array of strings, for aliases.
- * If so, the first entry of the array will be used as the final argument.
- *
- * A regular expression can also be used.
- * The evaluated argument will be an object containing the `match` and `matches` if global.
- */
- customType?: (string | string[])[] | RegExp | string | null;
-}
-
-export type BushMissingPermissionSupplier = (message: CommandMessage | SlashMessage) => Promise<any> | any;
-
-interface ExtendedCommandOptions {
- /**
- * Whether the command is hidden from the help command.
- */
- hidden?: boolean;
-
- /**
- * The channels the command is limited to run in.
- */
- restrictedChannels?: Snowflake[];
-
- /**
- * The guilds the command is limited to run in.
- */
- restrictedGuilds?: Snowflake[];
-
- /**
- * Show how to use the command.
- */
- usage: string[];
-
- /**
- * Examples for how to use the command.
- */
- examples: string[];
-
- /**
- * A fake command, completely hidden from the help command.
- */
- pseudo?: boolean;
-
- /**
- * Allow this command to be run in channels that are blacklisted.
- */
- bypassChannelBlacklist?: boolean;
-
- /**
- * Use instead of {@link BaseBushCommandOptions.args} when using argument generators or custom slashOptions
- */
- helpArgs?: ArgsInfo[];
-
- /**
- * Extra information about the command, displayed in the help command.
- */
- note?: string;
-}
-
-export interface BaseBushCommandOptions
- extends Omit<CommandOptions, 'userPermissions' | 'clientPermissions' | 'args'>,
- ExtendedCommandOptions {
- /**
- * The description of the command.
- */
- description: string;
-
- /**
- * The arguments for the command.
- */
- args?: BushArgumentOptions[] & CustomBushArgumentOptions[];
-
- category: string;
-
- /**
- * Permissions required by the client to run this command.
- */
- clientPermissions: bigint | bigint[] | BushMissingPermissionSupplier;
-
- /**
- * Permissions required by the user to run this command.
- */
- userPermissions: bigint | bigint[] | BushMissingPermissionSupplier;
-
- /**
- * Whether the argument is only accessible to the owners.
- */
- ownerOnly?: boolean;
-
- /**
- * Whether the argument is only accessible to the super users.
- */
- superUserOnly?: boolean;
-}
-
-export type BushCommandOptions = Omit<BaseBushCommandOptions, 'helpArgs'> | Omit<BaseBushCommandOptions, 'args'>;
-
-export interface ArgsInfo {
- /**
- * The name of the argument.
- */
- name: string;
-
- /**
- * The description of the argument.
- */
- description: string;
-
- /**
- * Whether the argument is optional.
- * @default false
- */
- optional?: boolean;
-
- /**
- * Whether or not the argument has autocomplete enabled.
- * @default false
- */
- autocomplete?: boolean;
-
- /**
- * Whether the argument is restricted a certain command.
- * @default 'slash & text'