Skip to main content
logo

✨ nonebot-plugin-parsehub ✨

LICENSE pypi python uv
ruff CI

📖 介绍

基于 ParseHub 的社交媒体链接解析插件:群里出现受支持的分享链接时自动解析,发回视频 / 图集 / 图文,并配一张 App Store「Today」风格的信息卡片。

  • 自动解析:发链接或分享文案即可,也可用 解析 命令手动触发
  • 按会话开关:解析开关 控制某个群 / 私聊,超管和群管理可操作
  • 24 个平台:Bilibili、抖音、小红书、微博、快手、知乎、贴吧、豆瓣、今日头条、微信公众号、微信视频号、酷安、皮皮虾、最右、小黑盒、Bangumi、X/Twitter、Instagram、YouTube、TikTok、Threads、Facebook、Snapchat、Medium
  • 卡片 + 媒体:先发信息卡片,再发视频 / 图集;2 个以上媒体合并转发,单个作品最多 20 个
  • 实况照片:图片和短视频一起发;视频走 video 消息段,不占群文件
  • 表情回应:给触发消息点表情(收到 / 成功 / 失败),不引用原消息
  • 成本控制:体积 / 时长上限、会话内去重、并发限制、临时文件自动清理
  • 缓存与投递:同一作品 24 小时内直接发本地缓存;投递方式 file / http / base64 三选一

🎨 效果图

B 站视频卡片:

B 站卡片

抖音图集卡片:

抖音卡片

💿 安装

使用 nb-cli 安装

在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装

nb plugin install nonebot-plugin-parsehub --upgrade

使用 uv 安装

在 nonebot2 项目的插件目录下, 打开命令行, 输入以下指令即可安装

uv add nonebot-plugin-parsehub

安装仓库 main 分支

uv add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main

用 uv 安装后还需要在 nonebot2 项目根目录的 pyproject.toml 里注册插件 (nb-cli 会自动完成这一步):

[tool.nonebot]
plugins = ["nonebot_plugin_parsehub"]

⚙️ 配置

在 nonebot2 项目的 .env 文件中添加下表中的配置, 全部可选(零配置即可加载运行)

配置项 必填 默认值 说明
PARSEHUB_AUTO 否 true 群里出现链接时自动解析(总开关)
PARSEHUB_MAX_FILE_MB 否 100 单个媒体文件体积上限(MB),超过直接跳过;0 = 不限
PARSEHUB_MAX_SECONDS 否 300 视频时长上限(秒),超过只发封面 + 一句提示、不下载;0 = 不限
PARSEHUB_PLATFORMS 否 无 平台白名单:只解析这些平台,留空 = 全部。可写平台 id(xhs)或中文名(小红书)
PARSEHUB_DEDUPE_SECONDS 否 120 同一会话内同一链接的去重窗口(秒),0 = 不去重
PARSEHUB_CONCURRENCY 否 2 同时处理的任务数
PARSEHUB_PROXY 否 无 解析 / 下载代理,如 http://127.0.0.1:7890
PARSEHUB_PROXY_PLATFORMS 否 海外 8 平台 只对这些平台走代理,留空 = 全部走(列表要用合法 JSON)
PARSEHUB_COOKIE 否 无 兜底 cookie(优先读 parsehub 自己的 cookies.toml)
PARSEHUB_TIMEOUT 否 180 解析 + 下载总超时(秒)
PARSEHUB_CACHE_TTL_HOURS 否 24 媒体缓存保留小时数,命中就直接发本地那份;0 = 关闭缓存
PARSEHUB_CACHE_MAX_MB 否 1024 媒体缓存总容量上限(MB),超了按最久没用过的删
PARSEHUB_CARD 否 true 是否发信息卡片图(失败自动退回文字)
PARSEHUB_CARD_FONT 否 无 中文字体路径,留空则自动找系统字体 / 下载
PARSEHUB_FORWARD_TIMEOUT 否 60 合并转发等待协议端的秒数,超时才逐条发
PARSEHUB_SEND_TEXT 否 true 是否发送标题 / 正文
PARSEHUB_MAX_CHARS 否 300 正文最多发送多少字符
PARSEHUB_FAIL_NOTICE 否 true 视频发送失败时是否额外发文字提示
PARSEHUB_DELIVERY 否 file 媒体交给协议端:file = 本机路径(要求同机)/ http = 中转地址 / base64 = 内容内联
PARSEHUB_RELAY_HOST 否 无 中转服务对外地址,留空自动探测内网 IP(仅 http 模式)
PARSEHUB_RELAY_PORT 否 21473 中转服务端口(仅 http 模式)
PARSEHUB_TASK_TTL_MINUTES 否 30 临时文件保留分钟数

列表类配置必须是合法 JSON(如 PARSEHUB_PROXY_PLATFORMS=["twitter", "youtube"]); 数值项有下界校验(如 PARSEHUB_TIMEOUT >= 5),写 0 或负数会在启动时直接报错。 哪些群 / 私聊解析由命令 解析开关 控制,没有对应的配置项。

需要登录态的平台(X、Instagram、TikTok、豆瓣、微信视频号 等),cookie 优先从 ParseHub 自己的配置读取 (ph set cookie <平台>),也可以用 PARSEHUB_COOKIE 兜底。

🎉 使用

指令表

