Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasDelsart committed Mar 8, 2025
2 parents 6449ec7 + 613a7db commit 6358ed1
Show file tree
Hide file tree
Showing 12 changed files with 1,667 additions and 679 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
exclude: (build|dist)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: check-added-large-files
Expand All @@ -13,7 +13,7 @@ repos:
- id: check-added-large-files

- repo: https://github.com/ambv/black
rev: 24.8.0
rev: 24.10.0
hooks:
- id: black
args: [--line-length, '130', --target-version, py38]
Expand Down Expand Up @@ -57,7 +57,7 @@ repos:
args: [-f, requirements.txt, -o, requirements.txt, --without-hashes]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.2
rev: v1.13.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
2,167 changes: 1,577 additions & 590 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ name = "tgtg-scanner"
packages = [{include = "tgtg_scanner"}]
readme = "README.md"
repository = "https://github.com/Der-Henning/tgtg"
version = "1.22.0"
version = "1.22.2"

[tool.poetry.dependencies]
apprise = "^1.4.0"
Expand All @@ -35,9 +35,10 @@ requests = "^2.31.0"
pyinstaller = "^6.3.0"

[tool.poetry.group.test.dependencies]
pre-commit = "^3.3.3"
poetry-plugin-export = "^1.9.0"
pre-commit = "^4.0.1"
pytest = "^8.0.0"
pytest-cov = "^5.0.0"
pytest-cov = "^6.0.0"
pytest-mock = "^3.11.1"
responses = "^0.25.0"

Expand Down
52 changes: 26 additions & 26 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
aiohappyeyeballs==2.4.3 ; python_version >= "3.9" and python_version < "3.13"
aiohttp==3.10.10 ; python_version >= "3.9" and python_version < "3.13"
aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "3.13"
anyio==4.6.2.post1 ; python_version >= "3.9" and python_version < "3.13"
apprise==1.9.0 ; python_version >= "3.9" and python_version < "3.13"
async-timeout==4.0.3 ; python_version >= "3.9" and python_version < "3.11"
attrs==24.2.0 ; python_version >= "3.9" and python_version < "3.13"
babel==2.16.0 ; python_version >= "3.9" and python_version < "3.13"
cachetools==5.5.0 ; python_version >= "3.9" and python_version < "3.13"
certifi==2024.8.30 ; python_version >= "3.9" and python_version < "3.13"
charset-normalizer==3.4.0 ; python_version >= "3.9" and python_version < "3.13"
click==8.1.7 ; python_version >= "3.9" and python_version < "3.13"
aiohappyeyeballs==2.4.6 ; python_version >= "3.9" and python_version < "3.13"
aiohttp==3.11.13 ; python_version >= "3.9" and python_version < "3.13"
aiosignal==1.3.2 ; python_version >= "3.9" and python_version < "3.13"
anyio==4.8.0 ; python_version >= "3.9" and python_version < "3.13"
apprise==1.9.2 ; python_version >= "3.9" and python_version < "3.13"
async-timeout==5.0.1 ; python_version >= "3.9" and python_version < "3.11"
attrs==25.1.0 ; python_version >= "3.9" and python_version < "3.13"
babel==2.17.0 ; python_version >= "3.9" and python_version < "3.13"
cachetools==5.5.2 ; python_version >= "3.9" and python_version < "3.13"
certifi==2025.1.31 ; python_version >= "3.9" and python_version < "3.13"
charset-normalizer==3.4.1 ; python_version >= "3.9" and python_version < "3.13"
click==8.1.8 ; python_version >= "3.9" and python_version < "3.13"
colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.13" and (sys_platform == "win32" or platform_system == "Windows")
colorlog==6.9.0 ; python_version >= "3.9" and python_version < "3.13"
cron-descriptor==1.4.5 ; python_version >= "3.9" and python_version < "3.13"
discord-py==2.4.0 ; python_version >= "3.9" and python_version < "3.13"
discord-py==2.5.0 ; python_version >= "3.9" and python_version < "3.13"
discord==2.3.2 ; python_version >= "3.9" and python_version < "3.13"
exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11"
frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.13"
googlemaps==4.10.0 ; python_version >= "3.9" and python_version < "3.13"
h11==0.14.0 ; python_version >= "3.9" and python_version < "3.13"
httpcore==1.0.6 ; python_version >= "3.9" and python_version < "3.13"
httpx==0.27.2 ; python_version >= "3.9" and python_version < "3.13"
humanize==4.11.0 ; python_version >= "3.9" and python_version < "3.13"
httpcore==1.0.7 ; python_version >= "3.9" and python_version < "3.13"
httpx==0.28.1 ; python_version >= "3.9" and python_version < "3.13"
humanize==4.12.1 ; python_version >= "3.9" and python_version < "3.13"
idna==3.10 ; python_version >= "3.9" and python_version < "3.13"
importlib-metadata==8.5.0 ; python_version >= "3.9" and python_version < "3.10"
importlib-metadata==8.6.1 ; python_version >= "3.9" and python_version < "3.10"
markdown==3.7 ; python_version >= "3.9" and python_version < "3.13"
multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.13"
oauthlib==3.2.2 ; python_version >= "3.9" and python_version < "3.13"
packaging==24.1 ; python_version >= "3.9" and python_version < "3.13"
packaging==24.2 ; python_version >= "3.9" and python_version < "3.13"
progress==1.6 ; python_version >= "3.9" and python_version < "3.13"
prometheus-client==0.21.0 ; python_version >= "3.9" and python_version < "3.13"
propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.13"
pycron==3.1.1 ; python_version >= "3.9" and python_version < "3.13"
prometheus-client==0.21.1 ; python_version >= "3.9" and python_version < "3.13"
propcache==0.3.0 ; python_version >= "3.9" and python_version < "3.13"
pycron==3.1.2 ; python_version >= "3.9" and python_version < "3.13"
python-pushsafer==1.1 ; python_version >= "3.9" and python_version < "3.13"
python-telegram-bot[callback-data]==21.6 ; python_version >= "3.9" and python_version < "3.13"
python-telegram-bot[callback-data]==21.10 ; python_version >= "3.9" and python_version < "3.13"
pyyaml==6.0.2 ; python_version >= "3.9" and python_version < "3.13"
requests-oauthlib==2.0.0 ; python_version >= "3.9" and python_version < "3.13"
requests==2.32.3 ; python_version >= "3.9" and python_version < "3.13"
sniffio==1.3.1 ; python_version >= "3.9" and python_version < "3.13"
typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.11"
urllib3==2.2.3 ; python_version >= "3.9" and python_version < "3.13"
yarl==1.17.1 ; python_version >= "3.9" and python_version < "3.13"
zipp==3.20.2 ; python_version >= "3.9" and python_version < "3.10"
typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.13"
urllib3==2.3.0 ; python_version >= "3.9" and python_version < "3.13"
yarl==1.18.3 ; python_version >= "3.9" and python_version < "3.13"
zipp==3.21.0 ; python_version >= "3.9" and python_version < "3.10"
9 changes: 2 additions & 7 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import configparser
import platform
import tempfile
from random import randint
from uuid import uuid4

