Compare commits

...

4 Commits

Author SHA1 Message Date
deadzilla
d4b457f94e docs: помечены закрытые критические задачи в ISSUES.md 2026-07-14 22:04:38 +05:00
deadzilla
3bea7abaea fix: translate_weather() проверяет точное совпадение перед substring
Точное совпадение (case-insensitive) теперь имеет приоритет над
substring-matching, что исключает ложные совпадения вида
'Heavy rain' внутри 'Heavy rain shower'.
2026-07-14 22:03:18 +05:00
deadzilla
0c6e10a482 fix: setup_logging() вызывается до первого logger.info()
Первый лог-сообщение '=== Запуск Discord бота ===' больше не теряется,
так как логгер настроен до его вывода.
2026-07-14 22:03:13 +05:00
deadzilla
9b04bc0c93 fix: setup_logging() больше не создаёт дублирующиеся handlers
Добавлен root.handlers.clear() перед добавлением новых хендлеров.
Решает проблему накопления StreamHandler/RotatingFileHandler при
повторных вызовах setup_logging().
2026-07-14 22:03:08 +05:00
4 changed files with 19 additions and 5 deletions

View File

@ -39,6 +39,10 @@
- [x] **`requirements.txt` без пиннинга версий** — `>=` заменён на `~=` (compatible release)
- [x] **Закомментированный тест `pressure_to_mmhg(0)`** — удалена устаревшая закомментированная строка
- [x] **`format_articles(None)` бросает `TypeError`** — добавлена валидация `None`, graceful fallback с сообщением
- [x] **`setup_logging()` создаёт дублирующиеся handlers** — добавлен `root.handlers.clear()` (`utils/logger.py`)
- [x] **Первый `logger.info()` теряется**`setup_logging()` вызывается до первого лога (`bot.py`)
- [x] **`translate_weather()` уязвим к ложным substring-совпадениям** — точное совпадение приоритизируется (`utils/pogoda.py`)
---
@ -46,9 +50,9 @@
### Критические
- [ ] **`setup_logging()` создаёт дублирующиеся handlers** — каждый вызов добавляет новые `StreamHandler` и `RotatingFileHandler` к root-логгеру без проверки (`utils/logger.py`, строки 30-39)
- [ ] **Первый `logger.info()` теряется**`"=== Запуск Discord бота ==="` вызван до `setup_logging()`, у root-логгера нет handlers (`bot.py`, строка 196)
- [ ] **`translate_weather()` уязвим к ложным substring-совпадениям** — `if key.lower() in en_lower` может вернуть неверный перевод (например, `"Heavy rain"` совпадёт в `"Heavy rain shower"` раньше, чем точный ключ) (`utils/pogoda.py`)
- [x] ~~**`setup_logging()` создаёт дублирующиеся handlers**~~ — добавлен `root.handlers.clear()` перед добавлением новых хендлеров (`utils/logger.py`)
- [x] ~~**Первый `logger.info()` теряется**~~`setup_logging()` перемещён до первого `logger.info()` (`bot.py`)
- [x] ~~**`translate_weather()` уязвим к ложным substring-совпадениям**~~ — добавлена проверка точного совпадения (case-insensitive) перед substring-matching (`utils/pogoda.py`)
### Средние

2
bot.py
View File

@ -273,8 +273,8 @@ def _validate_config() -> None:
if __name__ == "__main__":
from utils.logger import setup_logging
logger.info("=== Запуск Discord бота ===")
setup_logging()
logger.info("=== Запуск Discord бота ===")
_validate_config()

View File

@ -33,6 +33,7 @@ def setup_logging() -> logging.Logger:
root = logging.getLogger()
root.setLevel(level)
root.handlers.clear()
root.addHandler(console)
# File handler — logs/bot.log с ротацией по размеру (5 МБ, 5 бэкапов)

View File

@ -174,10 +174,19 @@ _WEATHER_MAPPING = [
def translate_weather(en: Optional[str]) -> str:
if not en or not en.strip():
return ""
en_lower = en.strip().lower()
en_stripped = en.strip()
en_lower = en_stripped.lower()
# Сначала проверяем точное совпадение (приоритет над substring)
for key, value in _WEATHER_MAPPING:
if key.lower() == en_lower:
return value
# Fallback: substring-matching (отсортировано по убыванию длины ключа)
for key, value in _WEATHER_MAPPING:
if key.lower() in en_lower:
return value
return en