您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Core logic library for TriX Executor with Python/WASM support.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/541461/1618702/TriX%20Core%20Library.js
// ==UserScript== // @name TriX Core Library // @namespace https://github.com/YourUsername/TriX-Executor // @version 1.6.1 // @description Core logic library for TriX Executor with Python/WASM support. // @author You // @license MIT // ==/UserScript== const TriX_Core = (function() { 'use strict'; const SCRIPT_PREFIX = 'trix_script_'; const BROADCAST_CHANNEL = 'trix_broadcast_channel'; const TAB_LIST_KEY = 'trix_active_tabs'; const HEARTBEAT_INTERVAL = 5000; const STALE_TAB_TIMEOUT = 15000; const TAB_ID = `tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`; const LOAD_TIME = Date.now(); const PYODIDE_CDN = 'https://cdn.jsdelivr.net/pyodide/v0.25.1/full/pyodide.js'; const PyodideManager = { pyodide: null, isLoading: false, // NEW: Function to dynamically load Pyodide in the correct context loadPyodideDynamically() { return new Promise((resolve, reject) => { if (window.loadPyodide) { // Check if it's already loaded console.log('[Pyodide Loader] Already loaded.'); return resolve(window.loadPyodide); } const script = document.createElement('script'); script.src = PYODIDE_CDN; script.onload = () => { console.log('[Pyodide Loader] Script loaded successfully.'); resolve(window.loadPyodide); }; script.onerror = (err) => { console.error('[Pyodide Loader] Failed to load script from CDN.', err); reject(err); }; document.head.appendChild(script); }); }, async init() { if (this.pyodide || this.isLoading) return; this.isLoading = true; TriX_UI.log('Initializing Python runtime (Pyodide)... This may take a moment.', 'info'); try { const loadPyodide = await this.loadPyodideDynamically(); this.pyodide = await loadPyodide(); TriX_UI.log('Python runtime ready.', 'info'); } catch (err) { TriX_UI.log('Error loading Pyodide. Python features will be unavailable.', 'error'); console.error("Pyodide loading error:", err); } finally { this.isLoading = false; } }, async run(code, packages) { if (!this.pyodide) { await this.init(); if (!this.pyodide) return; } try { if (packages) { TriX_UI.log(`Loading Python packages: ${packages}`, 'info'); await this.pyodide.loadPackage("micropip"); const micropip = this.pyodide.pyimport("micropip"); await micropip.install(packages.split(',').map(p => p.trim())); TriX_UI.log('Packages loaded.', 'info'); } TriX_UI.log('Executing Python script...', 'info'); this.pyodide.setStdout({ batched: (msg) => TriX_UI.log(`[Python]: ${msg}`, 'log') }); this.pyodide.setStderr({ batched: (msg) => TriX_UI.log(`[Python]: ${msg}`, 'error') }); let result = await this.pyodide.runPythonAsync(code); if (result !== undefined) { TriX_UI.log(`Python script returned: ${result}`, 'info'); } } catch (err) { TriX_UI.log(`Python Error: ${err}`, 'error'); } } }; // --- The rest of the library is unchanged. --- const TabManager = { tabs:[], myTabInfo:{}, uiInitialized:false, isMaster:false, init(username){this.myTabInfo={id:TAB_ID,username:username,loadTime:LOAD_TIME,lastSeen:Date.now()};GM_addValueChangeListener(TAB_LIST_KEY,(name,old_value,new_value,remote)=>{if(remote)this.pruneAndRefresh(new_value)});this.register();setInterval(()=>this.register(),HEARTBEAT_INTERVAL);window.addEventListener('beforeunload',()=>this.unregister())}, async register(){let currentTabs=await GM_getValue(TAB_LIST_KEY,[]);const now=Date.now();currentTabs=currentTabs.filter(tab=>now-tab.lastSeen<STALE_TAB_TIMEOUT);this.myTabInfo.lastSeen=now;const myIndex=currentTabs.findIndex(tab=>tab.id===TAB_ID);if(myIndex>-1){currentTabs[myIndex]=this.myTabInfo}else{currentTabs.push(this.myTabInfo)}await GM_setValue(TAB_LIST_KEY,currentTabs);this.pruneAndRefresh(currentTabs)}, async unregister(){let currentTabs=await GM_getValue(TAB_LIST_KEY,[]);currentTabs=currentTabs.filter(tab=>tab.id!==TAB_ID);await GM_setValue(TAB_LIST_KEY,currentTabs)}, pruneAndRefresh(tabList){this.tabs=tabList;if(this.uiInitialized&&typeof TriX_UI!=='undefined')TriX_UI.updateTabCountUI(tabList.length);this.checkMasterStatus()}, checkMasterStatus(){this.isMaster=this.amIMaster();if(this.isMaster&&!this.uiInitialized){this.initUI()}}, amIMaster(){if(!this.myTabInfo.username||this.myTabInfo.username.startsWith('Guest_'))return true;const competingTabs=this.tabs.filter(tab=>tab.username===this.myTabInfo.username);if(competingTabs.length===0)return true;const earliestLoadTime=Math.min(...competingTabs.map(tab=>tab.loadTime));return this.myTabInfo.loadTime===earliestLoadTime}, initUI(){if(this.uiInitialized)return;console.log('[TriX Core] This tab is the master. Initializing UI.');this.uiInitialized=true;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(SCRIPT_PREFIX+e,t),TriX_UI.log(`Script '${e}' saved.`,"info"),this.populateScriptList(SCRIPT_PREFIX+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,""),s=e.replace(SCRIPT_PREFIX,"");document.getElementById("trix-editor").value=t,document.getElementById("trix-save-name").value=s,TriX_UI.log(`Loaded script: ${s}`,"info"),TriX_UI.currentScriptName=s,TriX_UI.setActiveScriptItem(e)},async deleteCurrentScript(){const e=TriX_UI.currentScriptName;e&&confirm(`Are you sure you want to delete '${e}'?`)&&(await GM_deleteValue(SCRIPT_PREFIX+e),TriX_UI.log(`Script '${e}' deleted.`,"info"),document.getElementById("trix-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 s=(await GM_listValues()).filter(e=>e.startsWith(SCRIPT_PREFIX));s.sort().forEach(e=>{const s=document.createElement("div");s.className="trix-script-item",s.textContent=e.replace(SCRIPT_PREFIX,""),s.dataset.scriptKey=e,t.appendChild(s)}),TriX_UI.setActiveScriptItem(e||TriX_UI.currentScriptName?SCRIPT_PREFIX+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(BROADCAST_CHANNEL,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_setValue(BROADCAST_CHANNEL,t),TriX_UI.log(`Broadcast sent: ${JSON.stringify(e)}`,"broadcast")}}; return { TabManager, ScriptManager, Executor, MultiTab, PyodideManager }; })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址