I’m developing a Telegram bot for a store using the aiogram library in Python. My project requires two bots, namely the store bot and the courier-delivery bot for the store, to work together in the same application. I’ve tried various approaches, but I believe the best solution for this is to use webhooks.
I tried to write my own server so that it would send an update to the right bot.
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiohttp import web
from datetime import datetime
import courier
import registration
import shop
import time
import config
import middlewares
users_notified = {}
start_time = datetime.fromtimestamp(time.time())
dp = Dispatcher(config.bot, storage=MemoryStorage()) #User bot
dpc = Dispatcher(config.bot_courier, storage=MemoryStorage()) #Courier Bot
dp.middleware.setup(middlewares.AntiSpamMiddleware())
dp.middleware.setup(middlewares.OnlineTimeMiddleWare())
registration.BindRegistration(dp)
shop.BindShop(dp)
# Бот курьера
dpc = Dispatcher(config.bot_courier, storage=MemoryStorage())
courier.BindCourier(dpc)
# Create aiohttp application
app = web.Application()
async def on_startup(app):
await config.bot.set_webhook(config.WEBHOOK_URL, drop_pending_updates=False)
await config.bot_courier.set_webhook(config.WEBHOOK_URL_COURIER, drop_pending_updates=False)
async def on_shutdown(app):
await config.bot.delete_webhook()
session1 = await config.bot.get_session()
await session1.close()
await config.bot_courier.delete_webhook()
session2 = await config.bot_courier.get_session()
await session2.close()
async def process_update1(request):
data = await request.json()
update = types.Update(**data)
if update.message.date < start_time:
user_id = update.message.from_user.id
if user_id not in users_notified and config.notify:
await config.bot.send_message(user_id, "There was an error, but we are back online.")
users_notified[user_id] = True # Mark the user as notified
return web.Response()
Bot.set_current(config.bot)
await dp.process_update(update)
return web.Response()
async def process_update2(request):
data = await request.json()
update = types.Update(**data)
# Ignore updates that were sent before the server was started
if update.message.date < start_time:
return web.Response()
Bot.set_current(config.bot_courier)
await dpc.process_update(update)
return web.Response()
app.on_startup.append(on_startup)
app.on_shutdown.append(on_shutdown)
app.router.add_post(config.WEBHOOK_PATH, process_update1)
app.router.add_post(config.WEBHOOK_PATH_COURIER, process_update2)
web.run_app(app, host='0.0.0.0', port=3000)
But I am getting error "state = Dispatcher.get_current().current_state()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: ‘NoneType’ object has no attribute ‘current_state’", I get it the first time "get_current" is called, no matter where it first occurs.
Please help, explain what I’m doing wrong, maybe there are some others , more trivial approaches to solving this problem Thanks in advance!
I tried different ways to implement 2 bots in one project, tried using asyncio.gather(executor.start_webhook(),…) to run this as a caroutine. I also tried to use long-poolong but all this did not work correctly.
2
Answers
For me, using aiogram 2.17.1 and a long-polling looks like this:
in Initializer created 2 Bot and 2 Dispatcher objects
I know its quite late but i fixed it like this: