TriX Core Library

Core logic library for the TriX Executor. Not intended for direct installation.

Този скрипт не може да бъде инсталиран директно. Това е библиотека за други скриптове и може да бъде използвана с мета-директива // @require https://update.greasyfork.org/scripts/541461/1663259/TriX%20Core%20Library.js

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name        TriX Core Library
// @namespace   https://github.com/COURTESYCOIL/TriX-Executor
// @version     2.4.0a
// @description Core logic library for TriX Executor.
// @author      Painsel
// @license     MIT
// ==/UserScript==

const TriX_Core = (function() {
    'use strict';
    let _GM; 

    const TabManager = { /* ... (unchanged) ... */ };
    const ScriptManager = {
        async saveScriptFromEditor() {
            const name = document.getElementById("trix-save-name").value.trim();
            // Get content from CodeMirror instances via the UI library
            const jsCode = TriX_UI.jsEditor.state.doc.toString();
            const pyCode = TriX_UI.pyEditor.state.doc.toString();
            
            if (!name) return TriX_UI.log("Cannot save: Name is required.", "error");
            if (!jsCode && !pyCode) return TriX_UI.log("Cannot save: Both editors are empty.", "warn");
            
            const scriptData = JSON.stringify({ js: jsCode, py: pyCode });
            await _GM.GM_setValue(`trix_script_${name}`, scriptData);
            
            TriX_UI.log(`Script '${name}' saved.`, "info");
            this.populateScriptList();
        },
        async loadScriptToEditor(key) {
            if (!key) return TriX_UI.log("Invalid script key.", "error");
            const scriptJSON = await _GM.GM_getValue(key, "{}");
            const name = key.replace("trix_script_", "");
            try {
                const scriptData = JSON.parse(scriptJSON);
                const jsEditor = TriX_UI.jsEditor;
                const pyEditor = TriX_UI.pyEditor;

                // Use CodeMirror's transaction system to update the content
                jsEditor.dispatch({ changes: { from: 0, to: jsEditor.state.doc.length, insert: scriptData.js || "" } });
                pyEditor.dispatch({ changes: { from: 0, to: pyEditor.state.doc.length, insert: scriptData.py || "" } });

                document.getElementById("trix-save-name").value = name;
                TriX_UI.log(`Loaded script: ${name}`, "info");
                TriX_UI.currentScriptName = name;
                TriX_UI.setActiveScriptItem(key);
            } catch (e) {
                TriX_UI.log("Error loading script data.", "error");
            }
        },
        async deleteCurrentScript() { /* ... (unchanged) ... */ },
        async populateScriptList() { /* ... (unchanged) ... */ }
    };
    const Executor = { /* ... (unchanged) ... */ };
    const MultiTab = { /* ... (unchanged) ... */ };
    
    function init(username, gmFunctions) {
        _GM = gmFunctions;
        TabManager.init(username);
    }
    
    // Minified unchanged code for brevity
    TabManager.init=function(e){this.myTabInfo={id:`tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`,username:e,loadTime:Date.now(),lastSeen:Date.now()};_GM.GM_addValueChangeListener("trix_active_tabs",(e,t,i,s)=>{s&&this.pruneAndRefresh(i)});this.register();setInterval(()=>this.register(),5e3);window.addEventListener("beforeunload",()=>this.unregister())},TabManager.register=async function(){let e=await _GM.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.GM_setValue("trix_active_tabs",e),this.pruneAndRefresh(e)},TabManager.unregister=async function(){let e=await _GM.GM_getValue("trix_active_tabs",[]);e=e.filter(e=>e.id!==this.myTabInfo.id),await _GM.GM_setValue("trix_active_tabs",e)},TabManager.pruneAndRefresh=function(e){this.tabs=e,this.uiInitialized&&TriX_UI.updateTabCountUI(e.length),this.checkMasterStatus()},TabManager.checkMasterStatus=function(){this.isMaster=this.amIMaster(),this.isMaster&&!this.uiInitialized&&this.initUI()},TabManager.amIMaster=function(){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))},TabManager.initUI=function(){this.uiInitialized||(console.log("[TriX Core] This tab is the master. Initializing UI."),this.uiInitialized=!0,TriX_UI.init(_GM))};
    ScriptManager.deleteCurrentScript=async function(){const e=TriX_UI.currentScriptName;e&&confirm(`Are you sure you want to delete '${e}'?`)&&(await _GM.GM_deleteValue(`trix_script_${e}`),TriX_UI.log(`Script '${e}' deleted.`,"info"),TriX_UI.jsEditor.dispatch({changes:{from:0,to:TriX_UI.jsEditor.state.doc.length,insert:""}}),TriX_UI.pyEditor.dispatch({changes:{from:0,to:TriX_UI.pyEditor.state.doc.length,insert:""}}),document.getElementById("trix-save-name").value="",TriX_UI.currentScriptName="",this.populateScriptList())},ScriptManager.populateScriptList=async function(e=null){const t=document.getElementById("trix-script-list");t.innerHTML="";const i=(await _GM.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)};
    Executor.executeJS=function(e){if(!e.trim())return TriX_UI.log("JS Execution skipped: script is empty.","warn");TriX_UI.log("Executing JavaScript...","info");try{const t=this.createAPI(),i=new Function("TriX",e);i(t)}catch(e){TriX_UI.log(`JavaScript Error: ${e.message}`,"error"),console.error("TriX Executor JS Error:",e)}},Executor.executePY=function(e){if(!e.trim())return TriX_UI.log("Python Execution skipped: script is empty.","warn");if("undefined"==typeof Sk)return TriX_UI.log("Skulpt not loaded. Cannot run Python.","error");TriX_UI.log("Executing Python via Skulpt...","info"),Sk.configure({output:e=>{e.trim()&&TriX_UI.log(`[Python]: ${e.trim()}`,"log")},read:function(e){if(void 0===Sk.builtinFiles||void 0===Sk.builtinFiles.files[e])throw"File not found: '"+e+"'";return Sk.builtinFiles.files[e]}}),Sk.misceval.asyncToPromise(()=>Sk.importMainWithBody("<stdin>",!1,e,!0)).then(e=>{TriX_UI.log("Skulpt script finished.","info")}).catch(e=>{TriX_UI.log(e.toString(),"error")})},Executor.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)}});
    MultiTab.init=function(e){_GM=e;const t=`tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`;this.TAB_ID=t,_GM.GM_addValueChangeListener("trix_broadcast_channel",this.listener.bind(this))},MultiTab.listener=function(e,t,i,s){s&&i.senderId!==this.TAB_ID&&TriX_UI.log(`Received broadcast: ${JSON.stringify(i.payload)}`,"broadcast")},MultiTab.broadcast=function(e){const t={senderId:this.TAB_ID,timestamp:Date.now(),payload:e};_GM.GM_setValue("trix_broadcast_channel",t),TriX_UI.log(`Broadcast sent: ${JSON.stringify(e)}`,"broadcast")};

    return { init, ScriptManager, Executor, MultiTab };
})();