From a5c5faf328119a4886b3a1440d0a2b21c7982d8a Mon Sep 17 00:00:00 2001 From: Wx-2025 <351320169@qq.com> Date: Mon, 7 Jul 2025 02:07:41 +0800 Subject: [PATCH] Add files via upload --- assets/amily2-modal.html | 158 ++++++++++++++++++++ assets/style.css | 49 +++++++ core/api.js | 303 +++++++++++++++++++++++++++++++++++++++ core/commands.js | 198 +++++++++++++++++++++++++ core/events.js | 98 +++++++++++++ core/lore.js | 241 +++++++++++++++++++++++++++++++ index.js | 95 ++++++++++++ manifest.json | 13 ++ package.json | 22 +++ ui/bindings.js | 196 +++++++++++++++++++++++++ ui/drawer.js | 131 +++++++++++++++++ ui/state.js | 104 ++++++++++++++ utils/auth.js | 194 +++++++++++++++++++++++++ utils/settings.js | 218 ++++++++++++++++++++++++++++ 14 files changed, 2020 insertions(+) create mode 100644 assets/amily2-modal.html create mode 100644 assets/style.css create mode 100644 core/api.js create mode 100644 core/commands.js create mode 100644 core/events.js create mode 100644 core/lore.js create mode 100644 index.js create mode 100644 manifest.json create mode 100644 package.json create mode 100644 ui/bindings.js create mode 100644 ui/drawer.js create mode 100644 ui/state.js create mode 100644 utils/auth.js create mode 100644 utils/settings.js diff --git a/assets/amily2-modal.html b/assets/amily2-modal.html new file mode 100644 index 0000000..3acc0de --- /dev/null +++ b/assets/amily2-modal.html @@ -0,0 +1,158 @@ + +
紧急报告:无法加载Amily2号府邸内饰。
', + ); + } + } + + }, + ); +} diff --git a/ui/state.js b/ui/state.js new file mode 100644 index 0000000..5728864 --- /dev/null +++ b/ui/state.js @@ -0,0 +1,104 @@ +import { extension_settings } from "/scripts/extensions.js"; +import { extensionName } from "../utils/settings.js"; +import { pluginAuthStatus } from "../utils/auth.js"; + +let availableModels = []; + + +export function setAvailableModels(models) { + availableModels = models; +} + + +export function populateModelDropdown() { + const modelSelect = $("#amily2_model"); + const modelNotes = $("#amily2_model_notes"); + + modelSelect.empty(); + const currentModel = extension_settings[extensionName]?.model || ""; + + if (availableModels.length === 0) { + modelSelect.append(''); + modelNotes.html( + '请检查API配置后点击"刷新模型"', + ); + return; + } + + const defaultOption = $("").val("").text("-- 选择模型 --"); + modelSelect.append(defaultOption); + + availableModels.forEach((model) => { + const option = $("").val(model).text(model); + if (model === currentModel) { + option.attr("selected", "selected"); + } + modelSelect.append(option); + }); + + if (currentModel && modelSelect.val() === currentModel) { + modelNotes.html(`已选择: ${currentModel}`); + } else { + modelNotes.html(`已加载 ${availableModels.length} 个可用模型`); + } +} + + +export function updateUI() { + if (!pluginAuthStatus.authorized) { + $("#auth_panel").show(); + $(".plugin-features").hide(); + } else { + $("#auth_panel").hide(); + $(".plugin-features").show(); + + const settings = extension_settings[extensionName]; + if (!settings) return; // 安全检查 + + // --- 通用设置 --- + $("#amily2_enabled").prop("checked", settings.enabled); + $("#amily2_api_url").val(settings.apiUrl); + $("#amily2_api_key").val(settings.apiKey); + $("#amily2_model").val(settings.model); + + + $("#amily2_max_tokens").val(settings.maxTokens); + $("#amily2_max_tokens_value").text(settings.maxTokens); + $("#amily2_temperature").val(settings.temperature); + $("#amily2_temperature_value").text(settings.temperature); + $("#amily2_context_messages").val(settings.contextMessages); + $("#amily2_context_messages_value").text(settings.contextMessages); + + + $( + `input[name="amily2_optimization_mode"][value="${settings.optimizationMode}"]`, + ).prop("checked", true); + $("#amily2_optimization_enabled").prop( + "checked", + settings.optimizationEnabled, + ); + $("#amily2_show_optimization_toast").prop( + "checked", + settings.showOptimizationToast, + ); + $("#amily2_suppress_toast").prop("checked", settings.suppressToast); + + + $("#amily2_system_prompt").val(settings.systemPrompt); + $("#amily2_main_prompt").val(settings.mainPrompt); + $("#amily2_output_format_prompt").val(settings.outputFormatPrompt); + $("#amily2_summarization_prompt").val(settings.summarizationPrompt); + + + $("#amily2_worldbook_enabled").prop("checked", settings.worldbookEnabled); + $("#amily2_summarization_enabled").prop( + "checked", + settings.summarizationEnabled, + ); + $( + `input[name="amily2_lorebook_target"][value="${settings.lorebookTarget}"]`, + ).prop("checked", true); + + populateModelDropdown(); + } +} diff --git a/utils/auth.js b/utils/auth.js new file mode 100644 index 0000000..c58b8b7 --- /dev/null +++ b/utils/auth.js @@ -0,0 +1,194 @@ + +import { extension_settings } from "/scripts/extensions.js"; +import { saveSettings } from "./settings.js"; +import { updateUI } from "../ui/state.js"; + + +export const pluginAuthStatus = { + authorized: false, + expired: false, +}; + +const PASSWORD_VALIDITY_DAYS = 7; + +const AUTH_CONFIG = { + expiryDate: new Date("2025-12-31"), + validityDays: PASSWORD_VALIDITY_DAYS, +}; + + +console.log(`[Amily2号] 密码有效期为: ${PASSWORD_VALIDITY_DAYS}天`); + + +function generateDynamicPassword(date = new Date()) { + const seed = { a: 1103515245, c: 12345, m: 2147483647 }; + + function customHash(input) { + let hash = 0; + for (let i = 0; i < input.length; i++) { + hash = (hash << 5) - hash + input.charCodeAt(i); + hash |= 0; + } + return hash >>> 0; + } + + const month = date.getMonth() + 1; + const day = date.getDate(); + const year = date.getFullYear(); + const baseInput = `${month}-${day}-AMILY_${year}`; + const str1 = `SD${customHash(baseInput)}`; + const str2 = `V${customHash(str1)}`; + + function lcgRandom(params) { + return function () { + params.seed = (params.a*params.seed + params.c) % params.m; + return params.seed; + }; + } + + const combinedSeed = customHash(str2) % seed.m; + const randFunc = lcgRandom({ ...seed, seed: combinedSeed }); + const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; + const segments = []; + for (let segIdx = 0; segIdx < 3; segIdx++) { + let segment = ""; + for (let i = 0; i < 4; i++) { + const randValue = Math.abs(randFunc()); + segment += chars.charAt(randValue % chars.length); + } + segments.push(segment); + } + return segments.join("-"); +} + + +export function getPasswordForDate(date = new Date()) { + return generateDynamicPassword(date); +} + + +export function checkAuthorization() { + const now = new Date(); + pluginAuthStatus.expired = now > AUTH_CONFIG.expiryDate; + + if (pluginAuthStatus.expired) { + localStorage.removeItem("plugin_activated"); + localStorage.removeItem("plugin_auth_code"); + localStorage.removeItem("plugin_valid_until"); + console.log("[Amily2号] 检测到授权过期,已清理本地存储。"); + } + + const activated = localStorage.getItem("plugin_activated") === "true"; + const savedAuthCode = localStorage.getItem("plugin_auth_code"); + const validUntil = localStorage.getItem("plugin_valid_until"); + + let withinValidityPeriod = false; + if (validUntil) { + const validUntilDate = new Date(validUntil); + withinValidityPeriod = now <= validUntilDate; + console.log(`[Amily2号] 授权有效期检查: + 当前时间: ${now.toISOString()} + 授权有效期至: ${validUntilDate.toISOString()} + 是否在有效期内: ${withinValidityPeriod}`); + } + + let passwordMatches = false; + if (savedAuthCode) { + const today = new Date(); + for (let i = 0; i < AUTH_CONFIG.validityDays; i++) { + const checkDate = new Date(); + checkDate.setDate(today.getDate() - i); + const passwordForDay = getPasswordForDate(checkDate); + if (savedAuthCode === passwordForDay) { + passwordMatches = true; + console.log(`[Amily2号] 密码匹配: ${savedAuthCode} 对应第${i + 1}天前`); + break; + } + } + } + + pluginAuthStatus.authorized = + activated && + !pluginAuthStatus.expired && + passwordMatches && + withinValidityPeriod; + + return pluginAuthStatus.authorized; +} + + +export async function activatePluginAuthorization(authCode) { + let isValidCode = false; + const today = new Date(); + + for (let i = 0; i < AUTH_CONFIG.validityDays; i++) { + const checkDate = new Date(); + checkDate.setDate(today.getDate() - i); + const passwordForDay = getPasswordForDate(checkDate); + if (authCode === passwordForDay) { + isValidCode = true; + break; + } + } + + if (!isValidCode) { + toastr.error("授权码无效", "激活失败"); + return false; + } + + const now = new Date(); + if (now > AUTH_CONFIG.expiryDate) { + toastr.error("授权已过期", "激活失败"); + return false; + } + + const validUntil = new Date(); + validUntil.setDate(now.getDate() + AUTH_CONFIG.validityDays); + localStorage.setItem("plugin_valid_until", validUntil.toISOString()); + localStorage.setItem("plugin_auth_code", authCode); + localStorage.setItem("plugin_activated", "true"); + localStorage.setItem("plugin_auto_login", "true"); + + toastr.success( + `授权激活成功!${AUTH_CONFIG.validityDays}天内将自动登录。`, + "Amily2号启用", + ); + pluginAuthStatus.authorized = true; + + $("#auth_panel").slideUp(400, function () { + $(".plugin-features").slideDown(400); + updateUI(); + }); + + extension_settings[extensionName].enabled = true; + saveSettings(); + + return true; +} + + +export function displayExpiryInfo() { + const now = new Date(); + const daysLeft = Math.ceil( + (AUTH_CONFIG.expiryDate - now) / (1000* 60 *60* 24), + ); + const validUntil = localStorage.getItem("plugin_valid_until"); + + if (pluginAuthStatus.expired) { + return '