Forum teuk.org

🐦‍🔥 Mediabot v3: Fawkes Bugfix Pass — Dispatch, Quotas, Caches, and IRC Edge Cases

in Mediabot · started by TeuK · yesterday

TeuK · yesterday

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.

🧯 What this pass was about

This pass focused on practical bugfixes across Mediabot v3:

  • Partyline dispatch cleanup;
  • duplicate or unreachable command handlers;
  • command output bugs;
  • broken winner/label display;
  • bad pagination counters;
  • AI quota key mismatch;
  • !ai pin clear behavior;
  • YouTube duration parsing;
  • Instagram/Facebook cache behavior;
  • SSL verification handling;
  • memory reporting;
  • NOTICE sanitizing;
  • channel ban display;
  • deprecated channel lookup usage;
  • Hailo return-value handling.

That is a lot, but the theme is simple:

Make existing features behave exactly as they claim to behave.

🧙 Partyline dispatch: removing cursed duplicates

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:

  • fewer duplicate branches;
  • fewer unreachable handlers;
  • metrics attached consistently;
  • one source of truth for AI stats.

Partyline command routing is now less like the Department of Mysteries and more like a proper command hall.


⚖️ !compare: no more double lead

A 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 removed

The !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”.


🧮 AI quota key fixed

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.


🎥 YouTube duration parsing fixed

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


📸 Instagram and Facebook cache actually implemented

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.


🔐 HTTP SSL behavior fixed

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 fixed

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


📚 Pagination counters made consistent

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.


🚫 Channel bans: better “showing” message

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.


🎬 TMDB language command: deprecated lookup removed

!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 return value fixed

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


🧭 Partyline .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.


🧹 Small cleanup: .ai status

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


🛡 No database schema change

This pass remains application-level.

No schema migration.
No new table.
No new column.

Everything here is bugfixing and cleanup:

  • dispatch logic;
  • display formatting;
  • cache behavior;
  • SSL options;
  • runtime diagnostics;
  • pagination;
  • source hygiene.

That makes the change safer to deploy.


🧪 Suggested regression tests

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

🏁 Final status

This was not another “make it prettier” pass.

This was a Fawkes bugfix pass.

The bot came out cleaner in several important places:

  • Partyline dispatch is less duplicated;
  • AI quota works against the right key;
  • !ai pin clear really clears;
  • poll winner labels are correct;
  • YouTube durations are sane;
  • SSL verification options are respected;
  • status memory output works;
  • NOTICE output is cleaner;
  • pagination is more accurate;
  • old deprecated channel lookup was removed;
  • Hailo chatter reporting now respects the real return value.

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.