cjongseok / mtproto

Telegram MTProto and its proxy (over gRPC) in Go (golang). API Layer: 71
Apache License 2.0
151 stars 20 forks source link

Feature to load external session #10

Closed moelius closed 6 years ago

moelius commented 6 years ago

Hi, is it possible to load a session from some external storage to your library? We using https://github.com/LonamiWebs/Telethon and we have session store in redis with rate limiting and we can load session from there. Session is in format: {\"phone\":******,\"api_id\":\"****\",\"api_hash\":\"****\",\"id\":\"****\",\"port\":***,\"salt\":\"***\",\"sequence\":****,\"time_offset\":***,\"server_address\":\"****\",\"auth_key_data\":\"***\"}

I looked one eye at the library and can help if necessary with programming. Or you do not interest it and it's easier for us to make a fork?

cjongseok commented 6 years ago

@moelius Thanks for your interest in my code. This mtproto stores a session as a file but api_id, api_hash, and phone number. It seems it is reasonable to include these values together into the session file in such JSON format. Before getting into this feature, I need to check some fields above. If there is no compatibility issue, your help would be great.

cjongseok commented 6 years ago

@moelius I think "auth_key_data" would contain more fields, e.g. key and hash pair. Can you check it?

moelius commented 6 years ago

@cjongseok auth_key_data looks like: QawytUyZakqTqse4m4OQuDsH18cMiFRSUq2yZb5w23F3yjc+qfpjeB7np397TcrWtMJ2+4CosTaMNJGMzGKEimZg5SXpx36vmtsMxqvlCveU0REpL54R8i8wLaprWRcp9NdYWIkBChqOwfF04yT+kKONOlNqDTbpuXgb+Nvya5eoHmb9Ycqf3feVD3oWAE39oSjgys2em0HwfJBNIUv329mKnc60i1TWPYcEe14Wfy1YMTb9BGrUtc4STqX3SUw/ePEk7uJPn8wJlIhOf31v/5YZZ8fm7rBuq51B+xNZeQlSFbtU0Ze+4zGcUFEwz9TmXjKI8oZIx14OO6I8IVuBSw==

The code how telethon do this here: https://github.com/LonamiWebs/Telethon/blob/master/telethon/helpers.py

https://core.telegram.org/mtproto/description#defining-aes-key-and-initialization-vector

cjongseok commented 6 years ago

@moelius good. auth_key.key_id in helpers.py is what I was looking for. It seems it re-calculates key_id whenever it loads the key from the session according to AuthKey class.

And is ezdev128/telethon-session-redis the session on Redis you use? I found the link in Telethon docs. If so, can you check whether 'auth_key_data' is same with 'auth_key'? because I cannot find 'auth_key_data' there. If your 'auth_key_data' is equivalent with 'auth_key', I can believe 'auth_key_data' is the key itself, not a composed object.

moelius commented 6 years ago

No, we use external redis store with rate limits, access_hash for every channel we parsing, it's not a part of this library. Then we get session from store and loads this as memory telethon session and update it each time after request. And yes 'auth_key_data' is equivalent with 'auth_key' but we do some decode operation. It was some issue as I remember to store without. We communicate with grpc with external session store. This is release method.

 @telegram_response_handler
 def release(self, phone, request, api_id, api_hash, access_hash, tl_session):
        """

        :param phone:
        :param request:
        :param api_id:
        :param api_hash:
        :param access_hash:
        :type tl_session: telethon.sessions.MemorySession
        :return:
        """
        return self.stub.Release(
            messages.SubscribedSession(request=request, access_hash=str(access_hash),
                                       session=messages.Session(phone=phone, api_id=str(api_id), api_hash=api_hash,
                                                                id=str(tl_session.id), port=tl_session.port,
                                                                salt=str(tl_session.salt),
                                                                sequence=tl_session._sequence,
                                                                time_offset=tl_session.time_offset,
                                                                server_address=tl_session.server_address,
                                                                auth_key_data=b64encode(tl_session.auth_key.key).decode(
                                                                    'ascii'))))
moelius commented 6 years ago

@cjongseok I founded, after we got session from store we use it to make AuthKey from store auth_key_data: https://github.com/LonamiWebs/Telethon/blob/master/telethon/crypto/auth_key.py sess._auth_key = AuthKey(data=b64decode(store_session.auth_key_data)) sess is telethon memory session.

cjongseok commented 6 years ago

@moelius I implemented credentials.json and pushed it to the credentials_json branch. Its JSON is:

{
  "phone": string,
  "api_id": number,
  "api_hash": string,
  "ip": string,
  "port": number,
  "salt": string,
  "auth_key": string
}

I renamed auth_key_data to auth_key, because it seems auth_key is more general naming in Telethon and others. In the JSON, both salt and auth_key, which are not alphanumeric, are encoded in base64 to make them human readable. These are decoded when mtproto reads credentials.json. I think this format also makes sense to your case. You can try it with the above commit(35f5056).

cjongseok commented 6 years ago

It is merged to main branch, 142b7f31f963a074dac9dd6759e0ae054e4a894c