Este script não deve ser instalado diretamente. Este script é uma biblioteca de outros scripts para incluir com o diretório meta // @require https://update.greasyforks.org/scripts/541461/1618726/TriX%20Core%20Library.js
// ==UserScript==
// @name TriX Core Library
// @namespace https://github.com/YourUsername/TriX-Executor
// @version 1.6.5
// @description Core logic library for TriX Executor with Python/WASM support and progress feedback.
// @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_BASE = 'https://cdn.jsdelivr.net/pyodide/v0.25.1/full/';
const PyodideManager = {
pyodide: null,
isLoading: false,
loadPyodideDynamically() {
// No changes needed here, the previous version is correct.
return new Promise((resolve, reject) => {
if (window.loadPyodide) return resolve(window.loadPyodide);
const script = document.createElement('script');
script.src = `${PYODIDE_CDN_BASE}pyodide.js`;
script.onload = () => {
const checkInterval = setInterval(() => {
if (window.loadPyodide) {
clearInterval(checkInterval);
resolve(window.loadPyodide);
}
}, 100);
};
script.onerror = (err) => reject(new Error("Failed to load Pyodide script from CDN. Check browser console for network errors."));
document.head.appendChild(script);
});
},
// --- NEW: Enhanced init function with progress bar ---
async init() {
if (this.pyodide || this.isLoading) return;
this.isLoading = true;
TriX_UI.setPythonStatus('loading');
TriX_UI.log('Initializing Python runtime (Pyodide)...', 'info');
TriX_UI.log('Note: First-time setup is a large download (~35MB). It will be cached for future use.', 'warn');
// Create and append the progress bar element to the console
const progressElement = TriX_UI.createProgressBar();
try {
const loadPyodideFunction = await this.loadPyodideDynamically();
this.pyodide = await loadPyodideFunction({
indexURL: PYODIDE_CDN_BASE,
// This hook provides live updates on the loading process
loadPackageMessageCallback: (message) => {
const progressText = document.getElementById('trix-py-progress-text');
if (progressText) {
progressText.textContent = `Loading: ${message}`;
}
}
});
progressElement.remove(); // Remove progress bar on success
TriX_UI.log('Python runtime ready.', 'info');
TriX_UI.setPythonStatus('ready');
} catch (err) {
if(progressElement) progressElement.remove();
TriX_UI.setPythonStatus('error');
TriX_UI.log(`Error loading Pyodide: ${err.message}. Python features will be unavailable.`, 'error');
console.error("Pyodide loading error:", err);
} finally {
this.isLoading = false;
}
},
async run(code, packages) {
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 packageList = packages.split(',').map(p => p.trim()).filter(p => p);
TriX_UI.log(`Loading Python packages: ${packageList.join(', ')}`, 'info');
await this.pyodide.loadPackage("micropip");
const micropip = this.pyodide.pyimport("micropip");
await micropip.install(packageList);
TriX_UI.log('Packages loaded.', 'info');
}
TriX_UI.log('Executing Python script...', 'info');
this.pyodide.setStdout({ batched: (msg) => TriX_UI.log(`${msg}`, 'log') });
this.pyodide.setStderr({ batched: (msg) => TriX_UI.log(`[Python Error]: ${msg}`, 'error') });
await this.pyodide.runPythonAsync(code);
} catch (err) {
TriX_UI.log(`Python Error: ${err}`, 'error');
} finally {
TriX_UI.setPythonStatus('ready');
}
}
};
// --- The rest of the library is unchanged and minified for brevity ---
const TabManager={tabs:[],myTabInfo:{},uiInitialized:!1,isMaster:!1,init(e){this.myTabInfo={id:TAB_ID,username:e,loadTime:LOAD_TIME,lastSeen:Date.now()},GM_addValueChangeListener(TAB_LIST_KEY,(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(TAB_LIST_KEY,[]);const t=Date.now();e=e.filter(e=>t-e.lastSeen<15e3),this.myTabInfo.lastSeen=t;const i=e.findIndex(e=>e.id===TAB_ID);-1<i?e[i]=this.myTabInfo:e.push(this.myTabInfo),await GM_setValue(TAB_LIST_KEY,e),this.pruneAndRefresh(e)},async unregister(){let e=await GM_getValue(TAB_LIST_KEY,[]);e=e.filter(e=>e.id!==TAB_ID),await GM_setValue(TAB_LIST_KEY,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(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,""),i=e.replace(SCRIPT_PREFIX,"");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(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 i=(await GM_listValues()).filter(e=>e.startsWith(SCRIPT_PREFIX));i.sort().forEach(e=>{const i=document.createElement("div");i.className="trix-script-item",i.textContent=e.replace(SCRIPT_PREFIX,""),i.dataset.scriptKey=e,t.appendChild(i)}),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 };
})();