112 lines
3.8 KiB
Python
112 lines
3.8 KiB
Python
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 |