ForcePilot/backend/package/yuxi/channels/adapters/slack/http_handler.py
Kris a2aa782b86 feat(slack adapter): 实现完整的Slack频道适配器基础功能
新增Slack适配器全套核心模块,包括消息处理流水线、会话管理、配置适配、权限控制等完整功能:
1. 新增语音、视觉相关的TTS和图像分析导出接口
2. 实现消息预处理、路由、线程上下文处理的完整流水线
3. 新增账号管理、缓存机制、房间上下文提取功能
4. 支持Webhook和Socket Mode两种事件接收方式
5. 实现权限白名单、审批配对、自动状态管理功能
6. 新增配置迁移、作用域校验、重连策略等辅助模块
2026-05-12 00:48:57 +08:00

58 lines
1.9 KiB
Python

from __future__ import annotations
import json
from typing import Any
from fastapi import APIRouter, Request, status
from fastapi.responses import JSONResponse, PlainTextResponse
from yuxi.channels.manager import channel_manager
from yuxi.utils.logging_config import logger
slack_webhook = APIRouter(tags=["slack-webhook"])
@slack_webhook.post("/api/webhook/slack")
async def slack_event_receiver(request: Request):
adapter = channel_manager._adapters.get("slack")
if not adapter:
return JSONResponse(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
content={"error": "Slack adapter is not running"},
)
body = await request.body()
headers = dict(request.headers)
if not await adapter.verify_webhook_signature(headers, body):
return JSONResponse(
status_code=status.HTTP_403_FORBIDDEN,
content={"error": "Invalid webhook signature"},
)
try:
payload: dict[str, Any] = json.loads(body.decode("utf-8"))
except (json.JSONDecodeError, UnicodeDecodeError) as e:
logger.error(f"Slack webhook: failed to parse JSON body: {e}")
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"error": "Invalid JSON body"},
)
event_type = payload.get("type", "")
if event_type == "url_verification":
challenge = payload.get("challenge", "")
logger.info("Slack URL verification challenge received, responding with challenge")
return PlainTextResponse(content=challenge, status_code=200)
if event_type == "event_callback":
try:
await adapter._handle_http_event(payload)
except Exception as e:
logger.error(f"Slack webhook event handling error: {e}", exc_info=True)
return JSONResponse(content={"ok": True})
logger.debug(f"Slack webhook: unhandled event type '{event_type}'")
return JSONResponse(content={"ok": True})