Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from bundle
Telegram MTProto MCP server with userbot watcher, chat/DM parser and context builders
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
CLAUDE.md
1# CLAUDE.md — Telegram MCP: знания и правила для LLM23Этот файл содержит накопленные знания, ошибки и best practices для работы с telegram-mcp.4Читай его перед любой задачей связанной с Telegram API.56---78## Архитектура910- **Библиотека:** Telethon (MTProto) + FastMCP11- **Сессия:** `{TELEGRAM_SESSION_NAME}.session` — файл сессии авторизованного аккаунта12- **MCP-инструменты:** зарегистрированы через `mcporter` как сервер `telegram`13- **Watcher:** `watcher.py` — systemd-сервис `tg-watcher`, читает все входящие/исходящие14- **Контекст:** `context/` — jsonl-файлы с сообщениями, профили людей, саммари чатов1516---1718## Критические ошибки (обязательно читать)1920### 1. `<br>` не работает в Telegram HTML21- ❌ `"текст<br>текст"`22- ✅ `"текст\nтекст"`23- Telethon с `parse_mode="html"` игнорирует `<br>`. Только `\n`.2425### 2. `list_messages` / `get_messages` — ограничения26- Максимум **100 сообщений** за один запрос27- В **личных чатах** возвращает 0 результатов28- ✅ Правильно: использовать `iter_all_messages(chat_id, limit, offset_id)`2930### 3. Пагинация через `offset_id`31- Telethon возвращает сообщения в порядке убывания ID32- `offset_id = min(msg["id"] for msg in batch)` — для следующей страницы33- Реализовано в `parse_chat.py`3435### 4. Параллельные вызовы `openclaw agent` → file lock36- Несколько одновременных вызовов → конфликт lock-файла37- ✅ Решение: `asyncio.Semaphore(1)` в watcher.py — только один вызов одновременно3839### 5. LLM timeout и overloaded_error40- `openclaw agent` с timeout=120 падает на больших промптах41- ✅ Решение: `timeout=300`, `asyncio.sleep(8)` между вызовами в context_builder_llm.py4243### 6. Кеширование `_me`44- `client.get_me()` — сетевой вызов, не вызывать на каждое сообщение45- ✅ Инициализировать один раз при старте: `_me = await client.get_me()`4647### 7. Реплаи через mcporter48- Для ответа на конкретное сообщение: `reply_to_message(chat_id, message_id, text)`49- ❌ НЕ `send_message` — оно не создаёт тред/цитату5051### 8. ID чатов52- Группы/супергруппы: отрицательные ID (например `-100123456789`)53- Личные чаты: user_id собеседника (положительное число)54- Каналы: тоже отрицательные, но начинаются с `-100`5556---5758## Работа с контекстом (context/)5960### Структура файлов61```62context/63├── messages.jsonl — live-лог всех сообщений от watcher64├── raw_{chat_id}.jsonl — спарсенные сообщения конкретного чата/лички65├── chats/{id}.md — саммари чата (статистика + LLM)66├── people/{id}.md — профиль человека67└── summary.md — общий индекс68```6970### Парсинг чата71```bash72python3 parse_chat.py {chat_id} --limit 500073```74- Сохраняет в `context/raw_{chat_id}.jsonl`75- Автоматически дописывает новые записи в `messages.jsonl` (с полем `chat_id`)76- ID для личной переписки = user_id собеседника7778### Формат записи в jsonl79```json80{"id": 12345, "sender": "Name", "date": "...", "text": "...", "reply_to": null, "chat_id": -100123456789}81```8283---8485## Watcher (watcher.py)8687- Запущен как `systemd` сервис: `systemctl status tg-watcher`88- Триггер "клав" — **only from TELEGRAM_OWNER_ID (set in .env)**89- Команды других пользователей игнорируются (защита от prompt injection)90- Семафор: один запрос к `openclaw agent` одновременно91- Подгружает контекст чата при каждом ответе92- `_me` кешируется при старте, не вызывается повторно9394---9596## Планируемый рефакторинг9798Текущий стек (Telethon + FastMCP) планируется переписать на **Pyrogram** для ускорения парсинга.99Текущее время парсинга 5000 сообщений: ~7 минут (медленно из-за пагинации через MCP).100Цель: < 1 минуты через нативный Pyrogram API.101102При переписывании сохранить:103- Ту же структуру `context/` файлов104- Тот же формат jsonl записей105- `parse_chat.py` интерфейс (аргументы)106- Автодобавление в `messages.jsonl`107