添加用户消息记录接口;

This commit is contained in:
karlcarlo
2025-12-11 03:53:47 +08:00
parent 6029da058a
commit 420fed4bcf
49 changed files with 7574 additions and 426 deletions

View File

@@ -0,0 +1,208 @@
#!/usr/bin/env python3
"""
企业微信会话存档API路由
"""
from typing import Optional
from fastapi import APIRouter, HTTPException, Query, Depends, BackgroundTasks
from fastapi.responses import FileResponse, JSONResponse
import logging
from app.services.wework_service import get_wework_service, WeworkService
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/wework",
tags=["wework"],
responses={404: {"description": "Not found"}},
)
def get_service():
"""依赖注入:获取企业微信服务实例"""
return get_wework_service()
@router.get("/health")
async def health_check(service: WeworkService = Depends(get_service)):
"""健康检查端点"""
return {
"status": "healthy",
"service": "wework",
"corpid": service.corpid,
"media_dir": str(service.media_dir)
}
@router.get("/chat")
async def get_chat(
seq: int = Query(0, description="从指定的seq开始拉取消息,首次使用请使用0"),
limit: int = Query(100, description="一次拉取的消息条数,最大值1000条", ge=1, le=1000),
proxy: Optional[str] = Query(None, description="代理链接,如:socks5://10.0.0.1:8081 或 http://10.0.0.1:8081"),
passwd: Optional[str] = Query(None, description="代理账号密码,如:user_name:passwd_123"),
timeout: int = Query(5, description="超时时间,单位秒", ge=1, le=60),
service: WeworkService = Depends(get_service)
):
"""
拉取会话存档
从企业微信拉取聊天记录,支持代理和分页
"""
try:
result = service.get_chat_data(
seq=seq,
limit=limit,
proxy=proxy or "",
passwd=passwd or "",
timeout=timeout
)
return result
except Exception as e:
logger.error(f"拉取会话存档失败: {e}")
raise HTTPException(status_code=500, detail=f"拉取会话存档失败: {str(e)}")
@router.post("/media")
async def download_media(
fileid: str = Query(..., description="媒体文件id,从解密后的会话存档中得到"),
filename: Optional[str] = Query(None, description="保存的文件名,如果为空则自动生成"),
proxy: Optional[str] = Query(None, description="代理链接"),
passwd: Optional[str] = Query(None, description="代理账号密码"),
timeout: int = Query(5, description="超时时间,单位秒", ge=1, le=60),
background_tasks: BackgroundTasks = None,
service: WeworkService = Depends(get_service)
):
"""
拉取媒体文件
下载企业微信中的媒体文件(图片、语音、视频等),支持大文件分片下载
"""
try:
result = service.get_media_data(
sdk_fileid=fileid,
filename=filename,
proxy=proxy or "",
passwd=passwd or "",
timeout=timeout
)
if result.get("success"):
# 可以添加后台任务,比如发送下载完成通知等
if background_tasks:
background_tasks.add_task(
logger.info,
f"媒体文件下载完成: {result['filename']}, 大小: {result['filesize']} 字节"
)
return result
else:
raise HTTPException(status_code=500, detail=result.get("error", "下载失败"))
except Exception as e:
logger.error(f"拉取媒体文件失败: {e}")
raise HTTPException(status_code=500, detail=f"拉取媒体文件失败: {str(e)}")
@router.get("/media/files")
async def list_media_files(
service: WeworkService = Depends(get_service)
):
"""
获取已下载的媒体文件列表
返回所有已下载的媒体文件信息
"""
try:
files = service.get_media_files()
return {
"count": len(files),
"files": files
}
except Exception as e:
logger.error(f"获取媒体文件列表失败: {e}")
raise HTTPException(status_code=500, detail=f"获取媒体文件列表失败: {str(e)}")
@router.get("/media/download/{filename}")
async def download_file(
filename: str,
service: WeworkService = Depends(get_service)
):
"""
下载媒体文件
通过文件名下载已保存的媒体文件
"""
try:
file_path = service.media_dir / filename
if not file_path.exists():
raise HTTPException(status_code=404, detail="文件不存在")
return FileResponse(
path=file_path,
filename=filename,
media_type='application/octet-stream'
)
except HTTPException:
raise
except Exception as e:
logger.error(f"下载文件失败: {e}")
raise HTTPException(status_code=500, detail=f"下载文件失败: {str(e)}")
@router.delete("/media/cleanup")
async def cleanup_media_files(
days: int = Query(7, description="保留天数,早于此天数的文件将被删除", ge=1, le=365),
service: WeworkService = Depends(get_service)
):
"""
清理旧的媒体文件
删除指定天数之前的媒体文件
"""
try:
deleted_count = service.cleanup_old_files(days)
return {
"message": f"成功删除 {deleted_count} 个旧文件",
"deleted_count": deleted_count,
"days": days
}
except Exception as e:
logger.error(f"清理媒体文件失败: {e}")
raise HTTPException(status_code=500, detail=f"清理媒体文件失败: {str(e)}")
@router.post("/decrypt")
async def decrypt_message(
encrypt_key: str = Query(..., description="解密密钥,使用RSA私钥解密encrypt_random_key后得到"),
encrypt_msg: str = Query(..., description="加密的消息内容"),
service: WeworkService = Depends(get_service)
):
"""
解密会话内容
使用企业自持的RSA私钥解密后的encrypt_key来解密encrypt_chat_msg
"""
try:
result = service.decrypt_data(encrypt_key, encrypt_msg)
return result
except Exception as e:
logger.error(f"解密消息失败: {e}")
raise HTTPException(status_code=500, detail=f"解密消息失败: {str(e)}")
@router.get("/config")
async def get_config(
service: WeworkService = Depends(get_service)
):
"""
获取当前配置
返回企业微信服务的配置信息
"""
return {
"corpid": service.corpid,
"corpid_masked": service.corpid[:8] + "..." + service.corpid[-4:] if len(service.corpid) > 12 else service.corpid,
"media_dir": str(service.media_dir),
"media_dir_exists": service.media_dir.exists()
}
# 应用关闭时的清理
@router.on_event("shutdown")
async def shutdown_event():
"""应用关闭时清理资源"""
from app.services.wework_service import close_wework_service
close_wework_service()
logger.info("企业微信服务已关闭")