Mediabot v3 now has a real persistent channel ban system.
Until now, the bot could kick users from IRC channels when it had operator privileges. That worked, but it had an obvious limitation: a kicked user could simply come back if no ban was set.
This update adds the missing piece: ban, kickban, unban, banlist, ban levels, timed bans, automatic expiration, and database persistence.
It brings Mediabot closer to the classic IRC bot behavior expected from systems like Eggdrop, while keeping Mediabot’s own user/channel permission model.
A new persistent ban layer has been added around a new database table:
CHANNEL_BAN
This table stores active and historical bans with:
channel
mask
ban level
reason
author
creation date
expiration date
active/inactive state
removal information
source
This means Mediabot can now remember bans, list them, expire them automatically, and keep a history after they are removed.
The new public IRC commands are:
bans [#channel]
ban [#channel] <nick|mask> [duration] [level] [reason]
kickban [#channel] <nick|mask> [duration] [level] [reason]
kb [#channel] <nick|mask> [duration] [level] [reason]
unban [#channel] <id|mask>
The short alias:
kb
is available for kickban.
Ban commands follow an Undernet-inspired model.
The minimum channel level required to use ban commands is:
75
The default ban level is the channel level of the user placing the ban, with a minimum of 75.
For example:
ban #test *!*baduser@example.org 10m
If the user placing the ban has channel level 100, the ban is stored with level 100 by default.
A manual level can also be provided:
ban #test *!*baduser@example.org 10m 75 reason here
But a user cannot set a ban level higher than their own channel level.
Mediabot now supports temporary bans.
Examples:
ban #test *!*baduser@example.org 10m test ban
ban #test *!*baduser@example.org 2h test ban
ban #test *!*baduser@example.org 3d test ban
ban #test *!*baduser@example.org 1w test ban
Accepted duration formats include:
10m
2h
3d
1w
permanent
0
If a ban has an expiration date, Mediabot automatically removes it when it expires.
The expiration process:
detect expired active ban
send MODE #channel -b mask
mark the ban inactive in CHANNEL_BAN
store removed_by_nick = system
store remove_reason = expired
The new kickban command does both operations:
MODE #channel +b mask
KICK #channel nick :reason
Example:
kickban #test SomeNick 10m 75 test kickban
If a nick is provided, Mediabot tries to resolve the latest known hostmask from channel logs.
If a mask is provided instead of a nick, Mediabot can set the ban, but it will not kick a specific user because there is no exact nick to kick.
The new system refuses dangerous masks.
For example, masks like these are rejected:
*!*@*
*!*@*.*
*!
*
This is important because allowing broad masks at a high level could accidentally lock out far too many users.
Mediabot requires a proper nick/user/host style ban mask with useful fixed host material.
Mediabot also protects users by level.
If the target user is known in the Mediabot database and has a channel level greater than or equal to the user trying to ban them, the ban is refused.
In plain terms:
you cannot ban someone with an equal or higher channel level
This prevents lower-level channel operators from using the bot against higher-level users.
The bans command lists active bans on a channel.
Example:
bans #test
Typical output includes:
#12 *!*baduser@example.org level=75 by=teuk expires=2026-05-02 01:42:00 reason=test ban
This gives quick visibility into what Mediabot currently considers active.
Bans can be removed either by ID or by mask:
unban #test 12
unban #test *!*baduser@example.org
When a ban is removed manually, Mediabot:
sends MODE #channel -b mask
marks the ban inactive
stores removed_by / removed_by_nick
stores remove_reason = manual unban
The ban history remains in the database.
A new migration file was added:
install/migrations/20260502_channel_ban.sql
The migration creates the CHANNEL_BAN table with indexes and foreign keys to the existing CHANNEL and USER tables.
The recommended import method is to open the MariaDB client with an explicit charset, then use SOURCE:
mysql --default-character-set=utf8mb4 -u root mediabotv3
Then inside MariaDB:
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
SET CHARACTER SET utf8mb4;
SOURCE /home/mediabot/mediabot_v3/install/migrations/20260502_channel_ban.sql;
This avoids relying on shell redirection and keeps charset handling explicit.
The feature was validated with:
Perl syntax checks
database table checks
foreign key checks
module smoke tests
ban mask validation tests
database insert rollback test
real IRC command tests
manual unban test
temporary ban expiration test
kickban test
The real flow was tested successfully:
ban -> MODE +b -> DB active=1
bans -> active ban listed
unban -> MODE -b -> DB active=0
temporary ban -> automatic expiration -> MODE -b -> DB active=0 remove_reason=expired
kickban -> MODE +b + KICK
This is a major step for Mediabot v3.
A bot that can only kick is useful, but limited. A bot that can manage persistent bans, timed bans, levels, expiration, and history becomes a real channel administration tool.
This update adds:
persistent channel bans
timed ban expiration
kickban support
ban level enforcement
safer mask validation
ban history
manual and automatic unban
It also keeps the implementation aligned with Mediabot’s existing channel/user model.
🪄 Petrificus Banum: add persistent channel bans and timed kickban control
Mediabot v3 now has the missing piece between moderation and real channel control.
You must be logged in to reply.