After the previous polish rounds, I thought Mediabot v3 was ready to fly quietly across the castle.
Then Fawkes landed on the desk, dropped a few smoking feathers, and reminded me that a good bot is never really “finished” — it is only one careful bugfix pass away from being safer, cleaner, and less cursed.
This update is different from the previous forum post.
The last one was mostly about making commands nicer, outputs clearer, and Partyline diagnostics more pleasant to use.
This one is a real bugfix pass.
No big new subsystem.
No database schema change.
No dramatic rewrite with a wand held sideways.
Just a careful hunt through the corridors for small regressions, dead code, bad dispatch paths, wrong counters, broken cache behavior, and tiny IRC edge cases that could become annoying later.
In short:
Less decoration.
More repair.
Fewer cursed goblets.
This pass focused on practical bugfixes across Mediabot v3:
!ai pin clear behavior;That is a lot, but the theme is simple:
Make existing features behave exactly as they claim to behave.
The Partyline command dispatcher had a few duplicated or shadowed routes.
Some commands technically existed, but were never reached because an earlier broader elsif had already captured the line.
That is a classic “moving staircase” problem: the door is there, but the castle keeps sending you somewhere else.
This was cleaned up for commands such as:
.top
.remind
.seen
.who
.aistats
The result is a cleaner dispatch flow:
Partyline command routing is now less like the Department of Mysteries and more like a proper command hall.
!compare: no more double leadA regression made !compare repeat the lead amount:
teuk leads by 53 msg(s) by 53 msg(s)
That was not dangerous, but it looked ridiculous.
The code already had the final verdict prepared, then another block appended the difference again.
Fixed output:
teuk: 142 msg(s) (61%) | Gwen: 89 msg(s) (39%) | teuk leads by 53 msg(s)
Clean. Direct. No echo charm.
!pollresult: winner label fixed!pollresult could display the option index instead of the option label:
Winner: 0 (62%)
That is technically true from the code’s point of view, but utterly useless for humans.
The fix resolves the winner through the poll options array:
Winner: Perl (62%)
Much better. The Sorting Hat should announce the house name, not the array index.
!ai pin clear: dead code removedThe !ai pin clear command had a nasty little trap.
Instead of clearing the pinned AI context, it could pin the literal word:
clear
because the pin handler consumed the command too early, and the later pin clear block was unreachable.
That is exactly the kind of bug that makes an AI feature feel haunted.
The command now behaves correctly:
!ai pin clear
clears the pinned context instead of creating a very philosophical prompt containing only “clear”.
The IRC-side AI quota command used a wrong key separator.
One path used a real NUL byte:
"\x00"
Another path used the literal four-character string:
'\x00'
In Perl, those are not the same spell.
Result: !ai quota could think the window had not started, even after AI usage.
That was fixed so the quota lookup uses the same key format as the rate limiter itself.
No more vanishing quota window.
!yt search had incorrect duration formatting for ISO 8601 durations.
Example:
PT3M45S
could become something wrong like:
3:45:0
The problem came from grouped regex captures in list context. If the hour part was missing, the capture list shifted.
The fix reads hours, minutes, and seconds independently.
Result:
3:45
instead of a malformed time string.
Tiny bug. Very visible output.
There were comments saying the cache should be stored, but no actual cache write.
That meant Instagram and Facebook links could relaunch Chromium repeatedly, even when the same URL was posted again shortly after.
That is not ideal.
The handlers now use dedicated caches with a 10-minute TTL, similar in spirit to the other URL caches.
So repeated links can avoid unnecessary browser work.
Fewer Chromium summons. Fewer smoking cauldrons.
The internal HTTP helper _make_http ignored the caller’s verify_SSL option.
So code could explicitly request SSL verification and still get a client with verification disabled.
That is not a polish issue. That is a real correctness issue.
Now _make_http respects the caller:
verify_SSL => 1
means SSL verification is enabled.
For callers that do not request it, the legacy behavior remains unchanged.
A defensive spell should do what the caster actually asked.
!status: memory reporting fixed!status could display:
Memory usage (VM ?MB) (Resident ?MB) (Shared ?MB) (Data+Stack ?MB)
The previous parsing expected a structure that did not match what was actually returned.
The fix reads /proc/self/status directly on Debian/Linux systems and extracts:
VmSize;VmRSS;RssFile;VmData;VmStk.Now the memory section is useful again.
No more question-mark divination.
!whotalk: pagination output repaired!whotalk had a display bug where paginated output could turn into:
whotalk[01]: : : : :
The command already had strings like:
teuk(42)
Gwen(15)
but the pagination code treated them like array references.
That produced empty fields.
The fix simply outputs the prepared strings as strings.
No transfiguration required.
botNotice: CR/LF sanitizing fixedbotNotice did not clean carriage returns consistently.
Some clients can behave badly when a raw \r slips through.
The function now sanitizes like botPrivmsg:
s/[\r\n]+/ /g
That keeps NOTICE output cleaner and avoids weird client-side truncation or display problems.
Small fix, important hygiene.
Several commands were improved or fixed around page numbering.
Instead of showing only:
countcmd[01]:
chanlist[01]:
timer[01]:
owncmd[01]:
the bot now reports total pages where appropriate:
countcmd[01/04]:
chanlist[01/03]:
timer[01/05]:
owncmd[01/04]:
This was also applied to related outputs such as:
checknick
checkhost
nicklist
checkhostchan
whoami masks
Pagination without the total page count is like a Marauder’s Map with no edges.
Useful, but incomplete.
The !bans output could say:
Showing 10/10 active bans
even when more bans existed.
Why? The array had already been sliced down to 10 before the message was built.
The fix keeps track of the fetched total before slicing and reports clearly when more entries exist.
Now the output does not pretend the first ten bans are the whole dungeon.
!tmdblangset still called the old getIdChannel() helper, which produced deprecation logs.
The code now resolves the channel through the in-memory channel object:
$self->{channels}{$target_channel}->get_id
That keeps the function aligned with the current object-oriented channel handling.
One less ghost from the old castle wing.
!hailo_chatter always reported failure even when the database update succeeded.
The reason was a classic Perl truthiness trap:
0
can mean success, but it is false.
The function expected truthiness instead of definedness.
The fix checks:
defined $ret
so a successful 0 return is handled correctly.
Perl remains Perl. We respect the old magic, but we verify the spellbook twice.
.quota: sorted output.quota now sorts entries by nick/channel instead of hash key order.
Before, output order could feel random.
Now it is predictable:
nick ASC, channel ASC
That makes Partyline diagnostics easier to read when several users have active AI quota windows.
.ai statusThe .ai status block had blank-line artifacts from previous edits.
No behavior change, just cleaner code.
Not every fix needs fireworks. Sometimes the broom does the work.
This pass remains application-level.
No schema migration.
No new table.
No new column.
Everything here is bugfixing and cleanup:
That makes the change safer to deploy.
IRC:
m compare teuk Gwen
m pollresult
m triviatop
m countcmd
m ai pin test
m ai pin clear
m ai quota
m yt search never gonna give you up
m weather Paris
m status
m whotalk #boulets
m chanlist
m bans
m tmdblangset #boulets fr-FR
m hailo_chatter #boulets 30
m timers
m owncmd
m modcmd kk message boulets hello
m checknick teuk
m checkhost teuk.org
m nicklist #boulets
m whoami
Partyline:
.top
.top 10
.top #boulets
.remind teuk test
.seen teuk
.who teuk
.who #boulets
.aistats
.quota
Shell:
perl -I. -c Mediabot/Partyline.pm
perl -I. -c Mediabot/UserCommands.pm
perl -I. -c Mediabot/DBCommands.pm
perl -I. -c Mediabot/External.pm
perl -I. -c Mediabot/AdminCommands.pm
perl -I. -c Mediabot/Helpers.pm
perl -I. -c Mediabot/ChannelCommands.pm
perl -I. -c Mediabot/Hailo.pm
perl -I. -c Mediabot/LoginCommands.pm
LC_ALL=C grep -P '\x00' -n Mediabot/Partyline.pm || true
git diff --check
This was not another “make it prettier” pass.
This was a Fawkes bugfix pass.
The bot came out cleaner in several important places:
!ai pin clear really clears;A phoenix pass, basically.
Some feathers burned.
The bot got better.
Suggested commit spell:
🐦🔥 Fawkes: fix dispatch, quota, cache, pagination, and IRC output regressions
Alternative:
🧯 Incendio Reverso: repair cursed regressions across Partyline and IRC commands
You must be logged in to reply.