n1cat-discord-script-manager
Version:
A Discord.js plugin for dynamic script management and execution
246 lines (220 loc) • 6.2 kB
JavaScript
/**
* 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;