I've been scratching my head at this a while. Trying to just do the simple act of creating a program that will automatically read in every new post from a Telegram channel into str or something that I can use to then create a bot. I've been looking for days and everything I've seen and tried doesn't seem to work for me. Apologies cause I know this is probably stupid simple and there is an answer somewhere but the answer's I've seen just haven't worked or maybe I just don't get async at all.
import configparser
import json
import re
from telethon import TelegramClient, events
api_id = 'xxxxx'
api_hash = 'xxxxxxxxxxxx'
user_input_channel = 'https://t.me/Kucoin_news'
subjectFilter = ['']
levelFilter = ['']
client = TelegramClient(None, api_id, api_hash)
#client.on(events.NewMessage(chats=user_input_channel))
async def newMessageListener(event):
# Get message text
newMessage = event.message.message
print(newMessage)
client.start()
client.run_until_disconnected()
/home/enigma/.config/spyder-py3/Bot.py:35: RuntimeWarning: coroutine 'AuthMethods._start' was never awaited
client.start()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/home/enigma/.config/spyder-py3/Bot.py:36: RuntimeWarning: coroutine 'UpdateMethods._run_until_disconnected' was never awaited
client.run_until_disconnected()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Does async HAVE to be used with a telethon application like this? This will only be for reading one channels new posts, not several. By the time a new post comes out the Bot will easily have completed its task. I thought that since client.start() and client.run_until_disconnected() were outside of the async function they didn't need to be awaited? Awaiting is just when you call a function inside of the async function correct? I've tried to read on this subject but find the way they explain it confusing and long winded.
client.start() under client = "ecc"
Related
so I've been trying to make my discord bot send a message every day at 12:30 UCT but i cant seem to get my code to work I'm not sure if its not working because of incorrect code or because its on replit or whatever else the issue could be as i get no errors from this it just send the message once it loads online and that's all.
import datetime, asyncio
bot = commands.Bot(command_prefix="+")
Async def on_Ready():
await schedule_daily_message()
async def schedule_daily_message():
now = datetime.datetime.now()
then = now+datetime.timedelta(days=1)
then.replace(hour=12, minute=30)
wait_time = (then-now).total_seconds()
await asyncio.sleep(wait_time)
channel = bot.get_channel(Channel_id)
await channel.send("Enemies Spawned!")
client.run(os.getenv('TOKEN'))
await asyncio.sleep is non blocking. Your script will execute beyond that statement. You will need to use time.sleep, which that will block all execution of code until the timer has run out.
See here for a more in depth explanation and how to use this in functions:
asyncio.sleep() vs time.sleep()
A way to implement a function that posts a message to a channel after a delay could look like this:
async def send_after_delay(d, c, m):
time.sleep(d)
await c.send(m)
Calling this function asynchronously allows you to continue with code execution beyond it, while still waiting past the calling of the function to send the message.
I have set up a script to download messages from thousands of Telegram supergroups (named chatlist). This works fine when I use a few groups, however, allowing 1000< groups seems to break it and no messages are collected at all. Is this the correct way to approach it, or is there a more efficient way? I don't think it's a network issue my end as I have GB internet
from telethon import TelegramClient, events, sync
client = TelegramClient('test', api_id, api_hash)
#client.on(events.NewMessage(chats=chatlist))
async def my_event_handler(event):
message = event.message.to_dict()
print(message['message'])
await client.start()
await client.run_until_disconnected()
A simple workaround is to remove the NewMessage event filter i.e.:
#client.on(events.NewMessage())
and filter messages inside the method yourself:
async def my_event_handler(event):
message = event.message.to_dict()
input_chat = await event.get_input_chat()
if input_chat in chatlist:
print(message['message'])
You didn't mention what's inside chatlist, so I assumed it's a list of InputChat objects.
Note that if your chat list is a list of #username strings, you'll soon reach Telegram username resolve limits. Always have InputChat or long ids in the chatlist.
So the idea is simple, I have a list of twitter IDs, when any of these accounts make a post, I want this bot to take that post, and share a link to it in a specific discord channel. Currently, it tosses an error at me when I make a twitter post.
Relevant Code:
class MyStreamListener(tweepy.StreamListener): #this runs whenever a tweet is posted
async def on_status(self, status):
send(status)
bot = commands.Bot(command_prefix='=')
#bot.event
async def on_ready():
print(f'{bot.user.name} has connected to Discord!')
myStreamListener = MyStreamListener() #sets up the listener
myStream = tweepy.Stream(auth = auth_api.auth, listener=myStreamListener)
myStream.filter(follow=[{ids of the accounts}], is_async = True)
async def send(postID):
channel = bot.get_channel(834887013756305490)
channel.send('https://twitter.com/twitter/statuses/'+str(postID.id)) #error happens here.
Here is the error:
C:...site-packages\tweepy\streaming.py:54: RuntimeWarning: coroutine 'MyStreamListener.on_status' was never awaited
if self.on_status(status) is False:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
I have attempted to do this in a non async channel, which gives me an error, and I have attempted to add "await" before channel.send (which is how it worked for sending a message on, say, a command prompt), but neither of these worked.
If anyone has any idea what I am missing here, help would be MUCH appreciated.
Messageable.send is a coroutine, it needs to be awaited
async def send(postID):
channel = bot.get_channel(834887013756305490)
await channel.send('https://twitter.com/twitter/statuses/'+str(postID.id))
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 am having a hard time understanding asyncio and the await function. I have a script that uses the Telethon wrapper that requires me to understand / use asyncio.
The only goal of the script is to download an image from a Telegram group.
I have read a beginner asyncio tutorial but I am still having a very hard time understand the concept of it and how to await something.
# Start Client
client1 = TelegramClient('sesh1', api_id1, api_hash1)
client1.start('xxx')
time.sleep(0.1)
# ---------------------------------------
# Get last message
for message in client1.iter_messages(groupname, limit=1):
data = message.file
print(data)
# Download is last message is media
if data is not None:
print("Img found")
x = client1.download_media(message=message)
print(x)
The error I keep getting is:
sys:1: RuntimeWarning: coroutine 'DownloadMethods.download_media' was never awaited.
How do I await the download function?