ForcePilot/backend/package/yuxi/channels/adapters/nextcloudtalk/pairing.py
Kris b018ad25da feat(backend): add Nextcloud Talk channel adapter implementation
实现了完整的Nextcloud Talk聊天适配器,包含以下核心功能:
1. 基础客户端通信与认证
2. 会话路由与聊天类型解析
3. 消息分块与格式转换
4. 用户配对与权限校验
5. 轮询式消息监听
6. 配置验证与诊断工具
7. 安全策略与去重缓存
8. 指标统计与状态快照

新增配套的配对用户缓存文件与模块导出入口。
2026-05-12 00:47:06 +08:00

76 lines
2.4 KiB
Python

from __future__ import annotations
import logging
from typing import Any
from .client import NextcloudTalkClient
logger = logging.getLogger(__name__)
PAIRING_MESSAGE = (
"Hello! Your account is not yet authorized to interact with this bot.\n\n"
"Your Nextcloud user id: `{user_id}`\n\n"
"Please ask an administrator to approve your access by adding your user id "
"to the paired users list using:\n\n"
"```\n"
"from yuxi.channels.adapters.nextcloudtalk.security import pair_user\n"
'pair_user("{user_id}")\n'
"```\n\n"
"Once approved, send another message to start interacting with the bot."
)
APPROVED_MESSAGE = "Your account `{user_id}` has been approved! Send a message to start."
async def send_pairing_challenge(
client: NextcloudTalkClient,
api_base: str,
token: str,
user_id: str,
config: dict[str, Any] | None = None,
) -> bool:
try:
message = PAIRING_MESSAGE.format(user_id=user_id)
payload = {
"token": token,
"message": message,
"referenceId": f"pairing-{user_id}",
}
result = await client.post(f"{api_base}/chat/{token}", json_data=payload)
ocs = result.get("ocs", {})
meta = ocs.get("meta", {})
if meta.get("statuscode") == 201:
logger.info(f"[NextcloudTalk] Pairing challenge sent to {user_id} in {token}")
return True
logger.warning(f"[NextcloudTalk] Failed to send pairing challenge: {meta}")
return False
except Exception as e:
logger.warning(f"[NextcloudTalk] Failed to send pairing challenge: {e}")
return False
async def send_pairing_approved(
client: NextcloudTalkClient,
api_base: str,
token: str,
user_id: str,
config: dict[str, Any] | None = None,
) -> bool:
try:
message = APPROVED_MESSAGE.format(user_id=user_id)
payload = {
"token": token,
"message": message,
"referenceId": f"pairing-approved-{user_id}",
}
result = await client.post(f"{api_base}/chat/{token}", json_data=payload)
ocs = result.get("ocs", {})
meta = ocs.get("meta", {})
if meta.get("statuscode") == 201:
logger.info(f"[NextcloudTalk] Pairing approved notification sent to {user_id}")
return True
return False
except Exception as e:
logger.warning(f"[NextcloudTalk] Failed to send pairing approved: {e}")
return False