Telegram control bot · user guide

tg-digest command guide

Every command of the bot, what it does, and how to use it — from adding a channel to scheduling a digest.

owner-only read-only scraper no AI calls 29 commands
01

What it is

tg-digest has two parts. A read-only scraper collects messages from the Telegram channels you choose and writes them to a JSON file. A control bot lets you drive that scraper entirely from a private Telegram chat with your own bot.

Source
Your channels
Public or joined channels & groups.
→
Scraper
main.py
Reads messages. Never sends, edits or reacts.
→
Output
Digest JSON
One file, with a summary prompt embedded.
→
You
Paste into any AI
The bot never contacts an AI service.
The bot is the remote control

The bot never scrapes by itself. When you send /run, it starts main.py as a separate process and reports progress back in the chat.

02

Quick start

  1. Install.
    pip install -r requirements.txt
  2. Create your bot. Talk to @BotFather in Telegram, send /newbot, follow the prompts, and copy the token it gives you.
  3. Fill in .env. Copy .env.example to .env and set: API_ID=1234567 API_HASH=... # from my.telegram.org BOT_TOKEN=... # from @BotFather OWNER_ID=... # your numeric Telegram id (or leave blank)
  4. Start the bot. python bot.py If you left OWNER_ID blank it prints a pairing code in the terminal — send /claim <code> to your bot from your own account.
  5. Log in. Send /login and scan the QR with a second device. Then /run today.
03

Logging in

The bot logs in your user account (not the bot) so the scraper can read your channels. Do it once; the session is saved.

CommandWhat it does
/loginQR login (recommended). Shows a QR image; scan it from a second device (Telegram → Settings → Devices → Link Desktop Device). Refreshes up to 3 times, ~2–3 min.
/login_phoneFallback: type your phone, then the code Telegram sends. Type the code with separators (e.g. 1-2-3-4-5). Telegram may reject codes sent through a chat — if so, use /login.
/statusShows whether you're logged in, your first name, and only the last 2 digits of your phone.
/logoutConfirms, logs out on Telegram's side, and deletes the local session file.
/cancelAborts a login in progress and clears the state.
The chat is not end-to-end encrypted

Anything you type in the bot chat is stored on Telegram's servers. The bot deletes your code/password messages immediately, but for the 2FA password the terminal login (python main.py --terminal-login) is safest.

04

All commands

Every command is owner-only and works in a private chat with your bot. Anyone else gets no reply at all.

Channels

CommandWhat it doesExample
/channels [tag]Lists your channels, 20 per page, with paused and invalid marks. Optional tag filter./channels jobs
/add <link|@name|id> [| label]Validates the channel (read-only) and appends it. Shows the resolved title and whether you're a member./add @news | Daily
/remove <#|link|name>Removes a channel after confirmation. If the match is ambiguous it asks which one./remove 3
/pause <#>Marks a line off — the scraper skips it and reports it as paused./pause 2
/resume <#>Removes the off mark./resume 2
/tag <#> <tag>Adds a tag so you can run a subset with group:<tag>./tag 1 news
/untag <#> <tag>Removes a tag./untag 1 news
/groupsLists your tag groups with counts./groups

Running

CommandWhat it doesExample
/run <window> [options]Runs the scraper and sends you the digest. See section 6 for options./run today
/preview <window> [group:<tag>]Dry run — shows how many messages each channel has. No file is written./preview 24h
/stopKills the running scrape (the whole process tree)./stop
/lastResends the most recent digest file(s)./last

Schedules

CommandWhat it doesExample
/schedule add <HH:MM> <window> [group:<tag>]Adds a daily run at that IST time (max 5 schedules)./schedule add 09:00 today
/schedule listLists schedules with their numbers./schedule list
/schedule remove <n>Removes a schedule (after confirmation)./schedule remove 1
/schedule pause <n>Temporarily stops a schedule./schedule pause 1
/schedule resume <n>Restarts a paused schedule./schedule resume 1

Settings & prompts

CommandWhat it doesExample
/settingsShows every setting and its current value./settings
/set <key> <value>Changes one setting (validated). See section 8./set dedupe on
/promptsLists the available summary prompts and marks the selected one./prompts
/prompt <name>Sends a prompt's text back to you (as a message, or a .md file if long)./prompt detailed

Files, health & safety

