ForcePilot/backend/package/yuxi/channels/adapters/qqbot/commands/builtin.py
Kris ef5483dc1a refactor(qqbot): 重构QQ机器人适配器代码,优化多项功能与结构
主要变更:
1. 修复速率限流器使用setdefault替代重复创建令牌桶
2. 重构交互注册表匹配逻辑,优化精确匹配查找
3. 重构去重缓存逻辑,移到适配器实例方法
4. 重构发送URL解析,增加合法性校验并拆分公共方法
5. 优化流式消息处理逻辑,简化flush_controller调用
6. 重构群聊类型判断代码,简化语法
7. 修复重连管理器对None类型关闭分类的处理
8. 新增消息缓存、线程模拟器、发送初始化模块
9. 重构凭证备份与会话存储逻辑,支持环境变量指定状态目录
10. 新增配置提示与向导二维码绑定功能
11. 优化媒体上传逻辑,增加重试机制与缓存
12. 新增审批键盘模板构建函数
13. 重构消息格式处理,修正媒体发送字段与长度限制
14. 修复令牌过期时间计算,使用time.time替代monotonic
15. 新增群组激活缓冲区与用户追踪器增强功能
16. 修复换行符问题,统一文件结尾格式
2026-05-13 16:13:48 +08:00

140 lines
4.4 KiB
Python

from __future__ import annotations
import time
from .framework import CommandContext, CommandRegistry, CommandResult
_start_time = time.time()
_QQBOT_CMD_INPUT_TAG = "<qqbot-cmd-input>"
_QQBOT_CMD_ENTER_TAG = "<qqbot-cmd-enter>"
async def _cmd_ping(ctx: CommandContext) -> CommandResult:
uptime = time.time() - _start_time
hours = int(uptime // 3600)
minutes = int((uptime % 3600) // 60)
seconds = int(uptime % 60)
msg = ctx.msg
user = msg.identity.channel_user_id or "Unknown"
return CommandResult(
success=True,
message=f"Pong! 在线时间: {hours}h {minutes}m {seconds}s\n发送者: {user}",
)
async def _cmd_version(ctx: CommandContext) -> CommandResult:
adapter = ctx.adapter
version = getattr(adapter, "_plugin_version", "1.0.0")
extra: dict[str, str] = {}
bot_info = getattr(adapter, "_bot_info", None)
if bot_info:
extra["BotID"] = bot_info.get("id", "")
extra["BotName"] = bot_info.get("username", "")
parts = [f"版本: {version}"]
for k, v in extra.items():
if v:
parts.append(f"{k}: {v}")
return CommandResult(success=True, message="\n".join(parts))
async def _cmd_help(ctx: CommandContext) -> CommandResult:
registry = ctx.adapter._command_registry if hasattr(ctx.adapter, "_command_registry") else None
if registry is None:
return CommandResult(success=True, message="命令系统未初始化。")
is_group = getattr(ctx.msg, "chat_type", None)
is_group_val = str(is_group) == "ChatType.GROUP" or (hasattr(is_group, "value") and is_group.value == "group")
lines = ["可用命令:"]
seen: set[str] = set()
for name in sorted(registry.command_names):
cmd = registry._commands.get(name)
if cmd is None or name in seen:
continue
if name.startswith("_") or name != cmd.name:
continue
seen.add(name)
hidden = cmd.metadata.get("hidden_in_group", False) if hasattr(cmd, "metadata") else False
if is_group_val and hidden:
continue
desc = cmd.description or "(无描述)"
usage = f" - 用法: {cmd.usage}" if cmd.usage else ""
cmd_display = f"{_QQBOT_CMD_INPUT_TAG}/{name}{_QQBOT_CMD_ENTER_TAG}"
lines.append(f" {cmd_display} - {desc}{usage}")
return CommandResult(success=True, message="\n".join(lines))
async def _cmd_status(ctx: CommandContext) -> CommandResult:
adapter = ctx.adapter
status = getattr(adapter, "status", "unknown")
reconnect = getattr(adapter, "_reconnect_manager", None)
reconnect_state = reconnect.state.name if reconnect else "N/A"
circuit_breaker = getattr(adapter, "_circuit_breaker", None)
cb_state = "open" if circuit_breaker and circuit_breaker.is_open else "closed"
return CommandResult(
success=True,
message=(f"状态: {status}\n重连状态: {reconnect_state}\n熔断器: {cb_state}"),
)
async def _cmd_clearlogs(ctx: CommandContext) -> CommandResult:
adapter = ctx.adapter
known_users = getattr(adapter, "_known_users", None)
group_buffer = getattr(adapter, "_group_buffer", None)
if known_users:
known_users.clear()
if group_buffer:
group_buffer.gc()
return CommandResult(success=True, message="日志已清理(已知用户记录 + 过期群聊缓冲)。")
def register_builtin_commands(registry: CommandRegistry) -> CommandRegistry:
registry.register(
name="bot-ping",
handler=_cmd_ping,
description="检测 Bot 是否在线",
usage="/bot-ping",
aliases=["ping", "p"],
)
registry.register(
name="bot-version",
handler=_cmd_version,
description="显示 Bot 版本信息",
usage="/bot-version",
aliases=["version", "v"],
)
registry.register(
name="bot-help",
handler=_cmd_help,
description="显示所有可用命令",
usage="/bot-help",
aliases=["help", "h"],
)
registry.register(
name="bot-status",
handler=_cmd_status,
description="查看 Bot 运行状态",
usage="/bot-status",
aliases=["status", "st"],
)
registry.register(
name="bot-clearlogs",
handler=_cmd_clearlogs,
description="清理运行日志和缓存",
usage="/bot-clearlogs",
aliases=["clearlogs"],
)
return registry