In the following example on the wiki retrieving an entity#via GetContactsRequest it is recommended to use the user's access_hash to request users and contacts.
contacts = client(GetContactsRequest(self_user.access_hash))
client.get_me().access_hash is a _long_.
However, the API expect's an _int_ not a _long_, and throws an exception.
in a comment, it's mentioned that an empty hash works, this is not the case.
So what am I missing? The example in the wiki doesn't work, but is it a bug?
Am I not understanding the hash required by telethon.tl.functions.contacts.GetContactsRequest?
the code (relevant snippets):
cli = TelegramClient(conf['name'], api_id=conf['app_id'], api_hash=conf['api_hash'])
cli.connect()
me = cli.get_me()
...
getContacts = telethon.tl.functions.contacts.GetContactsRequest(me.access_hash)
Contacts = cli(getContacts)
error:
.../lib/python3.6/site-packages/telethon/tl/functions/contacts.py", line 233, in to_bytes
struct.pack('<i', self.hash),
struct.error: 'i' format requires -2147483648 <= number <= 2147483647
PS: thanks for Telethon, it's so much more stable and predictable than competing solutions
Hey there I had a similar issue:
https://github.com/LonamiWebs/Telethon/issues/269
If you substitute you me.access_hash for 0 it works fine.
Its some undisclosed formed hash value they are expecting in order to retrieve only contacts not retrieved before, so by passing an empty hash ( 0 ) it works as @Lonami explained in the issue I opened.
it is recommended to use the user's access_hash to request users and contacts.
Whoops, that wrong. It's supposed to be a special hash calculated based on how the contacts you're aware of, so that Telegram can send only the latest changes. I need to update the wiki, or you can do it if you wish. Starting value should be 0. I don't know how to calculate such hash, but clients like Unigram should have the algorithm.
an empty hash works, this is not the case.
It doesn't? Passing 0 should return all.
struct.error: 'i' format requires -2147483648 <= number <= 2147483647
Yes, passing 0 should work then.
PS: thanks for Telethon, it's so much more stable and predictable than competing solutions
Thanks for this, some cheering is needed when all it seems is that everyone else has errors or offer other better/new alternatives…
Thanks to you both!
0 works indeed, although calling it an empty hash is misleading (for me).
I've modified the example in the wiki. I'd love to understand the hash and what we're supposed to put there though.
I'd love to understand the hash and what we're supposed to put there though.
Me too, let's keep this open and see if someone would like to help. To solve this issue, the task is to port to Python the method that calculates the hash based on the contacts you know already. Simply make a pull request with the algorithm and I'll try to figure out how to embed it nicely in the library (or you can do that too!).
These are @stek29's thoughts, cleaned up a bit.
Turns out
-O2changes the behaviour of the shift, while-O0gives the same result. Shifting is defined as "unsigned divide by 2 X times" in the Intel's ASM manual. So why doesn't it return zero? […] Shifting by 33 actually behaves like shifting by 1, sinceshris shift and rotate:In a logical shift instruction (also referred to as unsigned shift), the bits that slide off the end disappear (except for the last, which goes into the carry flag), and the spaces are always filled with zeros. Logical shifts are best used with unsigned numbers.
"Always filled with zeroes" doesn't seem to be the case here.
[…]
Turns out the algorithm was originally designed for 64 bits, since the document IDs are longs. For 32 bits however it's a no-op. The developers didn't even read the algorithm. This code is equivalent:
func hashIdsOpt(_ ids: [Int32]) -> Int32 { var acc: UInt32 = 0 for id in ids { acc = (acc &* 20261) acc = (acc &* 20261) &+ UInt32(bitPattern: id) } return Int32(bitPattern: acc & UInt32(0x7FFFFFFF)) }So there were supposed to be a version for both 64 and 32 bits but they simply copy-pasted the 64 bit version for 32, which worked surprisingly only because they used high level language on x86_64 (Swift). Java was fine too and on iOS they saw no issues because ARM handles shift by integer size "correctly".
(official developer) It was written for int64 initially.
Seems like things changed between Swift3 and Swift4 as the later doesn't crash. Here's even another version:
def hash20261_32(ints): acc = 0 for id in ints: acc = (acc * 20261 * 20261 + id) & 0xffff_ffff return acc & 0xffff_ffffEven with these changes, the algorithm doesn't work. All contacts are resent, even with all possible combinations of versions for the algorithm.
TL;DR, even if we add the algorithm, it won't be of any use (yet).
Thanks for the follow up @Lonami and keep up the great job. Will keep an eye on their API changes as well.
@Ilhicas It's easier to do that [keep an eye on changes] with https://github.com/stek29/tl-schema :)