指令 权限 需要@ 范围 说明
解析 <链接或分享文案>(别名 ph、解析链接) 群员 否 群聊/私聊 手动解析,不做去重拦截
解析平台 群员 否 群聊/私聊 列出支持的平台
解析开关 [开|关]、解析开、解析关 主人/群管 否 群聊/私聊 按会话开关解析(私聊仅主人)
解析状态 群员 否 群聊/私聊 查看当前会话的开关状态

触发规则

  • 群里发链接或分享文案即自动解析,一条消息最多处理 3 个链接
  • 解析关 后该会话不再自动解析;手动 解析 只对超管 / 群管理有效
  • 命令前缀支持空前缀与 /(COMMAND_START 需包含 "")

解析开关

  • 以会话为维度(群按群号,私聊按对方 QQ),群和私聊默认都开
  • 关掉后该会话不再自动解析,手动解析仅超管 / 群管可用;状态所有人可看
  • 超管与群主 / 管理员可修改;状态存在 sessions.json,只记录与默认值不同的会话

媒体缓存

  • 按作品跨会话共享:A 群发过的视频,B 群再发直接发本地那份
  • 命中即跳过:不解析、不下载、不画卡(卡片图也一起缓存)
  • 保留 24 小时(命中续期),总量上限 1GB,超了按最久没用过的删
  • 不同写法归一:b23.tv/xxx 与 bilibili.com/video/BVxxx 是同一个作品
  • 时间线:120 秒内同会话重复 → 静默;120 秒 ~ 24 小时 → 直接发缓存;超过 24 小时 → 重新解析
  • 手动 解析 <链接> 同样吃缓存(只是不做去重拦截)

说明

  • 视频被协议端拒绝时只点失败表情,不会退回群文件
  • 投递三选一、互不兜底:file 发本机路径(协议端同机)/ http 发中转地址(跨机)/ base64 内容内联(请求体约 +1/3)
  • parsehub 全程同步阻塞,插件把所有调用放进 asyncio.to_thread;首次导入懒加载,不影响启动
  • 卡片用 Pillow 画,封面三级兜底(thumb_url → 图片媒体 → 视频抽帧),没装 Pillow 或没有中文字体时自动退回文字; 字体优先 PARSEHUB_CARD_FONT → 缓存目录 → 系统字体 → 下载(sha256 校验),缺字用回退字体补,emoji 用 Twemoji 位图字体

🛠️ 开发

uv sync --all-groups            # 安装依赖(含测试)
uv run poe check                # 代码检查 + 格式检查 + 测试(CI 同款)
uv run pytest -q                # 只跑测试
uv run poe live                 # 真实链路自检(解析 → 下载 → 中转取回)

代码结构

src/nonebot_plugin_parsehub/
├── triggers.py         # matcher / 命令:只决定「处理谁」
├── service.py          # 编排:每个结局都是 Outcome 里的一个值
├── delivery.py         # 三种上传模式 + 合并转发/逐条 + 统一失败记账
├── feedback.py         # 表情回应与用户提示文案
├── cache.py            # 作品级媒体缓存(哈希目录、原子写)
├── dedupe.py           # 会话级去重(claim / commit / release)
├── relay.py            # 只读中转服务(只服务 relay/)
├── parsehub_client.py  # ParseHub 懒加载 + 线程池封装
├── card/               # fonts / cover / layout + CardRenderer
└── app.py              # 装配与生命周期

模块级单例已全部移除:App 持有设置、客户端、缓存、去重、开关、中转、投递和卡片, 测试直接 App.build(...) 造独立实例。

代码风格

遵循 Google Python Style Guide:行宽 80,Google 风格文档字符串, ruff 强制 pydocstyle(google) + pep8-naming + isort。

有意保留的偏差:包内用相对导入(本地插件加载时绝对自引用会 ImportError);NoneBot 按名字导入; 中文文档字符串以「。」结尾(关闭 D415);测试不强制文档字符串。

📄 许可

MIT

🙏 致谢

Metadata

Release files for nonebot-plugin-parsehub 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nonebot-plugin-parsehub 1.0.0
File Size Uploaded Provenance
nonebot_plugin_parsehub-1.0.0.tar.gz 388.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for nonebot-plugin-parsehub 1.0.0
File Interpreter ABI Platform
nonebot_plugin_parsehub-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 795.5 kB

Release files / nonebot_plugin_parsehub-1.0.0.tar.gz

Download URL nonebot_plugin_parsehub-1.0.0.tar.gz
Size 388.7 kB
Tags Source
SHA-256 checksum
How to use checksums
823d5728bbf7cb1e4c2f45ee1a6b77bd2810c76758cf8315309c489d35a543a6
BLAKE2b-256 checksum
How to use checksums
d2012da268eb3f3a50b0a096207b4727994f34253f1e24d05973e41524065f7f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / nonebot_plugin_parsehub-1.0.0-py3-none-any.whl

Download URL nonebot_plugin_parsehub-1.0.0-py3-none-any.whl
Size 406.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
db6abb1c925754a6e7d1156bf67164da267b2c8887518446a67b2466148b286a
BLAKE2b-256 checksum
How to use checksums
4e8dfa94c2ded571da497e035a8cdc88072cf1bf78bbcb57172dd96349d14179
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Security for nonebot-plugin-parsehub 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for nonebot_plugin_parsehub-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page