Skip to content

Instantly share code, notes, and snippets.

@kldzj
Last active December 29, 2021 19:54
Show Gist options
  • Select an option

  • Save kldzj/bacf30f50d3264d1245c8ab4af8e9262 to your computer and use it in GitHub Desktop.

Select an option

Save kldzj/bacf30f50d3264d1245c8ab4af8e9262 to your computer and use it in GitHub Desktop.
Automatically watch the next best EFT stream with drops enabled and claim said drops

EFT Drop Stream Guide

Once you've got the Guide script running, you'll see a white button on the bottom left on twitch.tv. Clicking it enables the Drop Guide, which automatically navigates to the next best stream that has drops enabled. The extension will only guide you within tabs you enabled it in.

Twitch Drop Taker

The drop taker is enabled on the Twitch Drop Inventory Page and automatically claims every available drop.

Installation

You can run these scripts in your browser using Tampermonkey or similar tools. Once you've got Tampermonkey installed, you can click the Raw button above the scripts to view the installation page.

Make sure to open two tabs (the two Twitch links above) and activate the Drop Stream Guide using the button on the bottom left.

// ==UserScript==
// @name EFT Drop Stream Guide
// @namespace https://kldzj.dev
// @version 0.1.1
// @description Automatically navigate to the next best stream during EFT Christmas Drops
// @author kldzj
// @include /^https:\/\/(www\.)?twitch\.tv\/([a-zA-Z0-9_]*)?$/
// @exclude /^https:\/\/(www\.)?twitch\.tv\/drops/
// @exclude /^https:\/\/(www\.)?twitch\.tv\/settings/
// @icon https://www.google.com/s2/favicons?domain=twitch.tv
// @downloadURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-guide.user.js
// @installURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-guide.user.js
// @updateURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-guide.user.js
// @grant GM_getTab
// @grant GM_saveTab
// ==/UserScript==
const dropsEnabledTag = 'c2542d6d-cd10-4532-919b-3d19f30a768b';
function __getTab() {
return new Promise(resolve => GM_getTab(resolve));
}
async function __setTab(data) {
const current = await __getTab();
GM_saveTab({ ...current, ...data });
}
function getTwitchToken() {
const t = document.cookie.match(/(?:^|; )auth-token=([^;]*)/);
return t[1] || '';
}
async function fetchOnlineStreams() {
const response = await fetch('https://gql.twitch.tv/gql', {
method: 'post',
headers: {
Authorization: `OAuth ${getTwitchToken()}`
},
body: JSON.stringify([{
operationName: "DirectoryPage_Game",
extensions: {
persistedQuery: {
sha256Hash: "d5c5df7ab9ae65c3ea0f225738c08a36a4a76e4c6c31db7f8c4b8dc064227f9e",
version: 1
}
},
variables: {
name: "escape from tarkov",
sortTypeIsRecency: false,
limit: 100,
options: {
sort: "RELEVANCE",
includeRestricted: ["SUB_ONLY_LIVE"],
tags: [dropsEnabledTag]
}
}
}])
});
if (!response.ok) {
throw new Error('Failed to fetch online streams!');
}
const result = await response.json();
if (!result[0] || !result[0].data) {
throw new Error('Invalid streams response!');
}
return result[0].data.game.streams.edges.map(({ node }) => node);
}
function getCurrentStream() {
const [_, __, match] = window.location.href.match(/https?:\/\/(www\.)?twitch.tv\/([a-z0-9_]*)/i);
if (!match || match === '') return null;
return match;
}
function getFirstStreamBroadcaster(streams) {
return streams.find(stream => stream.type === 'live').broadcaster.login;
}
async function addButton() {
const btn = document.createElement('button');
const baseStyle = 'position:fixed;bottom:5px;left:8px;background:white;border-radius:2px;padding:2px 5px;z-index:99999;';
const styles = {
active: 'color:green',
inactive: 'color:red'
};
const texts = {
active: 'Guiding...',
inactive: 'Guide Me'
};
const { guiding } = await __getTab();
btn.innerText = guiding ? texts.active : texts.inactive;
btn.style = baseStyle + (guiding ? styles.active : styles.inactive);
btn.onclick = async (e) => {
e.preventDefault();
const { guiding: active } = await __getTab();
if (active) {
await __setTab({ guiding: false });
btn.innerText = texts.inactive;
btn.style = baseStyle + styles.inactive;
} else {
await __setTab({ guiding: true });
btn.innerText = texts.active;
btn.style = baseStyle + styles.active;
await handler();
}
};
document.getElementsByTagName('body')[0].appendChild(btn);
}
async function handler() {
const { guiding } = await __getTab();
if (!guiding) return console.log('Currently not guiding...');
const currentStream = getCurrentStream();
const streams = await fetchOnlineStreams();
if (!currentStream || !streams.find(({ broadcaster }) => broadcaster.login.toLowerCase() === currentStream)) {
const newStream = getFirstStreamBroadcaster(streams);
console.log(`Current stream is none or offline, sending you to ${newStream}`);
window.location.href = `https://twitch.tv/${newStream}`;
return;
}
console.log('You should still be receiving drop progress...');
}
let initialized = false;
async function initialize() {
if (initialized) return;
await addButton();
setInterval(handler, 1 * 60 * 1000);
initialized = true;
console.log('EFT Drop Stream Guide loaded...');
await handler();
}
initialize().catch(e => console.error(e));
// ==UserScript==
// @name Twitch Drop Taker
// @namespace https://kldzj.dev
// @version 0.1
// @description Automatically claim drops on the Twitch Drop Inventory page
// @author kldzj
// @match https://www.twitch.tv/drops/inventory
// @icon https://www.google.com/s2/favicons?domain=twitch.tv
// @downloadURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-taker.user.js
// @installURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-taker.user.js
// @updateURL https://gist.github.com/kldzj/bacf30f50d3264d1245c8ab4af8e9262/raw/eft-drop-taker.user.js
// @grant none
// ==/UserScript==
const claimButton = '[data-test-selector="DropsCampaignInProgressRewardPresentation-claim-button"]';
(function() {
'use strict';
const onMutate = (mutations) => mutations.forEach(_ => {
if (document.querySelector(claimButton)) {
console.log('Trying to claim drop...');
document.querySelector(claimButton).click();
}
});
const observer = new MutationObserver(onMutate);
observer.observe(document.body, { childList: true, subtree: true });
setInterval(() => {
console.log('Twitch Drop Taker is reloading...');
window.location.reload();
}, 2 * 60 * 1000);
console.log('Twitch Drop Taker is active...');
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment