Scope monitoring TG by department
This commit is contained in:
173
README.md
173
README.md
@@ -1,123 +1,68 @@
|
||||
# parser-tg-bot
|
||||
# monitoring-tg
|
||||
|
||||
Парсер публичных Telegram-каналов на Telethon (MTProto). Сохраняет сообщения в Postgres,
|
||||
управляется через REST API. Период опроса настраивается через `.env`. На следующем шаге
|
||||
легко перевести на realtime через `events.NewMessage`.
|
||||
Сервис мониторинга Telegram-каналов для портала. Он сохраняет сообщения в
|
||||
Postgres, раскладывает каналы по вертикалям/подразделам и выполняет AI-анализ
|
||||
через OpenAI-compatible endpoint, общий с другими сервисами портала.
|
||||
|
||||
## Стек
|
||||
## Доступ
|
||||
|
||||
- Python 3.11, Telethon, FastAPI, SQLAlchemy 2 (async) + Alembic, APScheduler, Postgres 16
|
||||
- Админские операции остаются за админом портала: portal прокидывает
|
||||
`X-User-Is-Admin=1`.
|
||||
- Отдел видит только свои подразделы, каналы, сообщения и промпты через
|
||||
`X-User-Department-Id`.
|
||||
- Руководитель отдела может создавать и редактировать подразделы своего отдела:
|
||||
portal прокидывает `X-User-Is-Department-Head=1`.
|
||||
- Пароли подразделов и IP allowlist удалены.
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Основные переменные:
|
||||
|
||||
```env
|
||||
TG_API_ID=
|
||||
TG_API_HASH=
|
||||
TG_PHONE=
|
||||
TG_SESSION_STRING=
|
||||
|
||||
POSTGRES_HOST=postgres.monitoring-tg.svc.cluster.local
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USER=parser
|
||||
POSTGRES_PASSWORD=parser
|
||||
POSTGRES_DB=parser
|
||||
|
||||
PUBLIC_BASE_PATH=/api/monitoring-tg
|
||||
|
||||
LLM_ENABLED=true
|
||||
LLM_BASE_URL=http://10.2.3.5:8002
|
||||
LLM_API_KEY=
|
||||
LLM_MODEL=qwen2.5-14b
|
||||
```
|
||||
|
||||
Для локальной админской отладки можно задать `ADMIN_PASSWORD`, но в проде доступ
|
||||
должен идти через портал.
|
||||
|
||||
## Запуск в k8s
|
||||
|
||||
Манифесты лежат в `k8s/`. Перед применением нужно заполнить `k8s/secrets.yaml`
|
||||
реальными Telegram-кредами и, при необходимости, `LLM_API_KEY`.
|
||||
|
||||
```bash
|
||||
kubectl apply -k k8s
|
||||
```
|
||||
|
||||
Миграции выполняются entrypoint-ом контейнера перед запуском API.
|
||||
|
||||
## Структура
|
||||
|
||||
```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/ # миграции
|
||||
├── api/ FastAPI роуты + Pydantic-схемы
|
||||
├── db/ SQLAlchemy модели + сессии
|
||||
├── scheduler/ APScheduler-воркер периодического опроса
|
||||
├── telegram/ Telethon-клиент
|
||||
├── web/static/ страницы UI без бандлера
|
||||
├── config.py pydantic-settings
|
||||
└── main.py FastAPI lifespan + uvicorn
|
||||
alembic/ миграции
|
||||
k8s/ манифесты для портала
|
||||
```
|
||||
|
||||
## Первый запуск (локально, через 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.
|
||||
|
||||
Reference in New Issue
Block a user