lainrocks telegram bot
  • Go 99.6%
  • Dockerfile 0.4%
Find a file
2026-11-08 17:19:41 +01:00
internal fmt: apply gofmt to feature changes 2026-11-08 16:47:52 +01:00
.dockerignore docker: multi-stage image, compose, and deploy docs 2026-11-03 22:00:03 +01:00
.env.example feature: Forgejo integration (repos, stars, issues, profile) 2026-11-05 10:15:34 +01:00
.gitignore gitignore: ignore built bot binary 2026-11-08 17:19:41 +01:00
bot.go fmt: apply gofmt to feature changes 2026-11-08 16:47:52 +01:00
BRIEF.md scaffold: go module, env template, gitignore, readme 2026-11-03 21:46:02 +01:00
docker-compose.yml docker: multi-stage image, compose, and deploy docs 2026-11-03 22:00:03 +01:00
Dockerfile docker: multi-stage image, compose, and deploy docs 2026-11-03 22:00:03 +01:00
go.mod fix: LLDAP login JSON, GraphQL user(userId), IPv4 Telegram client, lain_* groups 2026-11-04 16:32:03 +01:00
go.sum fix: LLDAP login JSON, GraphQL user(userId), IPv4 Telegram client, lain_* groups 2026-11-04 16:32:03 +01:00
README.md features: commands menu, inline keyboards, HTML formatting, admin permissions 2026-11-04 16:49:30 +01:00

lainrocks Telegram Bot

A Telegram bot that ties a Telegram user_id to a lain.rocks account (LLDAP uid) and exposes:

  • New email notifications — watch Maildir dirs for new mail, DM the user.
  • lainboard new-post notifications — poll /var/www/boards/<board>/threads.json, DM on new threads/replies.
  • Account access from Telegram — link/unlink Telegram ↔ LLDAP, view profile, change password, register.
  1. LDAP bind — /link <uid> <password>: bot attempts ldap://10.0.0.1:3890 bind as uid=<uid>,ou=people,dc=lain,dc=rocks.
  2. Authelia OIDC (variant A) — /link oidc: bot returns an Authelia authorization URL; user logs in a browser, pastes the code back to /link oidc <code>; bot exchanges code → token → /api/oidc/userinfo → preferred_username.
  3. Claim token — /link claim <token>: user generates a claim token on the web account page and pastes it.

Commands

Command Auth Behavior
/start none welcome + link options
/help none command list
/link <uid> <password> none LDAP bind link
/link oidc [<code>] none OIDC authorize / paste code
/link claim <token> none claim token link
/unlink linked remove mapping
/whoami linked uid + profile via LLDAP GraphQL
/passwd <new> linked verify current, then change via admin ldap_modify
/register <uid> <email> <password> none create LLDAP account (rate-limited)
/subscribe <board> linked subscribe to board alerts
/unsubscribe <board> linked unsubscribe
/subscribed linked list subscriptions
/stats admin bot statistics

Gated commands reply Please link your account first when unlinked.

User interface

The bot registers a command menu so users see a /commands button in the chat attachment menu. In addition to typing commands, most actions are available via clickable inline keyboards:

  • Linking — /start or /link shows buttons for LDAP bind, Authelia OAuth2, and claim token.
  • Main menu — every reply attaches a menu with Whoami, Subscribe, and Help buttons.
  • Board subscriptions — tap a board to toggle subscription on/off.
  • Unlink — confirmed via Yes/Cancel buttons.

All user-facing messages are HTML-formatted (bold labels, code spans for commands/credentials).

Admin permission system

Set ADMIN_USER_IDS in .env to a comma-separated list of Telegram user IDs (e.g. ADMIN_USER_IDS=12345678,87654321). Only listed IDs can run admin commands:

  • /stats — linked accounts, total board subscriptions, admin count.

Stack

  • Language: Go 1.26 (stdlib net/http for Telegram Bot API; no external bot framework)
  • LDAP: github.com/go-ldap/ldap/v3
  • SQLite: modernc.org/sqlite (pure Go, no CGO)
  • Env: github.com/joho/godotenv

Deployment

cp .env.example .env
# edit .env with real secrets (BOT_TOKEN, LDAP_ADMIN_PW, AUTHELIA_CLIENT_SECRET)
go build -o bot .
sudo systemctl edit --force --full telegram-bot

Systemd unit (/etc/systemd/system/telegram-bot.service):

[Unit]
Description=lainrocks Telegram Bot
After=network.target

[Service]
Type=simple
WorkingDir=/root/stacks/telegram-bot
EnvironmentFile=/root/stacks/telegram-bot/.env
ExecStart=/root/stacks/telegram-bot/bot
Restart=unless-stopped
User=root

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now telegram-bot
sudo journalctl -u telegram-bot -f

Docker

Build and run with compose:

cp .env.example .env
# edit .env with real secrets
docker compose up -d --build
docker compose logs -f telegram-bot

The container joins the existing ldap_net Docker network (external) so it can reach LLDAP at ldap://10.0.0.1:3890 and the LLDAP HTTP API at http://10.0.0.1:17170. It persists state in the telegram-bot-data volume mounted at /app/data.

No ports are published — the bot polls Telegram via getUpdates long-poll.

Files created at runtime

  • data/links.db — SQLite: links(tg_id, uid UNIQUE, linked_at, tg_username), subs(tg_id, board), state(key, value)
  • state.json — poll state (mail seen files by inode+mtime; per-board last_no/last_modified)

Secrets

.env is gitignored. Never commit real tokens or passwords.