CommandWhat it doesExample
/filesLists recent outputs with buttons to resend any of them./files
/cleanDeletes outputs older than retention_days (after confirmation)./clean
/find <keyword> [6h|24h|3d]Searches saved digests locally — no Telegram call. Up to 10 matches with links./find result
/healthLogin state, last run, next schedule, disk space, versions, uptime./health
/panicKill switch (two confirmations). See section 11./panic
05

channels.txt

Your channel list is a plain text file. The bot edits it for you, but you can also edit it by hand.

# a comment — ignored @news | Daily News | tags=news,jobs | off https://t.me/somechannel | Some Channel -1001234567890
SegmentMeaning
entry@name, https://t.me/name, t.me/name, a post link, or a numeric id.
| labelA friendly name shown in /channels and in the digest.
| tags=a,bTags for grouping. Run just a group with /run today group:a.
| offPauses the line — the scraper skips it and reports it as paused.

Old two-column lines (entry | label) keep working unchanged. The file is edited line-by-line, so comments, blank lines and order are preserved, and a channels.txt.bak backup is kept before every change.

06

Running a digest

The shape of a run command is: /run <window> [options…]

Windows (pick one)

WindowMeans
todayFrom midnight IST until now.
yesterdayThe whole previous day (IST).
6h · 24h · 3dThe last N hours / days from now.
since-lastEverything since the last successful run.
<YYYY-MM-DD HH:MM> <YYYY-MM-DD HH:MM>An explicit IST range: start and end.

Options (any order, all optional)

OptionEffect
group:<tag>Only channels carrying that tag.
channel:<n>Only channel number n from /channels.
dedupeDrop near-duplicate messages.
min:<N>Skip messages shorter than N characters (0–500).
viewsInclude view counts.
send:noRun but don't send me the file.
# today's messages, only the "jobs" group, skip short posts, no file /run today group:jobs min:40 send:no # an explicit IST range /run 2026-10-17 06:00 2026-10-18 18:00
Run limits protect your account
  • One run at a time.
  • At least 5 minutes between runs.
  • At most 12 runs per day (manual and scheduled share the limit).
  • A hard 30-minute timeout, after which the process tree is killed.

While a run is going, the bot keeps one status message updated (at most every 10 seconds) showing the elapsed time and progress like channel 3/12. When it finishes you get a summary — channels ok, messages, skipped channels and reasons, truncated channels, estimated tokens — and the digest arrives as a document. If there are more than 10 parts it asks before sending.

07

Schedules

A schedule runs a digest for you every day at a fixed IST time. You can keep up to five.

# every day at 9:00 IST, today's messages /schedule add 09:00 today # every evening at 20:30, last 24 hours, only the "news" group /schedule add 20:30 24h group:news /schedule list /schedule pause 2 /schedule resume 2 /schedule remove 1
Missed runs are not caught up

If the bot was off at the scheduled time, it does not run late. When it starts again it tells you what was missed and offers a Run now button. If a run is already going, a scheduled run is skipped with a message.

The bot must be running for schedules to fire. Run it under systemd, tmux or screen — a laptop that sleeps, or Termux with the screen off, will stop it.

08

Settings

/settings shows all of these. /set <key> <value> changes one — invalid values are rejected without changing anything.

KeyValuesDefaultWhat it does
formatjson · jsonl · txtjsonOutput file format.
dedupeon · offoffDrop near-duplicate messages.
min_chars0–5000Skip messages shorter than this.
with_viewson · offoffInclude view counts.
max_chars50000–1000000300000Max size of one output part; larger digests are split.
max_per_channel100–200005000Cap messages read per channel.
retention_days1–607Delete output files older than this.
autodelete_minutes0–14400Auto-delete the bot's sent digest messages (0 = off).
summary_prompta prompt namedefaultWhich prompt is embedded in new digests.
/set format jsonl /set dedupe on /set min_chars 40 /set summary_prompt exam_alerts
09

Prompts

A prompt is just text embedded in the digest file as ai_instructions. When you paste the file into an AI, that text tells it what to do. The bot never calls an AI service itself.

