Skip to content

Telegram ​

SpaceFor
Channel @mosaic_searchAnnouncements: releases, pushes, pull requests, issues, a weekly digest. Read-only.
Group @mosaic_search_supportQuestions, help, discussion.

The two are linked: each channel post has a comment thread in the group.

The support bot ​

A bot answers in the group and in a private chat with it.

CommandReply
/helpthe list of commands
/installinstallation with pipx and pip
/versionthe latest release on PyPI
/docsa link to this documentation
/sourcesthe sources, grouped by the authentication they need
/changelogthe last three release notes from GitHub
/bughow to file a bug report
/roadmapopen milestones and planned enhancements

In the group, the bot also answers plain-text questions it recognises: installation, API keys, proxies and timeouts, Zotero, Obsidian, PDF downloads, configuration, similar papers, bulk downloads from .bib and .csv. It greets new members with installation instructions and links.

For maintainers ​

The channel posts come from GitHub Actions; the bot is a Cloudflare Worker that Telegram calls on every message.

GitHub Actions (telegram-*.yml) ──sendMessage──▶ channel ◀── linked ──▶ group
                                                                          │ webhook POST
                                                     Cloudflare Worker ◀──┘ (bot/worker.js)

Channel workflows ​

WorkflowTriggerPost
telegram-release.ymla GitHub release is publishedversion, changelog excerpt, PyPI and docs links
telegram-push.ymlpush to mainthe commits, their authors, the diff link
telegram-pr.ymlpull request opened, closed, mergedtitle, status, link
telegram-issues.ymlissue opened, closed, reopenedtitle, excerpt, link (pull requests are filtered out)
telegram-weekly.ymlMondays 08:00 UTCcommits, merged pull requests, issue counts of the week

They use the Python standard library only, and read the bot token and channel ID from GitHub secrets.

The bot ​

FileRole
bot/worker.jsthe Worker: commands, FAQ answers, welcome messages
bot/bot.pythe same bot in standard-library Python, polling getUpdates: the fallback
wrangler.tomlWorker configuration
.github/workflows/deploy-worker.ymldeploys the Worker and registers the webhook

The Worker checks the X-Telegram-Bot-Api-Secret-Token header (401 when it does not match), answers 200 at once, and handles the update in the background (ctx.waitUntil).

deploy-worker.yml runs on a push to main that changes bot/worker.js, wrangler.toml or the workflow, and on demand (Actions, Deploy Telegram Bot Worker, Run workflow). It runs wrangler deploy, stores TELEGRAM_BOT_TOKEN and WEBHOOK_SECRET as Worker secrets, and calls setWebhook with the Worker URL. To change the bot, edit bot/worker.js and push.

Repository secrets (Settings, Secrets and variables, Actions):

SecretUse
TELEGRAM_BOT_TOKENthe bot token from @BotFather, for the workflows and the Worker
TELEGRAM_CHANNEL_IDthe channel the workflows post to
CF_API_TOKENCloudflare token with Workers Scripts: Edit, nothing more
CF_ACCOUNT_IDthe Cloudflare account, so wrangler does not look it up
WEBHOOK_SECRETa random string, given to setWebhook and checked by the Worker

and one variable, CF_WORKER_URL, the Worker's URL, set after the first deploy. No credential is in a tracked file.

To fall back to polling: call deleteWebhook, then run bot/bot.py with TELEGRAM_BOT_TOKEN set.

Released under GPL-3.0-or-later, BSD-2-Clause, BSD-3-Clause or MIT, at your choice.