feat: Add Chat API endpoints for Matrix integration
City Service:
- GET /api/v1/chat/rooms/{room_id}/messages - get message history
- POST /api/v1/chat/rooms/{room_id}/messages - send message
- Add get_room_by_id to repo_city
Synapse:
- Increase rate limits for room creation
- Add rc_joins, rc_invites configuration
All 27 rooms now have matrix_room_id
This commit is contained in:
@@ -142,6 +142,24 @@ async def get_room_by_slug(slug: str) -> Optional[dict]:
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
async def get_room_by_id(room_id: str) -> Optional[dict]:
|
||||
"""Отримати кімнату по ID (UUID)"""
|
||||
pool = await get_pool()
|
||||
|
||||
query = """
|
||||
SELECT
|
||||
cr.id, cr.slug, cr.name, cr.description, cr.is_default, cr.created_at, cr.created_by,
|
||||
cr.matrix_room_id, cr.matrix_room_alias, cr.logo_url, cr.banner_url,
|
||||
cr.microdao_id, m.name AS microdao_name, m.slug AS microdao_slug, m.logo_url AS microdao_logo_url
|
||||
FROM city_rooms cr
|
||||
LEFT JOIN microdaos m ON cr.microdao_id = m.id
|
||||
WHERE cr.id = $1
|
||||
"""
|
||||
|
||||
row = await pool.fetchrow(query, room_id)
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
async def create_room(
|
||||
slug: str,
|
||||
name: str,
|
||||
|
||||
@@ -1589,6 +1589,102 @@ async def get_microdao_chat_room(slug: str):
|
||||
raise HTTPException(status_code=500, detail="Failed to get microdao chat room")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Chat API (TASK_PHASE_MATRIX_FINALIZE_v2)
|
||||
# =============================================================================
|
||||
|
||||
class SendMessageRequest(BaseModel):
|
||||
body: str
|
||||
sender: Optional[str] = None
|
||||
|
||||
|
||||
class ChatMessage(BaseModel):
|
||||
event_id: str
|
||||
sender: str
|
||||
body: str
|
||||
timestamp: int
|
||||
|
||||
|
||||
@api_router.get("/chat/rooms/{room_id}/messages")
|
||||
async def get_chat_messages(room_id: str, limit: int = 50):
|
||||
"""
|
||||
Отримати історію повідомлень з Matrix кімнати.
|
||||
room_id може бути slug або UUID кімнати.
|
||||
"""
|
||||
try:
|
||||
# Get room from DB
|
||||
room = await repo_city.get_room_by_id(room_id)
|
||||
if not room:
|
||||
# Try by slug
|
||||
room = await repo_city.get_room_by_slug(room_id)
|
||||
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail=f"Room not found: {room_id}")
|
||||
|
||||
matrix_room_id = room.get("matrix_room_id")
|
||||
if not matrix_room_id:
|
||||
raise HTTPException(status_code=400, detail="Room has no Matrix integration")
|
||||
|
||||
# Get messages from Matrix via gateway
|
||||
messages = await get_room_messages(matrix_room_id, limit=limit)
|
||||
|
||||
return {
|
||||
"room_id": room.get("id"),
|
||||
"room_slug": room.get("slug"),
|
||||
"matrix_room_id": matrix_room_id,
|
||||
"messages": messages,
|
||||
"count": len(messages)
|
||||
}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get chat messages for {room_id}: {e}")
|
||||
raise HTTPException(status_code=500, detail="Failed to get chat messages")
|
||||
|
||||
|
||||
@api_router.post("/chat/rooms/{room_id}/messages")
|
||||
async def send_chat_message(room_id: str, payload: SendMessageRequest):
|
||||
"""
|
||||
Надіслати повідомлення в Matrix кімнату.
|
||||
room_id може бути slug або UUID кімнати.
|
||||
"""
|
||||
try:
|
||||
# Get room from DB
|
||||
room = await repo_city.get_room_by_id(room_id)
|
||||
if not room:
|
||||
# Try by slug
|
||||
room = await repo_city.get_room_by_slug(room_id)
|
||||
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail=f"Room not found: {room_id}")
|
||||
|
||||
matrix_room_id = room.get("matrix_room_id")
|
||||
if not matrix_room_id:
|
||||
raise HTTPException(status_code=400, detail="Room has no Matrix integration")
|
||||
|
||||
# Send message via gateway
|
||||
event_id = await send_message_to_room(
|
||||
room_id=matrix_room_id,
|
||||
body=payload.body,
|
||||
sender=payload.sender
|
||||
)
|
||||
|
||||
if not event_id:
|
||||
raise HTTPException(status_code=500, detail="Failed to send message to Matrix")
|
||||
|
||||
return {
|
||||
"ok": True,
|
||||
"event_id": event_id,
|
||||
"room_id": room.get("id"),
|
||||
"matrix_room_id": matrix_room_id
|
||||
}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send chat message to {room_id}: {e}")
|
||||
raise HTTPException(status_code=500, detail="Failed to send chat message")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Presence API (TASK_PHASE_AGENT_PRESENCE_INDICATORS_MVP)
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user