新增 Zalo OA、Zoom Chat、Zulip 三个渠道扩展。 Zalo OA 渠道扩展主要模块:sidecar_client, config, gateway, outbound, streaming, pairing, security, auth, dedupe, directory, monitor, status, session, reactions, tools Zoom Chat 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, crypto, dedupe, actions, media, mentions, monitor, status, session, reactions, threading Zulip 渠道扩展主要模块:client, config, gateway, outbound, streaming, pairing, security, monitor, status
97 lines
3.7 KiB
Python
97 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from yuxi.channel.extensions.zalouser.sidecar_client import ZcaSidecarClient
|
|
from yuxi.channel.protocols import ChannelAccountSnapshot
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ZaloUserStatus:
|
|
default_runtime = ChannelAccountSnapshot(account_id="default")
|
|
|
|
async def probe(self, account: dict | None = None, timeout_ms: int = 5000) -> dict:
|
|
if account is None:
|
|
return {"ok": False, "error": "No account provided", "elapsed_ms": 0}
|
|
|
|
sidecar_url = account.get("sidecar_url", "")
|
|
if not sidecar_url:
|
|
return {"ok": False, "error": "Sidecar URL is required", "elapsed_ms": 0}
|
|
|
|
import time
|
|
|
|
start = time.monotonic()
|
|
client = ZcaSidecarClient(sidecar_url, account.get("profile", "default"))
|
|
try:
|
|
status = await client.get_status()
|
|
elapsed_ms = int((time.monotonic() - start) * 1000)
|
|
authenticated = status.get("authenticated", False) or status.get("connected", False)
|
|
return {
|
|
"ok": True,
|
|
"authenticated": authenticated,
|
|
"sidecar_url": sidecar_url,
|
|
"elapsed_ms": elapsed_ms,
|
|
}
|
|
except Exception as e:
|
|
elapsed_ms = int((time.monotonic() - start) * 1000)
|
|
return {"ok": False, "error": str(e), "elapsed_ms": elapsed_ms}
|
|
finally:
|
|
await client.close()
|
|
|
|
def build_summary(self, snapshot: object) -> dict:
|
|
return {
|
|
"channel": "zalouser",
|
|
"accounts": 1,
|
|
}
|
|
|
|
def build_account_snapshot(
|
|
self,
|
|
account: dict,
|
|
config: dict,
|
|
runtime: ChannelAccountSnapshot | None = None,
|
|
probe_result: object | None = None,
|
|
audit: object | None = None,
|
|
) -> ChannelAccountSnapshot:
|
|
sidecar_url = account.get("sidecar_url", "")
|
|
configured = bool(sidecar_url)
|
|
|
|
status_state = "linked" if configured else "not-linked"
|
|
if probe_result is not None:
|
|
if isinstance(probe_result, dict):
|
|
if probe_result.get("authenticated"):
|
|
status_state = "authenticated"
|
|
elif probe_result.get("ok"):
|
|
status_state = "linked"
|
|
|
|
return ChannelAccountSnapshot(
|
|
account_id=account.get("account_id", ""),
|
|
name=account.get("name", ""),
|
|
enabled=account.get("enabled", True) if isinstance(account.get("enabled"), bool) else True,
|
|
configured=configured,
|
|
status_state=status_state,
|
|
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 and (isinstance(probe_result, dict) and probe_result.get("ok")) else "unknown"
|
|
),
|
|
dm_policy=account.get("dm_policy", "pairing"),
|
|
)
|
|
|
|
def collect_status_issues(self, accounts: list[ChannelAccountSnapshot]) -> list:
|
|
issues = []
|
|
for acc in accounts:
|
|
if not acc.configured:
|
|
issues.append(
|
|
{
|
|
"channel": "zalouser",
|
|
"account_id": acc.account_id,
|
|
"kind": "not-configured",
|
|
"message": "ZaloUser sidecar_url not configured",
|
|
"fix": (
|
|
"Set ZALOUSER_SIDECAR_URL environment variable or configure sidecar_url in channel settings"
|
|
),
|
|
}
|
|
)
|
|
return issues |