Auto SBC Submitter (Manual Trigger)

Auto-submit SBCs on EA FC Web App after manual start with "[" and stop with "]"

// ==UserScript==
// @name         Auto SBC Submitter (Manual Trigger)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Auto-submit SBCs on EA FC Web App after manual start with "[" and stop with "]"
// @match        https://www.ea.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    var SBC_TILE_SELECTOR = null;

    let running = false;

    // Simulate a full user-like click with mouse events
    function simulateFullClick(element) {
        ['mousedown', 'mouseup', 'click'].forEach(eventType => {
            const event = new MouseEvent(eventType, {
                view: window,
                bubbles: true,
                cancelable: true,
                buttons: 1
            });
            element.dispatchEvent(event);
        });
    }

    // Wait for an element to appear on the page
    function waitForElement(selector, interval = 500, timeout = 15000) {
        return new Promise((resolve, reject) => {
            const start = Date.now();
            const timer = setInterval(() => {
                const el = document.querySelector(selector);
                if (el) {
                    clearInterval(timer);
                    resolve(el);
                } else if (Date.now() - start > timeout) {
                    clearInterval(timer);
                    reject(new Error(`Timeout waiting for element: ${selector}`));
                }
            }, interval);
        });
    }

    async function performSequence() {
        if (!running) return;

        try {
            console.log('Starting sequence');

            const sbcTile = await waitForElement(SBC_TILE_SELECTOR);
            simulateFullClick(sbcTile);
            console.log('SBC tile clicked');

            const buildBtn = await waitForElement('button#use-template.btn-standard');
            simulateFullClick(buildBtn);
            console.log('Build Using Template clicked');

            await new Promise(res => setTimeout(res, 10));

            const submitBtnSelector = 'button.ut-squad-tab-button-control.actionTab.right.call-to-action:not([disabled])';
            await waitForElement(submitBtnSelector);
            const submitBtn = document.querySelector(submitBtnSelector);
            simulateFullClick(submitBtn);
            console.log('Submit button clicked');

            await new Promise(res => setTimeout(res, 10));

            const claimBtnSelector = 'div.game-rewards-view footer > button.btn-standard.call-to-action';
            const claimBtn = await waitForElement(claimBtnSelector);
            simulateFullClick(claimBtn);
            console.log('Claim Rewards clicked');

            if (running) performSequence();

        } catch (err) {
            console.error('Error in sequence:', err.message);

            if (running) {
                setTimeout(performSequence, 1000);
            }
        }
    }

    // Listen for "[" to start and "]" to stop
    window.addEventListener('keydown', async (e) => {
        if (e.key === '[') {
            var submitButton = document.querySelector('button.ut-squad-tab-button-control.actionTab.right.call-to-action');
            if (!submitButton) {
                alert("SBC page not selected. Please click into an SBC and press '[' again");
                return;
            }
            var sbc_name = document.querySelector(".ut-navigation-bar-view .title")?.textContent.trim(); // pulls the SBC name
            // i need to go back first? ok
            const navBar = document.querySelector('div.ut-navigation-bar-view');
            if (navBar) {
                const backButton = navBar.querySelector('button.ut-navigation-button-control');
                if (backButton) {
                    simulateFullClick(backButton);
                    console.log("Clicked back button");
                } else {
                    console.log("back button not found");
                    return;
                }
            } else {
                console.log("Navbar not found");
                return;
            }
            console.log("before wait for fav button");
            await waitForElement('div.sbc-set--buttons'); // i need this to sleep until this button shows up
            console.log("Found favourite button");
            await new Promise(resolve => setTimeout(resolve, 3000));

            const h1s = document.querySelectorAll('h1.tileTitle');

            for (const h1 of h1s) {
                console.log("Looking for sbc: " + sbc_name);
                if (h1.textContent.trim() === sbc_name) {
                    var sbcTileElement = h1.closest('div.ut-sbc-set-tile-view');
                    console.log("SBC located");
                    if (sbcTileElement) {
                        const dataId = sbcTileElement.getAttribute('data-id');
                        console.log(dataId);
                        SBC_TILE_SELECTOR = `div.ut-sbc-set-tile-view[data-id="${dataId}"]`;
                    } else {
                         console.log("Where tf id");
                    }
                    break;
                }
            }
            if (!SBC_TILE_SELECTOR) {
                alert("SBC Could not be found");
                console.log("SBC not found");
                return;
            }
            if (!running) {
                running = true;
                console.log('Automation started');
                performSequence();
            }
        } else if (e.key === ']') {
            if (running) {
                running = false;
                console.log('Automation stopped');
            }
        }
    });

})();