英文:
How to use numeric chat IDs to avoid expensive `get_entity(channel_name)` calls?
问题
根据这个评论,我尝试在我的Telethon代码中使用数字通道ID,以避免通过昂贵的名称查找调用而使Telegram API受到限制,但我遇到了一些困难。
例如,假设我已经实例化并连接了client
:
messages = client.get_messages(numeric_channel_id)
...出现以下错误:
ValueError: 无法找到PeerUser(user_id=[numeric_channel_id])(PeerUser)的输入实体
我认为这里发生了一些缓存,因为如果我首先使用帐户名称进行get_entity
调用,然后get_messages
调用就可以正常工作。也就是说,类似这样的操作:
client.get_entity(channel_name_which_belongs_to_numeric_channel_id)
messages = client.get_messages(numeric_channel_id)
这个方法运行正常,但现在我正在执行昂贵的get_entity(name)
调用,这正是我试图避免的(因为它将导致FloodWaitError
问题)。
在这种情况下,是否有任何方法可以使用通道的数字ID来避免昂贵的get_entity
调用?
我还尝试过强制实体类型为通道,如下所示:
channel = Channel(id=numeric_channel_id, title=None, photo=None, date=None)
messages = client.get_messages(channel)
...但结果是相同的,只是错误中提到了PeerChannel
而不是PeerUser
。
英文:
As per this comment, I'm trying to use numeric channel IDs in my telethon code, so that I don't end up spamming the Telegram API with expensive name lookup calls and getting throttled, but I'm having some difficulty.
e.g. assuming I've already instantiated and connected client
:
messages = client.get_messages(numeric_channel_id)
...fails with this error:
ValueError: Could not find the input entity for PeerUser(user_id=[numeric_channel_id]) (PeerUser)
I think there's some cacheing going on, because if I do a get_entity
call using the account name first, then the get_messages
call works. i.e. something like this:
client.get_entity(channel_name_which_belongs_to_numeric_channel_id)
messages = client.get_messages(numeric_channel_id)
That works just fine, but now I'm doing the expensive get_entity(name)
call which is what I'm trying to avoid (because it will result in FloodWaitError
problems).
Is there any way I can use the numeric ID of a channel to avoid the expensive get_entity
call, in this scenario?
I've also tried forcing the entity type to Channel, like this:
channel = Channel(id=numeric_channel_id, title=None, photo=None, date=None)
messages = client.get_messages(channel)
...but the results are the same, except that the error mentions PeerChannel
rather than PeerUser
答案1
得分: 1
ID使用不会生效,除非您像您所说的那样缓存了目标,这是使用整数ID的唯一方法。
您必须已经通过事件或手动请求(例如,获取用户名)遇到了实体。
您应该使用client.get_input_entity('username')
。
它会首先尝试在本地缓存中搜索已保存的ID +哈希,以查找与传递的用户名相等的内容,如果找到,它将不会执行ResolveUsername(较重的操作),而是使用本地的access_hash + ID,并返回一个inputPeer。然后,您可以将其传递给您想要的任何请求。
除非您确定已经遇到了其持有者,否则不能仅仅使用ID,换句话说,您使用的ID必须是您在库内并在同一会话中找到的,而不是您从外部获知的东西。
没有通过ID来获取某些内容的神奇方式,如果您确实知道它,那么库必须在存在access_hash时创建一个InputPeer
。
英文:
ID usage is not going to work unless you cached the target as you stated, that's the only way to use the integer id.
you must have met the entity from events or manual requests (say, username fetching).
you should be using client.get_input_entity('username')
it will try to search the local cache first for the saved id + hash that equals the passed username, if found it won't do ResolveUsername (heavy one) and use the local access_hash + id and return you an inputPeer. you pass that to any request you want.
you mustn't use id alone unless you're certain you have met its holder, in other words, id you use has to be something you found out from within the library and within the same session, not something you knew/found out externally.
There is no magical way to fetch something with id you claim you know, if you actually know it, the lib has to create (when the access_hash is present) an InputPeer
答案2
得分: 1
如另一个答案所述,按用户名获取数据始终有效但代价高昂。但请注意,这种调用会填充缓存,因此稍后可以通过ID更便宜地再次获取。
如果您确实需要对某个实体进行稳定引用,不能依赖会话缓存,并且希望避免使用用户名,可以参考实体与输入实体的文档可能会有所帮助。
归根结底,您可以这样做:
print(await client.get_input_entity('username'))
...这将显示类似于以下内容:
InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
...然后,调用get_input_entity
的帐户将始终能够使用打印出的结果,无需将其放入缓存中:
from telethon.tl.types import InputPeerChannel
USERNAME = InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
# ...
await client.send_message(USERNAME, 'Hi') # 不需要缓存即可正常工作
英文:
As the other answer states, fetching by username will always work but is expensive. However note that such a call will fill the cache so it can later be fetched again much more cheaply by ID.
If you really need a stable reference to some entity and cannot rely on the session cache, and want to avoid usernames, the documentation for Entities vs. Input Entities may be helpful.
What it boils down to is, you can do this:
print(await client.get_input_entity('username'))
...which will show something like:
InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
...and then, the account that made the get_input_entity
call will always be able to use the printed result, without the need for it to be in cache:
from telethon.tl.types import InputPeerChannel
USERNAME = InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
# ...
await client.send_message(USERNAME, 'Hi') # works without cache
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论