aboutsummaryrefslogtreecommitdiff
path: root/src/listeners
diff options
context:
space:
mode:
Diffstat (limited to 'src/listeners')
-rw-r--r--src/listeners/commands/commandBlocked.ts15
-rw-r--r--src/listeners/commands/commandError.ts11
-rw-r--r--src/listeners/commands/commandStarted.ts8
-rw-r--r--src/listeners/commands/messageBlocked.ts3
-rw-r--r--src/listeners/contextCommands/contextCommandBlocked.ts41
-rw-r--r--src/listeners/contextCommands/contextCommandError.ts123
-rw-r--r--src/listeners/contextCommands/contextCommandNotFound.ts16
-rw-r--r--src/listeners/contextCommands/contextCommandStarted.ts27
8 files changed, 227 insertions, 17 deletions
diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts
index 5724d33..0d3c1d9 100644
--- a/src/listeners/commands/commandBlocked.ts
+++ b/src/listeners/commands/commandBlocked.ts
@@ -5,7 +5,8 @@ export default class CommandBlockedListener extends BushListener {
public constructor() {
super('commandBlocked', {
emitter: 'commandHandler',
- event: 'commandBlocked'
+ event: 'commandBlocked',
+ category: 'commands'
});
}
@@ -32,26 +33,26 @@ export default class CommandBlockedListener extends BushListener {
switch (reason) {
case reasons.OWNER: {
return await respond({
- content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.toString())} command.`,
+ content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.id)} command.`,
ephemeral: true
});
}
case reasons.SUPER_USER: {
return await respond({
- content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.toString())} command.`,
+ content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.id)} command.`,
ephemeral: true
});
}
case reasons.DISABLED_GLOBAL: {
return await respond({
- content: `${util.emojis.error} My developers disabled the ${util.format.input(command!.toString())} command.`,
+ content: `${util.emojis.error} My developers disabled the ${util.format.input(command!.id)} command.`,
ephemeral: true
});
}
case reasons.DISABLED_GUILD: {
return await respond({
content: `${util.emojis.error} The ${util.format.input(
- command!.toString()
+ command!.id
)} command is currently disabled in ${util.format.input(message.guild!.name)}.`,
ephemeral: true
});
@@ -89,7 +90,7 @@ export default class CommandBlockedListener extends BushListener {
});
const pretty = util.oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.input(command!.toString())} can only be run in ${pretty}.`,
+ content: `${util.emojis.error} ${util.format.input(command!.id)} can only be run in ${pretty}.`,
ephemeral: true
});
}
@@ -99,7 +100,7 @@ export default class CommandBlockedListener extends BushListener {
const names = guilds!.map((g) => util.format.input(client.guilds.cache.get(g)?.name ?? g));
const pretty = util.oxford(names, 'and');
return await respond({
- content: `${util.emojis.error} ${util.format.input(command!.toString())} can only be run in ${pretty}.`,
+ content: `${util.emojis.error} ${util.format.input(command!.id)} can only be run in ${pretty}.`,
ephemeral: true
});
}
diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts
index e1acb00..d590e06 100644
--- a/src/listeners/commands/commandError.ts
+++ b/src/listeners/commands/commandError.ts
@@ -8,7 +8,8 @@ export default class CommandErrorListener extends BushListener {
public constructor() {
super('commandError', {
emitter: 'commandHandler',
- event: 'error'
+ event: 'error',
+ category: 'commands'
});
}
@@ -33,10 +34,10 @@ export default class CommandErrorListener extends BushListener {
'message.id': message.id,
'message.type': message.util.isSlash ? 'slash' : 'normal',
'message.parsed.content': message.util.parsed?.content,
- 'channel.id': (message.channel?.isDM() ? message.channel.recipient?.id : message.channel?.id) ?? '¯_(ツ)_/¯',
+ 'channel.id': (message.channel?.isDM() ? message.channel.recipient?.id : message.channel?.id) ?? '¯\\_(ツ)_/¯',
'channel.name': channel,
- 'guild.id': message.guild?.id ?? '¯_(ツ)_/¯',
- 'guild.name': message.guild?.name ?? '¯_(ツ)_/¯',
+ 'guild.id': message.guild?.id ?? '¯\\_(ツ)_/¯',
+ 'guild.name': message.guild?.name ?? '¯\\_(ツ)_/¯',
'environment': client.config.environment
}
});
@@ -232,7 +233,7 @@ export default class CommandErrorListener extends BushListener {
}
}
-class IFuckedUpError extends Error {
+export class IFuckedUpError extends Error {
public declare original: Error | any;
public declare newError: Error | any;
diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts
index 4d2f0ad..63b906b 100644
--- a/src/listeners/commands/commandStarted.ts
+++ b/src/listeners/commands/commandStarted.ts
@@ -21,11 +21,11 @@ export default class CommandStartedListener extends BushListener {
'message.id': message.id,
'message.type': message.util.isSlash ? 'slash' : 'normal',
'message.parsed.content': message.util.parsed?.content,
- 'channel.id': (message.channel.isDMBased() ? message.channel.recipient?.id : message.channel?.id) ?? '¯_(ツ)_/¯',
+ 'channel.id': (message.channel.isDMBased() ? message.channel.recipient?.id : message.channel?.id) ?? '¯\\_(ツ)_/¯',
'channel.name':
- (message.channel.isDMBased() ? message.channel.recipient?.tag : (<any>message.channel)?.name) ?? '¯_(ツ)_/¯',
- 'guild.id': message.guild?.id ?? '¯_(ツ)_/¯',
- 'guild.name': message.guild?.name ?? '¯_(ツ)_/¯',
+ (message.channel.isDMBased() ? message.channel.recipient?.tag : (<any>message.channel)?.name) ?? '¯\\_(ツ)_/¯',
+ 'guild.id': message.guild?.id ?? '¯\\_(ツ)_/¯',
+ 'guild.name': message.guild?.name ?? '¯\\_(ツ)_/¯',
'environment': client.config.environment
}
});
diff --git a/src/listeners/commands/messageBlocked.ts b/src/listeners/commands/messageBlocked.ts
index 1b969ed..5a2b10d 100644
--- a/src/listeners/commands/messageBlocked.ts
+++ b/src/listeners/commands/messageBlocked.ts
@@ -4,7 +4,8 @@ export default class MessageBlockedListener extends BushListener {
public constructor() {
super('messageBlocked', {
emitter: 'commandHandler',
- event: 'messageBlocked'
+ event: 'messageBlocked',
+ category: 'commands'
});
}
diff --git a/src/listeners/contextCommands/contextCommandBlocked.ts b/src/listeners/contextCommands/contextCommandBlocked.ts
new file mode 100644
index 0000000..7fe381e
--- /dev/null
+++ b/src/listeners/contextCommands/contextCommandBlocked.ts
@@ -0,0 +1,41 @@
+import { BushListener } from '#lib';
+import { ContextMenuCommandHandlerEvents } from 'discord-akairo';
+
+export default class ContextCommandBlockedListener extends BushListener {
+ public constructor() {
+ super('contextCommandBlocked', {
+ emitter: 'contextMenuCommandHandler',
+ event: 'blocked',
+ category: 'contextCommands'
+ });
+ }
+
+ public override async exec(...[interaction, command, reason]: ContextMenuCommandHandlerEvents['blocked']) {
+ void client.console.info(
+ `ContextCommandBlocked`,
+ `<<${interaction.user.tag}>> tried to run <<${command}>> but was blocked because <<${reason}>>.`,
+ true
+ );
+
+ switch (reason) {
+ case client.consts.BlockedReasons.OWNER: {
+ return await interaction.reply({
+ content: `${util.emojis.error} Only my developers can run the ${util.format.input(command!.id)} command.`,
+ ephemeral: true
+ });
+ }
+ case client.consts.BlockedReasons.SUPER_USER: {
+ return await interaction.reply({
+ content: `${util.emojis.error} You must be a superuser to run the ${util.format.input(command!.id)} command.`,
+ ephemeral: true
+ });
+ }
+ default: {
+ return await interaction.reply({
+ content: `${util.emojis.error} Command blocked with reason ${util.format.input(reason ?? 'unknown')}.`,
+ ephemeral: true
+ });
+ }
+ }
+ }
+}
diff --git a/src/listeners/contextCommands/contextCommandError.ts b/src/listeners/contextCommands/contextCommandError.ts
new file mode 100644
index 0000000..04a97ad
--- /dev/null
+++ b/src/listeners/contextCommands/contextCommandError.ts
@@ -0,0 +1,123 @@
+import { Severity } from '@sentry/types';
+import { ContextMenuCommand, ContextMenuCommandHandlerEvents } from 'discord-akairo';
+import { ContextMenuCommandInteraction, EmbedBuilder, GuildTextBasedChannel } from 'discord.js';
+import { BushListener } from '../../lib/extensions/discord-akairo/BushListener.js';
+import CommandErrorListener, { IFuckedUpError } from '../commands/commandError.js';
+
+export default class ContextCommandErrorListener extends BushListener {
+ public constructor() {
+ super('contextCommandError', {
+ emitter: 'contextMenuCommandHandler',
+ event: 'error',
+ category: 'contextCommands'
+ });
+ }
+
+ public override exec(...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) {
+ return ContextCommandErrorListener.handleError(error, interaction, command);
+ }
+
+ public static async handleError(...[error, interaction, command]: ContextMenuCommandHandlerEvents['error']) {
+ try {
+ const errorNum = Math.floor(Math.random() * 6969696969) + 69; // hehe funny number
+ const channel = interaction.channel?.isDM()
+ ? interaction.channel.recipient?.tag
+ : (<GuildTextBasedChannel>interaction.channel)?.name;
+
+ client.sentry.captureException(error, {
+ level: Severity.Error,
+ user: { id: interaction.user.id, username: interaction.user.tag },
+ extra: {
+ 'command.name': command?.id,
+ 'message.id': interaction.id,
+ 'message.type': 'context command',
+ 'channel.id':
+ (interaction.channel?.isDM() ? interaction.channel.recipient?.id : interaction.channel?.id) ?? '¯\\_(ツ)_/¯',
+ 'channel.name': channel,
+ 'guild.id': interaction.guild?.id ?? '¯\\_(ツ)_/¯',
+ 'guild.name': interaction.guild?.name ?? '¯\\_(ツ)_/¯',
+ 'environment': client.config.environment
+ }
+ });
+
+ void client.console.error(
+ `contextCommandError`,
+ `an error occurred with the <<${command}>> context command in <<${channel}>> triggered by <<${
+ interaction?.user?.tag
+ }>>:\n${error?.stack ?? <any>error}`,
+ false
+ );
+
+ const _haste = CommandErrorListener.getErrorHaste(error);
+ const _stack = CommandErrorListener.getErrorStack(error);
+ const [haste, stack] = await Promise.all([_haste, _stack]);
+ const options = { interaction, error, errorNum, command, channel, haste, stack };
+
+ const errorEmbed = this._generateErrorEmbed({
+ ...options,
+ type: 'command-log'
+ });
+
+ void client.logger.channelError({ embeds: [errorEmbed] });
+
+ if (interaction) {
+ if (!client.config.owners.includes(interaction.user.id)) {
+ const errorUserEmbed = this._generateErrorEmbed({
+ ...options,
+ type: 'command-user'
+ });
+ void interaction?.reply({ embeds: [errorUserEmbed] }).catch(() => null);
+ } else {
+ const errorDevEmbed = this._generateErrorEmbed({
+ ...options,
+ type: 'command-dev'
+ });
+
+ void interaction?.reply({ embeds: [errorDevEmbed] }).catch(() => null);
+ }
+ }
+ } catch (e) {
+ throw new IFuckedUpError('An error occurred while handling a command error.', error, e);
+ }
+ }
+
+ private static _generateErrorEmbed(options: {
+ interaction: ContextMenuCommandInteraction;
+ error: Error | any;
+ type: 'command-log' | 'command-dev' | 'command-user';
+ errorNum: number;
+ command?: ContextMenuCommand;
+ channel?: string;
+ haste: string[];
+ stack: string;
+ }): EmbedBuilder {
+ const embed = new EmbedBuilder().setColor(util.colors.error).setTimestamp();
+ if (options.type === 'command-user') {
+ return embed
+ .setTitle('An Error Occurred')
+ .setDescription(
+ `Oh no! ${
+ options.command ? `While running the command ${util.format.input(options.command.id)}, a` : 'A'
+ }n error occurred. Please give the developers code ${util.format.input(`${options.errorNum}`)}.`
+ );
+ }
+ const description = new Array<string>();
+
+ if (options.type === 'command-log') {
+ description.push(
+ `**User:** ${options.interaction.user} (${options.interaction.user.tag})`,
+ `**Command:** ${options.command ?? 'N/A'}`,
+ `**Channel:** <#${options.interaction.channel?.id}> (${options.channel})`
+ );
+ }
+
+ description.push(...options.haste);
+
+ embed.addFields([{ name: 'Stack Trace', value: options.stack.substring(0, 1024) }]);
+ if (description.length) embed.setDescription(description.join('\n').substring(0, 4000));
+
+ if (options.type === 'command-dev' || options.type === 'command-log')
+ embed.setTitle(`ContextCommandError #${util.format.input(`${options.errorNum}`)}`);
+ return embed;
+ }
+}
diff --git a/src/listeners/contextCommands/contextCommandNotFound.ts b/src/listeners/contextCommands/contextCommandNotFound.ts
new file mode 100644
index 0000000..b0a8f62
--- /dev/null
+++ b/src/listeners/contextCommands/contextCommandNotFound.ts
@@ -0,0 +1,16 @@
+import { BushListener } from '#lib';
+import { ContextMenuCommandHandlerEvents } from 'discord-akairo';
+
+export default class ContextCommandNotFoundListener extends BushListener {
+ public constructor() {
+ super('contextCommandNotFound', {
+ emitter: 'contextMenuCommandHandler',
+ event: 'notFound',
+ category: 'contextCommands'
+ });
+ }
+
+ public override async exec(...[interaction]: ContextMenuCommandHandlerEvents['notFound']) {
+ void client.console.info('contextCommandNotFound', `<<${interaction?.commandName}>> could not be found.`);
+ }
+}
diff --git a/src/listeners/contextCommands/contextCommandStarted.ts b/src/listeners/contextCommands/contextCommandStarted.ts
new file mode 100644
index 0000000..91eceaa
--- /dev/null
+++ b/src/listeners/contextCommands/contextCommandStarted.ts
@@ -0,0 +1,27 @@
+import { BushListener } from '#lib';
+import { ContextMenuCommandHandlerEvents } from 'discord-akairo';
+import { ChannelType } from 'discord.js';
+
+export default class ContextCommandStartedListener extends BushListener {
+ public constructor() {
+ super('contextCommandStarted', {
+ emitter: 'contextMenuCommandHandler',
+ event: 'started',
+ category: 'contextCommands'
+ });
+ }
+
+ public override async exec(...[interaction, command]: ContextMenuCommandHandlerEvents['started']) {
+ return void client.logger.info(
+ 'contextCommandStarted',
+ `The <<${command.id}>> command was used by <<${interaction.user.tag}>> in ${
+ interaction.channel
+ ? interaction.channel.type === ChannelType.DM
+ ? `their <<DMs>>`
+ : `<<#${interaction.channel.name}>> in <<${interaction.guild?.name}>>`
+ : 'unknown'
+ }.`,
+ true
+ );
+ }
+}