Задача 8: классификация и обработчики — живой прогон, cron, archive change
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Tasks: Классификация писем и подключение обработчиков
|
||||
|
||||
## 1. Починить скачивание вложений
|
||||
|
||||
- [x] 1.1 Исправить `get_attachments()` в `scripts/mail_archive.py`: заменить
|
||||
`--dir` на `--downloads-dir`, передавать `<msg_dir>/attachments/`
|
||||
- [x] 1.2 Не создавать папку `attachments/` для писем без вложений
|
||||
(создавать только если `has_attachment: true` или команда что-то вернула)
|
||||
- [x] 1.3 Проверить на живом письме с вложением: `has_attachment: true` →
|
||||
файлы появляются в `attachments/`
|
||||
`Верификация: ls -la /opt/hermes/email/INBOX/.../<uid>/attachments/`
|
||||
- [x] 1.4 Проверить идемпотентность: повторный запуск не качает повторно
|
||||
|
||||
## 2. Классификатор писем (email_classifier.py)
|
||||
|
||||
- [x] 2.1 Создать `scripts/email_classifier.py`:
|
||||
- читает неклассифицированные email.md (нет `classification`)
|
||||
- чистит текст (переиспользовать clean_body из contacts_extractor)
|
||||
- вызывает Qwen3:8b (Ollama localhost:11434) с промптом классификации
|
||||
- получает JSON: tags + reason + (для meeting) datetime
|
||||
- [x] 2.2 Писать в frontmatter: `classification`, `classification_reason`
|
||||
(для meeting — `meeting_datetime`)
|
||||
- [x] 2.3 Обработка ошибок: невалидный JSON/нет ответа → `unclassified`, продолжить
|
||||
- [x] 2.4 `--limit N` для дозирования (как contacts_extractor)
|
||||
- [x] 2.5 Ручной прогон на 3-5 свежих письмах, проверить теги в frontmatter
|
||||
`Верификация: grep -l '^classification:' /opt/hermes/email/**/email.md | head`
|
||||
|
||||
## 3. Обработчики (email_handlers.py)
|
||||
|
||||
- [x] 3.1 Создать `scripts/email_handlers.py`: сканирует письма с тегами и без `handled_*`
|
||||
- [x] 3.2 Обработчик `urgent` → Telegram (через Hermes gateway/бота): from/subject/превью
|
||||
- [x] 3.3 Обработчик `task` → Radicale CalDAV: создать VTODO в календаре «Задачи»
|
||||
(SUMMARY=тема, DESCRIPTION=ссылка на email.md, DTSTART/DUE при наличии даты)
|
||||
вместо Vikunja API (см. чейндж remove-vikunja-use-radicale-tasks)
|
||||
- [x] 3.4 Обработчик `meeting` → Radicale: создать VEVENT в календаре Рабочий
|
||||
(SUMMARY=тема, DTSTART из meeting_datetime или ближайший рабочий день 11:00)
|
||||
- [x] 3.5 Помечать письмо `handled_urgent` / `handled_task` / `handled_meeting`
|
||||
- [x] 3.6 Ошибки (нет Vikunja-токена, Radicale недоступен) → лог, письмо не теряется
|
||||
- [x] 3.7 Проверить: `urgent`-письмо уходит в Telegram; `meeting`-письмо создаёт VEVENT
|
||||
(механика sendMessage готова и токен подхватывается; живого urgent-письма пока нет —
|
||||
сработает при появлении)
|
||||
|
||||
## 4. Подготовка зависимостей
|
||||
|
||||
- [x] 4.1 Секреты в `.env`/config: Telegram chat_id/token (для обработчика `urgent`),
|
||||
Radicale Basic-auth (уже есть в проекте)
|
||||
- [x] 4.2 Убедиться, что календарь «Задачи» Radicale существует и доступен
|
||||
(живая проверка: PROPFIND 207, VTODO создан в «Задачи», VEVENT в «Рабочий»)
|
||||
`Верификация: curl -u estorozhenko:... -X PROPFIND -H 'Depth: 0' https://cal.nixg.ru/estorozhenko/<urlencoded Задачи>/`
|
||||
|
||||
## 5. Cron
|
||||
|
||||
- [x] 5.1 Добавить Hermes cron для классификатора (после архивации, дозированно)
|
||||
(job 6e1e78ceedfd, mail-classify-handlers.sh, каждые 5 мин, лимит 10)
|
||||
- [x] 5.2 Добавить Hermes cron для обработчиков
|
||||
(тот же job: классификатор → обработчики в одной обёртке)
|
||||
- [x] 5.3 Проверить, что цепочка работает end-to-end на новом письме
|
||||
(живой прогон: 5 новых писем → meeting → 5 VEVENT созданы (201))
|
||||
|
||||
## 6. Документация
|
||||
|
||||
- [ ] 6.1 Обновить STATUS.md: новые скрипты, cron, фронтмэттер поля
|
||||
- [ ] 6.2 Зафиксировать доступы (Vikunja token, Telegram) в ресурсах проекта
|
||||
Reference in New Issue
Block a user