import pytest
Expand Down Expand Up @@ -41,17 +40,15 @@ def test_save_tokens_to_ini():
with tempfile.NamedTemporaryFile(delete=not IS_WINDOWS) as temp_file:
access_token = uuid4().hex
refresh_token = uuid4().hex
user_id = str(randint(10**9, 10**10 - 1))
datadome = uuid4().hex
config = Config(temp_file.name)
config.save_tokens(access_token, refresh_token, user_id, datadome)
config.save_tokens(access_token, refresh_token, datadome)

config_parser = configparser.ConfigParser()
config_parser.read(temp_file.name, encoding="utf-8")

assert config_parser.get("TGTG", "AccessToken") == access_token
assert config_parser.get("TGTG", "RefreshToken") == refresh_token
assert config_parser.get("TGTG", "UserId") == user_id
assert config_parser.get("TGTG", "Datadome") == datadome


Expand All @@ -60,15 +57,13 @@ def test_token_path(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setenv("TGTG_TOKEN_PATH", temp_dir)
access_token = uuid4().hex
refresh_token = uuid4().hex
user_id = uuid4().hex
datadome = uuid4().hex
config = Config()
config.save_tokens(access_token, refresh_token, user_id, datadome)
config.save_tokens(access_token, refresh_token, datadome)
config._load_tokens()

assert config.tgtg.access_token == access_token
assert config.tgtg.refresh_token == refresh_token
assert config.tgtg.user_id == user_id
assert config.tgtg.datadome == datadome


Expand Down
25 changes: 10 additions & 15 deletions tests/test_tgtg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@

from tgtg_scanner.models import Config
from tgtg_scanner.tgtg.tgtg_client import (
API_ITEM_ENDPOINT,
AUTH_BY_EMAIL_ENDPOINT,
AUTH_POLLING_ENDPOINT,
BASE_URL,
FAVORITE_ITEM_ENDPOINT,
REFRESH_ENDPOINT,
USER_AGENTS,
TgtgClient,
)
Expand Down Expand Up @@ -49,30 +53,27 @@ def test_tgtg_login_with_mail(mocker: MockerFixture):
"access_token": "new_access_token",
"access_token_ttl_seconds": 172800,
"refresh_token": "new_refresh_token",
"startup_data": {"user": {"user_id": "123456789"}},
}
responses.add(
responses.POST,
"https://apptoogoodtogo.com/api/auth/v3/authByEmail",
urljoin(BASE_URL, AUTH_BY_EMAIL_ENDPOINT),
json.dumps(auth_response_data),
status=200,
)
responses.add(
responses.POST,
"https://apptoogoodtogo.com/api/auth/v3/authByRequestPollingId",
urljoin(BASE_URL, AUTH_POLLING_ENDPOINT),
status=202,
)
responses.add(
responses.POST,
"https://apptoogoodtogo.com/api/auth/v3/authByRequestPollingId",
urljoin(BASE_URL, AUTH_POLLING_ENDPOINT),
json.dumps(poll_response_data),
status=200,
)
client.login()
assert client.access_token == poll_response_data.get("access_token")
assert client.refresh_token == poll_response_data.get("refresh_token")
user_id = poll_response_data.get("startup_data", {}).get("user", {}).get("user_id") # type: ignore[attr-defined]
assert client.user_id == user_id
assert json.loads(responses.calls[1].request.body) == {
"device_type": client.device_type,
"email": client.email,
Expand All @@ -90,7 +91,6 @@ def test_tgtg_login_with_token(mocker: MockerFixture):
email="[email protected]",
access_token="old_access_token",
refresh_token="old_refresh_token",
user_id="old_user_id",
)
response_data = {
"access_token": "new_access_token",
Expand All @@ -99,7 +99,7 @@ def test_tgtg_login_with_token(mocker: MockerFixture):
}
responses.add(
responses.POST,
"https://apptoogoodtogo.com/api/auth/v3/token/refresh",
urljoin(BASE_URL, REFRESH_ENDPOINT),
json.dumps(response_data),
status=200,
)
Expand All @@ -117,15 +117,14 @@ def test_tgtg_get_items(mocker: MockerFixture, tgtg_item: dict):
mocker.patch("tgtg_scanner.tgtg.tgtg_client.TgtgClient.login", return_value=None)
responses.add(
responses.POST,
"https://apptoogoodtogo.com/api/item/v8/",
urljoin(BASE_URL, API_ITEM_ENDPOINT),
json.dumps({"items": [tgtg_item]}),
status=200,
)
client = TgtgClient(
email="[email protected]",
access_token="access_token",
refresh_token="refresh_token",
user_id="user_id",
)
response = client.get_items(favorites_only=True)
assert response == [tgtg_item]
Expand All @@ -141,15 +140,14 @@ def test_tgtg_get_item(mocker: MockerFixture, tgtg_item: dict):
item_id = tgtg_item.get("item", {}).get("item_id")
responses.add(
responses.POST,
f"https://apptoogoodtogo.com/api/item/v8/{item_id}",
urljoin(BASE_URL, API_ITEM_ENDPOINT + item_id),
json.dumps(tgtg_item),
status=200,
)
client = TgtgClient(
email="[email protected]",
access_token="access_token",
refresh_token="refresh_token",
user_id="user_id",
)
response = client.get_item(item_id)
assert response == tgtg_item
Expand All @@ -173,7 +171,6 @@ def test_tgtg_set_favorite(mocker: MockerFixture):
email="[email protected]",
access_token="access_token",
refresh_token="refresh_token",
user_id="user_id",
)
client.set_favorite(item_id, True)
assert json.loads(responses.calls[0].request.body) == {"is_favorite": True}
Expand All @@ -196,7 +193,6 @@ def test_tgtg_api(item_properties: dict):
polling_wait_time=config.tgtg.polling_wait_time,
access_token=config.tgtg.access_token,
refresh_token=config.tgtg.refresh_token,
user_id=config.tgtg.user_id,
datadome_cookie=config.tgtg.datadome,
)

