xd2shuffle

Visual larp: Changes ARS to $ everywhere (bets, balance, everything) - keeps numbers the same

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         xd2shuffle
// @namespace    http://tampermonkey.net/
// @version      7.7.8.1
// @description  Visual larp: Changes ARS to $ everywhere (bets, balance, everything) - keeps numbers the same
// @author       fusi | @loficat on tg | codedfusi on github
// @match        *://*.shuffle.com/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
    const processedTextNodes = new WeakSet();
    const processedImages = new WeakSet();

    // Force update a text node
    function updateTextNode(node) {
        if (node.nodeType !== 3 || !node.nodeValue) return false;
        
        let original = node.nodeValue;
        let newValue = original;
        let changed = false;

        // Replace ARS with $ (case insensitive just in case)
        if (newValue.includes("ARS")) {
            newValue = newValue.replace(/ARS/g, "$");
            changed = true;
        }
        
        // Replace lowercase "ars" if it appears
        if (newValue.includes("ars")) {
            newValue = newValue.replace(/ars/g, "$");
            changed = true;
        }

        // Remove space after the new $
        if (changed) {
            newValue = newValue.replace(/\$\s+/g, '$');
        }

        if (changed && newValue !== original) {
            node.nodeValue = newValue;
            return true;
        }
        return false;
    }

    function processTextNode(node) {
        if (node.nodeType === 3 && node.nodeValue && !processedTextNodes.has(node)) {
            if (updateTextNode(node)) {
                processedTextNodes.add(node);
            }
        }
    }

    function processImageElement(el) {
        if (el.nodeType === 1 && el.hasAttribute("src") && !processedImages.has(el)) {
            const src = el.getAttribute("src");
            if (src && src.includes("/icons/fiat/ARS.svg")) {
                el.setAttribute("src", src.replace("/icons/fiat/ARS.svg", "/icons/fiat/USD.svg"));
                processedImages.add(el);
            }
        }
    }

    function walkAndProcess(root) {
        if (!root) return;

        // Process all text nodes
        const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
        let node;
        while ((node = walker.nextNode())) {
            processTextNode(node);
        }

        // Process all ARS flag images
        const images = root.querySelectorAll('img[src*="/icons/fiat/ARS.svg"]');
        images.forEach(img => processImageElement(img));
    }

    // More aggressive mutation handling
    function onMutation(mutations) {
        let needsFullScan = false;
        
        for (const mutation of mutations) {
            // If attributes changed (like a bet amount updating), scan the target
            if (mutation.type === 'attributes') {
                if (mutation.target.nodeType === 1) {
                    // Re-scan this element and its children
                    walkAndProcess(mutation.target);
                    // Also scan its parent in case the change bubbled
                    if (mutation.target.parentNode) {
                        walkAndProcess(mutation.target.parentNode);
                    }
                }
                needsFullScan = true;
            }
            
            // If child nodes were added, process them
            if (mutation.type === 'childList') {
                for (const addedNode of mutation.addedNodes) {
                    if (addedNode.nodeType === 1) {
                        walkAndProcess(addedNode);
                    } else if (addedNode.nodeType === 3) {
                        processTextNode(addedNode);
                    }
                }
                needsFullScan = true;
            }
            
            // If text itself changed (characterData mutation)
            if (mutation.type === 'characterData') {
                if (mutation.target.nodeType === 3) {
                    // Re-process this text node even if it was processed before
                    const node = mutation.target;
                    if (node.nodeValue && (node.nodeValue.includes("ARS") || node.nodeValue.includes("ars"))) {
                        updateTextNode(node);
                    }
                }
                needsFullScan = true;
            }
        }
        
        // Do a quick partial scan of the body periodically to catch anything missed
        if (needsFullScan) {
            setTimeout(() => {
                // Scan the whole body but skip nodes we've already processed to save performance
                const allTextNodes = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
                let tn;
                while ((tn = allTextNodes.nextNode())) {
                    if (tn.nodeValue && (tn.nodeValue.includes("ARS") || tn.nodeValue.includes("ars"))) {
                        if (updateTextNode(tn)) {
                            processedTextNodes.add(tn);
                        }
                    }
                }
            }, 100);
        }
    }

    // Start when DOM is ready
    document.addEventListener("DOMContentLoaded", () => {
        walkAndProcess(document.body);

        // Watch for attribute changes (like bet amounts), text changes, AND child lists
        const observer = new MutationObserver(onMutation);
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,      // <-- CRITICAL: catches bet amount updates
            attributeFilter: ['textContent', 'innerHTML', 'value'], // Focus on text-related attributes
            characterData: true    // <-- CRITICAL: catches direct text changes
        });
        
        // Also run every second as a backup (heavy but ensures bets get caught)
        setInterval(() => {
            const allTextNodes = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
            let tn;
            while ((tn = allTextNodes.nextNode())) {
                if (tn.nodeValue && (tn.nodeValue.includes("ARS") || tn.nodeValue.includes("ars"))) {
                    updateTextNode(tn);
                }
            }
        }, 1000);
    });
})();