I want to send a message to a private telegram channel using python with Telethon.
What I tried:
from telethon import TelegramClient
from telethon.tl.types import Channel
client = TelegramClient('fx', api id, "API hash")
client.start()
def sendMSG(channel, msg):
entity = client.get_entity(channel)
client.send_message(entity = entity,message=msg)
sendMSG("Channel Name", "Hello")
But this code gives me this error:
RuntimeWarning: coroutine 'UserMethods.get_entity' was never awaited
sendMSG("Channel", "Hello")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Telethon is an asynchronous library. This means you need to await almost everything.
import asyncio
async def sendMSG(channel, msg):
entity = client.get_entity(channel)
await client.send_message(entity = entity,message=msg)
asyncio.run(sendMSG("Channel Name", "Hello"))
Related
I'd like to listen for a new incoming message in a Telegram channel.
I'm using the Telethon package and tried to run the example found in the docs.
from telethon import TelegramClient, events
api_id = "..."
api_hash = "..."
CHANNEL_ID = "..."
client = TelegramClient('anon', api_id, api_hash)
client.start()
#client.on(events.NewMessage(chats=CHANNEL_ID, outgoing=False))
async def my_event_handler(event):
print(event)
client.run_until_disconnected()
This code runs, asks me for my phone number and the login code. But after that, nothing happens.
When a message is sent to the channel, I don't see anything printed out.
I'm trying to run this first code snippet provided by the Telethon documentation. But, after multiple problems (here and here), I ended up with this modified version:
import os
import sys
from telethon.sync import TelegramClient, events
# import nest_asyncio
# nest_asyncio.apply()
session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"
os.chdir(sys.path[0])
if f"{session_name}.session" in os.listdir():
os.remove(f"{session_name}.session")
async with TelegramClient(session_name, api_id, api_hash) as client:
client.send_message('me', 'Hello, myself!')
print(client.download_profile_photo('me'))
#client.on(events.NewMessage(pattern='(?i).*Hello'))
async def handler(event):
await event.reply('Hey!')
client.run_until_disconnected()
However now I'm getting these warnings:
usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:23: RuntimeWarning: coroutine 'MessageMethods.send_message' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:24: RuntimeWarning: coroutine 'DownloadMethods.download_profile_photo' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:30: RuntimeWarning: coroutine 'UpdateMethods._run_until_disconnected' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
when running the code on Jupyter. Now here are my questions:
what those warning messages mean and how should I address them?
what is the expected result of this code if working properly? Should I receive a message in Telegram or something? Because I don't recive any messages other than the signin code.
What does the # symbol at the beginning of the #client.on... line mean? what does that line is supposed to do? From this line onwards I do not understand the code. Would appreciate if you could help me understand it.
Just add await the client.send_message('me', 'Hello, myself!') to solve that error and print afterdownload_profile_photo has done its work downloads an image to localhost so that may be why you don't see anything. You should read telethon documentation thoroughly and also how to use photo downloads correctly
All the calls to the client have a delay and should always be awaited so that your code doesn't get blocked. You should read the asyncio tutorial
The correct code would be:
async with TelegramClient(session_name, api_id, api_hash) as client:
await client.send_message('me', 'Hello, myself!')
print(await client.download_profile_photo('me'))
#client.on(events.NewMessage(pattern='(?i).*Hello'))
async def handler(event):
await event.reply('Hey!')
#await client.run_until_disconnected()
The # is a decorator and you should read the PEP related to decorators, but in short words, they execute a function before yours.
In this case #client.on(events.NewMessage means:
When there is a new event that happens to be a message that matches the pattern specified handle it with this function called handler
Jupyter will run the asyncio event loop so that you can use async for / with / await outside of an async def. This conflicts with Telethon's .sync magic which you should try to avoid when using Jupyter, IPython, or similar.
To fix your code:
from telethon import TelegramClient, events
# ^ note no .sync
session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"
async with TelegramClient(session_name, api_id, api_hash) as client:
await client.send_message('me', 'Hello, myself!')
# ^ note you need to use `await` in Jupyter
# we are avoiding the `.sync` magic so it needs to be done by yourself
print(await client.download_profile_photo('me'))
# ^ same here, needs await
#client.on(events.NewMessage(pattern='(?i).*Hello'))
async def handler(event):
await event.reply('Hey!')
await client.run_until_disconnected()
# ^ once again needs await
If you want code to run anywhere (Jupyter, Python shell, normal run), just be sure to do everything inside async def:
import asyncio
from telethon import TelegramClient, events
session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"
async def main():
async with TelegramClient(session_name, api_id, api_hash) as client:
await client.send_message('me', 'Hello, myself!')
print(await client.download_profile_photo('me'))
#client.on(events.NewMessage(pattern='(?i).*Hello'))
async def handler(event):
await event.reply('Hey!')
await client.run_until_disconnected()
# Only this line changes, the rest will work anywhere.
# Jupyter
await main()
# Otherwise
asyncio.run(main())
I'm trying to figure out how telethon works.
it has a good documentation but I don't understand how download a video from telegram group.
I created a telegram group for test pourpose. I uploaded a video (from desktop client).
This code should starts to download the video on message events.
from telethon import TelegramClient, events
from telethon.tl.types import InputMessagesFilterVideo
import logging
logging.basicConfig(format='[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s',
level=logging.WARNING)
api_id = #########
api_hash = "#######################"
client = TelegramClient('desktop', api_id, api_hash)
#client.on(events.NewMessage)
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.reply('hi!')
channel_username = '######'
message = await client.get_messages(channel_username, limit=10)
await message[0].download_media("Video.mp4")
#video = await client.get_messages(chat, 0, filter=InputMessagesFilterVideo)
#print(video.total)
client.start()
client.run_until_disconnected()
Error:
AttributeError: 'TotalList' object has no attribute 'download_media'
Attribute doesn't exist , but I dont know how get the right ref
Thanks for help
EDIT : updated to
await message[0].download_media("Video.mp4")
I have this code
from telethon.sync import TelegramClient, events
with TelegramClient('name', api_id, api_hash) as client:
#client.on(events.NewMessage(pattern=pattern))
async def handler(event):
await event.reply("Here should be the Chat or Group name")
How to implement this?
if we are talking only about groups/channels
chat_from = event.chat if event.chat else (await event.get_chat()) # telegram MAY not send the chat enity
chat_title = chat_from.title
Else (If we want to get the full name of chat entities, including Users):
from telethon import utils
chat_from = event.chat if event.chat else (await event.get_chat()) # telegram MAY not send the chat enity
chat_title = utils.get_display_name(chat_from)
get_display_name() actually gets a name that you would see. Works for types User, Channel, Chat
That method shall not have await
I have little problem with writing my bot, I'm trying to send message only inside my bot, but my client handle any messages in any chats.
from telethon.sync import TelegramClient, events
import socks
api_id = 'my_id'
api_hash = 'my_hash'
client = TelegramClient('name', api_id, api_hash, proxy=###).start(bot_token='bot_token')
#client.on(events.NewMessage(pattern='/start'))
async def send_welcome(event):
await event.reply('How re you doing')
#client.on(events.NewMessage)
async def echo_all(event):
await event.reply(event.text)
client.run_until_disconnected()
You need to had func=lambda e: e.is_private into events.NewMessage() so the handler will only catch messages from private conversations (that's what you defined as "messages only inside your bot").
It will look like this:
#events.register(events.NewMessage(func=lambda e: e.is_private))
async def handler(event):
...