Twitch Drop Auto-Claim

Auto-Claims drops, while attempting to evade bot detection and claim quickly.

当前为 2023-05-27 提交的版本,查看 最新版本

// ==UserScript==
// @name         Twitch Drop Auto-Claim
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Auto-Claims drops, while attempting to evade bot detection and claim quickly. 
// @author       @Synthetic
// @license      MIT
// @match        https://www.twitch.tv/inventory
// @match        https://www.twitch.tv/drops/inventory
// @icon         https://www.google.com/s2/favicons?sz=64&domain=twitch.tv
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
    'use strict';

    const PROGRESS_BAR = 'div[data-a-target="tw-progress-bar-animation"]';
    const CLAIM_DROP = 'button.ScCoreButton-sc-ocjdkq-0.ScCoreButtonPrimary-sc-ocjdkq-1.dNGoHt.hdAxZi';
    const THIRTY_RATE = 18;

    const setTimer = (refresh) => {
        console.log('Setting refresh of', refresh, 'seconds');
        window.setTimeout(() => { window.location.reload(); }, refresh * 1000);
    }

    const claimDrop = () => {
        if (document.querySelector(CLAIM_DROP)) {
            document.querySelector(CLAIM_DROP).click();
            return true;
        }
        return false;
    }

    const onMutate = function(mutationsList) {
        mutationsList.forEach(mutation => {
            if (refresh == null) {
                const progress = document.querySelectorAll(PROGRESS_BAR);
                if (progress.length) {
                    clearTimeout(timeout);
                    var p = 0;
                    for (var i = 0; i < progress.length; i++) {
                        var v = progress[i].getAttribute('value');
                        if (v > p) {
                            p = v;
                        }
                    }
                    console.log('Progress', p);
                    if (p == 100) {
                        if (claimDrop()) {
                            console.log('Drop claimed!');
                            p = 0;
                            refresh = THIRTY_RATE * 100;
                            base = (new Date()).getTime();
                        } else {
                            refresh = THIRTY_RATE;
                        }
                    } else {
                        var rate;
                        if (previous) {
                            var increase = p - previous.progress;
                            rate = increase < 1 ? THIRTY_RATE : Math.ceil(interval / increase);
                        } else {
                            rate = THIRTY_RATE;
                        }
                        console.log('Rate', rate);
                        refresh = Math.min((100 - p) * rate, 3600);
                        console.log('Refresh', refresh);
                    }
                    GM_setValue(
                        'previous',
                        JSON.stringify({
                            base: base,
                            timestamp: (new Date()).getTime(),
                            progress: p
                        })
                    );
                    setTimer(refresh);
                }
            }
        })
    };

    console.log('Loaded at', new Date());

    var timeout;
    var refresh = null;
    var interval;
    var base;
    var previous = GM_getValue('previous');

    if (previous) {
        previous = JSON.parse(previous);
        base = previous.base;
        console.log('First read', new Date(previous.base));
        interval = ((new Date()).getTime() - previous.base) / 1000;
        console.log('Interval', interval);
        if (interval > 15000) {
            previous = false;
        }
    }

    if (!previous) {
        console.log('No read found');
        base = (new Date()).getTime();
    }

    timeout = window.setTimeout(
        () => {
            GM_setValue('previous', false);
            setTimer(100 * THIRTY_RATE);
        },
        10000
    );

    var observer = new MutationObserver(onMutate);
    observer.observe(document.body, {childList: true, subtree: true});

})();