ValorantDropFarmer

Farm twitch drops automatically from your browser

// ==UserScript==
// @name         ValorantDropFarmer
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Farm twitch drops automatically from your browser
// @author       dinglemyberry#6969
// @match        https://www.twitch.tv/*
// @match        https://player.twitch.tv/*
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==

//Settings DO NOT CHANGE
var clientId = '9nksyt83rj58cafwa8m9nkxb9c5qjq';
//Set the id Twitch uses for the game, for Valorant
var gameId = '516575';
//url for getting first 30 english streams of the game specified in gameId from the Twitch API
var gameStreams = 'https://api.twitch.tv/helix/streams?first=30&language=en&game_id=' + gameId;
var cs = 'current_streamer';
var cg = 'current_game';
var autoRun = true;
var retries = -1; // Amount of cycles to try and load your points balance before giving up.

//Actual Valorant Drops (Finding Valorant Streams & Getting new stream when one goes offline)
(function() {
    'use strict';
    var nbForReload = 0;

    function getHttp(url) {
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open('GET', url, false);
        xmlHttp.setRequestHeader('Client-ID', clientId);
        xmlHttp.send()
        return JSON.parse(xmlHttp.responseText);
    }

    function tmGet(name) {
        let val = GM_getValue(name);
        if(typeof val == 'undefined') {
            val = '';
        }
        return val;
    }

    function tmSet(name, value) {
        let val = value;
        if(typeof value == 'undefined') {
            val = '';
        }
        GM_setValue(name, val);
    }

    function farmTwitch() {
        console.log(tmGet(cs));
        var streamerName = '';
        //Test if we have a valid streamer saved in TamperMonkey's variable
        if (tmGet(cs) && tmGet(cs) != '') {
            let url = 'https://api.twitch.tv/helix/streams?user_id=' + tmGet(cs);
            let stream = getHttp(url).data;
            console.log(stream);
            if(stream[0] && stream[0].type == 'live') {
                //get the variable game_id which comes from the Twitch API response
                tmSet(cg, stream[0].game_id);
                streamerName = stream[0].user_name;
                console.log(stream[0])
                console.log('this is the current game:' + tmGet(cg));
            } else {
                tmSet(cs, '');
                tmSet(cg, '');
            }
        } else {
            tmSet(cg, '');
        }

        var locationWrong = false;

        if ('/' + streamerName != window.location.pathname) {
            locationWrong = true;
            console.log('location is wrong')
        }

        if (tmGet(cg) != gameId || locationWrong) {
            // choose a streamer
            var streams = getHttp(gameStreams).data;
            if (streams) {
                console.log(streams);
                var validStreams = [];

                for(var i=0; i < streams.length; i++) {
                    let viewerCount = streams[i].viewer_count;

                    if(viewerCount > 100) {
                        validStreams.push(streams[i]);
                    }
                }

                if(validStreams.length) {
                    // define random number from valid streams
                    let rnd = Math.floor(Math.random() * validStreams.length);
                    let sid = validStreams[rnd].user_id;
                    tmSet(cs, sid);
                    console.log('Valid stream is: ' + sid);
                    window.location = 'https://www.twitch.tv/' + validStreams[rnd].user_name;
                } else {
                    // go to the second streamer, if everything was filtered out or the first one if only one stream
                    let mini = Math.min(1, streams.length-1);
                    tmSet(cs, validStreams[mini].user_id);
                    console.log('No valid streams');
                    window.location = 'https://www.twitch.tv/' + streams[mini].user_name;
                }
            }
        } else {
            // reload page every 6th check or about 10 min, since we don't check for errors in the stream
            nbForReload++;
            if(nbForReload >= 6) {
                location.reload();
            } else {
                setTimeout(function(){ location.reload(); }, 600*1000);
            }
        }
    }
    setTimeout(farmTwitch, 1000*10);
})();

//Twitch Channel Points AutoClaiming
var balance = -1;
var balanceSet = false;
(function() {
    console.log(timeString() + " [CPA] Begin ChannelPoints Autoclaim by Evanito.");
    if (autoRun) {
        console.log(timeString() + " [CPA] Running...");
        run();
    }
})();

function run() {
    clickChest();
    var oldBalance = balance;
    balance = getBalance();
    if (balance > -1) {balanceSet = true; retries = 999;}
    if (balance != oldBalance && oldBalance != -1) {
        console.log(timeString() + " [CPA] Balance has changed by: " + (balance - oldBalance));
    }
    if (retries-- > 0 || retries < -1) {
        setTimeout(function(){ run(); }, 5000);
    } else {
        console.log(timeString() + " [CPA] No channel points found. Shutting down.");
    }
}

function clickChest() {
    var plays = document.getElementsByClassName("claimable-bonus__icon");
    for (var i = 0; i < plays.length; i++) {
        plays[i].click();
        console.log(timeString() + " [CPA] Clicked a bonus chest.");
    }
}

function getBalance() { // Returns user's balance as int, or -1 if cannot be found yet.
    var balances = document.getElementsByClassName("tw-tooltip tw-tooltip--align-center tw-tooltip--right");
    var balance = -1;
    if (balances.length >= 3) { // For some reason, the balances div is always third, unless it hasn't loaded.
        try {
            var balanceHTML = balances[2].innerHTML;
            var patt = /\d*,?\d*/;
            var balanceRegEx = patt.exec(balanceHTML)[0];
            balance = parseInt(balanceRegEx.replace(",", ""));
        } catch(err) {
            console.log(timeString() + " [CPA] Couldn't find balance, err: " + err);
        }
    }
    return balance;
}

function getRewards() { // WIP: get objects for each of the rewards for further processing.
    try {
    var rewardBox = document.getElementsByClassName("rewards-list");
    if (rewardBox.length >= 1) {
        var rewards = rewardBox[0].getElementsByClassName("reward-list-item");
        return rewards; // Outputs an array of the reward HTML objects, need to clean this up.
    }
    return -1;
    } catch(err) {
        console.log(timeString() + " [CPA] Error getting channel's rewards. Err: " + err);
        return -1;
    }
}

function timeString() {
    let d = new Date();
    let h = (d.getHours()<10?'0':'') + d.getHours();
    let m = (d.getMinutes()<10?'0':'') + d.getMinutes();
    let s = (d.getSeconds()<10?'0':'') + d.getSeconds();
    let dstr = h + ':' + m + ":" + s;
    return dstr;
}

//Tricking Twitch to think that the stream is never tabbed off
// Try to trick the site into thinking it's never hidden
Object.defineProperty(document, 'hidden', {value: false, writable: false});
Object.defineProperty(document, 'visibilityState', {value: 'visible', writable: false});
Object.defineProperty(document, 'webkitVisibilityState', {value: 'visible', writable: false});
document.dispatchEvent(new Event('visibilitychange'));
document.hasFocus = function () { return true; };

// visibilitychange events are captured and stopped
document.addEventListener('visibilitychange', function(e) {
	e.stopImmediatePropagation();
}, true, true);

// Set the player quality to "Source"
window.localStorage.setItem('s-qs-ts', Math.floor(Date.now()));
window.localStorage.setItem('video-quality', '{"default":"chunked"}');

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址