Telethon and messages not received from some channels - python

I have a software which monitors multiple telegram channels and performs actions based on the received messages.
The problem is that in the past month it stopped received messages from some of the channels.
I'm using one of the examples in the official repositories with some additions.
#callback
async def check_chat(self, event=None):
"""
Checks the input chat where to send and listen messages from.
"""
if self.me is None:
return # Not logged in yet
chat = self.chat.get().strip()
try:
chat = int(chat)
except ValueError:
pass
async def on_msg_received(self, event):
global folders_list
now = datetime.now()
hour = now.hour
minute = now.minute
nome_chat = ''
try:
async for dialog in self.cl.iter_dialogs():
if(dialog.id == event.chat_id):
nome_chat = dialog.name
except:
logging.warning('error at on_msg_received')
logging.warning('------- chat = %s', nome_chat)
testo = event.raw_text
With some chats I don't get any activity at all, I expect to get either an error or the chat name.
What could be the issue here?
Does it make any difference if the channel is sending messages from telegram web or desktop?

Related

Delete scheduled message from telegram using telethon library

I am almost new to telegram bots development and have basic experience in using the telethon python library.
I am working on a project where I need to schedule the message using telethon and then delete the messages if needed. I am using following code to schedule the messages on telegram channels and groups.
await client.send_message(receiver, message_text, schedule=schedule_time)
And when I need to get the scheduled messages for that channels I am using the following code to get the messages from the telegram servers.
result = await self.client(functions.messages.GetScheduledHistoryRequest(
peer=target,
hash=0
))
And I want to delete the messages I have scheduled. I have gone through the documentation of telethon library and found the following code to do delete the messages.
group = await client.get_entity(group_id)
list_of_messages = await get_scheduled_messages(group_id)
for message in list_of_messages:
status = await client.delete_messages(group, [message.id])
And this is not working. I have also tried the delete method for the message object like this.
group = await client.get_entity(group_id)
list_of_messages = await get_scheduled_messages(group_id)
for message in list_of_messages:
await message.delete()
Is there something I am missing or there is nothing to delete the scheduled messages which has not been sen yet!
In order to delete your scheduled messages you'll have first to get them using GetScheduledHistoryRequest and then you can delete all the messages you'd prefer to, using DeleteScheduledMessagesRequest.
chat = await client.get_input_entity('yourchat')
result = await client(functions.messages.GetScheduledHistoryRequest(
peer=chat,
hash=0
))
# use result.messages to access the list of scheduled messages
msg = result.messages[0] # or any other message you want to delete
await client(functions.messages.DeleteScheduledMessagesRequest(
peer=chat,
id=[msg.id] # !imporant you need to pass a list here
))
In order to edit a scheduled message, since the edit_messages() and edit() functions seems not working properly with scheduled messages, you'll need to use the Telegram raw APIs messages.editMessage.
chat = await client.get_input_entity('yourchat')
result = await client(functions.messages.GetScheduledHistoryRequest(
peer=chat,
hash=0
))
msg = result.messages[0] # or any other message you want to edit
await client(functions.messages.EditMessageRequest(
peer = msg.to_id,
id = msg.id,
message = 'new text',
no_webpage= False, # didn't find anything into the Message object to refer to
entities= msg.entities,
media= msg.media,
reply_markup = msg.reply_markup,
schedule_date= msg.date
))
Keep in mind that I've refer to the older message to fill the all parameters into the EditMessageRequest() function, but you should be able to edit no_webpage, media, schedule_date without any problem.

How to get a telegram private channel id with telethon

