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_initandinitialize_server, apparently not working for bothtelethon_telegram_generatemethod calls - message reception: not working (no errors are returned)
- message sending: not working (no errors are returned)
- additional notes: after the
curlcommand is executed, aNew connection from 127.0.0.1:<random_port>message is printed, but no Telegram messages are sent