Search code examples
pythonpython-3.xasync-awaittelethonevent-loop

How to intergrate telethon script into my event loop?


I have two bots, one is using pydle for IRC, like:

async def start_ircbot ():
    try:
        client = MyOwnBot(NICK, 
                       realname=REALNAME,
                       sasl_username=SASL_USERNAME,
                       sasl_password=SASL_PASSWORD,
                       sasl_identity=SASL_IDENTITY,)

        loop = asyncio.get_event_loop()
        asyncio.ensure_future(client.connect(HOST, PORT, tls=True, tls_verify=False), loop=loop)
        loop.run_forever()
        loop.close()
    except Exception as e:
        print (e)

and another is using telethon for Telegram:

@client.on(events.NewMessage)
async def my_event_handler(event):
    ...

async def start_client ():
    print ("Telegram monitor started...")
    await client.start()
    await client.run_until_disconnected()

Both of them work without problem separately.

Now, I want to integrate both of them, I tried to launch both of them in my main function like this,

import Notifier

...

async def main():
    await asyncio.gather (Notifier.start_client (), start_ircbot ())

asyncio.run(main())

It starts without issue but my_event_handler seems never to get new messages. If I swap the order of functions:

await asyncio.gather (start_ircbot (), Notifier.start_client ())

The script will be stuck at launching, I suspect it has to be something within events loops and tried some different methods but without luck, could anyone shed light on this for me?


Solution

  • Newer Python versions are removing the loop parameter from most methods, so you should try to avoid using it. As long as you don't use asyncio.run (which creates a new loop) or you don't create a new loop yourself, both libraries should be using the default loop from the main thread (I can't speak for pydle, but Telethon does this).

    As long as the asyncio event loop is running, Telethon should have no trouble receiving updates. You can use client.loop to make sure it's using the same loop:

    tlclient = TelegramClient(...)
    irclient = MyOwnBot(...)
    
    @tlclient.on(events.NewMessage)
    async def my_event_handler(event):
        ...
    
    async def main():
        await tlclient.start()
        await irclient.connect(HOST, PORT, tls=True, tls_verify=False), loop=tlclient.tlclient)
        await tlclient.run_until_disconnected()  # similar to loop.run_forever() but stops when the client disconnects
    
    client.loop.run_until_complete(main())