181 Commits

Author SHA1 Message Date
deadzilla
4f2e3ec05b fix: заменить list comprehension на generator в stats.py
len([ch for ch in ...]) создавал временный список.
Заменено на sum(1 for ch in ...) — без выделения памяти
под промежуточный список.
2026-07-22 22:29:38 +05:00
deadzilla
8b59ddb0c9 fix: добавить add_done_callback в Scheduler._task
Если _scheduler_loop завершится с неожиданной ошибкой
(не CancelledError), это теперь залогировано через
_on_task_done callback. Штатное завершение через cancel()
пропускается без логов.
2026-07-22 22:28:13 +05:00
deadzilla
81a99aaeab feat: добавить pyproject.toml
Объединены зависимости из requirements.txt и requirements-dev.txt,
настройки pytest из pytest.ini, и базовая конфигурация ruff.
Dockerfile обновлён: установка зависимостей через pyproject.toml.
requirements.txt/pytest.ini сохранены для обратной совместимости.
2026-07-22 22:25:43 +05:00
deadzilla
089a77ce17 Реорганизация ISSUES.md: открытые задачи сверху, завершенные снизу, убраны дубли 2026-07-22 22:14:25 +05:00
deadzilla
311cfa7513 fix: добавить WEATHER_CITY в docker-compose, убрать conftest.py из Docker
- WEATHER_CITY и WEATHER_CACHE_TTL добавлены в docker-compose.yml
  с дефолтными значениями
- conftest.py удалён из Dockerfile — тестовый файл не нужен в production

Файлы: Dockerfile, docker-compose.yml
2026-07-22 22:10:59 +05:00
deadzilla
5e01cc6d8f refactor: вынести дублирующую логику RSS в _format_feed_section()
Блоки обработки articles и posts в !nw были почти идентичны.
Вынесено в _format_feed_section() с параметризацией лейблов,
сообщений об ошибках и заголовков RSS-источников.

Файлы: commands/news.py
2026-07-22 22:07:17 +05:00
deadzilla
ecff77ef66 feat: вынести город в WEATHER_CITY env-переменную
Город больше не захардкожен в коде. Переопределяется через
WEATHER_CITY (по умолчанию "Магнитогорск"). Шаблон изменён на
"Погода: {city}:" для обхода проблемы падежей в русском языке.

Файлы: utils/pogoda.py, .env.example, tests/test_morning_runner.py
2026-07-22 22:05:03 +05:00
deadzilla
1a6b7043ad fix: применить ruff format к 7 файлам
ruff format --check падает на 7 файлах (не 5 как было указано).
Изменения — чистое форматирование: line wrapping, trailing commas, blank lines.
Никаких логических изменений.

Файлы: bot.py, tests/test_commands_news.py, tests/test_commands_pg.py,
tests/test_fetch_weather.py, tests/test_help_command.py,
tests/test_morning_runner.py, utils/pogoda.py
2026-07-22 21:58:55 +05:00
deadzilla
0f3ec2f9bc docs: add WEATHER_CACHE_TTL to config table 2026-07-21 09:46:20 +05:00
deadzilla
4b20645430 fix: align docker-compose env vars with Yandex Weather API
- Add YANDEX_WEATHER_API_KEY (required by bot.py and pogoda.py)
- Rename WEATHER_API_RATE/BURST to YANDEX_WEATHER_API_RATE/BURST
  (matching os.getenv keys in utils/rate_limiter.py)
