From e16ddeaa7b7b7c0a267590b801710dc958919959 Mon Sep 17 00:00:00 2001 From: DevilXD Date: Fri, 18 Aug 2023 20:41:24 +0200 Subject: [PATCH] Differentiate CLIENT_URL between different clients --- constants.py | 11 ++++++++--- twitch.py | 26 +++++++++++++------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/constants.py b/constants.py index a40ca71..0c158ee 100644 --- a/constants.py +++ b/constants.py @@ -80,7 +80,7 @@ MAX_TOPICS = (MAX_WEBSOCKETS * WS_TOPICS_LIMIT) - BASE_TOPICS MAX_CHANNELS = MAX_TOPICS // TOPICS_PER_CHANNEL # Misc DEFAULT_LANG = "English" -BASE_URL = URL("https://twitch.tv") +BASE_URL = URL("https://www.twitch.tv") # Intervals and Delays PING_INTERVAL = timedelta(minutes=3) PING_TIMEOUT = timedelta(seconds=10) @@ -99,7 +99,8 @@ OUTPUT_FORMATTER = logging.Formatter("{levelname}: {message}", style='{', datefm class ClientInfo: - def __init__(self, client_id: str, user_agents: str | list[str]) -> None: + def __init__(self, client_url: URL, client_id: str, user_agents: str | list[str]) -> None: + self.CLIENT_URL: URL = client_url self.CLIENT_ID: str = client_id self.USER_AGENT: str if isinstance(user_agents, list): @@ -108,11 +109,12 @@ class ClientInfo: self.USER_AGENT = user_agents def __iter__(self): - return iter((self.CLIENT_ID, self.USER_AGENT)) + return iter((self.CLIENT_URL, self.CLIENT_ID, self.USER_AGENT)) class ClientType: WEB = ClientInfo( + BASE_URL, "kimne78kx3ncx6brgo4mv6wki5h1ko", ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " @@ -120,6 +122,7 @@ class ClientType: ), ) MOBILE_WEB = ClientInfo( + URL("https://m.twitch.tv"), "r8s4dac0uhzifbpu9sjdiwzctle17ff", [ ( @@ -153,6 +156,7 @@ class ClientType: ] ) ANDROID_APP = ClientInfo( + BASE_URL, "kd1unb4b3q4t58fwlpcbzcbnm76a8fp", ( "Dalvik/2.1.0 (Linux; U; Android 7.1.2; SM-G977N Build/LMY48Z) " @@ -160,6 +164,7 @@ class ClientType: ), ) SMARTBOX = ClientInfo( + URL("https://android.tv.twitch.tv"), "ue6666qo983tsx6so1t0vnawi233wa", ( "Mozilla/5.0 (Linux; Android 7.1; Smart Box C1) AppleWebKit/537.36 " diff --git a/twitch.py b/twitch.py index cadebba..588dec0 100644 --- a/twitch.py +++ b/twitch.py @@ -91,7 +91,7 @@ class SkipExtraJsonDecoder(json.JSONDecoder): return obj -CLIENT_ID, USER_AGENT = ClientType.MOBILE_WEB +CLIENT_URL, CLIENT_ID, USER_AGENT = ClientType.MOBILE_WEB SAFE_LOADS = lambda s: json.loads(s, cls=SkipExtraJsonDecoder) @@ -281,9 +281,9 @@ class _AuthState: "Cache-Control": "no-cache", "Client-Id": CLIENT_ID, "Host": "id.twitch.tv", - "Origin": "https://android.tv.twitch.tv", + "Origin": str(CLIENT_URL), "Pragma": "no-cache", - "Referer": "https://android.tv.twitch.tv/", + "Referer": str(CLIENT_URL), "User-Agent": USER_AGENT, "X-Device-Id": self.device_id, } @@ -504,8 +504,8 @@ class _AuthState: if hasattr(self, "device_id"): headers["X-Device-Id"] = self.device_id if gql: - headers["Origin"] = "https://www.twitch.tv" - headers["Referer"] = "https://www.twitch.tv/" + headers["Origin"] = str(BASE_URL) + headers["Referer"] = str(BASE_URL) headers["Authorization"] = f"OAuth {self.access_token}" if integrity: headers["Client-Integrity"] = self.integrity_token @@ -518,12 +518,12 @@ class _AuthState: async def _validate(self): if not hasattr(self, "session_id"): self.session_id = create_nonce(CHARS_HEX_LOWER, 16) - if not self._hasattrs("client_version", "device_id", "access_token", "user_id"): + if not self._hasattrs("device_id", "access_token", "user_id"): session = await self._twitch.get_session() jar = cast(aiohttp.CookieJar, session.cookie_jar) - if not self._hasattrs("client_version", "device_id"): + if not self._hasattrs("device_id"): async with self._twitch.request( - "GET", BASE_URL, headers=self.headers() + "GET", CLIENT_URL, headers=self.headers() ) as response: page_html = await response.text("utf8") assert page_html is not None @@ -532,7 +532,7 @@ class _AuthState: # raise MinerException("Unable to extract client_version") # self.client_version = match.group(1) # doing the request ends up setting the "unique_id" value in the cookie - cookie = jar.filter_cookies(BASE_URL) + cookie = jar.filter_cookies(CLIENT_URL) self.device_id = cookie["unique_id"].value if not self._hasattrs("access_token", "user_id"): # looks like we're missing something @@ -540,7 +540,7 @@ class _AuthState: logger.info("Checking login") login_form.update(_("gui", "login", "logging_in"), None) for attempt in range(2): - cookie = jar.filter_cookies(BASE_URL) + cookie = jar.filter_cookies(CLIENT_URL) if "auth-token" not in cookie: self.access_token = await self._oauth_login() cookie["auth-token"] = self.access_token @@ -557,8 +557,8 @@ class _AuthState: if status == 401: # the access token we have is invalid - clear the cookie and reauth logger.info("Restored session is invalid") - assert BASE_URL.host is not None - jar.clear_domain(BASE_URL.host) + assert CLIENT_URL.host is not None + jar.clear_domain(CLIENT_URL.host) continue elif status == 200: validate_response = await response.json() @@ -572,7 +572,7 @@ class _AuthState: logger.info(f"Login successful, user ID: {self.user_id}") login_form.update(_("gui", "login", "logged_in"), self.user_id) # update our cookie and save it - jar.update_cookies(cookie, BASE_URL) + jar.update_cookies(cookie, CLIENT_URL) jar.save(COOKIES_PATH) # if not self._hasattrs("integrity_token") or self.integrity_expired: # async with self._twitch.request(