UNPKG

n1cat-discord-script-manager

Version:

A Discord.js plugin for dynamic script management and execution

246 lines (220 loc) 6.2 kB
/** * MessageHandler - 安全的消息處理工具 * 專注於提供簡潔的 API,同時確保盡可能使用 Discord.js 原生方法 */ const { EmbedBuilder } = require("discord.js"); const Logger = require("../utils/logger"); // 用於追蹤函式調用的輔助函數 function getCallerInfo() { const stack = new Error().stack; const callerLine = stack.split("\n")[3]; // 跳過 Error 和 getCallerInfo 的堆疊 const match = callerLine.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/); if (match) { const [, functionName, file, line, column] = match; return { function: functionName, file: file.split("/").pop(), // 只取檔案名稱 line, column, }; } return { function: "unknown", file: "unknown", line: "unknown", column: "unknown", }; } // 日誌輸出函數 function log(message, isError = false) { const caller = getCallerInfo(); const debugMode = this.options?.debug ?? false; // 如果是錯誤或 debug 模式開啟,則輸出詳細日誌 if (isError || debugMode) { console.log(`[${caller.file}:${caller.line}] ${message}`); } } class MessageHandler { /** * 創建一個新的消息處理器 * @param {Message} message - Discord.js 原始消息對象 * @param {Object} [options] - 配置選項 * @param {number} [options.timeout=5000] - 操作超時時間(毫秒) * @param {number} [options.maxRetries=3] - 最大重試次數 * @param {number} [options.cacheSize=100] - 消息緩存大小 */ constructor(message, options = {}) { // 驗證必要參數 if (!message) { throw new Error("Message is required"); } // 設置默認選項 this.options = { timeout: options.timeout || 5000, maxRetries: options.maxRetries || 3, cacheSize: options.cacheSize || 100, debug: options.debug || false, }; // 創建上下文日誌器 this.logger = Logger.createContextLogger({ module: "MessageHandler", debug: this.options.debug, }); // 初始化屬性 this.message = message; this.content = message.content; this.author = message.author; this.channel = message.channel; this.guild = message.guild; this._cache = new Map(); } /** * 獲取消息的內容 */ get content() { return this.message.content; } /** * 獲取發送消息的用戶 */ get author() { return this.message.author; } /** * 分割消息內容 * @param {string} separator - 分隔符,默認為空格 * @returns {string[]} 分割後的片段 */ split(separator = " ") { return this.message.content.split(separator); } /** * 檢查消息內容是否包含指定文字 * @param {string} text - 要檢查的文字 */ includes(text) { return this.message.content.includes(text); } /** * 檢查消息內容是否以指定文字開頭 * @param {string} text - 要檢查的文字 */ startsWith(text) { return this.message.content.startsWith(text); } /** * 回覆消息 * @param {string|Object} content - 回覆內容 * @param {boolean} [mentionUser=true] - 是否提及用戶 * @returns {Promise<Message>} 回覆的消息 */ async reply(content, mentionUser = true) { try { return await this.message.reply({ content: typeof content === "string" ? content : content.content, allowedMentions: { users: mentionUser ? [this.author.id] : [] }, }); } catch (error) { if (this.options.debug) { this.logger.error("Failed to reply to message", { showStack: true }); } throw error; } } /** * 發送消息 * @param {string|Object} content - 消息內容 * @returns {Promise<Message>} 發送的消息 */ async send(content) { try { return await this.channel.send(content); } catch (error) { if (this.options.debug) { this.logger.error("Failed to send message", { showStack: true }); } throw error; } } /** * 發送嵌入消息 * @param {Object} embed - 嵌入消息配置 * @returns {Promise<Message>} 發送的消息 */ async sendEmbed(embed) { try { return await this.channel.send({ embeds: [embed] }); } catch (error) { if (this.options.debug) { this.logger.error("Failed to send embed", { showStack: true }); } throw error; } } /** * 編輯消息 * @param {string|Object} content - 新的消息內容 * @returns {Promise<Message>} 編輯後的消息 */ async edit(content) { try { this.logger.debug(`編輯消息: ${JSON.stringify(content)}`); return await this.message.edit(content); } catch (error) { this.logger.error(`編輯消息失敗: ${error.message}`, { showStack: true }); throw error; } } /** * 刪除消息 * @param {number} [timeout] - 延遲刪除時間(毫秒) * @returns {Promise<void>} */ async delete(timeout) { try { if (timeout) { this.logger.debug(`延遲 ${timeout}ms 刪除消息`); await new Promise((resolve) => setTimeout(resolve, timeout)); } await this.message.delete(); this.logger.debug("消息已成功刪除"); } catch (error) { this.logger.error(`刪除消息失敗: ${error.message}`, { showStack: true }); throw error; } } /** * 獲取原始 Discord.js 消息對象 */ getRawMessage() { return this.message; } /** * 將處理器轉換為字符串 */ toString() { return this.message.content; } /** * 緩存消息 * @private */ _cacheMessage(message) { if (!message) return; // 如果緩存已滿,刪除最舊的消息 if (this._cache.size >= this.options.cacheSize) { const oldestKey = this._cache.keys().next().value; this._cache.delete(oldestKey); } this._cache.set(message.id, message); } /** * 獲取緩存的消息 * @param {string} messageId - 消息ID * @returns {Message|null} 緩存的消息對象 */ getCachedMessage(messageId) { return this._cache.get(messageId) || null; } } module.exports = MessageHandler;