import getpass import json import os import sys from nio import ( AsyncClient, AsyncClientConfig, LoginResponse ) CONFIG_FILE = "./credentials.json" STORE_PATH = "./crypto_store" TRUST_USERS = ["@tema:godnessli.ru"] async def login_from_credentials() -> AsyncClient: """ Аутентификация: - если credentials.json есть — используем сохранённые данные; - если нет — спрашиваем у пользователя и логинимся по паролю, после чего сохраняем данные в credentials.json. Логика взята из официального примера matrix-nio verify_with_emoji.py. """ client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) if not os.path.exists(STORE_PATH): os.makedirs(STORE_PATH) # ===== Вариант 1: файла нет — логинимся по паролю ===== if not os.path.exists(CONFIG_FILE): print("Файл credentials.json не найден. Входим по паролю.") homeserver = input("Введите URL homeserver [https://matrix.example.org]: ").strip() if not homeserver: homeserver = "https://matrix.example.org" if not (homeserver.startswith("https://") or homeserver.startswith("http://")): homeserver = "https://" + homeserver user_id = input("Введите полный user ID [@user:example.org]: ").strip() device_name = input("Имя устройства [echo-bot]: ").strip() if not device_name: device_name = "echo-bot" password = getpass.getpass("Пароль: ") client = AsyncClient( homeserver, user_id, store_path=STORE_PATH, config=client_config, ) resp = await client.login(password=password, device_name=device_name) if not isinstance(resp, LoginResponse): print(f"[FATAL] Не удалось войти: {resp}") sys.exit(1) # Сохраняем данные в credentials.json with open(CONFIG_FILE, "w") as f: json.dump( { "homeserver": homeserver, "user_id": resp.user_id, "device_id": resp.device_id, "access_token": resp.access_token, }, f, indent=2, ) print(f"[INFO] Вход выполнен. Данные сохранены в {CONFIG_FILE}.") print(f"[INFO] user_id={resp.user_id}, device_id={resp.device_id}") # После login нужно вызвать restore_login, чтобы установить # user_id/device_id/access_token и загрузить хранилище E2EE client.restore_login( user_id=resp.user_id, device_id=resp.device_id, access_token=resp.access_token, ) return client # ===== Вариант 2: файл есть — используем сохранённые данные ===== with open(CONFIG_FILE, "r") as f: config = json.load(f) client = AsyncClient( config["homeserver"], config["user_id"], device_id=config["device_id"], store_path=STORE_PATH, config=client_config, ) client.restore_login( user_id=config["user_id"], device_id=config["device_id"], access_token=config["access_token"], ) print( f"[INFO] Вход по сохранённым данным: " f"{config['user_id']} / {config['device_id']}" ) return client