From c2e29ccd1f4be1a8c07ed2c62b2b0a1a43f4aff4 Mon Sep 17 00:00:00 2001 From: Mikhail Putilovskij Date: Thu, 2 Apr 2026 22:49:59 +0300 Subject: [PATCH] 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 --- adapter/matrix/handlers/auth.py | 101 ++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/adapter/matrix/handlers/auth.py b/adapter/matrix/handlers/auth.py index bb8b332..ba8a989 100644 --- a/adapter/matrix/handlers/auth.py +++ b/adapter/matrix/handlers/auth.py @@ -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})