ForcePilot/backend/package/yuxi/channel/extensions/dingtalk/config.py
Kris 472afc4d1e feat(dingtalk): 新增钉钉渠道插件完整实现
该提交实现了完整的钉钉聊天渠道插件,包含:
1. 基础配置、账号管理与凭证校验
2. WebSocket长连接网关与消息去重
3. 消息接收/解析/分发与安全校验
4. 媒体文件上传下载与缓存
5. 互动卡片流式更新与回调处理
6. 群管理、命令支持与诊断工具
7. 完整的插件元数据与依赖声明
2026-05-21 10:44:03 +08:00

188 lines
7.1 KiB
Python

from __future__ import annotations
import logging
import os
from yuxi.channel.extensions.dingtalk.types import DingTalkAccount
logger = logging.getLogger(__name__)
class DingTalkConfig:
def list_account_ids(self, config: dict) -> list[str]:
dingtalk_cfg = _get_dingtalk_config(config)
accounts = dingtalk_cfg.get("accounts", {})
if accounts:
return list(accounts.keys())
if dingtalk_cfg.get("appKey") or dingtalk_cfg.get("app_key"):
return ["default"]
if os.environ.get("DINGTALK_APP_KEY"):
return ["default"]
return []
def default_account_id(self, config: dict) -> str:
dingtalk_cfg = _get_dingtalk_config(config)
return dingtalk_cfg.get("defaultAccount") or dingtalk_cfg.get("default_account", "default")
async def resolve_account(self, account_id: str, config: dict | None = None) -> DingTalkAccount:
dingtalk_cfg = _get_dingtalk_config(config) if config else {}
accounts = dingtalk_cfg.get("accounts", {})
account = accounts.get(account_id, {}) if accounts else {}
app_key = (
account.get("appKey")
or account.get("app_key")
or dingtalk_cfg.get("appKey")
or dingtalk_cfg.get("app_key")
or os.environ.get("DINGTALK_APP_KEY", "")
)
app_secret = (
account.get("appSecret")
or account.get("app_secret")
or dingtalk_cfg.get("appSecret")
or dingtalk_cfg.get("app_secret")
or os.environ.get("DINGTALK_APP_SECRET", "")
)
robot_code = (
account.get("robotCode")
or account.get("robot_code")
or dingtalk_cfg.get("robotCode")
or dingtalk_cfg.get("robot_code")
or os.environ.get("DINGTALK_ROBOT_CODE", "")
)
mode = account.get("mode") or dingtalk_cfg.get("mode", "stream")
streaming = account.get("streaming") or dingtalk_cfg.get("streaming", "block")
dingtalk_card_enabled = (
account.get("dingtalkCardEnabled")
if "dingtalkCardEnabled" in account
else dingtalk_cfg.get("dingtalkCardEnabled", dingtalk_cfg.get("dingtalk_card_enabled", False))
)
card_template_id = (
account.get("cardTemplateId")
or account.get("card_template_id")
or dingtalk_cfg.get("cardTemplateId")
or dingtalk_cfg.get("card_template_id", "")
)
dm_policy = (
account.get("dmPolicy")
or account.get("dm_policy")
or dingtalk_cfg.get("dmPolicy")
or dingtalk_cfg.get("dm_policy", "open")
)
group_policy = (
account.get("groupPolicy")
or account.get("group_policy")
or dingtalk_cfg.get("groupPolicy")
or dingtalk_cfg.get("group_policy", "open")
)
group_shared_session = (
account.get("groupSharedSession")
if "groupSharedSession" in account
else dingtalk_cfg.get("groupSharedSession", dingtalk_cfg.get("group_shared_session", True))
)
expires_in_seconds = (
account.get("expiresInSeconds")
or dingtalk_cfg.get("expiresInSeconds")
or dingtalk_cfg.get("expires_in_seconds", 3600)
)
hot_reload = (
account.get("hotReload")
if "hotReload" in account
else dingtalk_cfg.get("hotReload", dingtalk_cfg.get("hot_reload", False))
)
chat_time_module = (
account.get("chatTimeModule")
if "chatTimeModule" in account
else dingtalk_cfg.get("chatTimeModule", dingtalk_cfg.get("chat_time_module", False))
)
chat_start_time = (
account.get("chatStartTime")
or dingtalk_cfg.get("chatStartTime")
or dingtalk_cfg.get("chat_start_time", "00:00")
)
chat_stop_time = (
account.get("chatStopTime")
or dingtalk_cfg.get("chatStopTime")
or dingtalk_cfg.get("chat_stop_time", "24:00")
)
agent = account.get("agent") if "agent" in account else dingtalk_cfg.get("agent", False)
agent_workspace = (
account.get("agentWorkspace")
or dingtalk_cfg.get("agentWorkspace")
or dingtalk_cfg.get("agent_workspace", "~/cow")
)
render_mode = (
account.get("renderMode")
or account.get("render_mode")
or dingtalk_cfg.get("renderMode")
or dingtalk_cfg.get("render_mode", "auto")
)
subscribe_topics = (
account.get("subscribeTopics")
or account.get("subscribe_topics")
or dingtalk_cfg.get("subscribeTopics")
or dingtalk_cfg.get("subscribe_topics", [])
)
enabled = account.get("enabled") if "enabled" in account else dingtalk_cfg.get("enabled", True)
return DingTalkAccount(
account_id=account_id,
app_key=app_key,
app_secret=app_secret,
robot_code=robot_code,
mode=mode,
streaming=streaming,
dingtalk_card_enabled=dingtalk_card_enabled,
card_template_id=card_template_id,
dm_policy=dm_policy,
group_policy=group_policy,
group_shared_session=group_shared_session,
expires_in_seconds=expires_in_seconds,
hot_reload=hot_reload,
chat_time_module=chat_time_module,
chat_start_time=chat_start_time,
chat_stop_time=chat_stop_time,
agent=agent,
agent_workspace=agent_workspace,
render_mode=render_mode,
subscribe_topics=subscribe_topics if isinstance(subscribe_topics, list) else [],
enabled=enabled,
)
def is_configured(self, account: DingTalkAccount | dict) -> bool:
if isinstance(account, DingTalkAccount):
return account.is_configured()
return bool(account.get("app_key") or account.get("appKey")) and bool(
account.get("app_secret") or account.get("appSecret")
)
def is_enabled(self, account: DingTalkAccount | dict) -> bool:
if isinstance(account, DingTalkAccount):
return account.enabled
return account.get("enabled", True)
def disabled_reason(self, account: DingTalkAccount | dict) -> str:
if not self.is_configured(account):
return "AppKey or AppSecret not configured"
return ""
def describe_account(self, account: DingTalkAccount | dict) -> dict:
if isinstance(account, DingTalkAccount):
return {
"account_id": account.account_id,
"configured": account.is_configured(),
"mode": account.mode,
}
return {
"account_id": account.get("account_id", ""),
"configured": self.is_configured(account),
"mode": account.get("mode", "stream"),
}
def _get_dingtalk_config(config: dict | None) -> dict:
if not config:
return {}
return config.get("channels", {}).get("dingtalk", {})