Telethon reading message from Channel with id - python

Hello I'm using Telethon 1.21.1 
The most question here are outdated.
This scripts task is to read a message of a specific Channel per id.
I'm not sure where to pass the info for the channel and how if I use the method to read the msg in the proper way. await but I'm not sure how I pull it off
This is what I have:
my_private_channel_id = "-100777000"
my_private_channel = "test"
api_id = # 7 Digit Telegram API ID.
api_hash = '' # 32 Character API Hash
phone = '+' #Enter Your Mobilr Number
client = TelegramClient(phone, api_id, api_hash)
async def main():
await client.send_message('me', 'Hello !!!!') # just to test connection
with client:
client.loop.run_until_complete(main())
client.connect()
if not client.is_user_authorized():
client.send_code_request(phone)
client.sign_in(phone, input('Enter verification code: '))
chats = []
last_date = None
chunk_size = 200
channels=[] #target channel
result = client(GetDialogsRequest(
offset_date=last_date,
offset_id=0,
offset_peer=InputPeerEmpty(),
limit=chunk_size,
hash = 0
))
chats.extend(result.chats)
for chat in chats:
try:
if chat.channels== True:
readmsg = client.get_messages(chat, None)
except:
continue

from telethon import TelegramClient, events
client = TelegramClient('session', api_id, api_hash)
#client.on(events.NewMessage(chats="#TelethonUpdates"))
async def my_event_handler(event):
print(event.text)
client.start()
client.run_until_disconnected()
This is the right and simple way.

Related

Discord.py async-await won't close connection with Airflow DAG/Task

I'm trying to post a dataframe to a Discord channel. However, I am having issue getting Discord.py to close the connection and move on the next task. I've tried using the event loop as suggested in this thread (How to run async function in Airflow?) as well as asyncio.run() function. Not really familiar with the async and hoping to get some pointers here. Below is my code in Python that I've tried importing in DAG and Task without success. Thanks in advance!
Airflow: 2.5.1
Python: 3.7
import discord
from tabulate import tabulate
import asyncio
import pandas as pd
async def post_to_discord(df, channel_id, bot_token, as_message=True, num_rows=5):
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
try:
#client.event
async def on_ready():
channel = client.get_channel(channel_id)
if as_message:
# Post the dataframe as a message, num_rows rows at a time
for i in range(0, len(df), num_rows):
message = tabulate(df.iloc[i:i+num_rows,:], headers='keys', tablefmt='pipe', showindex=False)
await channel.send(message)
else:
# Send the dataframe as a CSV file
df.to_csv("dataframe.csv", index=False)
with open("dataframe.csv", "rb") as f:
await channel.send(file=discord.File(f))
# client.run(bot_token)
await client.start(bot_token)
await client.wait_until_ready()
finally:
await client.close()
async def main(df, channel_id, bot_token, as_message=True, num_rows=5):
# loop = asyncio.get_event_loop()
# result = loop.run_until_complete(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
result = asyncio.run(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
await result
return result
if __name__ =='__main__':
main()
It seems like your script works but the server is blocking the open socket (and kudos - the discord server is good at that). So we will work by creating a ping function (adopted from another answer).
def ping(ip, port):
try:
s = socket.socket() # TCP - standard values are `socket.AF_INET, socket.SOCK_STREAM` so you don't have to write them
s.settimeout(2)
print('[DEBUG] connect')
s.connect((ip, int(port)))
#result = s.connect_ex((ip, int(port)))
#print('result:', result)
return True
except socket.timeout as ex:
print('[DEBUG] timeout')
return True
except Exception as ex:
print('[Exception]', ex)
return False
finally:
print('[DEBUG] close')
s.close()
Feel free to test your ID
id = ...channel number...
print(id, type(id))
and you should see
<built-in function id> <class 'builtin_function_or_method'>
Then let us move on to improving your code:
import discord
import asyncio
import time # you are not using this module
import socket
import os
from tabulate import tabulate
import pandas as pd # as pd is not required
def ping(ip, port):
try:
s = socket.socket() # TCP - standard values are `socket.AF_INET, socket.SOCK_STREAM` so you don't have to write them
s.settimeout(2)
print('[DEBUG] connect')
s.connect((ip, int(port)))
#result = s.connect_ex((ip, int(port)))
#print('result:', result)
return True
except socket.timeout as ex:
print('[DEBUG] timeout')
return True
except Exception as ex:
print('[Exception]', ex)
return False
finally:
print('[DEBUG] close')
s.close()
TOKEN = os.getenv('DISCORD_TOKEN')
client = discord.Client()
async def post_to_discord(df, channel_id, bot_token, as_message=True, num_rows=5):
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
try:
#client.event
async def on_ready():
channel = client.get_channel(channel_id)
if as_message:
# Post the dataframe as a message, num_rows rows at a time
for i in range(0, len(df), num_rows):
message = tabulate(df.iloc[i:i+num_rows,:], headers='keys', tablefmt='pipe', showindex=False)
await channel.send(message)
else:
# Send the dataframe as a CSV file
df.to_csv("dataframe.csv", index=False)
with open("dataframe.csv", "rb") as f:
await channel.send(file=discord.File(f))
# client.run(bot_token)
await client.start(bot_token)
await client.wait_until_ready()
while True:
online = ping("26.51.174.109", "25565") #modify it as you see fit
#online = ping("192.168.1.101", "8081") #same as above
if online:
print("server online")
#await channel.edit(name="Server Status - Online")
else:
print("server offline")
#await channel.edit(name="Server Status - Offline")
await asyncio.sleep(5)
# optional - client.run(TOKEN)
finally:
await client.close()
async def main(df, channel_id, bot_token, as_message=True, num_rows=5):
# loop = asyncio.get_event_loop()
# result = loop.run_until_complete(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
result = asyncio.run(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
await result
return result
if __name__ =='__main__':
main()

ValueError (Could not find the input entity) when using Telethon

Code:
client = TelegramClient('session_name', api_id, api_hash)
client.start()
async def FirstFunction():
await client(AddChatUserRequest(
chat_id=1234,
user_id=1234,
fwd_limit=10
))
client.loop.run_until_complete(FirstFunction())
Error:
ValueError: Could not find the input entity for PeerUser(user_id=1234) (PeerUser).
Note: I am using the same id for chat_id + user_id

valueerror: you also need to provide a phone_code_hash

from telethon.sync import TelegramClient
from telethon.tl.functions.messages import GetDialogsRequest
from telethon.tl.types import InputPeerEmpty
api_id = XXXXXXX
api_hash = 'XXXXXXXXXXXXXXXXXXXXXXXX'
phone = '+XXXXXXXXXXX'
client = TelegramClient(phone, api_id, api_hash)
client.connect()
if not client.is_user_authorized():
client.send_code_request(phone)
phone_code_hash = client.send_code_request(phone).phone_code_hash
client = TelegramClient(phone, api_id, api_hash)
client.connect()
client.sign_in(phone, input('Enter the code: '))
How can I pass it on phone_code_hash to the check client.sign_in(phone, input('Enter the code: '))
If you do not insert the cache, an error occurs valueerror: you also need to provide a phone_code_hash.
The hash must be entered in the fifth entry
client = TelegramClient(phone, api_id, api_hash)
client.connect()
if not client.is_user_authorized():
client.send_code_request(phone)
phone_code_hash = client.send_code_request(phone).phone_code_hash
client = TelegramClient(phone, api_id, api_hash)
client.connect()
client.sign_in(phone, input('Enter the code: '), phone_code_hash=phone_code_hash)
I took the answer from here https://github.com/LonamiWebs/Telethon/blob/9445d2ba535ed7d214a7e6e68b85e7f3af1a690e/telethon/telegram_client.py#L141-L149

Run two asynco loop in a python script (telethon, aiopg)

I would like to use Telethon (Telegram bot) and aiopg (PostgreSQL) library.
Telethon example:
from telethon import TelegramClient
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('anon', api_id, api_hash)
async def main():
# Getting information about yourself
me = await client.get_me()
print(me.stringify())
#client.on(events.NewMessage)
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.reply('hi!')
client.start()
client.run_until_disconnected()
aiopg example:
import aiopg
dsn = 'dbname=aiopg user=aiopg password=passwd host=127.0.0.1'
async def notify(conn):
async with conn.cursor() as cur:
for i in range(5):
msg = "message {}".format(i)
print('Send ->', msg)
await cur.execute("NOTIFY channel, %s", (msg,))
await cur.execute("NOTIFY channel, 'finish'")
async def listen(conn):
async with conn.cursor() as cur:
await cur.execute("LISTEN channel")
while True:
msg = await conn.notifies.get()
if msg.payload == 'finish':
return
else:
print('Receive <-', msg.payload)
async def main():
async with aiopg.create_pool(dsn) as pool:
async with pool.acquire() as conn1:
listener = listen(conn1)
async with pool.acquire() as conn2:
notifier = notify(conn2)
await asyncio.gather(listener, notifier)
print("ALL DONE")
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I would like to use both in a same python script.
I tried to find the solution and it is maybe the asyncio.gather(...), but I don't know how can I combine these two library, how to start both loop.
Can you please help me?
create a new async function which creates a new client instance and add all the handlers you need, for the sake of this example I showed some example handlers of mine.
async def init_bot() -> TelegramClient:
client = TelegramClient(
session="trade-bot",
api_hash=Config.API_HASH,
api_id=Config.API_ID,
)
await client.start(bot_token=Config.BOT_TOKEN)
client.add_event_handler(
register_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]register$"),
)
client.add_event_handler(
get_webhook_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]webhook$"),
)
client.add_event_handler(
status_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]status$"),
)
_LOG.info("Bot client started")
return client
then later on you main function
client = await init_bot()
await client.connect()
# the below code is non-blocking
asyncio.create_task(client.run_until_disconnected())

