tg-check
Telegram inbox analysis: read per-channel folders in inbox/, extract findings (API keys, tools, services, freebies, attachments) and report to the user. Triggered by "check tg", "what's new in tg". Th
SKILL.mdskills/telegram/parts/tg-check/SKILL.md
GitHubtg-check — Telegram inbox analysis
⚠️ Automation gets you banned very often. Telethon/user-session — a reserve only, not the base: priority is reading already-downloaded files, official/web paths without a user session. No write operations through a user-session without an explicit owner command.
Important: this skill is the read side. Fetch runs regularly on its own via
python your-telegram-fetcher fetch. Here we only read the per-channel folders and hand over a digest to the user.
Briefly
- Look at
inbox/.fetch_stats.json— what arrived in the last fetch. - Read the newest part of the group's folder —
inbox/<safe_title>/<YYYY-MM-DD-NNN>.md(see Step 2). - Optionally look into
inbox/<safe_title>/attachments/(or<topic>/attachments/) if there were attachments. - Extract findings (API keys, tools, services, promocodes, freebies, files).
- Report to the user per group + a general "what is worth checking".
Every inbox part is under 100 KB (MAX_INBOX_BYTES), so reading a whole part
is always safe — no truncation, no cut-off context.
Step 0. Fetcher architecture (for reference)
The project has three independent TG scripts. The canonical one is telegram_watcher.py.
| Script | API | What it does | Per-group? |
|---|---|---|---|
| your Telegram fetcher (a local Telethon script) | Telethon, user-session | Monitors selected groups/PMs, writes one folder per channel inbox/<safe_title>/ (one part per <100 KB, per-topic subfolders for forums; the forum feed goes to 1-General/) + dashboard telegram_group_inbox.md + private DMs to _signal.md. Media is not fetched — attach pulls it on demand into inbox/<safe_title>[/<topic>]/attachments/ |
✅ |
| Bot API | Removed 2026-10-17 (a scripts reorganisation retired its one-off poller); writes went to a flat inbox file. Not per-group. | ❌ | |
| Bot API, daemon | Removed 2026-09-27 (scripts review: no caller anywhere). There is no TG→agent command bridge today; sending is your Telegram sender, control of Freebuff Desktop is `the host's own control bot. |
❌ |
telegram_watcher.py config lives in the fetcher's config file
(NOT in the project root). Contains:
groups— array of tracked dialogs (id, title, username, last_message_id, is_pm, fetch_limit).last_fetch— ISO time of the last run.api_id,api_hash— take frommy.telegram.org/apps, fill in viapython telegram_watcher.py setup.discovered_topics,topic_names,topics— forum groups only.priority_topics— topics to check first; also the source of thelabelused in topic folder names (inbox/<channel>/<topic_id>-<label>/). Separateinbox/priority/*.mdfiles are no longer written.topic_last_ids(per group) — read cursor per topic ({"4": 89710, "1": …}). The main feed useslast_message_id; each topic keeps its own, so a run cut short by--max-secondsdoes not skip a topic's messages. Leave it alone by hand — it is written by the fetcher.archive_hash_<name>— service hashes against double archiving.
Session: the fetcher's session file (never committed, never shared) (Telethon, SQLite format;
do not share, do not commit, in .gitignore).
Step 1. What is fresh
# Config freshness
python your-telegram-fetcher status
# Freshness of specific files
ls -lt inbox/*.md inbox/*/*.md inbox/*/*/*.md 2>/dev/null | head -40
Look at:
- the fetcher's config file → the
last_fetchfield (ISO). inbox/.fetch_stats.json→ dict{group_title: new_messages}of the last fetch.inbox/<safe_title>/→ parts by name (YYYY-MM-DD-NNN.md, newest = highest number).inbox/<safe_title>[/<topic>]/attachments/→ fresh files (by mtime).
If last_fetch is more than 1 hour ago — the fetcher may be stuck. Not our
business in this skill, just mention it to the user.
Step 2. Per-channel inbox folders
Each group/channel/DM has a folder inbox/<safe_title>/ (name sanitised:
underscores instead of spaces, special characters stripped). Inside it the log is
split into parts YYYY-MM-DD-NNN.md — NNN is sequential inside the folder, so
the newest part is the highest number and each part is under 100 KB. Read the
newest part; add the previous one only if you need more context, or read the
parts in order for the whole history. This is the canonical source of truth for
a group.
Forum groups (and chats with configured topics) get one subfolder per topic:
inbox/<safe_title>/<topic_id>-<label>/ (e.g. inbox/<channel>/11-<topic>/,
inbox/<channel>/4-<topic>/, inbox/<channel>/597-<topic>/). <label>
comes from priority_topics in the config, else the Telegram topic title, else
topic-<id>. The forum main feed and the general topic (id=1) are the same stream
and live in the fixed subfolder inbox/<safe_title>/1-General/ (owner decision
2026-10-07). A forum's channel root holds no .md part at all — only topic
subfolders. (Root parts left over from before the change were moved once by
a one-shot migration script.)
Shape examples:
inbox/<channel>/— one folder per tracked dialog.inbox/<channel>/597-<topic>/— a forum topic inside a channel.inbox/<channel>/plus topic subfolders4-<topic>/,11-<topic>/,238-<topic>/,307-<topic>/inbox/telegram_group_inbox.md— dashboard aggregator (NOT a channel folder; a merge of ALL groups).inbox/_signal.md— private messages via the bot (NOT a channel folder; PMs in one pile).- Agent-written logs and digests (
inbox/keys_log.md,inbox/ai_tools_log.md,inbox/digest-latest*.md) stay flat — they are not channel dumps. The 100 KB rule holds, but rotation is manual since 2026-10-17 (inbox_log_append.pyis retired): copy the current content to_archive/logs/<name>.<date>.md, add a row to_archive/logs/MANIFEST.tsv, then append the new block to the emptied log. That manifest is how an archived log is found.
Format of each record in a channel/topic part:
---
**{group_title}** | {YYYY-MM-DD HH:MM:SS} | ot @{sender} [#{message_id}]:
{text}
[📎 сохранено: `inbox/{channel}[/{topic}]/attachments/...`]
Algorithm:
- From
inbox/.fetch_stats.jsontake the list of groups withcount > 0. - For each group:
ls -t inbox/<safe_title>/→ read the newestYYYY-MM-DD-NNN.mdpart(s), plus the topic subfolders that matter (read_filesworks on any part).- Extract findings.
- If
.fetch_stats.jsonis absent or empty — read the newest part of every channel folder wherelast_fetchis fresh (ls -lt inbox/*/*.md). - The legacy flat inbox was reorganised once by
python migrate-inbox-to-folders(one-shot tool,--dry-runavailable). Do not re-run it against the current folder layout.
Step 3. Attachments (on demand, not by the fetcher)
The fetcher downloads no media at all (owner decision 2026-10-07: a download
burst is a ban risk for the account). A record keeps only the type marker
([📷 Фото], [📎 Файл: name], [🎬 Видео]) plus the message id [#id].
Attachments are pulled on demand — they sit next to the log they belong to:
python your-telegram-fetcher attach "<channel>" --topic <topic-id> --limit 3
python your-telegram-fetcher attach "<channel>" --msg <message-id>
python your-telegram-fetcher attach "<channel>" # whole channel, newest
It takes ≤ --limit files (default 10) with a --delay pause (default 2 s)
between them, and names each file msg<id><ext> — so a second run sees the file
and skips it instead of downloading again. Files land in:
inbox/<safe_title>/attachments/msg<id>.<ext> # feed/channel-level
inbox/<safe_title>/<topic_id>-<label>/attachments/msg<id>.<ext> # topic-level
Feed-level media is main-feed/general-topic media; topic media goes into that topic's own subfolder. In markdown the record is marked:
[📎 сохранено: `inbox/<safe_title>[/<topic>]/attachments/<file>`]
Files > 50 MB are always skipped.
Attachment search priority (ALWAYS in this order):
~/Downloads/Telegram Desktop/— where Telegram Desktop puts files the user downloaded manually. LOOK HERE FIRST. The user often downloads files themselves (via the app), and they do not land in the inbox — only here. The file name usually matches the original (<archive>.zip).inbox/<safe_title>[/<topic>]/attachments/— what the fetcher downloaded (≤50 MB).~/Downloads/— general downloads (if the file was downloaded from a browser, not from TG).
If a file is being searched by name/context from TG — first
ls ~/Downloads/Telegram Desktop/, then the channel's attachments/. Do not write
Telegram download scripts until the file has been checked in the Telegram
Desktop downloads.
What to do with attachments:
.md,.txt,.json,.csv,.py,.sh— read and distill the essence into the report..pdf— mention the file name, do not try to parse..jpg/.png/.webp— mention, do not analyze without an explicit request..zip/.7z/.tar.gz— ask the user to confirm extraction, do not do it yourself.
Step 4. Analysis and categorization
| Type | What to look for | Action |
|---|---|---|
| API keys | sk-..., hf_..., AIza..., ghp_..., glpat-..., xoxb-... |
Tell the user immediately. Do not write the full key into the report or logs — only a mask like sk-...AbCd. |
| Tools | GitHub links (github.com/...), npm packages, bots |
If new — briefly propose: "worth a look" |
| Free services | Free APIs, promocodes, trial credits | Check the deadline/terms, mention in "worth checking" |
| System prompts / jailbreaks | Large texts with model instructions | Save to knowledge/wiki/code/ or unfiltered/jb-archive/ |
.md/.txt attachments with content |
Save locally (the fetcher already did) | Read and distill the essence |
| Scam | Template "$1 ChatGPT Plus", "KYC method", indo-pack flood | Warn, do not recommend paying |
Step 5. Report to the user
Format (SHORT, not a wall of text):
📬 TG snapshot at <last_fetch>
<Group 1> (<N> new):
• <finding 1 briefly>
• <finding 2 briefly>
<Group 2> (<N> new):
• <finding>
• attachment: inbox/<channel>[/<topic>]/attachments/<file>
🔥 Most interesting:
• <what to check first>
If last_fetch is recent and .fetch_stats.json is empty/absent — write "nothing
new, the fetcher is silent since <time>". Do not make things up.
Exceptions and gotchas
- Do not run the fetcher from this skill. It is the read side. If you want fresh messages — let the user say "fetch" separately.
- Do not send messages to TG from this skill. Read only. Sending is
send_telegram.pyorsend_to_telegram.pyon explicit request. - Do not delete old inbox parts — they are needed for history/context.
Archiving is a separate command
python your-telegram-fetcher archive. - If a group is not in
<fetcher-config>.groups— its channel folder (or a legacy flat file) is stale. Look for data intelegram_group_inbox.md, but mark it as "probably stale". - Folders outside the fetcher's config (for example
inbox/<manual-zone>/) — landing zones for manual inserts (NOT watcher-generated; the user puts things there by hand). inbox/priority/no longer exists — the former priority topics are ordinary topic subfolders now (see Step 2). Old notes and cron configs still pointing atinbox/priority/*.mdare dead paths.- In a forum, never look for channel-root parts — they are all in
1-General/(feed) or a topic subfolder.--no-attachmentsonfetchis an obsolete no-op: media has not been fetched since 2026-10-07. - If fetch failed with an error (403, FloodWait, etc.) — record it in the notes, continue with the next group.
- This skill must not be autonomous (see heartbeat/oper-workflow) — heavy actions (archive extraction, paying for something) always belong to the user.
Hands and feet: how to read files without pain
| Need | Command |
|---|---|
| Tail of a channel's newest part (last 80 lines) | powershell -Command "Get-Content (Get-ChildItem 'inbox/<safe_title>/*.md' | Sort-Object Name | Select-Object -Last 1) -Tail 80" |
| Newest part of a channel | ls -t inbox/<safe_title>/ |
| Freshness of all parts | ls -lt inbox/*/*.md |
| Freshness of attachments | ls -lt inbox/<safe_title>/attachments/ |
| Size of the whole inbox | du -sh inbox/ |
| Archive all inbox parts (hash-dedup) | python your-telegram-fetcher archive |
| Reorganise a legacy flat inbox into folders (one-shot, dry-run first) | python migrate-inbox-to-folders --dry-run |
Move leftover forum-root parts into 1-General/ (one-shot, dry-run first) |
python migrate-forum-root-to-general --dry-run |
| Download attachments on demand (≤limit, with pauses) | python your-telegram-fetcher attach "<channel>" [--topic N] [--msg ID] [--limit K] |
| Append to an agent log (manual 100 KB rotation) | append to inbox/<log>.md; when it passes 100 KB first copy it to _archive/logs/<name>.<date>.md and record the row in _archive/logs/MANIFEST.tsv |
| Find an archived agent log | grep _archive/logs/MANIFEST.tsv |
| Clean the inbox | Do not run from the read-side skill; archiving and data deletion require separate owner authorization |