Telethon async and await mess

Question:

Here is my code as follows:

import time
import telethon
import asyncio

# Enter your API ID and API hash here
api_id = 13******
api_hash = '8ba0a***********************'

# Enter the name of the text file containing the messages
message_file = 'messages.txt'

async def main():
    # Connect to the Telegram API using your API ID and API hash
    client = telethon.TelegramClient('sender', api_id, api_hash)

    # Read the messages from the text file
    with open(message_file, 'r') as f:
        messages = f.readlines()

    # Send the messages and pause for one minute between each message
    for message in messages:
        await client.send_message('@Example_recipient', message.strip())
        await time.sleep(60)

    # Disconnect from the Telegram API
    client.disconnect()

async def run() -> asyncio.coroutine:
    await main()

asyncio.run(run())

Whenever I run it, it gives me this error:

  File "/usr/local/lib/python3.10/dist-packages/telethon/network/mtprotosender.py", line 173, in send
    raise ConnectionError('Cannot send requests while disconnected')
ConnectionError: Cannot send requests while disconnected

asyncio.run fixed a previous error which was:

RuntimeWarning: coroutine 'run' was never awaited
  run()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Now I am stuck with this new error that I can’t seem to get around.

Asked By: MohaMoney

||

Answers:

Try changing your code to something like this:

import asyncio
import telethon

api_id = 13******
api_hash = '8ba0a***********************'
message_file = 'messages.txt'

# Better style would be to have these not initiated
# at the top-level and instead behind the if name == main
# guard, but lets keep it simple.
client = telethon.TelegramClient('sender', api_id, api_hash)
with open(message_file, 'r') as f:
    messages = f.readlines()

async def main():
    for message in messages:
        await client.send_message('@Example_recipient', message.strip())
        await asyncio.sleep(60)

if __name__ == "__main__":
    # The context manager will release the resource
    # (i.e. call client.disconnect) for us when the
    # block exits.
    with client:
        client.loop.run_until_complete(main())
    

which is much closer to the example in the documentation. Also it’s not clear why you have the 60 second wait, or why you are using asyncio if you want to wait between sending messages. It looks like you could just use telethon.sync and block and not have any of the asyncio boilerplate?

Update based on comments

with open(file) as handle:
    messages = list(handle.readlines())

...

    while len(messages):
        first = messages.pop()
        # check here before popping that the list
        # isn't already empty
        second = messages.pop()
        await client.send_message(first)
        await client.send_message(second)
Answered By: Jared Smith