Skip to content

Commit db1f65a

Browse files
committed
Merge remote-tracking branch 'upstream/wout-helix-api' into smart_high_odds
2 parents ef1c109 + 3c31015 commit db1f65a

File tree

6 files changed

+88
-51
lines changed

6 files changed

+88
-51
lines changed

TwitchChannelPointsMiner/TwitchChannelPointsMiner.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,11 @@ def run(self, streamers: list = [], blacklist: list = [], followers=False):
240240
)
241241

242242
# Subscribe to community-points-user. Get update for points spent or gains
243+
user_id = self.twitch.twitch_login.get_user_id()
243244
self.ws_pool.submit(
244245
PubsubTopic(
245246
"community-points-user-v1",
246-
user_id=self.twitch.twitch_login.get_user_id(),
247+
user_id=user_id,
247248
)
248249
)
249250

@@ -252,7 +253,7 @@ def run(self, streamers: list = [], blacklist: list = [], followers=False):
252253
self.ws_pool.submit(
253254
PubsubTopic(
254255
"predictions-user-v1",
255-
user_id=self.twitch.twitch_login.get_user_id(),
256+
user_id=user_id,
256257
)
257258
)
258259

TwitchChannelPointsMiner/classes/Twitch.py

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
)
2424
from TwitchChannelPointsMiner.classes.Settings import Priority, Settings
2525
from TwitchChannelPointsMiner.classes.TwitchLogin import TwitchLogin
26-
from TwitchChannelPointsMiner.constants import API, CLIENT_ID, GQLOperations
26+
from TwitchChannelPointsMiner.constants import CLIENT_ID, GQLOperations
2727
from TwitchChannelPointsMiner.utils import (
2828
_millify,
2929
create_chunks,
@@ -143,33 +143,34 @@ def check_streamer_online(self, streamer):
143143
streamer.set_offline()
144144

145145
def get_channel_id(self, streamer_username):
146-
json_response = self.__do_helix_request(f"/users?login={streamer_username}")
147-
if "data" not in json_response:
146+
json_data = copy.deepcopy(GQLOperations.ReportMenuItem)
147+
json_data["variables"] = {"channelLogin": streamer_username}
148+
json_response = self.post_gql_request(json_data)
149+
if (
150+
"data" not in json_response
151+
or "user" not in json_response["data"]
152+
or json_response["data"]["user"] is None
153+
):
148154
raise StreamerDoesNotExistException
149155
else:
150-
data = json_response["data"]
151-
if len(data) >= 1:
152-
return data[0]["id"]
153-
else:
154-
raise StreamerDoesNotExistException
155-
156-
def get_followers(self, first=100):
157-
followers = []
158-
pagination = {}
159-
while 1:
160-
query = f"/users/follows?from_id={self.twitch_login.get_user_id()}&first={first}"
161-
if pagination != {}:
162-
query += f"&after={pagination['cursor']}"
163-
164-
json_response = self.__do_helix_request(query)
165-
pagination = json_response["pagination"]
166-
followers += [fw["to_login"].lower() for fw in json_response["data"]]
167-
time.sleep(random.uniform(0.3, 0.7))
168-
169-
if pagination == {}:
170-
break
156+
return json_response["data"]["user"]["id"]
171157

172-
return followers
158+
def get_followers(self):
159+
json_data = copy.deepcopy(GQLOperations.PersonalSections)
160+
json_response = self.post_gql_request(json_data)
161+
try:
162+
if (
163+
"data" in json_response
164+
and "personalSections" in json_response["data"]
165+
and json_response["data"]["personalSections"] != []
166+
):
167+
return [
168+
fw["user"]["login"]
169+
for fw in json_response["data"]["personalSections"][0]["items"]
170+
if fw["user"] is not None
171+
]
172+
except KeyError:
173+
return []
173174

174175
def update_raid(self, streamer, raid):
175176
if streamer.raid != raid:
@@ -211,14 +212,6 @@ def __check_connection_handler(self, chunk_size):
211212
)
212213
self.__chuncked_sleep(random_sleep * 60, chunk_size=chunk_size)
213214

214-
def __do_helix_request(self, query, response_as_json=True):
215-
url = f"{API}/helix/{query.strip('/')}"
216-
response = self.twitch_login.session.get(url)
217-
logger.debug(
218-
f"Query: {query}, Status code: {response.status_code}, Content: {response.json()}"
219-
)
220-
return response.json() if response_as_json is True else response
221-
222215
def post_gql_request(self, json_data):
223216
try:
224217
response = requests.post(
@@ -362,14 +355,12 @@ def send_minute_watched_events(self, streamers, priority, chunk_size=3):
362355
drop.has_preconditions_met is not False
363356
and drop.is_printable is True
364357
):
365-
# print("=" * 125)
366358
logger.info(
367359
f"{streamers[index]} is streaming {streamers[index].stream}"
368360
)
369361
logger.info(f"Campaign: {campaign}")
370362
logger.info(f"Drop: {drop}")
371363
logger.info(f"{drop.progress_bar()}")
372-
# print("=" * 125)
373364

374365
except requests.exceptions.ConnectionError as e:
375366
logger.error(f"Error while trying to send minute watched: {e}")
@@ -541,7 +532,9 @@ def __get_campaigns_details(self, campaigns):
541532
}
542533

543534
response = self.post_gql_request(json_data)
544-
result += list(map(lambda x: x["data"]["user"]["dropCampaign"], response))
535+
for r in response:
536+
if r["data"]["user"] is not None:
537+
result.append(r["data"]["user"]["dropCampaign"])
545538
return result
546539

