Add HeXi bot codebase: custom plugins, web frontends, tests

- hexi core: message handling, rate limiting, cooldown, plugin manager
- Custom plugins: BF stats, daily check-in, quotes, persona cards, etc.
- Community plugins vendored under hexi/plugins with local fixes
- Web admin frontends (learning-chat, persona-admin), unified hexi/web
- Tests for rate_limit/cooldown/memes/persona; poetry.lock

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 13:13:40 +08:00
co-authored by Claude
parent 1783c60afa
commit b61d09f09f
3201 changed files with 160436 additions and 171 deletions
@@ -0,0 +1,48 @@
import os
import re
from nonebot import on_startswith, require
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.plugin import PluginMetadata
require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import UniMessage
from .HuoZiYinShua.huoZiYinShua import huoZiYinShua
__plugin_meta__ = PluginMetadata(
name="otto活字印刷",
description="鬼畜音源活字印刷(otto语音合成)",
usage="otto 一些内容 生成otto语音\notto 一些内容 -reverse 生成并倒放",
type="application",
)
self_path = os.path.dirname(__file__)
settings = {
"sourceDirectory": os.path.join(self_path, "HuoZiYinShua", "sources", ""),
"ysddSourceDirectory": os.path.join(self_path, "HuoZiYinShua", "ysddSources", ""),
"dictFile": os.path.join(self_path, "HuoZiYinShua", "dictionary.json"),
"ysddTableFile": os.path.join(self_path, "HuoZiYinShua", "ysddTable.json"),
}
HZYS = huoZiYinShua(settings)
otto = on_startswith("otto")
@otto.handle()
async def otto_handle(ev: MessageEvent):
txt = ev.message.extract_plain_text().removeprefix("otto")
pattern_reverse = re.compile(r"-reverse\s*$")
if re.search(pattern_reverse, txt):
# 结尾匹配到 -reverse
reverse = True
txt = re.sub(pattern_reverse, "", txt)
txt = ",,," + txt # 加一段空白
else:
reverse = False
txt = txt + ",,," # 加一段空白
b64audio = HZYS.export(txt, inYsddMode=True, reverse=reverse)
await UniMessage.voice(url=f"base64://{b64audio.decode()}").send()