HarukaBot: pushing Bilibili updates into a QQ group
将 B 站的动态和直播信息推送至 QQ,基于 NoneBot2 开发
At a glance
- What is it?
- HarukaBot is a NoneBot2 plugin that watches Bilibili creators and pushes their posts and live status into QQ groups, with per-creator and per-group controls and a workaround for the group-wide mention limit. Its pyproject.toml is the most interesting part, because every version cap there comes with a comment explaining the incompatibility that caused it.
- Who is it for?
- Adopt HarukaBot if you run a QQ group around a set of Bilibili creators and want the posts and live status to arrive without someone copying links by hand, because the per-creator and per-group settings cover the cases that make such bots annoying otherwise.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A bot for the group chat of a fan community
HarukaBot pushes Bilibili creator posts and live information to QQ, and the README describes it as an elegant Bilibili push QQ bot. The project description in the repository metadata is the same idea in English: push dynamics and live informations from bilibili to QQ, based on nonebot2.
The name comes from a Bilibili creator, the README says the name derives from 白神遥Haruka, and the logo was drawn by someone else, Ratto, both credited by link. The project is the successor to an earlier bot of the same author's, dd-bot, so the code carries the conventions of a bot that has been running for a while rather than a fresh start.
The framework is NoneBot2, and the project is a plugin for it, with the plugin name in the project keywords and the configuration in pyproject.toml listing the adapter and the plugins it loads. The licence is AGPL-3.0, the project is published on PyPI as haruka-bot, and the documentation site is haruka-bot.sk415.icu, which also carries the changelog and a demo screenshot.
The primary language is Python, the default branch is master, and the last push was on 2026-10-13. The QQ group the project points people at has a number in the README, which is a small sign of an active community around it.
Per-creator filters, admin-only use, and the mention limit
The features section is short and it is all about the details that make a push bot tolerable.
Push content is customised per creator, so a creator can be limited to dynamics only, or to live only, which matters because a busy channel and a slow one are different objects and mixing them is the most common complaint about such bots.
The bot can be restricted in a group so that only administrators and above can use it. That is the difference between a bot that reacts to any command from any member and one that only answers when someone with the right permission asks.
The mention behaviour is the most interesting of the three. A group-wide mention of all members can be scheduled for a chosen content type, and once the count is used up the request is ignored automatically. And the bot can connect several QQ accounts at the same time, which the README gives as the reason: it avoids the problem of running out of group-wide mentions.
That last point is worth pausing on as an engineer, because it tells you how the platform's limits shape the design. A QQ account has a budget of group-wide mentions per period, and the bot spreads the load across accounts rather than rationing one account. The README frames the scenes it serves as fan groups, entertainment groups and live-notification groups, which are three quite different traffic patterns, and the settings are per group so a busy group can have stricter rules than a quiet one.
The dependency list is the integration story
The dependencies in pyproject.toml describe how the bot reaches Bilibili and how it reaches QQ, and they are worth reading in detail.
On the Bilibili side there are two: bilireq at ^0.2.6, and the project credits the bilibili_api Python library and the bilibili-API-collect documentation, which it describes as very detailed API documentation for the site, and the go-cqhttp project, credited as a stable and complete CQHTTP implementation. NoneBot2 is the framework, nonebot-adapter-onebot at ^2.2.3 is the QQ adapter, and the nonebot configuration in the same file selects the OneBot V11 adapter with the module name nonebot.adapters.onebot.v11.
On the infrastructure side there is nonebot-plugin-apscheduler at ^0.3.0, which is how a polling schedule is expressed, tortoise-orm with the asyncpg extra at ^0.19.3, which is the ORM and the PostgreSQL driver, httpx for HTTP, click for the command line, python-dotenv for the environment file, and playwright at ^1.35.0, which in a bot of this kind is normally there for a headless browser to get through a page that requires one.
And there is aunly-captcha-solver at ^0.1, a captcha solver, which is the dependency that tells you the bot logs in to Bilibili with a real account rather than reading public pages anonymously. That is a legitimate thing for a bot to do, and it is also the dependency that makes the ToS question real rather than theoretical.
The remaining dependency, msvc-runtime at ^14.34.31931 with a win32 marker, exists so the package installs on Windows, and packaging is there for version comparisons.
Every version cap has a reason written next to it
What makes this pyproject.toml worth reading is that the constraints come with explanations, in the file, in Chinese comments. That is rare and useful, because each cap is a record of a specific breakage.
The fastapi dependency is capped below 0.119 for Python 3.14 and above, and the comment says that fastapi 0.120 and later is no longer compatible with pydantic v1 on Python 3.14, while older Pythons are unaffected and can keep using the newer version. The marker on the dependency line is what makes that conditional.
pydantic is pinned to ^1.10.9,<2, and the comment says that the original looser constraint actually allowed pydantic 2.0.0, whereas the project uses the pydantic v1 API. That is the classic v1 to v2 break, and the fix was to state the upper bound rather than to migrate.
tortoise-orm with asyncpg is capped at <1, and the comment says tortoise-orm 1.x changed to a context-based model that is incompatible with this project's older Tortoise.init() usage. httpx is held below 0.28. The project itself declares requires-python >=3.8,<4.0.
So the dependency set describes a codebase pinned to a coherent set of older libraries, with the reasons recorded. It is honest, and it is also a maintenance liability, because each cap is waiting for a security advisory or a platform change to force the migration. The alternative would have been to spend the work migrating earlier, and the author chose stability of the running bot over that.
The Docker image is a Playwright image, and an old one
The Dockerfile is short and reveals a good deal.
FROM mcr.microsoft.com/playwright/python:v1.22.0-focal
LABEL maintainer="https://github.com/SK-415/HarukaBot"
EXPOSE 8080
RUN pip install haruka-bot -i https://mirrors.aliyun.com/pypi/simple/
WORKDIR /haruka_bot
COPY .env.prod /haruka_bot/.env.prod
ENV TZ=Asia/Shanghai LANG=zh_CN.UTF-8 HOST=0.0.0.0
CMD ["hb" ,"run"]The base image is the Playwright Python image, which is the right choice for a bot that needs a browser, and the container installs the package from PyPI through the Aliyun mirror, which is a sensible default for the audience this project serves. The timezone and locale are set to Asia/Shanghai and zh_CN.UTF-8, the host binding is 0.0.0.0 with port 8080 exposed, and the entry point is the hb command from the project's console script, run with the run argument.
There is one inconsistency worth flagging. The image is pinned to Playwright v1.22.0, while the dependency on the playwright package is ^1.35.0, and the base image carries the browser binaries of its own version. A pip install of a newer playwright inside a container with older browser binaries is a mismatch that shows up as a missing browser or a version error at run time rather than at build time, because the image installs the published package rather than building this repository.
The image also copies .env.prod into the container, so the environment configuration is baked into the image rather than supplied at run time, which is convenient for a single-user deployment and wrong for anything shared.
Plugin wiring, entry points, and the repository layout
The NoneBot2 configuration in pyproject.toml is short and tells you the shape of the deployment. The adapters list has one entry, OneBot V11. The plugins list has three: haruka_bot, nonebot_plugin_gocqhttp and nonebot_plugin_guild_patch, with plugin_dirs and builtin_plugins both empty, which means nothing is discovered at run time and the set is fixed in the manifest.
The guild patch has its own history worth noting. The README credits HarukaBot_Guild_Patch as a patch that lets HarukaBot work in channels, and says it has been merged into HarukaBot, which is the project asking for a feature and then taking the contribution.
The console script is hb, mapped to haruka_bot.__main__:main, so the package has its own entry point rather than expecting you to call the framework's runner directly. The version is dynamic and read from a file, with the pdm version source set to file and a path, which is the arrangement that lets a development build carry a version that was never tagged.
The top-level listing matches a bot project: bot.py, the haruka_bot/ package, test.py, a .env.prod file, a .flake8 configuration, pdm.lock as the lockfile, a docs/ directory with the VuePress site, the Dockerfile and the pyproject.toml. The .env.prod file being tracked in the repository is worth a second look, since a production environment file in version control is where credentials end up, and the Dockerfile copies that same file into the image.
Three years of commits and a release from 2023
The release history is the most useful signal in the repository's metadata, and it is the one that needs care.
The three most recent releases are v1.6.0.post3 on 2023-06-29, v1.6.0.post4 on 2023-06-29, and v1.6.0post5 on 2023-07-11. The last two are from the same month, the second and third are ten minutes apart, and the last one is over three years old.
Against that, the last push to the repository was on 2026-10-13, and the pyproject.toml contains dependency changes that could only have been made recently, including the Python 3.14 compatibility cap on fastapi, which is a current concern. So the code is being worked on and the releases are not being cut. The version of the project as published on PyPI is three years behind the version in the repository.
The tag naming is also inconsistent, v1.6.0post5 against v1.6.0.post4, and the difference is not cosmetic. A post-release suffix normalises to a dotted form for the package index, and a tag that does not match the normalised version is a tag that a tool looking for the version cannot find.
What this means for an adopter is straightforward. If you want a running bot, the published package is the one you will get, and it is from 2023, running against the dependency versions of that time. If you want the current behaviour, you build from the repository, which means you inherit the dependency caps and the environment file question. Either way, the README's own advice applies: issues and pull requests are welcome, and the project asks for support through a QQ group and an Afdian page.
Editorial conclusion
Adopt HarukaBot if you run a QQ group around a set of Bilibili creators and want the posts and live status to arrive without someone copying links by hand, because the per-creator and per-group settings cover the cases that make such bots annoying otherwise. Do not adopt it as a base for your own bot without reading the dependency constraints, because the pyproject.toml is full of upper bounds tied to old APIs, the Playwright base image in the Dockerfile is far older than the Playwright dependency it installs, and the last tagged release is from 2023. Before you deploy it, check that its Bilibili login flow still works with the captcha solver dependency it carries, confirm the AGPL-3.0 terms suit how you intend to run it, and expect to build from the repository rather than from a published wheel.
Frequently asked questions
What does HarukaBot do?
It pushes Bilibili creator posts and live status into QQ groups. Push content can be customised per creator, so a creator can be limited to dynamics only or live only, the bot can be restricted in a group so that only administrators and above can use it, and several QQ accounts can be connected at once to work around the group-wide mention limit.
Which framework is HarukaBot built on?
NoneBot2, as a plugin. The NoneBot configuration in pyproject.toml selects the OneBot V11 adapter with the module nonebot.adapters.onebot.v11, and loads the haruka_bot plugin together with nonebot_plugin_gocqhttp and nonebot_plugin_guild_patch. The package installs a console script called hb.
Why does HarukaBot pin old versions of fastapi and pydantic?
The pyproject.toml comments explain each cap. fastapi is held below 0.119 on Python 3.14 because newer releases are not compatible with pydantic v1 there, pydantic is held below 2 because the project uses the v1 API, and tortoise-orm is held below 1 because version 1.x changed to a context model that the project's older init style is incompatible with.
What licence is HarukaBot under?
GNU AGPLv3. The pyproject.toml records the licence as AGPL-3.0-or-later, and the README states that the project uses the GNU AGPLv3 as its open source licence, with a LICENSE file in the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sk-415-harukabot)Was this useful?