UNPKG

n1cat-discord-script-manager

Version:

A Discord.js plugin for dynamic script management and execution

244 lines (216 loc) 7.75 kB
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, } = require("discord.js"); const fs = require("fs"); const Logger = require("../utils/logger"); module.exports = { data: new SlashCommandBuilder() .setName("previewscript") .setDescription("預覽腳本詳細信息") .setDefaultMemberPermissions(PermissionFlagsBits.Administrator) .addStringOption((option) => option .setName("scriptname") .setDescription("要預覽的腳本名稱") .setRequired(true) .setAutocomplete(true) ), async execute(interaction) { const logger = Logger.createContextLogger({ module: "PreviewScript", debug: interaction.client.config?.debug || false, }); try { const scriptName = interaction.options.getString("scriptname"); const scriptManager = interaction.client.scriptManager; if (!scriptManager) { return interaction.reply({ content: "❌ 找不到腳本管理器", ephemeral: true, }); } const script = scriptManager.scripts.get(scriptName); if (!script) { return interaction.reply({ content: `❌ 找不到腳本:${scriptName}`, ephemeral: true, }); } // 讀取腳本文件內容 let scriptContent = ""; try { scriptContent = fs.readFileSync(script.path, "utf8"); } catch (error) { logger.error(`讀取腳本文件失敗: ${error.message}`); return interaction.reply({ content: `❌ 無法讀取腳本文件:${error.message}`, ephemeral: true, }); } // 從腳本頭部註釋中提取元數據 const headerMatch = scriptContent.match(/\/\*\n([\s\S]*?)\*\//); const headerComment = headerMatch ? headerMatch[1].trim() : ""; // 解析頭部註釋中的元數據 const metadataFallback = { originalFileName: "未知", author: "未知", createdAt: "未知", description: "暫無描述", attachmentUrl: null, }; // 從頭部註釋中提取元數據 const extractMetadata = (comment) => { const metadata = { ...metadataFallback }; // 嘗試解析原始腳本名稱(支持新舊兩種格式) const originalFileNameMatch = comment.match(/原始腳本名稱:\s*(.+)/) || comment.match(/原始檔案:\s*(.+)/); if (originalFileNameMatch) metadata.originalFileName = originalFileNameMatch[1].trim(); const authorMatch = comment.match(/由\s*(.+?)\s*在/); if (authorMatch) metadata.author = authorMatch[1].trim(); const createdAtMatch = comment.match( /在\s*(\d{4}\/\d{2}\/\d{2}\s*\d{2}:\d{2}:\d{2})\s*\(UTC\)/ ); if (createdAtMatch) metadata.createdAt = createdAtMatch[1].trim(); const descriptionMatch = comment.match(/腳本描述:\s*(.+)/); if (descriptionMatch) metadata.description = descriptionMatch[1].trim(); const attachmentUrlMatch = comment.match(/原始附件鏈接:\s*(.+)/); if (attachmentUrlMatch && attachmentUrlMatch[1] !== "N/A") { metadata.attachmentUrl = attachmentUrlMatch[1].trim(); } return metadata; }; // 合併現有元數據和從頭部提取的元數據 const mergedMetadata = { ...metadataFallback, ...script.metadata, ...extractMetadata(headerComment), }; // 創建嵌入消息 const embed = new EmbedBuilder() .setColor(0x00ae86) .setTitle(`腳本預覽:${scriptName}`) .setDescription("腳本詳細信息") .addFields( { name: "原始腳本名稱", value: mergedMetadata.originalFileName, inline: true, }, { name: "上傳者", value: typeof mergedMetadata.author === "object" && mergedMetadata.author.id ? `${mergedMetadata.author.name || "未知"} (${ mergedMetadata.author.id })` : mergedMetadata.author || "未知", inline: true, }, { name: "上傳時間", value: mergedMetadata.createdAt, inline: true, }, { name: "腳本狀態", value: script.enabled ? "已啟用" : "已停用", inline: true, }, { name: "腳本描述", value: mergedMetadata.description, inline: false, } ) .setFooter({ text: "腳本詳細信息" }); // 如果有附件鏈接,添加到 embed if (mergedMetadata.attachmentUrl) { embed.addFields({ name: "原始附件", value: mergedMetadata.attachmentUrl, inline: false, }); } // 預覽腳本前幾行 const previewLines = scriptContent.split("\n").slice(0, 10).join("\n"); embed.addFields({ name: "腳本預覽", value: `\`\`\`js\n${previewLines}\n...\`\`\``, inline: false, }); await interaction.reply({ embeds: [embed], ephemeral: false, }); } catch (error) { logger.error(`預覽腳本時出錯: ${error.message}`, { showStack: true }); await interaction.reply({ content: `❌ 預覽腳本時出錯:${error.message}`, ephemeral: true, }); } }, async autocomplete(interaction) { const logger = Logger.createContextLogger({ module: "PreviewScript", 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(), }); } } }, };