feat(01-01): rewrite matrix invite flow for spaces

- create a private space and first chat room on first invite
- store space metadata and dynamic chat ids for new users
This commit is contained in:
Mikhail Putilovskij 2026-04-02 22:49:59 +03:00
parent 9123401556
commit c2e29ccd1f

View file

@ -1,34 +1,101 @@
from __future__ import annotations
import structlog
from typing import Any
from adapter.matrix.store import get_room_meta, set_room_meta
from nio.responses import RoomCreateError
from adapter.matrix.store import (
get_user_meta,
next_chat_id,
set_room_meta,
set_user_meta,
)
logger = structlog.get_logger(__name__)
async def handle_invite(client: Any, room: Any, event: Any, platform, store, auth_mgr) -> None:
existing = await get_room_meta(store, room.room_id)
if existing is not None:
matrix_user_id = getattr(event, "sender", "")
display_name = getattr(room, "display_name", None) or matrix_user_id
existing = await get_user_meta(store, matrix_user_id)
if existing and existing.get("space_id"):
return
user = await platform.get_or_create_user(
external_id=getattr(event, "sender", ""),
platform="matrix",
display_name=getattr(room, "display_name", None),
)
await auth_mgr.confirm(getattr(event, "sender", ""))
await client.join(room.room_id)
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]
space_resp = await client.room_create(
name=f"Lambda — {display_name}",
space=True,
visibility="private",
)
if isinstance(space_resp, RoomCreateError):
logger.error(
"space creation failed",
user=matrix_user_id,
error=getattr(space_resp, "status_code", None),
)
return
space_id = space_resp.room_id
chat_resp = await client.room_create(
name="Чат 1",
visibility="private",
is_direct=False,
)
if isinstance(chat_resp, RoomCreateError):
logger.error(
"chat room creation failed",
user=matrix_user_id,
error=getattr(chat_resp, "status_code", None),
)
return
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,
)
await client.room_invite(space_id, matrix_user_id)
await client.room_invite(chat_room_id, matrix_user_id)
chat_id = await next_chat_id(store, matrix_user_id)
user_meta = await get_user_meta(store, matrix_user_id) or {}
user_meta["space_id"] = space_id
await set_user_meta(store, matrix_user_id, user_meta)
await set_room_meta(
store,
room.room_id,
chat_room_id,
{
"room_type": "chat",
"chat_id": "C1",
"display_name": getattr(room, "display_name", room.room_id),
"matrix_user_id": getattr(event, "sender", user.external_id),
"chat_id": chat_id,
"display_name": "Чат 1",
"matrix_user_id": matrix_user_id,
"space_id": space_id,
},
)
message = (
f"Привет, {user.display_name or user.external_id}! Пиши — я здесь.\n\n"
f"Команды: !new · !chats · !rename · !archive · !skills"
welcome = (
f"Привет, {user.display_name or matrix_user_id}! Пиши — я здесь.\n\n"
"Команды: !new · !chats · !rename · !archive · !skills · !soul · !safety · !settings"
)
await client.room_send(
chat_room_id,
"m.room.message",
{"msgtype": "m.text", "body": welcome},
)
await client.room_send(room.room_id, "m.room.message", {"msgtype": "m.text", "body": message})