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

7.0 KiB
Raw Blame History

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

Структура

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 → API development tools.

  2. Скопировать .env.example в .env и заполнить TG_API_ID, TG_API_HASH, TG_PHONE.

  3. Поднять Postgres + накатить миграции:

    docker compose up -d db
    docker compose run --rm app alembic upgrade head
    
  4. Запуск:

    docker compose up -d
    docker compose logs app --tail=50
    
  5. Авторизация Telegram — открыть http://localhost:8000/auth.html и нажать «Отправить код». Telegram пришлёт код на номер из TG_PHONE → ввести код (и 2FA-пароль, если включён). Готово, парсер начнёт опрос.

    Сессия сохраняется в ./data/session/parser.session — рестарты её переиспользуют, повторно входить не нужно.

Админ-доступ и коды подразделов

  • ADMIN_PASSWORD — дополнительный пароль для админских функций. Если не задан, остаётся прежний режим: доступ определяется только ADMIN_ALLOWED_IPS.
  • http://localhost:8000/admin.html — вход по админ-паролю. После входа доступны удаление и редактирование подразделов, просмотр их кодов, управление каналами, ручной опрос, промпты, авторизация Telegram и Swagger.
  • При создании подраздела обязательно задаётся Код доступа. Пользователь вводит этот код при первом открытии данных подраздела; после входа он может добавлять каналы в этот подраздел. Админ видит код в списке подразделов.

Прод-вариант: без UI и без volume (k8s-friendly)

Сделай интерактивный логин один раз на dev-машине и получи опаковую строку:

docker compose run --rm -it app python -m parser_bot.auth

Скрипт напечатает строку вида TG_SESSION_STRING=1AbcD.... Положи её в .env или k8s Secret — после этого приложение поднимается без UI и без монтирования сессионного файла:

TG_SESSION_STRING=1AbcDef...     # вместо TG_SESSION_PATH/volume

⚠️ ApiIdPublishedFloodError — Telegram заблокировал твою пару api_id/api_hash (попала в публичный доступ). Создай новое приложение на my.telegram.org и не публикуй креды нигде. Старый api_id восстановить нельзя.

UI

После запуска доступны страницы:

  • Дашборд — общая статистика, топ каналов, кнопка опросить всех
  • Каналы — добавить / удалить / включить-выключить / опросить вручную
  • Сообщения — фильтр по каналу, поиск по тексту, пагинация, raw JSON
  • Настройки — текущая конфигурация и подсказки
  • Авторизация — веб-логин в Telegram (код + 2FA)
  • Swagger UI — интерактивный 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.