NextUp.Game Enhancer

Shows the names of the streamers for each clip on NextUp Game voting page

目前為 2024-10-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         NextUp.Game Enhancer
// @namespace    PrimeMinister
// @version      1.0
// @description  Shows the names of the streamers for each clip on NextUp Game voting page
// @author       Kier
// @match        https://nextup.game/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    function getStreamerInfo() {
        const scriptTag = document.querySelector('#__NEXT_DATA__');
        if (!scriptTag) return {};

        const jsonData = JSON.parse(scriptTag.textContent);
        const streamers = jsonData?.props?.pageProps?.event?.streamers;
        if (!streamers) return {};

        return streamers.reduce((acc, streamer) => {
            acc[streamer.id] = streamer.kick_username;
            return acc;
        }, {});
    }

    function addStreamerNames(streamer1, streamer2) {
        const targetDiv = document.querySelector('.space-y-4');
        if (!targetDiv) return;

        if (document.querySelector('.streamer-info')) return;

        const streamerInfoDiv = document.createElement('div');
        streamerInfoDiv.className = 'text-center text-lg font-bold mt-2 streamer-info';
        streamerInfoDiv.textContent = `${streamer1} vs ${streamer2}`;

        targetDiv.appendChild(streamerInfoDiv);
    }

    async function fetchClipData(streamerInfo) {
        try {
            const response = await fetch('https://api.nextup.game/v1/votes/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                credentials: 'include'
            });
            const data = await response.json();
            if (data.success && data.data && data.data.clips) {
                const clipA = data.data.clips.a;
                const clipB = data.data.clips.b;

                const streamer1 = streamerInfo[clipA.streamer_id] || 'Unknown Streamer 1';
                const streamer2 = streamerInfo[clipB.streamer_id] || 'Unknown Streamer 2';

                addStreamerNames(streamer1, streamer2);
            }
        } catch (error) {
            console.error('Error fetching clip data:', error);
        }
    }

    function main() {
        const streamerInfo = getStreamerInfo();
        if (Object.keys(streamerInfo).length > 0) {
            fetchClipData(streamerInfo);
        }
    }

    function observePageChanges() {
        const targetNode = document.querySelector('body');
        const config = { childList: true, subtree: true };

        const callback = function (mutationsList) {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    if (!document.querySelector('.streamer-info') && window.location.pathname === '/vote') {
                        setTimeout(main, 1000);
                    }
                }
            }
        };

        const observer = new MutationObserver(callback);
        if (targetNode) {
            observer.observe(targetNode, config);
        }
    }

    function observeUrlChanges() {
        let lastPathname = window.location.pathname;
        setInterval(() => {
            if (window.location.pathname !== lastPathname) {
                lastPathname = window.location.pathname;
                if (lastPathname === '/vote') {
                    main();
                    observePageChanges();
                }
            }
        }, 500);
    }

    setTimeout(() => {
        if (window.location.pathname === '/vote') {
            main();
            observePageChanges();
        }
        observeUrlChanges();
    }, 1500);
})();