Checking the Telegram channels
Each training group is wired to a Telegram channel. That wiring can break quietly — the bot gets removed from a channel, or demoted, or loses permission to post — and nothing tells you until a broadcast reaches nobody.
There’s a check for that.
Running it
From any /coach/* page, open your browser’s developer console and run:
fetch('/api/admin/telegram-test').then(r => r.json()).then(console.log)Admin only. It doesn’t post anything — it asks Telegram about each channel and reports back. Safe to run any time, including mid-season.
Reading the result
Each channel comes back with a verdict:
| Verdict | Meaning | Fix |
|---|---|---|
ok | Bot is an admin and can post | Nothing |
unreachable | Wrong channel, deleted, or the bot was never added | Re-add the bot; re-check the channel in group settings |
not_member | The bot was removed | Re-add it as an admin |
not_admin | Bot is in the channel but not an admin | Promote it |
cannot_post | Admin, but posting was turned off | Re-enable “Post messages” in its admin rights |
It also checks the inbound webhook — whether Telegram is set up to send updates back to us. That’s what mirrors your own posts in a channel into the chat panel on family pages. It’s a separate thing from the bot being able to post, and it can break on its own:
| Webhook verdict | Meaning |
|---|---|
ok | Registered and subscribed to channel posts |
not_set | No webhook at all — your channel posts won’t mirror |
erroring | Registered, but Telegram’s last delivery failed |
missing_channel_posts | Registered but not subscribed to channel posts (Telegram’s default excludes them) |
You also get:
groups_without_channel— training groups with no Telegram channel at all. Not necessarily wrong; just worth knowing.channels_with_no_families_joined— see below.
Actually sending a test post
When you want to confirm end to end, not just check permissions:
fetch('/api/admin/telegram-test', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ post: true })}).then(r => r.json()).then(console.log)That posts a short “connection test — you can ignore this” message to every
channel. To limit it to one group, add group_id:
body: JSON.stringify({ post: true, group_id: 'grp-u16' })”Everything passed but nobody’s getting posts”
Passing all the checks means the club can post. It doesn’t mean anyone is listening.
Families have to join the channel — there’s an Open in Telegram → link on their family page. Until they tap it, they’re not in the channel and won’t get the phone notification.
They don’t lose the message, though: the family page has a chat panel that mirrors channel posts, so a family that never touches Telegram still sees everything. Joining is an upgrade, not a requirement.
channels_with_no_families_joined in the result tells you where that gap is.
Worth doing before the season
One check at the start of the season, and a real test post to one group, is enough to know the pipeline works before you depend on it.