Skip to content

Latest commit

 

History

History
152 lines (119 loc) · 6.02 KB

File metadata and controls

152 lines (119 loc) · 6.02 KB

TG Assistant — Handoff Document

What This Is

A locally-running Telegram assistant for Snax. It reads all Telegram messages (DMs, groups, channels), stores them in SQLite, and exposes a Telegram bot (@tgsnaxbot) for Q&A, priority management, and message drafting — all powered by a local Ollama LLM (qwen2.5:14b on a 4090 GPU).

Architecture

Two Telegram clients running in one asyncio loop:

  • User client (Telethon MTProto) — reads Snax's messages, syncs to DB, sends messages as Snax via /reply and /draft
  • Bot client (@tgsnaxbot) — only responds to Snax (gated by SNAX_USER_ID), provides all commands
  • SQLite + FTS5 — message storage with full-text search
  • Ollama — local LLM for Q&A, summaries, intent detection, drafting

Files

src/
├── main.py          — Entry point, starts both clients via asyncio.gather()
├── config.py        — Loads .env, typed config vars
├── database.py      — MessageDB class, all SQL, schema, migrations
├── user_client.py   — Telethon user client, sync, real-time event handlers
├── bot_client.py    — Bot commands, intent handling, free-form Q&A
├── llm.py           — Ollama wrapper, system prompts, intent detection
├── query_engine.py  — Multi-signal retrieval (FTS, sender, date range, chat name)
├── prioritizer.py   — Priority gathering, LLM summarization, formatted output
└── __init__.py

Database Tables

Table Purpose
chats All synced chats with metadata, invite_link cache
users Telegram users seen in messages
messages All messages with FTS5 virtual table for search
contact_notes Per-user notes, nicknames, priority tiers (vip/high/normal/low)
sync_state Key-value for sync progress tracking
dismissed_chats Temporarily hidden from priority (auto-undismiss on new message)
followup_chats Follow-up list (not urgent, needs eventual attention)
friends Friend list with last-contact tracking
ignored_users Permanently hidden from priority and unread
ignored_folders Telegram folders to skip during sync
ignored_chat_ids Resolved chat IDs from ignored folders
tagged_chats Chat tags (bd=Biz Dev, pd=PizzaDAO) with composite PK (chat_id, tag)

Bot Commands

Priority Management

  • /p or /priority — Show priority messages (DMs + group @mentions/replies)
  • /done 3, 6, 7 — Mark items as handled (by number or @username)
  • /flup 3, 6, 7 — Move to follow-up list
  • /flup — View follow-up list
  • /prio 1, 2 — Move from follow-up back to priority
  • /mute 3, 5 — Permanently ignore users
  • /unmute @user — Remove from ignore list
  • /muted — List ignored users
  • /undone @user — Bring back to priority
  • /dismissed — List dismissed conversations

Tags

  • /bd 3, @user — Tag as Biz Dev
  • /bd — View Biz Dev list
  • /unbd 3 — Remove Biz Dev tag
  • /pd 3, @user — Tag as PizzaDAO
  • /pd — View PizzaDAO list
  • /unpd 3 — Remove PizzaDAO tag

Messaging

  • /reply @user <message> — Send as Snax
  • /draft 3 or /draft @user — AI drafts a reply (optional topic)
  • /send — Send the pending draft
  • /edit <text> — Replace draft text and send

Search & Info

  • /search <query> — FTS keyword search
  • /unread — Summarize unread messages
  • /status — Sync stats

Contacts

  • /fren 3, @user — Add friends
  • /fren — View friends + last contact time
  • /unfren @user — Remove friend
  • /note @user <text> — Add contact notes
  • /notes @user — View contact notes
  • /vip @user — Mark as VIP
  • /tier @user <level> — Set priority tier
  • /contacts — List annotated contacts

Folders

  • /folders — List Telegram folders
  • /ignore <folder> — Stop syncing a folder
  • /unignore <folder> — Resume syncing a folder

Natural Language

All commands also work via natural language through intent detection:

  • "1 and 3 are done"
  • "follow up on 5"
  • "mute 2 and 4"
  • "make john a vip"
  • Free-form questions: "What did John say about the event?"

Number-Based References

/p stores a numbered list. Numbers work with /done, /flup, /mute, /draft, and natural language. /flup stores its own numbered list for /prio.

Priority Sources

  1. Unanswered DMs — DMs where the last message is from them (not Snax)
  2. Unread messages — Any unread message across all chats
  3. Group mentions — Messages in groups that @mention Snax or reply to Snax's messages

All filtered against dismissed chats, ignored users, and ignored folders. Deduped to one item per conversation.

Group Chat Links

  • Public groups (have username): t.me/username link
  • Private supergroups (chat_id -100{id}): tg://privatepost deep link
  • Basic groups: Invite link fetched via GetFullChatRequest and cached in DB

Sync Behavior

  • First run: Fetches last 500 messages per chat, marks initial_sync_complete
  • Subsequent runs: Catch-up sync, only fetches messages newer than last synced ID
  • Real-time: Event handlers for new/edited/deleted/read messages
  • Auto-undismiss: When someone sends a new message in a dismissed chat, it returns to priority

Credentials

Stored in .env (gitignored):

  • TG_API_ID, TG_API_HASH — Telegram API credentials
  • TG_BOT_TOKEN — Bot token for @tgsnaxbot
  • SNAX_USER_ID — Snax's Telegram user ID (706681092)
  • OLLAMA_MODEL — Default: qwen2.5:14b

Running

cd C:\Users\samgo\OneDrive\Documents\PizzaDAO\Code\tg
venv\Scripts\activate
python -m src.main

First run requires interactive phone/code input for the user client session. Session persists in data/snax_user.session.

Known Limitations

  • Basic groups without invite links can't be deep-linked (Telegram limitation)
  • ExportChatInviteRequest requires admin — falls back to GetFullChatRequest for existing invite links
  • FTS5 keyword search is simple OR matching, not semantic
  • Priority dedupes to one message per conversation — may miss multiple threads in same group