- Remove unused OPEN_METEO_API_RATE/BURST
- Add WEATHER_CACHE_TTL to .env.example
2026-07-21 09:44:03 +05:00
deadzilla
f7df0f4900 feat(weather): кэширование погоды с TTL 1 час
- fetch_weather кэширует результат на 3600 сек (WEATHER_CACHE_TTL)
- Провал запроса тоже кэшируется — не долбит API повторно
- bypass_cache=True для форсирования свежего запроса
- clear_weather_cache() для сброса кэша
- asyncio.Lock для thread-safety
- 5 новых тестов (cache hit, bypass, failure cache, clear, TTL expiry)
2026-07-21 00:08:09 +05:00
deadzilla
b8b1801f23 fix(weather): исправлены баги в погодном функционале
- JSONDecodeError теперь ловится в fetch_weather (был краш при невалидном JSON от API)
- Порывы ветра больше не теряются при отсутствии base wind (gust fallback)
- Устранено дублирование 'м/с' при порывах + отсутствии направления ветра
- Переименован windspeedKmph → wind_speed_mps (ключ хранил м/с, а не км/ч)
- Обновлены тесты, добавлены 6 новых (gust-only, no-duplication, JSONDecodeError)
2026-07-20 23:56:07 +05:00
deadzilla
517bb4b9fa docs: update README to reflect current project state
- Weather API: wttr.in + Open-Meteo → Yandex Weather API (api.weather.yandex.ru)
- Add required YANDEX_WEATHER_API_KEY env var and config validation section
- Add new env vars: CAT_API_KEY, YANDEX_WEATHER_API_RATE/BURST
- Document new functions: yandex_condition_to_russian(), get_weather_description()
- Document new file: utils/compat.py (Python 3.14+ monkey-patch)
- Update rate limiters: cat_limiter, yandex_weather_limiter, habr_rss_limiter + factory functions
- Remove outdated: fetch_open_meteo(), open_meteo_limiter, weather_limiter (wttr.in)
- Update requirements versions
- Add BotRunner and TextHelpCommand sections
- Note morning digest format: plain text + cat as separate message
2026-07-20 23:38:57 +05:00
deadzilla
48e64c2bc8 Replace wttr.in/Open-Meteo with Yandex Weather API
- Switch from wttr.in + Open-Meteo fallback to Yandex Weather API
- Add YANDEX_WEATHER_API_KEY to .env and config validation
- Enrich weather output: wind gusts, wind direction (Russian)
- Pressure now in mmHg directly from Yandex (no conversion needed)
- Update rate limiter: weather_limiter + open_meteo_limiter → yandex_weather_limiter
- Remove dead code: API_URL_WEATHER, fetch_open_meteo, translate_weather
- Update all tests (271 passed)
2026-07-20 23:31:11 +05:00
deadzilla
ee04f67506 заменён AGENTS.md на глобальный шаблон Global Instructions
Проектные инструкции удалены, заменены на универсальные
правила для ассистента (priorities, boundaries, workflow, testing, safety)
2026-07-20 21:58:17 +05:00
deadzilla
cc618af445 добавлены открытые задачи в ISSUES.md по результатам код-ревью
- высокий: ruff format на 5 файлах
- средний: pyproject.toml, дублирование в news.py, хардкод города,
  Scheduler без callback, неверный тест HTTP-ошибки
- низкий: list comprehension в stats.py, дублирование в TextHelpCommand,
  try/except в morning.py, файл nul
