surfaces/adapter/matrix/handlers/auth.py

163 lines
4.5 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.

from __future__ import annotations
from typing import Any
import structlog
from nio.api import RoomVisibility
from nio.responses import RoomCreateError
from adapter.matrix.store import (
get_user_meta,
next_platform_chat_id,
set_room_meta,
set_user_meta,
)
logger = structlog.get_logger(__name__)
def _default_room_name(chat_id: str) -> str:
suffix = chat_id[1:] if chat_id.startswith("C") else chat_id
return f"Чат {suffix}"
async def provision_workspace_chat(
client: Any,
matrix_user_id: str,
display_name: str,
platform,
store,
auth_mgr,
chat_mgr,
room_name_override: str | None = None,
) -> dict:
user = await platform.get_or_create_user(
external_id=matrix_user_id,
platform="matrix",
display_name=display_name,
)
await auth_mgr.confirm(matrix_user_id)
homeserver = matrix_user_id.split(":")[-1]
user_meta = await get_user_meta(store, matrix_user_id) or {}
space_id = user_meta.get("space_id")
if not space_id:
space_resp = await client.room_create(
name=f"Lambda — {display_name}",
space=True,
visibility=RoomVisibility.private,
invite=[matrix_user_id],
)
if isinstance(space_resp, RoomCreateError):
logger.error(
"space creation failed",
user=matrix_user_id,
error=getattr(space_resp, "status_code", None),
)
raise RuntimeError("Не удалось создать Space.")
space_id = space_resp.room_id
user_meta["space_id"] = space_id
await set_user_meta(store, matrix_user_id, user_meta)
next_chat_index = int(user_meta.get("next_chat_index", 1))
chat_id = f"C{next_chat_index}"
platform_chat_id = await next_platform_chat_id(store)
room_name = room_name_override or _default_room_name(chat_id)
chat_resp = await client.room_create(
name=room_name,
visibility=RoomVisibility.private,
is_direct=False,
invite=[matrix_user_id],
)
if isinstance(chat_resp, RoomCreateError):
logger.error(
"chat room creation failed",
user=matrix_user_id,
error=getattr(chat_resp, "status_code", None),
)
raise RuntimeError("Не удалось создать рабочий чат.")
chat_room_id = chat_resp.room_id
await client.room_put_state(
room_id=space_id,
event_type="m.space.child",
content={"via": [homeserver]},
state_key=chat_room_id,
)
user_meta["space_id"] = space_id
user_meta["next_chat_index"] = next_chat_index + 1
await set_user_meta(store, matrix_user_id, user_meta)
await set_room_meta(
store,
chat_room_id,
{
"room_type": "chat",
"chat_id": chat_id,
"display_name": room_name,
"matrix_user_id": matrix_user_id,
"space_id": space_id,
"platform_chat_id": platform_chat_id,
},
)
await chat_mgr.get_or_create(
user_id=matrix_user_id,
chat_id=chat_id,
platform="matrix",
surface_ref=chat_room_id,
name=room_name,
)
return {
"user": user,
"space_id": space_id,
"chat_room_id": chat_room_id,
"chat_id": chat_id,
"room_name": room_name,
}
async def handle_invite(
client: Any,
room: Any,
event: Any,
platform,
store,
auth_mgr,
chat_mgr,
) -> None:
matrix_user_id = getattr(event, "sender", "")
display_name = getattr(room, "display_name", None) or matrix_user_id
await client.join(room.room_id)
existing = await get_user_meta(store, matrix_user_id)
if existing and existing.get("space_id"):
return
try:
created = await provision_workspace_chat(
client,
matrix_user_id,
display_name,
platform,
store,
auth_mgr,
chat_mgr,
room_name_override="Чат 1",
)
except RuntimeError as exc:
logger.error("invite_workspace_provision_failed", user=matrix_user_id, error=str(exc))
return
welcome = (
f"Привет, {created['user'].display_name or matrix_user_id}! Пиши — я здесь.\n\n"
"Команды: !new · !chats · !rename · !archive · !context · !save · !load · !help"
)
await client.room_send(
created["chat_room_id"],
"m.room.message",
{"msgtype": "m.text", "body": welcome},
)