diff options
201 files changed, 1372 insertions, 1173 deletions
diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 3666e7a..550cb28 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -175,6 +175,7 @@ module.exports = { '@typescript-eslint/no-namespace': 'off', 'no-debugger': 'warn', '@typescript-eslint/prefer-as-const': 'warn', - '@typescript-eslint/ban-types': 'off' + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-inferrable-types': 'off' } }; diff --git a/.vscode/settings.json b/.vscode/settings.json index 600c85e..d3f096d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,11 +30,11 @@ "prettier.withNodeModules": true, "prettier.useEditorConfig": false, "javascript.format.enable": false, - "javascript.preferences.importModuleSpecifier": "relative", + "javascript.preferences.importModuleSpecifier": "shortest", "javascript.preferences.importModuleSpecifierEnding": "js", "javascript.preferences.useAliasesForRenames": false, "typescript.format.enable": false, - "typescript.preferences.importModuleSpecifier": "relative", + "typescript.preferences.importModuleSpecifier": "shortest", "typescript.preferences.importModuleSpecifierEnding": "js", "typescript.preferences.useAliasesForRenames": false, "discord.removeDetails": false, diff --git a/.vscode/typescript.code-snippets b/.vscode/typescript.code-snippets index 4e2bec4..c4ab25c 100644 --- a/.vscode/typescript.code-snippets +++ b/.vscode/typescript.code-snippets @@ -10,8 +10,8 @@ "description": "A bot command template", "body": [ "import {", + "\tBotCommand,", "\tclientSendAndPermCheck,", - "\tCustomCommand,", "\temojis,", "\ttype ArgType,", "\ttype CommandMessage,", @@ -20,7 +20,7 @@ "} from '#lib';", "", "import { ApplicationCommandOptionType } from 'discord.js';", - "export default class ${1:CommandName} extends CustomCommand {", + "export default class ${1:CommandName} extends BotCommand {", "\tpublic constructor() {", "\t\tsuper('${2:commandId}', {", "\t\t\taliases: ['${3:alias}'],", @@ -50,7 +50,7 @@ "\t\t\t],", "\t\t\tslash: ${22|true,false|},", "\t\t\tchannel: '${23|guild,dm|}',", - "\t\t\tclientPermissions: (m) => clientSendAndPermCheck(m),", + "\t\t\tclientPermissions: [],", "\t\t\tuserPermissions: []", "\t\t});", "\t}", diff --git a/lib/extensions/discord-akairo/BotArgumentTypeCaster.ts b/lib/extensions/discord-akairo/BotArgumentTypeCaster.ts index 5f4f32f..d7943fc 100644 --- a/lib/extensions/discord-akairo/BotArgumentTypeCaster.ts +++ b/lib/extensions/discord-akairo/BotArgumentTypeCaster.ts @@ -1,3 +1,3 @@ -import { type CommandMessage } from '#lib'; +import type { CommandMessage } from '#lib'; export type BotArgumentTypeCaster<R = unknown> = (message: CommandMessage, phrase: string) => R; diff --git a/lib/extensions/discord-akairo/BotCommand.ts b/lib/extensions/discord-akairo/BotCommand.ts index abd945e..11a8bad 100644 --- a/lib/extensions/discord-akairo/BotCommand.ts +++ b/lib/extensions/discord-akairo/BotCommand.ts @@ -1,17 +1,16 @@ import { type DiscordEmojiInfo, type RoleWithDuration } from '#args'; -import { - type BotArgumentTypeCaster, - type BotCommandHandler, - type BotInhibitor, - type BotListener, - type BotTask, - type ParsedDuration, - type TanzaniteClient +import type { + BotArgumentTypeCaster, + BotCommandHandler, + BotInhibitor, + BotListener, + BotTask, + ParsedDuration, + TanzaniteClient } from '#lib'; import { - ArgumentMatch, Command, - CommandUtil, + CommandArguments, type AkairoApplicationCommandAutocompleteOption, type AkairoApplicationCommandChannelOptionData, type AkairoApplicationCommandChoicesData, @@ -20,26 +19,25 @@ import { type AkairoApplicationCommandOptionData, type AkairoApplicationCommandSubCommandData, type AkairoApplicationCommandSubGroupData, + type ArgumentMatch, type ArgumentOptions, type ArgumentType, type ArgumentTypeCaster, type BaseArgumentType, type CommandOptions, + type CommandUtil, type ContextMenuCommand, - type MissingPermissionSupplier, type SlashOption, type SlashResolveType } from 'discord-akairo'; import { - Message, PermissionsBitField, - User, type ApplicationCommandOptionChoiceData, - // eslint-disable-next-line @typescript-eslint/no-unused-vars type ApplicationCommandOptionType, - type PermissionResolvable, + type Message, type PermissionsString, - type Snowflake + type Snowflake, + type User } from 'discord.js'; import _ from 'lodash'; import { SlashMessage } from './SlashMessage.js'; @@ -219,6 +217,7 @@ export type CustomMissingPermissionSupplier = (message: CommandMessage | SlashMe interface ExtendedCommandOptions { /** * Whether the command is hidden from the help command. + * @default false */ hidden?: boolean; @@ -244,11 +243,13 @@ interface ExtendedCommandOptions { /** * A fake command, completely hidden from the help command. + * @default false */ pseudo?: boolean; /** * Allow this command to be run in channels that are blacklisted. + * @default false */ bypassChannelBlacklist?: boolean; @@ -261,6 +262,24 @@ interface ExtendedCommandOptions { * Extra information about the command, displayed in the help command. */ note?: string; + + /** + * Whether to check for channel overrides when considering client permissions. + * @default false + */ + clientCheckChannel?: boolean; + + /** + * Whether to check for channel overrides when considering user permissions. + * @default false + */ + userCheckChannel?: boolean; + + /** + * **Text Command Only**: Don't check if the user has send permissions in the channel. + * @default false + */ + skipSendCheck?: boolean; } export interface BaseBotCommandOptions @@ -281,12 +300,12 @@ export interface BaseBotCommandOptions /** * Permissions required by the client to run this command. */ - clientPermissions: bigint | bigint[] | CustomMissingPermissionSupplier; + clientPermissions: PermissionsString[]; /** * Permissions required by the user to run this command. */ - userPermissions: bigint | bigint[] | CustomMissingPermissionSupplier; + userPermissions: PermissionsString[]; /** * Whether the argument is only accessible to the owners. @@ -364,6 +383,8 @@ export abstract class BotCommand extends Command { public declare client: TanzaniteClient; public declare handler: BotCommandHandler; public declare description: string; + public declare userPermissions: PermissionsString[]; + public declare clientPermissions: PermissionsString[]; /** * Show how to use the command. @@ -411,7 +432,7 @@ export abstract class BotCommand extends Command { public bypassChannelBlacklist: boolean; /** - * Info about the arguments for the help command. + * Information about the arguments for the help command. */ public argsInfo?: ArgsInfo[]; @@ -420,6 +441,24 @@ export abstract class BotCommand extends Command { */ public note?: string; + /** + * Whether to check for channel overrides when considering client permissions. + * @default true + */ + public clientCheckChannel: boolean; + + /** + * Whether to check for channel overrides when considering user permissions. + * @default true + */ + public userCheckChannel: boolean; + + /** + * **Text Command Only**: Don't check if the user has send permissions in the channel. + * @default false + */ + public skipSendCheck: boolean; + public constructor(id: string, options: CustomCommandOptions) { const options_ = options as BaseBotCommandOptions; @@ -490,7 +529,7 @@ export abstract class BotCommand extends Command { if (newTextArgs.length > 0) newOptions.args = newTextArgs; if (newSlashArgs.length > 0) newOptions.slashOptions = options_.slashOptions ?? newSlashArgs; } else if (key === 'clientPermissions' || key === 'userPermissions') { - newOptions[key] = options_[key] as PermissionResolvable | PermissionResolvable[] | MissingPermissionSupplier; + newOptions[key] = options_[key]; } else { newOptions[key] = options_[key]; } @@ -543,12 +582,15 @@ export abstract class BotCommand extends Command { this.examples = options_.examples; this.options = options_; this.parsedOptions = newOptions; - this.hidden = !!options_.hidden; + this.hidden = options_.hidden ?? false; this.restrictedChannels = options_.restrictedChannels; this.restrictedGuilds = options_.restrictedGuilds; - this.pseudo = !!options_.pseudo; - this.bypassChannelBlacklist = !!options_.bypassChannelBlacklist; + this.pseudo = options_.pseudo ?? false; + this.bypassChannelBlacklist = options_.bypassChannelBlacklist ?? false; this.note = options_.note; + this.clientCheckChannel = options_.clientCheckChannel ?? false; + this.userCheckChannel = options_.userCheckChannel ?? false; + this.skipSendCheck = options_.skipSendCheck ?? false; } /** @@ -556,13 +598,13 @@ export abstract class BotCommand extends Command { * @param message - Message that triggered the command. * @param args - Evaluated arguments. */ - public abstract override exec(message: CommandMessage, args: any): any; + public abstract override exec(message: CommandMessage, args: CommandArguments): any; /** * Executes the command. * @param message - Message that triggered the command. * @param args - Evaluated arguments. */ - public abstract override exec(message: CommandMessage | SlashMessage, args: any): any; + public abstract override exec(message: CommandMessage | SlashMessage, args: CommandArguments): any; } type SlashOptionKeys = diff --git a/lib/extensions/discord-akairo/BotCommandHandler.ts b/lib/extensions/discord-akairo/BotCommandHandler.ts index 8a4fe60..71d9ad4 100644 --- a/lib/extensions/discord-akairo/BotCommandHandler.ts +++ b/lib/extensions/discord-akairo/BotCommandHandler.ts @@ -1,6 +1,7 @@ -import { type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; -import { CommandHandler, type Category, type CommandHandlerEvents, type CommandHandlerOptions } from 'discord-akairo'; -import { type Collection, type Message, type PermissionsString } from 'discord.js'; +import type { BotCommand, CommandMessage, SlashMessage } from '#lib'; +import { CommandHandler, CommandHandlerEvents, type Category, type CommandHandlerOptions } from 'discord-akairo'; +import { GuildMember, PermissionResolvable, type Collection, type Message, type PermissionsString } from 'discord.js'; +import { CommandHandlerEvent } from '../../utils/Constants.js'; export type CustomCommandHandlerOptions = CommandHandlerOptions; @@ -18,20 +19,116 @@ export interface BotCommandHandlerEvents extends CommandHandlerEvents { load: [command: BotCommand, isReload: boolean]; messageBlocked: [message: /* no util */ Message | CommandMessage | SlashMessage, reason: string]; messageInvalid: [message: CommandMessage]; - missingPermissions: [message: CommandMessage, command: BotCommand, type: 'client' | 'user', missing: PermissionsString[]]; + missingPermissions: [ + message: CommandMessage, + command: BotCommand, + type: 'client' | 'user', + // fix: this is jank + missing: (PermissionsString | '[[UnsupportedChannel]]')[] + ]; remove: [command: BotCommand]; slashBlocked: [message: SlashMessage, command: BotCommand, reason: string]; slashError: [error: Error, message: SlashMessage, command: BotCommand]; slashFinished: [message: SlashMessage, command: BotCommand, args: any, returnValue: any]; - slashMissingPermissions: [message: SlashMessage, command: BotCommand, type: 'client' | 'user', missing: PermissionsString[]]; + slashMissingPermissions: [ + message: SlashMessage, + command: BotCommand, + type: 'client' | 'user', + // fix: this is jank + missing: (PermissionsString | '[[UnsupportedChannel]]')[] + ]; slashStarted: [message: SlashMessage, command: BotCommand, args: any]; } export class BotCommandHandler extends CommandHandler { public declare modules: Collection<string, BotCommand>; public declare categories: Collection<string, Category<string, BotCommand>>; + + //! this is a simplified version of the original + public override async runPermissionChecks( + message: Message | SlashMessage, + command: BotCommand, + slash: boolean = false + ): Promise<boolean> { + const event = slash ? CommandHandlerEvent.SlashMissingPermissions : CommandHandlerEvent.MissingPermissions; + + const appSlashPerms = slash ? (message as SlashMessage).interaction.appPermissions : null; + const userSlashPerms = slash ? (message as SlashMessage).interaction.memberPermissions : null; + + console.dir(message); + console.dir(appSlashPerms); + console.dir(userSlashPerms); + console.dir(event); + console.dir(command); + + const noPerms = message.channel == null || (message.channel.isThread() && message.channel.parent == null); + + if (message.inGuild()) { + if (noPerms && command.clientCheckChannel && appSlashPerms == null) { + this.emit(event, message, command, 'client', ['[[UnsupportedChannel]]']); + return true; + } + if (message.channel?.isDMBased()) return false; + + const missing = command.clientCheckChannel + ? (appSlashPerms ?? message.channel?.permissionsFor(message.guild.members.me!))?.missing(command.clientPermissions) + : message.guild?.members.me?.permissions.missing(command.clientPermissions); + + if (missing?.length) { + this.emit(event, message, command, 'client', missing); + return true; + } + } + + if (command.userPermissions) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const ignorer = command.ignorePermissions || this.ignorePermissions; + const isIgnored = Array.isArray(ignorer) + ? ignorer.includes(message.author.id) + : typeof ignorer === 'function' + ? ignorer(message, command) + : message.author.id === ignorer; + + if (!isIgnored) { + if (message.inGuild()) { + if (noPerms && command.userCheckChannel && userSlashPerms == null) { + this.emit(event, message, command, 'user', ['[[UnsupportedChannel]]']); + return true; + } + if (message.channel?.isDMBased()) return false; + + const missing = command.userCheckChannel + ? (userSlashPerms ?? message.channel?.permissionsFor(message.author))?.missing(command.userPermissions) + : message.member?.permissions.missing(command.userPermissions); + + if (missing?.length) { + this.emit(event, message, command, 'user', missing); + return true; + } + } + } + } + + return false; + } } export interface BotCommandHandler extends CommandHandler { findCommand(name: string): BotCommand; } + +export function permissionCheck( + message: CommandMessage | SlashMessage, + check: GuildMember, + perms: PermissionResolvable, + useChannel: boolean +): boolean { + if (message.inGuild()) { + if (!message.channel || message.channel.isDMBased()) return true; + + const missing = useChannel ? message.channel.permissionsFor(check)?.missing(perms) : check.permissions.missing(perms); + + if (missing?.length) return false; + } + return true; +} diff --git a/lib/extensions/discord-akairo/BotInhibitor.ts b/lib/extensions/discord-akairo/BotInhibitor.ts index d134eab..8892b8b 100644 --- a/lib/extensions/discord-akairo/BotInhibitor.ts +++ b/lib/extensions/discord-akairo/BotInhibitor.ts @@ -1,8 +1,12 @@ -import { type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; -import { Inhibitor } from 'discord-akairo'; +import type { BotCommand, CommandMessage, InhibitorReason, InhibitorType, SlashMessage } from '#lib'; +import { Inhibitor, InhibitorOptions } from 'discord-akairo'; import { Message } from 'discord.js'; export abstract class BotInhibitor extends Inhibitor { + public constructor(id: InhibitorReason, options?: BotInhibitorOptions) { + super(id, options); + } + /** * Checks if message should be blocked. * A return value of true will block the message. @@ -16,3 +20,28 @@ export abstract class BotInhibitor extends Inhibitor { public abstract override exec(message: CommandMessage, command: BotCommand): any; public abstract override exec(message: CommandMessage | SlashMessage, command: BotCommand): any; } + +/** + * Options to use for inhibitor execution behavior. + */ +export interface BotInhibitorOptions extends InhibitorOptions { + /** + * Reason emitted when command or message is blocked. + * @default "" + */ + reason: InhibitorReason; + + /** + * - {@link InhibitorType.All} run on all messages + * - {@link InhibitorType.Pre} run on messages not blocked by the built-in inhibitors + * - {@link InhibitorType.Post} run on messages that are commands + */ + type: InhibitorType; + + /** + * Priority for the inhibitor for when more than one inhibitors block a message. + * The inhibitor with the highest priority is the one that is used for the block reason. + * @default 0 + */ + priority?: number; +} diff --git a/lib/extensions/discord-akairo/BotListener.ts b/lib/extensions/discord-akairo/BotListener.ts index f4bfd6c..4f760e2 100644 --- a/lib/extensions/discord-akairo/BotListener.ts +++ b/lib/extensions/discord-akairo/BotListener.ts @@ -1,3 +1,49 @@ -import { Listener } from 'discord-akairo'; +import { Listener, type ListenerOptions } from 'discord-akairo'; -export abstract class BotListener extends Listener {} +export abstract class BotListener extends Listener { + public constructor(id: string, options: BotListenerOptions) { + super(id, options); + } +} + +/** + * Options to use for listener execution behavior. + */ +export interface BotListenerOptions extends ListenerOptions { + /** + * The event emitter, either a key from `ListenerHandler#emitters` or an EventEmitter. + */ + emitter: Emitter; + + /** + * Event name to listen to. + */ + event: string; + + /** + * Type of listener, either 'on' or 'once'. + * @default "on" + */ + type?: ListenerType; +} + +export const enum Emitter { + Client = 'client', + CommandHandler = 'commandHandler', + InhibitorHandler = 'inhibitorHandler', + ListenerHandler = 'listenerHandler', + TaskHandler = 'taskHandler', + ContextMenuCommandHandler = 'contextMenuCommandHandler', + Process = 'process', + Stdin = 'stdin', + Gateway = 'gateway', + Rest = 'rest', + Ws = 'ws' +} + +export const enum ListenerType { + On = 'on', + Once = 'once', + PrependListener = 'prependListener', + PrependOnceListener = 'prependOnceListener' +} diff --git a/lib/extensions/discord-akairo/BotListenerHandler.ts b/lib/extensions/discord-akairo/BotListenerHandler.ts index 9b3b525..bc14a53 100644 --- a/lib/extensions/discord-akairo/BotListenerHandler.ts +++ b/lib/extensions/discord-akairo/BotListenerHandler.ts @@ -1,3 +1,19 @@ import { ListenerHandler } from 'discord-akairo'; +import type readline from 'readline'; +import { TanzaniteClient } from './TanzaniteClient.js'; export class BotListenerHandler extends ListenerHandler {} + +export interface Emitters { + client: TanzaniteClient; + commandHandler: TanzaniteClient['commandHandler']; + inhibitorHandler: TanzaniteClient['inhibitorHandler']; + listenerHandler: TanzaniteClient['listenerHandler']; + taskHandler: TanzaniteClient['taskHandler']; + contextMenuCommandHandler: TanzaniteClient['contextMenuCommandHandler']; + process: NodeJS.Process; + stdin: readline.Interface; + gateway: TanzaniteClient['ws']; + rest: TanzaniteClient['rest']; + ws: TanzaniteClient['ws']; +} diff --git a/lib/extensions/discord-akairo/TanzaniteClient.ts b/lib/extensions/discord-akairo/TanzaniteClient.ts index fe34b58..ac09aea 100644 --- a/lib/extensions/discord-akairo/TanzaniteClient.ts +++ b/lib/extensions/discord-akairo/TanzaniteClient.ts @@ -11,7 +11,6 @@ import { snowflake } from '#args'; import type { Config } from '#config'; -import { BotClientEvents, emojis, formatError, inspect, updateEveryCache } from '#lib'; import { patch, type PatchedElements } from '@notenoughupdates/events-intercept'; import * as Sentry from '@sentry/node'; import { @@ -62,14 +61,18 @@ import { } from '../../models/index.js'; import { AllowedMentions } from '../../utils/AllowedMentions.js'; import { BotClientUtils } from '../../utils/BotClientUtils.js'; +import { emojis } from '../../utils/Constants.js'; import { Logger } from '../../utils/Logger.js'; +import { updateEveryCache } from '../../utils/UpdateCache.js'; +import { formatError, inspect } from '../../utils/Utils.js'; +import { BotClientEvents } from '../discord.js/BotClientEvents.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 { BotCommandHandler } from './BotCommandHandler.js'; import { BotInhibitorHandler } from './BotInhibitorHandler.js'; -import { BotListenerHandler } from './BotListenerHandler.js'; +import { BotListenerHandler, Emitters } from './BotListenerHandler.js'; import { BotTaskHandler } from './BotTaskHandler.js'; declare module 'discord.js' { @@ -578,17 +581,3 @@ export interface BotStats { */ slashCommandsUsed: bigint; } - -export interface Emitters { - client: TanzaniteClient; - commandHandler: TanzaniteClient['commandHandler']; - inhibitorHandler: TanzaniteClient['inhibitorHandler']; - listenerHandler: TanzaniteClient['listenerHandler']; - taskHandler: TanzaniteClient['taskHandler']; - contextMenuCommandHandler: TanzaniteClient['contextMenuCommandHandler']; - process: NodeJS.Process; - stdin: readline.Interface; - gateway: TanzaniteClient['ws']; - rest: TanzaniteClient['rest']; - ws: TanzaniteClient['ws']; -} diff --git a/lib/extensions/discord.js/BotClientEvents.ts b/lib/extensions/discord.js/BotClientEvents.ts index 284ea32..941a6d8 100644 --- a/lib/extensions/discord.js/BotClientEvents.ts +++ b/lib/extensions/discord.js/BotClientEvents.ts @@ -1,4 +1,3 @@ -import type { BanResponse, CommandMessage, Guild as GuildDB, GuildSettings } from '#lib'; import type { AkairoClientEvents } from 'discord-akairo'; import type { ButtonInteraction, @@ -13,32 +12,10 @@ import type { Snowflake, User } from 'discord.js'; - -export enum TanzaniteEvent { - Ban = 'customBan', - Block = 'customBlock', - Kick = 'customKick', - Mute = 'customMute', - PunishRoleAdd = 'punishRoleAdd', - PunishRoleRemove = 'punishRoleRemove', - Purge = 'customPurge', - RemoveTimeout = 'customRemoveTimeout', - Timeout = 'customTimeout', - Unban = 'customUnban', - Unblock = 'customUnblock', - Unmute = 'customUnmute', - UpdateModlog = 'updateModlog', - UpdateSettings = 'updateSettings', - Warn = 'customWarn', - LevelUpdate = 'levelUpdate', - Lockdown = 'lockdown', - Unlockdown = 'unlockdown', - MassBan = 'massBan', - MassEvidence = 'massEvidence', - Button = 'button', - SelectMenu = 'selectMenu', - ModalSubmit = 'modal' -} +import { Guild as GuildDB, GuildSettings } from '../../models/index.js'; +import { TanzaniteEvent } from '../../utils/Constants.js'; +import { CommandMessage } from '../discord-akairo/BotCommand.js'; +import { BanResponse } from './ExtendedGuildMember.js'; export interface BotClientEvents extends AkairoClientEvents { [TanzaniteEvent.Ban]: [ diff --git a/lib/extensions/discord.js/ExtendedGuild.ts b/lib/extensions/discord.js/ExtendedGuild.ts index 67de5cf..6b69206 100644 --- a/lib/extensions/discord.js/ExtendedGuild.ts +++ b/lib/extensions/discord.js/ExtendedGuild.ts @@ -1,19 +1,7 @@ -import { - AllowedMentions, - banResponse, - colors, - dmResponse, - emojis, - permissionsResponse, - punishmentEntryRemove, - TanzaniteClient, - type BanResponse, - type GuildFeatures, - type GuildLogType, - type GuildModel -} from '#lib'; import * as Moderation from '#lib/common/Moderation.js'; -import { Guild as GuildDB, ModLogType } from '#lib/models/index.js'; +import { Guild as GuildDB, GuildFeatures, GuildLogType, GuildModel, ModLogType } from '#lib/models/index.js'; +import { AllowedMentions } from '#lib/utils/AllowedMentions.js'; +import { colors, emojis, TanzaniteEvent } from '#lib/utils/Constants.js'; import { addOrRemoveFromArray } from '#lib/utils/Utils.js'; import assert from 'assert/strict'; import { @@ -43,7 +31,8 @@ import { type WebhookMessageOptions } from 'discord.js'; import _ from 'lodash'; -import { TanzaniteEvent } from './BotClientEvents.js'; +import { TanzaniteClient } from '../discord-akairo/TanzaniteClient.js'; +import { banResponse, BanResponse, dmResponse, permissionsResponse, punishmentEntryRemove } from './ExtendedGuildMember.js'; declare module 'discord.js' { export interface BaseGuild { diff --git a/lib/extensions/discord.js/ExtendedGuildMember.ts b/lib/extensions/discord.js/ExtendedGuildMember.ts index 172f6df..043cc1d 100644 --- a/lib/extensions/discord.js/ExtendedGuildMember.ts +++ b/lib/extensions/discord.js/ExtendedGuildMember.ts @@ -1,15 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { - formatError, - Moderation, - ModLogType, - TanzaniteClient, - Time, - type BotClientEvents, - type PunishmentTypeDM, - type ValueOf -} from '#lib'; -import { ChannelType, GuildMember, PermissionFlagsBits, @@ -17,7 +7,18 @@ import { type GuildTextBasedChannel, type Role } from 'discord.js'; -import { TanzaniteEvent } from './BotClientEvents.js'; +import { + checkMutePermissions, + createModLogEntry, + createPunishmentEntry, + punishDM, + PunishmentTypeDM, + removePunishmentEntry +} from '../../common/Moderation.js'; +import { ModLogType } from '../../models/index.js'; +import { TanzaniteEvent, Time } from '../../utils/Constants.js'; +import { formatError, ValueOf } from '../../utils/Utils.js'; +import { TanzaniteClient } from '../discord-akairo/TanzaniteClient.js'; /* eslint-enable @typescript-eslint/no-unused-vars */ declare module 'discord.js' { @@ -140,7 +141,7 @@ export class ExtendedGuildMember extends GuildMember { modlog?: string, sendFooter = true ): Promise<boolean> { - return Moderation.punishDM({ + return punishDM({ client: this.client, modlog, guild: this.guild, @@ -166,7 +167,7 @@ export class ExtendedGuildMember extends GuildMember { const ret = await (async (): Promise<{ result: WarnResponse; caseNum: number | null }> => { // add modlog entry - const result = await Moderation.createModLogEntry( + const result = await createModLogEntry( { client: this.client, type: ModLogType.WARN, @@ -214,7 +215,7 @@ export class ExtendedGuildMember extends GuildMember { const ret = await (async () => { if (options.addToModlog || options.duration) { - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: options.duration ? ModLogType.TEMP_PUNISHMENT_ROLE : ModLogType.PERM_PUNISHMENT_ROLE, guild: this.guild, @@ -230,7 +231,7 @@ export class ExtendedGuildMember extends GuildMember { caseID = modlog.id; if (options.addToModlog || options.duration) { - const punishmentEntrySuccess = await Moderation.createPunishmentEntry({ + const punishmentEntrySuccess = await createPunishmentEntry({ client: this.client, type: 'role', user: this, @@ -287,7 +288,7 @@ export class ExtendedGuildMember extends GuildMember { const ret = await (async () => { if (options.addToModlog) { - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.REMOVE_PUNISHMENT_ROLE, guild: this.guild, @@ -301,7 +302,7 @@ export class ExtendedGuildMember extends GuildMember { if (!modlog) return removeRoleResponse.MODLOG_ERROR; caseID = modlog.id; - const punishmentEntrySuccess = await Moderation.removePunishmentEntry({ + const punishmentEntrySuccess = await removePunishmentEntry({ client: this.client, type: 'role', user: this, @@ -370,7 +371,7 @@ export class ExtendedGuildMember extends GuildMember { */ public override async customMute(options: CustomTimedPunishmentOptions): Promise<MuteResponse> { // checks - const checks = await Moderation.checkMutePermissions(this.guild); + const checks = await checkMutePermissions(this.guild); if (checks !== true) return checks; const muteRoleID = (await this.guild.getSetting('muteRole'))!; @@ -393,7 +394,7 @@ export class ExtendedGuildMember extends GuildMember { if (!muteSuccess) return muteResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: options.duration ? ModLogType.TEMP_MUTE : ModLogType.PERM_MUTE, user: this, @@ -409,7 +410,7 @@ export class ExtendedGuildMember extends GuildMember { caseID = modlog.id; // add punishment entry so they can be unmuted later - const punishmentEntrySuccess = await Moderation.createPunishmentEntry({ + const punishmentEntrySuccess = await createPunishmentEntry({ client: this.client, type: 'mute', user: this, @@ -456,7 +457,7 @@ export class ExtendedGuildMember extends GuildMember { */ public override async customUnmute(options: CustomPunishmentOptions): Promise<UnmuteResponse> { // checks - const checks = await Moderation.checkMutePermissions(this.guild); + const checks = await checkMutePermissions(this.guild); if (checks !== true) return checks; const muteRoleID = (await this.guild.getSetting('muteRole'))!; @@ -478,7 +479,7 @@ export class ExtendedGuildMember extends GuildMember { if (!muteSuccess) return unmuteResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.UNMUTE, user: this, @@ -493,7 +494,7 @@ export class ExtendedGuildMember extends GuildMember { caseID = modlog.id; // remove mute entry - const removePunishmentEntrySuccess = await Moderation.removePunishmentEntry({ + const removePunishmentEntrySuccess = await removePunishmentEntry({ client: this.client, type: 'mute', user: this, @@ -548,7 +549,7 @@ export class ExtendedGuildMember extends GuildMember { if (!moderator) return kickResponse.CANNOT_RESOLVE_USER; const ret = await (async () => { // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.KICK, user: this, @@ -613,7 +614,7 @@ export class ExtendedGuildMember extends GuildMember { const ret = await (async () => { // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: options.duration ? ModLogType.TEMP_BAN : ModLogType.PERM_BAN, user: this, @@ -641,7 +642,7 @@ export class ExtendedGuildMember extends GuildMember { if (!banSuccess) return banResponse.ACTION_ERROR; // add punishment entry so they can be unbanned later - const punishmentEntrySuccess = await Moderation.createPunishmentEntry({ + const punishmentEntrySuccess = await createPunishmentEntry({ client: this.client, type: 'ban', user: this, @@ -699,7 +700,7 @@ export class ExtendedGuildMember extends GuildMember { if (!blockSuccess) return blockResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: options.duration ? ModLogType.TEMP_CHANNEL_BLOCK : ModLogType.PERM_CHANNEL_BLOCK, user: this, @@ -713,7 +714,7 @@ export class ExtendedGuildMember extends GuildMember { caseID = modlog.id; // add punishment entry so they can be unblocked later - const punishmentEntrySuccess = await Moderation.createPunishmentEntry({ + const punishmentEntrySuccess = await createPunishmentEntry({ client: this.client, type: 'block', user: this, @@ -727,7 +728,7 @@ export class ExtendedGuildMember extends GuildMember { // dm user const dmSuccess = options.silent ? null - : await Moderation.punishDM({ + : await punishDM({ client: this.client, punishment: 'blocked', reason: options.reason ?? undefined, @@ -793,7 +794,7 @@ export class ExtendedGuildMember extends GuildMember { if (!blockSuccess) return unblockResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.CHANNEL_UNBLOCK, user: this, @@ -807,7 +808,7 @@ export class ExtendedGuildMember extends GuildMember { caseID = modlog.id; // remove punishment entry - const punishmentEntrySuccess = await Moderation.removePunishmentEntry({ + const punishmentEntrySuccess = await removePunishmentEntry({ client: this.client, type: 'block', user: this, @@ -819,7 +820,7 @@ export class ExtendedGuildMember extends GuildMember { // dm user const dmSuccess = options.silent ? null - : await Moderation.punishDM({ + : await punishDM({ client: this.client, punishment: 'unblocked', reason: options.reason ?? undefined, @@ -880,7 +881,7 @@ export class ExtendedGuildMember extends GuildMember { if (!timeoutSuccess) return timeoutResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.TIMEOUT, user: this, @@ -942,7 +943,7 @@ export class ExtendedGuildMember extends GuildMember { if (!timeoutSuccess) return removeTimeoutResponse.ACTION_ERROR; // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ + const { log: modlog } = await createModLogEntry({ client: this.client, type: ModLogType.REMOVE_TIMEOUT, user: this, diff --git a/lib/utils/Arg.ts b/lib/utils/Arg.ts index 99060fb..80ca878 100644 --- a/lib/utils/Arg.ts +++ b/lib/utils/Arg.ts @@ -1,10 +1,4 @@ -import { - type BaseBotArgumentType, - type BotArgumentType, - type BotArgumentTypeCaster, - type CommandMessage, - type SlashMessage -} from '#lib'; +import type { BaseBotArgumentType, BotArgumentType, BotArgumentTypeCaster, CommandMessage, SlashMessage } from '#lib'; import { Argument, type Command, type Flag, type ParsedValuePredicate } from 'discord-akairo'; import { type Message } from 'discord.js'; diff --git a/lib/utils/BotClientUtils.ts b/lib/utils/BotClientUtils.ts index 1dd46bf..4b2c99b 100644 --- a/lib/utils/BotClientUtils.ts +++ b/lib/utils/BotClientUtils.ts @@ -1,8 +1,8 @@ -import { ConfigChannelKey } from '#config'; +import type { ConfigChannelKey } from '#config'; import type { CodeBlockLang, CustomInspectOptions } from '#lib'; -import { GlobalCache, SharedCache } from '#lib/common/BotCache.js'; -import { CommandMessage } from '#lib/extensions/discord-akairo/BotCommand.js'; -import { SlashMessage } from '#lib/extensions/discord-akairo/SlashMessage.js'; +import type { GlobalCache, SharedCache } from '#lib/common/BotCache.js'; +import type { CommandMessage } from '#lib/extensions/discord-akairo/BotCommand.js'; +import type { SlashMessage } from '#lib/extensions/discord-akairo/SlashMessage.js'; import { Global, Shared } from '#lib/models/index.js'; import assert from 'assert/strict'; import { diff --git a/lib/utils/Constants.ts b/lib/utils/Constants.ts index 8e4871b..c30d01d 100644 --- a/lib/utils/Constants.ts +++ b/lib/utils/Constants.ts @@ -1,10 +1,4 @@ import { default as 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, Snowflake } from 'discord.js'; const rawCapeUrl = 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/'; @@ -489,39 +483,6 @@ export const bots: Record<Snowflake, { applicationId: Snowflake }> = { } }; -export const ArgumentMatches = Object.freeze({ - ...AkairoArgumentMatches -} as const); - -export const ArgumentTypes = Object.freeze({ - ...AkairoArgumentTypes, - DURATION: 'duration', - CONTENT_WITH_DURATION: 'contentWithDuration', - PERMISSION: 'permission', - SNOWFLAKE: 'snowflake', - DISCORD_EMOJI: 'discordEmoji', - ROLE_WITH_DURATION: 'roleWithDuration', - ABBREVIATED_NUMBER: 'abbreviatedNumber', - GLOBAL_USER: 'globalUser' -} as const); - -export const BlockedReasons = Object.freeze({ - ...BuiltInReasons, - DISABLED_GUILD: 'disabledGuild', - DISABLED_GLOBAL: 'disabledGlobal', - ROLE_BLACKLIST: 'roleBlacklist', - USER_GUILD_BLACKLIST: 'userGuildBlacklist', - USER_GLOBAL_BLACKLIST: 'userGlobalBlacklist', - RESTRICTED_GUILD: 'restrictedGuild', - CHANNEL_GUILD_BLACKLIST: 'channelGuildBlacklist', - CHANNEL_GLOBAL_BLACKLIST: 'channelGlobalBlacklist', - RESTRICTED_CHANNEL: 'restrictedChannel' -} as const); - -export const CommandHandlerEvents = Object.freeze({ - ...AkairoCommandHandlerEvents -} as const); - export const moulberryBushRoleMap = deepLock([ { name: '*', id: '792453550768390194' }, { name: 'Admin Perms', id: '746541309853958186' }, @@ -552,3 +513,184 @@ export const moulberryBushRoleMap = deepLock([ export type PronounCode = keyof typeof pronounMapping; export type Pronoun = typeof pronounMapping[PronounCode]; + +export const enum ArgumentMatches { + Phrase = 'phrase', + Flag = 'flag', + Option = 'option', + Rest = 'rest', + Separate = 'separate', + Text = 'text', + Content = 'content', + RestContent = 'restContent', + None = 'none' +} + +export const enum ArgumentTypes { + String = 'string', + Lowercase = 'lowercase', + Uppercase = 'uppercase', + CharCodes = 'charCodes', + Number = 'number', + Integer = 'integer', + Bigint = 'bigint', + Emojint = 'emojint', + Url = 'url', + Date = 'date', + Color = 'color', + User = 'user', + Users = 'users', + Member = 'member', + Members = 'members', + Relevant = 'relevant', + Relevants = 'relevants', + Channel = 'channel', + Channels = 'channels', + TextChannel = 'textChannel', + TextChannels = 'textChannels', + VoiceChannel = 'voiceChannel', + VoiceChannels = 'voiceChannels', + CategoryChannel = 'categoryChannel', + CategoryChannels = 'categoryChannels', + NewsChannel = 'newsChannel', + NewsChannels = 'newsChannels', + StageChannel = 'stageChannel', + StageChannels = 'stageChannels', + ThreadChannel = 'threadChannel', + ThreadChannels = 'threadChannels', + DirectoryChannel = 'directoryChannel', + DirectoryChannels = 'directoryChannels', + ForumChannel = 'forumChannel', + ForumChannels = 'forumChannels', + TextBasedChannel = 'textBasedChannel', + TextBasedChannels = 'textBasedChannels', + VoiceBasedChannel = 'voiceBasedChannel', + VoiceBasedChannels = 'voiceBasedChannels', + Role = 'role', + Roles = 'roles', + Emoji = 'emoji', + Emojis = 'emojis', + Guild = 'guild', + Guilds = 'guilds', + Message = 'message', + GuildMessage = 'guildMessage', + RelevantMessage = 'relevantMessage', + Invite = 'invite', + UserMention = 'userMention', + MemberMention = 'memberMention', + ChannelMention = 'channelMention', + RoleMention = 'roleMention', + EmojiMention = 'emojiMention', + CommandAlias = 'commandAlias', + Command = 'command', + Inhibitor = 'inhibitor', + Listener = 'listener', + Task = 'task', + ContextMenuCommand = 'contextMenuCommand', + Duration = 'duration', + contentWithDuration = 'contentWithDuration', + Permission = 'permission', + DiscordEmoji = 'discordEmoji', + RoleWithDuration = 'roleWithDuration', + AbbreviatedNumber = 'abbreviatedNumber', + GlobalUser = 'globalUser' +} + +export const enum InhibitorReason { + Client = 'client', + Bot = 'bot', + Owner = 'owner', + SuperUser = 'superUser', + Guild = 'guild', + Dm = 'dm', + AuthorNotFound = 'authorNotFound', + NotNsfw = 'notNsfw', + DisabledGuild = 'disabledGuild', + DisabledGlobal = 'disabledGlobal', + RoleBlacklist = 'roleBlacklist', + UserGuildBlacklist = 'userGuildBlacklist', + UserGlobalBlacklist = 'userGlobalBlacklist', + RestrictedGuild = 'restrictedGuild', + ChannelGuildBlacklist = 'channelGuildBlacklist', + ChannelGlobalBlacklist = 'channelGlobalBlacklist', + RestrictedChannel = 'restrictedChannel', + GuildBlacklist = 'guildBlacklist', + Fatal = 'fatal', + CannotSend = 'cannotSend', + GuildUnavailable = 'guildUnavailable' +} + +export const enum InhibitorType { + /** + * Run on all messages + */ + All = 'all', + + /** + * Run on messages not blocked by the built-in inhibitors + */ + Pre = 'pre', + + /** + * Run on messages that are commands + */ + Post = 'post' +} + +export const enum CommandHandlerEvent { + CommandBlocked = 'commandBlocked', + CommandBreakout = 'commandBreakout', + CommandCancelled = 'commandCancelled', + CommandTimeout = 'commandTimeout', + CommandFinished = 'commandFinished', + CommandInvalid = 'commandInvalid', + CommandLocked = 'commandLocked', + CommandStarted = 'commandStarted', + Cooldown = 'cooldown', + Error = 'error', + InPrompt = 'inPrompt', + MessageBlocked = 'messageBlocked', + MessageInvalid = 'messageInvalid', + MissingPermissions = 'missingPermissions', + SlashBlocked = 'slashBlocked', + SlashError = 'slashError', + SlashFinished = 'slashFinished', + SlashMissingPermissions = 'slashMissingPermissions', + SlashNotFound = 'slashNotFound', + SlashStarted = 'slashStarted', + SlashOnly = 'slashOnly' +} + +export const enum ContextCommandHandlerEvent { + Error = 'error', + Finished = 'finished', + NotFound = 'notFound', + Started = 'started', + Blocked = 'blocked' +} + +export const enum TanzaniteEvent { + Ban = 'customBan', + Block = 'customBlock', + Kick = 'customKick', + Mute = 'customMute', + PunishRoleAdd = 'punishRoleAdd', + PunishRoleRemove = 'punishRoleRemove', + Purge = 'customPurge', + RemoveTimeout = 'customRemoveTimeout', + Timeout = 'customTimeout', + Unban = 'customUnban', + Unblock = 'customUnblock', + Unmute = 'customUnmute', + UpdateModlog = 'updateModlog', + UpdateSettings = 'updateSettings', + Warn = 'customWarn', + LevelUpdate = 'levelUpdate', + Lockdown = 'lockdown', + Unlockdown = 'unlockdown', + MassBan = 'massBan', + MassEvidence = 'massEvidence', + Button = 'button', + SelectMenu = 'selectMenu', + ModalSubmit = 'modal' +} diff --git a/lib/utils/Format.ts b/lib/utils/Format.ts index debaf4b..d1c0a51 100644 --- a/lib/utils/Format.ts +++ b/lib/utils/Format.ts @@ -1,4 +1,4 @@ -import { type CodeBlockLang } from '#lib'; +import type { CodeBlockLang } from '#lib'; import { bold as discordBold, codeBlock as discordCodeBlock, diff --git a/lib/utils/Utils.ts b/lib/utils/Utils.ts index f7404e1..9280e05 100644 --- a/lib/utils/Utils.ts +++ b/lib/utils/Utils.ts @@ -1,14 +1,3 @@ -import { - Arg, - CommandMessage, - SlashEditMessageType, - SlashSendMessageType, - TanzaniteClient, - timeUnits, - type BaseBotArgumentType, - type CustomInspectOptions, - type SlashMessage -} from '#lib'; import { humanizeDuration as humanizeDurationMod } from '@notenoughupdates/humanize-duration'; import assert from 'assert/strict'; import cp from 'child_process'; @@ -21,14 +10,21 @@ import { OAuth2Scopes, PermissionFlagsBits, PermissionsBitField, + PermissionsString, type APIEmbed, type APIMessage, type CommandInteraction, - type InteractionReplyOptions, - type PermissionsString + type InteractionReplyOptions } from 'discord.js'; import { DeepWritable } from 'ts-essentials'; import { inspect as inspectUtil, promisify } from 'util'; +import { BaseBotArgumentType, CommandMessage } from '../extensions/discord-akairo/BotCommand.js'; +import { SlashMessage } from '../extensions/discord-akairo/SlashMessage.js'; +import { TanzaniteClient } from '../extensions/discord-akairo/TanzaniteClient.js'; +import { CustomInspectOptions } from '../types/InspectOptions.js'; +import { SlashEditMessageType, SlashSendMessageType } from '../types/misc.js'; +import * as Arg from './Arg.js'; +import { mappings, timeUnits } from './Constants.js'; import * as Format from './Format.js'; export type StripPrivate<T> = { [K in keyof T]: T[K] extends Record<string, any> ? StripPrivate<T[K]> : T[K] }; @@ -428,68 +424,8 @@ export function getSymbols(obj: Record<string, any>): symbol[] { return symbols; } -/** - * Checks if a user has a certain guild permission (doesn't check channel permissions). - * @param message The message to check the user from. - * @param permissions The permissions to check for. - * @returns The missing permissions or null if none are missing. - */ -export function userGuildPermCheck( - message: CommandMessage | SlashMessage, - permissions: typeof PermissionFlagsBits[keyof typeof PermissionFlagsBits][] -): PermissionsString[] | null { - if (!message.inGuild()) return null; - const missing = message.member?.permissions.missing(permissions) ?? []; - - return missing.length ? missing : null; -} - -/** - * Check if the client has certain permissions in the guild (doesn't check channel permissions). - * @param message The message to check the client user from. - * @param permissions The permissions to check for. - * @returns The missing permissions or null if none are missing. - */ -export function clientGuildPermCheck(message: CommandMessage | SlashMessage, permissions: bigint[]): PermissionsString[] | null { - const missing = message.guild?.members.me?.permissions.missing(permissions) ?? []; - - return missing.length ? missing : null; -} - -/** - * Check if the client has permission to send messages in the channel as well as check if they have other permissions - * in the guild (or the channel if `checkChannel` is `true`). - * @param message The message to check the client user from. - * @param permissions The permissions to check for. - * @param checkChannel Whether to check the channel permissions instead of the guild permissions. - * @returns The missing permissions or null if none are missing. - */ -export function clientSendAndPermCheck( - message: CommandMessage | SlashMessage, - permissions: bigint[] = [], - checkChannel = false -): PermissionsString[] | null { - if (!message.inGuild() || !message.channel) return null; - - const missing: PermissionsString[] = []; - const sendPerm = message.channel.isThread() ? 'SendMessages' : 'SendMessagesInThreads'; - - // todo: remove once forum channels are fixed - if (message.channel.parent === null && message.channel.isThread()) return null; - - if (!message.guild.members.me!.permissionsIn(message.channel!.id).has(sendPerm)) missing.push(sendPerm); - - missing.push( - ...(checkChannel - ? message.guild!.members.me!.permissionsIn(message.channel!.id!).missing(permissions) - : clientGuildPermCheck(message, permissions) ?? []) - ); - - return missing.length ? missing : null; -} - +export * as arg from './Arg.js'; export { deepLock as deepFreeze }; -export { Arg as arg }; export { Format as format }; export { DiscordConstants as discordConstants }; export { AkairoUtil as akairo }; @@ -613,3 +549,7 @@ export function formatError(error: Error | any, colors = false): string { export function deepWriteable<T>(obj: T): DeepWritable<T> { return obj as DeepWritable<T>; } + +export function formatPerms(permissions: PermissionsString[]) { + return permissions.map((p) => `\`${mappings.permissions[p]?.name ?? p}\``).join(', '); +} diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts index e17a85b..46f6db3 100644 --- a/src/commands/admin/channelPermissions.ts +++ b/src/commands/admin/channelPermissions.ts @@ -2,7 +2,6 @@ import { Arg, BotCommand, ButtonPaginator, - clientSendAndPermCheck, emojis, formatError, type ArgType, @@ -10,7 +9,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default class ChannelPermissionsCommand extends BotCommand { public constructor() { @@ -58,8 +57,8 @@ export default class ChannelPermissionsCommand extends BotCommand { ] } ], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]), - userPermissions: [PermissionFlagsBits.Administrator], + clientPermissions: ['ManageChannels'], + userPermissions: ['Administrator'], channel: 'guild', slash: true, lock: 'guild' diff --git a/src/commands/admin/roleAll.ts b/src/commands/admin/roleAll.ts index 3675891..446f3cd 100644 --- a/src/commands/admin/roleAll.ts +++ b/src/commands/admin/roleAll.ts @@ -1,12 +1,4 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - emojis, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; @@ -38,8 +30,8 @@ export default class RoleAllCommand extends BotCommand { } ], channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]), - userPermissions: [PermissionFlagsBits.Administrator], + clientPermissions: ['ManageRoles'], + userPermissions: ['Administrator'], typing: true, slash: true, lock: 'guild' diff --git a/src/commands/config/_customAutomodPhrases.ts b/src/commands/config/_customAutomodPhrases.ts index 0b571e5..5925fb5 100644 --- a/src/commands/config/_customAutomodPhrases.ts +++ b/src/commands/config/_customAutomodPhrases.ts @@ -30,8 +30,8 @@ // ], // slash: true, // channel: 'guild', -// clientPermissions: (m) => clientSendAndPermCheck(m), -// userPermissions: [PermissionFlagsBits.ManageGuild] +// clientPermissions: [], +// userPermissions: ['ManageGuild'] // }); // } diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts index 5419658..c7f3d99 100644 --- a/src/commands/config/blacklist.ts +++ b/src/commands/config/blacklist.ts @@ -3,7 +3,6 @@ import { AllowedMentions, Arg, BotCommand, - clientSendAndPermCheck, emojis, format, type ArgType, @@ -11,7 +10,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, GuildMember, PermissionFlagsBits, User } from 'discord.js'; +import { ApplicationCommandOptionType, GuildMember, User } from 'discord.js'; export default class BlacklistCommand extends BotCommand { public constructor() { @@ -52,8 +51,8 @@ export default class BlacklistCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.ManageGuild] + clientPermissions: [], + userPermissions: ['ManageGuild'] }); } diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts index a37d67c..b923d56 100644 --- a/src/commands/config/config.ts +++ b/src/commands/config/config.ts @@ -1,7 +1,6 @@ import { addOrRemoveFromArray, BotCommand, - clientSendAndPermCheck, colors, emojis, GuildNoArraySetting, @@ -149,8 +148,8 @@ export default class ConfigCommand extends BotCommand { }; }), channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.ManageGuild] + clientPermissions: [], + userPermissions: ['ManageGuild'] }); } diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts index a4a876c..6dd94a6 100644 --- a/src/commands/config/disable.ts +++ b/src/commands/config/disable.ts @@ -3,14 +3,13 @@ import { AllowedMentions, Arg, BotCommand, - clientSendAndPermCheck, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, AutocompleteInteraction, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, AutocompleteInteraction } from 'discord.js'; import { default as Fuse } from 'fuse.js'; assert(Fuse); @@ -29,7 +28,7 @@ export default class DisableCommand extends BotCommand { { id: 'action', description: 'Whether to disable or enable the command.', - readableType: "'disable'|'enable", + readableType: "'disable'|'enable'", prompt: 'Would you like to disable or enable a command?', slashType: ApplicationCommandOptionType.String, choices: ['disable', 'enable'].map((v) => ({ name: v, value: v })), @@ -58,8 +57,8 @@ export default class DisableCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.ManageGuild] + clientPermissions: [], + userPermissions: ['ManageGuild'] }); } diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts index 55f99bd..8d69d17 100644 --- a/src/commands/config/features.ts +++ b/src/commands/config/features.ts @@ -1,6 +1,5 @@ import { BotCommand, - clientSendAndPermCheck, colors, emojis, guildFeaturesArr, @@ -14,7 +13,6 @@ import { ActionRowBuilder, ComponentType, EmbedBuilder, - PermissionFlagsBits, SelectMenuBuilder, type Message, type SelectMenuInteraction @@ -30,8 +28,9 @@ export default class FeaturesCommand extends BotCommand { examples: ['features'], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), - userPermissions: [PermissionFlagsBits.ManageGuild] + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, + userPermissions: ['ManageGuild'] }); } diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts index f058670..493d486 100644 --- a/src/commands/config/log.ts +++ b/src/commands/config/log.ts @@ -1,6 +1,5 @@ import { BotCommand, - clientSendAndPermCheck, emojis, guildLogsArr, oxford, @@ -11,7 +10,7 @@ import { } from '#lib'; import assert from 'assert/strict'; import { ArgumentGeneratorReturn } from 'discord-akairo'; -import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, ChannelType } from 'discord.js'; export default class LogCommand extends BotCommand { public constructor() { @@ -48,8 +47,8 @@ export default class LogCommand extends BotCommand { } ], channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.ManageGuild] + clientPermissions: [], + userPermissions: ['ManageGuild'] }); } diff --git a/src/commands/dev/__template.ts b/src/commands/dev/__template.ts index fbb88ac..0fc133f 100644 --- a/src/commands/dev/__template.ts +++ b/src/commands/dev/__template.ts @@ -1,12 +1,4 @@ -import { - BotCommand, - clientSendAndPermCheck, - emojis, - type ArgType, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { BotCommand, emojis, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import { ApplicationCommandOptionType } from 'discord.js'; export default class TemplateCommand extends BotCommand { @@ -41,7 +33,7 @@ export default class TemplateCommand extends BotCommand { ownerOnly: true, channel: 'guild', hidden: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/dev/dm.ts b/src/commands/dev/dm.ts index e51651e..c3b2831 100644 --- a/src/commands/dev/dm.ts +++ b/src/commands/dev/dm.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import { ApplicationCommandOptionType } from 'discord.js'; export default class DMCommand extends BotCommand { @@ -31,7 +31,8 @@ export default class DMCommand extends BotCommand { slash: false, ownerOnly: true, hidden: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + skipSendCheck: true, + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 3929f99..83168e0 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -173,6 +173,7 @@ export default class EvalCommand extends BotCommand { ], slash: true, ownerOnly: true, + skipSendCheck: true, clientPermissions: [], userPermissions: [] }); diff --git a/src/commands/dev/javascript.ts b/src/commands/dev/javascript.ts index 43ccf94..c34ec42 100644 --- a/src/commands/dev/javascript.ts +++ b/src/commands/dev/javascript.ts @@ -1,13 +1,4 @@ -import { - BotCommand, - clientSendAndPermCheck, - colors, - emojis, - type ArgType, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { BotCommand, colors, emojis, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; import { VM } from 'vm2'; @@ -44,7 +35,8 @@ export default class JavascriptCommand extends BotCommand { ], slash: true, superUserOnly: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts index 2d5b9d9..57746b3 100644 --- a/src/commands/dev/reload.ts +++ b/src/commands/dev/reload.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, emojis, formatError, shell, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, emojis, formatError, shell, type CommandMessage, type SlashMessage } from '#lib'; export default class ReloadCommand extends BotCommand { public constructor() { @@ -11,7 +11,8 @@ export default class ReloadCommand extends BotCommand { ownerOnly: true, typing: true, slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + skipSendCheck: true, + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/dev/say.ts b/src/commands/dev/say.ts index 22ad9ba..de3bdb1 100644 --- a/src/commands/dev/say.ts +++ b/src/commands/dev/say.ts @@ -21,6 +21,7 @@ export default class SayCommand extends BotCommand { } ], ownerOnly: true, + skipSendCheck: true, clientPermissions: [], userPermissions: [], slash: true diff --git a/src/commands/dev/servers.ts b/src/commands/dev/servers.ts index 6bba93c..3207225 100644 --- a/src/commands/dev/servers.ts +++ b/src/commands/dev/servers.ts @@ -1,13 +1,4 @@ -import { - BotCommand, - ButtonPaginator, - chunk, - clientSendAndPermCheck, - colors, - format, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { BotCommand, ButtonPaginator, chunk, colors, format, type CommandMessage, type SlashMessage } from '#lib'; import { stripIndent } from '#tags'; import { type APIEmbed, type Guild } from 'discord.js'; @@ -19,7 +10,7 @@ export default class ServersCommand extends BotCommand { description: 'Displays all the severs the bot is in', usage: ['servers'], examples: ['servers'], - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], ownerOnly: true }); diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts index 6a034bc..fc7fcbf 100644 --- a/src/commands/dev/superUser.ts +++ b/src/commands/dev/superUser.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, emojis, format, type ArgType, type CommandMessage } from '#lib'; +import { BotCommand, emojis, format, type ArgType, type CommandMessage } from '#lib'; import { type ArgumentGeneratorReturn, type ArgumentTypeCasterReturn } from 'discord-akairo'; export default class SuperUserCommand extends BotCommand { @@ -9,9 +9,6 @@ export default class SuperUserCommand extends BotCommand { description: 'A command to manage superusers.', usage: ['superuser <add/remove> <user>'], examples: ['superuser add IRONM00N'], - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [], - ownerOnly: true, helpArgs: [ { name: 'action', @@ -24,7 +21,10 @@ export default class SuperUserCommand extends BotCommand { type: 'user', match: 'restContent' } - ] + ], + clientPermissions: [], + userPermissions: [], + ownerOnly: true }); } diff --git a/src/commands/dev/syncAutomod.ts b/src/commands/dev/syncAutomod.ts index 7a0fb58..087d7e6 100644 --- a/src/commands/dev/syncAutomod.ts +++ b/src/commands/dev/syncAutomod.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, emojis, Shared, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, emojis, Shared, type CommandMessage, type SlashMessage } from '#lib'; import typescript from 'typescript'; import { NodeVM } from 'vm2'; @@ -12,7 +12,7 @@ export default class SyncAutomodCommand extends BotCommand { examples: ['sync-automod'], slash: false, hidden: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index cc32657..e1f3b73 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,13 +1,4 @@ -import { - BotCommand, - ButtonPaginator, - clientSendAndPermCheck, - colors, - emojis, - OptArgType, - Shared, - type CommandMessage -} from '#lib'; +import { BotCommand, ButtonPaginator, colors, emojis, OptArgType, Shared, type CommandMessage } from '#lib'; import { ActionRowBuilder, ButtonBuilder, @@ -42,7 +33,8 @@ export default class TestCommand extends BotCommand { } ], superUserOnly: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/fun/coinFlip.ts b/src/commands/fun/coinFlip.ts index 66b6016..c97c808 100644 --- a/src/commands/fun/coinFlip.ts +++ b/src/commands/fun/coinFlip.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class CoinFlipCommand extends BotCommand { public constructor() { @@ -8,7 +8,7 @@ export default class CoinFlipCommand extends BotCommand { description: 'Flip a virtual coin.', usage: ['coinflip'], examples: ['coinflip'], - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], slash: true }); diff --git a/src/commands/fun/dice.ts b/src/commands/fun/dice.ts index 5941564..99871c2 100644 --- a/src/commands/fun/dice.ts +++ b/src/commands/fun/dice.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class DiceCommand extends BotCommand { public constructor() { @@ -8,7 +8,7 @@ export default class DiceCommand extends BotCommand { description: 'Roll virtual dice.', usage: ['dice'], examples: ['dice'], - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], slash: true }); diff --git a/src/commands/fun/eightBall.ts b/src/commands/fun/eightBall.ts index be9c7b5..ea6942d 100644 --- a/src/commands/fun/eightBall.ts +++ b/src/commands/fun/eightBall.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, type CommandMessage, type SlashMessage } from '#lib'; import { ApplicationCommandOptionType } from 'discord.js'; export default class EightBallCommand extends BotCommand { @@ -21,7 +21,7 @@ export default class EightBallCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts index ec21b11..85945c7 100644 --- a/src/commands/fun/minesweeper.ts +++ b/src/commands/fun/minesweeper.ts @@ -1,12 +1,4 @@ -import { - BotCommand, - clientSendAndPermCheck, - emojis, - OptArgType, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { BotCommand, emojis, OptArgType, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import { Minesweeper } from '@notenoughupdates/discord.js-minesweeper'; import assert from 'assert/strict'; import { ApplicationCommandOptionType } from 'discord.js'; @@ -71,7 +63,7 @@ export default class MinesweeperCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts index b97364f..aaeebbf 100644 --- a/src/commands/info/avatar.ts +++ b/src/commands/info/avatar.ts @@ -1,5 +1,5 @@ -import { Arg, BotCommand, clientSendAndPermCheck, colors, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; -import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, PermissionFlagsBits } from 'discord.js'; +import { Arg, BotCommand, colors, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; +import { ApplicationCommandOptionType, EmbedBuilder, GuildMember } from 'discord.js'; export default class AvatarCommand extends BotCommand { public constructor() { @@ -21,7 +21,8 @@ export default class AvatarCommand extends BotCommand { slashType: ApplicationCommandOptionType.User } ], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], slash: true }); diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts index 64ecf1d..a877073 100644 --- a/src/commands/info/botInfo.ts +++ b/src/commands/info/botInfo.ts @@ -1,14 +1,6 @@ -import { - BotCommand, - clientSendAndPermCheck, - colors, - humanizeDuration, - shell, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { BotCommand, colors, humanizeDuration, shell, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { EmbedBuilder, PermissionFlagsBits, version as discordJSVersion } from 'discord.js'; +import { EmbedBuilder, version as discordJSVersion } from 'discord.js'; import * as os from 'os'; const { default: prettyBytes } = await import('pretty-bytes'); assert(prettyBytes); @@ -23,7 +15,8 @@ export default class BotInfoCommand extends BotCommand { usage: ['bot-info'], examples: ['bot-info'], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts index c139e1a..b396baa 100644 --- a/src/commands/info/color.ts +++ b/src/commands/info/color.ts @@ -1,15 +1,6 @@ -import { - AllowedMentions, - Arg, - BotCommand, - clientSendAndPermCheck, - emojis, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, Arg, BotCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, PermissionFlagsBits, Role } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, Role } from 'discord.js'; import tinycolor from 'tinycolor2'; assert(tinycolor); @@ -34,7 +25,8 @@ export default class ColorCommand extends BotCommand { } ], channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index 97e4be3..e364a89 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -2,7 +2,6 @@ import { akairo, Arg, BotCommand, - clientSendAndPermCheck, colors, emojis, mappings, @@ -52,7 +51,8 @@ export default class GuildInfoCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index 6460b99..1680b75 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -1,9 +1,10 @@ import { BotCommand, - clientSendAndPermCheck, colors, format, + formatPerms, invite, + permissionCheck, type ArgType, type CommandMessage, type OptArgType, @@ -17,8 +18,7 @@ import { AutocompleteInteraction, ButtonBuilder, ButtonStyle, - EmbedBuilder, - PermissionFlagsBits + EmbedBuilder } from 'discord.js'; import { default as Fuse } from 'fuse.js'; import packageDotJSON from '../../../package.json' assert { type: 'json' }; @@ -58,7 +58,8 @@ export default class HelpCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } @@ -88,14 +89,24 @@ export default class HelpCommand extends BotCommand { .setFooter({ text: `For more information about a command use ${prefix_}help <command>` }); for (const [, category] of this.handler.categories.sort((a, b) => a.id.localeCompare(b.id))) { const categoryFilter = category.filter((command) => { + const inGuild = message.inGuild(); + if (command.pseudo) return false; if (command.hidden && !args.showHidden) return false; - if (command.channel == 'guild' && !message.guild && !args.showHidden) return false; + if (command.channel == 'guild' && !inGuild && !args.showHidden) return false; if (command.ownerOnly && !message.author.isOwner()) return false; if (command.superUserOnly && !message.author.isSuperUser()) return false; if (command.restrictedGuilds?.includes(message.guild?.id ?? '') === false && !args.showHidden) return false; if (command.aliases.length === 0) return false; + permissions: { + if (!inGuild || !message.member) break permissions; + + const canUse = permissionCheck(message, message.member, command.userPermissions, false); + + if (!canUse) return false; + } + return true; }); const categoryNice = category.id @@ -121,7 +132,7 @@ export default class HelpCommand extends BotCommand { this.addCommandAliases(embed, command); this.addCommandArguments(embed, command, message.author.isOwner(), message.author.isSuperUser()); this.addCommandRestrictions(embed, command); - // todo: permissions + this.addCommandPermissions(embed, command); const params = { embeds: [embed], components: row.components.length ? [row] : undefined }; return message.util.reply(params); @@ -178,6 +189,7 @@ export default class HelpCommand extends BotCommand { return ret; }) .join('\n') + .slice(0, 1024) }); } } @@ -209,6 +221,14 @@ export default class HelpCommand extends BotCommand { } } + private addCommandPermissions(embed: EmbedBuilder, command: BotCommand): void { + if (command.userPermissions.length < 1 && command.clientPermissions.length < 1) return; + const permissions: string[] = []; + if (command.userPermissions.length > 0) permissions.push(`__User__: ${formatPerms(command.userPermissions)}`); + if (command.clientPermissions.length > 0) permissions.push(`__Client__: ${formatPerms(command.clientPermissions)}`); + embed.addFields({ name: '» Required Permissions', value: permissions.join('\n') }); + } + private addLinks(message: CommandMessage | SlashMessage): ActionRowBuilder<ButtonBuilder> { const row = new ActionRowBuilder<ButtonBuilder>(); const config = this.client.config; diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts index 71f02f9..ed7e8ca 100644 --- a/src/commands/info/icon.ts +++ b/src/commands/info/icon.ts @@ -1,6 +1,6 @@ -import { BotCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, colors, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { EmbedBuilder, escapeMarkdown, PermissionFlagsBits } from 'discord.js'; +import { EmbedBuilder, escapeMarkdown } from 'discord.js'; export default class IconCommand extends BotCommand { public constructor() { @@ -10,7 +10,8 @@ export default class IconCommand extends BotCommand { description: "A command to get the server's icon", usage: ['icon'], examples: ['icon'], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], channel: 'guild', slash: true diff --git a/src/commands/info/inviteInfo.ts b/src/commands/info/inviteInfo.ts index 590bf16..bf66a4c 100644 --- a/src/commands/info/inviteInfo.ts +++ b/src/commands/info/inviteInfo.ts @@ -1,5 +1,5 @@ -import { Arg, ArgType, BotCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib'; -import { ApplicationCommandOptionType, EmbedBuilder, Invite, PermissionFlagsBits } from 'discord.js'; +import { Arg, ArgType, BotCommand, colors, type CommandMessage, type SlashMessage } from '#lib'; +import { ApplicationCommandOptionType, EmbedBuilder, Invite } from 'discord.js'; export default class InviteInfoCommand extends BotCommand { public constructor() { @@ -20,7 +20,9 @@ export default class InviteInfoCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + hidden: true, + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts index ecc09c8..b3d0292 100644 --- a/src/commands/info/links.ts +++ b/src/commands/info/links.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, invite, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, invite, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; import packageDotJSON from '../../../package.json' assert { type: 'json' }; @@ -13,7 +13,7 @@ export default class LinksCommand extends BotCommand { description: 'Sends bot links', usage: ['links'], examples: ['links'], - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], slash: true }); diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts index 91bec1d..ad58cc0 100644 --- a/src/commands/info/ping.ts +++ b/src/commands/info/ping.ts @@ -1,5 +1,5 @@ -import { BotCommand, clientSendAndPermCheck, colors, format, type CommandMessage, type SlashMessage } from '#lib'; -import { EmbedBuilder, PermissionFlagsBits, type Message } from 'discord.js'; +import { BotCommand, colors, format, type CommandMessage, type SlashMessage } from '#lib'; +import { EmbedBuilder, type Message } from 'discord.js'; export default class PingCommand extends BotCommand { public constructor() { @@ -10,7 +10,8 @@ export default class PingCommand extends BotCommand { usage: ['ping'], examples: ['ping'], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts index 47061fc..138bdfc 100644 --- a/src/commands/info/pronouns.ts +++ b/src/commands/info/pronouns.ts @@ -1,12 +1,5 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; -import { ApplicationCommandOptionType, EmbedBuilder, escapeMarkdown, PermissionFlagsBits } from 'discord.js'; +import { AllowedMentions, BotCommand, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; +import { ApplicationCommandOptionType, EmbedBuilder, escapeMarkdown } from 'discord.js'; export default class PronounsCommand extends BotCommand { public constructor() { @@ -27,7 +20,8 @@ export default class PronounsCommand extends BotCommand { slashType: ApplicationCommandOptionType.User } ], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], slash: true }); diff --git a/src/commands/info/snowflake.ts b/src/commands/info/snowflake.ts index deaf41c..ba93611 100644 --- a/src/commands/info/snowflake.ts +++ b/src/commands/info/snowflake.ts @@ -1,19 +1,10 @@ -import { - BotCommand, - clientSendAndPermCheck, - colors, - timestamp, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { BotCommand, colors, timestamp, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import { stripIndent } from '#tags'; import { ApplicationCommandOptionType, ChannelType, EmbedBuilder, escapeMarkdown, - PermissionFlagsBits, SnowflakeUtil, type DeconstructedSnowflake, type Snowflake @@ -37,7 +28,8 @@ export default class SnowflakeCommand extends BotCommand { slashType: ApplicationCommandOptionType.String } ], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], slash: true }); diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts index 52875ef..f70896d 100644 --- a/src/commands/info/userInfo.ts +++ b/src/commands/info/userInfo.ts @@ -2,9 +2,9 @@ import { Arg, BotCommand, bots, - clientSendAndPermCheck, colors, emojis, + formatPerms, mappings, oxford, sleep, @@ -51,7 +51,8 @@ export default class UserInfoCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } @@ -246,11 +247,7 @@ export default class UserInfoCommand extends BotCommand { if (member?.permissions.has(PermissionFlagsBits.Administrator) || member.guild?.ownerId == member.user.id) { perms.push('`Administrator`'); } else if (member?.permissions.toArray().length) { - member.permissions.toArray().forEach((permission) => { - if (mappings.permissions[permission]?.important) { - perms.push(`\`${mappings.permissions[permission].name}\``); - } - }); + perms.push(formatPerms(member.permissions.toArray().filter((p) => mappings.permissions[p]?.important === true))); } if (perms.length) embed.addFields({ name: title, value: perms.join(' ') }); diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts index 109f398..50af997 100644 --- a/src/commands/leveling/leaderboard.ts +++ b/src/commands/leveling/leaderboard.ts @@ -1,14 +1,4 @@ -import { - BotCommand, - ButtonPaginator, - chunk, - clientSendAndPermCheck, - emojis, - Level, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { BotCommand, ButtonPaginator, chunk, emojis, Level, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; @@ -33,7 +23,8 @@ export default class LeaderboardCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts index 2547b06..869140d 100644 --- a/src/commands/leveling/level.ts +++ b/src/commands/leveling/level.ts @@ -2,7 +2,6 @@ import { AllowedMentions, BotCommand, CanvasProgressBar, - clientSendAndPermCheck, emojis, Level, type CommandMessage, @@ -37,7 +36,8 @@ export default class LevelCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['AttachFiles'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/leveling/levelRoles.ts b/src/commands/leveling/levelRoles.ts index 4973b01..860e88a 100644 --- a/src/commands/leveling/levelRoles.ts +++ b/src/commands/leveling/levelRoles.ts @@ -1,15 +1,6 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - emojis, - type ArgType, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, emojis, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class LevelRolesCommand extends BotCommand { public constructor() { @@ -42,8 +33,8 @@ export default class LevelRolesCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]), - userPermissions: [PermissionFlagsBits.ManageGuild, PermissionFlagsBits.ManageRoles] + clientPermissions: ['ManageRoles'], + userPermissions: ['ManageGuild', 'ManageRoles'] }); } diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts index cd30978..6f6f69e 100644 --- a/src/commands/leveling/setLevel.ts +++ b/src/commands/leveling/setLevel.ts @@ -1,16 +1,6 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - Level, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, emojis, format, Level, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class SetLevelCommand extends BotCommand { public constructor() { @@ -40,8 +30,8 @@ export default class SetLevelCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.Administrator] + clientPermissions: [], + userPermissions: ['Administrator'] }); } diff --git a/src/commands/leveling/setXp.ts b/src/commands/leveling/setXp.ts index 23f4463..8c3b86f 100644 --- a/src/commands/leveling/setXp.ts +++ b/src/commands/leveling/setXp.ts @@ -1,16 +1,6 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - Level, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, emojis, format, Level, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class SetXpCommand extends BotCommand { public constructor() { @@ -41,8 +31,8 @@ export default class SetXpCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.Administrator] + clientPermissions: [], + userPermissions: ['Administrator'] }); } diff --git a/src/commands/moderation/_activePunishments.ts b/src/commands/moderation/_activePunishments.ts index 4ded902..140e540 100644 --- a/src/commands/moderation/_activePunishments.ts +++ b/src/commands/moderation/_activePunishments.ts @@ -47,8 +47,8 @@ // slash: true, // channel: 'guild', // hidden: true, -// clientPermissions: (m) => clientSendAndPermCheck(m), -// userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) +// clientPermissions: [], +// userPermissions: ['ManageMessages'] // }); // } diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index fdb8033..aee8805 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -14,7 +14,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type User } from 'discord.js'; +import { ApplicationCommandOptionType, type User } from 'discord.js'; export default class BanCommand extends BotCommand { public constructor() { @@ -70,8 +70,8 @@ export default class BanCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: [PermissionFlagsBits.BanMembers], - userPermissions: [PermissionFlagsBits.BanMembers] + clientPermissions: ['BanMembers'], + userPermissions: ['BanMembers'] }); } diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts index a3f7bc1..a5ad31d 100644 --- a/src/commands/moderation/block.ts +++ b/src/commands/moderation/block.ts @@ -3,11 +3,9 @@ import { blockResponse, BotCommand, castDurationContent, - clientSendAndPermCheck, emojis, format, Moderation, - userGuildPermCheck, type ArgType, type BlockResponse, type CommandMessage, @@ -15,7 +13,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class BlockCommand extends BotCommand { public constructor() { @@ -57,8 +55,8 @@ export default class BlockCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]), + clientPermissions: ['ManageChannels'], + userPermissions: ['ManageMessages'], lock: 'channel' }); } diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts index bc4cdb2..9a5e70f 100644 --- a/src/commands/moderation/evidence.ts +++ b/src/commands/moderation/evidence.ts @@ -1,20 +1,18 @@ import { BotCommand, - clientSendAndPermCheck, emojis, format, ModLog, OptArgType, regex, TanzaniteEvent, - userGuildPermCheck, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { Argument, ArgumentGeneratorReturn } from 'discord-akairo'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type Message } from 'discord.js'; +import { ApplicationCommandOptionType, type Message } from 'discord.js'; export default class EvidenceCommand extends BotCommand { public constructor() { @@ -55,8 +53,8 @@ export default class EvidenceCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: [], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts index ca87ea5..6c50157 100644 --- a/src/commands/moderation/hideCase.ts +++ b/src/commands/moderation/hideCase.ts @@ -1,16 +1,6 @@ -import { - BotCommand, - clientSendAndPermCheck, - emojis, - format, - ModLog, - TanzaniteEvent, - userGuildPermCheck, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { BotCommand, emojis, format, ModLog, TanzaniteEvent, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; export default class HideCaseCommand extends BotCommand { public constructor() { @@ -31,8 +21,8 @@ export default class HideCaseCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]), + clientPermissions: [], + userPermissions: ['ManageMessages'], channel: 'guild' }); } diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts index a5938f8..82ddce4 100644 --- a/src/commands/moderation/kick.ts +++ b/src/commands/moderation/kick.ts @@ -1,7 +1,6 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, emojis, format, kickResponse, @@ -13,7 +12,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class KickCommand extends BotCommand { public constructor() { @@ -54,8 +53,8 @@ export default class KickCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.KickMembers]), - userPermissions: [PermissionFlagsBits.KickMembers] + clientPermissions: ['KickMembers'], + userPermissions: ['KickMembers'] }); } diff --git a/src/commands/moderation/lockdown.ts b/src/commands/moderation/lockdown.ts index 57f9caf..c88cc17 100644 --- a/src/commands/moderation/lockdown.ts +++ b/src/commands/moderation/lockdown.ts @@ -1,7 +1,6 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, colors, ConfirmationPrompt, emojis, @@ -17,7 +16,6 @@ import { Collection, Constants, NewsChannel, - PermissionFlagsBits, TextChannel, ThreadChannel, VoiceChannel @@ -62,8 +60,9 @@ export default class LockdownCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]), - userPermissions: [PermissionFlagsBits.ManageChannels], + clientPermissions: ['ManageChannels'], + userPermissions: ['ManageChannels'], + userCheckChannel: true, lock: 'channel' }); } diff --git a/src/commands/moderation/massBan.ts b/src/commands/moderation/massBan.ts index 4ba4f47..445506f 100644 --- a/src/commands/moderation/massBan.ts +++ b/src/commands/moderation/massBan.ts @@ -3,7 +3,6 @@ import { BanResponse, banResponse, BotCommand, - clientSendAndPermCheck, colors, emojis, overflowEmbed, @@ -15,7 +14,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, Collection, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, Collection } from 'discord.js'; export default class MassBanCommand extends BotCommand { public constructor() { @@ -61,8 +60,9 @@ export default class MassBanCommand extends BotCommand { quoted: true, slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.BanMembers], + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, + userPermissions: ['BanMembers'], lock: 'user' }); } diff --git a/src/commands/moderation/massEvidence.ts b/src/commands/moderation/massEvidence.ts index b44060e..29d806e 100644 --- a/src/commands/moderation/massEvidence.ts +++ b/src/commands/moderation/massEvidence.ts @@ -1,6 +1,5 @@ import { BotCommand, - clientSendAndPermCheck, colors, emojis, ModLog, @@ -13,7 +12,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; import EvidenceCommand from './evidence.js'; export default class MassEvidenceCommand extends BotCommand { @@ -50,8 +49,8 @@ export default class MassEvidenceCommand extends BotCommand { quoted: true, slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: [PermissionFlagsBits.ManageMessages], + clientPermissions: ['EmbedLinks'], + userPermissions: ['ManageMessages'], lock: 'user' }); } diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts index 08e5397..dcab9ef 100644 --- a/src/commands/moderation/modlog.ts +++ b/src/commands/moderation/modlog.ts @@ -3,19 +3,17 @@ import { BotCommand, ButtonPaginator, chunk, - clientSendAndPermCheck, colors, emojis, humanizeDuration, ModLog, timestamp, - userGuildPermCheck, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, escapeMarkdown, PermissionFlagsBits, User } from 'discord.js'; +import { ApplicationCommandOptionType, escapeMarkdown, User } from 'discord.js'; export default class ModlogCommand extends BotCommand { public static separator = '\n━━━━━━━━━━━━━━━\n'; @@ -48,8 +46,8 @@ export default class ModlogCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: [], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts index debcf03..9ffaf8d 100644 --- a/src/commands/moderation/mute.ts +++ b/src/commands/moderation/mute.ts @@ -2,12 +2,10 @@ import { AllowedMentions, BotCommand, castDurationContent, - clientSendAndPermCheck, emojis, format, Moderation, muteResponse, - userGuildPermCheck, type ArgType, type CommandMessage, type MuteResponse, @@ -15,7 +13,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class MuteCommand extends BotCommand { public constructor() { @@ -57,8 +55,8 @@ export default class MuteCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: ['ManageRoles'], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/myLogs.ts b/src/commands/moderation/myLogs.ts index 34ab8e0..8faca8c 100644 --- a/src/commands/moderation/myLogs.ts +++ b/src/commands/moderation/myLogs.ts @@ -2,7 +2,6 @@ import { BotCommand, ButtonPaginator, chunk, - clientSendAndPermCheck, colors, emojis, ModLog, @@ -35,7 +34,8 @@ export default class MyLogsCommand extends BotCommand { ], slash: true, channel: null, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts index 106f394..1eff48e 100644 --- a/src/commands/moderation/purge.ts +++ b/src/commands/moderation/purge.ts @@ -1,16 +1,6 @@ -import { - Arg, - BotCommand, - clientSendAndPermCheck, - emojis, - OptArgType, - TanzaniteEvent, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { Arg, BotCommand, emojis, OptArgType, TanzaniteEvent, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, Collection, PermissionFlagsBits, type Message } from 'discord.js'; +import { ApplicationCommandOptionType, Collection, type Message } from 'discord.js'; export default class PurgeCommand extends BotCommand { public constructor() { @@ -52,9 +42,10 @@ export default class PurgeCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => - clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true), - userPermissions: [PermissionFlagsBits.ManageMessages], + clientPermissions: ['ManageMessages', 'EmbedLinks'], + clientCheckChannel: true, + userPermissions: ['ManageMessages'], + userCheckChannel: true, channel: 'guild' }); } diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts index 5baeffc..a4ad4de 100644 --- a/src/commands/moderation/removeReactionEmoji.ts +++ b/src/commands/moderation/removeReactionEmoji.ts @@ -1,15 +1,6 @@ -import { - Arg, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { Arg, BotCommand, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, Message, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, Message } from 'discord.js'; export default class RemoveReactionEmojiCommand extends BotCommand { public constructor() { @@ -42,9 +33,10 @@ export default class RemoveReactionEmojiCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => - clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.EmbedLinks], true), - userPermissions: [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.ManageEmojisAndStickers] // Can't undo the removal of 1000s of reactions + clientPermissions: ['ManageMessages', 'EmbedLinks'], + clientCheckChannel: true, + userPermissions: ['ManageMessages', 'ManageEmojisAndStickers'], // Can't undo the removal of 1000s of reactions + userCheckChannel: true }); } diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index 6b874da..565f214 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -2,7 +2,6 @@ import { addRoleResponse, AllowedMentions, BotCommand, - clientSendAndPermCheck, emojis, format, humanizeDuration, @@ -67,8 +66,8 @@ export default class RoleCommand extends BotCommand { channel: 'guild', flags: ['--force'], typing: true, - clientPermissions: (m) => - clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles, PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['ManageRoles', 'EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts index 66bc2a0..82d0264 100644 --- a/src/commands/moderation/slowmode.ts +++ b/src/commands/moderation/slowmode.ts @@ -1,18 +1,7 @@ -import { - Arg, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - humanizeDuration, - userGuildPermCheck, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { Arg, BotCommand, emojis, format, humanizeDuration, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { Argument } from 'discord-akairo'; -import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, ChannelType } from 'discord.js'; export default class SlowmodeCommand extends BotCommand { public constructor() { @@ -46,9 +35,8 @@ export default class SlowmodeCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => - clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels, PermissionFlagsBits.EmbedLinks], true), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: ['ManageChannels', 'EmbedLinks'], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/timeout.ts b/src/commands/moderation/timeout.ts index 5ab62e4..7bb02f7 100644 --- a/src/commands/moderation/timeout.ts +++ b/src/commands/moderation/timeout.ts @@ -2,7 +2,6 @@ import { AllowedMentions, BotCommand, castDurationContent, - clientSendAndPermCheck, emojis, format, Moderation, @@ -13,7 +12,7 @@ import { type TimeoutResponse } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class TimeoutCommand extends BotCommand { public constructor() { @@ -54,8 +53,8 @@ export default class TimeoutCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]), - userPermissions: [PermissionFlagsBits.ModerateMembers] + clientPermissions: ['ModerateMembers'], + userPermissions: ['ModerateMembers'] }); } diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts index 29dedab..537e176 100644 --- a/src/commands/moderation/unban.ts +++ b/src/commands/moderation/unban.ts @@ -12,7 +12,7 @@ import { type UnbanResponse } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type User } from 'discord.js'; +import { ApplicationCommandOptionType, type User } from 'discord.js'; export default class UnbanCommand extends BotCommand { public constructor() { @@ -44,8 +44,8 @@ export default class UnbanCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: [PermissionFlagsBits.BanMembers], - userPermissions: [PermissionFlagsBits.BanMembers] + clientPermissions: ['BanMembers'], + userPermissions: ['BanMembers'] }); } diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts index e342f0f..4838392 100644 --- a/src/commands/moderation/unblock.ts +++ b/src/commands/moderation/unblock.ts @@ -1,12 +1,10 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, emojis, format, Moderation, unblockResponse, - userGuildPermCheck, type ArgType, type CommandMessage, type OptArgType, @@ -14,7 +12,7 @@ import { type UnblockResponse } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class UnblockCommand extends BotCommand { public constructor() { @@ -56,8 +54,8 @@ export default class UnblockCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: ['ManageChannels'], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/unlockdown.ts b/src/commands/moderation/unlockdown.ts index 38d2fe6..09b78a0 100644 --- a/src/commands/moderation/unlockdown.ts +++ b/src/commands/moderation/unlockdown.ts @@ -1,6 +1,6 @@ import { LockdownCommand } from '#commands'; -import { BotCommand, clientSendAndPermCheck, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; -import { ApplicationCommandOptionType, Constants, PermissionFlagsBits } from 'discord.js'; +import { BotCommand, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; +import { ApplicationCommandOptionType, Constants } from 'discord.js'; export default class UnlockdownCommand extends BotCommand { public constructor() { @@ -41,8 +41,8 @@ export default class UnlockdownCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageChannels]), - userPermissions: [PermissionFlagsBits.ManageChannels] + clientPermissions: ['ManageChannels'], + userPermissions: ['ManageChannels'] }); } diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts index 4f408eb..a4d348d 100644 --- a/src/commands/moderation/unmute.ts +++ b/src/commands/moderation/unmute.ts @@ -1,16 +1,14 @@ import { AllowedMentions, - clientSendAndPermCheck, formatUnmuteResponse, Moderation, - userGuildPermCheck, type ArgType, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType } from 'discord.js'; import { BotCommand } from '../../../lib/extensions/discord-akairo/BotCommand.js'; export default class UnmuteCommand extends BotCommand { @@ -53,8 +51,8 @@ export default class UnmuteCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageRoles]), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: ['ManageRoles'], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moderation/untimeout.ts b/src/commands/moderation/untimeout.ts index 8bc977b..3775c65 100644 --- a/src/commands/moderation/untimeout.ts +++ b/src/commands/moderation/untimeout.ts @@ -1,7 +1,6 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, emojis, format, Moderation, @@ -13,7 +12,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class UntimeoutCommand extends BotCommand { public constructor() { @@ -55,8 +54,8 @@ export default class UntimeoutCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ModerateMembers]), - userPermissions: [PermissionFlagsBits.ModerateMembers] + clientPermissions: ['ModerateMembers'], + userPermissions: ['ModerateMembers'] }); } diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts index 9547583..4bc7f13 100644 --- a/src/commands/moderation/warn.ts +++ b/src/commands/moderation/warn.ts @@ -1,12 +1,10 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, emojis, format, Moderation, ordinal, - userGuildPermCheck, warnResponse, type ArgType, type CommandMessage, @@ -15,7 +13,7 @@ import { type WarnResponse } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js'; +import { ApplicationCommandOptionType, type GuildMember } from 'discord.js'; export default class WarnCommand extends BotCommand { public constructor() { @@ -56,8 +54,8 @@ export default class WarnCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), - userPermissions: (m) => userGuildPermCheck(m, [PermissionFlagsBits.ManageMessages]) + clientPermissions: [], + userPermissions: ['ManageMessages'] }); } diff --git a/src/commands/moulberry-bush/capePermissions.ts b/src/commands/moulberry-bush/capePermissions.ts index fdeddd8..6f7ac4a 100644 --- a/src/commands/moulberry-bush/capePermissions.ts +++ b/src/commands/moulberry-bush/capePermissions.ts @@ -1,7 +1,6 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, colors, emojis, format, @@ -10,7 +9,7 @@ import { type CommandMessage, type SlashMessage } from '#lib'; -import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default class CapePermissionsCommand extends BotCommand { public constructor() { @@ -31,7 +30,8 @@ export default class CapePermissionsCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], channel: 'guild' }); diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts index 79c163f..b292f24 100644 --- a/src/commands/moulberry-bush/capes.ts +++ b/src/commands/moulberry-bush/capes.ts @@ -2,7 +2,6 @@ import { AllowedMentions, BotCommand, ButtonPaginator, - clientSendAndPermCheck, colors, DeleteButton, emojis, @@ -13,7 +12,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, PermissionFlagsBits, type APIEmbed, type AutocompleteInteraction } from 'discord.js'; +import { ApplicationCommandOptionType, type APIEmbed, type AutocompleteInteraction } from 'discord.js'; import { default as Fuse } from 'fuse.js'; assert(Fuse); @@ -39,7 +38,8 @@ export default class CapesCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/moulberry-bush/gimmeRole.ts b/src/commands/moulberry-bush/gimmeRole.ts new file mode 100644 index 0000000..2e3cc77 --- /dev/null +++ b/src/commands/moulberry-bush/gimmeRole.ts @@ -0,0 +1,42 @@ +import { BotCommand, emojis, mappings, type CommandMessage, type SlashMessage } from '#lib'; +import assert from 'assert/strict'; + +export default class GimmeRole extends BotCommand { + public constructor() { + super('gimmeRole', { + aliases: ['gimme-role', 'gimme'], + category: "Moulberry's Bush", + description: 'Gives you role.', + usage: ['gimme-role'], + examples: ['gimme-role'], + slash: false, + channel: 'guild', + clientPermissions: [], + userPermissions: [], + restrictedGuilds: [mappings.guilds["Moulberry's Bush"]] + }); + } + + public override async exec(message: CommandMessage | SlashMessage) { + assert(message.inGuild() && message.member); + assert(message.guildId === mappings.guilds["Moulberry's Bush"]); + + const roleId = '1016149863651622923'; + + try { + if (!message.guild.roles.cache.has(roleId)) { + return await message.util.reply(`${emojis.error} Fucky wucky, the role does not exist.`); + } + + if (message.member.roles.cache.has(roleId)) { + await message.member.roles.remove(roleId); + return await message.util.reply(`${emojis.success} Removed role.`); + } else { + await message.member.roles.add(roleId); + return await message.util.reply(`${emojis.success} Added role.`); + } + } catch { + return message.util.reply(`${emojis.error} Fucky wucky, an error occurred.`); + } + } +} diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts index aebcc52..ef08473 100644 --- a/src/commands/moulberry-bush/giveawayPing.ts +++ b/src/commands/moulberry-bush/giveawayPing.ts @@ -1,4 +1,4 @@ -import { AllowedMentions, BotCommand, clientSendAndPermCheck, emojis, mappings, type CommandMessage } from '#lib'; +import { AllowedMentions, BotCommand, emojis, mappings, type CommandMessage } from '#lib'; import assert from 'assert/strict'; import { PermissionFlagsBits } from 'discord.js'; @@ -10,14 +10,9 @@ export default class GiveawayPingCommand extends BotCommand { description: 'Pings the giveaway role.', usage: ['giveaway-ping'], examples: ['giveaway-ping'], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageMessages], true), - userPermissions: [ - PermissionFlagsBits.ManageGuild, - PermissionFlagsBits.ManageMessages, - PermissionFlagsBits.BanMembers, - PermissionFlagsBits.KickMembers, - PermissionFlagsBits.ViewChannel - ], + clientPermissions: ['ManageMessages'], + clientCheckChannel: true, + userPermissions: ['ManageGuild', 'ManageMessages', 'BanMembers', 'KickMembers', 'ViewChannel'], channel: 'guild', ignoreCooldown: [], ignorePermissions: [], diff --git a/src/commands/moulberry-bush/moulHammer.ts b/src/commands/moulberry-bush/moulHammer.ts index 0407428..776dea1 100644 --- a/src/commands/moulberry-bush/moulHammer.ts +++ b/src/commands/moulberry-bush/moulHammer.ts @@ -1,6 +1,6 @@ -import { BotCommand, clientSendAndPermCheck, colors, mappings, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, colors, mappings, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default class MoulHammerCommand extends BotCommand { public constructor() { @@ -24,7 +24,8 @@ export default class MoulHammerCommand extends BotCommand { channel: 'guild', slashGuilds: [mappings.guilds["Moulberry's Bush"]], restrictedGuilds: [mappings.guilds["Moulberry's Bush"]], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/moulberry-bush/neuRepo.ts b/src/commands/moulberry-bush/neuRepo.ts index d8eb7ed..9ff2903 100644 --- a/src/commands/moulberry-bush/neuRepo.ts +++ b/src/commands/moulberry-bush/neuRepo.ts @@ -1,12 +1,6 @@ -import { BotCommand, clientSendAndPermCheck, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import canvas from '@napi-rs/canvas'; -import { - ApplicationCommandOptionType, - AttachmentBuilder, - AutocompleteInteraction, - CacheType, - PermissionFlagsBits -} from 'discord.js'; +import { ApplicationCommandOptionType, AttachmentBuilder, AutocompleteInteraction, CacheType } from 'discord.js'; import { join } from 'path'; import tinycolor from 'tinycolor2'; import { formattingInfo, RawNeuItem } from '../../../lib/utils/Minecraft.js'; @@ -43,7 +37,8 @@ export default class NeuRepoCommand extends BotCommand { } */ ], slash: false, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], ownerOnly: true, hidden: true diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts index 8eb412c..02de6fe 100644 --- a/src/commands/moulberry-bush/report.ts +++ b/src/commands/moulberry-bush/report.ts @@ -1,7 +1,6 @@ import { AllowedMentions, BotCommand, - clientSendAndPermCheck, colors, emojis, mappings, @@ -11,7 +10,7 @@ import { } from '#lib'; import { stripIndent } from '#tags'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default class ReportCommand extends BotCommand { public constructor() { @@ -42,7 +41,8 @@ export default class ReportCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], channel: 'guild' }); diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts index 5f2155f..b4ca571 100644 --- a/src/commands/moulberry-bush/rule.ts +++ b/src/commands/moulberry-bush/rule.ts @@ -1,15 +1,6 @@ -import { - AllowedMentions, - Arg, - BotCommand, - clientSendAndPermCheck, - mappings, - type CommandMessage, - type OptArgType, - type SlashMessage -} from '#lib'; +import { AllowedMentions, Arg, BotCommand, mappings, type CommandMessage, type OptArgType, type SlashMessage } from '#lib'; import { stripIndent } from '#tags'; -import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; const rules = [ { @@ -101,7 +92,8 @@ export default class RuleCommand extends BotCommand { slash: true, slashGuilds: [mappings.guilds["Moulberry's Bush"]], channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], restrictedGuilds: [mappings.guilds["Moulberry's Bush"]] }); diff --git a/src/commands/moulberry-bush/serverStatus.ts b/src/commands/moulberry-bush/serverStatus.ts index 709de26..8e59c9f 100644 --- a/src/commands/moulberry-bush/serverStatus.ts +++ b/src/commands/moulberry-bush/serverStatus.ts @@ -1,5 +1,5 @@ -import { BotCommand, clientSendAndPermCheck, colors, emojis, type CommandMessage } from '#lib'; -import { EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { BotCommand, colors, emojis, type CommandMessage } from '#lib'; +import { EmbedBuilder } from 'discord.js'; export default class ServerStatusCommand extends BotCommand { public constructor() { @@ -9,7 +9,8 @@ export default class ServerStatusCommand extends BotCommand { description: "Gives the status of moulberry's server", usage: ['server-status'], examples: ['server-status', 'ss'], - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], slash: true }); diff --git a/src/commands/moulberry-bush/solved.ts b/src/commands/moulberry-bush/solved.ts index 197a3ce..ecda1c7 100644 --- a/src/commands/moulberry-bush/solved.ts +++ b/src/commands/moulberry-bush/solved.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, emojis, mappings, type CommandMessage, type SlashMessage } from '#lib'; +import { BotCommand, emojis, mappings, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; export default class Solved extends BotCommand { @@ -11,7 +11,7 @@ export default class Solved extends BotCommand { examples: ['solved'], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], slashGuilds: [mappings.guilds["Moulberry's Bush"]], restrictedGuilds: [mappings.guilds["Moulberry's Bush"]] diff --git a/src/commands/tickets/ticket-!.ts b/src/commands/tickets/ticket-!.ts index d1462fb..c5c59f2 100644 --- a/src/commands/tickets/ticket-!.ts +++ b/src/commands/tickets/ticket-!.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, deepWriteable, type SlashMessage } from '#lib'; +import { BotCommand, deepWriteable, type SlashMessage } from '#lib'; import { Flag, type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo'; import { ApplicationCommandOptionType } from 'discord.js'; @@ -31,7 +31,7 @@ export default class TicketCommand extends BotCommand { ), slash: false, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [], ownerOnly: true, hidden: true diff --git a/src/commands/utilities/_poll.ts b/src/commands/utilities/_poll.ts index 4655f36..b5b517b 100644 --- a/src/commands/utilities/_poll.ts +++ b/src/commands/utilities/_poll.ts @@ -29,7 +29,7 @@ // } // ], // slash: true, -// clientPermissions: (m) => clientSendAndPermCheck(m), +// clientPermissions: [], // userPermissions: [] // }); // } diff --git a/src/commands/utilities/activity.ts b/src/commands/utilities/activity.ts index 414e6a2..89ca53e 100644 --- a/src/commands/utilities/activity.ts +++ b/src/commands/utilities/activity.ts @@ -1,6 +1,5 @@ import { BotCommand, - clientSendAndPermCheck, emojis, regex, type ArgType, @@ -124,7 +123,7 @@ export default class ActivityCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/utilities/calculator.ts b/src/commands/utilities/calculator.ts index c9d300c..f8e0219 100644 --- a/src/commands/utilities/calculator.ts +++ b/src/commands/utilities/calculator.ts @@ -1,12 +1,4 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - colors, - emojis, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, colors, emojis, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; import { evaluate } from 'mathjs'; @@ -33,7 +25,8 @@ export default class CalculatorCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/utilities/decode.ts b/src/commands/utilities/decode.ts index 12a016b..b7e6927 100644 --- a/src/commands/utilities/decode.ts +++ b/src/commands/utilities/decode.ts @@ -1,13 +1,4 @@ -import { - AllowedMentions, - BotCommand, - capitalize, - clientSendAndPermCheck, - colors, - formatError, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, capitalize, colors, formatError, type CommandMessage, type SlashMessage } from '#lib'; import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; const encodingTypesArray = ['ascii', 'utf8', 'utf-8', 'utf16le', 'ucs2', 'ucs-2', 'base64', 'latin1', 'binary', 'hex']; @@ -51,7 +42,8 @@ export default class DecodeCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts index 1c741bd..7d4c7b6 100644 --- a/src/commands/utilities/hash.ts +++ b/src/commands/utilities/hash.ts @@ -25,7 +25,7 @@ // slashType: ApplicationCommandOptionType.String // } // ], -// clientPermissions: (m) => clientSendAndPermCheck(m), +// clientPermissions: [], // userPermissions: [] // }); // } diff --git a/src/commands/utilities/highlight-!.ts b/src/commands/utilities/highlight-!.ts index 4995e97..7716887 100644 --- a/src/commands/utilities/highlight-!.ts +++ b/src/commands/utilities/highlight-!.ts @@ -1,4 +1,4 @@ -import { BotCommand, clientSendAndPermCheck, deepWriteable, Highlight, HighlightWord, type SlashMessage } from '#lib'; +import { BotCommand, deepWriteable, Highlight, HighlightWord, type SlashMessage } from '#lib'; import { Flag, type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo'; import { ApplicationCommandOptionType, Constants, type AutocompleteInteraction, type CacheType } from 'discord.js'; @@ -162,7 +162,8 @@ export default class HighlightCommand extends BotCommand { ), slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts index a1645dc..06afe3b 100644 --- a/src/commands/utilities/price.ts +++ b/src/commands/utilities/price.ts @@ -1,6 +1,6 @@ -import { ArgType, BotCommand, clientSendAndPermCheck, colors, emojis, format, oxford, type CommandMessage } from '#lib'; +import { ArgType, BotCommand, colors, emojis, format, oxford, type CommandMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, AutocompleteInteraction, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, AutocompleteInteraction, EmbedBuilder } from 'discord.js'; import { default as Fuse } from 'fuse.js'; assert(Fuse); @@ -43,7 +43,8 @@ export default class PriceCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], typing: true }); diff --git a/src/commands/utilities/remind.ts b/src/commands/utilities/remind.ts index 498a63d..ecc3830 100644 --- a/src/commands/utilities/remind.ts +++ b/src/commands/utilities/remind.ts @@ -1,7 +1,6 @@ import { BotCommand, castDurationContent, - clientSendAndPermCheck, dateDelta, emojis, format, @@ -35,7 +34,7 @@ export default class RemindCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/utilities/reminders.ts b/src/commands/utilities/reminders.ts index f98166f..8dd7e25 100644 --- a/src/commands/utilities/reminders.ts +++ b/src/commands/utilities/reminders.ts @@ -2,7 +2,6 @@ import { BotCommand, ButtonPaginator, chunk, - clientSendAndPermCheck, colors, emojis, Reminder, @@ -11,7 +10,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { PermissionFlagsBits, type APIEmbed } from 'discord.js'; +import { type APIEmbed } from 'discord.js'; import { Op } from 'sequelize'; assert(Op); @@ -25,7 +24,8 @@ export default class RemindersCommand extends BotCommand { usage: ['reminder'], examples: ['reminders'], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks]), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts index 7f70830..a208920 100644 --- a/src/commands/utilities/steal.ts +++ b/src/commands/utilities/steal.ts @@ -1,17 +1,7 @@ -import { - Arg, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - OptArgType, - regex, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { Arg, BotCommand, emojis, format, OptArgType, regex, type CommandMessage, type SlashMessage } from '#lib'; import assert from 'assert/strict'; import { type ArgumentGeneratorReturn, type ArgumentType, type ArgumentTypeCaster } from 'discord-akairo'; -import { ApplicationCommandOptionType, Attachment, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, Attachment } from 'discord.js'; import _ from 'lodash'; import { Stream } from 'stream'; import { URL } from 'url'; @@ -46,8 +36,8 @@ export default class StealCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.ManageEmojisAndStickers]), - userPermissions: [PermissionFlagsBits.ManageEmojisAndStickers] + clientPermissions: ['ManageEmojisAndStickers'], + userPermissions: ['ManageEmojisAndStickers'] }); } diff --git a/src/commands/utilities/suicide.ts b/src/commands/utilities/suicide.ts index bc76d9c..8376b1c 100644 --- a/src/commands/utilities/suicide.ts +++ b/src/commands/utilities/suicide.ts @@ -1,4 +1,4 @@ -import { AllowedMentions, BotCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib'; +import { AllowedMentions, BotCommand, colors, type CommandMessage, type SlashMessage } from '#lib'; import { stripIndent } from '#tags'; import { EmbedBuilder } from 'discord.js'; @@ -11,7 +11,8 @@ export default class SuicideCommand extends BotCommand { usage: ['suicide'], examples: ['suicide'], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], bypassChannelBlacklist: true }); diff --git a/src/commands/utilities/uuid.ts b/src/commands/utilities/uuid.ts index 041acfc..1d13741 100644 --- a/src/commands/utilities/uuid.ts +++ b/src/commands/utilities/uuid.ts @@ -1,14 +1,4 @@ -import { - AllowedMentions, - ArgType, - BotCommand, - clientSendAndPermCheck, - emojis, - format, - mcUUID, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, ArgType, BotCommand, emojis, format, mcUUID, type CommandMessage, type SlashMessage } from '#lib'; import { ApplicationCommandOptionType } from 'discord.js'; export default class UuidCommand extends BotCommand { @@ -40,7 +30,7 @@ export default class UuidCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: [], userPermissions: [] }); } diff --git a/src/commands/utilities/viewRaw.ts b/src/commands/utilities/viewRaw.ts index 63125c3..1220f0f 100644 --- a/src/commands/utilities/viewRaw.ts +++ b/src/commands/utilities/viewRaw.ts @@ -1,7 +1,6 @@ import { Arg, BotCommand, - clientSendAndPermCheck, colors, emojis, inspect, @@ -11,7 +10,7 @@ import { type SlashMessage } from '#lib'; import assert from 'assert/strict'; -import { ApplicationCommandOptionType, Constants, EmbedBuilder, Message, PermissionFlagsBits } from 'discord.js'; +import { ApplicationCommandOptionType, Constants, EmbedBuilder, Message } from 'discord.js'; export default class ViewRawCommand extends BotCommand { public constructor() { @@ -62,7 +61,8 @@ export default class ViewRawCommand extends BotCommand { ], slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } @@ -87,24 +87,24 @@ export default class ViewRawCommand extends BotCommand { `${emojis.error} There was an error fetching that message, make sure that is a valid id and if the message is not in this channel, please provide a channel.` ); - const Embed = await ViewRawCommand.getRawData(newMessage, { json: args.json, js: args.js }); + const Embed = await getRawData(newMessage, { json: args.json, js: args.js }); return await message.util.reply({ embeds: [Embed] }); } +} - public static async getRawData(message: Message, options: { json?: boolean; js: boolean }): Promise<EmbedBuilder> { - const content = - options.json || options.js - ? options.json - ? JSON.stringify(message.toJSON(), undefined, 2) - : inspect(message.toJSON()) || '[No Content]' - : message.content || '[No Content]'; - const lang = options.json ? 'json' : options.js ? 'js' : undefined; - return new EmbedBuilder() - .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined }) - .setTimestamp(message.createdTimestamp) - .setColor(message.member?.roles?.color?.color ?? colors.default) - .setTitle('Raw Message Information') - .setDescription(await message.client.utils.codeblock(content, 2048, lang)); - } +export async function getRawData(message: Message, options: { json?: boolean; js: boolean }): Promise<EmbedBuilder> { + const content = + options.json || options.js + ? options.json + ? JSON.stringify(message.toJSON(), undefined, 2) + : inspect(message.toJSON()) || '[No Content]' + : message.content || '[No Content]'; + const lang = options.json ? 'json' : options.js ? 'js' : undefined; + return new EmbedBuilder() + .setFooter({ text: message.author.tag, iconURL: message.author.avatarURL() ?? undefined }) + .setTimestamp(message.createdTimestamp) + .setColor(message.member?.roles?.color?.color ?? colors.default) + .setTitle('Raw Message Information') + .setDescription(await message.client.utils.codeblock(content, 2048, lang)); } diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts index 23eccd6..9b12a1c 100644 --- a/src/commands/utilities/whoHasRole.ts +++ b/src/commands/utilities/whoHasRole.ts @@ -2,7 +2,6 @@ import { BotCommand, ButtonPaginator, chunk, - clientSendAndPermCheck, colors, emojis, OptArgType, @@ -35,7 +34,8 @@ export default class WhoHasRoleCommand extends BotCommand { ), slash: true, channel: 'guild', - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [], typing: true }); diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts index 863b16a..503af87 100644 --- a/src/commands/utilities/wolframAlpha.ts +++ b/src/commands/utilities/wolframAlpha.ts @@ -1,13 +1,4 @@ -import { - AllowedMentions, - BotCommand, - clientSendAndPermCheck, - colors, - emojis, - type ArgType, - type CommandMessage, - type SlashMessage -} from '#lib'; +import { AllowedMentions, BotCommand, colors, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; import { initializeClass as WolframAlphaAPI } from '@notenoughupdates/wolfram-alpha-api'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, EmbedBuilder, type MessageOptions } from 'discord.js'; @@ -43,7 +34,8 @@ export default class WolframAlphaCommand extends BotCommand { } ], slash: true, - clientPermissions: (m) => clientSendAndPermCheck(m), + clientPermissions: ['EmbedLinks'], + clientCheckChannel: true, userPermissions: [] }); } diff --git a/src/context-menu-commands/message/viewRaw.ts b/src/context-menu-commands/message/viewRaw.ts index f216a59..0a8fcfc 100644 --- a/src/context-menu-commands/message/viewRaw.ts +++ b/src/context-menu-commands/message/viewRaw.ts @@ -1,6 +1,6 @@ import { ContextMenuCommand } from 'discord-akairo'; import { ApplicationCommandType, type ContextMenuCommandInteraction, type Message } from 'discord.js'; -import ViewRawCommand from '../../commands/utilities/viewRaw.js'; +import { getRawData } from '../../commands/utilities/viewRaw.js'; export default class ViewRawContextMenuCommand extends ContextMenuCommand { public constructor() { @@ -13,7 +13,10 @@ export default class ViewRawContextMenuCommand extends ContextMenuCommand { public override async exec(interaction: ContextMenuCommandInteraction) { await interaction.deferReply({ ephemeral: true }); - const embed = await ViewRawCommand.getRawData(interaction.options.getMessage('message') as Message, { + + const message = interaction.options.getMessage('message') as Message; + + const embed = await getRawData(message, { json: false, js: false }); diff --git a/src/inhibitors/blacklist/channelGlobalBlacklist.ts b/src/inhibitors/blacklist/channelGlobalBlacklist.ts index 988931b..a212606 100644 --- a/src/inhibitors/blacklist/channelGlobalBlacklist.ts +++ b/src/inhibitors/blacklist/channelGlobalBlacklist.ts @@ -1,21 +1,21 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class UserGlobalBlacklistInhibitor extends BotInhibitor { public constructor() { - super('channelGlobalBlacklist', { - reason: 'channelGlobalBlacklist', - type: 'post', + super(InhibitorReason.ChannelGlobalBlacklist, { + reason: InhibitorReason.ChannelGlobalBlacklist, + type: InhibitorType.Post, priority: 500 }); } public exec(message: CommandMessage | SlashMessage, command: BotCommand): boolean { if (!message.author || !message.inGuild()) return false; - // do not change to message.author.isOwner() + //! do not change to message.author.isOwner() if (this.client.isOwner(message.author) || this.client.user!.id === message.author.id) return false; if (this.client.cache.global.blacklistedChannels.includes(message.channel!.id) && !command.bypassChannelBlacklist) { void this.client.console.verbose( - 'channelGlobalBlacklist', + InhibitorReason.ChannelGlobalBlacklist, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/blacklist/channelGuildBlacklist.ts b/src/inhibitors/blacklist/channelGuildBlacklist.ts index 4bf42d2..ec81666 100644 --- a/src/inhibitors/blacklist/channelGuildBlacklist.ts +++ b/src/inhibitors/blacklist/channelGuildBlacklist.ts @@ -1,17 +1,17 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class ChannelGuildBlacklistInhibitor extends BotInhibitor { public constructor() { - super('channelGuildBlacklist', { - reason: 'channelGuildBlacklist', - type: 'post', + super(InhibitorReason.ChannelGuildBlacklist, { + reason: InhibitorReason.ChannelGuildBlacklist, + type: InhibitorType.Post, priority: 499 }); } public async exec(message: CommandMessage | SlashMessage, command: BotCommand): Promise<boolean> { if (!message.author || !message.inGuild()) return false; - // do not change to message.author.isOwner() + //! do not change to message.author.isOwner() if (this.client.isOwner(message.author) || this.client.user!.id === message.author.id) return false; if ( (await message.guild.getSetting('bypassChannelBlacklist'))?.includes(message.author.id) && @@ -24,7 +24,7 @@ export default class ChannelGuildBlacklistInhibitor extends BotInhibitor { !command.bypassChannelBlacklist ) { void this.client.console.verbose( - 'channelGuildBlacklist', + InhibitorReason.ChannelGuildBlacklist, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/blacklist/guildBlacklist.ts b/src/inhibitors/blacklist/guildBlacklist.ts index 636d0a3..b1f1543 100644 --- a/src/inhibitors/blacklist/guildBlacklist.ts +++ b/src/inhibitors/blacklist/guildBlacklist.ts @@ -1,17 +1,17 @@ -import { BotInhibitor, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type CommandMessage, type SlashMessage } from '#lib'; export default class GuildBlacklistInhibitor extends BotInhibitor { public constructor() { - super('guildBlacklist', { - reason: 'guildBlacklist', - type: 'all', + super(InhibitorReason.GuildBlacklist, { + reason: InhibitorReason.GuildBlacklist, + type: InhibitorType.All, priority: 50 }); } public exec(message: CommandMessage | SlashMessage): boolean { if (!message.author || !message.inGuild()) return false; - // do not change to message.author.isOwner() + //! do not change to message.author.isOwner() if ( this.client.isOwner(message.author) || this.client.isSuperUser(message.author) || @@ -20,7 +20,7 @@ export default class GuildBlacklistInhibitor extends BotInhibitor { return false; if (this.client.cache.global.blacklistedGuilds.includes(message.guild.id)) { void this.client.console.verbose( - 'guildBlacklist', + InhibitorReason.GuildBlacklist, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/blacklist/userGlobalBlacklist.ts b/src/inhibitors/blacklist/userGlobalBlacklist.ts index f5b15df..b0eacfc 100644 --- a/src/inhibitors/blacklist/userGlobalBlacklist.ts +++ b/src/inhibitors/blacklist/userGlobalBlacklist.ts @@ -1,21 +1,21 @@ -import { BotInhibitor, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type CommandMessage, type SlashMessage } from '#lib'; export default class UserGlobalBlacklistInhibitor extends BotInhibitor { public constructor() { - super('userGlobalBlacklist', { - reason: 'userGlobalBlacklist', - type: 'pre', + super(InhibitorReason.UserGlobalBlacklist, { + reason: InhibitorReason.UserGlobalBlacklist, + type: InhibitorType.Pre, priority: 30 }); } public exec(message: CommandMessage | SlashMessage): boolean { if (!message.author) return false; - // do not change to message.author.isOwner() + //! do not change to message.author.isOwner() if (this.client.isOwner(message.author) || this.client.user!.id === message.author.id) return false; if (this.client.cache.global.blacklistedUsers.includes(message.author.id)) { void this.client.console.verbose( - 'userGlobalBlacklist', + InhibitorReason.UserGlobalBlacklist, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${ message.inGuild() ? message.guild?.name : message.author.tag }>>.` diff --git a/src/inhibitors/blacklist/userGuildBlacklist.ts b/src/inhibitors/blacklist/userGuildBlacklist.ts index 3186d59..4330f87 100644 --- a/src/inhibitors/blacklist/userGuildBlacklist.ts +++ b/src/inhibitors/blacklist/userGuildBlacklist.ts @@ -1,17 +1,17 @@ -import { BotInhibitor, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type CommandMessage, type SlashMessage } from '#lib'; export default class UserGuildBlacklistInhibitor extends BotInhibitor { public constructor() { - super('userGuildBlacklist', { - reason: 'userGuildBlacklist', - type: 'pre', + super(InhibitorReason.UserGuildBlacklist, { + reason: InhibitorReason.UserGuildBlacklist, + type: InhibitorType.Pre, priority: 20 }); } public async exec(message: CommandMessage | SlashMessage): Promise<boolean> { if (!message.author || !message.inGuild()) return false; - // do not change to message.author.isOwner() + //! do not change to message.author.isOwner() if ( this.client.isOwner(message.author) || this.client.isSuperUser(message.author) || @@ -20,7 +20,7 @@ export default class UserGuildBlacklistInhibitor extends BotInhibitor { return false; if ((await message.guild.getSetting('blacklistedUsers'))?.includes(message.author.id)) { void this.client.console.verbose( - 'userGuildBlacklist', + InhibitorReason.UserGuildBlacklist, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/checks/cannotSend.ts b/src/inhibitors/checks/cannotSend.ts new file mode 100644 index 0000000..e9eab98 --- /dev/null +++ b/src/inhibitors/checks/cannotSend.ts @@ -0,0 +1,39 @@ +import { BotCommand, BotInhibitor, InhibitorReason, InhibitorType, type SlashMessage } from '#lib'; +import { type Message } from 'discord.js'; + +export default class CannotSendInhibitor extends BotInhibitor { + public constructor() { + super(InhibitorReason.CannotSend, { + reason: InhibitorReason.CannotSend, + type: InhibitorType.Post, + priority: 1000 + }); + } + + public async exec(message: Message | SlashMessage, command: BotCommand): Promise<boolean> { + // let it error if it is the owner + if (this.client.isOwner(message.author)) return false; + if (!message.inGuild() || !message.channel) return false; + if (command.skipSendCheck) return false; + + if (!message.guild.members.me) throw new Error(`Client member not cached in ${message.guild.name} (${message.guild.id})`); + + // doesn't apply to slash commands + if (message.util?.isSlash) return false; + + const sendPerm = message.channel.isThread() ? 'SendMessages' : 'SendMessagesInThreads'; + + const perms = message.channel.permissionsFor(message.guild.members.me); + + if (perms == null) { + // todo: remove once forum channels are fixed + if (message.channel.isThread() && message.channel.parent == null) { + return false; + } else { + return true; + } + } + + return !perms.has(sendPerm); + } +} diff --git a/src/inhibitors/checks/fatal.ts b/src/inhibitors/checks/fatal.ts index 4364d48..b585bd8 100644 --- a/src/inhibitors/checks/fatal.ts +++ b/src/inhibitors/checks/fatal.ts @@ -1,11 +1,11 @@ -import { BotInhibitor, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type SlashMessage } from '#lib'; import { type Message } from 'discord.js'; export default class FatalInhibitor extends BotInhibitor { public constructor() { - super('fatal', { - reason: 'fatal', - type: 'all', + super(InhibitorReason.Fatal, { + reason: InhibitorReason.Fatal, + type: InhibitorType.All, priority: 100 }); } @@ -16,7 +16,7 @@ export default class FatalInhibitor extends BotInhibitor { for (const property in globalCache) { if (!globalCache[property as keyof typeof globalCache]) { void this.client.console.verbose( - 'fatal', + InhibitorReason.Fatal, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/checks/guildUnavailable.ts b/src/inhibitors/checks/guildUnavailable.ts index 4439d69..dc2ac26 100644 --- a/src/inhibitors/checks/guildUnavailable.ts +++ b/src/inhibitors/checks/guildUnavailable.ts @@ -1,11 +1,11 @@ -import { BotInhibitor, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type SlashMessage } from '#lib'; import { type Message } from 'discord.js'; export default class GuildUnavailableInhibitor extends BotInhibitor { public constructor() { - super('guildUnavailable', { - reason: 'guildUnavailable', - type: 'all', + super(InhibitorReason.GuildUnavailable, { + reason: InhibitorReason.GuildUnavailable, + type: InhibitorType.All, priority: 70 }); } @@ -13,7 +13,7 @@ export default class GuildUnavailableInhibitor extends BotInhibitor { public async exec(message: Message | SlashMessage): Promise<boolean> { if (message.inGuild() && !message.guild.available) { void this.client.console.verbose( - 'guildUnavailable', + InhibitorReason.GuildUnavailable, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/command/globalDisabledCommand.ts b/src/inhibitors/command/disabledGlobal.ts index 4a93f2f..bfb5969 100644 --- a/src/inhibitors/command/globalDisabledCommand.ts +++ b/src/inhibitors/command/disabledGlobal.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; -export default class DisabledGuildCommandInhibitor extends BotInhibitor { +export default class DisabledGlobalInhibitor extends BotInhibitor { public constructor() { - super('disabledGlobalCommand', { - reason: 'disabledGlobal', - type: 'post', + super(InhibitorReason.DisabledGlobal, { + reason: InhibitorReason.DisabledGlobal, + type: InhibitorType.Post, priority: 300 }); } @@ -13,7 +13,7 @@ export default class DisabledGuildCommandInhibitor extends BotInhibitor { if (message.author.isOwner()) return false; if (this.client.cache.global.disabledCommands.includes(command?.id)) { void this.client.console.verbose( - 'disabledGlobalCommand', + InhibitorReason.DisabledGlobal, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/command/guildDisabledCommand.ts b/src/inhibitors/command/disabledGuild.ts index 97ac995..0df827d 100644 --- a/src/inhibitors/command/guildDisabledCommand.ts +++ b/src/inhibitors/command/disabledGuild.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; -export default class DisabledGuildCommandInhibitor extends BotInhibitor { +export default class DisabledGuildInhibitor extends BotInhibitor { public constructor() { - super('disabledGuildCommand', { - reason: 'disabledGuild', - type: 'post', + super(InhibitorReason.DisabledGuild, { + reason: InhibitorReason.DisabledGuild, + type: InhibitorType.Post, priority: 250 }); } @@ -15,7 +15,7 @@ export default class DisabledGuildCommandInhibitor extends BotInhibitor { if ((await message.guild.getSetting('disabledCommands'))?.includes(command?.id)) { void this.client.console.verbose( - 'disabledGuildCommand', + InhibitorReason.DisabledGuild, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild.name}>>.` ); return true; diff --git a/src/inhibitors/command/dm.ts b/src/inhibitors/command/dm.ts index f25f542..aa39b94 100644 --- a/src/inhibitors/command/dm.ts +++ b/src/inhibitors/command/dm.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class DMInhibitor extends BotInhibitor { public constructor() { - super('dm', { - reason: 'dm', - type: 'post', + super(InhibitorReason.Dm, { + reason: InhibitorReason.Dm, + type: InhibitorType.Post, priority: 75 }); } diff --git a/src/inhibitors/command/guild.ts b/src/inhibitors/command/guild.ts index 1d70c7d..24e2577 100644 --- a/src/inhibitors/command/guild.ts +++ b/src/inhibitors/command/guild.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class GuildInhibitor extends BotInhibitor { public constructor() { - super('guild', { - reason: 'guild', - type: 'post', + super(InhibitorReason.Guild, { + reason: InhibitorReason.Guild, + type: InhibitorType.Post, priority: 80 }); } @@ -12,7 +12,7 @@ export default class GuildInhibitor extends BotInhibitor { public async exec(message: CommandMessage | SlashMessage, command: BotCommand): Promise<boolean> { if (command.channel === 'guild' && !message.guild) { void this.client.console.verbose( - 'guild', + InhibitorReason.Guild, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.author.tag}>>.` ); return true; diff --git a/src/inhibitors/command/nsfw.ts b/src/inhibitors/command/notNsfw.ts index 623115e..08e5556 100644 --- a/src/inhibitors/command/nsfw.ts +++ b/src/inhibitors/command/notNsfw.ts @@ -1,11 +1,11 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; import { type TextChannel } from 'discord.js'; -export default class NsfwInhibitor extends BotInhibitor { +export default class NotNsfwInhibitor extends BotInhibitor { public constructor() { - super('nsfw', { - reason: 'notNsfw', - type: 'post', + super(InhibitorReason.NotNsfw, { + reason: InhibitorReason.NotNsfw, + type: InhibitorType.Post, priority: 25 }); } @@ -13,7 +13,7 @@ export default class NsfwInhibitor extends BotInhibitor { public async exec(message: CommandMessage | SlashMessage, command: BotCommand): Promise<boolean> { if (command.onlyNsfw && !(message.channel as TextChannel).nsfw) { void this.client.console.verbose( - 'notNsfw', + InhibitorReason.NotNsfw, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/command/owner.ts b/src/inhibitors/command/owner.ts index 15643be..8736cff 100644 --- a/src/inhibitors/command/owner.ts +++ b/src/inhibitors/command/owner.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class OwnerInhibitor extends BotInhibitor { public constructor() { - super('owner', { - reason: 'owner', - type: 'post', + super(InhibitorReason.Owner, { + reason: InhibitorReason.Owner, + type: InhibitorType.Post, priority: 100 }); } @@ -13,7 +13,7 @@ export default class OwnerInhibitor extends BotInhibitor { if (command.ownerOnly) { if (!this.client.isOwner(message.author)) { void this.client.console.verbose( - 'owner', + InhibitorReason.Owner, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/command/restrictedChannel.ts b/src/inhibitors/command/restrictedChannel.ts index ec23604..bfacebc 100644 --- a/src/inhibitors/command/restrictedChannel.ts +++ b/src/inhibitors/command/restrictedChannel.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class RestrictedChannelInhibitor extends BotInhibitor { public constructor() { - super('restrictedChannel', { - reason: 'restrictedChannel', - type: 'post', + super(InhibitorReason.RestrictedChannel, { + reason: InhibitorReason.RestrictedChannel, + type: InhibitorType.Post, priority: 10 }); } @@ -13,7 +13,7 @@ export default class RestrictedChannelInhibitor extends BotInhibitor { if (command.restrictedChannels?.length && message.channel) { if (!command.restrictedChannels.includes(message.channel.id)) { void this.client.console.verbose( - 'restrictedChannel', + InhibitorReason.RestrictedChannel, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/command/restrictedGuild.ts b/src/inhibitors/command/restrictedGuild.ts index ec0ad2c..4520cbc 100644 --- a/src/inhibitors/command/restrictedGuild.ts +++ b/src/inhibitors/command/restrictedGuild.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class RestrictedGuildInhibitor extends BotInhibitor { public constructor() { - super('restrictedGuild', { - reason: 'restrictedGuild', - type: 'post', + super(InhibitorReason.RestrictedGuild, { + reason: InhibitorReason.RestrictedGuild, + type: InhibitorType.Post, priority: 5 }); } @@ -13,7 +13,7 @@ export default class RestrictedGuildInhibitor extends BotInhibitor { if (command.restrictedChannels?.length && message.channel) { if (!command.restrictedChannels.includes(message.channel.id)) { void this.client.console.verbose( - 'restrictedGuild', + InhibitorReason.RestrictedGuild, `Blocked message with id <<${message.id}>> from <<${message.author.tag}>> in <<${message.guild?.name}>>.` ); return true; diff --git a/src/inhibitors/command/superUser.ts b/src/inhibitors/command/superUser.ts index a923c1a..dd71539 100644 --- a/src/inhibitors/command/superUser.ts +++ b/src/inhibitors/command/superUser.ts @@ -1,10 +1,10 @@ -import { BotInhibitor, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; +import { BotInhibitor, InhibitorReason, InhibitorType, type BotCommand, type CommandMessage, type SlashMessage } from '#lib'; export default class SuperUserInhibitor extends BotInhibitor { public constructor() { - super('superUser', { - reason: 'superUser', - type: 'post', + super(InhibitorReason.SuperUser, { + reason: InhibitorReason.SuperUser, + type: InhibitorType.Post, priority: 99 }); } diff --git a/src/listeners/automod/automodCreate.ts b/src/listeners/automod/automodCreate.ts index e2454e6..88520d2 100644 --- a/src/listeners/automod/automodCreate.ts +++ b/src/listeners/automod/automodCreate.ts @@ -1,14 +1,15 @@ -import { BotListener, MessageAutomod, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, MessageAutomod, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class AutomodMessageCreateListener extends BotListener { public constructor() { super('automodCreate', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']) { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { if (message.member === null) return; return new MessageAutomod(message); } diff --git a/src/listeners/automod/automodUpdate.ts b/src/listeners/automod/automodUpdate.ts index 0609e67..4c623cb 100644 --- a/src/listeners/automod/automodUpdate.ts +++ b/src/listeners/automod/automodUpdate.ts @@ -1,14 +1,15 @@ -import { BotListener, MessageAutomod, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, MessageAutomod, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class AutomodMessageUpdateListener extends BotListener { public constructor() { super('automodUpdate', { - emitter: 'client', - event: 'messageUpdate' + emitter: Emitter.Client, + event: Events.MessageUpdate }); } - public async exec(...[_, newMessage]: BotClientEvents['messageUpdate']) { + public async exec(...[_, newMessage]: BotClientEvents[Events.MessageUpdate]) { const fullMessage = newMessage.partial ? await newMessage.fetch().catch(() => null) : newMessage; if (!fullMessage?.member) return; return new MessageAutomod(fullMessage); diff --git a/src/listeners/automod/memberAutomod.ts b/src/listeners/automod/memberAutomod.ts index 557d13a..828e0a7 100644 --- a/src/listeners/automod/memberAutomod.ts +++ b/src/listeners/automod/memberAutomod.ts @@ -1,15 +1,16 @@ -import { BotClientEvents, BotListener, MemberAutomod } from '#lib'; +import { BotClientEvents, BotListener, Emitter, MemberAutomod } from '#lib'; import chalk from 'chalk'; +import { Events } from 'discord.js'; export default class PresenceAutomodListener extends BotListener { public constructor() { super('memberAutomod', { - emitter: 'client', - event: 'guildMemberUpdate' + emitter: Emitter.Client, + event: Events.GuildMemberUpdate }); } - public async exec(...[_, newMember]: BotClientEvents['guildMemberUpdate']) { + public async exec(...[_, newMember]: BotClientEvents[Events.GuildMemberUpdate]) { if (!(await newMember.guild.hasFeature('automodMembers'))) return; if (!(await newMember.guild.hasFeature('automod'))) return; diff --git a/src/listeners/automod/presenceAutomod.ts b/src/listeners/automod/presenceAutomod.ts index a89d45c..8ec3bab 100644 --- a/src/listeners/automod/presenceAutomod.ts +++ b/src/listeners/automod/presenceAutomod.ts @@ -1,14 +1,15 @@ -import { BotClientEvents, BotListener, PresenceAutomod } from '#lib'; +import { BotClientEvents, BotListener, Emitter, PresenceAutomod } from '#lib'; +import { Events } from 'discord.js'; export default class PresenceAutomodListener extends BotListener { public constructor() { super('presenceAutomod', { - emitter: 'client', - event: 'presenceUpdate' + emitter: Emitter.Client, + event: Events.PresenceUpdate }); } - public async exec(...[_, newPresence]: BotClientEvents['presenceUpdate']) { + public async exec(...[_, newPresence]: BotClientEvents[Events.PresenceUpdate]) { if (!newPresence.member || !newPresence.guild) return; if (!newPresence.activities.length) return; diff --git a/src/listeners/bush/appealListener.ts b/src/listeners/bush/appealListener.ts index ecc65c5..46859d1 100644 --- a/src/listeners/bush/appealListener.ts +++ b/src/listeners/bush/appealListener.ts @@ -1,18 +1,18 @@ -import { BotListener, colors, mappings, ModLog, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, mappings, ModLog, type BotClientEvents } from '#lib'; import assert from 'assert/strict'; -import { EmbedBuilder } from 'discord.js'; +import { EmbedBuilder, Events } from 'discord.js'; import UserInfoCommand from '../../commands/info/userInfo.js'; import ModlogCommand from '../../commands/moderation/modlog.js'; export default class AppealListener extends BotListener { public constructor() { super('appealListener', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']): Promise<any> { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]): Promise<any> { if (!this.client.config.isProduction || !message.inGuild() || message.guildId !== mappings.guilds["Moulberry's Bush"]) return; if (message.author.id !== '855446927688335370' || message.embeds.length < 1) return; diff --git a/src/listeners/bush/joinAutoBan.ts b/src/listeners/bush/joinAutoBan.ts index 66fdf54..706491f 100644 --- a/src/listeners/bush/joinAutoBan.ts +++ b/src/listeners/bush/joinAutoBan.ts @@ -1,15 +1,15 @@ -import { AllowedMentions, BotListener, colors, emojis, format, mappings, type BotClientEvents } from '#lib'; -import { TextChannel } from 'discord.js'; +import { AllowedMentions, BotListener, colors, Emitter, emojis, format, mappings, type BotClientEvents } from '#lib'; +import { Events, TextChannel } from 'discord.js'; export default class JoinAutoBanListener extends BotListener { public constructor() { super('joinAutoBan', { - emitter: 'client', - event: 'guildMemberAdd' + emitter: Emitter.Client, + event: Events.GuildMemberAdd }); } - public async exec(...[member]: BotClientEvents['guildMemberAdd']): Promise<void> { + public async exec(...[member]: BotClientEvents[Events.GuildMemberAdd]): Promise<void> { if (!this.client.config.isProduction) return; if (member.guild.id !== mappings.guilds["Moulberry's Bush"]) return; const guild = member.guild; diff --git a/src/listeners/bush/supportThread.ts b/src/listeners/bush/supportThread.ts index 3e806e2..ea39f3b 100644 --- a/src/listeners/bush/supportThread.ts +++ b/src/listeners/bush/supportThread.ts @@ -1,17 +1,17 @@ -import { BotListener, colors, mappings, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, mappings, type BotClientEvents } from '#lib'; import { stripIndent } from '#tags'; import assert from 'assert/strict'; -import { EmbedBuilder, MessageType, PermissionFlagsBits, TextChannel } from 'discord.js'; +import { EmbedBuilder, Events, MessageType, PermissionFlagsBits, TextChannel } from 'discord.js'; export default class SupportThreadListener extends BotListener { public constructor() { super('supportThread', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']): Promise<void | undefined> { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]): Promise<void | undefined> { if (!this.client.config.isProduction || !message.inGuild()) return; if (![MessageType.Default, MessageType.Reply].includes(message.type)) return; if (message.thread) return; diff --git a/src/listeners/bush/userUpdateAutoBan.ts b/src/listeners/bush/userUpdateAutoBan.ts index ae8bca3..e39f8da 100644 --- a/src/listeners/bush/userUpdateAutoBan.ts +++ b/src/listeners/bush/userUpdateAutoBan.ts @@ -1,11 +1,11 @@ -import { AllowedMentions, BotListener, colors, emojis, format, mappings, type BotClientEvents } from '#lib'; -import { GuildMember, type TextChannel } from 'discord.js'; +import { AllowedMentions, BotListener, colors, Emitter, emojis, format, mappings, type BotClientEvents } from '#lib'; +import { Events, GuildMember, type TextChannel } from 'discord.js'; export default class UserUpdateAutoBanListener extends BotListener { public constructor() { super('userUpdateAutoBan', { - emitter: 'client', - event: 'userUpdate' + emitter: Emitter.Client, + event: Events.UserUpdate }); } diff --git a/src/listeners/client/akairoDebug.ts b/src/listeners/client/akairoDebug.ts index af973bf..ee4d8a6 100644 --- a/src/listeners/client/akairoDebug.ts +++ b/src/listeners/client/akairoDebug.ts @@ -1,9 +1,9 @@ -import { BotListener, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; export default class DiscordJsDebugListener extends BotListener { public constructor() { super('akairoDebug', { - emitter: 'client', + emitter: Emitter.Client, event: 'akairoDebug' }); } diff --git a/src/listeners/client/djsDebug.ts b/src/listeners/client/djsDebug.ts index 28bac7f..6dd62a2 100644 --- a/src/listeners/client/djsDebug.ts +++ b/src/listeners/client/djsDebug.ts @@ -1,14 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; -export default class DiscordJsDebugListener extends BotListener { +export default class DjsDebugListener extends BotListener { public constructor() { - super('discordJsDebug', { - emitter: 'client', - event: 'debug' + super('djsDebug', { + emitter: Emitter.Client, + event: Events.Debug }); } - public async exec(...[message]: BotClientEvents['debug']): Promise<void> { + public async exec(...[message]: BotClientEvents[Events.Debug]): Promise<void> { void this.client.console.superVerbose('dc.js-debug', message); } } diff --git a/src/listeners/client/djsError.ts b/src/listeners/client/djsError.ts index 04fbfaa..23d8b33 100644 --- a/src/listeners/client/djsError.ts +++ b/src/listeners/client/djsError.ts @@ -1,14 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; -export default class DiscordJsErrorListener extends BotListener { +export default class DjsErrorListener extends BotListener { public constructor() { - super('discordJsError', { - emitter: 'client', - event: 'error' + super('djsError', { + emitter: Emitter.Client, + event: Events.Error }); } - public async exec(...[error]: BotClientEvents['error']): Promise<void> { + public async exec(...[error]: BotClientEvents[Events.Error]): Promise<void> { void this.client.console.superVerbose('dc.js-error', error); } } diff --git a/src/listeners/client/djsWarn.ts b/src/listeners/client/djsWarn.ts index 9162a36..f6c4608 100644 --- a/src/listeners/client/djsWarn.ts +++ b/src/listeners/client/djsWarn.ts @@ -1,14 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; -export default class DiscordJsWarnListener extends BotListener { +export default class DjsWarnListener extends BotListener { public constructor() { - super('discordJsWarn', { - emitter: 'client', - event: 'warn' + super('djsWarn', { + emitter: Emitter.Client, + event: Events.Warn }); } - public async exec(...[message]: BotClientEvents['warn']): Promise<void> { + public async exec(...[message]: BotClientEvents[Events.Warn]): Promise<void> { void this.client.console.superVerbose('dc.js-warn', message); } } diff --git a/src/listeners/client/ready.ts b/src/listeners/client/ready.ts index 1c887ed..b74c132 100644 --- a/src/listeners/client/ready.ts +++ b/src/listeners/client/ready.ts @@ -1,17 +1,17 @@ -import { BotClientEvents, BotListener, Guild } from '#lib'; +import { BotClientEvents, BotListener, Emitter, Guild } from '#lib'; import chalk from 'chalk'; +import { Events } from 'discord.js'; export default class ReadyListener extends BotListener { public constructor() { super('ready', { - emitter: 'client', - event: 'ready', - type: 'on' + emitter: Emitter.Client, + event: Events.ClientReady }); } // eslint-disable-next-line no-empty-pattern - public async exec(...[]: BotClientEvents['ready']) { + public async exec(...[]: BotClientEvents[Events.ClientReady]) { process.emit('ready' as any); const tag = `<<${this.client.user?.tag}>>`, diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts index d9a95c1..534e744 100644 --- a/src/listeners/commands/commandBlocked.ts +++ b/src/listeners/commands/commandBlocked.ts @@ -1,33 +1,31 @@ import { - BlockedReasons, BotListener, + CommandHandlerEvent, + Emitter, emojis, format, + InhibitorReason, oxford, - type BotCommand, type BotCommandHandlerEvents, - type CommandMessage, - type SlashMessage + type CommandMessage } from '#lib'; import { type Client, type InteractionReplyOptions, type ReplyMessageOptions } from 'discord.js'; export default class CommandBlockedListener extends BotListener { public constructor() { super('commandBlocked', { - emitter: 'commandHandler', - event: 'commandBlocked' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.CommandBlocked }); } - public async exec(...[message, command, reason]: BotCommandHandlerEvents['commandBlocked']) { + public async exec(...[message, command, reason]: BotCommandHandlerEvents[CommandHandlerEvent.CommandBlocked]) { return await CommandBlockedListener.handleBlocked(this.client, message, command, reason); } public static async handleBlocked( client: Client, - message: CommandMessage | SlashMessage, - command: BotCommand | null, - reason?: string + ...[message, command, reason]: BotCommandHandlerEvents[CommandHandlerEvent.CommandBlocked | CommandHandlerEvent.SlashBlocked] ) { const isSlash = !!command && !!message.util?.isSlash; @@ -40,25 +38,25 @@ export default class CommandBlockedListener extends BotListener { ); switch (reason) { - case BlockedReasons.OWNER: { + case InhibitorReason.Owner: { return await respond({ content: `${emojis.error} Only my developers can run the ${format.input(command!.id)} command.`, ephemeral: true }); } - case BlockedReasons.SUPER_USER: { + case InhibitorReason.SuperUser: { return await respond({ content: `${emojis.error} You must be a superuser to run the ${format.input(command!.id)} command.`, ephemeral: true }); } - case BlockedReasons.DISABLED_GLOBAL: { + case InhibitorReason.DisabledGlobal: { return await respond({ content: `${emojis.error} My developers disabled the ${format.input(command!.id)} command.`, ephemeral: true }); } - case BlockedReasons.DISABLED_GUILD: { + case InhibitorReason.DisabledGuild: { return await respond({ content: `${emojis.error} The ${format.input(command!.id)} command is currently disabled in ${format.input( message.guild!.name @@ -66,23 +64,23 @@ export default class CommandBlockedListener extends BotListener { ephemeral: true }); } - case BlockedReasons.CHANNEL_GLOBAL_BLACKLIST: - case BlockedReasons.CHANNEL_GUILD_BLACKLIST: + case InhibitorReason.ChannelGlobalBlacklist: + case InhibitorReason.ChannelGuildBlacklist: return isSlash ? await respond({ content: `${emojis.error} You cannot use this bot in this channel.`, ephemeral: true }) : await (message as CommandMessage).react(emojis.cross); - case BlockedReasons.USER_GLOBAL_BLACKLIST: - case BlockedReasons.USER_GUILD_BLACKLIST: + case InhibitorReason.UserGlobalBlacklist: + case InhibitorReason.UserGuildBlacklist: return isSlash ? await respond({ content: `${emojis.error} You are blacklisted from using this bot.`, ephemeral: true }) : await (message as CommandMessage).react(emojis.cross); - case BlockedReasons.ROLE_BLACKLIST: { + case InhibitorReason.RoleBlacklist: { return isSlash ? await respond({ content: `${emojis.error} One of your roles blacklists you from using this bot.`, @@ -90,7 +88,7 @@ export default class CommandBlockedListener extends BotListener { }) : await (message as CommandMessage).react(emojis.cross); } - case BlockedReasons.RESTRICTED_CHANNEL: { + case InhibitorReason.RestrictedChannel: { if (!command) break; const channels = command.restrictedChannels; const names: string[] = []; @@ -103,7 +101,7 @@ export default class CommandBlockedListener extends BotListener { ephemeral: true }); } - case BlockedReasons.RESTRICTED_GUILD: { + case InhibitorReason.RestrictedGuild: { if (!command) break; const guilds = command.restrictedGuilds; const names = guilds!.map((g) => format.input(client.guilds.cache.get(g)?.name ?? g)); @@ -113,6 +111,10 @@ export default class CommandBlockedListener extends BotListener { ephemeral: true }); } + case InhibitorReason.CannotSend: + case InhibitorReason.Fatal: + // don't send anything + break; default: { return await respond({ content: `${emojis.error} Command blocked with reason ${format.input(reason ?? 'unknown')}.`, diff --git a/src/listeners/commands/commandCooldown.ts b/src/listeners/commands/commandCooldown.ts index 1a5b790..2ec95e0 100644 --- a/src/listeners/commands/commandCooldown.ts +++ b/src/listeners/commands/commandCooldown.ts @@ -1,14 +1,14 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; export default class CommandCooldownListener extends BotListener { public constructor() { super('commandCooldown', { - emitter: 'commandHandler', - event: 'cooldown' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.Cooldown }); } - public async exec(...[message, command, remaining]: BotCommandHandlerEvents['cooldown']) { + public async exec(...[message, command, remaining]: BotCommandHandlerEvents[CommandHandlerEvent.Cooldown]) { void this.client.console.info( 'commandCooldown', `<<${message.author.tag}>> tried to run <<${ diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts index b96b8de..027c567 100644 --- a/src/listeners/commands/commandError.ts +++ b/src/listeners/commands/commandError.ts @@ -1,14 +1,14 @@ -import { BotListener, handleCommandError, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, handleCommandError, type BotCommandHandlerEvents } from '#lib'; export default class CommandErrorListener extends BotListener { public constructor() { super('commandError', { - emitter: 'commandHandler', - event: 'error' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.Error }); } - public exec(...[error, message, command]: BotCommandHandlerEvents['error']) { + public exec(...[error, message, command]: BotCommandHandlerEvents[CommandHandlerEvent.Error]) { return handleCommandError(this.client, error, message, command); } } diff --git a/src/listeners/commands/commandLocked.ts b/src/listeners/commands/commandLocked.ts index fbceca8..1033861 100644 --- a/src/listeners/commands/commandLocked.ts +++ b/src/listeners/commands/commandLocked.ts @@ -1,14 +1,14 @@ -import { BotListener, emojis, format, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, emojis, format, type BotCommandHandlerEvents } from '#lib'; export default class CommandLockedListener extends BotListener { public constructor() { super('commandLocked', { - emitter: 'commandHandler', - event: 'commandLocked' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.CommandLocked }); } - public async exec(...[message, command]: BotCommandHandlerEvents['commandLocked']) { + public async exec(...[message, command]: BotCommandHandlerEvents[CommandHandlerEvent.CommandLocked]) { return message.util.reply( `${emojis.error} You cannot use the ${format.input(command.id)} command because it is already in use.` ); diff --git a/src/listeners/commands/commandMissingPermissions.ts b/src/listeners/commands/commandMissingPermissions.ts index a2ec461..9a59077 100644 --- a/src/listeners/commands/commandMissingPermissions.ts +++ b/src/listeners/commands/commandMissingPermissions.ts @@ -1,26 +1,35 @@ -import { BotListener, emojis, format, mappings, oxford, surroundArray, type BotCommandHandlerEvents } from '#lib'; +import { + BotListener, + CommandHandlerEvent, + Emitter, + emojis, + format, + mappings, + oxford, + surroundArray, + type BotCommandHandlerEvents +} from '#lib'; import { Client, type PermissionsString } from 'discord.js'; export default class CommandMissingPermissionsListener extends BotListener { public constructor() { super('commandMissingPermissions', { - emitter: 'commandHandler', - event: 'missingPermissions' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.MissingPermissions }); } - public async exec(...[message, command, type, missing]: BotCommandHandlerEvents['missingPermissions']) { + public async exec(...[message, command, type, missing]: BotCommandHandlerEvents[CommandHandlerEvent.MissingPermissions]) { return await CommandMissingPermissionsListener.handleMissing(this.client, message, command, type, missing); } public static async handleMissing( client: Client, ...[message, command, type, missing]: - | BotCommandHandlerEvents['missingPermissions'] - | BotCommandHandlerEvents['slashMissingPermissions'] + | BotCommandHandlerEvents[CommandHandlerEvent.MissingPermissions | CommandHandlerEvent.SlashMissingPermissions] ) { const niceMissing = (missing.includes('Administrator') ? (['Administrator'] as PermissionsString[]) : missing).map( - (perm) => mappings.permissions[perm]?.name ?? missing + (perm) => mappings.permissions[perm as PermissionsString]?.name ?? missing ); const discordFormat = oxford(surroundArray(niceMissing, '**'), 'and', ''); @@ -31,6 +40,14 @@ export default class CommandMissingPermissionsListener extends BotListener { command?.id }>> but could not because <<${type}>> is missing the ${consoleFormat} permissions${missing.length ? 's' : ''}.` ); + + // fix: this is far too jank + if (missing.length === 1 && missing[0] === '[[UnsupportedChannel]]') { + return await message.util + .reply(`${emojis.error} Forum channels are not supported by the ${format.input(command?.id)} command.`) + .catch(() => {}); + } + if (type == 'client') { return await message.util .reply( diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts index 407662c..9c687b6 100644 --- a/src/listeners/commands/commandStarted.ts +++ b/src/listeners/commands/commandStarted.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; import { ChannelType } from 'discord.js'; export default class CommandStartedListener extends BotListener { public constructor() { super('commandStarted', { - emitter: 'commandHandler', - event: 'commandStarted' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.CommandStarted }); } - public exec(...[message, command]: BotCommandHandlerEvents['commandStarted']): void { + public exec(...[message, command]: BotCommandHandlerEvents[CommandHandlerEvent.CommandStarted]): void { this.client.sentry.addBreadcrumb({ message: `[commandStarted] The ${command.id} was started by ${message.author.tag}.`, level: 'info', diff --git a/src/listeners/commands/messageBlocked.ts b/src/listeners/commands/messageBlocked.ts index 3d92d32..797a00c 100644 --- a/src/listeners/commands/messageBlocked.ts +++ b/src/listeners/commands/messageBlocked.ts @@ -1,14 +1,14 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; export default class MessageBlockedListener extends BotListener { public constructor() { super('messageBlocked', { - emitter: 'commandHandler', - event: 'messageBlocked' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.MessageBlocked }); } - public async exec(...[message, reason]: BotCommandHandlerEvents['messageBlocked']) { + public async exec(...[message, reason]: BotCommandHandlerEvents[CommandHandlerEvent.MessageBlocked]) { if (['client', 'bot'].includes(reason)) return; // return await CommandBlockedListener.handleBlocked(message as Message, null, reason); return void this.client.console.verbose( diff --git a/src/listeners/commands/slashBlocked.ts b/src/listeners/commands/slashBlocked.ts index 528c97b..7114d3e 100644 --- a/src/listeners/commands/slashBlocked.ts +++ b/src/listeners/commands/slashBlocked.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; import CommandBlockedListener from './commandBlocked.js'; export default class SlashBlockedListener extends BotListener { public constructor() { super('slashBlocked', { - emitter: 'commandHandler', - event: 'slashBlocked' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.SlashBlocked }); } - public async exec(...[message, command, reason]: BotCommandHandlerEvents['slashBlocked']) { + public async exec(...[message, command, reason]: BotCommandHandlerEvents[CommandHandlerEvent.SlashBlocked]) { return await CommandBlockedListener.handleBlocked(this.client, message, command, reason); } } diff --git a/src/listeners/commands/slashCommandError.ts b/src/listeners/commands/slashCommandError.ts index 03eb34a..11f4e1d 100644 --- a/src/listeners/commands/slashCommandError.ts +++ b/src/listeners/commands/slashCommandError.ts @@ -1,14 +1,14 @@ -import { BotListener, handleCommandError, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, handleCommandError, type BotCommandHandlerEvents } from '#lib'; export default class SlashCommandErrorListener extends BotListener { public constructor() { super('slashError', { - emitter: 'commandHandler', - event: 'slashError' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.SlashError }); } - public async exec(...[error, message, command]: BotCommandHandlerEvents['slashError']) { + public async exec(...[error, message, command]: BotCommandHandlerEvents[CommandHandlerEvent.SlashError]) { return await handleCommandError(this.client, error, message, command); } } diff --git a/src/listeners/commands/slashMissingPermissions.ts b/src/listeners/commands/slashMissingPermissions.ts index 68388bf..6054940 100644 --- a/src/listeners/commands/slashMissingPermissions.ts +++ b/src/listeners/commands/slashMissingPermissions.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; import CommandMissingPermissionsListener from './commandMissingPermissions.js'; export default class SlashMissingPermissionsListener extends BotListener { public constructor() { super('slashMissingPermissions', { - emitter: 'commandHandler', - event: 'slashMissingPermissions' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.SlashMissingPermissions }); } - public async exec(...[message, command, type, missing]: BotCommandHandlerEvents['slashMissingPermissions']) { + public async exec(...[message, command, type, missing]: BotCommandHandlerEvents[CommandHandlerEvent.SlashMissingPermissions]) { return await CommandMissingPermissionsListener.handleMissing(this.client, message, command, type, missing); } } diff --git a/src/listeners/commands/slashNotFound.ts b/src/listeners/commands/slashNotFound.ts index 7e76fe6..4a33e96 100644 --- a/src/listeners/commands/slashNotFound.ts +++ b/src/listeners/commands/slashNotFound.ts @@ -1,14 +1,14 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; export default class SlashNotFoundListener extends BotListener { public constructor() { super('slashNotFound', { - emitter: 'commandHandler', - event: 'slashNotFound' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.SlashNotFound }); } - public async exec(...[interaction]: BotCommandHandlerEvents['slashNotFound']) { + public async exec(...[interaction]: BotCommandHandlerEvents[CommandHandlerEvent.SlashNotFound]) { void this.client.console.info('slashNotFound', `<<${interaction?.commandName}>> could not be found.`); } } diff --git a/src/listeners/commands/slashStarted.ts b/src/listeners/commands/slashStarted.ts index 898af13..3dddd37 100644 --- a/src/listeners/commands/slashStarted.ts +++ b/src/listeners/commands/slashStarted.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, type BotCommandHandlerEvents } from '#lib'; import { ChannelType } from 'discord.js'; export default class SlashStartedListener extends BotListener { public constructor() { super('slashStarted', { - emitter: 'commandHandler', - event: 'slashStarted' + emitter: Emitter.CommandHandler, + event: CommandHandlerEvent.SlashStarted }); } - public async exec(...[message, command]: BotCommandHandlerEvents['slashStarted']) { + public async exec(...[message, command]: BotCommandHandlerEvents[CommandHandlerEvent.SlashStarted]) { this.client.sentry.addBreadcrumb({ message: `[slashStarted] The ${command.id} was started by ${message.author.tag}.`, level: 'info', diff --git a/src/listeners/contextCommands/contextCommandBlocked.ts b/src/listeners/contextCommands/contextCommandBlocked.ts index d8d002e..93b53c7 100644 --- a/src/listeners/contextCommands/contextCommandBlocked.ts +++ b/src/listeners/contextCommands/contextCommandBlocked.ts @@ -1,15 +1,16 @@ -import { BlockedReasons, BotListener, emojis, format } from '#lib'; +import { BotListener, ContextCommandHandlerEvent, Emitter, emojis, format } from '#lib'; import { type ContextMenuCommandHandlerEvents } from 'discord-akairo'; +import { BuiltInReasons } from 'discord-akairo/dist/src/util/Constants.js'; export default class ContextCommandBlockedListener extends BotListener { public constructor() { super('contextCommandBlocked', { - emitter: 'contextMenuCommandHandler', - event: 'blocked' + emitter: Emitter.ContextMenuCommandHandler, + event: ContextCommandHandlerEvent.Blocked }); } - public async exec(...[interaction, command, reason]: ContextMenuCommandHandlerEvents['blocked']) { + public async exec(...[interaction, command, reason]: ContextMenuCommandHandlerEvents[ContextCommandHandlerEvent.Blocked]) { void this.client.console.info( `ContextCommandBlocked`, `<<${interaction.user.tag}>> tried to run <<${command}>> but was blocked because <<${reason}>>.`, @@ -17,13 +18,13 @@ export default class ContextCommandBlockedListener extends BotListener { ); switch (reason) { - case BlockedReasons.OWNER: { + case BuiltInReasons.OWNER: { return await interaction.reply({ content: `${emojis.error} Only my developers can run the ${format.input(command!.id)} command.`, ephemeral: true }); } - case BlockedReasons.SUPER_USER: { + case BuiltInReasons.SUPER_USER: { return await interaction.reply({ content: `${emojis.error} You must be a superuser to run the ${format.input(command!.id)} command.`, ephemeral: true diff --git a/src/listeners/contextCommands/contextCommandError.ts b/src/listeners/contextCommands/contextCommandError.ts index 091bee9..24e5cef 100644 --- a/src/listeners/contextCommands/contextCommandError.ts +++ b/src/listeners/contextCommands/contextCommandError.ts @@ -1,20 +1,33 @@ -import { BotListener, colors, format, formatError, getErrorHaste, getErrorStack, IFuckedUpError } from '#lib'; +import { + BotListener, + colors, + ContextCommandHandlerEvent, + Emitter, + format, + formatError, + getErrorHaste, + getErrorStack, + IFuckedUpError +} from '#lib'; import { type ContextMenuCommand, type ContextMenuCommandHandlerEvents } from 'discord-akairo'; import { ChannelType, Client, ContextMenuCommandInteraction, EmbedBuilder, GuildTextBasedChannel } from 'discord.js'; export default class ContextCommandErrorListener extends BotListener { public constructor() { super('contextCommandError', { - emitter: 'contextMenuCommandHandler', - event: 'error' + emitter: Emitter.ContextMenuCommandHandler, + event: ContextCommandHandlerEvent.Error }); } - public exec(...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) { + public exec(...[error, interaction, command]: ContextMenuCommandHandlerEvents[ContextCommandHandlerEvent.Error]) { return ContextCommandErrorListener.handleError(this.client, error, interaction, command); } - public static async handleError(client: Client, ...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) { + public static async handleError( + client: Client, + ...[error, interaction, command]: ContextMenuCommandHandlerEvents[ContextCommandHandlerEvent.Error] + ) { try { const errorNum = Math.floor(Math.random() * 6969696969) + 69; // hehe funny number const channel = diff --git a/src/listeners/contextCommands/contextCommandNotFound.ts b/src/listeners/contextCommands/contextCommandNotFound.ts index 4bb397e..da364ed 100644 --- a/src/listeners/contextCommands/contextCommandNotFound.ts +++ b/src/listeners/contextCommands/contextCommandNotFound.ts @@ -1,15 +1,15 @@ -import { BotListener } from '#lib'; +import { BotListener, ContextCommandHandlerEvent, Emitter } from '#lib'; import { type ContextMenuCommandHandlerEvents } from 'discord-akairo'; export default class ContextCommandNotFoundListener extends BotListener { public constructor() { super('contextCommandNotFound', { - emitter: 'contextMenuCommandHandler', - event: 'notFound' + emitter: Emitter.ContextMenuCommandHandler, + event: ContextCommandHandlerEvent.NotFound }); } - public async exec(...[interaction]: ContextMenuCommandHandlerEvents['notFound']) { + public async exec(...[interaction]: ContextMenuCommandHandlerEvents[ContextCommandHandlerEvent.NotFound]) { void this.client.console.info('contextCommandNotFound', `<<${interaction?.commandName}>> could not be found.`); } } diff --git a/src/listeners/contextCommands/contextCommandStarted.ts b/src/listeners/contextCommands/contextCommandStarted.ts index 867af54..bf7cc58 100644 --- a/src/listeners/contextCommands/contextCommandStarted.ts +++ b/src/listeners/contextCommands/contextCommandStarted.ts @@ -1,16 +1,16 @@ -import { BotListener } from '#lib'; +import { BotListener, ContextCommandHandlerEvent, Emitter } from '#lib'; import { ContextMenuCommandHandlerEvents } from 'discord-akairo'; import { ApplicationCommandType, ChannelType } from 'discord.js'; export default class ContextCommandStartedListener extends BotListener { public constructor() { super('contextCommandStarted', { - emitter: 'contextMenuCommandHandler', - event: 'started' + emitter: Emitter.ContextMenuCommandHandler, + event: ContextCommandHandlerEvent.Started }); } - public async exec(...[interaction, command]: ContextMenuCommandHandlerEvents['started']) { + public async exec(...[interaction, command]: ContextMenuCommandHandlerEvents[ContextCommandHandlerEvent.Started]) { this.client.sentry.addBreadcrumb({ message: `[contextCommandStarted] The ${command.id} was started by ${interaction.user.tag}.`, level: 'info', diff --git a/src/listeners/guild-custom/lockdown.ts b/src/listeners/guild-custom/lockdown.ts index bf3ee7c..1551377 100644 --- a/src/listeners/guild-custom/lockdown.ts +++ b/src/listeners/guild-custom/lockdown.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, emojis, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder } from 'discord.js'; export default class LockdownListener extends BotListener { public constructor() { super('lockdown', { - emitter: 'client', - event: 'lockdown' + emitter: Emitter.Client, + event: TanzaniteEvent.Lockdown }); } - public async exec(...[moderator, reason, channelsSuccessMap, _all]: BotClientEvents['lockdown']) { + public async exec(...[moderator, reason, channelsSuccessMap, _all]: BotClientEvents[TanzaniteEvent.Lockdown]) { const logChannel = await moderator.guild.getLogChannel('moderation'); if (!logChannel) return; diff --git a/src/listeners/guild-custom/unlockdown.ts b/src/listeners/guild-custom/unlockdown.ts index e08a42b..6b6e16e 100644 --- a/src/listeners/guild-custom/unlockdown.ts +++ b/src/listeners/guild-custom/unlockdown.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, emojis, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder } from 'discord.js'; export default class UnlockdownListener extends BotListener { public constructor() { - super('unlockdown', { - emitter: 'client', - event: 'unlockdown' + super(TanzaniteEvent.Unlockdown, { + emitter: Emitter.Client, + event: TanzaniteEvent.Unlockdown }); } - public async exec(...[moderator, reason, channelsSuccessMap, _all]: BotClientEvents['unlockdown']) { + public async exec(...[moderator, reason, channelsSuccessMap, _all]: BotClientEvents[TanzaniteEvent.Unlockdown]) { const logChannel = await moderator.guild.getLogChannel('moderation'); if (!logChannel) return; diff --git a/src/listeners/guild/guildCreate.ts b/src/listeners/guild/guildCreate.ts index 3db28d6..c4d33a5 100644 --- a/src/listeners/guild/guildCreate.ts +++ b/src/listeners/guild/guildCreate.ts @@ -1,14 +1,15 @@ -import { BotListener, colors, emojis, format, Guild, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, format, Guild, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class GuildCreateListener extends BotListener { public constructor() { super('guildCreate', { - emitter: 'client', - event: 'guildCreate' // when the bot joins a guild + emitter: Emitter.Client, + event: Events.GuildCreate // when the bot joins a guild }); } - public async exec(...[guild]: BotClientEvents['guildCreate']) { + public async exec(...[guild]: BotClientEvents[Events.GuildCreate]) { void this.client.console.info( 'guildCreate', `Joined <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.` diff --git a/src/listeners/guild/guildDelete.ts b/src/listeners/guild/guildDelete.ts index 2cc23f1..b87694d 100644 --- a/src/listeners/guild/guildDelete.ts +++ b/src/listeners/guild/guildDelete.ts @@ -1,14 +1,15 @@ -import { BotListener, colors, emojis, format, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, format, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class GuildDeleteListener extends BotListener { public constructor() { super('guildDelete', { - emitter: 'client', - event: 'guildDelete' // when the bot leaves a guild + emitter: Emitter.Client, + event: Events.GuildDelete // when the bot leaves a guild }); } - public async exec(...[guild]: BotClientEvents['guildDelete']) { + public async exec(...[guild]: BotClientEvents[Events.GuildDelete]) { void this.client.console.info( 'guildDelete', `Left <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.` diff --git a/src/listeners/guild/guildMemberAdd.ts b/src/listeners/guild/guildMemberAdd.ts index 9268f01..d44f395 100644 --- a/src/listeners/guild/guildMemberAdd.ts +++ b/src/listeners/guild/guildMemberAdd.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, emojis, format, type BotClientEvents } from '#lib'; -import { EmbedBuilder, type GuildMember, type TextChannel } from 'discord.js'; +import { BotListener, colors, Emitter, emojis, format, type BotClientEvents } from '#lib'; +import { EmbedBuilder, Events, type GuildMember, type TextChannel } from 'discord.js'; export default class GuildMemberAddListener extends BotListener { public constructor() { super('guildMemberAdd', { - emitter: 'client', - event: 'guildMemberAdd' + emitter: Emitter.Client, + event: Events.GuildMemberAdd }); } - public async exec(...[member]: BotClientEvents['guildMemberAdd']) { + public async exec(...[member]: BotClientEvents[Events.GuildMemberAdd]) { void this.sendWelcomeMessage(member); } diff --git a/src/listeners/guild/guildMemberRemove.ts b/src/listeners/guild/guildMemberRemove.ts index ee626d6..4112365 100644 --- a/src/listeners/guild/guildMemberRemove.ts +++ b/src/listeners/guild/guildMemberRemove.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, emojis, format, sleep, StickyRole, Time, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, format, sleep, StickyRole, Time, type BotClientEvents } from '#lib'; import { EmbedBuilder, type GuildMember, type PartialGuildMember, type TextChannel } from 'discord.js'; export default class GuildMemberRemoveListener extends BotListener { public constructor() { super('guildMemberRemove', { - emitter: 'client', + emitter: Emitter.Client, event: 'guildMemberRemove' }); } diff --git a/src/listeners/guild/joinRoles.ts b/src/listeners/guild/joinRoles.ts index 142d4cd..195e36a 100644 --- a/src/listeners/guild/joinRoles.ts +++ b/src/listeners/guild/joinRoles.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, format, StickyRole, type BotClientEvents } from '#lib'; -import { type GuildMember, type Snowflake } from 'discord.js'; +import { BotListener, colors, Emitter, format, StickyRole, type BotClientEvents } from '#lib'; +import { Events, type GuildMember, type Snowflake } from 'discord.js'; export default class JoinRolesListener extends BotListener { public constructor() { super('joinRoles', { - emitter: 'client', - event: 'guildMemberUpdate' // listens to guildMemberUpdate so that the role's aren't given before the member accepts the welcome screen + emitter: Emitter.Client, + event: Events.GuildMemberUpdate // listens to guildMemberUpdate so that the role's aren't given before the member accepts the welcome screen }); } - public async exec(...[oldMember, newMember]: BotClientEvents['guildMemberUpdate']) { + public async exec(...[oldMember, newMember]: BotClientEvents[Events.GuildMemberUpdate]) { if (this.client.config.isDevelopment) return; if (oldMember.pending && !newMember.pending) { const feat = { diff --git a/src/listeners/guild/syncUnbanPunishmentModel.ts b/src/listeners/guild/syncUnbanPunishmentModel.ts index 352d704..eac3aa2 100644 --- a/src/listeners/guild/syncUnbanPunishmentModel.ts +++ b/src/listeners/guild/syncUnbanPunishmentModel.ts @@ -1,9 +1,9 @@ -import { ActivePunishment, ActivePunishmentType, BotListener, type BotClientEvents } from '#lib'; +import { ActivePunishment, ActivePunishmentType, BotListener, Emitter, type BotClientEvents } from '#lib'; export default class SyncUnbanListener extends BotListener { public constructor() { super('syncUnbanPunishmentModel', { - emitter: 'client', + emitter: Emitter.Client, event: 'guildBanRemove' }); } diff --git a/src/listeners/interaction/interactionCreate.ts b/src/listeners/interaction/interactionCreate.ts index d8a5cc9..c4c14c1 100644 --- a/src/listeners/interaction/interactionCreate.ts +++ b/src/listeners/interaction/interactionCreate.ts @@ -1,15 +1,24 @@ -import { BotListener, emojis, format, handleAutomodInteraction, oxford, surroundArray, type BotClientEvents } from '#lib'; -import { InteractionType } from 'discord.js'; +import { + BotListener, + Emitter, + emojis, + format, + handleAutomodInteraction, + oxford, + surroundArray, + type BotClientEvents +} from '#lib'; +import { Events, InteractionType } from 'discord.js'; export default class InteractionCreateListener extends BotListener { public constructor() { super('interactionCreate', { - emitter: 'client', - event: 'interactionCreate' + emitter: Emitter.Client, + event: Events.InteractionCreate }); } - public async exec(...[interaction]: BotClientEvents['interactionCreate']) { + public async exec(...[interaction]: BotClientEvents[Events.InteractionCreate]) { if (!interaction) return; if ('customId' in interaction && (interaction as any)['customId'].startsWith('test')) return; void this.client.console.verbose( diff --git a/src/listeners/member-custom/customBan.ts b/src/listeners/member-custom/customBan.ts index 5b199bb..7a5f0d9 100644 --- a/src/listeners/member-custom/customBan.ts +++ b/src/listeners/member-custom/customBan.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomBanListener extends BotListener { public constructor() { super(TanzaniteEvent.Ban, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Ban }); } diff --git a/src/listeners/member-custom/customBlock.ts b/src/listeners/member-custom/customBlock.ts index 8faa0b7..bf6bc31 100644 --- a/src/listeners/member-custom/customBlock.ts +++ b/src/listeners/member-custom/customBlock.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomBlockListener extends BotListener { public constructor() { super(TanzaniteEvent.Block, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Block }); } diff --git a/src/listeners/member-custom/customKick.ts b/src/listeners/member-custom/customKick.ts index bf3e2fe..085d628 100644 --- a/src/listeners/member-custom/customKick.ts +++ b/src/listeners/member-custom/customKick.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomKickListener extends BotListener { public constructor() { super(TanzaniteEvent.Kick, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Kick }); } diff --git a/src/listeners/member-custom/customMute.ts b/src/listeners/member-custom/customMute.ts index 21a24e8..21bfbe7 100644 --- a/src/listeners/member-custom/customMute.ts +++ b/src/listeners/member-custom/customMute.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomMuteListener extends BotListener { public constructor() { super(TanzaniteEvent.Mute, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Mute }); } diff --git a/src/listeners/member-custom/customPurge.ts b/src/listeners/member-custom/customPurge.ts index 956fcb7..70e3f10 100644 --- a/src/listeners/member-custom/customPurge.ts +++ b/src/listeners/member-custom/customPurge.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, emojis, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, emojis, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder } from 'discord.js'; export default class CustomPurgeListener extends BotListener { public constructor() { super(TanzaniteEvent.Purge, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Purge }); } diff --git a/src/listeners/member-custom/customRemoveTimeout.ts b/src/listeners/member-custom/customRemoveTimeout.ts index 00454bd..037e1b6 100644 --- a/src/listeners/member-custom/customRemoveTimeout.ts +++ b/src/listeners/member-custom/customRemoveTimeout.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomRemoveTimeoutListener extends BotListener { public constructor() { super(TanzaniteEvent.RemoveTimeout, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.RemoveTimeout }); } diff --git a/src/listeners/member-custom/customTimeout.ts b/src/listeners/member-custom/customTimeout.ts index 6b142ec..f21046a 100644 --- a/src/listeners/member-custom/customTimeout.ts +++ b/src/listeners/member-custom/customTimeout.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomTimeoutListener extends BotListener { public constructor() { super(TanzaniteEvent.Timeout, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Timeout }); } diff --git a/src/listeners/member-custom/customUnban.ts b/src/listeners/member-custom/customUnban.ts index aa4cd75..f3309f3 100644 --- a/src/listeners/member-custom/customUnban.ts +++ b/src/listeners/member-custom/customUnban.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomUnbanListener extends BotListener { public constructor() { super(TanzaniteEvent.Unban, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Unban }); } diff --git a/src/listeners/member-custom/customUnblock.ts b/src/listeners/member-custom/customUnblock.ts index a7553d9..827da44 100644 --- a/src/listeners/member-custom/customUnblock.ts +++ b/src/listeners/member-custom/customUnblock.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomUnblockListener extends BotListener { public constructor() { super(TanzaniteEvent.Unblock, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Unblock }); } diff --git a/src/listeners/member-custom/customUnmute.ts b/src/listeners/member-custom/customUnmute.ts index ef7b22f..1de5456 100644 --- a/src/listeners/member-custom/customUnmute.ts +++ b/src/listeners/member-custom/customUnmute.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomUnmuteListener extends BotListener { public constructor() { super(TanzaniteEvent.Unmute, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Unmute }); } diff --git a/src/listeners/member-custom/customWarnMember.ts b/src/listeners/member-custom/customWarnMember.ts index 3ca7e08..4a56086 100644 --- a/src/listeners/member-custom/customWarnMember.ts +++ b/src/listeners/member-custom/customWarnMember.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class CustomWarnListener extends BotListener { public constructor() { super(TanzaniteEvent.Warn, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.Warn }); } diff --git a/src/listeners/member-custom/levelUpdate.ts b/src/listeners/member-custom/levelUpdate.ts index 64dd388..53734fd 100644 --- a/src/listeners/member-custom/levelUpdate.ts +++ b/src/listeners/member-custom/levelUpdate.ts @@ -1,4 +1,4 @@ -import { BotListener, format, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, format, TanzaniteEvent, type BotClientEvents } from '#lib'; import assert from 'assert/strict'; import { type TextChannel } from 'discord.js'; @@ -7,7 +7,7 @@ type Args = BotClientEvents[TanzaniteEvent.LevelUpdate]; export default class LevelUpdateListener extends BotListener { public constructor() { super(TanzaniteEvent.LevelUpdate, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.LevelUpdate }); } diff --git a/src/listeners/member-custom/massBan.ts b/src/listeners/member-custom/massBan.ts index 7a6cd34..501902e 100644 --- a/src/listeners/member-custom/massBan.ts +++ b/src/listeners/member-custom/massBan.ts @@ -1,9 +1,19 @@ -import { BanResponse, banResponse, BotListener, colors, emojis, overflowEmbed, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { + BanResponse, + banResponse, + BotListener, + colors, + Emitter, + emojis, + overflowEmbed, + TanzaniteEvent, + type BotClientEvents +} from '#lib'; export default class MassBanListener extends BotListener { public constructor() { super(TanzaniteEvent.MassBan, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.MassBan }); } diff --git a/src/listeners/member-custom/massEvidence.ts b/src/listeners/member-custom/massEvidence.ts index acfa4f7..0cc9477 100644 --- a/src/listeners/member-custom/massEvidence.ts +++ b/src/listeners/member-custom/massEvidence.ts @@ -1,9 +1,9 @@ -import { BotListener, colors, overflowEmbed, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, overflowEmbed, TanzaniteEvent, type BotClientEvents } from '#lib'; export default class MassEvidenceListener extends BotListener { public constructor() { super(TanzaniteEvent.MassEvidence, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.MassEvidence }); } diff --git a/src/listeners/member-custom/punishRole.ts b/src/listeners/member-custom/punishRole.ts index 70a04d7..a7ef8ad 100644 --- a/src/listeners/member-custom/punishRole.ts +++ b/src/listeners/member-custom/punishRole.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, humanizeDuration, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class PunishRoleListener extends BotListener { public constructor() { super(TanzaniteEvent.PunishRoleAdd, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.PunishRoleAdd }); } diff --git a/src/listeners/member-custom/punishRoleRemove.ts b/src/listeners/member-custom/punishRoleRemove.ts index f144284..08d79d6 100644 --- a/src/listeners/member-custom/punishRoleRemove.ts +++ b/src/listeners/member-custom/punishRoleRemove.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder, GuildMember } from 'discord.js'; export default class PunishRoleRemoveListener extends BotListener { public constructor() { super(TanzaniteEvent.PunishRoleRemove, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.PunishRoleRemove }); } diff --git a/src/listeners/member-custom/updateModlog.ts b/src/listeners/member-custom/updateModlog.ts index f5f910d..2696ab8 100644 --- a/src/listeners/member-custom/updateModlog.ts +++ b/src/listeners/member-custom/updateModlog.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder } from 'discord.js'; export default class UpdateModlogListener extends BotListener { public constructor() { super(TanzaniteEvent.UpdateModlog, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.UpdateModlog }); } diff --git a/src/listeners/member-custom/updateSettings.ts b/src/listeners/member-custom/updateSettings.ts index 329212a..2b6c8b0 100644 --- a/src/listeners/member-custom/updateSettings.ts +++ b/src/listeners/member-custom/updateSettings.ts @@ -1,10 +1,10 @@ -import { BotListener, colors, TanzaniteEvent, type BotClientEvents } from '#lib'; +import { BotListener, colors, Emitter, TanzaniteEvent, type BotClientEvents } from '#lib'; import { EmbedBuilder } from 'discord.js'; export default class UpdateSettingsListener extends BotListener { public constructor() { super(TanzaniteEvent.UpdateSettings, { - emitter: 'client', + emitter: Emitter.Client, event: TanzaniteEvent.UpdateSettings }); } diff --git a/src/listeners/message/_quoteEdit.ts b/src/listeners/message/_quoteEdit.ts new file mode 100644 index 0000000..24bf3c2 --- /dev/null +++ b/src/listeners/message/_quoteEdit.ts @@ -0,0 +1,17 @@ +// import { BotClientEvents, BotListener, Emitter } from '#lib'; +// import { Events } from 'discord.js'; + +// export default class QuoteEditListener extends BotListener { +// public constructor() { +// super('quoteEdit', { +// emitter: Emitter.Client, +// event: Events.MessageUpdate +// }); +// } + +// public async exec(...[_, newMessage]: BotClientEvents[Events.MessageUpdate]) { +// return; +// // if (newMessage.partial) newMessage = await newMessage.fetch(); +// // return new QuoteCreateListener().exec(newMessage); +// } +// } diff --git a/src/listeners/message/autoPublisher.ts b/src/listeners/message/autoPublisher.ts index 36dcbe2..36c448a 100644 --- a/src/listeners/message/autoPublisher.ts +++ b/src/listeners/message/autoPublisher.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; -import { ChannelType } from 'discord.js'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { ChannelType, Events } from 'discord.js'; export default class autoPublisherListener extends BotListener { public constructor() { super('autoPublisher', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']) { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { if (!message.guild || !(await message.guild.hasFeature('autoPublish'))) return; const autoPublishChannels = await message.guild.getSetting('autoPublishChannels'); if (autoPublishChannels) { diff --git a/src/listeners/message/blacklistedFile.ts b/src/listeners/message/blacklistedFile.ts index 31fbe9d..27cba5a 100644 --- a/src/listeners/message/blacklistedFile.ts +++ b/src/listeners/message/blacklistedFile.ts @@ -1,9 +1,9 @@ -// import { CustomListener, type CustomClientEvents } from '#lib'; +// import { BotListener, Emitter, type BotClientEvents } from '#lib'; // import * as crypto from 'crypto'; -// import { ChannelType } from 'discord.js'; +// import { ChannelType, Events } from 'discord.js'; // import got from 'got'; -// export default class BlacklistedFileListener extends CustomListener { +// export default class BlacklistedFileListener extends BotListener { // #blacklistedFiles: { hash: string[]; name: string; description: string }[] = [ // { // hash: ['a0f5e30426234bc9d09306ffc9474422'], @@ -59,12 +59,12 @@ // public constructor() { // super('blacklistedFile', { -// emitter: 'client', -// event: 'messageCreate', +// emitter: Emitter.Client, +// event: Events.MessageCreate // }); // } -// public async exec(...[message]: CustomClientEvents['messageCreate']) { +// public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { // if (!message.guild || !(await message.guild.hasFeature('blacklistedFile'))) return; // // const embedAttachments = message.embeds.filter((e) => ['image', 'video', 'gifv'].includes(e.type)); // const foundEmojis = [...message.content.matchAll(/<(?<animated>a?):\w+:(?<id>\d+)>/g)]; diff --git a/src/listeners/message/boosterMessage.ts b/src/listeners/message/boosterMessage.ts index 43fb04e..5e046e5 100644 --- a/src/listeners/message/boosterMessage.ts +++ b/src/listeners/message/boosterMessage.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; -import { MessageType } from 'discord.js'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { Events, MessageType } from 'discord.js'; export default class BoosterMessageListener extends BotListener { public constructor() { super('boosterMessage', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']) { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { if (!message.guild || !(await message.guild?.hasFeature('boosterMessageReact'))) return; if ( [MessageType.GuildBoost, MessageType.GuildBoostTier1, MessageType.GuildBoostTier2, MessageType.GuildBoostTier3].includes( diff --git a/src/listeners/message/directMessage.ts b/src/listeners/message/directMessage.ts index efa5bb6..aea0145 100644 --- a/src/listeners/message/directMessage.ts +++ b/src/listeners/message/directMessage.ts @@ -1,11 +1,11 @@ -import { BotListener, colors, type BotClientEvents } from '#lib'; -import { ChannelType, EmbedBuilder } from 'discord.js'; +import { BotListener, colors, Emitter, type BotClientEvents } from '#lib'; +import { ChannelType, EmbedBuilder, Events } from 'discord.js'; export default class DirectMessageListener extends BotListener { public constructor() { super('directMessage', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } diff --git a/src/listeners/message/highlight.ts b/src/listeners/message/highlight.ts index d5d8304..ae48b24 100644 --- a/src/listeners/message/highlight.ts +++ b/src/listeners/message/highlight.ts @@ -1,14 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class HighlightListener extends BotListener { public constructor() { super('highlight', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']) { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { if (!message.inGuild()) return; if (message.author.bot || message.system) return; if (!(await message.guild.hasFeature('highlight'))) return; // allows highlighting to be disabled on a guild-by-guild basis diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts index 5c314a8..a445d1e 100644 --- a/src/listeners/message/level.ts +++ b/src/listeners/message/level.ts @@ -1,16 +1,17 @@ -import { BotListener, Level, TanzaniteEvent, type BotCommandHandlerEvents } from '#lib'; +import { BotListener, CommandHandlerEvent, Emitter, Level, TanzaniteEvent, type BotCommandHandlerEvents } from '#lib'; import { MessageType } from 'discord.js'; export default class LevelListener extends BotListener { #levelCooldowns: Set<string> = new Set(); public constructor() { super('level', { - emitter: 'commandHandler', - event: 'messageInvalid' // Using messageInvalid here so commands don't give xp + emitter: Emitter.CommandHandler, + // Using messageInvalid here so commands don't give xp + event: CommandHandlerEvent.MessageInvalid }); } - public async exec(...[message]: BotCommandHandlerEvents['messageInvalid']) { + public async exec(...[message]: BotCommandHandlerEvents[CommandHandlerEvent.MessageInvalid]) { if (message.author.bot || !message.author || !message.inGuild()) return; if (!(await message.guild.hasFeature('leveling'))) return; if (this.#levelCooldowns.has(`${message.guildId}-${message.author.id}`)) return; diff --git a/src/listeners/message/quoteCreate.ts b/src/listeners/message/quoteCreate.ts index 9bad9b8..1c3130c 100644 --- a/src/listeners/message/quoteCreate.ts +++ b/src/listeners/message/quoteCreate.ts @@ -1,14 +1,15 @@ -import { BotListener, mappings, type BotClientEvents } from '#lib'; +import { BotListener, Emitter, mappings, type BotClientEvents } from '#lib'; +import { Events } from 'discord.js'; export default class QuoteCreateListener extends BotListener { public constructor() { super('quoteCreate', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public async exec(...[message]: BotClientEvents['messageCreate']) { + public async exec(...[message]: BotClientEvents[Events.MessageCreate]) { if (message.author.id !== mappings.users['IRONM00N'] || !this.client.config.isProduction) return; if (!message.inGuild()) return; diff --git a/src/listeners/message/quoteEdit.ts b/src/listeners/message/quoteEdit.ts deleted file mode 100644 index 8422026..0000000 --- a/src/listeners/message/quoteEdit.ts +++ /dev/null @@ -1,16 +0,0 @@ -// import { CustomListener, type CustomClientEvents } from '#lib'; - -// export default class QuoteEditListener extends CustomListener { -// public constructor() { -// super('quoteEdit', { -// emitter: 'client', -// event: 'messageUpdate', -// }); -// } - -// public async exec(...[_, newMessage]: CustomClientEvents['messageUpdate']) { -// return; -// // if (newMessage.partial) newMessage = await newMessage.fetch(); -// // return new QuoteCreateListener().exec(newMessage); -// } -// } diff --git a/src/listeners/message/verbose.ts b/src/listeners/message/verbose.ts index 9c4ac3a..74e6fbe 100644 --- a/src/listeners/message/verbose.ts +++ b/src/listeners/message/verbose.ts @@ -1,15 +1,15 @@ -import { BotListener, type BotClientEvents } from '#lib'; -import { ChannelType } from 'discord.js'; +import { BotListener, Emitter, type BotClientEvents } from '#lib'; +import { ChannelType, Events } from 'discord.js'; export default class MessageVerboseListener extends BotListener { public constructor() { super('messageVerbose', { - emitter: 'client', - event: 'messageCreate' + emitter: Emitter.Client, + event: Events.MessageCreate }); } - public exec(...[message]: BotClientEvents['messageCreate']): void { + public exec(...[message]: BotClientEvents[Events.MessageCreate]): void { if (this.client.customReady) { if (message.channel?.type === ChannelType.DM) return; void this.client.console.verbose( diff --git a/src/listeners/other/consoleListener.ts b/src/listeners/other/consoleListener.ts index dc6b66b..878b3ac 100644 --- a/src/listeners/other/consoleListener.ts +++ b/src/listeners/other/consoleListener.ts @@ -1,12 +1,12 @@ -// import { CustomListener } from '#lib'; +// import { BotListener, Emitter } from '#lib'; // import { exec } from 'child_process'; // import { promisify } from 'util'; // // eslint-disable-next-line @typescript-eslint/no-unused-vars -// /* export default */ class ConsoleListener extends CustomListener { +// /* export default */ class ConsoleListener extends BotListener { // public constructor() { // super('console', { -// emitter: 'stdin', +// emitter: Emitter.Stdin, // event: 'line' // }); // } diff --git a/src/listeners/other/exit.ts b/src/listeners/other/exit.ts index e1c8fee..63274e5 100644 --- a/src/listeners/other/exit.ts +++ b/src/listeners/other/exit.ts @@ -1,9 +1,9 @@ -import { BotListener } from '#lib'; +import { BotListener, Emitter } from '#lib'; export default class ExitListener extends BotListener { public constructor() { super('exit', { - emitter: 'process', + emitter: Emitter.Process, event: 'exit' }); } diff --git a/src/listeners/other/promiseRejection.ts b/src/listeners/other/promiseRejection.ts index 876e014..07779e0 100644 --- a/src/listeners/other/promiseRejection.ts +++ b/src/listeners/other/promiseRejection.ts @@ -1,11 +1,11 @@ -import { BotListener, formatError, generateErrorEmbed } from '#lib'; +import { BotListener, Emitter, formatError, generateErrorEmbed, ListenerType } from '#lib'; export default class PromiseRejectionListener extends BotListener { public constructor() { super('promiseRejection', { - emitter: 'process', + emitter: Emitter.Process, event: 'unhandledRejection', - type: 'prependListener' + type: ListenerType.PrependListener }); } diff --git a/src/listeners/other/uncaughtException.ts b/src/listeners/other/uncaughtException.ts index ab1c1b7..f44f0ce 100644 --- a/src/listeners/other/uncaughtException.ts +++ b/src/listeners/other/uncaughtException.ts @@ -1,11 +1,11 @@ -import { BotListener, formatError, generateErrorEmbed } from '#lib'; +import { BotListener, Emitter, formatError, generateErrorEmbed, ListenerType } from '#lib'; export default class UncaughtExceptionListener extends BotListener { public constructor() { super('uncaughtException', { - emitter: 'process', + emitter: Emitter.Process, event: 'uncaughtException', - type: 'prependListener' + type: ListenerType.PrependListener }); } diff --git a/src/listeners/other/warning.ts b/src/listeners/other/warning.ts index 7fdcd46..b18901d 100644 --- a/src/listeners/other/warning.ts +++ b/src/listeners/other/warning.ts @@ -1,9 +1,9 @@ -import { BotListener, colors, formatError, generateErrorEmbed } from '#lib'; +import { BotListener, colors, Emitter, formatError, generateErrorEmbed } from '#lib'; export default class WarningListener extends BotListener { public constructor() { super('warning', { - emitter: 'process', + emitter: Emitter.Process, event: 'warning' }); } diff --git a/src/listeners/rest/rateLimit.ts b/src/listeners/rest/rateLimit.ts index 46e5471..40900c7 100644 --- a/src/listeners/rest/rateLimit.ts +++ b/src/listeners/rest/rateLimit.ts @@ -1,15 +1,15 @@ -import { BotListener } from '#lib'; -import type { RestEvents } from '@discordjs/rest'; +import { BotListener, Emitter } from '#lib'; +import { RESTEvents, RestEvents } from '@discordjs/rest'; export default class RateLimitedListener extends BotListener { public constructor() { super('rateLimited', { - emitter: 'rest', - event: 'rateLimited' + emitter: Emitter.Rest, + event: RESTEvents.RateLimited }); } - public async exec(...[message]: RestEvents['rateLimited']): Promise<void> { + public async exec(...[message]: RestEvents[RESTEvents.RateLimited]): Promise<void> { void this.client.console.superVerboseRaw('rateLimited', message); } } diff --git a/src/listeners/track-manual-punishments/modlogSyncBan.ts b/src/listeners/track-manual-punishments/modlogSyncBan.ts index 5ecb8f3..83f6dd4 100644 --- a/src/listeners/track-manual-punishments/modlogSyncBan.ts +++ b/src/listeners/track-manual-punishments/modlogSyncBan.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; -import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { BotListener, colors, Emitter, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; +import { AuditLogEvent, EmbedBuilder, Events, PermissionFlagsBits } from 'discord.js'; export default class ModlogSyncBanListener extends BotListener { public constructor() { super('modlogSyncBan', { - emitter: 'client', - event: 'guildBanAdd' + emitter: Emitter.Client, + event: Events.GuildBanAdd }); } - public async exec(...[ban]: BotClientEvents['guildBanAdd']) { + public async exec(...[ban]: BotClientEvents[Events.GuildBanAdd]) { if (!(await ban.guild.hasFeature('logManualPunishments'))) return; if (!ban.guild.members.me) return; // bot was banned if (!ban.guild.members.me.permissions.has(PermissionFlagsBits.ViewAuditLog)) { diff --git a/src/listeners/track-manual-punishments/modlogSyncKick.ts b/src/listeners/track-manual-punishments/modlogSyncKick.ts index fc3fab9..e8b2433 100644 --- a/src/listeners/track-manual-punishments/modlogSyncKick.ts +++ b/src/listeners/track-manual-punishments/modlogSyncKick.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; -import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { BotListener, colors, Emitter, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; +import { AuditLogEvent, EmbedBuilder, Events, PermissionFlagsBits } from 'discord.js'; export default class ModlogSyncKickListener extends BotListener { public constructor() { super('modlogSyncKick', { - emitter: 'client', - event: 'guildMemberRemove' + emitter: Emitter.Client, + event: Events.GuildMemberRemove }); } - public async exec(...[member]: BotClientEvents['guildMemberRemove']) { + public async exec(...[member]: BotClientEvents[Events.GuildMemberRemove]) { if (!(await member.guild.hasFeature('logManualPunishments'))) return; if (!member.guild.members.me) return; // bot was removed from guild if (!member.guild.members.me.permissions.has(PermissionFlagsBits.ViewAuditLog)) { diff --git a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts index 6248654..2a4e0bb 100644 --- a/src/listeners/track-manual-punishments/modlogSyncTimeout.ts +++ b/src/listeners/track-manual-punishments/modlogSyncTimeout.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; -import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { BotListener, colors, Emitter, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; +import { AuditLogEvent, EmbedBuilder, Events, PermissionFlagsBits } from 'discord.js'; export default class ModlogSyncTimeoutListener extends BotListener { public constructor() { super('modlogSyncTimeout', { - emitter: 'client', - event: 'guildMemberUpdate' + emitter: Emitter.Client, + event: Events.GuildMemberUpdate }); } - public async exec(...[_oldMember, newMember]: BotClientEvents['guildMemberUpdate']) { + public async exec(...[_oldMember, newMember]: BotClientEvents[Events.GuildMemberUpdate]) { if (!(await newMember.guild.hasFeature('logManualPunishments'))) return; if (!newMember.guild.members.me!.permissions.has(PermissionFlagsBits.ViewAuditLog)) { return newMember.guild.error( diff --git a/src/listeners/track-manual-punishments/modlogSyncUnban.ts b/src/listeners/track-manual-punishments/modlogSyncUnban.ts index 96de018..4738066 100644 --- a/src/listeners/track-manual-punishments/modlogSyncUnban.ts +++ b/src/listeners/track-manual-punishments/modlogSyncUnban.ts @@ -1,15 +1,15 @@ -import { BotListener, colors, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; -import { AuditLogEvent, EmbedBuilder, PermissionFlagsBits } from 'discord.js'; +import { BotListener, colors, Emitter, humanizeDuration, Moderation, ModLogType, sleep, Time, type BotClientEvents } from '#lib'; +import { AuditLogEvent, EmbedBuilder, Events, PermissionFlagsBits } from 'discord.js'; export default class ModlogSyncUnbanListener extends BotListener { public constructor() { super('modlogSyncUnban', { - emitter: 'client', - event: 'guildBanRemove' + emitter: Emitter.Client, + event: Events.GuildBanRemove }); } - public async exec(...[ban]: BotClientEvents['guildBanRemove']) { + public async exec(...[ban]: BotClientEvents[Events.GuildBanRemove]) { if (!(await ban.guild.hasFeature('logManualPunishments'))) return; if (!ban.guild.members.me!.permissions.has(PermissionFlagsBits.ViewAuditLog)) { return ban.guild.error( diff --git a/src/listeners/ws/INTERACTION_CREATE.ts b/src/listeners/ws/INTERACTION_CREATE.ts index 250d8b5..d0327df 100644 --- a/src/listeners/ws/INTERACTION_CREATE.ts +++ b/src/listeners/ws/INTERACTION_CREATE.ts @@ -1,4 +1,4 @@ -import { BotListener, capitalize, colors, emojis, Moderation, PunishmentTypePresent } from '#lib'; +import { BotListener, capitalize, colors, Emitter, emojis, Moderation, PunishmentTypePresent } from '#lib'; import assert from 'assert/strict'; import { ActionRowBuilder, @@ -24,7 +24,7 @@ import { export default class WsInteractionCreateListener extends BotListener { public constructor() { super('wsInteractionCreate', { - emitter: 'ws', + emitter: Emitter.Ws, event: GatewayDispatchEvents.InteractionCreate }); } |