How HoshinoBot Group Management and Anti-Spam Features Work: A Deep Dive into the Service Architecture
HoshinoBot implements group management and anti-spam through a modular Service class that wraps NoneBot event handlers with automatic permission checks, per-group configuration, and block-list integration.
The ice9coffee/hoshinobot repository structures every group-management function—whether anti-spam, anti-recall, or keyword filtering—around a lightweight Service abstraction. This design ensures consistent privilege validation and allows administrators to toggle features per group without modifying core logic.
Core Architecture: The Service Class and Permission Layer
Service Registration and Event Binding
At the heart of HoshinoBot's group management system lies the Service class defined in hoshino/service.py. This class acts as a wrapper that registers callbacks with the underlying NoneBot event system while automatically handling group-level enable/disable states.
When you create a service instance, you define its visibility and default availability:
from hoshino import Service
sv = Service('anti-kfc', enable_on_default=False)
The Service class provides decorators such as @sv.on_message, @sv.on_keyword, and @sv.on_notice to bind handler functions. These decorators create a ServiceFunc object and register it with the global trigger registry. When a matching event arrives—whether a keyword in chat or a message recall notice—the service's internal _check_all method executes a series of validation checks before running your handler.
Privilege and Block-List Checks
Before any anti-spam handler executes, the service validates the context through the hoshino.priv module. This system enforces a privilege hierarchy (SUPERUSER, ADMIN, NORMAL) and maintains global block-lists for users and groups.
The _check_all method performs three critical validations:
self.check_enabled(group_id)— Verifies the service is explicitly enabled for the current groupnot priv.check_block_group(group_id)— Confirms the group is not globally blacklistedpriv.check_priv(event, self.use_priv)— Ensures the sender has sufficient privilege to trigger the service
If any check fails, the handler aborts silently. When handlers need to punish offenders, they call priv.set_block_user(user_id, duration) to mute users or priv.set_block_group(group_id) to blacklist entire groups.
How Anti-Spam Modules Are Structured
HoshinoBot organizes all group-management logic under hoshino/modules/groupmaster/. Each anti-spam rule lives in a separate Python file, creating a Service instance and attaching specialized handlers via decorators.
Keyword-Based Filtering
The anti_kfc.py module demonstrates the standard pattern for keyword-based anti-spam. It creates a service disabled by default, then registers a keyword trigger for "疯狂星期四" (Crazy Thursday) spam:
from hoshino import Service, priv, util
sv = Service('anti-kfc', enable_on_default=False)
@sv.on_keyword('kfc', '疯狂星期四')
async def anti_kfc_crazy_thursday(bot, ev):
# Block user for 4 minutes (240 seconds)
priv.set_block_user(ev.user_id, timedelta(seconds=240))
await util.silence(ev, 4 * 60, skip_su=False)
await bot.send(ev, f'{ms.at(ev.user_id)} 检测到关键词,已被禁言4分钟')
try:
await bot.delete_msg(self_id=ev.self_id, message_id=ev.message_id)
except CQHttpError:
pass
This handler demonstrates the complete enforcement chain: block-list registration, timed muting via util.silence, warning message delivery, and offending message deletion.
Notice Event Handling
For non-message events like message recalls, anti_msg_recall.py uses @sv.on_notice to monitor group_recall events. When a user withdraws a message, the bot captures the recall event and reposts the original content to the group, preventing information hiding.
Other modules follow this pattern with specialized triggers:
anti_holo.py— Blocks Hololive-related keywords with immediate 10-minute mutesanti_abuse.py— Implements a word-list filter and provides aban_wordcommand for admins to add forbidden terms dynamicallyanti_lex.py— Combines scheduled jobs (@sv.scheduled_job) with keyword triggers for periodic reminders
The Groupmaster Module Directory
All group-management modules reside in hoshino/modules/groupmaster/, ensuring a unified location for moderation logic:
anti_msg_recall.py— Anti-recall message repostinganti_kfc.py— Scam keyword filteringanti_holo.py— VTuber spam preventionanti_abuse.py— Banned word filtering and red-packet abuse detectionanti_lex.py— Scheduled broadcasts and keyword remindersjoin_approve.py— Automated group join approval workflowssleeping_set.py— Night-mode group restrictions
Each module follows the Service pattern, guaranteeing consistent privilege handling and per-group toggling capabilities.
Execution Flow of an Anti-Spam Rule
When a group message triggers an anti-spam rule, HoshinoBot executes a strict validation pipeline before taking action:
- Service Creation — The module initializes a
Serviceinstance, often withenable_on_default=Falseto require explicit admin activation - Trigger Registration — Decorators like
@sv.on_keywordbind the handler to specific event types in the NoneBot router - Event Reception — NoneBot routes the group message to the appropriate trigger registry (keyword, notice, or command)
- Permission Validation —
Service._check_allvalidates group enablement status, global block-lists, and user privileges in sequence - Handler Execution — Upon passing all checks, the handler executes its logic: calling
priv.set_block_userto update the block-list, invokingutil.silenceto apply timed mutes, sending warning messages, and optionally deleting the offending content viabot.delete_msg
This architecture ensures that adding a new anti-spam rule requires only creating a new module with a Service instance and attaching the appropriate decorator—no changes to core routing or permission logic are necessary.
Practical Implementation Examples
Creating a Custom Keyword Anti-Spam Rule
To add a new spam filter, create a file under hoshino/modules/groupmaster/ following this template:
# my_anti_spam.py
from datetime import timedelta
from hoshino import Service, priv, util
from hoshino.typing import CQEvent, CQHttpError, MessageSegment as ms
sv = Service('anti-spam-custom', enable_on_default=False)
@sv.on_keyword('spamword', 'advertisement')
async def block_spam(bot, ev: CQEvent):
# Apply 5-minute block and mute
priv.set_block_user(ev.user_id, timedelta(minutes=5))
await util.silence(ev, 5 * 60, skip_su=False)
# Notify and clean up
await bot.send(ev, f'{ms.at(ev.user_id)} 广告信息已屏蔽')
try:
await bot.delete_msg(self_id=ev.self_id, message_id=ev.message_id)
except CQHttpError:
pass
The Service wrapper automatically guards this handler with the _check_all logic, ensuring it only runs when enabled for the group and the user isn't already blocked.
Enabling Services Per Group
Administrators toggle modules using the service's set_enable method:
from hoshino import Service, priv
sv = Service('admin-commands', visible=False)
@sv.on_command('enable_filter', aliases=('开启过滤',))
async def enable_filter(session):
from hoshino.modules.groupmaster.my_anti_spam import sv as filter_sv
filter_sv.set_enable(session.ctx['group_id'])
await session.send('已在本群启用自定义过滤规则')
Users with priv.ADMIN or higher can invoke this command to activate specific anti-spam rules for their groups.
Summary
- HoshinoBot's group management relies on the
Serviceclass inhoshino/service.pyto wrap NoneBot handlers with automatic permission and configuration checks - Anti-spam modules reside in
hoshino/modules/groupmaster/and use decorators like@sv.on_keywordand@sv.on_noticeto register triggers - Permission enforcement occurs through
hoshino.priv, providingset_block_user,check_priv, and privilege levels (SUPERUSER,ADMIN,NORMAL) - Enforcement actions typically combine
util.silencefor timed mutes,priv.set_block_userfor block-list updates, andbot.delete_msgfor content removal - Per-group toggling is handled via
Service.set_enable()andService.set_disable(), allowing fine-grained control without code changes
Frequently Asked Questions
How do I enable anti-spam features for specific groups only?
Use enable_on_default=False when creating the Service instance, then provide an admin command that calls sv.set_enable(group_id). Only groups where an administrator explicitly enables the service will process its anti-spam handlers, as the _check_all method validates enablement status before execution.
What privilege levels control group management features?
HoshinoBot implements three privilege tiers in hoshino.priv: SUPERUSER (bot owner), ADMIN (group administrators), and NORMAL (regular users). The Service class checks these via priv.check_priv(event, required_level), and anti-spam handlers typically require ADMIN or higher to modify block-lists or enable services.
Can I customize the mute duration for spam violations?
Yes. When calling priv.set_block_user(user_id, duration), pass a timedelta object specifying the exact blocking period. Additionally, use util.silence(event, seconds) to apply the mute duration—both anti_kfc.py (4 minutes) and anti_holo.py (10 minutes) demonstrate different duration configurations.
How does the anti-recall feature capture deleted messages?
The anti_msg_recall.py module registers a handler via @sv.on_notice listening for group_recall events. When NoneBot detects a message withdrawal, the handler receives the original message ID and content from the event object, allowing the bot to repost the content before it disappears from the group history.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →