From e61d24a2622ca8405a45e94b6106d5d20008f980 Mon Sep 17 00:00:00 2001 From: Donnie <43322006+dclstn@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:01:05 +0000 Subject: [PATCH] refactor auto-claim drops (#6560) * refactor auto-claim drops * use twitch pubsub * fix * fix 2 * ensure precoditions are met --- src/modules/auto_claim/index.js | 106 ++++++++++++------ .../components/settings/twitch/AutoClaim.jsx | 2 +- 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/src/modules/auto_claim/index.js b/src/modules/auto_claim/index.js index 14a1e299cc..0357dd469b 100644 --- a/src/modules/auto_claim/index.js +++ b/src/modules/auto_claim/index.js @@ -1,59 +1,99 @@ -import debounce from 'lodash.debounce'; +import gql from 'graphql-tag'; import {AutoClaimFlags, PlatformTypes, SettingIds} from '../../constants.js'; -import domObserver from '../../observers/dom.js'; import settings from '../../settings.js'; import {hasFlag} from '../../utils/flags.js'; import {loadModuleForPlatforms} from '../../utils/modules.js'; import twitch from '../../utils/twitch.js'; +import {getCurrentUser} from '../../utils/user.js'; import watcher from '../../watcher.js'; -const AUTO_CLAIM_SELECTOR = '.chat-private-callout__header-segment'; -const AUTO_CLAIM_BUTTON_SELECTOR = `${AUTO_CLAIM_SELECTOR} button[class*="ScCoreButtonPrimary"]`; - -let autoClaimListener; - -function handleClaim(node) { - const autoClaim = settings.get(SettingIds.AUTO_CLAIM); - - const eligibleEventTypes = []; - if (hasFlag(autoClaim, AutoClaimFlags.DROPS)) { - eligibleEventTypes.push('drop'); +const inventoryQuery = gql` + query BTTVInventory { + currentUser { + id + inventory { + dropCampaignsInProgress { + id + timeBasedDrops { + id + requiredMinutesWatched + self { + isClaimed + currentMinutesWatched + dropInstanceID + hasPreconditionsMet + } + } + } + } + } } +`; - const event = twitch.getPrivateCalloutEvent(node); - if (event == null || !eligibleEventTypes.includes(event.type)) { - return; +const claimDropMutation = gql` + mutation BTTVClaimDrop($input: ClaimDropRewardsInput!) { + claimDropRewards(input: $input) { + status + } } +`; + +async function handleMessage(message) { + const messageData = JSON.parse(message); - const claimButton = document.querySelector(AUTO_CLAIM_BUTTON_SELECTOR); - if (claimButton == null) { + if ( + messageData.type !== 'create-notification' || + messageData.data?.notification?.type !== 'user_drop_reward_reminder_notification' + ) { return; } - claimButton.click(); -} + const {data} = await twitch.graphqlQuery(inventoryQuery); + const {dropCampaignsInProgress} = data?.currentUser?.inventory ?? {}; -const handleClaimDebounced = debounce(handleClaim, 1000); + for await (const {timeBasedDrops, id: campaignId} of dropCampaignsInProgress) { + for await (const drop of timeBasedDrops) { + if ( + drop.self.isClaimed || + drop.self.currentMinutesWatched < drop.requiredMinutesWatched || + !drop.self.hasPreconditionsMet + ) { + continue; + } + let {dropInstanceID} = drop.self; + if (dropInstanceID == null) { + dropInstanceID = `${data.currentUser.id}#${campaignId}#${drop.id}`; + } + try { + await twitch.graphqlMutation(claimDropMutation, {input: {dropInstanceID}}); + } catch (_) {} + } + } +} +let listenerAttached = false; class AutoClaimModule { constructor() { watcher.on('load.chat', () => this.load()); settings.on(`changed.${SettingIds.AUTO_CLAIM}`, () => this.load()); } - load() { + async load() { const autoClaim = settings.get(SettingIds.AUTO_CLAIM); - const autoClaimDrops = hasFlag(autoClaim, AutoClaimFlags.DROPS); - const shouldAutoClaim = autoClaimDrops; - - if (!shouldAutoClaim && autoClaimListener != null) { - autoClaimListener(); - autoClaimListener = undefined; - } else if (shouldAutoClaim && autoClaimListener == null) { - autoClaimListener = domObserver.on(AUTO_CLAIM_SELECTOR, (node, isConnected) => { - if (!isConnected) return; - handleClaimDebounced(node); - }); + const shouldAutoClaim = hasFlag(autoClaim, AutoClaimFlags.DROPS); + const client = window.__twitch_pubsub_client; + const currentUser = getCurrentUser(); + if (client == null || currentUser == null) { + return; + } + const topicId = `onsite-notifications.${currentUser.id}`; + if (!shouldAutoClaim && listenerAttached) { + listenerAttached = false; + client.topicListeners.removeListener(topicId, handleMessage); + } + if (shouldAutoClaim && !listenerAttached) { + listenerAttached = true; + client.topicListeners.addListener(topicId, handleMessage); } } } diff --git a/src/modules/settings/components/settings/twitch/AutoClaim.jsx b/src/modules/settings/components/settings/twitch/AutoClaim.jsx index 4cb84e3573..af280cdb6a 100644 --- a/src/modules/settings/components/settings/twitch/AutoClaim.jsx +++ b/src/modules/settings/components/settings/twitch/AutoClaim.jsx @@ -43,7 +43,7 @@ function AutoClaim() {

{formatMessage({defaultMessage: 'Drops'})}

- {formatMessage({defaultMessage: 'Automatically claim drops once you earn them'})} + {formatMessage({defaultMessage: 'Automatically claim all drops once you earn them'})}