"""Shared Help facts and renderers for command/chat modes.""" from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True) class Service: key: str title: str summary: str admin: bool = False SERVICES = ( Service("setu", "涩图", "按标签、R18 和 AI 条件获取图片"), Service("pixiv", "Pixiv", "按 PID 获取 Pixiv 图片"), Service("bilibili", "Bilibili", "按 BV 号获取视频并以文件发送"), Service("jm", "JM", "搜索、下载并发送 JM 作品"), Service("mail", "邮件", "绑定邮箱、读取邮件、发送邮件和接收新邮件通知"), Service("akaros_mail", "Akaros 邮件", "使用白花 Akaros 邮箱收发邮件"), Service("live", "直播", "关注直播间并接收开播通知"), Service("ginkgo", "白果云", "课程通知、手动签到和自动签到"), Service("schedule", "定时提醒", "创建一次性或重复定时任务,并查看或取消"), Service("notebook", "备忘录与待办", "长期保存笔记,并管理带期限的个人约定"), Service("my", "身份与设置", "管理统一身份、平台绑定和推送开关"), Service("chat", "聊天与记忆", "自然聊天、长期记忆、历史整理和主动对话"), Service("server", "服务器", "服务器状态与管理", True), Service("deepseek", "DeepSeek", "模型余额及监控", True), Service("log", "日志", "查看运行日志", True), ) def service(key: str): key = key.lower() for index, item in enumerate(SERVICES, 1): if key in (item.key, str(index)): return item return None def command_index(include_admin: bool = False) -> str: lines = ["服务列表", "━━━━━━━━━━━━"] for index, item in enumerate(SERVICES, 1): if item.admin and not include_admin: continue lines.append(f"{index}. {item.title}:.{item.key} help") lines += ["━━━━━━━━━━━━", "TG 可点击下方按钮;QQ 可发送 .help <编号>"] return "\n".join(lines) def _legacy_help(item: Service) -> str: if item.key == "akaros_mail": import importlib return importlib.import_module("for-bot_mail").HELP_TEXT if item.key == "my": import identity_cmd return identity_cmd.MY_HELP_TEXT if item.key == "chat": return ( "聊天与记忆\n━━━━━━━━━━━━\n" ".wallet 查看模型钱包\n.compact 整理聊天历史\n" ".del 删除最近 n 条记录\n.memory 查看或管理长期记忆\n" ".setting 切换 command/chat 模式" ) if item.key == "server": import for_admin_komari_agent return getattr(for_admin_komari_agent, "HELP_TEXT", "使用 .server help 查看服务器帮助") if item.key == "deepseek": from deepseek import deepseek_balance return getattr(deepseek_balance, "HELP_TEXT", "使用 .deepseek help 查看余额监控帮助") if item.key == "log": import for_admin_catch_log return getattr(for_admin_catch_log, "HELP_TEXT", "使用 .log help 查看日志帮助") module = __import__(item.key if item.key != "ginkgo" else "ginkgostu") return getattr(module, "HELP_TEXT", f"使用 .{item.key} help 查看帮助") def command_help(key: str | None = None, include_admin: bool = False) -> str: if not key: return command_index(include_admin) item = service(key) if item is None or (item.admin and not include_admin): return command_index(include_admin) return _legacy_help(item) def _chat_fallback(key: str | None, include_admin: bool) -> str: if key: item = service(key) if item and (include_admin or not item.admin): return f"「{item.title}」可以{item.summary}。你想做什么,直接用自己的话告诉我就好。" lines = ["可以陪你聊天,也能处理这些工具:"] lines += [f"• {x.title}:{x.summary}" for x in SERVICES if include_admin or not x.admin] lines.append("直接说你想做什么就行。") return "\n".join(lines) async def chat_help(uid: int, key: str | None = None, include_admin: bool = False) -> str: fallback = _chat_fallback(key, include_admin) try: from chat import engine facts = command_help(key, include_admin) prompt = ( engine.user_persona_prompt(uid) + "\n\n请把下面的能力说明自然地说给用户听。主帮助直接说明你能做什么," "不必自我介绍,更不要写‘话不算多,先把……介绍一下’之类的开场预告;" "保持准确,不添加不存在的功能,不要逐字照搬命令列表," "可以保留必要命令作为示例。不要以‘需要我……吗’等套路问句结尾。" + ("\n用户指定了模块:" + key if key else "") + "\n\n能力资料:\n" + facts ) import skill_runtime with skill_runtime.skill_session("help", output_mode="text"): raw = await engine.call_deepseek(prompt, "请生成帮助正文,只输出正文。", 0) return raw.strip()[:3900] if raw and raw.strip() else fallback except Exception: return fallback