Initial import of Shirobana bot backend
Include utility modules, shared channels, prompts, read-only skills, wardrobe memory and regression tests. Externalize legacy credentials and exclude private runtime state.
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
"""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 条记录\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
|
||||
Reference in New Issue
Block a user