新增 Nextcloud Talk 渠道扩展,支持在 Yuxi 平台中集成 Nextcloud Talk 即时通讯渠道。 包含以下功能模块: - accounts: 账户管理 - bot_admin: Bot 管理 - chat_api: 聊天 API 封装 - config_schema: 配置模式 - conversation: 会话管理 - gateway: SSE/WebSocket 网关接入 - inbound: 入站消息处理 - send: 消息发送 - webhook_server: Webhook 服务 - format: 消息格式转换 - normalize: 消息规范化 - poll_api: 投票 API - reaction_api: 表情反应 API - policy: 安全策略 - probe: 健康探测 - replay_guard: 重放防护 - signature: 签名验证 - room_info: 房间信息 - types: 类型定义
76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from yuxi.channel.extensions.nextcloud_talk.config_schema import NextcloudTalkConfig
|
|
from yuxi.channel.extensions.nextcloud_talk.types import ResolvedNextcloudTalkAccount
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _read_secret_file(file_path: str) -> str:
|
|
p = Path(file_path)
|
|
if not p.is_file():
|
|
logger.warning("Nextcloud Talk: secret file not found: %s", file_path)
|
|
return ""
|
|
if p.is_symlink():
|
|
logger.warning("Nextcloud Talk: secret file is a symlink, refusing to read: %s", file_path)
|
|
return ""
|
|
try:
|
|
return p.read_text(encoding="utf-8").strip()
|
|
except Exception as e:
|
|
logger.warning("Nextcloud Talk: failed to read secret file %s: %s", file_path, e)
|
|
return ""
|
|
|
|
|
|
def _resolve_bot_secret(cfg: NextcloudTalkConfig, account_id: str) -> tuple[str, str]:
|
|
if account_id == "default":
|
|
env_val = os.environ.get("NEXTCLOUD_TALK_BOT_SECRET")
|
|
if env_val:
|
|
return env_val, "env"
|
|
if cfg.bot_secret_file:
|
|
content = _read_secret_file(cfg.bot_secret_file)
|
|
if content:
|
|
return content, "file"
|
|
if cfg.bot_secret:
|
|
return cfg.bot_secret, "config"
|
|
return "", "none"
|
|
|
|
|
|
def _resolve_api_password(cfg: NextcloudTalkConfig) -> tuple[str, str]:
|
|
if cfg.api_password:
|
|
return cfg.api_password, "config"
|
|
if cfg.api_password_file:
|
|
content = _read_secret_file(cfg.api_password_file)
|
|
if content:
|
|
return content, "file"
|
|
return "", "none"
|
|
|
|
|
|
def resolve_nextcloud_talk_account(
|
|
cfg: NextcloudTalkConfig, account_id: str = "default"
|
|
) -> ResolvedNextcloudTalkAccount:
|
|
bot_secret, secret_source = _resolve_bot_secret(cfg, account_id)
|
|
api_password, api_password_source = _resolve_api_password(cfg)
|
|
|
|
configured = bool(cfg.base_url and bot_secret)
|
|
|
|
return ResolvedNextcloudTalkAccount(
|
|
account_id=account_id,
|
|
enabled=cfg.enabled,
|
|
name=cfg.name or account_id,
|
|
configured=configured,
|
|
base_url=cfg.base_url,
|
|
bot_secret=bot_secret,
|
|
secret_source=secret_source,
|
|
api_user=cfg.api_user,
|
|
api_password=api_password,
|
|
api_password_source=api_password_source,
|
|
)
|
|
|
|
|
|
def list_nextcloud_talk_account_ids(cfg: NextcloudTalkConfig) -> list[str]:
|
|
return ["default"]
|