Forum teuk.org

🪶 Mediabot v3: The Grand Polish

in Mediabot · started by TeuK · 2d ago

TeuK · 2d ago

This one was not about adding a giant new subsystem.
It was not about changing the database schema.
It was not about summoning a dragon and hoping it would behave.

This was the quiet but important kind of work: making existing commands sharper, outputs clearer, diagnostics more useful, and the whole bot nicer to operate on real IRC channels.

In Hogwarts terms, this was not a flashy tournament spell.

It was more like walking through the castle at night with a lantern, checking every corridor, tightening every enchanted hinge, silencing noisy portraits, and making sure Peeves did not hide a regression in the plumbing.

And honestly, that kind of work matters.


🧭 The goal of this pass

The rule was simple:

Improve existing behavior.
Fix small bugs.
Polish command output.
Do not touch the database schema.
Prepare a clean commit.

Mediabot v3 already has a lot of history behind it. It is not a toy bot freshly written last weekend. It has old features, new modules, IRC-specific behavior, AI integration, Partyline tooling, radio commands, statistics, karma, quotes, reminders, and a lot of small features that people actually use.

So this pass focused on making the bot feel more coherent.

Not more complicated.

Just better.


🧙 Cleaner command diagnostics

Several command paths now produce more useful debug information.

SQL command dispatch

The old debug message was generic:

Check SQL command : kk

It worked, but it lacked context.

Now the dispatch log is more useful:

mbDbCommand: !kk on #boulets by teuk

That gives the command, the channel, and the caller in one line.

Much better when reading logs after something strange happened on IRC.

Private command dispatch

Private commands also got cleaner DEBUG3 logging:

mbCommandPrivate: !ai from teuk

The special q command remains quiet, because logging someone leaving a session is not exactly the most thrilling prophecy in the tower.

Cooldown blocks

When a command is blocked by cooldown, the logs now say so clearly:

checkCmdCooldown() blocking !ai on #boulets — 8s remaining

That is the kind of detail you want when diagnosing “why did the bot not answer?”


🧠 Claude / AI visibility

The Claude integration keeps getting more mature.

AI quota consistency

Both IRC-side !ai quota and Partyline .quota now respect the configured values:

anthropic.RATE_MAX
anthropic.RATE_WINDOW

No more hardcoded “5 requests / 60 seconds” in one place while another part of the bot reads the configuration.

That sort of inconsistency is how cursed objects are born.

Human-readable quota reset

Partyline quota output now includes both the relative wait time and the reset clock time:

teuk  #boulets  3/5 req (1m 33s left, resets 11:42)

That is much more useful than raw seconds. Humans should not need to perform arithmetic just to know when the cauldron is ready again.

.ai status

A new Partyline AI status command gives a compact overview:

Claude: 3 session(s) (~2.4k chars), 2 pinned, 1 persona(s).

This is excellent operational visibility. It tells you how much AI context is alive in memory without digging through internal structures.

.ai history

AI history output now includes exchanges and approximate character count:

6 message(s) in context (3 exchange(s), ~840 chars):

This makes it easier to understand how much context the bot is carrying.


📊 Better statistics commands

A lot of this polish pass improved existing statistics commands.

!stats: channel rank

The !stats output now includes the user’s rank on the channel:

teuk: 342 msg(s) (8.7%) on #boulets | rank: #12 | first seen: ...

That small rank: #12 makes the output immediately more meaningful.

!active: activity counts

Before:

Active in last 24h on #boulets: teuk, Gwen, bot42 (3 nick(s))

After:

Active in last 24h on #boulets: teuk(142), Gwen(89), bot42(12) (3 nick(s))

This is far better. It shows both who was active and how active they were.

!when: total message count

The !when command now includes the total number of messages:

teuk first seen on #boulets: 2024-03-15 14:22:07 (1y 2m ago), 1204 msg(s)

That turns a historical lookup into a useful summary.

!last: exact time