NameUse it for
defaultShort instructions embedded in every digest — a good all-round summary.
detailedA full structured brief: coverage, top 10, per-channel, dates table, action items, conflicts, unverified.
exam_alertsJobs, recruitment and exam updates — notifications, a dates calendar, results, "verify first".
news_briefNews and current affairs grouped by topic, with facts vs claims.
merge_partsCombine the summaries of several parts into one final summary.
askAnswer one question from the digest (put your question after QUESTION:).

Three ways to summarise

Quick

Open the digest in any AI chat. The embedded ai_instructions already does the job.

Stronger

Choose a prompt: /set summary_prompt detailed, then run. Or --summary-prompt detailed on the CLI.

Multi-part

Summarise each part, then give the AI the merge_parts prompt plus the part summaries.

Privacy

A digest can contain private channel content. Whatever AI service you paste it into will receive that content. The bot itself never contacts an AI service — it only stores, selects and embeds prompt text.

Adding your own prompt

Drop a .md file into prompts/. The first line must be # <name> - <description> and the file must stay under 8000 characters. It then appears in /prompts and can be selected with /set summary_prompt <name>.

10

Files & search

/files

Lists recent digests (name, size, time, message count) with a button to resend any of them.

/clean

Deletes output files older than retention_days, after a confirmation.

/find

Searches saved digests locally — no Telegram call, works with Hindi text. Up to 10 matches with links.

# find a keyword in the last 24 hours of digests /find admit-card 24h

Retention also runs automatically: at startup and once a day, files older than retention_days in the output folder are removed. It only ever touches that folder, and never follows a symlink out of it.

11

Health & panic

/health is a read-only check-up. /panic is the emergency stop.

/health shows

Logged in or not · session file present · last run (result, time, duration) · skipped channels from the last run · next scheduled run · free disk space in the output folder · library versions · bot uptime. No secrets, no full phone number.

/panic does (two confirmations)
  • Pauses all schedules.
  • Stops any running scrape.
  • Logs out and deletes the local session file.
  • Deletes the output files and .cache/ — but keeps .cache/run_history.json and .cache/run.lock so your daily/gap limits survive.
  • Keeps channels.txt and settings.json.
  • Reports every step honestly, including partial failures.
12

Troubleshooting

SymptomFix
Bot replies to nobody / nothing happensCheck OWNER_ID is your numeric id, or that you claimed ownership with /claim <code>. Non-owners are silently ignored.
"Not logged in"Send /login and scan the QR. Or run python main.py --terminal-login.
database is lockedA scrape is using the session file. Wait for it to finish; the bot retries cleanly.
QR will not scanOpen the QR from a second device (Settings → Devices → Link Desktop Device) while the bot is still waiting, then /login again.
Code rejected right after typingTelegram may block codes sent through a chat. Use /login (QR) or the terminal.
Run refusedYou hit a limit — 5-minute gap, 12 runs/day, or a run already in progress. The message tells you which.
Schedule did not fireThe bot must be running. A missed run is offered as a Run now button when the bot starts.
Help text looks oddRestart the bot — messages are sent as plain text so underscores and <placeholders> render literally.
13

Security

Owner-only

Identified by your numeric Telegram id, never a username. Every handler checks it before doing anything; everyone else is dropped with no reply and no log.

Read-only scraper

The user client never sends, edits, deletes, forwards, reacts or marks read. An automated scan of the source enforces this.

No shell

The scraper runs as a separate process with an argument list — never a shell string — and only validated values reach it.

Secrets stay out

API keys, tokens, phone number and session files are never logged, never sent to the chat, and never committed to git.

The chat is not end-to-end encrypted

Sensitive inputs (phone, login code, 2FA password) are deleted from the chat right after they are read, but Telegram's servers hold them until then. For the 2FA password, the terminal login is the safest option.

14

FAQ

QuestionAnswer
Does it download the files in a channel?No. It records a label in the media field. For a document it includes the filename (document:notice.pdf); for video, audio, voice, GIF and stickers it records only the type.
Does it join channels?Never from the bot. Joining only happens in the terminal scraper with the explicit --auto-join flag.
Can I add or remove channels from the bot?Yes — /add, /remove, /pause, /resume, /tag, /untag.
Does the bot summarise with AI?No. It embeds a prompt into the JSON; you paste the file into whatever AI you like.
How many runs can I do a day?12 total, at least 5 minutes apart, one at a time, 30-minute timeout.
Where are the digests?In the output folder on the machine running the bot. /files lists them; /last resends the newest.