4.4 KiB
beavergram
A Telegram client that keeps everything and writes nowhere but your own Saved Messages. A userbot on your own account logs every incoming message into Postgres, including the ones later deleted or edited, along with media, reactions, presence and stories. A web client reads that archive back, and an MCP server hands it to agents.
Useful on its own: a Telegram where nothing disappears. In the beaver setup it is one of the agent's hands - the dispatcher reads chat history by the chat_id stored in a person's card.
What it keeps
- Messages with edits as versions and deletions as flags, so a message removed in Telegram is still in the archive with its history.
- Media on disk, content-addressed, with the versions of a replaced photo.
- Voice transcribed through Telegram's own transcription (Premium), queued when the quota runs out: your own and the played ones by themselves, any voice or round video on request.
- Presence as a time series (TimescaleDB), read receipts, stories.
- Capture policy from your Telegram folders with per-chat overrides: channels nothing, groups messages only, private chats everything, by default.
- Annotations and watches: your notes on messages, with
#tagsand one list of them all, and rules that fire alerts, both yours to write in the web client. - Watched bots: bot tokens you add in the web client. Each one logs in over MTProto (
auth.importBotAuthorization, the same door a bot-login client uses), backfills the history of the bot's dialogs once and then keeps the incoming stream: who writes to the bot, what, and when. A separate authorization, so it does not takegetUpdatesaway from whoever runs that bot over the Bot API.
Nothing is ever deleted from the archive.
Parts
backend/-userbot(kurigram, the capture loop and jobs),watcher(kurigram again, one bot-token session per watched bot) andapi(FastAPI: the web API, the MCP server, and the built frontend as static files).frontend/- SvelteKit,adapter-static; a chat client over the archive: folders, chat list, thread with media, versions and the deleted messages inline, a feed of what was deleted or edited across chats, search, stories, presence graphs.docker-compose.yml- includesbackend/(Postgres with TimescaleDB,userbot,api) andfrontend/(the dev server); profilesexternalandservices.
MCP
Read: search_messages_tool, list_chats, get_chat_history (a readable transcript, deleted messages included) and get_chat_history_raw (the same as JSON), get_deleted_messages, get_feed (deleted and edited messages and profile changes across chats), get_message_versions, get_media, get_callbacks, get_read_info, presence_history, presence_stats, get_peer_history, get_person, get_stories, get_annotations, list_watches, list_alerts.
Act: transcribe_message asks Telegram for the transcript of any voice or round video, set_watch writes a rule, download_media pulls any attachment and leaves a public link to it for a day, visible and revocable in the web client. send_to_saved is the one thing that sends to Telegram, and only to your own Saved Messages: text, a file by URL (as a voice message when asked), or an archived message, forwarded while it lives and copied from the archive once it is gone. Send any OGG/Opus there as a voice and transcribe_message turns Telegram Premium into a free transcriber. There is no tool that edits, deletes or sends anywhere else.
The same over HTTP: POST /api/media/transcribe (wait seconds to hold for the text), GET /api/media/lookup?sha256= (where these exact bytes appear in the archive), POST /api/saved (multipart account_id, text, file, voice) and POST /api/saved/forward.
Run
make env # .env and docker-compose.override.yml from the examples
make -C backend session # log the account in once; the session file stays in backend/sessions
make -C backend migrate # the schema
make recreate # build and start the services in COMPOSE_PROFILES
COMPOSE_PROFILES in .env selects what runs on the machine, docker-compose.override.yml in each part holds the published ports and the caddy network aliases. The web client and the MCP endpoint are served by api; the bearer for both is AUTH__TOKEN.
Develop
make fmt
make check
make -C frontend dev