61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
# bot/management/commands/runbots.py
|
||
import asyncio
|
||
import logging
|
||
import signal
|
||
from django.core.management.base import BaseCommand
|
||
from bot.models import TelegramBot
|
||
from bot.bot_factory import build_application_for_bot
|
||
|
||
log = logging.getLogger(__name__)
|
||
|
||
class Command(BaseCommand):
|
||
help = "Запуск ВСЕХ активных ботов (PTB 22.3) в одном процессе."
|
||
|
||
def handle(self, *args, **options):
|
||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
|
||
asyncio.run(self._amain())
|
||
|
||
async def _amain(self):
|
||
bots = list(TelegramBot.objects.filter(is_active=True))
|
||
if not bots:
|
||
self.stderr.write(self.style.ERROR("Нет активных ботов (is_active=True)."))
|
||
return
|
||
|
||
apps = []
|
||
try:
|
||
# Инициализация и старт polling для каждого бота
|
||
for tb in bots:
|
||
app, allowed_updates = build_application_for_bot(tb)
|
||
await app.initialize()
|
||
await app.start()
|
||
# в 22.x polling запускается через updater
|
||
await app.updater.start_polling(allowed_updates=allowed_updates)
|
||
apps.append(app)
|
||
log.info("Bot started: %s (@%s)", tb.name, tb.username or "—")
|
||
|
||
# Ожидание сигнала остановки
|
||
stop_event = asyncio.Event()
|
||
|
||
def _stop(*_):
|
||
stop_event.set()
|
||
|
||
loop = asyncio.get_running_loop()
|
||
for sig in (signal.SIGINT, signal.SIGTERM):
|
||
try:
|
||
loop.add_signal_handler(sig, _stop)
|
||
except NotImplementedError:
|
||
# Windows
|
||
pass
|
||
|
||
await stop_event.wait()
|
||
|
||
finally:
|
||
# Корректная остановка всех приложений
|
||
for app in reversed(apps):
|
||
try:
|
||
await app.updater.stop()
|
||
await app.stop()
|
||
await app.shutdown()
|
||
except Exception:
|
||
log.exception("Shutdown error")
|