mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-11 18:23:49 +01:00
"Wersja 0.1.7 «Callistus I»" told nobody whether Callistus was the fifteenth pope or the hundredth, and the changelog was the one place the ladder is actually read. pope_line() derives both facts from popes.json -- the ordinal, and the `reign` string exactly as the table spells it, so the one reigning pope keeps his single year instead of being padded into a range he never had. It appears in all four places a version is named: the group announcement (header and every block of a backlog), each section of DOCS-changelog.md, /healthz, and the !papiez caption, which now describes the release's pope in the same sentence it uses for every other one. The changelog's copy is checked rather than trusted, like the heading name already was: a test walks the raw file and compares each line against popes.json, so a hand-edited ordinal fails here instead of in a group. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017w1HZ3cZ7neL3rFdQ6VMBA
65 lines
2.1 KiB
Python
65 lines
2.1 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence.
|
|
"""The !papież command: a random pope, his portrait, his Latin name, his article.
|
|
|
|
The list this draws from is the same signal_bot/popes.json the version ladder
|
|
is built on, so the bot posts the popes it is named after.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import secrets
|
|
from typing import TYPE_CHECKING, Final
|
|
|
|
from signal_bot.animals import load_aliases
|
|
from signal_bot.versioning import POPES, article_url, pope_line
|
|
|
|
if TYPE_CHECKING:
|
|
from signal_bot.decorators import Decorator
|
|
from signal_bot.portraits import PortraitCache
|
|
from signal_bot.registry import CommandContext, CommandRegistry, Handler
|
|
from signal_bot.versioning import Pope
|
|
|
|
COMMAND_NAME: Final = "pope"
|
|
DESCRIPTION: Final = "losowy papież z portretem i imieniem po łacinie"
|
|
|
|
|
|
def random_pope() -> Pope:
|
|
"""Return one pope, uniformly at random.
|
|
|
|
secrets rather than random for the reason animals.paged_url gives: the
|
|
choice is not security-sensitive, but ruff's ALL rule set flags `random`
|
|
and this repo forbids the noqa that would silence it.
|
|
"""
|
|
return POPES[secrets.randbelow(len(POPES))]
|
|
|
|
|
|
def caption_for(pope: Pope) -> str:
|
|
"""Return the message that rides along with the portrait."""
|
|
return f"{pope.name} — {pope.latin}\n{pope_line(pope)}\n{article_url(pope)}"
|
|
|
|
|
|
def pope_handler(cache: PortraitCache) -> Handler:
|
|
"""Build the handler that posts a random pope."""
|
|
|
|
async def handler(ctx: CommandContext) -> None:
|
|
pope = random_pope()
|
|
image = await cache.get_base64(pope)
|
|
await ctx.reply_image(image, caption_for(pope))
|
|
|
|
return handler
|
|
|
|
|
|
def register_pope_command(
|
|
registry: CommandRegistry,
|
|
cache: PortraitCache,
|
|
*,
|
|
decorate: Decorator | None = None,
|
|
aliases: dict[str, list[str]] | None = None,
|
|
) -> None:
|
|
"""Register !papież under every trigger aliases.json gives it."""
|
|
table = load_aliases() if aliases is None else aliases
|
|
handler = pope_handler(cache)
|
|
if decorate is not None:
|
|
handler = decorate(handler)
|
|
registry.register(COMMAND_NAME, table[COMMAND_NAME], handler, DESCRIPTION)
|