Hi can't figure out how to solve this problem, so any help will be really appreciated.
I'm subscribed to a private channel. This channel has no username and I don't have the invite link (the admin just added me).
Since I use this channel at work, to speed up the things I want to process the messages posted on the channel using Telethon.
The core of the program is:
#events.register(events.NewMessage(chats = my_private_channel))
async def handler(event):
#do things
The problem is that I am not able to filter the messages coming to that specific channel id. I get the error:
ValueError: Cannot find any entity corresponding to "0123456789"
I have tried different technique to obtain my channel Id but the error is always the same. In particular:
The channel is private so it has no username ("#blablabla")
I have no invite link
I have tried to process all incoming messages until the admin sent a message on the channel, print sender information and get the value from the "ID" key
I have tried to use telegram web and get the ID from the url (also adding -100 in front of it)
But when I put the ID in the parameter chats, I get always the error reported above.
Thanks in advance,
Have a nice day
if you have access to the channel, then it's shown in your chat list.
You have to loop through your chats checking their titles and then store the desired chat in a variable:
my_private_channel_id = None
my_private_channel = None
async for dialog in tg.client.iter_dialogs():
if dialog.name == "private chat name":
my_private_channel = dialog
my_private_channel_id = dialog.id
break
if my_private_channel is None:
print("chat not found")
else:
print("chat id is", my_private_channel_id)
Than you can filter messages sent to my_private_channel.
You can print all the dialogs/conversations that you are part of.
also you need to remove -100 prefix from the id you got like: -1001419092328 = 1419092328 (actual ID)
from telethon import TelegramClient, events
client = TelegramClient("bot", API_ID, API_HASH)
client.start()
print("🎉 Connected")
#client.on(events.NewMessage())
async def my_event_handler(event):
async for dialog in client.iter_dialogs():
print(dialog.name, 'has ID', dialog.id) # test ID -1001419092328
client.run_until_disconnected()
if you want to listen to a specific channel, you can use channel_id=1419092328. you will only receive messages that are broadcasted to it:
from telethon import TelegramClient, events
from telethon.tl.types import PeerChannel
print(f"👉 Connecting...")
client = TelegramClient("bot", API_ID, API_HASH)
client.start()
print("🎉 Connected")
#client.on(events.NewMessage(PeerChannel(channel_id=1419092328)))
async def my_event_handler(event):
msg = event.text
print(f"[M] {msg}")
client.run_until_disconnected()
You can't join a private channel without the invite link, nor can you get any information about it. It's private, as the name implies.

Make Irssi like text frontend in Python using curses or anything available

By using the Discord API I made a simple script which shows messages received to a certain channel and allow to send a message to that channel. But the problem is input() is holding the program and the new messages do not print until Enter is pressed.
To overcome the problem I am thinking to make Irssi like a front end in which the top part shows messages and the button part allow us to input the messages.
Backend Code
from discord.ext import commands
channel_id = discord_channel_id
bot_token = bot_token
class MyClient(discord.Client):
async def on_ready(self):
global channel, msg
channel = discord.Client.get_channel(self, id=channel_id)
print(f'You are Connected on {channel}')
while True:
# Send message
msg = input('[You] >> ')
await channel.send(msg)
async def on_message(self, message):
# Don't respond to ourselves
if message.author == self.user:
return
if message.content:
global received
received = message.content
client = MyClient()
client.run(bot_token)
Curses
import time
import curses
def main(stdscr):
status = 'connecting'
server = 'connecting'
channel = 'connecting'
online = 'connecting'
key = 0
stdscr.clear()
stdscr.refresh()
# Disable cursor blinking
curses.curs_set(0)
while (key != ord('~')):
# Initialization
stdscr.clear()
height, width = stdscr.getmaxyx()
# Status Bar
stdscr.addstr(f"Status: {status} Server: {server} Channel: {channel} Online: {online}", curses.A_REVERSE)
stdscr.chgat(-1, curses.A_REVERSE)
# Update the screen
stdscr.refresh()
key = stdscr.getch()
curses.wrapper(main)
I made a simple curses UI, but I could not add an input window in the button as in Irssi. I want any message received by the API to print in the Top part and an input button to send a message to the server. But I am stuck in here.
getch has a timeout which can be turned off (nodelay) or set to a small value (timeout)

