discordBot/bot.py
deadzilla 8090b4fe17 fix: resolve issue #3 (deduplication) and fix coroutine handling
- Create utils/news.py with shared RSS parsing and formatting logic
- Refactor commands/news.py and console_commands/news.py to use utils/news.py
- Fix bot.py to handle async console commands (news, pogoda)
- Fix utils/pogoda.py to fall back to Open-Meteo on requests.RequestException
- Mark issue #3 as resolved in ISSUES.md
2026-05-26 13:58:35 +05:00

103 lines
3.1 KiB
Python

import asyncio
import inspect
import os
import sys
import threading
import discord
from discord.ext import commands
from discord.ext.commands import CommandNotFound
from dotenv import load_dotenv
from commands import ALL_COMMANDS
from console_commands import ALL_CONSOLE_COMMANDS
load_dotenv()
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
stop_event = threading.Event()
bot_ready = threading.Event()
@bot.event
async def on_ready():
print(f"Бот вошёл как {bot.user}")
for cog_class in ALL_COMMANDS:
cog = cog_class()
await bot.add_cog(cog)
for cog in bot.cogs:
print(f" Загружен: {cog}")
bot_ready.set()
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, CommandNotFound):
return
print(f"Ошибка команды: {error}")
@bot.command(name="msg")
async def msg(ctx, *, text: str):
"""Повторяет текст после !msg"""
await ctx.send(text)
def console_input():
bot_ready.wait()
print("Доступные команды:")
available = {k: v for k, v in ALL_CONSOLE_COMMANDS.items() if k != "stop"}
for idx, (name, func) in enumerate(available.items(), 1):
print(f" {idx}. {name}")
print(" 0. stop")
while not stop_event.is_set():
try:
choice = input("\nВыберите команду (номер): ").strip()
if choice == "0":
print("\nОстановка бота...")
stop_event.set()
break
try:
idx = int(choice)
if 0 < idx <= len(available):
cmd_name = list(available.keys())[idx - 1]
cmd_func = ALL_CONSOLE_COMMANDS[cmd_name]
if inspect.iscoroutinefunction(cmd_func):
asyncio.run_coroutine_threadsafe(cmd_func(stop_event, bot), bot.loop).result()
else:
cmd_func(stop_event, bot)
else:
print(f"Неизвестная команда: {choice}")
except (ValueError, IndexError):
print(f"Неизвестная команда: {choice}")
except (EOFError, KeyboardInterrupt):
stop_event.set()
try:
asyncio.run_coroutine_threadsafe(bot.close(), bot.loop).result(timeout=5)
except Exception as e:
print(f"Ошибка при остановке бота: {e}")
break
if __name__ == "__main__":
print("Введите 'stop' для остановки бота")
thread = threading.Thread(target=console_input, daemon=True)
thread.start()
try:
token = os.getenv("DISCORD_TOKEN")
if not token:
print("Ошибка: токен не найден в .env")
sys.exit(1)
bot.run(token)
except KeyboardInterrupt:
print("\nОстановка бота...")
stop_event.set()
asyncio.run_coroutine_threadsafe(bot.close(), bot.loop).result()
sys.exit(0)