新增 Tlon 渠道扩展,支持在 Yuxi 平台中集成 Tlon/Urbit 去中心化通讯平台。 包含以下功能模块: - tlon_api: Tlon API 客户端封装 - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - sse_client: SSE 客户端 - outbound: 外发消息管理 - send: 消息发送 - security: 安全校验 - auth: 认证管理 - monitor: 渠道状态监控 - status: 会话状态管理 - session: 会话管理 - approval: 审批流程 - channel_mgmt: 频道管理 - channel_ops: 频道操作 - contacts: 联系人管理 - discovery: 服务发现 - doctor: 健康诊断 - expose: 服务暴露 - gallery: 图库管理 - history: 历史记录 - hooks: 钩子管理 - media: 媒体资源处理 - notebook: 笔记本功能 - settings_store: 设置存储 - setup: 初始化设置 - story: 故事功能 - targets: 目标管理 - cite_parser: 引用解析 - utils: 工具函数 - types: 类型定义
75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
import asyncio
|
|
import logging
|
|
import time
|
|
|
|
from yuxi.channel.extensions.twitch.config import TwitchAccountConfig
|
|
from yuxi.channel.extensions.twitch.token import denormalize_token
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def probe_twitch(account: TwitchAccountConfig, timeout_ms: int = 10000) -> dict:
|
|
start = time.time()
|
|
|
|
if not account.access_token or not account.username:
|
|
return {
|
|
"ok": False,
|
|
"error": "missing credentials (access_token, username)",
|
|
"username": account.username,
|
|
"elapsed_ms": int((time.time() - start) * 1000),
|
|
}
|
|
|
|
token = denormalize_token(account.access_token)
|
|
|
|
from twitchio import Client
|
|
|
|
client = Client(token=token)
|
|
|
|
try:
|
|
connected = asyncio.Event()
|
|
|
|
@client.event()
|
|
async def event_ready():
|
|
connected.set()
|
|
|
|
connect_task = asyncio.create_task(client.start())
|
|
|
|
try:
|
|
await asyncio.wait_for(connected.wait(), timeout=timeout_ms / 1000)
|
|
elapsed = int((time.time() - start) * 1000)
|
|
|
|
return {
|
|
"ok": True,
|
|
"connected": True,
|
|
"username": account.username,
|
|
"channel": account.channel,
|
|
"elapsed_ms": elapsed,
|
|
}
|
|
except TimeoutError:
|
|
return {
|
|
"ok": False,
|
|
"error": f"timeout after {timeout_ms}ms",
|
|
"username": account.username,
|
|
"channel": account.channel,
|
|
"elapsed_ms": timeout_ms,
|
|
}
|
|
finally:
|
|
connect_task.cancel()
|
|
try:
|
|
await connect_task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
except Exception as e:
|
|
return {
|
|
"ok": False,
|
|
"error": str(e),
|
|
"username": account.username,
|
|
"channel": account.channel,
|
|
"elapsed_ms": int((time.time() - start) * 1000),
|
|
}
|
|
finally:
|
|
try:
|
|
await client.close()
|
|
except Exception:
|
|
pass
|