deadzilla 91f34625a8 feat: команды !status и !stats
Добавлены Discord-команды:
  - !status — пинг к gateway, uptime, статус (embed)
  - !stats — серверы, каналы, пользователи (embed)

Добавлены консольные команды:
  - status — статус бота в терминале
  - stats — статистика серверов в терминале

Тесты:
  - test_commands_status.py (6 тестов)
  - test_commands_stats.py (4 теста)
  - всего: 233 теста

Обновления:
  - README.md — новые команды в таблицах и архитектуре
  - ISSUES.md — высокий приоритет закрыт
  - admin.py — hint на !status и !stats
2026-06-12 16:19:21 +05:00

201 lines
5.8 KiB
Python
Raw 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.

"""Админ-скрипт для управления ботом через docker exec.
Использование:
docker exec discord-bot python admin.py pogoda
docker exec discord-bot python admin.py news
docker exec discord-bot python admin.py cat
docker exec discord-bot python admin.py morning
docker exec discord-bot python admin.py help
"""
import sys
import asyncio
def print_help():
"""Показать список команд."""
print("\nАдмин-команды:")
print("-" * 40)
commands = [
("pogoda", "Прогноз погоды в Магнитогорске"),
("news", "Топ-5 статей и новостей AI с Habr"),
("cat", "URL случайного котика"),
("morning", "Утренний дайджест: погода + новости + котик"),
("help", "Показать этот список"),
]
for name, desc in commands:
print(f" {name:<12}{desc}")
print("-" * 40)
print("\n status — через Discord: !status")
print(" stats — через Discord: !stats")
print(" stop — docker stop discord-bot\n")
async def run_pogoda():
"""Вывести прогноз погоды для Магнитогорска."""
from utils.pogoda import (
API_URL_WEATHER,
fetch_weather,
format_weather_data_for_console,
)
data = await fetch_weather(API_URL_WEATHER)
if data is None:
print("Не удалось получить данные о погоде.")
return
formatted = format_weather_data_for_console(data)
if not formatted:
print("Не удалось получить данные о погоде.")
return
for line in formatted:
print(line)
async def run_news():
"""Вывести топ-5 свежих статей по AI с Habr."""
from utils.news import (
RSS_URL_ARTICLES,
RSS_URL_POSTS,
fetch_rss,
format_articles,
)
articles = await fetch_rss(RSS_URL_ARTICLES)
if articles is None:
print("Не удалось получить новости.")
return
if not articles:
print("Новостей пока нет.")
return
lines = format_articles(
articles,
"Статьи AI / Хабр",
"https://habr.com/ru/hubs/artificial_intelligence/articles/top/daily/",
)
posts = await fetch_rss(RSS_URL_POSTS)
if posts is not None and posts:
lines.append("")
lines.extend(
format_articles(
posts,
"Новости AI / Хабр",
"https://habr.com/ru/hubs/artificial_intelligence/news/top/daily/",
)
)
for line in lines:
print(line)
async def run_cat():
"""Вывести URL случайного котика."""
from utils.cat import fetch_cat
url = await fetch_cat()
if url is None:
print("Не удалось получить котика.")
return
print(f"Котик: {url}")
async def run_morning():
"""Вывести утренний дайджест: погода + новости + котик."""
from utils.cat import fetch_cat
from utils.morning_runner import gather_morning
from utils.news import format_articles
from utils.pogoda import format_weather_data_for_console
data = await gather_morning()
print("Доброе утро!\n")
# --- Котик ---
if data.cat_url:
print(f"Котик: {data.cat_url}\n")
else:
print("Котика получить не удалось.\n")
# --- Погода ---
formatted = format_weather_data_for_console(data.weather)
if formatted:
print("**Погода в Магнитогорске:**")
for line in formatted:
print(line)
else:
print("Не удалось получить данные о погоде.")
print()
# --- Новости: статьи ---
if data.articles is not None:
if data.articles:
print(
"\n".join(
format_articles(
data.articles,
"Статьи AI / Хабр",
"https://habr.com/ru/hubs/"
"artificial_intelligence/articles/top/daily/",
)
)
)
else:
print("Новостей пока нет.")
else:
print("Не удалось получить новости.")
print()
# --- Новости: посты ---
if data.posts is not None:
if data.posts:
print(
"\n".join(
format_articles(
data.posts,
"Новости AI / Хабр",
"https://habr.com/ru/hubs/"
"artificial_intelligence/news/top/daily/",
)
)
)
else:
print("Новостей пока нет.")
else:
print("Не удалось получить новости.")
COMMANDS = {
"pogoda": run_pogoda,
"news": run_news,
"cat": run_cat,
"morning": run_morning,
"help": lambda: print_help(),
}
def main():
"""Точка входа: парсит аргумент и вызывает команду."""
if len(sys.argv) < 2:
print("Укажите команду.")
print_help()
sys.exit(1)
command = sys.argv[1].lower()
handler = COMMANDS.get(command)
if handler is None:
print(f"Неизвестная команда: {command}")
print_help()
sys.exit(1)
if command == "help":
handler()
else:
asyncio.run(handler())
if __name__ == "__main__":
main()