TriX Core Library

Core logic library for TriX Executor.

当前为 2025-07-11 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/541461/1622822/TriX%20Core%20Library.js

// ==UserScript==
// @name        TriX Core Library
// @namespace   https://github.com/YourUsername/TriX-Executor
// @version     2.2.1
// @description Core logic library for TriX Executor.
// @author      You
// @license     MIT
// ==/UserScript==

const TriX_Core = (function() {
    'use strict';
    
    // --- Global storage for passed-in GM functions ---
    let _GM; 

    // --- All module definitions here... ---
    // (The internal code of these modules is unchanged, but now they use the _GM object)

    const TabManager = {
        tabs:[], myTabInfo:{}, uiInitialized:false, isMaster:false,
        async init(config){
            _GM = config.gm; // Store the passed GM functions
            this.myTabInfo={id:config.tabId,username:config.username,loadTime:config.loadTime,lastSeen:Date.now()};
            _GM.GM_addValueChangeListener(config.broadcastChannel,(name,old_value,new_value,remote)=>{if(remote)this.pruneAndRefresh(new_value, config)});
            await this.register(config);
            setInterval(()=>this.register(config), config.heartbeatInterval);
            window.addEventListener('beforeunload',()=>this.unregister(config))
        },
        async register(config){let e=await _GM.GM_getValue(config.tabListKey,[]);const t=Date.now();e=e.filter(e=>t-e.lastSeen<config.staleTimeout),this.myTabInfo.lastSeen=t;const i=e.findIndex(e=>e.id===config.tabId);-1<i?e[i]=this.myTabInfo:e.push(this.myTabInfo),await _GM.GM_setValue(config.tabListKey,e),this.pruneAndRefresh(e,config)},
        async unregister(config){let e=await _GM.GM_getValue(config.tabListKey,[]);e=e.filter(e=>e.id!==config.tabId),await _GM.GM_setValue(config.tabListKey,e)},
        pruneAndRefresh(tabList,config){this.tabs=tabList;if(this.uiInitialized)TriX_UI.updateTabCountUI(tabList.length);this.checkMasterStatus(config)},
        checkMasterStatus(config){this.isMaster=this.amIMaster();if(this.isMaster&&!this.uiInitialized){this.initUI(config)}},
        amIMaster(){if(!this.myTabInfo.username||this.myTabInfo.username.startsWith("Guest_"))return!0;const e=this.tabs.filter(e=>e.username===this.myTabInfo.username);return 0===e.length||this.myTabInfo.loadTime===Math.min(...e.map(e=>e.loadTime))},
        initUI(config){if(this.uiInitialized)return;console.log("[TriX Core] This tab is the master. Initializing UI.");this.uiInitialized=!0;TriX_UI.init(_GM);MultiTab.init(config)}
    };
    const ScriptManager={async saveScriptFromEditor(prefix){const e=document.getElementById("trix-save-name").value.trim(),t=document.getElementById("trix-editor").value;e?t?(await _GM.GM_setValue(prefix+e,t),TriX_UI.log(`Script '${e}' saved.`,"info"),this.populateScriptList(prefix)):TriX_UI.log("Cannot save: Editor is empty.","warn"):TriX_UI.log("Cannot save: Name is required.","error")},async loadScriptToEditor(prefix){if(!TriX_UI.currentScriptName)return TriX_UI.log("Invalid script key.","error");const e=await _GM.GM_getValue(prefix+TriX_UI.currentScriptName,""),t=TriX_UI.currentScriptName;document.getElementById("trix-editor").value=e,document.getElementById("trix-save-name").value=t,TriX_UI.log(`Loaded script: ${t}`,"info")},async deleteCurrentScript(prefix){const e=TriX_UI.currentScriptName;e&&confirm(`Are you sure you want to delete '${e}'?`)&&(await _GM.GM_deleteValue(prefix+e),TriX_UI.log(`Script '${e}' deleted.`,"info"),document.getElementById("trix-editor").value="",document.getElementById("trix-python-editor").value="",document.getElementById("trix-save-name").value="",TriX_UI.currentScriptName="",this.populateScriptList(prefix))},async populateScriptList(prefix){const e=document.getElementById("trix-script-list");e.innerHTML="";const t=(await _GM.GM_listValues()).filter(e=>e.startsWith(prefix));t.sort().forEach(t=>{const i=document.createElement("div");i.className="trix-script-item",i.textContent=t.replace(prefix,""),i.dataset.scriptKey=t.replace(prefix,""),e.appendChild(i)}),TriX_UI.setActiveScriptItem(TriX_UI.currentScriptName)}};
    const Executor={execute(e){if(!e.trim())return TriX_UI.log("Execution skipped: script is empty.","warn");TriX_UI.log("Executing script...","info");try{const t=this.createAPI(),i=new Function("TriX",e);i(t)}catch(e){TriX_UI.log(`Execution Error: ${e.message}`,"error"),console.error("TriX Executor Error:",e)}},createAPI:()=>({log:(e,t="log")=>{const i="object"==typeof e?JSON.stringify(e):String(e);TriX_UI.log(i,t)},broadcast:e=>{MultiTab.broadcast(e)},query:(e,t="text")=>{const i=document.querySelector(e);return i?"html"===t?i.innerHTML:"value"===t?i.value:"element"===t?i:i.textContent:null},queryAll:(e,t="text")=>{const i=document.querySelectorAll(e);return Array.from(i).map(e=>"html"===t?e.innerHTML:"value"===t?e.value:"element"===t?e:e.textContent)},GM_addStyle:_GM.GM_addStyle,html2canvas:"undefined"!=typeof html2canvas?html2canvas:null,Python:TriX_Python})};
    const MultiTab={init(config){_GM.GM_addValueChangeListener(config.broadcastChannel,this.listener)},listener(e,t,i,s){s&&i.senderId!==TAB_ID&&TriX_UI.log(`Received broadcast: ${JSON.stringify(i.payload)}`,"broadcast")},broadcast(e){const t={senderId:TAB_ID,timestamp:Date.now(),payload:e};_GM.GM_setValue(BROADCAST_CHANNEL,t),TriX_UI.log(`Broadcast sent: ${JSON.stringify(e)}`,"broadcast")}};
    
    // The main init function for the entire Core library
    function init(config) {
        const fullConfig = {
            gm: {
                GM_addStyle: config.GM_addStyle,
                GM_setValue: config.GM_setValue,
                GM_getValue: config.GM_getValue,
                GM_listValues: config.GM_listValues,
                GM_deleteValue: config.GM_deleteValue,
                GM_addValueChangeListener: config.GM_addValueChangeListener,
                'GM.xmlHttpRequest': config['GM.xmlHttpRequest'],
            },
            username: config.username,
            tabId: TAB_ID,
            loadTime: LOAD_TIME,
            scriptPrefix: SCRIPT_PREFIX,
            broadcastChannel: BROADCAST_CHANNEL,
            tabListKey: TAB_LIST_KEY,
            heartbeatInterval: HEARTBEAT_INTERVAL,
            staleTimeout: STALE_TAB_TIMEOUT
        };
        TabManager.init(fullConfig);
    }
    
    return { init, ScriptManager, Executor, MultiTab };
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址