import os from yuxi.channel.extensions.wechat_miniprogram.types import MiniProgramAccount class MiniProgramConfig: ENV_MAP = { "app_id": "WECHAT_MINIPROGRAM_APP_ID", "app_secret": "WECHAT_MINIPROGRAM_APP_SECRET", "token": "WECHAT_MINIPROGRAM_TOKEN", "encoding_aes_key": "WECHAT_MINIPROGRAM_ENCODING_AES_KEY", "reply_mode": "WECHAT_MINIPROGRAM_REPLY_MODE", "subscribe_msg": "WECHAT_MINIPROGRAM_SUBSCRIBE_MSG", "remove_markdown": "WECHAT_MINIPROGRAM_REMOVE_MD", "dm_policy": "WECHAT_MINIPROGRAM_DM_POLICY", } def list_account_ids(self, config: dict | None = None) -> list[str]: if self._resolve_app_id(): return ["default"] return [] def resolve_account(self, account_id: str = "default") -> MiniProgramAccount: app_id = self._resolve_app_id() return MiniProgramAccount( account_id=account_id, app_id=app_id or "", app_secret=self._env_or_config("app_secret") or "", token=self._env_or_config("token") or "", encoding_aes_key=self._env_or_config("encoding_aes_key") or "", dm_policy=self._env_or_config("dm_policy") or "open", reply_mode=self._env_or_config("reply_mode") or "active", subscribe_msg=self._env_or_config("subscribe_msg") or "", remove_markdown=self._env_or_config("remove_markdown") != "false", ) def is_configured(self, account: dict | None = None) -> bool: return bool( self._resolve_app_id() and self._env_or_config("app_secret") and self._env_or_config("token") and self._env_or_config("encoding_aes_key") ) def is_enabled(self, account: dict | None = None) -> bool: return os.getenv("WECHAT_MINIPROGRAM_ENABLED", "true").lower() != "false" def _resolve_app_id(self) -> str | None: return self._env_or_config("app_id") def _env_or_config(self, key: str) -> str | None: env_key = self.ENV_MAP.get(key, "") if env_key: val = os.getenv(env_key) if val: return val return None def config_schema(self) -> dict: return { "$schema": "https://json-schema.org/draft-07/schema#", "type": "object", "title": "微信小程序客服消息配置", "properties": { "app_id": { "type": "string", "title": "小程序 AppID", "description": "微信小程序的 AppID(小程序 ID)", }, "app_secret": { "type": "string", "title": "小程序 AppSecret", "x-ui-password": True, "description": "微信小程序的 AppSecret(小程序密钥)", }, "token": { "type": "string", "title": "消息签名 Token", "description": "小程序后台配置的消息推送 Token", }, "encoding_aes_key": { "type": "string", "title": "EncodingAESKey", "x-ui-password": True, "description": "小程序后台配置的 43 字符 EncodingAESKey", }, "dm_policy": { "type": "string", "enum": ["open", "pairing", "allowlist", "disabled"], "default": "open", "title": "DM 策略", }, "reply_mode": { "type": "string", "enum": ["passive", "active"], "default": "active", "title": "回复模式", "description": "active=客服消息 API 主动推送, passive=被动回复 XML(5s 内同步返回)", }, "subscribe_msg": { "type": "string", "title": "进入客服会话欢迎语", "description": "用户首次进入客服会话时自动回复的消息", }, "remove_markdown": { "type": "boolean", "default": True, "title": "移除 Markdown 格式", "description": "自动移除 AI 回复中的 Markdown 符号", }, }, "required": ["app_id", "app_secret", "token", "encoding_aes_key"], }