Files
monitoring-tg/README.md
2026-06-04 14:55:41 +03:00

124 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# parser-tg-bot
Парсер публичных Telegram-каналов на Telethon (MTProto). Сохраняет сообщения в Postgres,
управляется через REST API. Период опроса настраивается через `.env`. На следующем шаге
легко перевести на realtime через `events.NewMessage`.
## Стек
- Python 3.11, Telethon, FastAPI, SQLAlchemy 2 (async) + Alembic, APScheduler, Postgres 16
## Структура
```text
src/parser_bot/
├── api/ # FastAPI роуты + Pydantic-схемы
├── db/ # SQLAlchemy модели + сессии
├── scheduler/ # APScheduler-воркер периодического опроса
├── telegram/ # Telethon-клиент (resolve, fetch)
├── web/static/ # SPA-странички (HTML/CSS/JS, без бандлера)
├── config.py # pydantic-settings
└── main.py # FastAPI lifespan + uvicorn
alembic/ # миграции
```
## Первый запуск (локально, через Docker)
1. Получить `api_id` и `api_hash` на [my.telegram.org](https://my.telegram.org) → API development tools.
2. Скопировать `.env.example` в `.env` и заполнить `TG_API_ID`, `TG_API_HASH`, `TG_PHONE`.
3. Поднять Postgres + накатить миграции:
```bash
docker compose up -d db
docker compose run --rm app alembic upgrade head
```
4. Запуск:
```bash
docker compose up -d
docker compose logs app --tail=50
```
5. **Авторизация Telegram** — открыть [http://localhost:8000/auth.html](http://localhost:8000/auth.html)
и нажать «Отправить код». Telegram пришлёт код на номер из `TG_PHONE` →
ввести код (и 2FA-пароль, если включён). Готово, парсер начнёт опрос.
Сессия сохраняется в `./data/session/parser.session` — рестарты её переиспользуют,
повторно входить не нужно.
### Админ-доступ и коды подразделов
- `ADMIN_PASSWORD` — дополнительный пароль для админских функций. Если не задан,
остаётся прежний режим: доступ определяется только `ADMIN_ALLOWED_IPS`.
- [http://localhost:8000/admin.html](http://localhost:8000/admin.html) — вход по
админ-паролю. После входа доступны удаление и редактирование подразделов,
просмотр их кодов, управление каналами, ручной опрос, промпты, авторизация
Telegram и Swagger.
- При создании подраздела обязательно задаётся `Код доступа`. Пользователь вводит
этот код при первом открытии данных подраздела; после входа он может добавлять
каналы в этот подраздел. Админ видит код в списке подразделов.
### Прод-вариант: без UI и без volume (k8s-friendly)
Сделай интерактивный логин **один раз** на dev-машине и получи опаковую строку:
```bash
docker compose run --rm -it app python -m parser_bot.auth
```
Скрипт напечатает строку вида `TG_SESSION_STRING=1AbcD...`. Положи её в
`.env` или k8s Secret — после этого приложение поднимается без UI и без
монтирования сессионного файла:
```ini
TG_SESSION_STRING=1AbcDef... # вместо TG_SESSION_PATH/volume
```
> ⚠️ **`ApiIdPublishedFloodError`** — Telegram заблокировал твою пару
> `api_id`/`api_hash` (попала в публичный доступ). Создай **новое** приложение
> на [my.telegram.org](https://my.telegram.org) и не публикуй креды нигде.
> Старый `api_id` восстановить нельзя.
## UI
После запуска доступны страницы:
- [Дашборд](http://localhost:8000/) — общая статистика, топ каналов, кнопка опросить всех
- [Каналы](http://localhost:8000/channels.html) — добавить / удалить / включить-выключить / опросить вручную
- [Сообщения](http://localhost:8000/messages.html) — фильтр по каналу, поиск по тексту, пагинация, raw JSON
- [Настройки](http://localhost:8000/settings.html) — текущая конфигурация и подсказки
- [Авторизация](http://localhost:8000/auth.html) — веб-логин в Telegram (код + 2FA)
- [Swagger UI](http://localhost:8000/docs) — интерактивный API
Глубокая ссылка `messages.html?channel_id=42` открывает ленту конкретного канала.
## API
- `GET /healthz` — health check
- `GET /api/v1/auth/status` — авторизован ли клиент
- `POST /api/v1/auth/send-code` — отправить код на `TG_PHONE`
- `POST /api/v1/auth/submit-code` `{"code": "12345"}` — подтвердить код
- `POST /api/v1/auth/submit-password` `{"password": "..."}` — 2FA-пароль
- `POST /api/v1/auth/logout` — завершить сессию
- `GET /api/v1/stats` — глобальные счётчики
- `GET /api/v1/settings` — read-only вид конфигурации
- `GET /api/v1/channels` — список каналов
- `POST /api/v1/channels` `{"identifier": "@durov"}` — добавить
- `GET /api/v1/channels/{id}` — карточка
- `PATCH /api/v1/channels/{id}` `{"is_active": false}` — включить/выключить
- `DELETE /api/v1/channels/{id}` — удалить
- `GET /api/v1/channels/{id}/stats` — счётчики по каналу
- `POST /api/v1/channels/{id}/poll` — форсировать опрос одного канала
- `POST /api/v1/poll` — форсировать опрос всех активных каналов
- `GET /api/v1/messages?channel_id=...&q=...&limit=50&offset=0` — лента
- `GET /api/v1/messages/{id}` — одно сообщение (с `raw` JSONB)
## Дальше
- **Realtime**: заменить APScheduler на `client.add_event_handler(handler, events.NewMessage)`,
оставив periodic poll как фоновый «доводчик» для пропущенных сообщений.
- **Go-микросервис**: контракт = таблицы `channels` / `messages` в Postgres.
Go-сервис может либо читать ту же БД, либо ходить в `/api/v1/messages`.
- **k8s**: добавить Helm-чарт; `data/session/` маппится на PVC, `.env` — в Secret.