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,40 @@
"""通用平台视频解析编排层 — B站 / YouTube / Twitter 等"""
from pathlib import Path
from typing import Optional
from nonebot import logger
from nonebot_plugin_alconna import UniMessage
from ..fetchers.video_downloader import download_video
from .sender import PendingMedia, _as_paths
async def handle_universal(
url: str,
is_private: bool,
plan: str | None = None,
) -> tuple[Optional[PendingMedia], Optional[str]]:
"""
下载通用平台视频 → 打包待发送媒体(上传/发送由 sender 多级处理)
Returns:
(PendingMedia, public_url) — None 表示下载失败
"""
video_file = await download_video(url)
if not video_file:
await UniMessage.text("视频下载失败。").send()
return None, None
logger.info(f"文件路径:{video_file}")
return (
PendingMedia(
files=_as_paths(video_file),
image_post=False,
is_private=is_private,
plan=plan,
title="title",
),
None,
)