fix: 修复messages类型问题和设备验证问题

1. 使用 get_conversation_history 返回字典列表
2. send_message 增加设备验证回退机制
3. 当 nio 发送失败时回退到 HTTP API

依赖:python-olm, cachetools, atomicwrites, peewee
This commit is contained in:
2026-04-11 23:49:15 +08:00
parent ac7a329e53
commit d018342b45
3 changed files with 78 additions and 40 deletions

View File

@@ -106,53 +106,48 @@ class MatrixBot:
"""处理加密消息MegolmEvent"""
logger.info(f"收到加密消息: [{room.room_id}] event_id={event.event_id}")
# 打印 event 的所有属性来调试
logger.info(f"MegolmEvent属性: {dir(event)}")
logger.info(f"event.source: {event.source}")
logger.info(f"event.sender: {event.sender}")
logger.info(f"event.session_id: {event.session_id if hasattr(event, 'session_id') else 'N/A'}")
# 检查是否已解密
logger.info(f"event.decrypted: {event.decrypted}")
# 尝试从不同来源获取消息内容
try:
body = None
sender = event.sender
# 方法1: 从 source 获取
if hasattr(event, 'source') and event.source:
content = event.source.get('content', {})
body = content.get('body', '')
sender = event.source.get('sender', event.sender)
logger.info(f"从source获取: body={body[:50] if body else 'empty'}")
# 方法1: 检查 decrypted 属性
if event.decrypted:
logger.info(f"消息已解密: {event.decrypted}")
# 使用 parse_decrypted_event 获取解密后的完整事件
try:
decrypted_event = event.parse_decrypted_event(event.decrypted)
if decrypted_event:
logger.info(f"解密事件类型: {type(decrypted_event)}")
if hasattr(decrypted_event, 'body'):
body = decrypted_event.body
sender = decrypted_event.sender if hasattr(decrypted_event, 'sender') else event.sender
logger.info(f"从 decrypted 获取: {body}")
except Exception as e:
logger.warning(f"parse_decrypted_event 失败: {e}")
# 方法2: 直接尝试 event.body (nio可能已解密)
if hasattr(event, 'body') and event.body:
# 方法2: 从 source 获取(如果是自己发的消息)
if not body and hasattr(event, 'source') and event.source:
content = event.source.get('content', {})
# 检查是否有 plaintext body
if 'body' in content:
body = content.get('body', '')
sender = event.source.get('sender', event.sender)
logger.info(f"从source.content获取: {body[:50] if body else 'empty'}")
# 方法3: 直接尝试 event.body (某些情况下可能有)
if not body and hasattr(event, 'body') and event.body:
body = event.body
logger.info(f"从event.body获取: {body[:50]}")
# 方法3: 检查 room 中的最近事件
if not body:
# 从 room timeline 查找解密后的消息
for timeline_event in room.timeline:
if hasattr(timeline_event, 'event_id') and timeline_event.event_id == event.event_id:
if hasattr(timeline_event, 'body'):
body = timeline_event.body
logger.info(f"从room.timeline获取: {body[:50] if body else 'empty'}")
if body:
logger.info(f"解密成功: sender={sender}, body={body[:50]}")
await self._process_message(room, sender, body, event.event_id)
else:
logger.warning(f"加密消息无法解密event_id={event.event_id}")
# 尝试手动解密
try:
decrypted = await self.client.decrypt_event(event)
if decrypted and hasattr(decrypted, 'body'):
body = decrypted.body
sender = decrypted.sender
logger.info(f"手动解密成功: {body[:50]}")
await self._process_message(room, sender, body, event.event_id)
except Exception as de:
logger.error(f"手动解密失败: {de}")
logger.warning(f"加密消息无法解密: event_id={event.event_id}")
logger.warning(f"event.decrypted={event.decrypted}, 需要密钥")
except Exception as e:
logger.error(f"处理加密消息失败: {e}")
@@ -235,8 +230,8 @@ class MatrixBot:
except Exception as e:
logger.warning(f"发送输入状态失败: {e}")
# 获取AI回复
messages = conv_service.get_messages(conversation.id)
# 获取AI回复 - 使用字典格式
messages = conv_service.get_conversation_history(conversation.conversation_id)
ai_response = await ai_service.chat(messages)
# 保存AI回复
@@ -287,6 +282,7 @@ class MatrixBot:
return False
try:
# 先尝试直接发送
await self.client.room_send(
room_id,
"m.room.message",
@@ -298,10 +294,52 @@ class MatrixBot:
logger.info(f"Matrix消息发送成功: {room_id}")
return True
except Exception as e:
logger.error(f"发送Matrix消息错误: {e}")
import traceback
logger.error(traceback.format_exc())
return False
error_str = str(e)
if "not verified" in error_str or "OlmUnverifiedDeviceError" in error_str:
logger.warning(f"设备未验证,尝试验证设备后发送: {e}")
try:
# 验证所有未验证的设备
for user_id, devices in self.client.device_store.items():
for device_id, device in devices.items():
if not device.verified:
logger.info(f"验证设备: {user_id} {device_id}")
self.client.verify_device(device)
# 再次尝试发送
await self.client.room_send(
room_id,
"m.room.message",
{
"msgtype": "m.text",
"body": message
}
)
logger.info(f"Matrix消息发送成功验证设备后: {room_id}")
return True
except Exception as e2:
logger.error(f"验证设备后发送仍失败: {e2}")
# 最后尝试用 HTTP API 发送(不加密)
try:
import httpx
async with httpx.AsyncClient() as http_client:
txn_id = f"m{int(asyncio.get_event_loop().time() * 1000)}"
resp = await http_client.put(
f"{self.homeserver}/_matrix/client/v3/rooms/{room_id}/send/m.room.message/{txn_id}",
headers={"Authorization": f"Bearer {self.client.access_token}"},
json={"msgtype": "m.text", "body": message}
)
if resp.status_code == 200:
logger.info(f"Matrix消息通过HTTP发送成功: {room_id}")
return True
else:
logger.error(f"HTTP发送失败: {resp.status_code}")
return False
except Exception as e3:
logger.error(f"HTTP发送失败: {e3}")
return False
else:
logger.error(f"发送Matrix消息错误: {e}")
return False
async def disconnect(self):
"""断开连接"""