diff --git a/DOCKER_README.md b/DOCKER_README.md index 74bdd4f2..67f128d2 100644 --- a/DOCKER_README.md +++ b/DOCKER_README.md @@ -10,8 +10,8 @@ Readme, source and documentation on [https://github.com/Der-Henning/tgtg](https: - [`edge`](https://github.com/Der-Henning/tgtg/blob/main/Dockerfile) - [`edge-alpine`](https://github.com/Der-Henning/tgtg/blob/main/Dockerfile.alpine) -- [`v1`, `v1.14`, `v1.14.4`, `latest`](https://github.com/Der-Henning/tgtg/blob/v1.14.4/Dockerfile) -- [`v1-alpine`, `v1.14-alpine`, `v1.14.4-alpine`, `latest-alpine`](https://github.com/Der-Henning/tgtg/blob/v1.14.4/Dockerfile.alpine) +- [`v1`, `v1.14`, `v1.14.5`, `latest`](https://github.com/Der-Henning/tgtg/blob/v1.14.5/Dockerfile) +- [`v1-alpine`, `v1.14-alpine`, `v1.14.5-alpine`, `latest-alpine`](https://github.com/Der-Henning/tgtg/blob/v1.14.5/Dockerfile.alpine) # Quick Start diff --git a/src/_version.py b/src/_version.py index db831091..1e2e576b 100644 --- a/src/_version.py +++ b/src/_version.py @@ -1,6 +1,6 @@ __title__ = "TGTG Scanner" __description__ = "Provides notifications for TGTG magic bags" -__version__ = "1.14.4" +__version__ = "1.14.5" __author__ = "Henning Merklinger" __author_email__ = "henning.merklinger@gmail.com" __license__ = "GPL" diff --git a/src/tgtg/tgtg_client.py b/src/tgtg/tgtg_client.py index 745238e4..3526e84e 100644 --- a/src/tgtg/tgtg_client.py +++ b/src/tgtg/tgtg_client.py @@ -5,7 +5,7 @@ import random import re import time -from datetime import datetime, timedelta +from datetime import datetime from http import HTTPStatus from typing import List from urllib.parse import urljoin @@ -43,6 +43,33 @@ ) +class TgtgSession(requests.Session): + http_adapter = HTTPAdapter( + max_retries=Retry( + total=5, + status_forcelist=[429, 500, 502, 503, 504], + allowed_methods=["GET", "POST"], + backoff_factor=1, + ) + ) + + def __init__(self, headers: dict = {}, timeout: int = None, + proxies: dict = None, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.mount("https://", self.http_adapter) + self.mount("http://", self.http_adapter) + self.headers = headers + self.timeout = timeout + self.proxies = proxies + + def send(self, request, **kwargs): + for key in ["timeout", "proxies"]: + val = kwargs.get(key) + if val is None and hasattr(self, key): + kwargs[key] = getattr(self, key) + return super().send(request, **kwargs) + + class TgtgClient: def __init__( self, @@ -78,18 +105,7 @@ def __init__( self.language = language self.proxies = proxies self.timeout = timeout - self.http_adapter = HTTPAdapter( - max_retries=Retry( - total=5, - status_forcelist=[429, 500, 502, 503, 504], - allowed_methods=["GET", "POST"], - backoff_factor=1, - ) - ) - self.session = requests.Session() - self.session.mount("https://", self.http_adapter) - self.session.mount("http://", self.http_adapter) - self.session.headers = self._headers + self.session = self._create_session() self.captcha_error_count = 0 @@ -99,6 +115,11 @@ def __del__(self) -> None: def _get_url(self, path) -> str: return urljoin(self.base_url, path) + def _create_session(self) -> TgtgSession: + return TgtgSession(self._headers, + self.timeout, + self.proxies) + def get_credentials(self) -> dict: """Returns current tgtg api credentials. @@ -112,16 +133,12 @@ def get_credentials(self) -> dict: "user_id": self.user_id, } - def _post(self, path, login: bool = True, retry: int = 0, **kwargs + def _post(self, path, retry: int = 0, **kwargs ) -> requests.Response: max_retries = 1 - if login: - self.login() response = self.session.post( self._get_url(path), headers=self._headers, - proxies=self.proxies, - timeout=self.timeout, **kwargs, ) if response.status_code in (HTTPStatus.OK, HTTPStatus.ACCEPTED): @@ -133,11 +150,11 @@ def _post(self, path, login: bool = True, retry: int = 0, **kwargs # Status Code == 403 and no json contend # --> Blocked due to rate limit / wrong user_agent. # 1. Get latest APK Version from google - # 2. Give the current token a 1 hour penalty (faster refresh) + # 2. Reset current session # 3. Rety request if response.status_code == 403 and retry < max_retries: self.user_agent = self._get_user_agent() - self.last_time_token_refreshed -= timedelta(hours=1) + self.session = self._create_session() return self._post(path, retry=retry + 1, **kwargs) self.captcha_error_count += 1 raise TgtgCaptchaError(response.status_code, @@ -195,8 +212,7 @@ def _refresh_token(self) -> None: return response = self._post( REFRESH_ENDPOINT, - json={"refresh_token": self.refresh_token}, - login=False + json={"refresh_token": self.refresh_token} ) self.access_token = response.json()["access_token"] self.refresh_token = response.json()["refresh_token"] @@ -218,8 +234,7 @@ def login(self) -> None: json={ "device_type": self.device_type, "email": self.email, - }, - login=False + } ) first_login_response = response.json() if first_login_response["state"] == "TERMS": @@ -240,8 +255,7 @@ def start_polling(self, polling_id) -> None: "device_type": self.device_type, "email": self.email, "request_polling_id": polling_id, - }, - login=False + } ) if response.status_code == HTTPStatus.ACCEPTED: log.warning( @@ -281,6 +295,7 @@ def get_items( hidden_only=False, we_care_only=False, ) -> List[dict]: + self.login() # fields are sorted like in the app data = { "user_id": self.user_id, @@ -303,6 +318,7 @@ def get_items( return response.json()["items"] def get_item(self, item_id: str) -> dict: + self.login() response = self._post( f"{API_ITEM_ENDPOINT}/{item_id}", json={"user_id": self.user_id, "origin": None}, @@ -310,6 +326,7 @@ def get_item(self, item_id: str) -> dict: return response.json() def set_favorite(self, item_id: str, is_favorite: bool) -> None: + self.login() self._post( f"{API_ITEM_ENDPOINT}/{item_id}/setFavorite", json={"is_favorite": is_favorite}, @@ -333,8 +350,7 @@ def signup_by_email( "name": name, "newsletter_opt_in": newsletter_opt_in, "push_notification_opt_in": push_notification_opt_in, - }, - login=False + } ) login_response = response.json()["login_response"] self.access_token = login_response["access_token"]