first commit
This commit is contained in:
101
utils/errorHandler.js
Normal file
101
utils/errorHandler.js
Normal file
@@ -0,0 +1,101 @@
|
||||
const { EmbedBuilder } = require('discord.js');
|
||||
require('dotenv').config();
|
||||
const logger = require('../../modules/colorfulLogger');
|
||||
|
||||
const logErrorToConsole = (error, context) => {
|
||||
console.error(`\n\x1b[31m[${new Date().toISOString()}] \x1b[33m[${context || 'ERROR'}]\x1b[0m`);
|
||||
console.error(error);
|
||||
};
|
||||
|
||||
const sendErrorToDiscord = async (error, client, contextInfo) => {
|
||||
try {
|
||||
const errorLogChannelId = process.env.ERROR_LOG_CHANNEL_ID;
|
||||
if (!errorLogChannelId || !client?.channels) return;
|
||||
|
||||
const errorEmbed = new EmbedBuilder()
|
||||
.setColor(0xFF0000)
|
||||
.setTitle('오류 발생')
|
||||
.setTimestamp();
|
||||
|
||||
if (typeof contextInfo === 'string') {
|
||||
errorEmbed.addFields({ name: '오류 발생 위치', value: contextInfo });
|
||||
} else if (contextInfo?.isInteraction) {
|
||||
const interaction = contextInfo;
|
||||
errorEmbed.setTitle('명령어 인터랙션 오류');
|
||||
errorEmbed.addFields(
|
||||
{ name: '명령어', value: `\`/${interaction.commandName}\``, inline: true },
|
||||
{ name: '사용자', value: `${interaction.user.tag} (\`${interaction.user.id}\`)`, inline: true },
|
||||
{ name: '서버/채널', value: `${interaction.guild.name} / #${interaction.channel.name}`, inline: false }
|
||||
);
|
||||
} else if (contextInfo?.author) {
|
||||
const message = contextInfo;
|
||||
errorEmbed.setTitle('메시지 처리 오류');
|
||||
errorEmbed.addFields(
|
||||
{ name: '메시지 내용', value: message.content.substring(0, 200) },
|
||||
{ name: '사용자', value: `${message.author.tag} (\`${message.author.id}\`)`, inline: true },
|
||||
{ name: '서버/채널', value: `${message.guild.name} / #${message.channel.name}`, inline: true }
|
||||
);
|
||||
}
|
||||
|
||||
errorEmbed.addFields(
|
||||
{ name: '오류 메시지', value: `\`\`\`${error.message}\`\`\`` },
|
||||
{ name: 'Stack Trace', value: `\`\`\`javascript\n${error.stack.substring(0, 1000)}\`\`\`` }
|
||||
);
|
||||
|
||||
const channel = await client.channels.fetch(errorLogChannelId).catch(() => null);
|
||||
if (channel?.isTextBased()) {
|
||||
await channel.send({ embeds: [errorEmbed] });
|
||||
}
|
||||
} catch (discordError) {
|
||||
console.error('\n\x1b[1m\x1b[31m[FATAL] Discord로 오류 로그 전송에 실패했습니다.\x1b[0m');
|
||||
logErrorToConsole(discordError, 'DISCORD LOG SEND FAILED');
|
||||
logErrorToConsole(error, 'ORIGINAL ERROR');
|
||||
}
|
||||
};
|
||||
|
||||
const handleCommandError = async (error, context, client) => {
|
||||
logErrorToConsole(error, context?.commandName || context?.content || 'Command Execution');
|
||||
await sendErrorToDiscord(error, client, context);
|
||||
|
||||
if (context?.isInteraction) {
|
||||
const interaction = context;
|
||||
const reply = {
|
||||
content: '명령어를 실행하는 중 오류가 발생했습니다.',
|
||||
embeds: [],
|
||||
ephemeral: true,
|
||||
};
|
||||
try {
|
||||
if (interaction.replied || interaction.deferred) {
|
||||
await interaction.followUp(reply);
|
||||
} else {
|
||||
await interaction.reply(reply);
|
||||
}
|
||||
} catch (replyError) {
|
||||
logErrorToConsole(replyError, 'COMMAND ERROR REPLY FAILED');
|
||||
}
|
||||
} else if (context?.channel) {
|
||||
try {
|
||||
await context.channel.send({ content: '명령어를 처리하는 중 오류가 발생했습니다.' });
|
||||
} catch (replyError) {
|
||||
logErrorToConsole(replyError, 'COMMAND ERROR REPLY FAILED');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFatalError = async (error, context, client, shutdownLogic) => {
|
||||
logErrorToConsole(error, context);
|
||||
await sendErrorToDiscord(error, client, context);
|
||||
|
||||
if (typeof shutdownLogic === 'function') {
|
||||
logger.error('Fatal error detected. Performing shutdown logic before exit...');
|
||||
await shutdownLogic();
|
||||
}
|
||||
|
||||
logger.error('치명적인 오류로 인해 프로세스를 종료합니다.');
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
handleCommandError,
|
||||
handleFatalError,
|
||||
};
|
Reference in New Issue
Block a user