From 746c7933ca3b4dca3886969f041224b1c44f240d Mon Sep 17 00:00:00 2001 From: oldnapalm <38410858+oldnapalm@users.noreply.github.com> Date: Mon, 15 Jul 2024 21:00:20 -0300 Subject: [PATCH] Download economy config --- README.md | 2 +- online_sync.py | 23 ++++++++++++++++++++++- scripts/get_profile.py | 39 ++++++++++++++++++++++++++++++++++++--- scripts/get_profile.spec | 2 +- zwift_offline.py | 10 ++++++++-- 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4e29205d..49ec4538 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ To obtain your current profile: * Ensure zoffline is disabled. * Run ``scripts/get_profile.py -u `` * Or, if using the Windows zoffline.exe version without Python installed you can run ``get_profile.exe`` obtained from https://github.com/zoffline/zwift-offline/releases/tag/zoffline_helper in place of ``scripts/get_profile.py`` -* Move the resulting ``profile.bin`` and ``achievements.bin`` (saved in whatever directory you ran get_profile.py in) into the ``storage/1`` directory. +* Move the resulting ``profile.bin``, ``achievements.bin`` and ``economy_config.txt`` (saved in whatever directory you ran get_profile.py in) into the ``storage/1`` directory. * If using zoffline.exe on Windows, create a ``storage/1`` directory within the same folder as zoffline.exe if it does not already exist. * If using Docker, the directory ``1`` should be in the path you passed to ``-v`` diff --git a/online_sync.py b/online_sync.py index 75ee70d4..61bfa857 100755 --- a/online_sync.py +++ b/online_sync.py @@ -66,7 +66,7 @@ def post_credentials(session, username, password): print('Invalid uname and/or password') -def query(session, access_token, route): +def get(session, access_token, route): try: response = session.get( url="https://us-or-rly101.zwift.com/%s" % route, @@ -87,6 +87,27 @@ def query(session, access_token, route): print('HTTP Request failed: %s' % e) +def post(session, access_token, route): + try: + response = session.post( + url="https://us-or-rly101.zwift.com/%s" % route, + headers={ + "Content-Type": "application/x-protobuf-lite", + "Accept": "application/x-protobuf-lite", + "Connection": "keep-alive", + "Host": "us-or-rly101.zwift.com", + "User-Agent": "Zwift/115 CFNetwork/758.0.2 Darwin/15.0.0", + "Authorization": "Bearer %s" % access_token, + "Accept-Language": "en-us", + }, + ) + + return response.content + + except requests.exceptions.RequestException as e: + print('HTTP Request failed: %s' % e) + + def logout(session, refresh_token): # Logout # POST https://secure.zwift.com/auth/realms/zwift/tokens/logout diff --git a/scripts/get_profile.py b/scripts/get_profile.py index d0217d7f..085dd411 100755 --- a/scripts/get_profile.py +++ b/scripts/get_profile.py @@ -31,6 +31,9 @@ import os import requests import sys +sys.path.insert(0, '../protobuf') +import login_pb2 +from google.protobuf.json_format import MessageToDict if getattr(sys, 'frozen', False): @@ -92,7 +95,7 @@ def post_credentials(session, username, password): exit(-1) -def query(session, access_token, route): +def get(session, access_token, route): try: response = session.get( url="https://us-or-rly101.zwift.com/%s" % route, @@ -118,6 +121,32 @@ def query(session, access_token, route): print('HTTP Request failed: %s' % e) +def post(session, access_token, route): + try: + response = session.post( + url="https://us-or-rly101.zwift.com/%s" % route, + headers={ + "Content-Type": "application/x-protobuf-lite", + "Accept": "application/x-protobuf-lite", + "Connection": "keep-alive", + "Host": "us-or-rly101.zwift.com", + "User-Agent": "Zwift/115 CFNetwork/758.0.2 Darwin/15.0.0", + "Authorization": "Bearer %s" % access_token, + "Accept-Language": "en-us", + }, + verify=args.verifyCert, + ) + + if args.verbose: + print('Response HTTP Status Code: {status_code}'.format( + status_code=response.status_code)) + + return response.content + + except requests.exceptions.RequestException as e: + print('HTTP Request failed: %s' % e) + + def logout(session, refresh_token): # Logout # POST https://secure.zwift.com/auth/realms/zwift/tokens/logout @@ -197,12 +226,16 @@ def main(argv): session = requests.session() access_token, refresh_token = login(session, username, password) - profile = query(session, access_token, "api/profiles/me") + profile = get(session, access_token, "api/profiles/me") with open('%s/profile.bin' % SCRIPT_DIR, 'wb') as f: f.write(profile) - achievements = query(session, access_token, "achievement/loadPlayerAchievements") + achievements = get(session, access_token, "achievement/loadPlayerAchievements") with open('%s/achievements.bin' % SCRIPT_DIR, 'wb') as f: f.write(achievements) + login_response = login_pb2.LoginResponse() + login_response.ParseFromString(post(session, access_token, "api/users/login")) + with open('%s/economy_config.txt' % SCRIPT_DIR, 'w') as f: + json.dump(MessageToDict(login_response, preserving_proto_field_name=True)['economy_config'], f, indent=2) logout(session, refresh_token) diff --git a/scripts/get_profile.spec b/scripts/get_profile.spec index afbe299f..da50d08c 100644 --- a/scripts/get_profile.spec +++ b/scripts/get_profile.spec @@ -6,7 +6,7 @@ import sys sys.modules['FixTk'] = None a = Analysis(['get_profile.py'], - pathex=[], + pathex=['../protobuf'], binaries=[], datas=[], hiddenimports=[], diff --git a/zwift_offline.py b/zwift_offline.py index 752424d7..ea4f7e80 100644 --- a/zwift_offline.py +++ b/zwift_offline.py @@ -845,13 +845,19 @@ def profile(username): access_token, refresh_token = online_sync.login(session, username, password) try: if request.form.get("zwift_profile"): - profile = online_sync.query(session, access_token, "api/profiles/me") + profile = online_sync.get(session, access_token, "api/profiles/me") profile_file = '%s/profile.bin' % profile_dir backup_file(profile_file) with open(profile_file, 'wb') as f: f.write(profile) + login_response = login_pb2.LoginResponse() + login_response.ParseFromString(online_sync.post(session, access_token, "api/users/login")) + economy_config_file = '%s/economy_config.txt' % profile_dir + backup_file(economy_config_file) + with open(economy_config_file, 'w') as f: + json.dump(MessageToDict(login_response, preserving_proto_field_name=True)['economy_config'], f, indent=2) if request.form.get("achievements"): - achievements = online_sync.query(session, access_token, "achievement/loadPlayerAchievements") + achievements = online_sync.get(session, access_token, "achievement/loadPlayerAchievements") achievements_file = '%s/achievements.bin' % profile_dir backup_file(achievements_file) with open(achievements_file, 'wb') as f: