#!/usr/bin/env python3 """ 消息API路由 提供加载会话存档、查询消息等功能的API接口 """ from typing import Optional from fastapi import APIRouter, HTTPException, Query, Depends import logging from app.services.message_service import get_message_service, MessageService logger = logging.getLogger(__name__) router = APIRouter( prefix="/messages", tags=["messages"], responses={404: {"description": "Not found"}}, ) @router.post("/load") async def load_messages( seq: int = Query(0, description="起始seq值,首次使用0"), limit: int = Query(100, description="拉取数量限制", ge=1, le=1000), service: MessageService = Depends(get_message_service), ): """ 加载会话存档到数据库 完整流程:拉取 → 解密 → 保存 - 从企业微信拉取会话存档 - 自动解密所有加密消息 - 自动保存到数据库(去重处理) 参数说明: - seq: 起始序列号,首次拉取使用0,后续使用上次返回的max_seq - limit: 一次拉取的消息数量,最大1000 返回示例: ```json { "success": true, "message": "消息加载完成", "data": { "total_fetched": 150, "encrypted_count": 120, "decrypted_success": 115, "decrypted_failed": 5, "saved_count": 145, "duplicates_skipped": 5, "failed_to_save": 0, "max_seq": 12345, "next_seq": 12346 }, "execution_time": "0:00:02.345678", "timestamp": "2025-12-10T16:44:22.123456" } ``` """ try: logger.info(f"API调用: 加载消息, seq={seq}, limit={limit}") result = await service.load_messages(seq=seq, limit=limit) if not result.get("success", False): raise HTTPException( status_code=500, detail=result.get("message", "加载消息失败") ) return result except Exception as e: logger.error(f"加载消息API调用失败: {e}") raise HTTPException(status_code=500, detail=f"加载消息失败: {str(e)}") @router.get("/") async def get_messages( page: int = Query(1, description="页码", ge=1), page_size: int = Query(20, description="每页数量", ge=1, le=100), msgtype: Optional[str] = Query(None, description="消息类型过滤"), roomid: Optional[str] = Query(None, description="群聊ID过滤"), from_user: Optional[str] = Query(None, description="发送者过滤"), service: MessageService = Depends(get_message_service), ): """ 查询消息列表 支持分页和过滤条件查询 """ try: logger.info( f"API调用: 查询消息列表, page={page}, page_size={page_size}, " f"msgtype={msgtype}, roomid={roomid}, from_user={from_user}" ) result = await service.get_messages( page=page, page_size=page_size, msgtype=msgtype, roomid=roomid, from_user=from_user, ) if not result.get("success", False): raise HTTPException( status_code=500, detail=result.get("message", "查询消息列表失败") ) return result except Exception as e: logger.error(f"查询消息列表失败: {e}") raise HTTPException(status_code=500, detail=f"查询消息列表失败: {str(e)}") @router.get("/stats") async def get_message_stats(service: MessageService = Depends(get_message_service)): """ 获取消息统计信息 返回数据库中消息的统计信息 """ try: # 这里可以添加统计逻辑 # 暂时返回空统计,实际实现需要连接数据库统计 return { "success": True, "data": {"total_messages": 0, "message_types": {}, "date_distribution": {}}, } except Exception as e: logger.error(f"获取消息统计失败: {e}") raise HTTPException(status_code=500, detail=f"获取消息统计失败: {str(e)}") @router.get("/config") async def get_message_config(): """ 获取消息服务配置信息 返回企业微信SDK配置、文件路径等基本信息 """ try: import os from pathlib import Path # 从环境变量获取配置 corpid = os.getenv("CORPID", "") secret = os.getenv("WEWORK_SECRET", "") # 构建文件路径 backend_dir = Path(__file__).parent.parent.parent lib_path = backend_dir / "lib" / "sdk" / "libWeWorkFinanceSdk_C.so" data_dir = backend_dir / "data" config = { "corpid": corpid, # "secret": secret[:10] + "..." if secret else "", # 只显示前10个字符 "libPath": str(lib_path), "dataDir": str(data_dir), } return {"success": True, "message": "配置获取成功", "data": config} except Exception as e: logger.error(f"获取配置信息失败: {e}") raise HTTPException(status_code=500, detail=f"获取配置信息失败: {str(e)}") @router.get("/{msgid}") async def get_message_by_id( msgid: str, service: MessageService = Depends(get_message_service) ): """ 根据消息ID获取单个消息详情 """ try: # 这里可以添加根据msgid查询消息的逻辑 # 暂时返回空,实际实现需要连接数据库查询 return {"success": True, "data": None, "message": "消息查询功能待实现"} except Exception as e: logger.error(f"查询消息详情失败 (msgid: {msgid}): {e}") raise HTTPException(status_code=500, detail=f"查询消息详情失败: {str(e)}")