Telegram Telethon : How to get messages if you know channel hash - python

When I have to deal with that kind of link : https://t.me/channelName
I usually get message from channel like this :
async def main():
channel = await client.get_entity('channelName')
messages = await client.get_messages(channel, limit = N )
#...Code etc..
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
How do you get message if you link is like this ?
https://t.me/joinchat/DDDDDxxxxAAAA
I know that 'DDDDDxxxxAAAA' is the channel_hash, so I joined the channel by telegram client and I tried get channel id and message object :
channel_hash = "DDDDDxxxxAAAA"
channel = await client(functions.messages.CheckChatInviteRequest(hash=channel_hash))
Now , channel object containes channel ID and many others fields.
example : (chat=Channel(id=123456789,...etcc
So , I tried like this:
messages = await client.get_messages(channel, limit = N )
but it returns :
Traceback (most recent call last):
File "C:\Users\****\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\telethon\sessions\memory.py", line 192, in get_input_entity
return utils.get_input_peer(key)
File "C:\Users\****\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\telethon\utils.py", line 235, in get_input_peer
_raise_cast_fail(entity, 'InputPeer')
File "C:\Users\****\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\telethon\utils.py", line 138, in _raise_cast_fail
raise TypeError('Cannot cast {} to any kind of {}.'.format(
TypeError: Cannot cast ChatInviteAlready to any kind of InputPeer.
TypeError: Cannot cast ChatInviteAlready to any kind of InputPeer.
How to get messages if you only know channel hash ?
Thanks for help

Related

Error "405 Method Not Allowed" Fast API PUT method

I encounter an error 405 during a PUT request.
I have a list of ids ids = [1, 2, 3, 4] and my goal is to update two field activated_at and updated_at with the current date time.
query.py
--------
async def validate(ids: list) -> Array:
"""Validates a list of FDES in the database"""
# Preparing the updates
updates = {
"updated_at": datetime.now(),
"validated_at": datetime.now()
}
# Making the updates
await db.fdeses.updateMany({"id": {"$in": ids}}, {"$set": updates})
# Returning the modified document
documents = await db.fdeses.find({"id": {"$in": ids}}).to_list(CURSOR_LIMIT)
return documents
controllers.py
--------------
async def validate(ids:list) -> Fdeses:
db_fdeses = await queries.fdes.validate(ids)
return db_fdeses
router.py
---------
#router.put("/admin/fdes/activate", response_model=Fdeses)
async def validate(ids:list = Body(...))->Fdeses:
response = await controllers.fdes.validate(ids)
return response
I don't understand what is wrong with my code. What 405 error exactly mean?
EDIT:
I tried a PUT method using Postman instead of my VueJS client and I have an error 500.
Why my backend return me errors on other functions than functions I use for this endpoint? In this case it returns me errors about PUT function for /admin/fdes and GET function for admin/fdes.
Here is the error on FastAPI:
INFO: 172.20.0.1:65334 - "PUT /admin/fdes/activate HTTP/1.1" 500 Internal Server Error
File "./app/routers/fdes.py", line 40, in put_fdes
response = await controllers.fdes.update_fdes(fdes_id, fdes)
File "./app/controllers/fdes.py", line 57, in update_fdes
db_fdes = await queries.fdes.select_fdes(fdes_id)
File "./app/models/queries/fdes.py", line 16, in select_fdes
fdes_id = ObjectId(fdes_id)
File "/usr/local/lib/python3.8/site-packages/bson/objectid.py", line 110, in __init__
self.__validate(oid)
File "/usr/local/lib/python3.8/site-packages/bson/objectid.py", line 213, in __validate
_raise_invalid_id(oid)
File "/usr/local/lib/python3.8/site-packages/bson/objectid.py", line 38, in _raise_invalid_id
raise InvalidId(
bson.errors.InvalidId: 'activate' is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string

Assign text list to variable python

I have a python script which allows me to check if a number is used on telegram or not.
I try to change the variable "phone_number" to a .txt list which basically contain phone number (There is one phone number per line)
I want the script to take a phone number from the file.txt check if it exists or not then move on to the next one and so on until all the numbers are checked.
This is what i try so far...
import random
from telethon import TelegramClient
from telethon import functions, types
import ast
api_id = XXXXX
api_hash = 'XXXXXXXXXXXXXXXXXX'
client = TelegramClient('session', api_id, api_hash)
async def main():
phone_in = []
with open('file.txt', 'r') as f:
phone_str = f.readline()
phone_in.append(ast.literal_eval(phone_str))
result = await client(functions.contacts.ImportContactsRequest(
contacts=[types.InputPhoneContact(
client_id=random.randrange(-2**63, 2**63),
phone=phone_in,
first_name='Some Name',
last_name=''
)]
))
if len(result.users):
print(f"{phone_in} has a telegram account")
await client(functions.contacts.DeleteContactsRequest(result.users))
else:
print(f"couldn't find an account for {phone_in}")
client.start()
client.loop.run_until_complete(main())
I tried this but I had an error which is the following :
Traceback (most recent call last):
File "/Users/me/phone.py", line 33, in <module>
client.loop.run_until_complete(main())
File "/usr/local/Cellar/python#3.9/3.9.1_7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/Users/me/phone.py", line 17, in main
result = await client(functions.contacts.ImportContactsRequest(
File "/usr/local/lib/python3.9/site-packages/telethon/client/users.py", line 30, in __call__
return await self._call(self._sender, request, ordered=ordered)
File "/usr/local/lib/python3.9/site-packages/telethon/client/users.py", line 58, in _call
future = sender.send(request, ordered=ordered)
File "/usr/local/lib/python3.9/site-packages/telethon/network/mtprotosender.py", line 174, in send
state = RequestState(request)
File "/usr/local/lib/python3.9/site-packages/telethon/network/requeststate.py", line 17, in __init__
self.data = bytes(request)
File "/usr/local/lib/python3.9/site-packages/telethon/tl/tlobject.py", line 194, in __bytes__
return self._bytes()
File "/usr/local/lib/python3.9/site-packages/telethon/tl/functions/contacts.py", line 498, in _bytes
b'\x15\xc4\xb5\x1c',struct.pack('<i', len(self.contacts)),b''.join(x._bytes() for x in self.contacts),
File "/usr/local/lib/python3.9/site-packages/telethon/tl/functions/contacts.py", line 498, in <genexpr>
b'\x15\xc4\xb5\x1c',struct.pack('<i', len(self.contacts)),b''.join(x._bytes() for x in self.contacts),
File "/usr/local/lib/python3.9/site-packages/telethon/tl/types/__init__.py", line 9789, in _bytes
self.serialize_bytes(self.phone),
File "/usr/local/lib/python3.9/site-packages/telethon/tl/tlobject.py", line 112, in serialize_bytes
raise TypeError(
TypeError: bytes or str expected, not <class 'list'>
Here is the same code but the phone number to check is "hardcoded"
import random
from telethon import TelegramClient
from telethon import functions, types
api_id = XXXXXXX
api_hash = 'XXXXXXXXXXXXXXXXX'
client = TelegramClient('session', api_id, api_hash)
async def main():
phone_number = '+XXXXXXXXX'
result = await client(functions.contacts.ImportContactsRequest(
contacts=[types.InputPhoneContact(
client_id=random.randrange(-2**63, 2**63),
phone=phone_number,
first_name='Some Name',
last_name=''
)]
))
if len(result.users):
print(f"{phone_number} has a telegram account")
await client(functions.contacts.DeleteContactsRequest(result.users))
else:
print(f"couldn't find an account for {phone_number}")
client.start()
client.loop.run_until_complete(main())
Does anyone know how I can assign the file.txt to the phone_in variable?
If ImportContactsRequests expects one phone number at a time, then you have to call it for each phone number. That will create multiple records for a single name, but if the API doesn't allow multiple phone numbers per person, you'll have to decide how to handle it.
with open('file.txt', 'r') as f:
phone_str = f.readline()
result = await client(functions.contacts.ImportContactsRequest(
contacts=[types.InputPhoneContact(
client_id=random.randrange(-2**63, 2**63),
phone=phone_str,
first_name='Some Name',
last_name=''
)]
))
if len(result.users):
print(f"{phone_number} has a telegram account")
await client(functions.contacts.DeleteContactsRequest(result.users))
else:
print(f"couldn't find an account for {phone_number}")
According to the doc of InputPhoneContact, the phone argument takes string type not list. So you could read all phones in the file.txt first, then loop through the list.
async def main():
phone_in = []
with open('file.txt', 'r') as f:
phone_str = f.readline()
phone_in.append(ast.literal_eval(phone_str))
for phone in phone_in:
result = await client(functions.contacts.ImportContactsRequest(
contacts=[types.InputPhoneContact(
client_id=random.randrange(-2**63, 2**63),
phone=phone,
first_name='Some Name',
last_name=''
)]
))
if len(result.users):
print(f"{phone} has a telegram account")
await client(functions.contacts.DeleteContactsRequest(result.users))
else:
print(f"couldn't find an account for {phone}")
python does allow for creation of heterogeneous lists, so not sure why this is throwing an error. Depending on the version in use, maybe there is a constraint on the type homogeneity in the list.I'm not sure though...but curious to know if the following works?
Can you try with a small version of the file in which the numbers are of the same 'type'?
Alternately, can try with a x.strip("[/{(") before appending it to phone_in.

TypeError: 'NoneType' object is not iterable - SQLite and discord.py

The function will check if the channel with the reaction is a private channel between bot and user and then do other things.
The code:
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
msg = await channel.fetch_message(payload.message_id)
emoji = payload.emoji
author = payload.member
if emoji.is_custom_emoji():
emoji_count = discord.utils.get(msg.reactions, emoji=emoji).count
else:
emoji_count = discord.utils.get(msg.reactions, emoji = emoji.name).count
cur.execute(f"SELECT discord_user_dmchannel_id FROM users WHERE discord_user_id = \
{int(payload.user_id)};")
print(cur.fetchone())
channel_dm_id_list = list(cur.fetchone())
channel_dm_id = channel_dm_id_list[0]
if payload.channel_id == channel_dm_id:
if int(emoji_count) > 1:
if emoji = ...
The output:
(782664385889959976,)
Ignoring exception in on_raw_reaction_add
Traceback (most recent call last):
File "C:\Users\plays\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py",
line 312, in _run_event
await coro(*args, **kwargs)
File "C:\Users\plays\OneDrive\Рабочий стол\Python\bot2.py", line 130, in on_raw_reaction_add
channel_dm_id_list = list(cur.fetchone())
TypeError: 'NoneType' object is not iterable
The table columns:
users(
discord_user_id INT PRIMARY KEY,
discord_user_dmchannel_id INT,
discord_user_name TEXT,
...
...);
fetchone() is returning the next row.
In the line print(cur.fetchone()) you are already getting the first row. In the next line channel_dm_id_list = list(cur.fetchone()) you are trying to get the second value. But since there is no second value, the method returns None which is causing your error. So either remove the print statement or store the first result like that:
channel_dm_id_list = list(cur.fetchone())
print(channel_dm_id_list)

Creating private Vc discord.py

I am trying to create a private vc for a function i am trying to make. it makes the vc with the permissions i want it to make, but then it gives an error after it made it and i cannot put any code behind it.
This is the code:
guild = ctx.author.guild
players_role = await guild.create_role(name=f"Players {game_id}")
for i in all_players:
print(all_players)
print(i)
i = guild.get_member(int(i[1]))
await i.add_roles(players_role)
overwrites = {
guild.default_role: discord.PermissionOverwrite(view_channel=False),
players_role: discord.PermissionOverwrite(view_channel=True)
}
players_vc = await guild.create_voice_channel(f"Game: {game_id}", overwrites=overwrites)
await players_vc.edit(position=len(ctx.guild.voice_channels))
print("edited position")
What I am trying to do is edit the vc I created so that it gets pulled to the bottom, but it doesnt do this, because it gives an error in the previous line. I tried putting the players_vc = await guild.create_voice_channel(f"Game: {game_id}", overwrites=overwrites) in try: and except: but I need the variable to edit the position. here is the error message:
Traceback (most recent call last):
File "C:\Users\Gebruiker\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\core.py", line 83, in wrapped
ret = await coro(*args, **kwargs)
File "D:\Thijs coding map\TeaBot\TeaBot.py", line 889, in vc_test
test_vc = await guild.create_voice_channel(f"test vc", overwrites=overwrites)
File "C:\Users\Gebruiker\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\guild.py", line 888, in create_voice_channel
channel = VoiceChannel(state=self._state, guild=self, data=data)
File "C:\Users\Gebruiker\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\channel.py", line 553, in __init__
self._update(guild, data)
File "C:\Users\Gebruiker\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\channel.py", line 584, in _update
self._fill_overwrites(data)
File "C:\Users\Gebruiker\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\abc.py", line 294, in _fill_overwrites
self._overwrites.append(_Overwrites(id=overridden_id, **overridden))
TypeError: __new__() got an unexpected keyword argument 'allow_new'
for troubleshooting, you can use this code:
#client.command()
async def vc_test(ctx):
guild = ctx.guild
user = ctx.author
overwrites = {
guild.default_role: discord.PermissionOverwrite(view_channel=False),
guild.me: discord.PermissionOverwrite(view_channel=True)
}
test_vc = await guild.create_voice_channel(f"test vc", overwrites=overwrites)
await test_vc.edit(position=len(guild.voice_channels))
print("edited position")
I couldn't find this issue elsewhere
all help is appreciated
solution:
venv\lib\site-package\discord\abc.py
open and find
_Overwrites = namedtuple('_Overwrites', 'id allow deny type')
and replace
class _Overwrites:
__slots__ = ('id', 'allow', 'deny', 'type')
def __init__(self, **kwargs):
self.id = kwargs.pop('id')
self.allow = kwargs.pop('allow', 0)
self.deny = kwargs.pop('deny', 0)
self.type = kwargs.pop('type')
def _asdict(self):
return {
'id': self.id,
'allow': self.allow,
'deny': self.deny,
'type': self.type,
}
You can look here

Python - send uint8 and uint16 to socket

I'm trying to send some data with a python script to a java server. I use the socket module in python to send and recieve data.
When I send data, I need to specify a header with the datalength in it. The header is as following:
a uint8 for the version number
a uint8 for padding ('reserved')
a uint16 for the length of the data that is sent
That is a total of 32 bits.
I can use numpy to create an array with a certain data type, but the problem is sending this data through the socket. I use the following function to send data:
def send(socket, message):
r = b''
totalsent = 0
# as long as not everything has been sent ...
while totalsent < len(message):
# send it ; sent = actual sent data
sent = socket.send(message[totalsent:])
r += message[totalsent:]
# nothing sent? -> something wrong
if sent == 0:
raise RuntimeError("socket connection broken")
# update total sent
totalsent = totalsent + sent
return r
message = (something_with_numpy(VERSION_NUMBER, PADDING, len(data)))
send(socket, message)
I keep getting TypeErrors with this function. These pop up at len(message), r += message[...], or some other place.
I was wondering if there is a better way to do this, or how to fix this so it does work?
UPDATE: here are some exact error traces. I have tried several different things, so these error traces might have become irrelevant.
Traceback (most recent call last):
File "quick.py", line 47, in <module>
header += numpy.uint8(VERSION_NUMBER)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')
header = numpy.array([VERSION_NUMBER * 255 + PADDING, len(greetData)], dtype=numpy.uint16)
Traceback (most recent call last):
File "quick.py", line 48, in <module>
print(header + greetData)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S22') dtype('S22') dtype('S22')
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.uint8(VERSION_NUMBER))
File "quick.py", line 13, in send
while totalsent < len(message):
TypeError: object of type 'numpy.uint8' has no len()
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.array([VERSION_NUMBER], dtype=numpy.uint8))
File "quick.py", line 17, in send
r += message[totalsent:]
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')
You'll want to use the struct module to format the header before sending the data.
import struct
def send_message(socket, message):
length = len(message)
version = 0 # TODO: Is this correct?
reserved = 0 # TODO: Is this correct?
header = struct.pack('!BBH', version, reserved, length)
message = header + message # So we can use the same loop w/ error checking
while ...:
socket.send(...)

Categories

Resources