n1cat-discord-script-manager
Version:
A Discord.js plugin for dynamic script management and execution
216 lines (197 loc) • 7 kB
JavaScript
const { SlashCommandBuilder, PermissionFlagsBits } = require("discord.js");
const fs = require("fs");
const path = require("path");
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 scriptManager = global.client?.scriptManager;
const debugMode = scriptManager?.options?.debug ?? false;
// 如果是錯誤或 debug 模式開啟,則輸出詳細日誌
if (isError || debugMode) {
console.log(`[${caller.file}:${caller.line}] ${message}`);
}
}
module.exports = {
data: new SlashCommandBuilder()
.setName("managescript")
.setDescription("管理腳本(啟用/停用)")
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
.addStringOption((option) =>
option
.setName("script")
.setDescription("要管理的腳本名稱")
.setRequired(true)
.setAutocomplete(true)
)
.addStringOption((option) =>
option
.setName("action")
.setDescription("要執行的動作")
.setRequired(true)
.addChoices(
{ name: "啟用", value: "enable" },
{ name: "停用", value: "disable" }
)
),
async autocomplete(interaction) {
const logger = Logger.createContextLogger({
module: "ManageScript",
debug: interaction.client.config?.debug || false,
});
try {
logger.log("開始處理自動完成請求");
const scriptManager = interaction.client.scriptManager;
if (!scriptManager) {
logger.error("找不到腳本管理器");
return await interaction.respond([]);
}
const focusedValue = interaction.options.getFocused().toLowerCase();
logger.log(`搜尋腳本: ${focusedValue}`);
// 獲取所有腳本並轉換為選項
const scripts = Array.from(scriptManager.scripts.entries())
.map(([name, script]) => ({
name: `${name} (${script.enabled === false ? "已停用" : "啟用中"})`,
value: name,
}))
.filter(
(script) =>
script.value.toLowerCase().includes(focusedValue) ||
script.name.toLowerCase().includes(focusedValue)
);
logger.log(`找到的腳本: ${scripts.map((s) => s.value).join(", ")}`);
await interaction.respond(scripts.slice(0, 25));
logger.log("自動完成請求處理完成");
} catch (error) {
logger.error(`自動完成時出錯: ${error.message}`, { showStack: true });
console.error("詳細錯誤信息:", {
error: error.message,
code: error.code,
interactionId: interaction.id,
interactionState: {
replied: interaction.replied,
deferred: interaction.deferred,
},
timestamp: new Date().toISOString(),
});
try {
await interaction.respond([]);
logger.log("已發送空的自動完成回應");
} catch (e) {
logger.error(`回應自動完成時出錯: ${e.message}`, { showStack: true });
console.error("發送自動完成回應時的詳細錯誤:", {
error: e.message,
code: e.code,
interactionId: interaction.id,
interactionState: {
replied: interaction.replied,
deferred: interaction.deferred,
},
timestamp: new Date().toISOString(),
});
}
}
},
async execute(interaction) {
const logger = Logger.createContextLogger({
module: "ManageScript",
debug: interaction.client.config?.debug || false,
});
logger.log("開始執行 managescript 命令");
try {
// 先延遲回應,避免互動超時
await interaction.deferReply({ ephemeral: true });
logger.log("已延遲回應 managescript 命令");
const scriptManager = interaction.client.scriptManager;
if (!scriptManager) {
logger.error("找不到腳本管理器");
return await interaction.editReply({
content: "❌ 找不到腳本管理器",
});
}
const scriptName = interaction.options.getString("script");
const action = interaction.options.getString("action");
logger.log(
`準備${action === "enable" ? "啟用" : "停用"}腳本: ${scriptName}`
);
const script = scriptManager.scripts.get(scriptName);
if (!script) {
logger.error(`找不到腳本: ${scriptName}`);
return await interaction.editReply({
content: `❌ 找不到腳本:${scriptName}`,
});
}
// 更新腳本狀態
script.enabled = action === "enable";
scriptManager.scripts.set(scriptName, script);
logger.log(
`已${action === "enable" ? "啟用" : "停用"}腳本: ${scriptName}`
);
await interaction.editReply({
content: `✅ 已${
action === "enable" ? "啟用" : "停用"
}腳本:${scriptName}`,
});
logger.log("命令執行完成");
} catch (error) {
logger.error(`管理腳本時出錯: ${error.message}`, { showStack: true });
console.error("詳細錯誤信息:", {
error: error.message,
code: error.code,
interactionId: interaction.id,
interactionState: {
replied: interaction.replied,
deferred: interaction.deferred,
},
timestamp: new Date().toISOString(),
});
// 只在還沒有回應時才發送錯誤消息
if (!interaction.replied && !interaction.deferred) {
try {
await interaction.reply({
content: `❌ 執行命令時發生錯誤:${error.message}`,
ephemeral: true,
});
logger.log("已發送錯誤回應");
} catch (replyError) {
logger.error(`發送錯誤回應時出錯: ${replyError.message}`, {
showStack: true,
});
console.error("發送錯誤回應時的詳細錯誤:", {
error: replyError.message,
code: replyError.code,
interactionId: interaction.id,
interactionState: {
replied: interaction.replied,
deferred: interaction.deferred,
},
timestamp: new Date().toISOString(),
});
}
} else {
logger.log("互動已經被回應,跳過錯誤回應");
}
}
},
};