Forum teuk.org

πŸ›‘οΈ *Protego Floodum!* β€” Mediabot Gets Smarter Against Channel Floods

in Mediabot Β· started by TeuK Β· 1mo ago

TeuK Β· 1mo ago

Mediabot v3 just received a focused antiflood hardening pass.

The goal was not to rewrite the bot.
The goal was to protect busy channels better β€” especially cases where several users trigger the bot at the same time β€” without touching the database schema.

β€œWhen the whole room starts casting spells at once, one shield per wizard is not enough.” πŸͺ„


🎯 Why this was needed

Mediabot already had antiflood protections, but they were not ideal for a channel-wide burst.

There were two existing mechanisms:

checkAntiFlood()
  protects against too many outgoing bot messages per channel
  uses existing DB-backed CHANNEL_FLOOD settings

checkNickFlood()
  protects against one nick sending too many commands quickly

That helps when one person abuses the bot.

But it does not fully solve this situation:

nick1 -> !seen
nick2 -> !karma
nick3 -> !ai
nick4 -> !q
nick5 -> !date

Each user may stay under the per-nick limit, but the channel still causes the bot to produce too much traffic.

That is exactly the kind of pressure seen on active channels like #quebec.


⚑ AF1 β€” Faster output antiflood

checkAntiFlood() still uses the existing database-backed CHANNEL_FLOOD settings.

No schema change.

But the expensive part was improved: parameters are cached in memory instead of being queried repeatedly on every outgoing bot message.

The DB remains the source of truth for:

nbmsg_max
duration
timetowait

The runtime now keeps hot state in memory and refreshes parameters through a configurable cache TTL.

New config keys:

[antiflood]
OUTPUT_PARAMS_CACHE_TTL=60
OUTPUT_STATE_TTL=300
OUTPUT_PARAMS_STATE_TTL=600

Result: same behavior, much less synchronous DB pressure during bursts.


🚦 AF2 + AF3 β€” Per-nick flood becomes clearer and stronger

The per-nick limiter was improved in two ways.

First, it can now notify the user instead of failing silently.

A nick who sends too many commands can receive a NOTICE such as:

You are sending commands too fast. Please wait a few seconds.

Second, the limiter now uses a sliding timestamp window instead of a fragile fixed window.

That avoids the classic edge case:

4 commands at t=4.9s
4 commands at t=5.1s

A fixed window can let that through.
A sliding window sees the real burst.

New config keys:

[antiflood]
NICKFLOOD_WINDOW=5
NICKFLOOD_MAX_COMMANDS=5
NICKFLOOD_NOTIFY_COOLDOWN=30
NICKFLOOD_STATE_TTL=120

🌊 AF4 β€” New global channel input guard

This is the important part for multi-user floods.

A new channel-wide input guard counts all public commands addressed to the bot on a channel, regardless of which nick sent them.

If a channel crosses the threshold, the bot temporarily silences command handling for that channel.

New config keys:

[antiflood]
CHANFLOOD_WINDOW=10
CHANFLOOD_MAX_COMMANDS=8
CHANFLOOD_SILENCE=30
CHANFLOOD_NOTIFY_COOLDOWN=60

Example logic:

more than 8 bot commands in 10 seconds on the same channel
β†’ silence bot command handling on that channel for 30 seconds

This happens before the per-nick limiter and before expensive command handling.

That makes it much better for coordinated or accidental multi-user bursts.


πŸ”’ Private commands stay protected from channel flood state

One important correction was made during testing:

checkChanFlood() is intentionally public-channel only.

Private commands do not have a channel context and include login/admin workflows. They must not depend on a channel flood state.

So:

mbCommandPublic()
  uses channel-wide guard
  then per-nick guard

mbCommandPrivate()
  does not use channel-wide guard

This avoids breaking private login, admin, and Partyline-adjacent workflows.


πŸ“Š Metrics and Partyline visibility

The antiflood work also exposes better visibility.

Metrics added or covered:

mediabot_antiflood_blocks_total
mediabot_nickflood_blocks_total
mediabot_chanflood_blocks_total

Partyline gets .floodstatus, which can show:

output antiflood state
channel input flood state
per-nick flood state

This makes it much easier to understand what is happening while the bot is under pressure.


πŸ§ͺ Tests added

Five static tests were added to lock this down:

334_antiflood_configurable_thresholds.t
335_antiflood_chanflood_public_only.t
336_antiflood_nickflood_sliding_notice.t
337_antiflood_output_cache_and_metrics.t
338_antiflood_partyline_floodstatus.t

They verify:

configurable thresholds
public-only channel guard
private commands not depending on channel context
sliding per-nick window
notice cooldown
output antiflood parameter cache
metrics declarations
Partyline .floodstatus coverage

The test suite is now protecting the intended design instead of merely trusting the patch.


🧬 No database schema change

This was deliberate.

The current pass does not add new tables and does not alter existing schema.

The existing DB-backed CHANNEL_FLOOD table remains in place for output flood settings.

The new channel and per-nick input guards are memory-backed and configured through mediabot.conf.

That keeps the change safe for existing production databases.


βœ… Result

Mediabot now has a stronger antiflood stack:

AF1: faster outgoing channel antiflood with cached DB parameters
AF2: user notice when per-nick flood is triggered
AF3: sliding-window per-nick limiter
AF4: global channel input limiter for multi-user bursts

For busy channels, this is a major practical improvement.

It protects the bot before expensive commands run, keeps private workflows safe, adds visibility through Partyline/metrics, and avoids unnecessary database changes.


πŸͺ„ Spell of the day

Protego Floodum!

The bot now raises a better shield when the whole channel starts casting at once.

Mischief managed β€” and #quebec gets a much stronger umbrella. β˜”πŸͺ„

You must be logged in to reply.