Skip to content

Commit 70035cd

Browse files
committed
Switch to MOBILE_WEB Client ID
1 parent 137f540 commit 70035cd

File tree

2 files changed

+56
-29
lines changed

2 files changed

+56
-29
lines changed

constants.py

+47-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from __future__ import annotations
22

33
import sys
4+
import random
45
import logging
56
from pathlib import Path
67
from copy import deepcopy
78
from enum import Enum, auto
89
from datetime import timedelta
9-
from typing import Any, Dict, Literal, NamedTuple, NewType, TYPE_CHECKING
10+
from typing import Any, Dict, Literal, NewType, TYPE_CHECKING
1011

1112
from yarl import URL
1213

@@ -97,9 +98,17 @@ def _resource_path(relative_path: Path | str) -> Path:
9798
OUTPUT_FORMATTER = logging.Formatter("{levelname}: {message}", style='{', datefmt="%H:%M:%S")
9899

99100

100-
class ClientInfo(NamedTuple):
101-
CLIENT_ID: str
102-
USER_AGENT: str
101+
class ClientInfo:
102+
def __init__(self, client_id: str, user_agents: str | list[str]) -> None:
103+
self.CLIENT_ID: str = client_id
104+
self.USER_AGENT: str
105+
if isinstance(user_agents, list):
106+
self.USER_AGENT = random.choice(user_agents)
107+
else:
108+
self.USER_AGENT = user_agents
109+
110+
def __iter__(self):
111+
return iter((self.CLIENT_ID, self.USER_AGENT))
103112

104113

105114
class ClientType:
@@ -110,7 +119,40 @@ class ClientType:
110119
"(KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
111120
),
112121
)
113-
ANDROID = ClientInfo(
122+
MOBILE_WEB = ClientInfo(
123+
"r8s4dac0uhzifbpu9sjdiwzctle17ff",
124+
[
125+
(
126+
"Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 "
127+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
128+
),
129+
(
130+
"Mozilla/5.0 (Linux; Android 13; SM-A205U) AppleWebKit/537.36 "
131+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
132+
),
133+
(
134+
"Mozilla/5.0 (Linux; Android 13; SM-A102U) AppleWebKit/537.36 "
135+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
136+
),
137+
(
138+
"Mozilla/5.0 (Linux; Android 13; SM-G960U) AppleWebKit/537.36 "
139+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
140+
),
141+
(
142+
"Mozilla/5.0 (Linux; Android 13; SM-N960U) AppleWebKit/537.36 "
143+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
144+
),
145+
(
146+
"Mozilla/5.0 (Linux; Android 13; LM-Q720) AppleWebKit/537.36 "
147+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
148+
),
149+
(
150+
"Mozilla/5.0 (Linux; Android 13; LM-X420) AppleWebKit/537.36 "
151+
"(KHTML, like Gecko) Chrome/115.0.5790.166 Mobile Safari/537.36"
152+
),
153+
]
154+
)
155+
ANDROID_APP = ClientInfo(
114156
"kd1unb4b3q4t58fwlpcbzcbnm76a8fp",
115157
(
116158
"Dalvik/2.1.0 (Linux; U; Android 7.1.2; SM-G977N Build/LMY48Z) "

twitch.py

+9-24
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import re
44
import sys
55
import json
6-
import random
76
import asyncio
87
import logging
98
from time import time
@@ -91,7 +90,7 @@ def decode(self, s: str, *args):
9190
return obj
9291

9392

94-
CLIENT_ID, USER_AGENT = ClientType.SMARTBOX
93+
CLIENT_ID, USER_AGENT = ClientType.MOBILE_WEB
9594
SAFE_LOADS = lambda s: json.loads(s, cls=SkipExtraJsonDecoder)
9695

9796

@@ -499,8 +498,8 @@ def headers(
499498
headers["User-Agent"] = user_agent
500499
if hasattr(self, "session_id"):
501500
headers["Client-Session-Id"] = self.session_id
502-
if hasattr(self, "client_version"):
503-
headers["Client-Version"] = self.client_version
501+
# if hasattr(self, "client_version"):
502+
# headers["Client-Version"] = self.client_version
504503
if hasattr(self, "device_id"):
505504
headers["X-Device-Id"] = self.device_id
506505
if gql:
@@ -526,10 +525,11 @@ async def _validate(self):
526525
"GET", BASE_URL, headers=self.headers()
527526
) as response:
528527
page_html = await response.text("utf8")
529-
match = re.search(r'twilightBuildID="([-a-z0-9]+)"', page_html)
530-
if match is None:
531-
raise MinerException("Unable to extract client_version")
532-
self.client_version = match.group(1)
528+
assert page_html is not None
529+
# match = re.search(r'twilightBuildID="([-a-z0-9]+)"', page_html)
530+
# if match is None:
531+
# raise MinerException("Unable to extract client_version")
532+
# self.client_version = match.group(1)
533533
# doing the request ends up setting the "unique_id" value in the cookie
534534
cookie = jar.filter_cookies(BASE_URL)
535535
self.device_id = cookie["unique_id"].value
@@ -639,21 +639,6 @@ async def get_session(self) -> aiohttp.ClientSession:
639639
if session.closed:
640640
raise RuntimeError("Session is closed")
641641
return session
642-
# try to obtain the latest Chrome user agent from a Github project
643-
try:
644-
async with aiohttp.request(
645-
"GET",
646-
"https://jnrbsn.github.io/user-agents/user-agents.json",
647-
proxy=self.settings.proxy or None,
648-
) as response:
649-
agents = await response.json()
650-
if sys.platform == "win32":
651-
chrome_agent = random.choice(agents[:3])
652-
elif sys.platform == "linux":
653-
chrome_agent = random.choice(agents[7:11])
654-
except Exception:
655-
# looks like we can't rely on 3rd parties too much
656-
chrome_agent = ClientType.WEB.USER_AGENT
657642
# load in cookies
658643
cookie_jar = aiohttp.CookieJar()
659644
try:
@@ -668,7 +653,7 @@ async def get_session(self) -> aiohttp.ClientSession:
668653
self._session = aiohttp.ClientSession(
669654
connector=connector,
670655
cookie_jar=cookie_jar,
671-
headers={"User-Agent": chrome_agent},
656+
headers={"User-Agent": USER_AGENT},
672657
timeout=aiohttp.ClientTimeout(connect=5, total=10),
673658
)
674659
return self._session

0 commit comments

Comments
 (0)