Expand All @@ -207,7 +203,6 @@ def test_tgtg_api(item_properties: dict):
with open(env_file, "a", encoding="utf-8") as file:
file.write(f"TGTG_ACCESS_TOKEN={credentials['access_token']}\n")
file.write(f"TGTG_REFRESH_TOKEN={credentials['refresh_token']}\n")
file.write(f"TGTG_USER_ID={credentials['user_id']}\n")
file.write(f"TGTG_COOKIE={credentials['datadome_cookie']}\n")

# Tests
Expand Down
1 change: 0 additions & 1 deletion tgtg_scanner/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ def main():
print("Email: ", credentials.get("email"))
print("Access Token: ", credentials.get("access_token"))
print("Refresh Token: ", credentials.get("refresh_token"))
print("User ID: ", credentials.get("user_id"))
print("Datadome Cookie:", credentials.get("datadome_cookie"))
print("")
elif args.favorites:
Expand Down
10 changes: 1 addition & 9 deletions tgtg_scanner/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,6 @@ class TgtgConfig(BaseConfig):
username: Union[str, None] = None
access_token: Union[str, None] = None
refresh_token: Union[str, None] = None
user_id: Union[str, None] = None
datadome: Union[str, None] = None
timeout: int = 60
access_token_lifetime: int = 14400
Expand All @@ -485,7 +484,6 @@ def _read_ini(self, parser: configparser.ConfigParser):
self._ini_get(parser, "TGTG", "Username", "username")
self._ini_get(parser, "TGTG", "AccessToken", "access_token")
self._ini_get(parser, "TGTG", "RefreshToken", "refresh_token")
self._ini_get(parser, "TGTG", "UserID", "user_id")
self._ini_get(parser, "TGTG", "Datadome", "datadome")
self._ini_get_int(parser, "TGTG", "Timeout", "timeout")
self._ini_get_int(parser, "TGTG", "AccessTokenLifetime", "access_token_lifetime")
Expand All @@ -496,7 +494,6 @@ def _read_env(self):
self._env_get("TGTG_USERNAME", "username")
self._env_get("TGTG_ACCESS_TOKEN", "access_token")
self._env_get("TGTG_REFRESH_TOKEN", "refresh_token")
self._env_get("TGTG_USER_ID", "user_id")
self._env_get("TGTG_DATADOME", "datadome")
self._env_get_int("TGTG_TIMEOUT", "timeout")
self._env_get_int("TGTG_ACCESS_TOKEN_LIFETIME", "access_token_lifetime")
Expand Down Expand Up @@ -655,16 +652,14 @@ def _load_tokens(self) -> None:
self.tgtg.access_token = file.read()
with self._open("refreshToken", "r") as file:
self.tgtg.refresh_token = file.read()
with self._open("userID", "r") as file:
self.tgtg.user_id = file.read()
with self._open("datadome", "r") as file:
self.tgtg.datadome = file.read()
except FileNotFoundError:
log.warning("No token files in token path.")
except EnvironmentError as err:
log.error("Error loading Tokens - %s", err)

