diff --git a/index.js b/index.js index 76aec66..a2777d1 100644 --- a/index.js +++ b/index.js @@ -31,7 +31,7 @@ import { initializeApiListener, registerApiHandler, amilyHelper, initializeAmily import { registerContextOptimizerMacros, resetContextBuffer } from './core/context-optimizer.js'; import { initializeSuperMemory } from './core/super-memory/manager.js'; -const DOMPURIFY_CDN = "https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.8/purify.min.js"; +const DOMPURIFY_CDN = "https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.7/purify.min.js"; function loadExternalScript(url, globalName) { return new Promise((resolve, reject) => { @@ -250,16 +250,18 @@ function sanitizeHTML(html) { continue; } + // 移除所有属性,只保留允许的 const attrs = Array.from(el.attributes); for (const attr of attrs) { const attrName = attr.name.toLowerCase(); if (!allowedAttrs.includes(attrName)) { el.removeAttribute(attr.name); } else if (attrName === 'href') { + // 检查 href 是否包含 javascript: if (attr.value.toLowerCase().trim().startsWith('javascript:')) { el.removeAttribute('href'); } - } else if (attrName.startsWith('on')) { + } else if (attrName.startsWith('on')) { // 双重保险,移除所有事件处理器 el.removeAttribute(attr.name); } } @@ -274,6 +276,7 @@ async function handleMessageBoard() { if (messageData && messageData.message) { const messageBoard = $('#amily2_message_board'); const messageContent = $('#amily2_message_content'); + // 使用净化后的 HTML,防止 XSS 攻击 const safeContent = sanitizeHTML(messageData.message); messageContent.html(safeContent); messageBoard.show(); @@ -284,7 +287,7 @@ async function handleMessageBoard() { } }; await updateMessage(); - setInterval(updateMessage, 300000); + setInterval(updateMessage, 300000); // 5分钟刷新一次(从60秒改为300秒) } @@ -344,7 +347,9 @@ function loadPluginStyles() { window.addEventListener('message', function (event) { + // 处理头像获取请求 if (event.data && event.data.type === 'getAvatars') { + // 【兼容性修复】如果 LittleWhiteBox 激活,则不处理此消息,避免冲突 if (window.isXiaobaixEnabled) { return; } @@ -358,6 +363,7 @@ window.addEventListener('message', function (event) { return; } + // 处理来自 iframe 的交互事件 if (event.data && event.data.source === 'amily2-iframe') { const { action, detail } = event.data; console.log(`[Amily2-主窗口] 收到来自iframe的动作: ${action}`, detail); @@ -405,8 +411,10 @@ window.addEventListener("error", (event) => { jQuery(async () => { console.log("[Amily2号-帝国枢密院] 开始执行开国大典..."); + // 启动外部库加载 (DOMPurify) loadExternalScript(DOMPURIFY_CDN, 'DOMPurify').catch(e => console.warn("[Amily2] DOMPurify 加载失败,将使用内置净化器:", e)); - + + // 【V146.2 紧急优化】优先注册上下文优化器,确保它在密折司之前拦截并处理 Prompt try { console.log("[Amily2号-开国大典] 步骤0:优先注册上下文优化器..."); registerContextOptimizerMacros(); @@ -414,6 +422,7 @@ jQuery(async () => { console.error("[Amily2号-开国大典] 上下文优化器注册失败:", e); } + // 【密折司】延迟加载,确保它排在优化器之后 try { await import("./MiZheSi/index.js"); console.log("[Amily2号-开国大典] 密折司模块已就位。"); @@ -667,6 +676,7 @@ jQuery(async () => { const context = getContext(); if (!userMessage) { + // 尝试从聊天记录中获取最后一条用户消息(针对 /send 指令场景) if (context.chat && context.chat.length > 0) { const lastMsg = context.chat[context.chat.length - 1]; if (lastMsg.is_user) { @@ -719,6 +729,7 @@ jQuery(async () => { const contextTurnCount = globalSettings.plotOpt_contextLimit || 10; let slicedContext = []; + // 如果是从聊天记录中获取的消息,上下文需要排除最后一条 const contextSource = isFromTextarea ? context.chat : context.chat.slice(0, -1); if (contextTurnCount > 0) { @@ -882,8 +893,11 @@ jQuery(async () => { if (checkAuthorization()) { const userType = localStorage.getItem("plugin_user_type") || "未知"; const userNote = localStorage.getItem("plugin_user_note"); + + // 1. 先显示本地缓存的状态,保证启动速度和体验 const displayNote = userNote || userType; toastr.success(`欢迎回来!授权状态有效 (用户: ${displayNote})`, "Amily2 插件已就绪"); + refreshUserInfo().then(data => { if (data && data.note && data.note !== userNote) { console.log("[Amily2] 用户信息已更新:", data.note); @@ -908,9 +922,10 @@ jQuery(async () => { initializeOnlineTracker(); // 【Amily2号-在线统计】启动在线人数统计 initializeLocalLinkage(); // 【Amily2号-本地联动】启动本地联动服务 + // 【V146.4】自动初始化超级记忆系统 setTimeout(() => { initializeSuperMemory(); - }, 3000); + }, 3000); // 延迟3秒以确保 ST 环境完全就绪 initializeRenderer(); @@ -1007,9 +1022,11 @@ function initializeOnlineTracker() { return; } + // 防止短时间内重复调用 if (isConnecting) return; isConnecting = true; + // 清理旧连接 if (ws) { try { ws.close(); @@ -1046,6 +1063,8 @@ function initializeOnlineTracker() { $('#amily2-online-count').text('离线'); isConnecting = false; ws = null; + + // 延迟重连,而不是立即循环 if (!reconnectTimer) { reconnectTimer = setTimeout(() => { reconnectTimer = null; @@ -1068,6 +1087,8 @@ function initializeOnlineTracker() { } } } + + // 启动挂载流程 mountTracker(); } @@ -1089,7 +1110,7 @@ function initializeLocalLinkage() { ws.onopen = () => { console.log('[Amily2-本地联动] 已连接到启动器服务'); if (window.toastr) toastr.success('已连接到 Amily 启动器', '本地联动'); - retryCount = 0; + retryCount = 0; // 连接成功,重置计数 }; ws.onmessage = async (event) => { @@ -1107,6 +1128,7 @@ function initializeLocalLinkage() { const total = window.AmilyHelper.getLastMessageId() + 1; if (total > keep) { const deleteCount = total - keep; + // 生成要删除的 ID 列表 (0 到 deleteCount - 1) const idsToDelete = Array.from({length: deleteCount}, (_, i) => i); await window.AmilyHelper.deleteChatMessages(idsToDelete, { refresh: 'all' }); if (window.toastr) window.toastr.success(`已清理 ${deleteCount} 条旧消息,保留最近 ${keep} 条`, '清理完成');