feat: 网页端固定主用户,Matrix /new创建新会话,实时同步

This commit is contained in:
2026-04-11 12:29:11 +08:00
parent b05a03e198
commit b228283133
5 changed files with 206 additions and 128 deletions

View File

@@ -1,17 +1,21 @@
"""
Matrix Bot 服务 - 处理Matrix消息收发
所有消息都同步到主用户的最新会话
"""
import asyncio
import json
from typing import Optional, Callable
from nio import AsyncClient, MatrixRoom, RoomMessageText, LoginResponse, SyncResponse
from nio import AsyncClient, MatrixRoom, RoomMessageText, LoginResponse
import logging
from models import SessionLocal, User, Conversation, Message, MatrixRoomMapping, SystemConfig
from models import SessionLocal, User, Conversation, Message, SystemConfig
from services.conversation_service import ConversationService
logger = logging.getLogger(__name__)
# 主用户ID
MAIN_USER_ID = "main_user"
class MatrixBot:
def __init__(self):
@@ -45,14 +49,12 @@ class MatrixBot:
return False
try:
# 创建客户端
self.client = AsyncClient(
self.homeserver,
self.username,
store_path="/tmp/matrix_store"
)
# 如果有access_token直接设置
if self.access_token:
self.client.access_token = self.access_token
self.client.user_id = self.username
@@ -60,7 +62,6 @@ class MatrixBot:
self.is_running = True
return True
# 否则使用密码登录
response = await self.client.login(self.password)
if isinstance(response, LoginResponse):
@@ -85,14 +86,12 @@ class MatrixBot:
# 注册消息处理器
self.client.add_event_callback(self._handle_room_message, RoomMessageText)
# 首先执行一次同步获取房间信息
try:
sync_response = await self.client.sync(timeout=10000)
logger.info(f"Matrix初始同步完成")
await self.client.sync(timeout=10000)
logger.info("Matrix初始同步完成")
except Exception as e:
logger.warning(f"Matrix初始同步失败: {e}, 将尝试继续")
logger.warning(f"Matrix初始同步失败: {e}")
# 启动后台同步任务(不阻塞)
asyncio.create_task(self._sync_loop())
logger.info("Matrix同步任务已启动")
@@ -100,65 +99,77 @@ class MatrixBot:
"""后台同步循环"""
while self.is_running:
try:
# 使用较短的超时,避免长时间阻塞
await self.client.sync(timeout=5000)
await asyncio.sleep(1) # 每秒同步一次
await asyncio.sleep(1)
except Exception as e:
logger.warning(f"Matrix同步错误: {e}")
await asyncio.sleep(5) # 出错后等待5秒再重试
await asyncio.sleep(5)
async def _handle_room_message(self, room: MatrixRoom, event: RoomMessageText):
"""处理收到的房间消息"""
"""处理Matrix消息 - 所有消息同步到主用户最新会话"""
# 忽略自己发送的消息
if event.sender == self.username:
return
message_text = event.body.strip()
db = SessionLocal()
try:
conv_service = ConversationService(db)
# 获取或创建Matrix用户
matrix_user_id = event.sender
user = conv_service.get_or_create_user(
user_id=matrix_user_id,
display_name=room.users.get(matrix_user_id, {}).get('display_name', matrix_user_id),
user_type='matrix',
matrix_user_id=matrix_user_id
# 使用固定主用户
main_user = conv_service.get_or_create_user(
MAIN_USER_ID,
display_name="主用户",
user_type='web'
)
# 获取或创建房间映射
mapping = db.query(MatrixRoomMapping).filter(
MatrixRoomMapping.room_id == room.room_id
).first()
# 处理 /new 命令 - 创建新会话,不回复
if message_text == "/new":
conversation = conv_service.create_conversation(main_user.id)
await self.send_message(room.room_id, "✅ 已创建新会话")
logger.info(f"Matrix创建新会话: {conversation.conversation_id}")
# 通知WebSocket客户端
if self.on_message_callback:
await self.on_message_callback(
action="new_conversation",
conversation_id=conversation.conversation_id,
room_id=room.room_id
)
return
if not mapping:
# 为这个房间创建新会话
conversation = conv_service.create_conversation(user.id, title=f"Matrix: {room.display_name}")
mapping = MatrixRoomMapping(
room_id=room.room_id,
user_id=user.id,
conversation_id=conversation.id
)
db.add(mapping)
db.commit()
db.refresh(mapping)
# 获取最新会话
conversations = conv_service.get_user_conversations(main_user.id)
if not conversations:
# 如果没有会话,创建一个
conversation = conv_service.create_conversation(main_user.id)
else:
conversation = conversations[0] # 最新会话
# 保存用户消息
conv_service.add_message(
conversation_id=mapping.conversation_id,
user_msg = conv_service.add_message(
conversation_id=conversation.id,
role='user',
content=event.body,
content=message_text,
source='matrix',
extra_data={'event_id': event.event_id, 'room_id': room.room_id}
extra_data={
'event_id': event.event_id,
'room_id': room.room_id,
'sender': event.sender
}
)
# 调用外部消息处理器
logger.info(f"Matrix消息保存到会话 {conversation.conversation_id}")
# 调用消息处理器获取AI回复并同步
if self.on_message_callback:
await self.on_message_callback(
conversation_id=mapping.conversation.conversation_id,
user_message=event.body,
user_id=user.user_id,
room_id=room.room_id
action="chat",
conversation_id=conversation.conversation_id,
user_message=message_text,
room_id=room.room_id,
message_id=user_msg.id
)
finally:
db.close()
@@ -182,28 +193,12 @@ class MatrixBot:
logger.error(f"发送Matrix消息失败: {e}")
return False
async def get_room_id_for_user(self, user_matrix_id: str) -> Optional[str]:
"""获取与用户的对话房间ID"""
db = SessionLocal()
try:
user = db.query(User).filter(User.matrix_user_id == user_matrix_id).first()
if user:
mapping = db.query(MatrixRoomMapping).filter(
MatrixRoomMapping.user_id == user.id
).first()
if mapping:
return mapping.room_id
return None
finally:
db.close()
async def disconnect(self):
"""断开连接"""
if self.client:
await self.client.logout()
await self.client.close()
self.is_running = False
# 全局实例
matrix_bot = MatrixBot()
try:
await self.client.logout()
await self.client.close()
except:
pass
self.is_running = False