Twitch Auto Click Channel Points Chest and Statistics

Automatically click the Twitch channel points chest, monitor all point increases, and reset the accumulated total when switching channels.

Установить этот скрипт?
Рекомендуемый автором скрипт

Вам также может понравится Twitch Screenshot Helper.

Установить этот скрипт
// ==UserScript==
// @name         Twitch Auto Click Channel Points Chest and Statistics
// @name:zh-TW   Twitch 自動點擊忠誠點數寶箱和統計
// @name:zh-CN   Twitch 自动点击忠诚点数宝箱和统计
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Automatically click the Twitch channel points chest, monitor all point increases, and reset the accumulated total when switching channels.
// @description:zh-TW 自動點擊 Twitch 忠誠點數寶箱,並監控所有點數增加,切換直播間累積歸零
// @description:zh-CN 自动点击 Twitch 忠诚点数宝箱,并监控所有点数增加,切换直播间累积归零
// @author       chatgpt
// @match        https://www.twitch.tv/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let totalPoints = 0;
    let lastUrl = location.href;
    const recentPopups = new Set();

    // 支援多語言與關鍵字的主按鈕尋找
    function findMainBtn() {
        // 常見關鍵字:點數、Points、忠誠、Channel Points
        return (
            document.querySelector('button[aria-label*="點數"]') ||
            document.querySelector('button[aria-label*="Points"]') ||
            document.querySelector('button[aria-label*="忠誠"]') ||
            document.querySelector('button[aria-label*="Channel"]')
        );
    }

    function createPanel() {
        const panel = document.createElement('span');
        panel.id = 'my-loyalty-points-panel';
        panel.style.background = '#18181b';
        panel.style.color = '#FFD600';
        panel.style.padding = '2px 8px';
        panel.style.marginLeft = '8px';
        panel.style.borderRadius = '8px';
        panel.style.fontSize = '14px';
        panel.style.verticalAlign = 'middle';
        panel.style.display = 'inline-block';
        panel.style.zIndex = 9999;
        panel.innerText = `累積領取:${totalPoints} 點`;
        return panel;
    }

    // 插入提示框到主按鈕的最後面
    function insertPanel() {
        const oldPanel = document.getElementById('my-loyalty-points-panel');
        if (oldPanel) oldPanel.remove();

        const mainBtn = findMainBtn();
        if (mainBtn) {
            if (!mainBtn.querySelector('#my-loyalty-points-panel')) {
                const panel = createPanel();
                mainBtn.appendChild(panel);
            }
        }
    }

    function updatePanel() {
        let panel = document.getElementById('my-loyalty-points-panel');
        if (!panel) {
            insertPanel();
            panel = document.getElementById('my-loyalty-points-panel');
        }
        if (panel) {
            panel.innerText = `累積領取:${totalPoints} 點`;
        }
    }

    function isInDialog(node) {
        while (node) {
            if (
                (node.getAttribute && node.getAttribute('role') === 'dialog') ||
                (node.classList && node.classList.contains('tw-modal'))
            ) {
                return true;
            }
            node = node.parentElement;
        }
        return false;
    }

    function checkAndClickChest() {
        const iconDivs = document.querySelectorAll('.claimable-bonus__icon');
        for (const iconDiv of iconDivs) {
            const btn = iconDiv.closest('button');
            if (
                btn &&
                !btn.disabled &&
                btn.offsetParent !== null &&
                !isInDialog(btn)
            ) {
                btn.click();
                return;
            }
        }
    }

    // 精準抓取浮動分數提示
    function handlePopupNode(node) {
        if (
            node.classList &&
            node.classList.contains('Layout-sc-1xcs6mc-0') &&
            node.classList.contains('bgzAOg')
        ) {
            for (const child of node.childNodes) {
                if (child.nodeType === Node.TEXT_NODE) {
                    const text = child.textContent.trim();
                    const match = text.match(/^\+(\d+)\s*點?$/);
                    if (match) {
                        const key = text + '_' + Date.now();
                        for (let k of recentPopups) {
                            if (k.startsWith(text)) return;
                        }
                        recentPopups.add(key);
                        setTimeout(() => recentPopups.delete(key), 1000);

                        const add = parseInt(match[1], 10);
                        if (!isNaN(add)) {
                            totalPoints += add;
                            updatePanel();
                        }
                    }
                }
            }
        }
    }

    // 監控所有新出現的 .Layout-sc-1xcs6mc-0.bgzAOg
    function observePointPopups() {
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (!(node instanceof HTMLElement)) continue;
                    if (
                        node.classList.contains('Layout-sc-1xcs6mc-0') &&
                        node.classList.contains('bgzAOg')
                    ) {
                        handlePopupNode(node);
                    }
                    // 也檢查所有子孫
                    node.querySelectorAll && node.querySelectorAll('.Layout-sc-1xcs6mc-0.bgzAOg').forEach(handlePopupNode);
                }
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    function watchUrlChange() {
        if (location.href !== lastUrl) {
            lastUrl = location.href;
            totalPoints = 0;
            updatePanel();
            recentPopups.clear();
        }
    }

    function main() {
        insertPanel();
        checkAndClickChest();
        watchUrlChange();
        observePointPopups();
        // 每秒自動補回提示框
        setInterval(() => {
            let panel = document.getElementById('my-loyalty-points-panel');
            if (!panel) insertPanel();
        }, 1000);
        // 其他定時任務
        setInterval(() => {
            checkAndClickChest();
            watchUrlChange();
        }, 1000);
    }

    window.addEventListener('load', () => setTimeout(main, 1500));
})();
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元