feat: 添加飞书用户模块和订阅功能支持 - 新增feishu_users模块用于处理飞书用户身份验证和权限管理 - 新增subscriptions模块用于处理订阅相关功能 - 新增personalization模块用于个性化服务 - 在alembic迁移配置中注册新的模型模块 - 在API路由器中添加feishu_users和subscriptions路由 - 实现事件调度服务的改进,包括错误处理和状态更新优化 - 添加飞书命令处理的权限检查机制 - 实现飞书应用票据事件处理 - 改进审计日志记录功能 ```
89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
from fastapi import APIRouter, Depends, Request
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import ApiPrincipal, require_api_key
|
|
from app.application.feishu import FeishuCommandService, FeishuEventService
|
|
from app.modules.feishu.constants import FeishuEventSource, FeishuPayloadKey, FeishuResponseKey
|
|
from app.modules.feishu.event_verification import FeishuWebhookVerifier
|
|
from app.modules.feishu.schemas import (
|
|
FeishuCardMessage,
|
|
FeishuCommandRequest,
|
|
FeishuCommandResult,
|
|
FeishuSendResult,
|
|
FeishuTextMessage,
|
|
)
|
|
from app.modules.feishu.service import FeishuService
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/webhook")
|
|
async def feishu_webhook(request: Request, db: Session = Depends(get_db)) -> dict:
|
|
"""Handle Feishu webhook challenge and text command events."""
|
|
|
|
payload = FeishuWebhookVerifier().verify(await request.body(), request.headers)
|
|
return FeishuEventService(db)._handle_verified_event(
|
|
payload,
|
|
source=FeishuEventSource.WEBHOOK,
|
|
auto_reply=True,
|
|
)
|
|
|
|
|
|
@router.post("/send-text", response_model=FeishuSendResult)
|
|
def send_text(
|
|
payload: FeishuTextMessage,
|
|
db: Session = Depends(get_db),
|
|
principal: ApiPrincipal = Depends(require_api_key),
|
|
) -> dict:
|
|
result = FeishuService(db).send_text(
|
|
payload.text,
|
|
receive_id=payload.receive_id,
|
|
receive_id_type=payload.receive_id_type,
|
|
actor=principal.actor,
|
|
tenant_key=payload.tenant_key,
|
|
)
|
|
return {
|
|
FeishuResponseKey.OK: result.get(FeishuPayloadKey.CODE) == 0,
|
|
FeishuResponseKey.PROVIDER_RESPONSE: result,
|
|
}
|
|
|
|
|
|
@router.post("/send-card", response_model=FeishuSendResult)
|
|
def send_card(
|
|
payload: FeishuCardMessage,
|
|
db: Session = Depends(get_db),
|
|
principal: ApiPrincipal = Depends(require_api_key),
|
|
) -> dict:
|
|
result = FeishuService(db).send_card(
|
|
payload.card,
|
|
receive_id=payload.receive_id,
|
|
receive_id_type=payload.receive_id_type,
|
|
actor=principal.actor,
|
|
tenant_key=payload.tenant_key,
|
|
)
|
|
return {
|
|
FeishuResponseKey.OK: result.get(FeishuPayloadKey.CODE) == 0,
|
|
FeishuResponseKey.PROVIDER_RESPONSE: result,
|
|
}
|
|
|
|
|
|
@router.post(
|
|
"/commands/preview",
|
|
response_model=FeishuCommandResult,
|
|
)
|
|
def preview_command(
|
|
payload: FeishuCommandRequest,
|
|
db: Session = Depends(get_db),
|
|
principal: ApiPrincipal = Depends(require_api_key),
|
|
) -> dict:
|
|
"""Preview local Feishu command routing without requiring webhook delivery."""
|
|
|
|
return FeishuCommandService(db).handle_text(
|
|
payload.text,
|
|
chat_id=payload.chat_id,
|
|
actor=principal.actor,
|
|
auto_reply=payload.auto_reply,
|
|
tenant_key=payload.tenant_key,
|
|
)
|