Search code examples
pythonchatbot

how to pass variable or object to aiogram dp.message_handler decorated function?


I am trying to use aiogram building a chatbot, but find no example provided by the package is helpful. The problem is I can't find a way to pass my own object or variables from main to my chat function decorated by 'dp.message_handler()'. I need passing objects and variable which are text generator to chat function, so bot can chat instead of just echoing. I used their echo example as starting point, I can get user message at 'message.text' no problem...my code is like:

    @dp.message_handler()
    async def chat(message: types.Message, myobj, myvar):
        "using myobj and myvar to generate text as reply"
        await message.answer(reply)
        return message.text
     
    async def main():
        while Ture:
            said = await partial(chat, myobj=qna_model, myvar=text)
            if said == "bye": break
        dp.stop_polling()
        await dp.wait_closed()
        await bot.session.close()

    if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)
    asyncio.run(main())

But I got error: TypeError: chat() missing 2 required positional arguments: 'myobj' and 'myvar'. I even tried 'async def chat(message: types.Message, **kwargs)' and call it from main() without partial wraper, also no luck... I searched and can't find example about how to use aiogram to build a chatbot, may be I am in a wrong way of using aiogram... Has anyone used aiogram building chatbot successfully?


Solution

  • If you wanna pass a function to your handler just import it and use it directly. If you wanna apply it for some handlers, you should use a middleware.

    Direct usage

    def generate_text():
        return "generated text"
    
    async def handler(message: Message):
        text = generate_text()
        await message.answer(text)
    

    Middleware usage

    Create a middleware
    from aiogram.dispatcher.middlewares import BaseMiddleware
    from aiogram.types import Message
    
    class YourMiddleware(BaseMiddleware):
        async def on_pre_process_message(self, message: Message, data: dict):
            # `text` is a name of var passed to handler
            data["text"] = generate_text()
    
    Register it via Dispatcher (on_startup)
    dp.middleware.setup(YourMiddleware())
    
    Get text data inside the handler
    from aiogram.types import Message
    
    async def handler(message: Message, text: str):
        await message.answer(text)