60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
import asyncio
|
||
import logging
|
||
import signal
|
||
from typing import Sequence
|
||
|
||
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")
|
||
|
||
# ORM здесь, в синхронном контексте
|
||
bots: Sequence[TelegramBot] = list(TelegramBot.objects.filter(is_active=True))
|
||
if not bots:
|
||
self.stderr.write(self.style.ERROR("Нет активных ботов (is_active=True)."))
|
||
return
|
||
|
||
asyncio.run(self._amain(bots))
|
||
|
||
async def _amain(self, bots: Sequence[TelegramBot]):
|
||
apps = []
|
||
try:
|
||
for tb in bots:
|
||
app, allowed_updates = build_application_for_bot(tb)
|
||
await app.initialize()
|
||
await app.start()
|
||
await app.updater.start_polling(allowed_updates=allowed_updates)
|
||
apps.append(app)
|
||
log.info("Bot started: %s (@%s)", tb.name, tb.username or "—")
|
||
|
||
# Ждём SIGINT/SIGTERM
|
||
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:
|
||
pass # Windows
|
||
|
||
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")
|