Greasy Fork镜像 还支持 简体中文。

TriX Core Library

Core logic library for TriX Executor with Python/WASM support.

目前為 2025-07-11 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/541461/1622729/TriX%20Core%20Library.js

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

const TriX_Core = (function() {
    'use strict';
    const PYODIDE_CDN_BASE = 'https://cdn.jsdelivr.net/pyodide/v0.25.1/full/';
    const PyodideManager = {
        pyodide: null, isLoading: false, isSkipped: false,
        loadPyodideDynamically() { return new Promise((e,t)=>{if(window.loadPyodide)return e(window.loadPyodide);const i=document.createElement("script");i.src=`${PYODIDE_CDN_BASE}pyodide.js`,i.onload=()=>{const t=setInterval(()=>{window.loadPyodide&&(clearInterval(t),console.log("[Pyodide Loader] `loadPyodide` function found on window object."),e(window.loadPyodide))},100)},i.onerror=e=>t(new Error("Failed to load Pyodide script from CDN. Check browser console for network errors.")),document.head.appendChild(i)}) },
        async init(isPreloading=false, progressCallback=null) {
            if (this.pyodide || this.isLoading || this.isSkipped) return;
            this.isLoading = true;
            if(!isPreloading) { TriX_UI.setPythonStatus('loading'); TriX_UI.log('Initializing Python runtime (Pyodide)... This is a large one-time download.', 'info'); TriX_UI.createProgressBar(); }
            try {
                const loadPyodideFunction = await this.loadPyodideDynamically();
                this.pyodide = await loadPyodideFunction({ indexURL: PYODIDE_CDN_BASE,
                    fullErrHandler: (err) => { if(progressCallback) progressCallback({what: err}) },
                    stdout: (msg) => { if(progressCallback) progressCallback({what: msg}) },
                 });
                if(!isPreloading) { document.getElementById('trix-py-progress-container')?.remove(); TriX_UI.log('Python runtime ready.', 'info'); TriX_UI.setPythonStatus('ready'); }
            } catch (err) {
                if(!isPreloading) { document.getElementById('trix-py-progress-container')?.remove(); TriX_UI.setPythonStatus('error'); }
                TriX_UI.log(`Error loading Pyodide: ${err.message}. Python features will be unavailable.`, 'error');
                throw err;
            } finally { this.isLoading = false; }
        },
        async run(code, packages) { if(this.isSkipped)return TriX_UI.log("Python was skipped during startup. Please reload to enable.","warn");if(!this.pyodide){TriX_UI.log("Python runtime is not ready yet. Please wait.","warn");if(this.isLoading)return;await this.init();if(!this.pyodide)return}TriX_UI.setPythonStatus("running");try{if(packages){const e=packages.split(",").map(e=>e.trim()).filter(e=>e);TriX_UI.log(`Loading Python packages: ${e.join(", ")}`,"info"),await this.pyodide.loadPackage("micropip");const t=this.pyodide.pyimport("micropip");await t.install(e),TriX_UI.log("Packages loaded.","info")}TriX_UI.log("Executing Python script...","info"),this.pyodide.setStdout({batched:e=>TriX_UI.log(`${e}`,"log")}),this.pyodide.setStderr({batched:e=>TriX_UI.log(`[Python Error]: ${e}`,"error")}),await this.pyodide.runPythonAsync(code)}catch(e){TriX_UI.log(`Python Error: ${e}`,"error")}finally{TriX_UI.setPythonStatus("ready")}}
    };
    const TabManager={tabs:[],myTabInfo:{},uiInitialized:!1,isMaster:!1,init(e,t){this.myTabInfo={id:`tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`,username:e,loadTime:Date.now(),lastSeen:Date.now()},t&&(PyodideManager.isSkipped=!0),GM_addValueChangeListener("trix_active_tabs",(e,t,i,s)=>{s&&this.pruneAndRefresh(i)}),this.register(),setInterval(()=>this.register(),5e3),window.addEventListener("beforeunload",()=>this.unregister())},async register(){let e=await GM_getValue("trix_active_tabs",[]);const t=Date.now();e=e.filter(e=>t-e.lastSeen<15e3),this.myTabInfo.lastSeen=t;const i=e.findIndex(e=>e.id===this.myTabInfo.id);-1<i?e[i]=this.myTabInfo:e.push(this.myTabInfo),await GM_setValue("trix_active_tabs",e),this.pruneAndRefresh(e)},async unregister(){let e=await GM_getValue("trix_active_tabs",[]);e=e.filter(e=>e.id!==this.myTabInfo.id),await GM_setValue("trix_active_tabs",e)},pruneAndRefresh(e){this.tabs=e,this.uiInitialized&&"undefined"!=typeof TriX_UI&&TriX_UI.updateTabCountUI(e.length),this.checkMasterStatus()},checkMasterStatus(){this.isMaster=this.amIMaster(),this.isMaster&&!this.uiInitialized&&this.initUI()},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(){this.uiInitialized||(console.log("[TriX Core] This tab is the master. Initializing UI."),this.uiInitialized=!0,TriX_UI.init(),MultiTab.init())}};
    const ScriptManager={async saveScriptFromEditor(){const e=document.getElementById("trix-save-name").value.trim(),t=document.getElementById("trix-editor").value;e?t?(await GM_setValue(`trix_script_${e}`,t),TriX_UI.log(`Script '${e}' saved.`,"info"),this.populateScriptList(`trix_script_${e}`)):TriX_UI.log("Cannot save: Editor is empty.","warn"):TriX_UI.log("Cannot save: Name is required.","error")},async loadScriptToEditor(e){if(!e)return TriX_UI.log("Invalid script key.","error");const t=await GM_getValue(e,""),i=e.replace("trix_script_","");document.getElementById("trix-editor").value=t,document.getElementById("trix-save-name").value=i,TriX_UI.log(`Loaded script: ${i}`,"info"),TriX_UI.currentScriptName=i,TriX_UI.setActiveScriptItem(e)},async deleteCurrentScript(){const e=TriX_UI.currentScriptName;e&&confirm(`Are you sure you want to delete '${e}'?`)&&(await GM_deleteValue(`trix_script_${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())},async populateScriptList(e=null){const t=document.getElementById("trix-script-list");t.innerHTML="";const i=(await GM_listValues()).filter(e=>e.startsWith("trix_script_"));i.sort().forEach(e=>{const i=document.createElement("div");i.className="trix-script-item",i.textContent=e.replace("trix_script_",""),i.dataset.scriptKey=e,t.appendChild(i)}),TriX_UI.setActiveScriptItem(e||TriX_UI.currentScriptName?`trix_script_${TriX_UI.currentScriptName}`:null)}};
    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_addStyle,html2canvas:"undefined"!=typeof html2canvas?html2canvas:null})};
    const MultiTab={init(){GM_addValueChangeListener("trix_broadcast_channel",this.listener)},listener(e,t,i,s){s&&i.senderId!==`tab_${LOAD_TIME}_${Math.random().toString(36).substring(2)}`&&TriX_UI.log(`Received broadcast: ${JSON.stringify(i.payload)}`,"broadcast")},broadcast(e){const t={senderId:`tab_${LOAD_TIME}_${Math.random().toString(36).substring(2)}`,timestamp:Date.now(),payload:e};GM_setValue("trix_broadcast_channel",t),TriX_UI.log(`Broadcast sent: ${JSON.stringify(e)}`,"broadcast")}};
    
    return { TabManager, ScriptManager, Executor, MultiTab, PyodideManager };
})();

QingJ © 2025

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