1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
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: Emitter.ContextMenuCommandHandler,
event: ContextCommandHandlerEvent.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[ContextCommandHandlerEvent.Error]
) {
try {
const errorNum = Math.floor(Math.random() * 6969696969) + 69; // hehe funny number
const channel =
interaction.channel?.type === ChannelType.DM
? interaction.channel.recipient?.tag
: (<GuildTextBasedChannel>interaction.channel)?.name;
client.sentry.captureException(error, {
level: '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?.type === ChannelType.DM ? 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${formatError(error, true)}`,
false
);
const _haste = getErrorHaste(client, error);
const _stack = getErrorStack(client, 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 embeds = [new EmbedBuilder().setColor(colors.error)];
if (options.type === 'command-user') {
embeds[0]
.setTitle('An Error Occurred')
.setDescription(
`Oh no! ${
options.command ? `While running the command ${format.input(options.command.id)}, a` : 'A'
}n error occurred. Please give the developers code ${format.input(`${options.errorNum}`)}.`
)
.setTimestamp();
return embeds;
}
const description: 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);
embeds.push(new EmbedBuilder().setColor(colors.error).setTimestamp().setDescription(options.stack.substring(0, 4000)));
if (description.length) embeds[0].setDescription(description.join('\n').substring(0, 4000));
if (options.type === 'command-dev' || options.type === 'command-log')
embeds[0].setTitle(`ContextCommandError #${format.input(`${options.errorNum}`)}`);
return embeds;
}
}
|