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, };