Compare commits
No commits in common. "1000f8ea0b4da0ad46efbe6ba78e121f652fc308" and "da84ecacdceca7c6cc7347736353dc3ce8430d58" have entirely different histories.
1000f8ea0b
...
da84ecacdc
5
.gitignore
vendored
5
.gitignore
vendored
@ -26,8 +26,3 @@ Thumbs.db
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Coverage reports
|
||||
.coverage
|
||||
.coverage.*
|
||||
htmlcov/
|
||||
|
||||
146
AGENTS.md
146
AGENTS.md
@ -1,53 +1,115 @@
|
||||
---
|
||||
name: discord-bot-dev
|
||||
description: Помощник по разработке Discord-бота на discord.py
|
||||
tools: read,write,grep,bash,edit
|
||||
thinking: high
|
||||
model_requirements:
|
||||
context_window: 32000
|
||||
temperature: 0.3
|
||||
---
|
||||
# AGENTS.md
|
||||
|
||||
# Системный промпт
|
||||
## Проект
|
||||
Discord-бот на Python (discord.py)
|
||||
|
||||
Ты — ассистент по разработке Discord-бота на Python с использованием библиотеки discord.py.
|
||||
## Запуск
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
python bot.py
|
||||
```
|
||||
## Токен
|
||||
Токен бота хранится в `.env` (переменная `DISCORD_TOKEN`). Получи токен на [Discord Developer Portal](https://discord.com/developers/applications). Шаблон в `.env.example`.
|
||||
|
||||
## Твоя роль
|
||||
Ты помогаешь разрабатывать, отлаживать и поддерживать Discord-бота. Ты следуешь строгим правилам взаимодействия с пользователем и кодом.
|
||||
## Конвенции
|
||||
- Используй TODO-списки для каждого запроса с несколькими шагами.
|
||||
- Пиши комментарии на русском.
|
||||
- Обработка ошибок: try/except для всех внешних вызовов (API, БД, файловая система).
|
||||
- **Никогда не используй эмодзи в тексте или выводах.**
|
||||
- **До внесения любых изменений в код или файлы предоставь детальное описание всех планируемых изменений и получи явное согласие пользователя. Без согласования изменения не вносить.**
|
||||
- **Все git-коммиты согласовывать с пользователем перед созданием.**
|
||||
- **Все сообщения git-коммитов писать на русском языке.**
|
||||
- **Думать и размышляй на английском, а отвечать пользователю на русском.**
|
||||
|
||||
## Основные правила работы
|
||||
## Команды
|
||||
|
||||
### Коммуникация
|
||||
- **Думай и размышляй на английском языке** (внутренний монолог)
|
||||
- **Отвечай пользователю на русском языке**
|
||||
- **Никогда не используй эмодзи** в тексте или выводах
|
||||
- Будь вежливым и профессиональным
|
||||
| Команда | Описание | Формат вывода |
|
||||
|---------|----------|---------------|
|
||||
| `!pg` | Погода в Магнитогорске | Температура, ощущается, описание, влажность, ветер, давление |
|
||||
| `!nw` | Топ-5 статей и топ-5 новостей AI с Habr | Два блока: статьи и новости |
|
||||
| `!morning` | Погода + топ-5 статей + топ-5 новостей + котик | Embed: котик thumbnail, погода, статьи, новости |
|
||||
| `!cat` | Случайный котик | Embed с изображением |
|
||||
| `!msg <текст>` | Повторяет текст | Текст |
|
||||
|
||||
### Работа с кодом и файлами
|
||||
- **До внесения любых изменений в код или файлы предоставь детальное описание всех планируемых изменений**
|
||||
- **Получи явное согласие пользователя перед внесением изменений**
|
||||
- Без согласования изменения не вносить
|
||||
- Используй TODO-списки для каждого запроса, который требует нескольких шагов
|
||||
- Пиши комментарии на русском языке
|
||||
## Планировщик
|
||||
|
||||
### Git и контроль версий
|
||||
- **Все git-коммиты согласовывать с пользователем перед созданием**
|
||||
- **Сообщения git-коммитов писать на русском языке**
|
||||
- Не создавать коммиты без явного подтверждения
|
||||
- Ежедневный утренний дайджест (`!morning`) запускается автоматически в 07:00
|
||||
- Время задаётся в `.env` переменной `MORNING_TIME` (формат `ЧЧ:ММ`)
|
||||
- Реализован через `discord.ext.tasks.loop`
|
||||
- Отправляет дайджест в первый канал, где бот имеет права
|
||||
- Код в `utils/morning_runner.py`
|
||||
|
||||
### Обработка ошибок
|
||||
- Используй `try/except` для всех внешних вызовов:
|
||||
- API запросы
|
||||
- Базы данных
|
||||
- Файловая система
|
||||
- Логируй ошибки с понятными сообщениями
|
||||
## Структура проекта
|
||||
|
||||
## Технические требования к коду
|
||||
| Каталог | Назначение |
|
||||
|---------|------------|
|
||||
| `commands/` | Discord-команды (Cogs) |
|
||||
| `utils/` | Утилиты (API-клиенты, конвертации) |
|
||||
| `console_commands/` | Консольные команды (для терминала) |
|
||||
| `bot.py` | Точка входа, загрузка Cogs, обработка ошибок |
|
||||
|
||||
### Стиль и конвенции
|
||||
- Используй type hints для всех функций
|
||||
- Документируй публичные методы через docstrings
|
||||
- Следуй PEP 8
|
||||
- Используй f-строки вместо конкатенации
|
||||
## API и внешние сервисы
|
||||
|
||||
### Структура проекта
|
||||
### Погода (!pg, !morning)
|
||||
- **Основной**: `wttr.in/Magnitogorsk` (бесплатный, без ключа)
|
||||
- **Fallback**: `api.open-meteo.com` (бесплатный, без ключа)
|
||||
- Retry: 3 попытки с экспоненциальной задержкой при SSL/Connection/Timeout ошибках
|
||||
- Fallback срабатывает автоматически при неуспешных попытках
|
||||
- WMO weather codes → русский перевод в `wmo_to_russian()`
|
||||
|
||||
### Конвертации
|
||||
- Давление: hPa → мм рт. ст. (`* 0.750062`)
|
||||
- Ветер: км/ч → м/с (`/ 3.6`)
|
||||
- Погодные описания: английский → русский (`translate_weather()`)
|
||||
|
||||
### RSS-ленты Habr (!nw, !morning)
|
||||
| Тип | URL |
|
||||
|-----|-----|
|
||||
| Статьи | `https://habr.com/ru/rss/hubs/artificial_intelligence/articles/top/daily/?fl=ru` |
|
||||
| Новости | `https://habr.com/ru/rss/hubs/artificial_intelligence/news/top/daily/?fl=ru` |
|
||||
|
||||
Парсятся RSS 2.0 / Atom, извлекаются title, pubDate, creator, category, guid.
|
||||
|
||||
### Cat API (!cat, !morning)
|
||||
- **URL**: `https://api.thecatapi.com/v1/images/search`
|
||||
- Возвращает JSON: `[{"url": "..."}]`
|
||||
- Используется для случайных изображений котиков
|
||||
|
||||
## Конфигурация
|
||||
| Переменная | Описание | Где взять |
|
||||
|------------|----------|-----------|
|
||||
| `DISCORD_TOKEN` | Токен бота | Discord Developer Portal |
|
||||
| `MORNING_TIME` | Время запуска утреннего дайджеста | `.env` (формат `ЧЧ:ММ`, по умолчанию `07:00`) |
|
||||
| `MORNING_CHANNEL_ID` | ID канала для утреннего дайджеста | Правый клик по каналу → Копировать ID |
|
||||
|
||||
## Зависимости
|
||||
```txt
|
||||
discord.py>=2.3.2
|
||||
python-dotenv>=1.0.0
|
||||
requests>=2.31.0
|
||||
```
|
||||
|
||||
## Структура данных погоды
|
||||
Команда `!pg` возвращает:
|
||||
```
|
||||
Температура: X°C (ощущается как Y°C)
|
||||
Описание: Z
|
||||
Влажность: X%
|
||||
Ветер: X м/с
|
||||
Давление: X мм рт. ст.
|
||||
```
|
||||
|
||||
## Консольные команды
|
||||
Запускаются через терминал при старте бота. Список выводится при запуске.
|
||||
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| `pogoda` | Вывести погоду в Магнитогорск |
|
||||
| `news` | Вывести топ-5 статей AI с Habr |
|
||||
| `morning` | Вывести погоду, топ-5 статей и котик |
|
||||
| `cat` | Заглушка |
|
||||
| `stop` | Остановить бота |
|
||||
|
||||
## Безопасность
|
||||
- `.env` в `.gitignore` — токен никогда не должен попадать в репозиторий.
|
||||
- Используй `.env.example` как шаблон.
|
||||
|
||||
46
ISSUES.md
Normal file
46
ISSUES.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Tasks — список задач проекта
|
||||
|
||||
> Состояние на: 2026-05-26
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Критические
|
||||
|
||||
### 1. Убрать эмодзи из `console_commands/cat.py`
|
||||
- [x] Заменить `print("🐱 тут должен быть котик")` на `print("Заглушка: тут должен быть котик")`
|
||||
|
||||
---
|
||||
|
||||
## 🟡 Средние
|
||||
|
||||
### 2. Убрать пустой embed в `!morning` при всех ошибках
|
||||
- [ ] `commands/morning.py`: добавить fallback-сообщение в `description_lines`, если все API вернули `None`
|
||||
- [ ] Проверить, что `embed.description` никогда не пустой
|
||||
|
||||
### 3. Убрать дублирование парсинга погоды
|
||||
- [ ] `console_commands/pogoda.py`: вынести форматирование результата в `utils/pogoda.py` как `format_weather_data()`
|
||||
- [ ] `console_commands/morning.py`: использовать `format_weather_data()` вместо inline-парсинга
|
||||
- [ ] `commands/morning.py`: использовать `format_weather_data()` вместо inline-парсинга
|
||||
|
||||
### 6. Вынести `self.api_url` в константу класса
|
||||
- [ ] `commands/pogoda.py`: заменить `self.api_url = ...` на `API_URL = "..."` на уровне класса
|
||||
- [ ] `commands/morning.py`: аналогично
|
||||
- [ ] `console_commands/pogoda.py`: вынести URL в `utils/pogoda.py` как константу
|
||||
|
||||
---
|
||||
|
||||
## 🟢 Малые улучшения
|
||||
|
||||
### 4. Вынести `api_url` в константу
|
||||
- [ ] `commands/pogoda.py`: заменить `self.api_url = ...` на `API_URL = "..."` на уровне класса
|
||||
- [ ] `commands/morning.py`: аналогично
|
||||
- [ ] `console_commands/pogoda.py`: вынести URL в `utils/pogoda.py` как константу
|
||||
|
||||
### 5. Добавить `__all__` в `__init__.py`
|
||||
- [ ] `commands/__init__.py`: `__all__ = ["ALL_COMMANDS"]`
|
||||
- [ ] `console_commands/__init__.py`: `__all__ = ["ALL_CONSOLE_COMMANDS"]`
|
||||
- [ ] `utils/__init__.py`: добавить `__all__` с основными функциями
|
||||
|
||||
### 6. Добавить `raise_exception=True` в `bot.run()`
|
||||
- [ ] `bot.py`: добавить `raise_exception=True` для видимого падения при ошибках токена/сети
|
||||
- [ ] Добавить логирование в `KeyboardInterrupt` блок
|
||||
52
README.md
52
README.md
@ -2,10 +2,6 @@
|
||||
|
||||
Discord-бот для Магнитогорска. Команды погоды, новостей, котиков и утреннего дайджеста.
|
||||
|
||||
## 📖 Документация
|
||||
|
||||
Основной документ проекта — [`AGENTS.md`](./AGENTS.md). Содержит детальные инструкции по архитектуре, командам и работе с ботом.
|
||||
|
||||
## Установка
|
||||
|
||||
```bash
|
||||
@ -38,8 +34,8 @@ python bot.py
|
||||
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| `!pg` | Прогноз погоды для Магнитогорска |
|
||||
| `!nw` | Топ-5 свежих статей по AI с Habr |
|
||||
| `!pogoda` | Прогноз погоды для Магнитогорска |
|
||||
| `!news` | Топ-5 свежих статей по AI с Habr |
|
||||
| `!morning` | Погода + топ-5 статей + топ-5 новостей + котик (утренний дайджест) |
|
||||
| `!cat` | Случайный котик |
|
||||
| `!msg <текст>` | Повторить текст в чате |
|
||||
@ -61,7 +57,7 @@ bot.py # Точка входа, инициализация бо
|
||||
commands/ # Discord команды (cogs)
|
||||
__init__.py # ALL_COMMANDS — явные импорты
|
||||
pg.py # !pg — погода с retry + fallback
|
||||
news.py # !nw — новости с Habr
|
||||
news.py # !news — новости с Habr
|
||||
cat.py # !cat — случайный котик
|
||||
morning.py # !morning — утренний дайджест
|
||||
console_commands/ # Консольные команды
|
||||
@ -72,18 +68,16 @@ console_commands/ # Консольные команды
|
||||
morning.py # morning — утренний дайджест в терминале
|
||||
cat.py # cat — вывод URL котика
|
||||
utils/ # Утилиты (API-клиенты, конвертации)
|
||||
pogoda.py # fetch_weather(), fetch_open_meteo(), wmo_to_russian(), translate_weather(), pressure_to_mmhg(), format_weather_data_for_console()
|
||||
pogoda.py # fetch_weather(), fetch_open_meteo(), wmo_to_russian(), translate_weather(), pressure_to_mmhg()
|
||||
news.py # fetch_rss(), format_articles(), truncate_title(), parse_date()
|
||||
cat.py # fetch_cat()
|
||||
tests/ # pytest-тесты
|
||||
test_pogoda.py # translate_weather, pressure_to_mmhg, wmo_to_russian, format_weather_data_for_console
|
||||
test_pogoda.py # translate_weather, pressure_to_mmhg, wmo_to_russian
|
||||
test_fetch_cat.py # fetch_cat
|
||||
test_fetch_rss.py # fetch_rss
|
||||
test_fetch_weather.py # fetch_weather, fetch_open_meteo
|
||||
test_format_articles.py # truncate_title, parse_date, format_articles
|
||||
test_commands_pg.py # Pg cog
|
||||
test_bot.py # инициализация бота
|
||||
test_morning_runner.py# тесты morning runner-а
|
||||
ISSUES.md # Задачи и баг-трекер проекта
|
||||
pytest.ini # Конфигурация pytest
|
||||
```
|
||||
@ -110,16 +104,14 @@ python -m pytest tests/ -v
|
||||
|
||||
| Файл | Что тестирует | Кол-во |
|
||||
|------|---------------|--------|
|
||||
| `test_pogoda.py` | `translate_weather()`, `pressure_to_mmhg()`, `wmo_to_russian()`, `format_weather_data_for_console()` | 93 |
|
||||
| `test_pogoda.py` | `translate_weather()`, `pressure_to_mmhg()`, `wmo_to_russian()` | 93 |
|
||||
| `test_fetch_cat.py` | `fetch_cat()` | 10 |
|
||||
| `test_fetch_rss.py` | `fetch_rss()` | 20 |
|
||||
| `test_fetch_weather.py` | `fetch_weather()`, `fetch_open_meteo()` | 20 |
|
||||
| `test_format_articles.py` | `truncate_title()`, `parse_date()`, `format_articles()` | 24 |
|
||||
| `test_commands_pg.py` | `Pg` cog, команда `!pg` | 13 |
|
||||
| `test_bot.py` | инициализация бота | 7 |
|
||||
| `test_morning_runner.py` | morning runner-а | 68 |
|
||||
|
||||
**Итого: 258 тестов.**
|
||||
**Итого: 180 тестов.**
|
||||
|
||||
## API и внешние сервисы
|
||||
|
||||
@ -135,7 +127,7 @@ python -m pytest tests/ -v
|
||||
- Ветер: км/ч → м/с (`/ 3.6`)
|
||||
- Погодные описания: английский → русский (`translate_weather()`)
|
||||
|
||||
### Новости (!nw, !morning)
|
||||
### Новости (!news, !morning)
|
||||
- **Articles**: `https://habr.com/ru/rss/hubs/artificial_intelligence/articles/top/daily/?fl=ru`
|
||||
- **News**: `https://habr.com/ru/rss/hubs/artificial_intelligence/news/top/daily/?fl=ru`
|
||||
- Парсинг RSS 2.0 и Atom форматов
|
||||
@ -197,31 +189,3 @@ pytest-asyncio>=0.21.0
|
||||
Заголовки обрезаются до 60 символов с суффиксом `...`.
|
||||
|
||||
Ссылки отображаются без `<>` и `https://` префикса для предотвращения embed-превью в Discord.
|
||||
|
||||
## Основные функции утилит
|
||||
|
||||
### utils/pogoda.py
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| `fetch_weather()` | Основная функция получения погоды с wttr.in |
|
||||
| `fetch_open_meteo()` | Fallback при ошибках основного API |
|
||||
| `wmo_to_russian()` | Перевод WMO кодов погоды в русское описание |
|
||||
| `translate_weather()` | Перевод погодных описаний на русский язык |
|
||||
| `pressure_to_mmhg()` | Конвертация давления из hPa в мм рт. ст. |
|
||||
| `format_weather_data_for_console()` | Форматирование данных погоды для вывода в консоль |
|
||||
|
||||
### utils/news.py
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| `fetch_rss()` | Получение RSS ленты (статьи или новости) |
|
||||
| `parse_date()` | Парсинг даты из RSS |
|
||||
| `truncate_title()` | Обрезка заголовка до заданной длины |
|
||||
| `format_articles()` | Форматирование списка статей для вывода |
|
||||
|
||||
### utils/cat.py
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| `fetch_cat()` | Получение URL случайного котика |
|
||||
|
||||
@ -4,7 +4,7 @@ from utils.news import fetch_rss, format_articles, RSS_URL_ARTICLES, RSS_URL_POS
|
||||
|
||||
|
||||
class News(commands.Cog):
|
||||
"""Команда !news — свежие статьи и новости по AI с Habr"""
|
||||
"""Команда !nw — свежие статьи по AI с Habr"""
|
||||
|
||||
@commands.command(name="nw")
|
||||
async def nw(self, ctx):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user