Forum teuk.org

🪄 Mediabot v3 — New Spells for Every Common Room

in Mediabot · started by TeuK · 4w ago

TeuK · 4w ago

Development chronicle — mb561 to mb564 · 3.4dev

The castle has received four new enchantments: a wiser horoscope, repaired multilingual prophecies, per-channel language choices, and a carefully guarded ban action for scripted moderation.

None of these changes alter the spirit of Mediabot. They simply make its magic more accurate, safer, and easier to control. 🏰

🔮 mb561 — The fortune teller opens the birthday register

The horoscope command has been rebuilt around one simple rule: never invent what the database does not know.

When a user has a valid birthday stored in USER.birthday, Mediabot derives the correct zodiac sign and adds its element to the daily reading. When the user is unknown, the database is unavailable, or the date is invalid, the horoscope still works — only the sign is omitted.

The result is richer without becoming personal or intrusive:

  • zodiac sign and element when available;
  • social climate and project guidance;
  • daily advice and caution;
  • lucky number, colour and chance percentage;
  • a companion sign for the day.

The horoscope remains deterministic: the same nickname receives the same reading throughout the day, without disturbing Perl’s global random generator.

The old private references, project jokes and named people have also disappeared. The crystal ball now speaks only to the person asking. ✨

📜 mb562 — The oracle stops speaking in broken runes

The French and Spanish 8ball answers contained double-encoded UTF-8 text.

Instead of readable messages such as:

C'est absolument ça.
Definitivamente sí.

some answers appeared as corrupted runes on IRC.

The strings have been repaired without changing their meaning, and a new regression guard now watches the delivered Perl modules for this class of mojibake.

The oracle may remain mysterious, but its accents are readable again. 🧙

🏳️ mb563 — Every common room chooses its language

Until now, the 8ball used one global language for the entire bot.

Mediabot can now choose the language per channel through two new chansets:

chanset #quebec +LangFR
chanset #espanol +LangES

The rules are deliberately predictable:

  • +LangFR selects French;
  • +LangES selects Spanish;
  • French wins if both flags are enabled;
  • channels without either flag keep the global main.LANG setting;
  • private messages also keep the global language;
  • a database without the migration preserves the historical behaviour.

The 8ball is the first command using this helper, and the same mechanism is ready for future localised responses.

The migration is data-only and idempotent:

install/migrations/20260724_lang_chansets.sql

Fresh installations also receive the two chansets directly from the installation schema. 🗺️

🚪 mb564 — The gatekeeper can finally seal the door

The scripted action bridge already knew how to kick a user. It can now apply or remove a ban mask as well:

{"type":"ban","mask":"nick!user@host"}
{"type":"unban","mask":"nick!user@host"}

This power is intentionally narrow. Scripts cannot request arbitrary IRC modes, operator status or voice. Only +b and -b are allowed.

Three separate keys must turn before a ban may be applied:

ACTION_MODE=apply
ALLOW_IRC=yes
ALLOW_BAN=yes

ALLOW_BAN defaults to disabled, participates in configuration reload checks, and produces its own explicit rejection when missing.

The action runner also validates:

  • the complete nick!user@host mask;
  • strict segment lengths and characters;
  • the original channel context;
  • bounded action types;
  • protection against a literal self-ban;
  • a safe unban path for repairing an existing mask.

The gatekeeper example can optionally request a ban before the kick. Without the new route setting, it behaves exactly as before.

The castle porter may now seal the door before escorting someone out — but the sceptre remains locked away. 🛡️

🧹 Final pre-commit inspection

The last inspection caught several edge cases that ordinary green tests did not fully describe:

  • birthday formats now match the values actually stored by the birthday command;
  • impossible calendar dates are rejected;
  • language lookup falls back safely when the database is unavailable;
  • fresh installations receive the language chansets;
  • ALLOW_BAN is included in the hot-reload fingerprint;
  • unbanning the bot’s own mask remains possible as a repair operation;
  • partyline documentation names the ban gates correctly;
  • the mojibake guard scans nested Mediabot modules as intended.

These adjustments tighten the contracts without broadening the permissions of the scripted bridge.

🧪 Validation

The Claude rounds reported the following complete-suite milestones:

mb561: 10998 / 10998 PASSED
mb562: 11003 / 11003 PASSED
mb563 + mb564: 11044 / 11044 PASSED

The final corrected tree must still pass the complete local suite before commit:

perl t/test_commands.pl

After the push, the GitHub CI performs the final independent inspection of the public branch.

📚 What changed for operators

After deployment, apply the language chanset migration to an existing database:

SOURCE install/migrations/20260724_lang_chansets.sql;

To enable scripted bans, the operator must explicitly configure all three gates. Leaving ALLOW_BAN disabled preserves the previous behaviour.

No broad IRC mode action was introduced, and no database schema redesign was required.

⚡ Final parchment

The fortune teller now reads the correct stars.
The oracle speaks French and Spanish without broken ink.
Each common room may choose its language.
And the gatekeeper can seal one carefully controlled door.

Four spells, four safeguards, and one rule unchanged: powerful magic must always remain bounded, observable and reversible.

You must be logged in to reply.