ForcePilot/backend/package/yuxi/channel/extensions/clickup/threading.py
Kris a79fc8dd7b feat(clickup): 新增ClickUp聊天渠道插件完整实现
该提交实现了完整的ClickUp聊天渠道插件,包含以下核心功能:
1. 基础的@提及提取与格式化能力
2. 账号配对与会话管理
3. 消息流与流式回复支持
4. 重试限流与消息去重
5. 富文本格式转换与内容 sanitize
6. 安全策略与配置校验
7. Webhook接收与自动轮询回退
8. 消息收发、编辑、删除与回复
9. 频道与私信管理、反应功能
10. 完整的状态监控与健康检查
2026-05-21 10:43:19 +08:00

66 lines
2.2 KiB
Python

import logging
import httpx
from yuxi.channel.extensions.clickup.types import OutboundResult
logger = logging.getLogger(__name__)
API_V3_BASE = "https://api.clickup.com/api/v3"
async def send_reply(
workspace_id: str,
parent_message_id: str,
content: str,
api_token: str,
) -> OutboundResult:
url = f"{API_V3_BASE}/workspaces/{workspace_id}/chat/messages/{parent_message_id}/replies"
headers = {"Authorization": api_token, "Content-Type": "application/json"}
payload = {
"type": "message",
"content": content[:40000],
"content_format": "text/md",
}
async with httpx.AsyncClient(timeout=30.0) as client:
try:
resp = await client.post(url, json=payload, headers=headers)
if resp.status_code == 201:
data = resp.json()
return OutboundResult(success=True, message_id=data.get("id", ""))
else:
error_text = resp.text[:500]
logger.error("ClickUp send_reply failed: status=%d", resp.status_code)
return OutboundResult(success=False, error=f"http_{resp.status_code}", detail=error_text)
except Exception as e:
logger.exception("ClickUp send_reply exception: %s", e)
return OutboundResult(success=False, error="exception", detail=str(e))
async def get_replies(
workspace_id: str,
parent_message_id: str,
api_token: str,
limit: int = 50,
cursor: str | None = None,
) -> dict:
url = f"{API_V3_BASE}/workspaces/{workspace_id}/chat/messages/{parent_message_id}/replies"
params = {"limit": min(limit, 100)}
if cursor:
params["cursor"] = cursor
headers = {"Authorization": api_token}
async with httpx.AsyncClient(timeout=15.0) as client:
try:
resp = await client.get(url, params=params, headers=headers)
if resp.status_code == 200:
return resp.json()
logger.error("ClickUp get_replies failed: status=%d", resp.status_code)
return {"replies": []}
except Exception as e:
logger.exception("ClickUp get_replies exception: %s", e)
return {"replies": []}