Before:

teuk last said (3h 15m ago on #boulets): "bonjour tout le monde"

After:

teuk last said (3h 15m ago, 14:23 on #boulets): "bonjour tout le monde"

That exact time is a small detail, but it makes the command much more pleasant.

!compare: absolute lead

Before:

teuk: 142 msg(s) (61%) | Gwen: 89 msg(s) (39%) | teuk leads

After:

teuk: 142 msg(s) (61%) | Gwen: 89 msg(s) (39%) | teuk leads by 53 msg(s)

No ambiguity. No mental subtraction. Just the answer.


🪙 Karma polish

The karma system also received several small but useful improvements.

!karmadiff: current score included

Before:

teuk: karma changed by +3 in the last 24h (7 vote(s)).

After:

teuk: karma changed by +3 in the last 24h (7 vote(s), score: +42).

This gives both the movement and the current state.

!karmahist: summary in the header

Before:

teuk: recent karma changes on #boulets:

After:

teuk: recent karma changes on #boulets (+5/-2):

The header now immediately tells whether the recent karma movement was mostly positive or negative.

!karmainfo: log period

The command now shows the memory window covered by the in-memory karma log:

karmainfo teuk [score: +42] (last 7d in log): ...

That is honest and useful. It tells the user the scope of the displayed data instead of pretending the in-memory buffer is eternal.


🗳 Polls, trivia, notes, and small command quality

Several smaller commands were cleaned up too.

!pollresult: winner in the header

Poll results now show the winner immediately:

open poll: "Best language?" (8 vote(s))  Winner: Perl (62%):

The full detail is still shown below, but the answer is visible right away.

!triviatop: percentages

Trivia top results now include percentages:

Trivia hall of fame: #1. teuk: 7 (58%)  #2. Gwen: 4 (33%)

That makes the hall of fame easier to read at a glance.

!note search: result ratio

Before:

2 note(s) matching 'doctor':

After:

2/5 note(s) matching 'doctor':

It now shows how many results matched out of the user’s total notes.

!abbrev: source word count

Before:

teuk: RATM

After:

teuk: RATM (4 word(s))

Tiny improvement. Nice output.


📚 Command management polish

Custom commands are one of Mediabot’s oldest and most useful features, so they got some attention too.

!modcmd: show previous value

Before:

Modifying command kk [message] karma++ %N

After:

Modifying command kk [message] (was: PRIVMSG %c karma++ %N)

That is much safer. When changing a command, seeing the old action helps avoid accidental edits.

!countcmd: page count

Before:

countcmd[01]: addcmd remcmd ...

After:

countcmd[01/04]: addcmd remcmd ...

Much better when the result spans multiple pages.

!owncmd: percentage by author

Before:

teuk(42)  Gwen(15)  bot(8)

After:

teuk(42,64%)  Gwen(15,23%)  bot(8,12%)

This gives a clearer view of who owns how much command content.

!calclast: result count in header

Before:

Last calc(s):

After:

Last 3 calc(s):

Small, clear, useful.


⏱ Timers and cooldowns

Time formatting was made more consistent.

!timers

Before:

myTimer - every 3600s - !karma

After:

myTimer - every 1h00m - !karma

!addtimer

Before:

Timer mytimer added

After:

Timer mytimer added (every 1h00m): PRIVMSG #boulets !karma

The bot now confirms not only that the timer was created, but also the interval and command. That is much safer.

.schedule list

Partyline schedule output also uses human-readable intervals:

claude_history_purge  1h00m   running  4

instead of raw seconds.

.cmdcooldown

Cooldown list and set confirmation are now clearer:

Cooldown for !ai on #boulets set to 1m20s.
Cooldown for !ai on #boulets removed.

Good admin tooling should not feel like deciphering runes.


📻 Radio output polish

The radio commands were not the main subject this time, but a couple of nice improvements landed.

!radiostatus: compact output

Before, the command could produce four NOTICE lines.

Now it is reduced to two lines:

Icecast teuk.org | /stream | 128k | 1 listener(s) | Electro Mix Vol.3
Listen: http://teuk.org:8000/stream

Less spam. More signal.

!radiomounts

Already polished previously, the compact direction continues: IRC output should be readable, not a parchment scroll rolling across the channel.


🧾 Quotes and user summaries

!q stats

Quote stats now use a cleaner format:

Quotes on #boulets: 42 total — oldest 3y 2m ago, latest 2d ago

!userstats

User stats are now summarized on a single line:

Users: 42 total — Master:3, Friend:12, Registered:27

This is much better than multiple notices for a simple summary.

!cstat

Authenticated user stats now include a level summary in the header:

Authenticated users: 12 (Administrator:2, Friend:5, Registered:5)

🌐 DNS and URL output

!resolve

Resolution output is now cleaner:

1.2.3.4 => host.example.com
host.example.com => 1.2.3.4, 1.2.3.5

The old arrow format worked, but the new one is easier to scan.


🪄 Final safety pass

One important thing was caught before commit: the Partyline quota function had some dirty source formatting from earlier patching.

It contained literal line breaks inside strings and a weird control character around the internal \x00 split.

That was cleaned up properly.

The final version keeps:

  • configurable rate limits;
  • human-readable wait time;
  • reset clock time;
  • .quota;
  • .quota nick;

but uses clean source code:

$stream->write("No active rate limit windows.\r\n");
my ($nick_k, $chan_k) = split /\x00/, $key, 2;

This is exactly why double-checking matters.

Claude did good work.
The second review caught the cursed splinter in the wand.


🛡 No database schema change

This pass deliberately avoids schema changes.

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

Everything here is application-level polish:

  • better formatting;
  • better diagnostics;
  • better output;
  • better command summaries;
  • better Partyline visibility;
  • cleaner source code.

That makes the commit safer to review and easier to deploy.


🧪 Suggested smoke tests

IRC:

m check
m stats teuk
m active
m last teuk
m compare teuk Gwen
m karmadiff teuk
m karmahist teuk
m karmainfo teuk
m pollresult
m timers
m addtimer test 3600 PRIVMSG #test hello
m countcmd
m owncmd
m whotalk
m uptime
m q stats
m userstats
m note search test
m resolve teuk.org
m radiostatus
m ai quota

Partyline:

.quota
.quota teuk
.ai status
.ai history
.schedule list
.cmdcooldown list
.history
.logs

Code checks:

perl -I. -c mediabot.pl
perl -I. -c Mediabot/AdminCommands.pm
perl -I. -c Mediabot/ChannelCommands.pm
perl -I. -c Mediabot/DBCommands.pm
perl -I. -c Mediabot/External.pm
perl -I. -c Mediabot/Helpers.pm
perl -I. -c Mediabot/Mediabot.pm
perl -I. -c Mediabot/Partyline.pm
perl -I. -c Mediabot/UserCommands.pm
perl -I. -c Mediabot/Quotes.pm
perl -I. -c Mediabot/Hailo.pm

And one last anti-cursed-source check:

LC_ALL=C grep -P '\x00' -n Mediabot/Partyline.pm || true
git diff --check

🏁 Final status

This was a large polish pass, but a sane one.

Mediabot now feels sharper across many small commands:

  • clearer stats;
  • better karma summaries;
  • better Partyline diagnostics;
  • better AI quota/status visibility;
  • cleaner timers and cooldowns;
  • more compact radio status;
  • better command management output;
  • safer quota source code;
  • no database schema risk.

This is not the kind of commit that screams.

It is the kind of commit that makes the bot feel well-maintained.

Suggested commit spell:

✨ Lumos Maxima: refine command output, Partyline diagnostics, and IRC stats

Alternative:

🧭 Marauder's Polish: improve command clarity and Partyline diagnostics

You must be logged in to reply.