Some Mediabot updates arrive with new toys.
This one is different.
This is the kind of pass that does not try to impress the room immediately. It sharpens the knife, oils the hinges, checks the hidden staircases, and makes sure the old spell still points to the right wand.
It fixes real bugs:
a schema parser confused by comments
fresh achievements that could be lost during shutdown
duel streaks that could never properly trigger Underdog
a historical !top command shadowed by a newer alias
No database schema change. No migration drama. Just cleaner behavior, safer tooling, and fewer cursed corners.
Welcome to the Wolfhound Audit pass.
Because this update is not flashy.
It is loyal.
It guards the doorway.
It notices the weird sound in the wall before the wall starts moving.
Mediabot has recently gained social features, achievements, games, leaderboards, timelines and richer channel awareness. That is great. But once the castle gets larger, you need better patrols.
This pass is one of those patrols.
The schema drift checker had already been improved to stop producing cursed SQL like:
ALTER TABLE `KARMA_LOG` ADD COLUMN `COMMENT` 'Vote timestamp';
That bug came from parsing SQL too naively.
This pass goes further.
The parser now handles another subtle case:
`id` INT, -- comment with, commas, inside
`name` VARCHAR(64)
And also:
`id` INT, # MySQL-style comment with, commas, inside
`name` VARCHAR(64)
That matters because comments can contain commas, and a parser that splits blindly on commas will eventually invent nonsense.
The drift checker now understands more of the real SQL shape:
multi-line column definitions
COMMENT attributes
ENUM(...) values
quoted strings
backticked identifiers
inline -- comments
inline # comments
top-level commas only
The map is still a tool, not a full SQL engine. But it is much harder to trick now.
The checker also learned to pay attention to CHANSET_LIST.
That table is not ordinary user data.
It defines runtime features:
AchievementAnnounce
Games
UrlTitle
Youtube
Claude
RandomQuote
So when the schema says a chanset exists but the live DB does not have the row, that is a real drift.
The checker can now detect missing reference rows and generate safe idempotent SQL such as:
INSERT INTO `CHANSET_LIST` (`id_chanset_list`, `chanset`)
SELECT 16, 'Games'
WHERE NOT EXISTS (
SELECT 1 FROM `CHANSET_LIST` WHERE `chanset` = 'Games'
);
That is exactly the kind of output we want:
reviewable
safe to rerun
non-destructive
clear
And if the whole CHANSET_LIST table is missing, the checker no longer screams about every missing seed row. It reports the missing table and stops there.
Less noise. Better signal.
Achievements are persisted to JSON.
That is clean and avoids a schema change.
But there was a subtle shutdown risk.
Achievements are saved with a debounce so the bot does not write too often. That is usually fine.
But if an achievement unlock happened near shutdown, the latest unlock could exist only in memory and not yet on disk.
This pass adds a forced flush during clean_and_exit():
$self->{achievements}->save(1);
It happens before DB disconnection and is protected by eval, so shutdown remains safe.
Small fix. Big peace of mind.
Nobody wants to earn a rare badge and have it vanish like a badly handled Portkey.
The duel system had a logic bug in streak tracking.
The idea was simple:
lose several duels in a row
then win
unlock Underdog
But the old streak logic did not properly reset winners and losers when the direction changed.
A player with a winning streak who lost would not become -1 loss streak cleanly.
That broke the logic behind the Underdog achievement.
The new logic is clearer:
winner:
if previous result was win, increment positive streak
otherwise reset to +1
loser:
if previous result was loss, decrement negative streak
otherwise reset to -1
The underdog check is evaluated before overwriting the previous streak.
That means the expected scenario now works:
A loses 5 times
A wins next duel
A qualifies as underdog
That is fair. And more importantly, it is finally trackable.
!top: the old spell is restoredA subtle regression was found before commit.
The new leaderboard feature had added top as an alias.
But Mediabot already had a historical !top command.
In a Perl hash, duplicate keys do not coexist politely.
The last one wins.
So the newer alias could shadow the old command.
That is not acceptable.
This pass preserves the old behavior:
!top -> historical top command
!leaderboard -> new leaderboard
!lb -> new leaderboard
That is the right compromise.
New magic should not steal an old wand.
A new test file was added:
t/cases/382_check_schema_drift_parser.t
It covers the important parser cases:
multi-line COMMENT attributes
inline -- comments with commas
inline # comments with commas
-- inside strings
# inside strings
ENUM values
nested parentheses
reserved keyword guards
table constraints
That is valuable because this bug class is sneaky.
Without tests, it comes back.
With tests, the next person who breaks it gets caught by the gargoyle at the door.
This is worth repeating:
No database schema change.
No destructive migration.
No DROP.
No table rewrite.
This pass improves code and tooling only.
The existing database stays where it is.
That is exactly the kind of update you want after a larger feature series.
Syntax checks:
perl -I. -c Mediabot/Mediabot.pm
perl -I. -c Mediabot/UserCommands.pm
perl -I. -c Mediabot/Achievements.pm
perl -I. -c Mediabot/Helpers.pm
perl -I. -c Mediabot/Metrics.pm
perl -I. -c mediabot.pl
perl -c tools/check_schema_drift.pl
perl -c t/cases/382_check_schema_drift_parser.t
git diff --check
Runtime checks:
!top
!leaderboard
!lb
!chronos
!achievements
!duel SomeNick
Expected behavior:
!top keeps the old behavior
!leaderboard and !lb use the new leaderboard
!chronos still works
duel streaks update correctly
achievements are still saved
Drift checker check:
tools/check_schema_drift.pl --conf=mediabot.conf --generate-migration
Expected improvement:
no fake ADD COLUMN COMMENT
inline comments do not corrupt parsing
missing CHANSET_LIST rows are detected
missing CHANSET_LIST table does not produce noisy seed spam
This update is quiet, but important.
It does not add a spectacular command.
It makes existing things safer.
It protects old behavior. It preserves earned achievements. It makes duels fairer. It teaches the drift checker not to hallucinate SQL. It adds tests around the exact place where the parchment used to be cursed.
That is good engineering.
Not the fireworks kind.
The kind that lets the fireworks happen later without burning down the tower.
🐺🪶🧭
You must be logged in to reply.