91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
|
|
import logging
|
||
|
|
|
||
|
|
import httpx
|
||
|
|
|
||
|
|
from yuxi.channel.protocols import ChannelAccountSnapshot
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
class ClickUpStatus:
|
||
|
|
default_runtime = None
|
||
|
|
|
||
|
|
async def probe(self, account: dict | None = None) -> bool:
|
||
|
|
if not account:
|
||
|
|
return False
|
||
|
|
|
||
|
|
api_token = account.get("api_token", "")
|
||
|
|
if not api_token:
|
||
|
|
return False
|
||
|
|
|
||
|
|
headers = {"Authorization": api_token}
|
||
|
|
|
||
|
|
async with httpx.AsyncClient(timeout=15.0) as client:
|
||
|
|
try:
|
||
|
|
resp = await client.get(
|
||
|
|
"https://api.clickup.com/api/v2/team",
|
||
|
|
headers=headers,
|
||
|
|
)
|
||
|
|
if resp.status_code == 200:
|
||
|
|
teams = resp.json().get("teams", [])
|
||
|
|
logger.info("ClickUp probe OK: %d workspace(s) accessible", len(teams))
|
||
|
|
return True
|
||
|
|
else:
|
||
|
|
logger.warning("ClickUp probe failed: status=%d", resp.status_code)
|
||
|
|
return False
|
||
|
|
except Exception as e:
|
||
|
|
logger.warning("ClickUp probe exception: %s", e)
|
||
|
|
return False
|
||
|
|
|
||
|
|
def build_summary(self, snapshot: object) -> dict:
|
||
|
|
return {
|
||
|
|
"account_id": getattr(snapshot, "account_id", ""),
|
||
|
|
"status": "ok" if getattr(snapshot, "probe_ok", False) else "error",
|
||
|
|
}
|
||
|
|
|
||
|
|
def build_account_snapshot(
|
||
|
|
self,
|
||
|
|
account: dict,
|
||
|
|
config: dict,
|
||
|
|
runtime: ChannelAccountSnapshot | None = None,
|
||
|
|
probe_result: object | None = None,
|
||
|
|
audit: object | None = None,
|
||
|
|
) -> ChannelAccountSnapshot:
|
||
|
|
return ChannelAccountSnapshot(
|
||
|
|
account_id=account.get("account_id", "default"),
|
||
|
|
name=account.get("name", ""),
|
||
|
|
enabled=account.get("enabled", True),
|
||
|
|
configured=bool(account.get("api_token") and account.get("workspace_id")),
|
||
|
|
status_state="linked" if account.get("api_token") else "not-linked",
|
||
|
|
running=getattr(runtime, "running", False) if runtime else False,
|
||
|
|
connected=getattr(runtime, "connected", False) if runtime else False,
|
||
|
|
last_message_at=getattr(runtime, "last_message_at", None) if runtime else None,
|
||
|
|
health_state="ok" if probe_result else "unknown",
|
||
|
|
dm_policy=account.get("dm_policy", "open"),
|
||
|
|
)
|
||
|
|
|
||
|
|
def collect_status_issues(self, accounts: list[ChannelAccountSnapshot]) -> list:
|
||
|
|
issues = []
|
||
|
|
for acct in accounts:
|
||
|
|
if not getattr(acct, "configured", True):
|
||
|
|
issues.append(
|
||
|
|
{
|
||
|
|
"channel": "clickup",
|
||
|
|
"account_id": acct.account_id,
|
||
|
|
"kind": "not-configured",
|
||
|
|
"message": "ClickUp API Token 或 Workspace ID 未配置",
|
||
|
|
"fix": "设置 CLICKUP_API_TOKEN 和 CLICKUP_WORKSPACE_ID 环境变量",
|
||
|
|
}
|
||
|
|
)
|
||
|
|
elif not getattr(acct, "connected", True):
|
||
|
|
issues.append(
|
||
|
|
{
|
||
|
|
"channel": "clickup",
|
||
|
|
"account_id": acct.account_id,
|
||
|
|
"kind": "not-connected",
|
||
|
|
"message": "ClickUp gateway 未运行",
|
||
|
|
"fix": "检查 webhook 端点和 gateway 状态",
|
||
|
|
}
|
||
|
|
)
|
||
|
|
return issues
|