Files
uni-notify/README.md
Claude da28d0ac1c uni-notify: Outlook + Teams → Telegram с LLM-фильтром
- Playwright держит открытыми веб-версии Outlook и Teams (постоянный профиль, Xvfb)
- watcher.js перехватывает уведомления клиента и изменения карточек в реальном времени
- pipeline: дедуп, baseline, VIP/MUTE, оценка важности через Haiku (OpenRouter)
- aiogram-бот: уведомления, дайджест, вопросы по журналу, /login с 2FA-кодом, ручное управление браузером
- Docker/compose, systemd-юнит, e2e-тест на поддельных страницах

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0194buWJjpDjU52JPX7PjsMs
2026-11-13 14:20:14 +01:00

95 lines
6.9 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.
# uni-notify
Читает университетскую почту (Outlook) и Microsoft Teams через их веб-версии и присылает важное в Telegram. Ему можно задавать вопросы вроде «что препод писал про курсач?».
## Как это работает
```
Chromium (Playwright, постоянный профиль, Xvfb)
├─ вкладка Outlook ─┐ watcher.js ловит:
└─ вкладка Teams ──┤ 1) уведомления самого клиента (Notification / showNotification) — мгновенно
│ 2) изменения карточек в списках писем/чатов (MutationObserver) — страховка
▼
pipeline: дедуп → baseline → VIP/MUTE → LLM (Haiku через OpenRouter) → уровень 0–3
▼
Telegram-бот (aiogram): 🔴 срочно / 🟡 важно / дайджест / ответы на вопросы
```
- **Реалтайм.** Веб-клиенты Microsoft сами получают пуши. Бот держит их открытыми и перехватывает уведомления прямо в странице, поэтому задержка составляет секунды. Токены из браузера никуда не выносятся.
- **Сессия.** Профиль браузера хранится в `data/browser-profile`. Вход нужен один раз, дальше клиент сам обновляет токены. Если сессия всё-таки слетит, бот напишет «нужен /login».
- **2FA.** `/login` заполняет обычную форму входа Microsoft, а 6-значный код спрашивает у тебя в Telegram. Если включено сопоставление чисел, бот присылает число, которое нужно выбрать в Authenticator.
- **Нестандартный SSO университета.** Бот пришлёт скриншот. Дальше управляешь браузером через `/click X Y`, `/type`, `/key Enter`, `/screen`.
- **Хранилище.** SQLite с полнотекстовым поиском (`data/uni.db`). По нему бот отвечает на вопросы.
## Установка (Docker)
```bash
git clone https://git.azimkin.dev/Azimkin/uni-notify.git && cd uni-notify
cp .env.example .env && nano .env # токен бота, OWNER_ID, ключ OpenRouter, UNI_EMAIL
docker compose up -d --build
docker compose logs -f
```
Потом в Telegram: `/start`, затем `/login`, затем введи код из приложения.
Нужно примерно 1,5–2 ГБ RAM: Teams в браузере прожорлив. Вкладки перезагружаются раз в `RELOAD_HOURS`.
### Без Docker
```bash
sudo apt install -y xvfb
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt && playwright install --with-deps chromium
xvfb-run -a python -m app.main
```
systemd-юнит лежит в `deploy/uni-notify.service`.
## Первый запуск: что важно знать
1. **Baseline.** При самом первом старте всё, что уже лежит в списках, молча запоминается в течение 90 секунд. Старые письма не придут.
2. **Включи уведомления в веб-клиентах** (настройки хранятся в аккаунте, можно сделать со своего браузера):
- Outlook: Settings → General → Notifications → Desktop notifications → включить;
- Teams: Settings → Notifications → включить уведомления для чатов, упоминаний и активности.
Без этого бот всё равно работает через карточки списков, просто чуть менее точно.
3. **Проверка парсера:** `/debug mail` и `/debug teams` показывают, какие карточки видит бот. Если пусто, у Microsoft поменялась вёрстка: поправь `rowSelector` в `config/selectors.json` и перезапусти.
## Команды бота
| Команда | Что делает |
|---|---|
| любой текст | вопрос по журналу событий («какие дедлайны на неделе?») |
| `/status` | состояние сессий, статистика за сутки |
| `/recent [N]` | последние важные события |
| `/digest` | дайджест неважного прямо сейчас |
| `/login` | войти заново |
| `/vip слово`, `/mute слово`, `/lists` | всегда срочно / никогда / показать списки |
| `/screen [mail\|teams]` | скриншот вкладки |
| `/use`, `/click X Y`, `/type`, `/key`, `/goto` | ручное управление браузером |
| `/reload`, `/debug` | перезагрузка вкладки / что видит парсер |
## Настройка важности
- `config/rules.md`: правила на человеческом языке. LLM читает файл при каждой оценке, перезапуск не нужен.
- `.env`: `VIP`, `MUTE`, `NOTIFY_MIN_LEVEL`, `QUIET_HOURS`, `DIGEST_TIME`.
Уровни: **3** срочно (со звуком даже в тихие часы), **2** важно, **1** в дайджест, **0** игнор. Если LLM недоступна, бот присылает всё подряд: лучше лишнее, чем пропустить.
## Стоимость
Haiku через OpenRouter: одна пачка событий занимает примерно 1–2 тыс. токенов. При сотне событий в день выходит порядка $1–3 в месяц.
## Тест
```bash
CHROMIUM_PATH=/usr/bin/google-chrome python -m tests.test_e2e
```
Тест поднимает поддельные страницы Outlook и Teams и проверяет перехват уведомлений, дедуп, baseline, VIP/MUTE и устойчивость к «тикающему» времени в карточках.
## Риски
- Автоматизация веб-клиента может противоречить правилам ИТ университета. Худший реалистичный исход: блокировка сессии или вопросы от админов.
- Пароль, если указан в `.env`, хранится на сервере открытым текстом. Можно его не указывать: бот спросит пароль в Telegram при `/login` и сразу удалит сообщение. Пароль держится только в памяти.