- Добавить экспоненциальную задержку между попытками retry (1с, 2с, 4с) в pogoda.py - Заменить time.sleep на await asyncio.sleep для неблокирующих ожиданий - Обернуть requests.get в asyncio.to_thread для предотвращения блокировки event loop (news.py, cat.py, pogoda.py) - Добавить правило AGENTS.md: не использовать эмодзи - Добавить ISSUES.md с фиксацией проблем проекта
79 lines
6.0 KiB
Markdown
79 lines
6.0 KiB
Markdown
# Issues — список проблем проекта
|
||
|
||
> Состояние на: 2026-05-26
|
||
|
||
---
|
||
|
||
## 🔴 Критические
|
||
|
||
### 1. Retry без задержки между попытками ✅ РЕШЕНО
|
||
- **Где:** `commands/pogoda.py`, `console_commands/pogoda.py`
|
||
- **Проблема:** Цикл `for attempt in range(3)` не содержит `time.sleep()`. Все 3 попытки выполняются мгновенно, что бессмысленно при временных сетевых сбоях.
|
||
- **AGENTS.md обещает:** "Retry: 3 попытки с экспоненциальной задержкой" — но задержки нет.
|
||
- **Решение:** Добавить `time.sleep(2 ** attempt)` внутри цикла retry.
|
||
- **Статус:** Исправлено. Добавлена экспоненциальная задержка: 2 сек, 4 сек между попытками.
|
||
|
||
### 2. Блокировка event loop в async-методе ✅ РЕШЕНО
|
||
- **Где:** `commands/news.py`, `commands/cat.py`, `commands/pogoda.py`
|
||
- **Проблема:** Асинхронные методы вызывали синхронный `requests.get()`, блокируя весь event loop.
|
||
- **Решение:** Обернуть `requests.get()` в `await asyncio.to_thread()` и заменить `time.sleep()` на `await asyncio.sleep()`.
|
||
- **Статус:** Исправлено. В `news.py`, `cat.py`, `pogoda.py` все HTTP-запросы выполняются в отдельных потоках, а ожидания — неблокирующие.
|
||
|
||
---
|
||
|
||
## 🟡 Средние
|
||
|
||
### 3. Дублирование кода между Discord и console командами
|
||
- **Где:** `console_commands/pogoda.py` и `console_commands/news.py`
|
||
- **Проблема:** Логика погоды и новостей полностью продублирована. Изменения нужно вносить в два места.
|
||
- **Решение:** Вынести общую логику в `utils/` (например, `utils/weather.py`, `utils/rss.py`) и использовать её из обоих мест.
|
||
|
||
### 4. `from datetime import datetime` внутри метода
|
||
- **Где:** `commands/news.py` → `_format_and_send()`, строки 56 и 72
|
||
- **Проблема:** Импорт внутри метода — антипаттерн. Замедляет выполнение, нарушает PEP 8.
|
||
- **Решение:** Перенести `from datetime import datetime` в начало файла.
|
||
|
||
### 5. Консольная команда `cat` — заглушка
|
||
- **Где:** `console_commands/cat.py`
|
||
- **Проблема:** Функция просто печатает `"🐱 тут должен быть котик"`. Заглушка видна пользователю.
|
||
- **Решение:** Либо реализовать (вызвать API котиков), либо убрать из `ALL_CONSOLE_COMMANDS` и `README.md`.
|
||
|
||
### 6. `on_command_error` не сообщает пользователю об ошибке
|
||
- **Где:** `bot.py` → `on_command_error()`
|
||
- **Проблема:** Ошибки команд просто печатаются в `stdout`. Пользователь в чате не видит, что команда выполнилась с ошибкой.
|
||
- **Решение:** Добавить `await ctx.send("Произошла ошибка при выполнении команды.")` или отправить embed с деталями (если `ctx` не None).
|
||
|
||
### 7. Нет `.gitignore`
|
||
- **Где:** проект (файл отсутствует)
|
||
- **Проблема:** Нет явного `.gitignore`. `.env` может случайно попасть в репозиторий, хотя AGENTS.md говорит "`.env` в `.gitignore`".
|
||
- **Решение:** Создать `.gitignore` с правилами для Python (`__pycache__/`, `*.pyc`, `.env`, `venv/`, `*.egg-info/`).
|
||
|
||
### 8. `requests` без Session — нет переиспользования соединений
|
||
- **Где:** все файлы (`pogoda.py`, `news.py`)
|
||
- **Проблема:** Каждый `requests.get()` создаёт новое TCP-соединение. Для частых запросов это расточительно.
|
||
- **Решение:** Создать `requests.Session()` и использовать `session.get()`.
|
||
|
||
---
|
||
|
||
## 🟢 Малые улучшения
|
||
|
||
### 9. Linear search в `_translate_weather`
|
||
- **Где:** `commands/pogoda.py`, `console_commands/pogoda.py`
|
||
- **Проблема:** Метод `_translate_weather()` перебирает весь словарь `mapping` циклом `for key, value in mapping.items()`. При большом словаре — неэффективно.
|
||
- **Решение:** Сортировать ключи по длине (убывание) и использовать `re` или `any(key.lower() in text.lower() for key in sorted_keys)`.
|
||
|
||
### 10. Нет `__all__` в `__init__.py`
|
||
- **Где:** `commands/__init__.py`, `console_commands/__init__.py`
|
||
- **Проблема:** Нет явного экспорта публичного API модулей.
|
||
- **Решение:** Добавить `__all__ = ["ALL_COMMANDS"]` / `__all__ = ["ALL_CONSOLE_COMMANDS"]`.
|
||
|
||
### 11. Жёстко заданные URL в разных файлах
|
||
- **Где:** `commands/news.py` и `console_commands/news.py`
|
||
- **Проблема:** Константы `RSS_URL_ARTICLES` и `RSS_URL_POSTS` продублированы.
|
||
- **Решение:** Вынести в `config.py` и импортировать оттуда.
|
||
|
||
### 12. Потенциальная гонка при остановке бота
|
||
- **Где:** `bot.py`
|
||
- **Проблема:** `stop_event.set()` и `bot.close()` вызываются из `console_input()`, `KeyboardInterrupt` и `console_commands/stop.py`. Возможна гонка.
|
||
- **Решение:** Добавить флаг `is_stopping` или использовать `asyncio.Lock`.
|