carlok — zsh — 88×30
Carlo Perassi

$ grep -l bot _posts/*.md

#bot

11 posts tagged bot. Back to the full blog.

home.sh projects.sh blog.sh writing.sh math.sh cv.sh

caciarabot: telegram-shaped photo validation, enforced rule priority, and a lint-found dangling task

caciarabot’s validator already caught a file over Telegram’s upload ceiling, but size is not the only way Telegram refuses a photo: width and height above 10000 px, or a longer side more than 20× the shorter, fails with PHOTO_INVALID_DIMENSIONS even at a few hundred KB — and a panorama or tall screenshot is exactly the file people drop in. A new telegram/imagesize.py reads the dimensions out of the header with the standard library alone — PNG (IHDR), JPEG (skip the APPn segments to the start-of-frame marker) and all three WebP variants — checked against macOS sips on all 142 real images in media/ with no false positives (b06e315).

caciarabot: the weekend Wikipedia draws get their own prompt pool

The weekend digest swapped the tech feeds for a random Wikipedia article but kept the tech prompts, which tell the model it reads “computer-science-adjacent feeds” and must say something “technically true and not obvious” — handed a 150-character stub, that forces either an invented fact or a bolted-on code joke, and a county sheriff’s office had drawn a package.json comparison. A separate config/prompts/digest_weekend/ pool now holds three tones mirroring the tech one, confined to the excerpt and forbidden from asserting facts from memory or reaching for code-and-servers comparisons; the prompt is chosen by candidate.source rather than by re-checking the weekday, so it always matches its content, an empty weekend pool falls back to the tech pool instead of losing the day, and the validator requires the pool whenever the digest is enabled (932b0a6). A first pass still leaked — the Nagano article drew “visti i risultati complessivi”, implying an outcome the excerpt never stated — so the prompts now also forbid implying outcomes or quality the excerpt does not support.

caciarabot: weekends take a non-technical turn in the digest

Weekend days — in the bot’s own timezone, default Europe/Rome — now pull the daily digest’s candidate from Wikipedia under a non-technical topic filter instead of the configured tech sources, and the daily-thought Wikipedia rabbit hole uses the same filter on those days; weekdays are unchanged, and weekday Wikipedia draws stay unfiltered (00e467f, PR #1). is_weekend_in_bot_timezone() in llm/scheduler.py is the shared check, looks_technical() in llm/wikipedia.py the heuristic, and weekend Wikipedia picks skip the English-only page fetch so Italian reads come through. The same day’s second change fixes how updates land: deploy/update.sh now rebuilds, then does podman compose down and up -d, because up -d followed by restart could leave the old container running the previous image; the script deliberately keeps -v off down, so the bind-mounted config, media and data/ trees survive (bbaa82c, PR #2). The test suite stands at 174 passing.

topshift-trend: a transient failure no longer wipes out what was already delivered

A scheduled notify pass in topshift-trend can now fail halfway without repeating itself: per-chat deliveries are recorded as they succeed, so the next run skips the links a chat already received and retries only the ones that never went out, and the global cooldown baseline advances only after a clean pass (0ce1688, PR #9). Before this, one transient Telegram error in the middle of a batch could resend everything that had already arrived. A ruff UP035 fix — Mapping imported from collections.abc — rode along.

caciarabot: the secret feature logs how many people, not which ones

The segreto feature in caciarabot keeps a roster of who has posted — display names only, no message content, because the Bot API cannot list a group’s membership — but its dry-run log line wrote those names out in full. It now logs a count instead (db905db), and the README’s Privacy section says so explicitly: the events say how many people a secret was about, never which ones. The change also cleared CodeQL alert py/clear-text-logging-sensitive-data, whose “sensitive data” label was firing on the word “secret” rather than on a credential — the dataflow was real even where the rule’s name was not, and the count is all the operator needs to see the feature working.

caciarabot: the digest stops posting links it cannot read

The digest in caciarabot now skips candidate links whose target page is in another language (7fd451b), because GitHub trending routinely surfaces repositories documented entirely in Chinese — two of the fifty candidates in that day’s live fetch were exactly that, and posting one of them as the link of the day wastes the slot. The check runs in two stages, cheapest first: the pool is filtered on the title and description the source already returned, no extra request; only the picked candidate is fetched and checked, because verifying fifty to post one would be fifty requests a day, and a rejection drops that link and draws again, up to five times. For a GitHub repo the check reads the raw README rather than the repo page, since github.com serves <html lang="en"> on every page it renders, including for repos written entirely in Chinese; elsewhere the declared lang decides, falling back to an English-stopword ratio over the visible text. Two deliberate non-rejections: Latin-script languages pass the metadata stage (ten words of French cannot be told from English reliably), and a page yielding no usable evidence is accepted rather than quietly thinning the pool — and Greek is left out of the non-Latin script set on purpose, since a lone alpha here is more likely to be mathematics than prose.

topshift-trend: a cooldown so a chat is not notified twice about the same repo

topshift-trend, the Telegram bot that watches GitHub’s monthly trending list, learned to suppress repositories it recently notified: a repo that drops out of the top-N and comes back used to announce itself to every subscriber again. The bot now keeps a notification_history.json alongside its state and subscribers, and the scheduled check filters out keys seen inside a configurable window — NOTIFICATION_COOLDOWN_DAYS, default 30 days, 0 disables the suppression. The commit touches the config, store and main loop plus three test files, and the check’s log line now reports how many entries were suppressed next to how many notifications actually went out.

caciarabot: videos and GIFs alongside images

caciarabot word-trigger responses now ship videos and GIFs alongside images, so the bot can reply with moving media instead of only stills. The update script also always restarts the bot now, so config-only changes actually land on the next deploy.

caciarabot: config example file and mood-range daily thoughts

caciarabot stopped tracking its live config: the working bot.jsonc is no longer in the repo, and a bot.jsonc.example ships instead, so local state can’t be clobbered by updates or leak into history. The daily thought generator also gained a real mood range and occasionally follows a Wikipedia rabbit hole instead of picking a templated topic.

caciarabot Phase 3: admin commands and reply fixes

caciarabot grew a Phase 3 admin surface: /sleep, /wake, /categories, /stats, and /reload let moderators pause the bot, inspect its categories, and reload state without touching the container. Two reply bugs were also fixed — a cited reply and a word-trigger image can now fire together, and the LLM prompt no longer drifts into recurring ants/insects imagery.

caciarabot: an Italian-first Telegram group bot

caciarabot is a new self-hosted, reactive Telegram group bot designed Italian-first. It runs on your own infrastructure rather than a hosted service, and it reacts to group activity rather than only to explicit commands.