完成Help Scout渠道的完整功能实现,包含API客户端、webhook处理、轮询同步、自动回复、工单标签分配、客户资料管理等核心能力,附带完整的配置Schema与插件元信息
90 lines
3.5 KiB
Python
90 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
ENV_MAP = {
|
|
"app_id": "HELPSCOUT_APP_ID",
|
|
"app_secret": "HELPSCOUT_APP_SECRET",
|
|
"mailbox_id": "HELPSCOUT_MAILBOX_ID",
|
|
"mode": "HELPSCOUT_MODE",
|
|
"webhook_url": "HELPSCOUT_WEBHOOK_URL",
|
|
"webhook_secret": "HELPSCOUT_WEBHOOK_SECRET",
|
|
"auto_reply_mode": "HELPSCOUT_AUTO_REPLY_MODE",
|
|
"customer_allowlist": "HELPSCOUT_CUSTOMER_ALLOWLIST",
|
|
"poll_interval": "HELPSCOUT_POLL_INTERVAL",
|
|
"streaming_mode": "HELPSCOUT_STREAMING_MODE",
|
|
"language_detection": "HELPSCOUT_LANGUAGE_DETECTION",
|
|
"auto_register_webhook": "HELPSCOUT_AUTO_REGISTER_WEBHOOK",
|
|
"auto_unregister_webhook": "HELPSCOUT_AUTO_UNREGISTER_WEBHOOK",
|
|
}
|
|
|
|
|
|
def _env_or_config(key: str) -> str | None:
|
|
env_key = ENV_MAP.get(key, "")
|
|
if env_key:
|
|
return os.getenv(env_key)
|
|
return None
|
|
|
|
|
|
def resolve_account(account_id: str = "default") -> dict:
|
|
allowlist_str = _env_or_config("customer_allowlist") or ""
|
|
lang_str = _env_or_config("language_detection") or "true"
|
|
|
|
return {
|
|
"account_id": account_id,
|
|
"app_id": _env_or_config("app_id") or "",
|
|
"app_secret": _env_or_config("app_secret") or "",
|
|
"mailbox_id": int(_env_or_config("mailbox_id") or "0"),
|
|
"mode": _env_or_config("mode") or "webhook",
|
|
"webhook_url": _env_or_config("webhook_url") or "",
|
|
"webhook_secret": _env_or_config("webhook_secret") or "",
|
|
"auto_reply_mode": _env_or_config("auto_reply_mode") or "draft",
|
|
"customer_allowlist": [e.strip() for e in allowlist_str.split(",") if e.strip()],
|
|
"poll_interval": int(_env_or_config("poll_interval") or "30"),
|
|
"streaming_mode": _env_or_config("streaming_mode") or "block",
|
|
"language_detection": lang_str.lower() == "true",
|
|
"auto_register_webhook": (_env_or_config("auto_register_webhook") or "false").lower() == "true",
|
|
"auto_unregister_webhook": (_env_or_config("auto_unregister_webhook") or "false").lower() == "true",
|
|
}
|
|
|
|
|
|
class HelpScoutConfigAdapter:
|
|
def list_account_ids(self, config: dict) -> list[str]:
|
|
accounts = config.get("accounts", [])
|
|
if accounts:
|
|
return [a.get("account_id", "default") for a in accounts]
|
|
return ["default"]
|
|
|
|
async def resolve_account(self, account_id: str) -> dict:
|
|
return resolve_account(account_id)
|
|
|
|
def is_configured(self, account: dict) -> bool:
|
|
return bool(account.get("app_id") and account.get("app_secret") and int(account.get("mailbox_id", 0)) > 0)
|
|
|
|
def is_enabled(self, account: dict, config: dict | None = None) -> bool:
|
|
cfg = config or {}
|
|
return cfg.get("enabled", False)
|
|
|
|
def describe_account(self, account: dict, config: dict | None = None) -> dict:
|
|
return {
|
|
"account_id": account.get("account_id", "default"),
|
|
"mailbox_id": account.get("mailbox_id"),
|
|
"mode": account.get("mode", "webhook"),
|
|
}
|
|
|
|
def config_schema(self) -> dict:
|
|
from yuxi.channel.extensions.helpscout.config_schema import schema
|
|
|
|
return schema
|
|
|
|
def default_account_id(self, config: dict) -> str:
|
|
return config.get("default_account", "default")
|
|
|
|
def resolve_allow_from(self, config: dict, account_id: str | None = None) -> list[str | int] | None:
|
|
account = resolve_account(account_id or "default")
|
|
allowlist = account.get("customer_allowlist", [])
|
|
return allowlist if allowlist else None
|