2026-07-20 21:55:38 +05:00
deadzilla
0d98d31e61 ISSUES.md: задача Dockerfile+tests отмечена как отклонена (Docker — production) 2026-07-14 22:54:47 +05:00
deadzilla
60e7faca5f Откат: тесты и pytest удалены из Dockerfile (Docker — production-окружение) 2026-07-14 22:53:57 +05:00
deadzilla
f45beef888 ISSUES.md: отмечены все 5 задач низкого приоритета как выполненные 2026-07-14 22:51:10 +05:00
deadzilla
cd014b171f rate_limiter: добавлен комментарий, поясняющий дизайн глобальных синглтонов и factory-функций 2026-07-14 22:50:45 +05:00
deadzilla
d85f28f042 Удалены избыточные проверки ctx в on_command_error (ctx всегда передан discord.py) 2026-07-14 22:48:30 +05:00
deadzilla
bb9e50fb05 Убраны приватные атрибуты с объекта discord.py Bot: START_TIME вынесен на уровень модуля, _scheduler удалён (не использовался) 2026-07-14 22:46:57 +05:00
deadzilla
5a65be97d9 Dockerfile: добавлено копирование tests/ и установка pytest для отладки в контейнере 2026-07-14 22:43:19 +05:00
deadzilla
29313530f3 Удалены избыточные @pytest.mark.asyncio (asyncio_mode = auto в pytest.ini) 2026-07-14 22:41:10 +05:00
deadzilla
003bd0552f Отмечены все 4 задачи среднего уровня как выполненные в ISSUES.md 2026-07-14 22:27:59 +05:00
deadzilla
3888c3cd01 fetch_cat() передаёт x-api-key при наличии CAT_API_KEY в окружении 2026-07-14 22:27:30 +05:00
deadzilla
0d5d8dbe7b Удалён лишний __init__ в Pg; API_URL_WEATHER используется напрямую 2026-07-14 22:23:38 +05:00
deadzilla
bb9f291623 Scheduler.__init__ больше не создаёт task синхронно; start() стал async-методом 2026-07-14 22:20:45 +05:00
deadzilla
66b16e95f4 Вынесен импорт fromstring из fetch_rss на уровень модуля 2026-07-14 22:15:14 +05:00
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
deadzilla
250452ad60 Добавлены открытые задачи после кодревью (12 issue) 2026-07-12 23:39:56 +05:00
deadzilla
90547df975 docs: обновлён ISSUES.md — все задачи (средний + низкий) перенесены в исправленные 2026-07-12 00:18:43 +05:00
deadzilla
1ab3205333 fix: format_articles(None) возвращает graceful fallback вместо TypeError 2026-07-12 00:11:54 +05:00
deadzilla
f825be866b chore: удалена закомментированная устаревшая строка теста pressure_to_mmhg(0) 2026-07-12 00:09:21 +05:00
deadzilla
fb42a90bec fix: requirements.txt использует ~= (compatible release) вместо >= для предсказуемости версий 2026-07-12 00:08:49 +05:00
deadzilla
3982d26c95 fix: Dockerfile копирует conftest.py для запуска тестов в контейнере 2026-07-12 00:08:29 +05:00
deadzilla
5eb4184d63 refactor: RateLimiter принимает _time_func для детерминированных тестов без зависимости от реального времени 2026-07-12 00:08:13 +05:00
deadzilla
3a2c388adf refactor: вынесен monkey-patch asyncio.iscoroutinefunction в utils/compat.py 2026-07-12 00:05:46 +05:00
deadzilla
88ed1a6aa1 docs: обновлён ISSUES.md — 5 задач среднего приоритета перенесены в исправленные 2026-07-12 00:04:10 +05:00
deadzilla
6b0a6cd8a6 refactor: pressure_to_mmhg заменяет Any на float | int | str | None 2026-07-12 00:03:39 +05:00
deadzilla
d94b9c16ab fix: translate_weather обрезает пробелы перед проверкой на пустоту 2026-07-12 00:02:13 +05:00
deadzilla
efee713301 fix: TextHelpCommand показывает standalone-команды (без cog) если они не hidden 2026-07-11 23:59:41 +05:00
deadzilla
49cb1a430b perf: wmo_to_russian использует модульную константу _WMO_MAPPING вместо создания dict при каждом вызове 2026-07-11 23:56:54 +05:00
deadzilla
b22b02d65e fix: _parse_date валидирует формат даты через regex вместо возврата мусора 2026-07-11 23:55:18 +05:00
deadzilla
e957446063 docs: обновлён ISSUES.md — 3 задачи высокого приоритета перенесены в исправленные 2026-07-11 23:50:40 +05:00
deadzilla
048b9a3a91 fix: format_weather_data_for_console заменяет None на эм-дэш вместо вывода 'None' в текст 2026-07-11 23:50:05 +05:00
deadzilla
bc37362959 fix: !nw использует asyncio.gather() для параллельной загрузки RSS вместо последовательной 2026-07-11 23:47:00 +05:00