Files
memoir_bot/current-task.md
2026-07-06 13:30:48 +03:00

73 lines
5.3 KiB
Markdown
Raw Permalink 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.
# План изменений: расписание напоминаний
## Цели
1. Добавить расписание для напоминаний: бот должен писать только в явно разрешенные часы.
2. По умолчанию разрешенное окно: с 07:00 до 23:00 по МСК.
3. Если пользователь сам написал заметку, следующий reminder должен быть отложен минимум на 1 час.
## План
### 1. Расширить конфиг
- Добавить переменные в `.env.example` и `README.md`:
- `REMINDER_START_HOUR`
- `REMINDER_END_HOUR`
- `REMINDER_TIMEZONE`
- Значения по умолчанию:
- `REMINDER_START_HOUR=7`
- `REMINDER_END_HOUR=23`
- `REMINDER_TIMEZONE=Europe/Moscow`
- В `config.py` парсить часы как `int`, timezone через `zoneinfo.ZoneInfo`.
### 2. Изменить модель напоминаний
- Сейчас `send_reminders()` просто спит случайное число секунд между min/max.
- Нужно рассчитывать следующий момент отправки с учетом:
- разрешенного окна времени;
- случайного интервала `REMINDER_MIN_HOURS` / `REMINDER_MAX_HOURS`;
- timezone;
- ночного периода, когда отправка запрещена.
### 3. Добавить сброс после ручной заметки
- В `main.py` после успешного `journal.append(...)` сообщать планировщику, что пользователь сам написал заметку.
- Простой вариант: передать в `send_reminders()` общий объект состояния, например `ReminderScheduler` или `ReminderState`.
- В состоянии хранить `last_manual_entry_at`.
- При ручной записи следующий reminder должен быть не раньше `last_manual_entry_at + 1 hour`.
### 4. Сделать отдельную логику планирования
- Минимально оставить `send_reminders()` в `modules/reminders.py`, но добавить функции:
- `is_allowed_time(now, start_hour, end_hour)`
- `next_window_start(now, start_hour, timezone)`
- `calculate_next_reminder(...)`
- Не усложнять классами без необходимости, но небольшой объект состояния между handler и background task может быть оправдан.
### 5. Учесть edge cases
- Если сейчас ночь, следующий reminder переносится на 07:00 МСК.
- Если случайный интервал попадает за 23:00, reminder переносится на следующее 07:00.
- Если пользователь написал заметку в 22:30, минимальная задержка до 23:30, но окно уже закрыто, значит следующий reminder не раньше 07:00 следующего дня.
- Если пользователь написал ночью, reminder не раньше max(`+1 hour`, ближайшее 07:00).
- Если `REMINDER_START_HOUR >= REMINDER_END_HOUR`, лучше сразу падать с понятной ошибкой, чтобы не поддерживать ночные окна.
### 6. Обновить документацию
- README на русском: описать новое окно отправки.
- `.env.example`: добавить новые переменные.
- При необходимости обновить `AGENTS.md`, чтобы зафиксировать новые env vars и правило про timezone.
### 7. Проверка
- Запустить `uv run python -m compileall main.py config.py modules`.
- Если добавятся чистые функции расчета времени, можно добавить тесты позже, но сейчас отдельной тестовой инфраструктуры нет.
## Лог реализации
- Шаг 1: добавлены настройки `REMINDER_START_HOUR`, `REMINDER_END_HOUR`, `REMINDER_TIMEZONE` в `config.py`; часы валидируются как диапазон 0-23, окно должно быть start < end.
- Шаг 2: в `modules/reminders.py` добавлен минимальный `ReminderState`, расчет следующего reminder с учетом окна времени и пробуждение sleep через `asyncio.Event` при ручной записи.
- Шаг 3: `main.py` создает `ReminderState`, передает его в `send_reminders()` и вызывает `mark_manual_entry()` после успешного сохранения заметки.
- Шаг 4: обновлены `.env.example`, `README.md` и `AGENTS.md` с новыми настройками окна напоминаний, timezone и правилом задержки после ручной заметки.
- Проверка: `uv run python -m compileall main.py config.py modules` прошла успешно; `uv` создал локальную `.venv`, она игнорируется `.gitignore`.