pyscape/main.py
2025-05-02 10:06:51 +02:00

173 lines
6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
import sys
import json
import logging
import pyscape
import pyscape.utils
import pyscape.ui
import pyscape.game
# Настройка логирования
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s")
def launch_game_with_token(token, id_token):
"""
Запускает игру с переданным токеном и id_token.
"""
try:
id_token_payload = pyscape.parse_id_token(id_token)
except Exception as e:
raise e
# Получаем данные пользователя по sub из id_token
sub = id_token_payload["sub"]
user = pyscape.get_user_details(sub, token["access_token"])
logging.info("You are logged in as: {}#{}".format(user.display_name, user.suffix))
# Проверка поля login_provider в JWT
if (
"login_provider" not in id_token_payload
or id_token_payload["login_provider"] != pyscape.LOGIN_PROVIDER
):
logging.info(
"No known login_provider found in JWT token, using standard login..."
)
code, new_id_token = pyscape.standard_login(id_token)
# tup предполагается как кортеж, где второй элемент обновлённый id_token
pyscape.utils.write_to_config_file(new_id_token, "id_token")
session_id = pyscape.get_game_session(new_id_token)
accounts = pyscape.get_accounts(session_id)
logging.info("Found {} accounts".format(len(accounts)))
try:
account = pyscape.ui.get_chosen_account(user, accounts)
except pyscape.NoAccountChosenError:
logging.info("No account was chosen")
return
pyscape.game.launch_game(session_id, account)
def handle_social_auth(payload, refresh: bool = False):
"""
Обрабатывает social_auth: обменивает код на токен, сохраняет данные и запускает игру.
"""
if not refresh:
try:
token = pyscape.exchange(payload["code"])
except Exception as e:
raise e
else:
print("REFRESH")
token = payload
# Если метод extra недоступен, возможно, токен представлен как словарь
id_token = token.get("id_token")
if not id_token:
raise Exception("id_token not found in token response")
pyscape.utils.write_to_config_file(id_token, "id_token")
# Вычисляем время истечения токена как текущее время + время жизни токена (в секундах)
expiry = int(time.time() + token["expires_in"] * 1000)
token["expiry"] = expiry
# Сериализуем OAuth токен в JSON
token_json = json.dumps(token)
pyscape.utils.write_to_config_file(token_json, "token")
launch_game_with_token(token, id_token)
def get_cached_tokens():
"""
Читает сохранённые токены из конфигурационного файла.
Если срок действия токена истёк (или почти истёк), возбуждает исключение.
"""
token_json = pyscape.utils.read_from_config_file("token")
try:
token = json.loads(token_json)
except json.JSONDecodeError as e:
raise Exception("Invalid token JSON") from e
import datetime
current_time = datetime.datetime.now()
# Если до истечения токена осталось менее 30 минут, считаем его недействительным.
if (
datetime.datetime.fromtimestamp(token["expiry"]) - current_time
) <= datetime.timedelta(minutes=30):
raise Exception("cached token has expired")
id_token = pyscape.utils.read_from_config_file("id_token")
return token, id_token
def handle_regular_launch():
"""
Пытается использовать сохранённые токены для запуска игры,
иначе инициирует стандартный процесс аутентификации.
"""
try:
token, id_token = get_cached_tokens()
try:
refresh_result = pyscape.refresh_token(token["refresh_token"])
handle_social_auth(refresh_result, True)
except Exception as e:
print(str(e))
pyscape.login()
return
except Exception as e:
logging.info(
f"Could not load cached tokens, initiating regular login flow: {e}"
)
pyscape.login()
return
logging.info("Loaded cached tokens")
try:
launch_game_with_token(token, id_token)
except Exception as e:
print(e)
logging.info(
"Could not login with cached tokens, initiating regular login flow"
)
pyscape.login()
def main():
"""
Основная функция приложения.
Если аргументы командной строки не заданы используется регулярный запуск,
иначе выполняется разбор intent из payload.
"""
# Если отсутствуют дополнительные аргументы, инициируем регулярный запуск.
if len(sys.argv) < 2:
try:
handle_regular_launch()
except Exception as e:
logging.error(e)
sys.exit(1)
sys.exit(0)
# Если передан аргумент, то он рассматривается как payload для intent.
payload = pyscape.utils.parse_intent_payload(sys.argv[1])
if "intent" not in payload:
logging.fatal("No intent found in payload: {}".format(payload))
sys.exit(1)
if payload["intent"] == "social_auth":
try:
handle_social_auth(payload)
except Exception as e:
pyscape.utils.die(e)
raise
input("Press Enter to exit...")
if __name__ == "__main__":
main()