该提交实现了完整的钉钉聊天渠道插件,包含: 1. 基础配置、账号管理与凭证校验 2. WebSocket长连接网关与消息去重 3. 消息接收/解析/分发与安全校验 4. 媒体文件上传下载与缓存 5. 互动卡片流式更新与回调处理 6. 群管理、命令支持与诊断工具 7. 完整的插件元数据与依赖声明
188 lines
7.1 KiB
Python
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", {})
|