def save_tokens(self, access_token: str, refresh_token: str, user_id: str, datadome: str) -> None:
def save_tokens(self, access_token: str, refresh_token: str, datadome: str) -> None:
"""
Saves TGTG Access Tokens to config.ini
if provided or as files to token_path.
Expand All @@ -679,7 +674,6 @@ def save_tokens(self, access_token: str, refresh_token: str, user_id: str, datad
config.add_section("TGTG")
config.set("TGTG", "AccessToken", access_token)
config.set("TGTG", "RefreshToken", refresh_token)
config.set("TGTG", "UserId", user_id)
config.set("TGTG", "Datadome", datadome)
with open(config_file, "w", encoding="utf-8") as configfile:
configfile.write(CONFIG_FILE_HEADER)
Expand All @@ -692,8 +686,6 @@ def save_tokens(self, access_token: str, refresh_token: str, user_id: str, datad
file.write(access_token)
with self._open("refreshToken", "w") as file:
file.write(refresh_token)
with self._open("userID", "w") as file:
file.write(user_id)
with self._open("datadome", "w") as file:
file.write(datadome)
except EnvironmentError as err:
Expand Down
7 changes: 5 additions & 2 deletions tgtg_scanner/notifiers/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ async def _listen_for_items(self):
item = self.queue.get(block=False)
if item is None:
self.bot.dispatch("close")
await self.bot.close()
return
log.debug("Sending %s Notification", self.name)
await self._send(item)
Expand All @@ -89,7 +88,11 @@ def _run(self):
if not self.disable_commands:
# Commands are handled separately, in case commands are not enabled
self._setup_commands()
asyncio.run(self.bot.start(self.token))
asyncio.run(self._start_bot())

async def _start_bot(self):
async with self.bot:
await self.bot.start(self.token)

def _setup_events(self):
@self.bot.event
Expand Down
3 changes: 0 additions & 3 deletions tgtg_scanner/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def __init__(self, config: Config):
polling_wait_time=self.config.tgtg.polling_wait_time,
access_token=self.config.tgtg.access_token,
refresh_token=self.config.tgtg.refresh_token,
user_id=self.config.tgtg.user_id,
datadome_cookie=self.config.tgtg.datadome,
base_url=self.config.tgtg.base_url,
)
Expand Down Expand Up @@ -127,7 +126,6 @@ def _job(self) -> None:
self.config.save_tokens(
self.tgtg_client.access_token,
self.tgtg_client.refresh_token,
self.tgtg_client.user_id,
self.tgtg_client.datadome_cookie,
)

Expand Down Expand Up @@ -184,7 +182,6 @@ def run(self) -> NoReturn:
self.config.save_tokens(
self.tgtg_client.access_token,
self.tgtg_client.refresh_token,
self.tgtg_client.user_id,
self.tgtg_client.datadome_cookie,
)
# activate location service
Expand Down
Loading

0 comments on commit 6358ed1

Please sign in to comment.