This Mediabot v3 pass was a serious hardening round.
It started with concrete runtime bugs around Partyline AI commands and karma handling, then grew into a wider defensive audit across the codebase:
netsplit handling
database prepare/execute guards
Partyline AI subcommands
explicit karma voting
External URL handlers
antiflood edge cases
daily report karma sorting
reminders, trivia, choose, timezone, bans
The overall goal was not to add shiny features.
The goal was to make Mediabot harder to crash, less noisy during network events, and safer during real IRC operations.
The IRC side now behaves better during netsplits.
QUIT messages matching netsplit patterns such as:
*.net *.split
are now treated as infrastructure events.
For these QUITs, the bot updates in-memory nicklist state but skips expensive or misleading database operations such as:
logBotAction
updateUserSeen
auth logout
That avoids polluting logs and user state during a network split.
A Prometheus counter was also added:
mediabot_netsplit_quits_total
On reconnect, in-memory transient states are cleared:
_af
_chan_flood
_nick_flood
_nick_mute
_cmd_cooldown
That prevents stale flood/mute/cooldown state from surviving a reconnect and incorrectly silencing channels or users.
After login, channel JOINs are spaced out instead of being blasted at once.
A delayed WHO #channel is also sent after JOIN to resync nicklists.
That is especially useful after netsplits, reconnects, or large channel lists.
Claude history cleanup now happens on real QUITs, not netsplit QUITs.
That prevents valid context from being thrown away just because the IRC network split temporarily.
The old automatic karma scanner watched every public message for patterns like:
nick++
nick--
That was too dangerous.
Normal text such as:
Notepad++
C++
could create bogus karma entries.
The automatic scan is now disabled.
Karma changes must be explicit:
m karma + boole
m karma - boole
m karma ++ boole
m karma -- boole
Showing karma is unchanged:
m karma boole
The command also verifies that the target nick is present on the channel before modifying karma.
This is a much better tradeoff: fewer surprises, no accidental karma from software names, and cleaner daily reports.
Daily reports now sort karma by absolute score:
ORDER BY ABS(score) DESC
instead of only showing positive scores first.
That means negative karma can appear when it is one of the strongest signals, which makes the report more honest.
The Partyline .ai command now properly intercepts its subcommands.
Previously, commands such as:
.ai quota
could be sent to Claude as a normal prompt.
That produced nonsense like Claude asking what kind of quota was meant.
Now known subcommands are handled as Partyline commands:
.ai quota
.ai stats
.ai models
.ai history
.ai reset
.ai forget
.ai pin
.ai pin clear
.ai summary [n]
Normal prompts still work:
.ai explain netsplits in one sentence
.ai forget fixed.ai forget now clears the correct Partyline AI scope.
It no longer uses a hardcoded partyline key when the active scope is based on the resolved nick/channel context.
.ai summary fixed.ai summary now uses the real CHANNEL_LOG schema:
publictext
id_channel_log
It also handles Unicode safely when the prompt cache hashes text from IRC logs.
The fix encodes prompt text before passing it to Digest::MD5:
encode('UTF-8', lc($prompt // ''))
No more Wide character in subroutine entry from Unicode log summaries.
displayUrlTitle() now wraps URL handlers in eval.
That means a failure in a specific handler, such as Instagram, Spotify, YouTube, Facebook, or other media extraction, should not bubble up and crash the message handler.
The X/Twitter Chromium fallback was also wrapped more tightly around the risky external process call.
Result: network/parser/process failures should degrade gracefully instead of destabilizing normal IRC message processing.
A major part of this pass was defensive DB cleanup.
Across the codebase, many places used this unsafe pattern:
unless ($sth->execute(...)) {
If prepare() failed, $sth was undef, and the bot could crash with:
Can't call method "execute" on undef
The safer pattern is:
unless ($sth && $sth->execute(...)) {
This was applied across many modules, including:
UserCommands.pm
Helpers.pm
ChannelCommands.pm
Partyline.pm
DBCommands.pm
Quotes.pm
Hailo.pm
ChannelBan.pm
Mediabot.pm
This does not make the database magically healthy, but it makes failures controlled.
The bot should report or skip cleanly instead of exploding in the dispatcher.
Several smaller bugs were fixed along the way:
mbRemindList_ctx now strips [at:TS] before detecting [!].
That means delayed urgent reminders are correctly shown as urgent.
mbTriviaStop_ctx now resets more state so the next trivia game does not inherit stale scores or hint flags.
mbChoose_ctx now handles edge cases after deduplication more cleanly, including the case where only one option remains.
mbKarmaGraph_ctx now avoids warnings when older karma log entries have missing delta values or future timestamps.
Timezone update/delete helpers now guard failed prepare() calls.
Reminder delivery now checks the result of its delivery-state update instead of silently ignoring failed updates.
The channel flood guard now clamps invalid runtime values more safely.
A dangerous case such as:
.floodset #chan 0 ...
could previously leave window=0, which risks divide-by-zero or broken rate calculations.
The value is now clamped.
Warn-only mode logging was also corrected: logs no longer say the bot is silencing a channel when it is only warning.
A long-standing typo was fixed in UserCommands.pm:
$DBI::errstrstr
became:
$DBI::errstr
This appeared many times and could make database error reporting misleading or broken.
Before committing, the critical compile checks should pass:
perl -c mediabot.pl
perl -I. -c Mediabot/UserCommands.pm
perl -I. -c Mediabot/Helpers.pm
perl -I. -c Mediabot/ChannelCommands.pm
perl -I. -c Mediabot/DBCommands.pm
perl -I. -c Mediabot/Quotes.pm
perl -I. -c Mediabot/Hailo.pm
perl -I. -c Mediabot/ChannelBan.pm
perl -I. -c Mediabot/External.pm
perl -I. -c Mediabot/Partyline.pm
Runtime checks included Partyline AI behavior, .ai summary, .karma, and foreground startup.
This pass strengthens Mediabot v3 where it matters most:
netsplit events are less destructive
reconnects reset stale runtime flood state
JOINs are paced
WHO resync happens after JOIN
Claude history survives netsplits
karma is explicit and less error-prone
daily reports are more accurate
Partyline AI subcommands behave correctly
URL handlers are isolated with eval
DB prepare/execute paths are more defensive
reminders/trivia/choose/karma graph edge cases are fixed
No schema change.
Protego Maxima!
Less crashy.
Less noisy.
Less likely to punish someone for saying Notepad++.
Mischief hardened. π‘οΈπ§ββοΈ
You must be logged in to reply.