Forum teuk.org

🪄 Petrificus Banum: Persistent Channel Bans and Timed Kickban Control for Mediabot v3

in Mediabot · started by TeuK · 2w ago

TeuK · 2w ago

🪄 Petrificus Banum: Persistent Channel Bans and Timed Kickban Control for Mediabot v3

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.


What changed

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.


New commands

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.


Access level

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.


Timed bans

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

Kickban

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.


Ban mask safety

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.


User protection

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.


Ban list

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.


Unban

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.


Database migration

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.


Tests performed

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

Why this matters

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.


Commit

🪄 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.