Telegram client operating on multiple thread

Viewed 651

I'm trying to attach to Telegram APIs to interact through such platform.

I need to send messages on multiple different threads, but I've not found any solution so far allowing me to do that.

Here you can find two sketch codes of my attempts to manage messages on different threads, using both telethon and pyrogram libraries.

So far, I've not found a solution yet.

Telethon case

import time
import threading

from telethon import TelegramClient, events

telegram_client = None

async def telethon_telegram_init(api_id, api_hash):
    global telegram_client
    client = TelegramClient('my_account', api_id, api_hash)
    await client.start()
    try: assert await client.connect()
    except: pass
    if not await client.is_user_authorized():
        client.send_code_request(phone_number)
        me = client.sign_in(phone_number, input('Enter code: '))
    client.parse_mode = 'html'
    telegram_client = client
    @telegram_client.on(events.NewMessage(incoming=True))
    async def telethon_telegram_receive(event):
        if event.is_private: await event.respond('Thank you for your message')

def telethon_telegram_send(to, message):
    global telegram_client
    while True:
        telegram_client.send_message(to, message)
        time.sleep(60)

# initiating the client object
telegram_client = telethon_telegram_init(api_id, api_hash)

# running the thread aimed to send messages
threading.Thread(target=telethon_telegram_send, args=('me', 'Hello')).start()

Results:

  • initialization: ok
  • message reception: not working (no errors are returned)
  • message sending: not working (AttributeError: 'coroutine' object has no attribute 'send_message' returned)

Pyrogram case

import time
import threading

from pyrogram import Client, filters

def pyrogram_telegram_init(api_id, api_hash):
    client = Client('my_account', api_id, api_hash)
    @client.on_message(filters.private)
    async def pyrogram_telegram_receive(event):
        await event.reply_text(f'Thank you for your message')
    client.start()
    return client

def pyrogram_telegram_send(client, to, message):
    while True:
        client.send_message(to, message)
        time.sleep(60)

# initiating the client object
telegram_client = pyrogram_telegram_init(api_id, api_hash)

# running the thread aimed to send messages
threading.Thread(target=pyrogram_telegram_send, args=(telegram_client, 'me', 'Hello')).start()

Results:

  • initialization: ok
  • message reception: not working (no errors are returned)
  • message sending: not working (no errors are returned)

Update:

Attempts with asyncio

I've also tried to use asyncio, as suggested by @Lonami. I've focused on the telethon library. Nevertheless, please note that in my case, new Telegram messages are generated by a TCP server listening on the host, in a way similar to the simplified sketch code below.

Here is the code reporting my attempts.

import time
import asyncio

from telethon import TelegramClient, events

RECIPIENT = 'me'

api_id = '...'
api_hash = '...'

telegram_client = None

# server management part

from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

class ServerSample(StreamRequestHandler):
    def handle(self):
        message = 'New connection from %s:%s' % self.client_address
        print(message)
        self.server.loop.call_soon_threadsafe(self.server.queue.put_nowait, message)
        # also tried with the following:
        #self.server.queue.put_nowait(message)

async def initialize_server(loop, queue):
    with ThreadingTCPServer(('127.0.0.1', 8080), ServerSample) as server:
        server.loop = loop
        server.queue = queue
        server.serve_forever()

async def telethon_telegram_init(api_id, api_hash):
    global telegram_client
    client = TelegramClient('my_account', api_id, api_hash)
    await client.start()
    try: assert await client.connect()
    except Exception as e: print(str(e))
    if not await client.is_user_authorized():
        client.send_code_request(phone_number)
        me = client.sign_in(phone_number, input('Enter code: '))
    client.parse_mode = 'html'
    telegram_client = client
    @telegram_client.on(events.NewMessage(incoming=True))
    async def telethon_telegram_receive(event):
        if event.is_private: await event.respond('Thank you for your message')
    return telegram_client

async def telethon_telegram_generate(loop, queue, t):
    loop.call_soon_threadsafe(queue.put_nowait, 'Hello from direct {} call'.format(t))

async def main():
    global telegram_client
    loop = asyncio.get_running_loop()
    queue = asyncio.Queue()
    # initiating the Telegram client object
    await telethon_telegram_init(api_id, api_hash)
    # initializing the server (non blocking)
    loop.create_task(initialize_server(loop, queue))
    # creating a new message (non blocking)
    loop.create_task(telethon_telegram_generate(loop, queue, 'non blocking'))
    # creating a new message (blocking)
    loop.run_in_executor(None, telethon_telegram_generate, loop, queue, 'blocking')
    # managing the queue
    while True:
        message = await queue.get()
        print("Sending '{}'...".format(message))
        await telegram_client.send_message(RECIPIENT, message)
        time.sleep(1)

asyncio.run(main())

In this case, to trigger the generation of a new Telegram message from the TCP server itself, it is needed to launch a curl command like the following one:

curl http://localhost:8080

Nevertheless, results are not promising.

Results:

  • initialization: ok for telethon_telegram_init and initialize_server, apparently not working for both telethon_telegram_generate method calls
  • message reception: not working (no errors are returned)
  • message sending: not working (no errors are returned)
  • additional notes: after the curl command is executed, a New connection from 127.0.0.1:<random_port> message is printed, but no Telegram messages are sent
0 Answers
Related