How to get channels and groups data from my Telegram account?(Python)

How can I get last posts and messages from all channel and groups in my Telegram account using "telethon".
At first you should get your "api_id" and "api_hash" from Telegram API.
then you should use following code to connect to your Telegram account.
from telethon.sync import TelegramClient
from telethon.errors import SessionPasswordNeededError
# Create the client and connect
client = TelegramClient(you_username, api_id, api_hash)
client.start()
print("Client Created")
# Ensure you're authorized
if not client.is_user_authorized():
client.send_code_request(your_phone)
try:
client.sign_in(phone, input('Enter the code: '))
except SessionPasswordNeededError:
client.sign_in(password=input('Password: '))
In the next step we define a def to get last message of an entity (like channel or group):
from telethon.tl.functions.messages import GetHistoryRequest
def get_entity_data(entity_id, limit):
entity = client.get_entity(entity_id)
today = datetime.datetime.today()
# y = today - datetime.timedelta(days=1)
posts = client(GetHistoryRequest(
peer=entity,
limit=limit,
offset_date=None,
offset_id=0,
max_id=0,
min_id=0,
add_offset=0,
hash=0))
messages = []
for message in posts.messages:
messages.append(message.message)
return messages
This def gets id of a channel or group and limit on number of messages that we want to get from any channels and groups and returns the messages.
Then you should get all groups and channels using this code:
from telethon.tl.functions.messages import GetDialogsRequest
result = client(GetDialogsRequest(
offset_date=None,
offset_id=0,
offset_peer=InputPeerEmpty(),
limit=100,
hash=0))
entities = result.chats
And in last step you should iterate on entities and get last messages(for example 10 in following code)
for entity in entities:
title = entity.title
messages = get_entity_data(entity.id, 10)
print(title + ' :')
print(messages)
print('#######')

Categories

Resources