185 lines
7.4 KiB
Python
185 lines
7.4 KiB
Python
import login
|
|
import answers
|
|
import sys
|
|
|
|
from nio import (
|
|
MatrixRoom,
|
|
RoomMessageText,
|
|
InviteMemberEvent,
|
|
MegolmEvent,
|
|
KeyVerificationStart,
|
|
KeyVerificationKey,
|
|
KeyVerificationMac,
|
|
KeyVerificationCancel,
|
|
LocalProtocolError,
|
|
ToDeviceError
|
|
)
|
|
|
|
WELCOME_MSG = "Добро пожаловать ко мне, УЕБОТУ! АХАХА\n" \
|
|
"И так, вот что я умею:\n" \
|
|
"1. Сервер — Данные об использовании сервера.\n" \
|
|
"2. Погода в <город> — Погода в городе.=(тестово).\n" \
|
|
"3. SCP — Выдача случайного объекта фонда для чтения.\n" \
|
|
"4. SCP классы — Описание классов.\n" \
|
|
"5. Помощь — Это меню.\n\n" \
|
|
"Можете писать слова(Пример: Сервер) или цифрой(Пример: 1)."
|
|
|
|
client = None
|
|
|
|
async def message_callback(room: MatrixRoom, event: RoomMessageText):
|
|
print(f"[DEBUG] Открытое сообщение от {event.sender}.")
|
|
if event.sender == client.user_id:
|
|
return
|
|
|
|
content = None
|
|
|
|
if event.body.lower() == "сервер" or event.body == "1":
|
|
content = answers.system_request()
|
|
elif event.body.lower() == "погода" or event.body == "2":
|
|
content = answers.weather_request()
|
|
elif event.body.lower() == "scp" or event.body == "3":
|
|
content = answers.scp_request()
|
|
elif event.body.lower() == "scp классы" or event.body == "4":
|
|
content = answers.scp_classed()
|
|
else:
|
|
content = answers.unknown_request()
|
|
|
|
content += answers.help_request()
|
|
|
|
await send_message(room, content)
|
|
|
|
|
|
async def megolm_callback(room: MatrixRoom, event: MegolmEvent):
|
|
try:
|
|
decrypted = await client.decrypt_event(event)
|
|
except Exception as e:
|
|
print(f"[ERROR] Расшифровка не удалась: {e}")
|
|
return
|
|
|
|
if isinstance(decrypted, RoomMessageText):
|
|
print(f"[DEBUG] Расшифровано: {decrypted.body}")
|
|
if decrypted.sender == client.user_id:
|
|
return
|
|
await send_message(room, decrypted.body)
|
|
else:
|
|
print(f"[DEBUG] Расшифровано, но не текст: {type(decrypted).__name__}")
|
|
|
|
|
|
async def invite_callback(room: MatrixRoom, event: InviteMemberEvent):
|
|
print(f"[INFO] Приглашение в комнату {room.room_id}")
|
|
await client.join(room.room_id)
|
|
await send_message(room, WELCOME_MSG)
|
|
|
|
|
|
async def trust_user_devices(user_id: str, device_ids=None):
|
|
"""Доверие устройствам пользователя (локально, без интерактивной верификации)."""
|
|
if user_id == client.user_id:
|
|
return
|
|
if user_id not in client.device_store:
|
|
print(f"[WARN] Устройства {user_id} пока не известны.")
|
|
return
|
|
|
|
devices = client.device_store[user_id]
|
|
trusted = 0
|
|
for device_id, olm_device in devices.items():
|
|
if device_ids and device_id not in device_ids:
|
|
continue
|
|
try:
|
|
client.verify_device(olm_device)
|
|
print(f"[OK] Доверено устройство {device_id} пользователя {user_id}.")
|
|
trusted += 1
|
|
except Exception as e:
|
|
print(f"[ERROR] Не удалось доверить {device_id}: {e}")
|
|
if trusted == 0:
|
|
print(f"[WARN] Ни одно устройство {user_id} не было доверено.")
|
|
|
|
async def send_message(room: MatrixRoom, text: str):
|
|
CHUNK = 5000
|
|
if len(text) > CHUNK:
|
|
start = 0
|
|
end = 0
|
|
while start < len(text):
|
|
end = start + CHUNK
|
|
if end < len(text):
|
|
while text[end] != ".":
|
|
end -= 1
|
|
|
|
end += 1
|
|
chunk = text[start:end]
|
|
await client.room_send(
|
|
room_id = room.room_id,
|
|
message_type = "m.room.message",
|
|
content = {"msgtype" : "m.text", "body" : chunk},
|
|
ignore_unverified_devices = True
|
|
)
|
|
|
|
start = end
|
|
print(start)
|
|
else:
|
|
await client.room_send(
|
|
room_id = room.room_id,
|
|
message_type = "m.room.message",
|
|
content = {"msgtype" : "m.text", "body" : text},
|
|
ignore_unverified_devices = True
|
|
)
|
|
|
|
async def after_first_sync():
|
|
print("[INFO] Ожидание первого синка...")
|
|
await client.synced.wait()
|
|
print("[INFO] Первый синк выполнен. Доверяем устройствам...")
|
|
for user_id in login.TRUST_USERS:
|
|
await trust_user_devices(user_id)
|
|
|
|
async def to_device_callback(event):
|
|
"""Автоматически принимает и подтверждает SAS-верификацию от доверенных пользователей."""
|
|
try:
|
|
if isinstance(event, KeyVerificationStart):
|
|
if event.sender not in login.TRUST_USERS:
|
|
print(f"[WARN] Верификация от недоверенного пользователя {event.sender}, игнорируем.")
|
|
return
|
|
if "emoji" not in event.short_authentication_string:
|
|
print(f"[WARN] Устройство {event.sender} не поддерживает эмодзи-верификацию.")
|
|
return
|
|
|
|
print(f"[INFO] Принимаем запрос на верификацию от {event.sender}...")
|
|
resp = await client.accept_key_verification(event.transaction_id)
|
|
if isinstance(resp, ToDeviceError):
|
|
print(f"[ERROR] accept_key_verification: {resp}")
|
|
return
|
|
|
|
sas = client.key_verifications[event.transaction_id]
|
|
todevice_msg = sas.share_key()
|
|
resp = await client.to_device(todevice_msg)
|
|
if isinstance(resp, ToDeviceError):
|
|
print(f"[ERROR] to_device (share_key): {resp}")
|
|
|
|
elif isinstance(event, KeyVerificationKey):
|
|
sas = client.key_verifications[event.transaction_id]
|
|
print(f"[INFO] Эмодзи: {sas.get_emoji()}")
|
|
# Автоматически подтверждаем совпадение
|
|
resp = await client.confirm_short_auth_string(event.transaction_id)
|
|
if isinstance(resp, ToDeviceError):
|
|
print(f"[ERROR] confirm_short_auth_string: {resp}")
|
|
else:
|
|
print("[INFO] SAS подтверждён автоматически.")
|
|
|
|
elif isinstance(event, KeyVerificationMac):
|
|
sas = client.key_verifications[event.transaction_id]
|
|
try:
|
|
todevice_msg = sas.get_mac()
|
|
except LocalProtocolError as e:
|
|
print(f"[WARN] Верификация прервана: {e}")
|
|
return
|
|
resp = await client.to_device(todevice_msg)
|
|
if isinstance(resp, ToDeviceError):
|
|
print(f"[ERROR] to_device (mac): {resp}")
|
|
else:
|
|
print(f"[OK] Верификация с {event.sender} завершена. "
|
|
f"Доверенные устройства: {sas.verified_devices}")
|
|
|
|
elif isinstance(event, KeyVerificationCancel):
|
|
print(f"[INFO] Верификация отменена: {event.reason}")
|
|
|
|
except Exception as e:
|
|
print(f"[ERROR] to_device_callback: {e}")
|