Car Specification for Torn Races

Replace specified texts on the Torn Racing page

目前為 2024-12-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Car Specification for Torn Races
// @namespace    http://tampermonkey.net/
// @version      1.10
// @description  Replace specified texts on the Torn Racing page
// @author       HangingLow
// @match        https://www.torn.com/loader.php?sid=racing*
// @grant        none
// @license GNU GPLv3
// ==/UserScript==
 
(function() {
    'use strict';
 
    ////////////////////////////////////////////////////////////////////////////////////
    // Change here to false, if you want to use old car names e.g. Ford, Lexus etc... //
    ////////////////////////////////////////////////////////////////////////////////////
    const useNewCarNames = true
 
    // Function to replace specified texts in the webpage
    function replaceMultipleOccurrences(targetTexts, replacementTexts) {
        // Check for valid input arrays
        if (targetTexts.length !== replacementTexts.length) {
            console.error("Target texts and replacement texts arrays must have the same length.");
            return;
        }
 
        // Create a regular expression for all target texts
        const regex = new RegExp(targetTexts.join('|'), 'g');
 
        // Function to replace text in the body
        function recursiveReplace(node) {
            if (node.nodeType === Node.TEXT_NODE) {
                // Check if the text node contains any of the target texts
                if (regex.test(node.textContent)) {
                    const originalText = node.textContent; // Keep original text for debug
                    node.textContent = node.textContent.replace(regex, (matched) => {
                        const index = targetTexts.indexOf(matched);
                        return index !== -1 ? replacementTexts[index] : matched;
                    });
                    console.log(`Replaced "${originalText}" with "${node.textContent}"`); // Debug log
                }
            } else {
                node.childNodes.forEach(recursiveReplace);
            }
        }
 
        // Start the replacement process from the body of the webpage
        const targetDivs = document.querySelectorAll('.title-black.top-round.t-overflow, .enlisted-btn-wrap');
        targetDivs.forEach(div => {
            recursiveReplace(div);
        });
    }
 
    // Arrays of texts to find and their replacements
    const targetTexts = [
        'Withdrawal',
        'Uptown',
        'Underdog',
        'Parkland',
        'Docks',
        'Commerce',
        'Two Islands',
        'Industrial',
        'Vector',
        'Mudpit',
        'Hammerhead',
        'Sewage',
        'Meltdown',
        'Speedway',
        'Stone Park',
        'Convict'
    ]; // Replace with actual target texts
 
    const originalCarNames = [
        'Withdrawl - (T) Lexus LFA (LR) (T3)',
        'Uptown - (T) Lamborghini Gallardo (LR) (T3)',
        'Underdog - (T) Honda NSX (SR) (T2)',
        'Parkland - (D) Honda NSX (SR) (T3)',
        'Docks - (T) Ford GT (LR) (T3)',
        'Commerce - (T) Honda NSX (SR) (T2)',
        'Two Islands - (D) Honda NSX (LR) (T3)',
        'Industrial - (T) Honda NSX (SR) (T3)',
        'Vector - (T) Honda NSX (SR) (T3)',
        'Mudpit - (D) Sierra Cosworth (LR) (T3)',
        'Hammerhead - (D) Honda NSX (SR) (T2)',
        'Sewage - (T) Honda NSX (SR) (T2)',
        'Meltdown - (T) Honda NSX (SR) (T3)',
        'Speedway - (T) Lexus LFA (LR) (T3)',
        'Stone Park - (D) Audi R8 (SR) (T3)',
        'Convict - (T) Mercedes SLR (LR) (T3)'
    ]; // Replace with actual replacement texts
 
    const newCarNames = [
        'Withdrawl - (T) Veloria LFA (LR) (T3)',
        'Uptown - (T) Lambrini Torobravo (LR) (T3)',
        'Underdog - (T) Edomondo NSX (SR) (T2)',
        'Parkland - (D) Edomondo NSX (SR) (T3)',
        'Docks - (T) Volt GT40 (LR) (T3)',
        'Commerce - (T) Edomondo NSX (SR) (T2)',
        'Two Islands - (D) Edomondo NSX (LR) (T3)',
        'Industrial - (T) Edomondo NSX (SR) (T3)',
        'Vector - (T) Edomondo NSX (SR) (T3)',
        'Mudpit - (D) Colina Tanprice (LR) (T3)',
        'Hammerhead - (D) Edomondo NSX (SR) (T2)',
        'Sewage - (T) Edomondo NSX (SR) (T2)',
        'Meltdown - (T) Edomondo NSX (SR) (T3)',
        'Speedway - (T) Veloria LFA (LR) (T3)',
        'Stone Park - (D) Echo R8 (SR) (T3)',
        'Convict - (T) Mercia SLR (LR) (T3)'
    ]; // Replace with actual replacement texts
 
    let replacementTexts;
    if (useNewCarNames) {
        replacementTexts = newCarNames;
    } else {
        replacementTexts = originalCarNames;
    }
 
    // Function to initialize the text replacement on load
    function init() {
        //console.log('Script initialized.'); // Log initialization
        replaceMultipleOccurrences(targetTexts, replacementTexts);
 
        // Set up MutationObserver to handle dynamic content changes
        const observer = new MutationObserver(() => {
            // Replace only if the text has not already been replaced
            const currentTexts = Array.from(document.body.childNodes).map(node => node.textContent);
            const hasAlreadyReplaced = currentTexts.some(text => replacementTexts.some(replacement => text.includes(replacement)));
 
            if (!hasAlreadyReplaced) {
                replaceMultipleOccurrences(targetTexts, replacementTexts);
            }
        });
 
        // Start observing the body for changes
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
 
        //console.log('MutationObserver is active.'); // Log observer activation
    }
 
    // Check if the DOM is fully loaded before running the script
    if (document.readyState === 'loading') {
        //console.log('Document is loading. Waiting for DOM to be ready...');
        document.addEventListener('DOMContentLoaded', init);
    } else {
        // DOM is ready, run the init function directly
        //console.log('Document is already loaded. Initializing...');
        init();
    }
})();