My chat consumer is not working django-channels?

I am tryna make a one-one chat application but my chat socket get's disconnected immediately when i send the data to it.I think the problem is in my asynchronous recieve function of my consumer?
It's not giving me any reason for the error?The socket disconnects silently
Here's the recieve handler
async def receive(self, text_data):
data = json.loads(text_data)
text = data['message']
room_name = data['room_name']
username = data["username"]
only_one_user = False
profile = self.scope["user"].profile
# GET THE ROOM AND THE PROFILE
room_obj = await database_sync_to_async(Room.objects.get)(pk=self.room_name)
other_user = await database_sync_to_async(room_obj.other_user)(profile)
# CREATE AND ADD THE MESSAGE TO THE ROOM
message = Message.objects.create(author=profile,text=text,to=other_user.user.username)
room_obj.messages.add(message)
room_obj.updated = timezone.now()
room_obj.save()
profile = self.scope["user"].profile
clients_connected = await database_sync_to_async(Websocketclient.objects.filter)(room=int(self.room_name))
if clients_connected.count() < 2:
only_one_user = True
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'data': {"text":text,"pk":room_obj.pk,"author":{"username":message.author.user.username,"image":str(message.author.image)},"only_one_user":only_one_user}
}
)
Also how can i know what exactly is the error in my async code if i get any in future work...
Message.objects.create should also be wrapped in database_sync_to_async and room_obj.save()
in short any DB operation needs to be wrapped in database_sync_to_async.
As to why the error is be swallowed... welcome to async python :)
put a try except around the body of your function and print out the exception you get to test that the error is a this point.

Creating a twitter bot for a Discord server

I am trying to create a Discord bot that will monitor my twitter feed and post messages into a specific channel on my Discord server. I know solutions already exist for this task (zapier and IFTTT) but I am also wanting to use this as an exercise to develop my coding skills.
I have been following this example but now I haven't been able to get this to run successfully. My problem is that the bot can successfully join the Discord server and monitor my twitter feed but it won't post the message. I have used a print statement (that print(message) line) to determine that the bot does receive new tweets.
I have stored my access tokens and secret keys in another file called twitter_credentials.py (hence that import). I'm using the Tweepy and discord.py libraries, any help will be greatly appreciated - The code below uses << redacted >> identifying strings:
import tweepy, discord
import twitter_credentials
twitter_access_token = twitter_credentials.access_token
twitter_access_token_secret = twitter_credentials.access_token_secret
twitter_consumer_key = twitter_credentials.consumer_key
twitter_consumer_secret = twitter_credentials.consumer_secret
discord_token = twitter_credentials.token_twitter_bot
client = discord.Client()
class StdOutListener(tweepy.StreamListener):
""" A listener handles tweets that are received from the stream.
This is a basic listener that just prints received tweets to stdout."""
def on_status(self, status):
if not status.in_reply_to_status_id == None:
message = '#{0} : {1}'.format(status.in_reply_to_screen_name, status.text)
else:
message = '{0}'.format(status.text)
print(message)
channel = client.get_channel('<<channel_id>>')
em = discord.Embed(title='Tweet', description='My Twitter Feed', colour=0xDEADBF)
em.set_author(name='# <<Twitter_handle>>', icon_url=client.user.default_avatar_url)
client.send_message(channel, message, embed = em)
#client.event
async def on_ready():
if not client.is_logged_in:
raise Exception('Unable to connect to Discord')
else:
print('Connected to Discord')
auth = tweepy.OAuthHandler(twitter_consumer_key, twitter_consumer_secret, callback = 'oob')
auth.secure = True
auth.set_access_token(twitter_access_token, twitter_access_token_secret)
print('Starting Twitter stream')
stream = tweepy.Stream(auth, StdOutListener())
stream.filter(['<<twitter_ID>>'])
client.run(discord_token)
Thanks
Qui

Categories

Resources