From 508a107c93c22aab12023a877825eec0dd91424a Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Fri, 29 Jan 2021 19:36:14 +0100 Subject: [PATCH] Message of type: drop-claim is useless. If current progress is >= required check the drop in inventory and get the dropInstanceID for auto-claim #21 Signed-off-by: Alessandro Maggio --- .../classes/Exceptions.py | 4 ++ TwitchChannelPointsMiner/classes/Twitch.py | 19 ++++-- .../classes/WebSocketsPool.py | 28 +++++--- TwitchChannelPointsMiner/constants/twitch.py | 10 +++ TwitchChannelPointsMiner/utils.py | 64 +++++++++---------- 5 files changed, 80 insertions(+), 45 deletions(-) diff --git a/TwitchChannelPointsMiner/classes/Exceptions.py b/TwitchChannelPointsMiner/classes/Exceptions.py index 50d6abb..0d0acd0 100644 --- a/TwitchChannelPointsMiner/classes/Exceptions.py +++ b/TwitchChannelPointsMiner/classes/Exceptions.py @@ -8,3 +8,7 @@ class StreamerIsOfflineException(Exception): class WrongCookiesException(Exception): pass + + +class TimeBasedDropNotFound(Exception): + pass diff --git a/TwitchChannelPointsMiner/classes/Twitch.py b/TwitchChannelPointsMiner/classes/Twitch.py index eda97cb..5c680cc 100644 --- a/TwitchChannelPointsMiner/classes/Twitch.py +++ b/TwitchChannelPointsMiner/classes/Twitch.py @@ -18,6 +18,7 @@ from TwitchChannelPointsMiner.classes.TwitchLogin import TwitchLogin from TwitchChannelPointsMiner.classes.Exceptions import ( StreamerIsOfflineException, StreamerDoesNotExistException, + TimeBasedDropNotFound, ) from TwitchChannelPointsMiner.constants.twitch import CLIENT_ID, API, GQLOperations @@ -149,19 +150,27 @@ class Twitch: json_data["variables"] = {"input": {"dropInstanceID": drop_instance_id}} self.post_gql_request(json_data) + def search_drop_in_inventory(self, streamer, drop_id): + response = self.post_gql_request(GQLOperations.Inventory) + inventory = response["data"]["currentUser"]["inventory"] + for campaign in inventory["dropCampaignsInProgress"]: + for drop in campaign["timeBasedDrops"]: + if drop["id"] == drop_id: + return drop["self"] + raise TimeBasedDropNotFound + # Load the amount of current points for a channel, check if a bonus is available def load_channel_points_context(self, streamer, less_printing=False): json_data = copy.deepcopy(GQLOperations.ChannelPointsContext) - json_data["variables"] = ({"channelLogin": streamer.username}) + json_data["variables"] = {"channelLogin": streamer.username} response = self.post_gql_request(json_data) if response["data"]["community"] is None: raise StreamerDoesNotExistException - community_points = response["data"]["community"]["channel"]["self"][ - "communityPoints" - ] + channel = response["data"]["community"]["channel"] + community_points = channel["self"]["communityPoints"] streamer.channel_points = community_points["balance"] - # logger.info(f"{streamer.channel_points} channel points for {streamer.username}!") + if community_points["availableClaim"] is not None: self.claim_bonus( streamer, diff --git a/TwitchChannelPointsMiner/classes/WebSocketsPool.py b/TwitchChannelPointsMiner/classes/WebSocketsPool.py index 263f8cd..65f0c4e 100644 --- a/TwitchChannelPointsMiner/classes/WebSocketsPool.py +++ b/TwitchChannelPointsMiner/classes/WebSocketsPool.py @@ -7,6 +7,7 @@ import random from millify import millify from dateutil import parser +from TwitchChannelPointsMiner.classes.Exceptions import TimeBasedDropNotFound from TwitchChannelPointsMiner.classes.EventPrediction import EventPrediction from TwitchChannelPointsMiner.classes.Raid import Raid from TwitchChannelPointsMiner.classes.TwitchWebSocket import TwitchWebSocket @@ -283,14 +284,25 @@ class WebSocketsPool: ws.events_predictions[event_id].bet_confirmed = True elif message.topic == "user-drop-events": - # if message.type == "drop-progress" # We don't need to handle this event - if message.type == "drop-claim": - # Random delay before claim. Maybe It's not required. - time.sleep(random.uniform(20, 40)) - ws.twitch.claim_drop( - ws.streamers[streamer_index], - message.data["drop_instance_id"] - ) + if message.type == "drop-progress": + if ( + message.data["current_progress_min"] + >= message.data["required_progress_min"] + ): + try: + drop = ws.twitch.search_drop_in_inventory( + ws.streamers[streamer_index], + message.data["drop_id"], + ) + if drop["dropInstanceID"] is not None: + ws.twitch.claim_drop( + ws.streamers[streamer_index], + drop["dropInstanceID"], + ) + except TimeBasedDropNotFound: + logger.error( + f"Unable to find {message.data['drop_id']} in your inventory" + ) except Exception: logger.error( diff --git a/TwitchChannelPointsMiner/constants/twitch.py b/TwitchChannelPointsMiner/constants/twitch.py index 314f01c..422457c 100644 --- a/TwitchChannelPointsMiner/constants/twitch.py +++ b/TwitchChannelPointsMiner/constants/twitch.py @@ -71,3 +71,13 @@ class GQLOperations: } }, } + Inventory = { + "operationName": "Inventory", + "variables": {}, + "extensions": { + "persistedQuery": { + "version": 1, + "sha256Hash": "e0765ebaa8e8eeb4043cc6dfeab3eac7f682ef5f724b81367e6e55c7aef2be4c", + } + }, + } diff --git a/TwitchChannelPointsMiner/utils.py b/TwitchChannelPointsMiner/utils.py index d1cb391..d2af360 100644 --- a/TwitchChannelPointsMiner/utils.py +++ b/TwitchChannelPointsMiner/utils.py @@ -78,38 +78,38 @@ def get_user_agent(browser): def remove_emoji(string): emoji_pattern = re.compile( "[" - u"\U0001F600-\U0001F64F" # emoticons - u"\U0001F300-\U0001F5FF" # symbols & pictographs - u"\U0001F680-\U0001F6FF" # transport & map symbols - u"\U0001F1E0-\U0001F1FF" # flags (iOS) - u"\U00002500-\U00002BEF" # chinese char - u"\U00002702-\U000027B0" - u"\U00002702-\U000027B0" - u"\U000024C2-\U0001F251" - u"\U0001f926-\U0001f937" - u"\U00010000-\U0010ffff" - u"\u2640-\u2642" - u"\u2600-\u2B55" - u"\u200d" - u"\u23cf" - u"\u23e9" - u"\u231a" - u"\ufe0f" # dingbats - u"\u3030" - u"\u231b" - u"\u2328" - u"\u23cf" - u"\u23e9" - u"\u23ea" - u"\u23eb" - u"\u23ec" - u"\u23ed" - u"\u23ee" - u"\u23ef" - u"\u23f0" - u"\u23f1" - u"\u23f2" - u"\u23f3" + "\U0001F600-\U0001F64F" # emoticons + "\U0001F300-\U0001F5FF" # symbols & pictographs + "\U0001F680-\U0001F6FF" # transport & map symbols + "\U0001F1E0-\U0001F1FF" # flags (iOS) + "\U00002500-\U00002BEF" # chinese char + "\U00002702-\U000027B0" + "\U00002702-\U000027B0" + "\U000024C2-\U0001F251" + "\U0001f926-\U0001f937" + "\U00010000-\U0010ffff" + "\u2640-\u2642" + "\u2600-\u2B55" + "\u200d" + "\u23cf" + "\u23e9" + "\u231a" + "\ufe0f" # dingbats + "\u3030" + "\u231b" + "\u2328" + "\u23cf" + "\u23e9" + "\u23ea" + "\u23eb" + "\u23ec" + "\u23ed" + "\u23ee" + "\u23ef" + "\u23f0" + "\u23f1" + "\u23f2" + "\u23f3" "]+", flags=re.UNICODE, )