547540
def __sync_campaigns(self, campaigns):

TwitchChannelPointsMiner/classes/TwitchLogin.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Original Copyright (c) 2020 Rodney
33
# The MIT License (MIT)
44

5+
import copy
56
import getpass
67
import logging
78
import os
@@ -14,6 +15,7 @@
1415
BadCredentialsException,
1516
WrongCookiesException,
1617
)
18+
from TwitchChannelPointsMiner.constants import GQLOperations
1719

1820
logger = logging.getLogger(__name__)
1921

@@ -177,14 +179,7 @@ def check_login(self):
177179
if self.token is None:
178180
return False
179181

180-
response = self.session.get(
181-
f"https://api.twitch.tv/helix/users?login={self.username}"
182-
)
183-
response = response.json()
184-
if "data" in response:
185-
self.login_check_result = True
186-
self.user_id = response["data"][0]["id"]
187-
182+
self.login_check_result = self.__set_user_id()
188183
return self.login_check_result
189184

190185
def save_cookies(self, cookies_file):
@@ -203,6 +198,7 @@ def get_cookie_value(self, key):
203198
if cookie["name"] == key:
204199
if cookie["value"] is not None:
205200
return cookie["value"]
201+
return None
206202

207203
def load_cookies(self, cookies_file):
208204
if os.path.isfile(cookies_file):
@@ -211,7 +207,30 @@ def load_cookies(self, cookies_file):
211207
raise WrongCookiesException("There must be a cookies file!")
212208

213209
def get_user_id(self):
214-
return int(self.get_cookie_value("persistent").split("%")[0])
210+
persistent = self.get_cookie_value("persistent")
211+
user_id = (
212+
int(persistent.split("%")[0]) if persistent is not None else self.user_id
213+
)
214+
if user_id is None:
215+
if self.__set_user_id() is True:
216+
return self.user_id
217+
return user_id
218+
219+
def __set_user_id(self):
220+
json_data = copy.deepcopy(GQLOperations.ReportMenuItem)
221+
json_data["variables"] = {"channelLogin": self.username}
222+
response = self.session.post(GQLOperations.url, json=json_data)
223+
224+
if response.status_code == 200:
225+
json_response = response.json()
226+
if (
227+
"data" in json_response
228+
and "user" in json_response["data"]
229+
and json_response["data"]["user"]["id"] is not None
230+
):
231+
self.user_id = json_response["data"]["user"]["id"]
232+
return True
233+
return False
215234

216235
def get_auth_token(self):
217236
return self.get_cookie_value("auth-token")

TwitchChannelPointsMiner/classes/TwitchWebSocket.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ def listen(self, topic, auth_token=None):
4343
data = {"topics": [str(topic)]}
4444
if topic.is_user_topic() and auth_token is not None:
4545
data["auth_token"] = auth_token
46-
4746
nonce = create_nonce()
4847
self.send({"type": "LISTEN", "nonce": nonce, "data": data})
4948

TwitchChannelPointsMiner/classes/WebSocketsPool.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ def handle_reconnection(ws):
142142
# Why not create a new ws on the same array index? Let's try.
143143
self = ws.parent_pool
144144
self.ws[ws.index] = self.__new(ws.index) # Create a new connection.
145-
# self.ws[ws.index].topics = ws.topics
146145

147146
self.__start(ws.index) # Start a new thread.
148147
time.sleep(30)

TwitchChannelPointsMiner/constants.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Twitch endpoints
22
URL = "https://www.twitch.tv"
3-
API = "https://api.twitch.tv"
43
IRC = "irc.chat.twitch.tv"
54
IRC_PORT = 6667
65
WEBSOCKET = "wss://pubsub-edge.twitch.tv/v1"
@@ -118,7 +117,7 @@ class GQLOperations:
118117
"extensions": {
119118
"persistedQuery": {
120119
"version": 1,
121-
"sha256Hash": "14b5e8a50777165cfc3971e1d93b4758613fe1c817d5542c398dce70b7a45c05", # "7da6078b1bfa2f0a4dd061cb47bdcd1ffddf31cccadd966ec192e4cd06666e2b",
120+
"sha256Hash": "14b5e8a50777165cfc3971e1d93b4758613fe1c817d5542c398dce70b7a45c05",
122121
}
123122
},
124123
}
@@ -131,3 +130,30 @@ class GQLOperations:
131130
}
132131
},
133132
}
133+
ReportMenuItem = { # Use for replace https://api.twitch.tv/helix/users?login={self.username}
134+
"operationName": "ReportMenuItem",
135+
"extensions": {
136+
"persistedQuery": {
137+
"version": 1,
138+
"sha256Hash": "8f3628981255345ca5e5453dfd844efffb01d6413a9931498836e6268692a30c",
139+
}
140+
},
141+
}
142+
PersonalSections = {
143+
"operationName": "PersonalSections",
144+
"variables": {
145+
"input": {
146+
"sectionInputs": ["FOLLOWED_SECTION"],
147+
"recommendationContext": {"platform": "web"},
148+
},
149+
"channelLogin": None,
150+
"withChannelUser": False,
151+
"creatorAnniversariesExperimentEnabled": False,
152+
},
153+
"extensions": {
154+
"persistedQuery": {
155+
"version": 1,
156+
"sha256Hash": "9fbdfb00156f754c26bde81eb47436dee146655c92682328457037da1a48ed39",
157+
}
158+
},
159+
}

0 commit comments

Comments
 (0)