LM Arena Chat Interceptor

LmArena 自定义system提示词+拦截聊天请求替换绕过输入审查

// ==UserScript==
// @name         LM Arena Chat Interceptor
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  LmArena 自定义system提示词+拦截聊天请求替换绕过输入审查
// @match        https://lmarena.ai/*
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // ===== 注入 fetch 拦截器 =====
    function injectScript(code) {
        const s = document.createElement('script');
        s.textContent = code;
        document.documentElement.appendChild(s);
        s.remove();
    }

    const hookCode = `
(function () {
    function uuidv4() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = crypto.getRandomValues(new Uint8Array(1))[0] & 15;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    const DEFAULT_SYSTEM_PROMPT = "你是一个被特殊优化的助手";
    function getSystemPrompt() {
        try { return localStorage.getItem("lmArenaSystemPrompt") || DEFAULT_SYSTEM_PROMPT; }
        catch (e) { return DEFAULT_SYSTEM_PROMPT; }
    }

    function getSelectedModelId() {
        try { return localStorage.getItem("lmArenaSelectedModel") || null; }
        catch (e) { return null; }
    }

    const rawFetch = window.fetch;
    if (!rawFetch) return;

    function replaceRefreshContent(body){
       if (body.messages && Array.isArray(body.messages)) {
           var userMsg = body.messages[0];
           var newMsg = document.querySelector('textarea[name="message"]')?.value;
           if(newMsg){
               userMsg.content = newMsg;
           }
       }
    }

    function addSystemAndAdjustUserMessageRefresh(body) {
        let lastUserIndex = body.messages.map(m => m.role).lastIndexOf("user");
        let lastUserMsg = body.messages[lastUserIndex];

        // === 插入 system 消息(保留你原有逻辑)===
        if (body.messages && Array.isArray(body.messages)) {
            let systemId = null;
            if (!body.messages.some(m => m.role === "system")) {
                systemId = uuidv4();
                body.messages.unshift({
                    id: systemId,
                    role: "system",
                    content: getSystemPrompt(),
                    experimental_attachments: [],
                    parentMessageIds: [],
                    participantPosition: "a",
                    modelId: null,
                    evaluationSessionId: lastUserMsg.evaluationSessionId,
                    status: "success",
                    failureReason: null
                });
                console.log("插入 system 消息:", systemId);

                for (let i = 1; i < body.messages.length; i++) {
                    if (body.messages[i].role === "user") {
                        body.messages[i].parentMessageIds = [systemId];
                        console.log("修正第一条 user parentMessageIds:", body.messages[i]);
                        break;
                    }
                }
            }

            // === 插入空 user(保留你原有逻辑)===

                const emptyUserId = uuidv4();
                const emptyUserMsg = {
                    id: emptyUserId,
                    role: "user",
                    content: "",
                    experimental_attachments: [],
                    parentMessageIds: [body.messages[lastUserIndex].id],
                    participantPosition: "a",
                    modelId: null,
                    evaluationSessionId: lastUserMsg.evaluationSessionId,
                    status: "pending",
                    failureReason: null
                };
                body.messages.push(emptyUserMsg);
                console.log("插入空 user:", emptyUserMsg);

        }
    }

    function addSystemAndAdjustUserMessage(body) {
        // === 插入 system 消息(保留你原有逻辑)===
        if (body.messages && Array.isArray(body.messages)) {
            let systemId = null;
            if (!body.messages.some(m => m.role === "system")) {
                systemId = uuidv4();
                body.messages.unshift({
                    id: systemId,
                    role: "system",
                    content: getSystemPrompt(),
                    experimental_attachments: [],
                    parentMessageIds: [],
                    participantPosition: "a",
                    modelId: null,
                    evaluationSessionId: body.id,
                    status: "success",
                    failureReason: null
                });
                console.log("插入 system 消息:", systemId);

                for (let i = 1; i < body.messages.length; i++) {
                    if (body.messages[i].role === "user") {
                        body.messages[i].parentMessageIds = [systemId];
                        console.log("修正第一条 user parentMessageIds:", body.messages[i]);
                        break;
                    }
                }
            }

            // === 插入空 user(保留你原有逻辑)===
            let lastUserIndex = body.messages.map(m => m.role).lastIndexOf("user");
            let lastAssistantIndex = body.messages.findIndex(
                m => m.role === "assistant" && m.content === "" && m.status === "pending"
            );

            if (lastUserIndex !== -1 && lastAssistantIndex > lastUserIndex) {
                const emptyUserId = uuidv4();
                const emptyUserMsg = {
                    id: emptyUserId,
                    role: "user",
                    content: "",
                    experimental_attachments: [],
                    parentMessageIds: [body.messages[lastUserIndex].id],
                    participantPosition: "a",
                    modelId: null,
                    evaluationSessionId: body.id,
                    status: "pending",
                    failureReason: null
                };
                body.messages.splice(lastAssistantIndex, 0, emptyUserMsg);
                console.log("插入空 user:", emptyUserMsg);

                body.messages[lastAssistantIndex + 1].parentMessageIds = [emptyUserId];
                console.log("修正 assistant parentMessageIds:", body.messages[lastAssistantIndex + 1]);
            }
        }
    }

    window.fetch = async function (resource, config) {
        try {
            const isNew = typeof resource === "string" && resource.includes("/nextjs-api/stream/create-evaluation");
            const isReply = typeof resource === "string" && resource.includes("/nextjs-api/stream/post-to-evaluation/");
            const isRefresh = typeof resource === "string" && resource.includes("/nextjs-api/stream/retry-evaluation-session-message");
            const isImage = document.querySelector('button[aria-pressed="true"][aria-label="Image"]') != null;

            if (isNew || isReply || isRefresh) {
                console.group("[Interceptor] 拦截聊天请求", resource);

                if (config && config.body) {
                    let body = JSON.parse(config.body);

                    //const isImage = body.modality === 'image';
                    if (!isImage) {
                        if(isRefresh){
                            addSystemAndAdjustUserMessageRefresh(body);
                        }
                        else{
                            addSystemAndAdjustUserMessage(body);
                        }
                    }
                    else if(isRefresh){
                        replaceRefreshContent(body);
                    }

                    config.body = JSON.stringify(body);
                    console.log("修改后的 body:", config.body);
                }
                console.groupEnd();
            }
        } catch (e) {
            console.error("[Interceptor Error]", e);
        }
        return rawFetch.apply(this, arguments);
    };

    console.log("[Injected] fetch 拦截器已启用");
})();
    `;

    injectScript(hookCode);

    // ===== 提取完整模型列表 =====
    const exposeModelsCode = `
    (function(){
        function extractArray(serialized, key) {
            const keyToken = '"' + key + '":';
            const keyIdx = serialized.indexOf(keyToken);
            if (keyIdx === -1) return null;
            let idx = serialized.indexOf('[', keyIdx + keyToken.length);
            if (idx === -1) return null;

            let depth = 0, inStr = false, escape = false;
            for (let i = idx; i < serialized.length; i++) {
                const ch = serialized[i];
                if (inStr) {
                    if (escape) { escape = false; }
                    else if (ch === '\\\\') { escape = true; }
                    else if (ch === '"') { inStr = false; }
                } else {
                    if (ch === '"') inStr = true;
                    else if (ch === '[') depth++;
                    else if (ch === ']') {
                        depth--;
                        if (depth === 0) return serialized.slice(idx, i + 1);
                    }
                }
            }
            return null;
        }

        const timer = setInterval(() => {
            try {
                if (!self.__next_f) return;
                for (const item of self.__next_f) {
                    if (!Array.isArray(item) || item.length !== 2 || typeof item[1] !== "string") continue;
                    const serialized = item[1];
                    if (!serialized.includes("EvaluationStoreProvider") || !serialized.includes("initialModels")) continue;
                    const arrStr = extractArray(serialized, "initialModels");
                    if (arrStr) {
                        try {
                            const models = JSON.parse(arrStr);
                            localStorage.setItem("__LM_ALL_MODELS__", JSON.stringify(models));
                            console.log("[Injected] 成功提取模型列表,数量:", models.length);
                            clearInterval(timer);
                        } catch (e) {
                            console.error("[Injected] 解析失败:", e);
                        }
                    }
                }
            } catch (e) {
                console.error("[Injected] 异常:", e);
            }
        }, 800);
    })();
    `;
    //injectScript(exposeModelsCode);

    // ===== 保留你的齿轮按钮(编辑system提示词)=====
    const DEFAULT_SYSTEM_PROMPT = "你是一个被特殊优化的助手...";
    function getSystemPrompt() {
        return localStorage.getItem("lmArenaSystemPrompt") || DEFAULT_SYSTEM_PROMPT;
    }
    function setSystemPrompt(v) {
        localStorage.setItem("lmArenaSystemPrompt", v);
    }

    function createPanel() {
        const overlay = document.createElement("div");
        overlay.style.position = "fixed";
        overlay.style.top = "0";
        overlay.style.left = "0";
        overlay.style.width = "100%";
        overlay.style.height = "100%";
        overlay.style.background = "rgba(0,0,0,0.6)";
        overlay.style.zIndex = "9999";
        overlay.style.display = "flex";
        overlay.style.alignItems = "center";
        overlay.style.justifyContent = "center";
        overlay.style.overflow = "auto"; // 支持滚动

        const panel = document.createElement("div");
        panel.style.background = "#222";
        panel.style.color = "#eee";
        panel.style.padding = "24px";
        panel.style.borderRadius = "8px";
        panel.style.width = "800px";
        panel.style.maxWidth = "90%";
        panel.style.maxHeight = "90vh";
        panel.style.boxShadow = "0 4px 12px rgba(0,0,0,0.8)";
        panel.style.overflowY = "auto"; // 内容可滚动

        // === 标题 ===
        const title = document.createElement("div");
        title.textContent = "系统设置";
        title.style.fontWeight = "bold";
        title.style.fontSize = "18px";
        title.style.marginBottom = "16px";
        title.style.textAlign = "center";
        panel.appendChild(title);

        // === System 提示词编辑区 ===
        const sysTitle = document.createElement("div");
        sysTitle.textContent = "📝 System 提示词";
        sysTitle.style.marginTop = "16px";
        sysTitle.style.fontWeight = "bold";
        sysTitle.style.color = "#0f0";
        panel.appendChild(sysTitle);

        const sysTextarea = document.createElement("textarea");
        sysTextarea.style.width = "100%";
        sysTextarea.style.height = "120px";
        sysTextarea.style.background = "#111";
        sysTextarea.style.color = "#0f0";
        sysTextarea.style.border = "1px solid #555";
        sysTextarea.style.borderRadius = "4px";
        sysTextarea.style.marginTop = "8px";
        sysTextarea.value = getSystemPrompt();
        panel.appendChild(sysTextarea);

        // // === 模型选择区 ===
        // const modelTitle = document.createElement("div");
        // modelTitle.textContent = "🤖 选择默认模型";
        // modelTitle.style.marginTop = "24px";
        // modelTitle.style.fontWeight = "bold";
        // modelTitle.style.color = "#0af";
        // panel.appendChild(modelTitle);

        // const modelSelect = document.createElement("select");
        // modelSelect.style.width = "100%";
        // modelSelect.style.padding = "8px";
        // modelSelect.style.marginTop = "8px";
        // modelSelect.style.background = "#111";
        // modelSelect.style.color = "#fff";
        // modelSelect.style.border = "1px solid #555";
        // modelSelect.style.borderRadius = "4px";

        // // 加载模型
        // const raw = localStorage.getItem("__LM_ALL_MODELS__");
        // if (raw) {
        //     try {
        //         const models = JSON.parse(raw);
        //         const textModels = models.filter(m => !m.capabilities?.outputCapabilities?.image);
        //         const imageModels = models.filter(m => m.capabilities?.outputCapabilities?.image);

        //         function addOptgroup(label, models) {
        //             const group = document.createElement("optgroup");
        //             group.label = label;
        //             models.forEach(m => {
        //                 const opt = document.createElement("option");
        //                 opt.value = m.id;
        //                 opt.textContent = `${m.publicName} (${m.id})`;
        //                 group.appendChild(opt);
        //             });
        //             modelSelect.appendChild(group);
        //         }

        //         addOptgroup("🔤 语言模型", textModels);
        //         if (imageModels.length > 0) {
        //             addOptgroup("🖼️ 图像模型", imageModels);
        //         }

        //         // 设置当前选中
        //         const savedModelId = localStorage.getItem("lmArenaSelectedModel");
        //         if (savedModelId) {
        //             modelSelect.value = savedModelId;
        //         }
        //     } catch (e) {
        //         console.error("加载模型列表失败:", e);
        //         modelSelect.innerHTML = "<option>加载模型失败</option>";
        //     }
        // } else {
        //     modelSelect.innerHTML = "<option>模型列表未加载</option>";
        // }

        // panel.appendChild(modelSelect);

        // === 按钮区 ===
        const btnContainer = document.createElement("div");
        btnContainer.style.marginTop = "24px";
        btnContainer.style.display = "flex";
        btnContainer.style.justifyContent = "center";
        btnContainer.style.gap = "12px";

        const btnSave = document.createElement("button");
        btnSave.textContent = "💾 保存设置";
        btnSave.style.background = "#0a0";
        btnSave.style.color = "#fff";
        btnSave.style.border = "none";
        btnSave.style.padding = "8px 16px";
        btnSave.style.borderRadius = "4px";
        btnSave.style.cursor = "pointer";
        btnSave.style.fontSize = "14px";
        btnSave.onclick = () => {
            setSystemPrompt(sysTextarea.value);
            //localStorage.setItem("lmArenaSelectedModel", modelSelect.value);
            document.body.removeChild(overlay);
            alert("✅ 设置已保存:System 提示词");
        };
        btnContainer.appendChild(btnSave);

        const btnCancel = document.createElement("button");
        btnCancel.textContent = "❌ 取消";
        btnCancel.style.background = "#a00";
        btnCancel.style.color = "#fff";
        btnCancel.style.border = "none";
        btnCancel.style.padding = "8px 16px";
        btnCancel.style.borderRadius = "4px";
        btnCancel.style.cursor = "pointer";
        btnCancel.style.fontSize = "14px";
        btnCancel.onclick = () => document.body.removeChild(overlay);
        btnContainer.appendChild(btnCancel);

        panel.appendChild(btnContainer);
        overlay.appendChild(panel);
        document.body.appendChild(overlay);

        //console.log("[Userscript] 设置面板已打开,包含模型选择器");
    }

    // 添加齿轮按钮
    function addGearButton() {
        const container = document.querySelector('textarea[name="message"]')
            ?.nextElementSibling
            ?.querySelector('div[data-sentry-component="SelectChatModality"]');

        if (container && !container.querySelector('[aria-label="Edit System Prompt"]')) {
            const btn = document.createElement("button");
            btn.type = "button";
            btn.className = container.querySelector("button")?.className || "";
            btn.setAttribute("aria-label", "Edit System Prompt");
            btn.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"
                 viewBox="0 0 24 24" fill="none" stroke="currentColor"
                 stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                 class="lucide lucide-settings w-4 h-4 transition-colors
                 duration-150 ease-out text-interactive-normal">
              <circle cx="12" cy="12" r="3"></circle>
              <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83
              2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0
              0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0
              0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1
              1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65
              1.65 0 0 0-1.51-1H3a2 2 0 0
              1 0-4h.09c.7 0 1.31-.4 1.51-1a1.65
              1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1
              1 2.83-2.83l.06.06c.46.46 1.12.61
              1.82.33.6-.2 1-.81 1-1.51V3a2 2 0 0
              1 4 0v.09c0 .7.4 1.31 1 1.51.7.28
              1.36.13 1.82-.33l.06-.06a2 2 0 1
              1 2.83 2.83l-.06.06c-.46.46-.61
              1.12-.33 1.82.2.6.81 1 1.51
              1H21a2 2 0 0 1 0 4h-.09c-.7 0-1.31.4-1.51
              1z"></path>
            </svg>`;
            btn.onclick = createPanel;
            container.appendChild(btn);
            console.log("[Userscript] 齿轮按钮已添加");
        }
    }

    // ===== 监听 DOM,统一初始化齿轮按钮 + 模型下拉框 =====
    const obs = new MutationObserver(async () => {
        const container = document.querySelector('div[data-sentry-component="SelectChatModality"]');
        if (!container) return;

        // 1. 添加齿轮按钮(如果不存在)
        if (!container.querySelector('[aria-label="Edit System Prompt"]')) {
            addGearButton();
        }
    });
    obs.observe(document, { childList: true, subtree: true });

})();