import os import logging logger = logging.getLogger(__name__) ENV_PREFIX = "MESSENGER" class MessengerConfigAdapter: def list_account_ids(self, config: dict | None = None) -> list[str]: ids = [] if config and "accounts" in config: ids.extend(config["accounts"].keys()) page_id = os.environ.get(f"{ENV_PREFIX}_PAGE_ID") if page_id: ids.append("default") return list(dict.fromkeys(ids)) or ["default"] def resolve_account(self, account_id: str = "default", config: dict | None = None) -> dict: raw = {} if config and "accounts" in config: raw = config["accounts"].get(account_id, {}) return self._build_account(account_id, raw) def _build_account(self, account_id: str, raw: dict) -> dict: suffix = f"_{account_id.upper()}" if account_id != "default" else "" return { "account_id": account_id, "page_id": raw.get("page_id", os.environ.get(f"{ENV_PREFIX}_PAGE_ID{suffix}", "")), "page_access_token": raw.get( "page_access_token", os.environ.get(f"{ENV_PREFIX}_PAGE_ACCESS_TOKEN{suffix}", "") ), "app_secret": raw.get("app_secret", os.environ.get(f"{ENV_PREFIX}_APP_SECRET{suffix}", "")), "verify_token": raw.get("verify_token", os.environ.get(f"{ENV_PREFIX}_VERIFY_TOKEN{suffix}", "")), "dm_policy": raw.get("dm_policy", os.environ.get(f"{ENV_PREFIX}_DM_POLICY{suffix}", "pairing")), "allow_from": raw.get("allow_from", []), "persona_id": raw.get("persona_id"), "default_messaging_type": raw.get( "default_messaging_type", os.environ.get(f"{ENV_PREFIX}_DEFAULT_MESSAGING_TYPE{suffix}", "RESPONSE"), ), "notification_type": raw.get( "notification_type", os.environ.get(f"{ENV_PREFIX}_NOTIFICATION_TYPE{suffix}", "REGULAR"), ), "text_chunk_limit": raw.get("text_chunk_limit", 2000), "chunk_mode": raw.get("chunk_mode", "length"), } @staticmethod def is_configured(account: dict) -> bool: return bool(account.get("page_id") and account.get("page_access_token")) @staticmethod def is_enabled(account: dict) -> bool: return account.get("enabled", True) @staticmethod def disabled_reason(account: dict) -> str: if not account.get("page_id"): return "缺少 Page ID" if not account.get("page_access_token"): return "缺少 Page Access Token" return "" @staticmethod def default_account_id(config: dict | None = None) -> str: if config and "accounts" in config: return next(iter(config["accounts"]), "default") return "default" @staticmethod def config_schema() -> dict: return { "$schema": "https://json-schema.org/draft-07/schema#", "type": "object", "title": "Facebook Messenger 渠道配置", "properties": { "accounts": { "type": "object", "title": "账户列表", "description": "多账户配置,key 为账户 ID", "additionalProperties": { "type": "object", "title": "账户配置", "properties": { "page_id": { "type": "string", "title": "Page ID", "description": "Facebook Page 的数字 ID", }, "page_access_token": { "type": "string", "title": "Page Access Token", "description": "Facebook Page 的访问令牌", "x-ui-password": True, }, "app_secret": { "type": "string", "title": "App Secret", "description": "Meta App Secret,用于 Webhook 签名验证", "x-ui-password": True, }, "verify_token": { "type": "string", "title": "Webhook 验证 Token", "description": "Meta Webhook 配置时的自定义验证 Token", }, "dm_policy": { "type": "string", "title": "DM 策略", "enum": ["pairing", "allowlist", "open", "disabled"], "default": "pairing", }, "allow_from": { "type": "array", "title": "白名单用户 PSID 列表", "items": {"type": "string"}, "default": [], }, "persona_id": { "type": "string", "title": "Persona ID", "description": "Messenger Persona 虚拟形象 ID", }, "default_messaging_type": { "type": "string", "title": "消息类型", "enum": ["RESPONSE", "UPDATE", "MESSAGE_TAG"], "default": "RESPONSE", }, "notification_type": { "type": "string", "title": "通知类型", "enum": ["REGULAR", "SILENT_PUSH", "NO_PUSH"], "default": "REGULAR", }, "enabled": { "type": "boolean", "title": "启用", "default": True, }, }, "required": ["page_id", "page_access_token"], }, }, "default_account": { "type": "string", "title": "默认账户", "description": "默认使用的账户 ID", "default": "default", }, }, }