2

In reference to How to implement authorization using a Telegram API? This is the best telegram documentation I have yet to find! Thanks for that.

I am attempting to create a Python library to make calls to telegram.org. I can authenticate as described in the above link but ran into issues with method responses returning in a format found only in a previous layer. In other words, my client is calling a method from one layer of the api but the server is responding with a data format from an older api layer. I confirmed this by searching an older api layer file for the return id.

{
    "id": "571849917",
    "params": [
        {
            "name": "phone_registered",
            "type": "Bool"
        },
        {
            "name": "phone_code_hash",
            "type": "string"
        }
    ],
    "predicate": "auth.sentCode",
    "type": "auth.SentCode"
},

The format my client is expecting is this:

{
    "id": "-269659687",
    "params": [
        {
            "name": "phone_registered",
            "type": "Bool"
        },
        {
            "name": "phone_code_hash",
            "type": "string"
        },
        {
            "name": "send_call_timeout",
            "type": "int"
        },
        {
            "name": "is_password",
            "type": "Bool"
        }
    ],
    "predicate": "auth.sentCode",
    "type": "auth.SentCode"
},

So, I read in the telegram docs I need to call invokeWithLayer to make sure the client and server have their api layers in synch.

Several questions:

  1. Given a telegram api schema file, is there a way to determine from the schema which layer it is? Or do you just "simply have to know"?
  2. When calling invokeWithLayer how do you format the 'query' parameter? Do you have to serialize the query first?

Here is my initConnection code where I serialize each method before using it as a parameter. Unfortunately, the response is not favorable. The first response is:

('initConnection - msg: ', {u'messages': [{u'body': {u'first_msg_id': 6312441942040617984L, u'unique_id': 986871592203578887L, u'server_salt': 7658270006181864880L}, u'seqno': 1, u'msg_id': 6312441944354392065L, u'bytes': 28}, {u'body': {u'msg_ids': [6312441942040617984L]}, u'seqno': 2, u'msg_id': 6312441944354450433L, u'bytes': 20}]})

The second response is:

{u'req_msg_id': 6312441942040617984L, u'result': {u'error_message': 'INPUT_METHOD_INVALID', u'error_code': 400}})

...and the code:

 def initConnection(self, config):
    '''Set the API layer and initialize the connection'''

    # get the required config data
    api_layer = config.getint('App data', 'api_layer')
    api_id = config.getint('App data', 'api_id')
    version = config.get('App data', 'version')
    print
    print('----------------------------------------------')
    print('initConnection - api_layer: ', api_layer)
    print('initConnection - api_id:    ', api_id)
    print('initConnection - version:   ', version)

    # serialize a candidate method as a parameter. It doesn't
    # matter what it is so we will use something simple like get_future_salts.
    simpleQuery=TL.tl_serialize_method('get_future_salts', num=3)

    # serialize the initConnection method
    initConnectionQuery = TL.api_serialize_method('initConnection', api_id=api_id,
                                                 device_model='Unknown UserAgent',
                                                 system_version='Unknown Platform',
                                                 app_version=version,
                                                 lang_code='en-US',
                                                 query=simpleQuery)

    # perform the initialization
    msg = self.method_call('invokeWithLayer', layer=api_layer, query=initConnectionQuery)
    print('initConnection - msg: ', msg)

Thanks!

Community
  • 1
  • 1
Kenny Cason
  • 497
  • 5
  • 17
  • @ "This is the best telegram documentation I have yet to find! Thanks for that." You are welcome :) – Charles Okwuagwu Jul 29 '16 at 07:21
  • Take a look at this followup post http://stackoverflow.com/a/35492833/44080 "Steps after creating Authorization Key for Telegram API" – Charles Okwuagwu Jul 29 '16 at 07:26
  • Thank you Charles, I've already seen that post. The example is appreciated but uses classes like TL.help_getnearestdc and TL.invokewithlayer instead of the actual telegram methods like help.getNearestDc and invokeWithLayer. I can serialize individual methods and send them (see above: self.method_call() but invokeWithLayer uses other methods as a parameter. My questions remain:1.Given a telegram api schema file, is there a way to determine from the schema which layer it is? 2.When calling invokeWithLayer how do you format the 'query' parameter? Do you have to serialize the query first? – Kenny Cason Jul 29 '16 at 13:36

1 Answers1

2

1) I get the latest telegram schema from here: https://github.com/telegramdesktop/tdesktop/blob/master/Telegram/Resources/scheme.tl

You can build your own TL parser library that works the way you want it too, and easily update it to the latest as the versions change.

2) To send the X query param you simply serialize and append to the end of your invoke with layer query.

Example: (from my Telegram Elixir Library)

 msg = TL.invokewithlayer(layer, TL.initconnection(app_id, device_model, system_version, app_version, lang_code, TL.help_getconfig))

You can see the definition of relevant Telegram schema:

initConnection#69796de9 {X:Type} api_id:int device_model:string system_version:string app_version:string lang_code:string query:!X = X;
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
Steve Blackwell
  • 5,904
  • 32
  • 49
Charles Okwuagwu
  • 10,538
  • 16
  • 87
  • 157
  • Thanks for the link, that will be helpful. But, since invokeWithLayer requires the "layer" parameter where does that come from? How do I know what layer is being used? As far as I can tell there is nothing in the schema itself that indicates the layer. – Kenny Cason Aug 01 '16 at 12:21
  • Also, I was able to successfully execute the initConnection method with invokeWithLayer after hard coding the "layer" parameter and serializing each method in turn. I used help.getNearestDc as the imbedded method. It seams there are two responses from the telegram server: 1) a response for initConnection, and 2) a response for help.getNearestDc. Is this correct? – Kenny Cason Aug 01 '16 at 12:25
  • I use current layer. It is indicated at the bottom of the page I linked to – Charles Okwuagwu Aug 01 '16 at 13:29
  • Current layer is 53 – Charles Okwuagwu Aug 01 '16 at 13:29
  • yes correct, you should be able to handle multiple responses and embedded responses – Charles Okwuagwu Aug 01 '16 at 14:06
  • I wrote a tl parser so can now use the latest layer (53). But I am unsure how to handle "flags" types. They are only mentioned in the tl docs but not defined (as far as I can tell) at the bottom of the page here: [link](https://core.telegram.org/mtproto/TL-formal). – Kenny Cason Aug 11 '16 at 16:32
  • For example, when a method returns a 'message' type it should look like this: `message#c09be45f flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int edit_date:flags.15?int = Message; ` If I understand correctly each flag is a bit set in some variable, right? – Kenny Cason Aug 11 '16 at 16:37
  • make a new question, let me explain it to you – Charles Okwuagwu Aug 11 '16 at 17:16
  • also accept this answer if it solved your initial problem. – Charles Okwuagwu Aug 11 '16 at 17:18
  • Is tl based on some formal language or was it created specifically for telegram? I tried parsing it with YAML and that didn't go well. :-) – Kenny Cason Aug 11 '16 at 17:56
  • TL is telegram specific – Charles Okwuagwu Aug 11 '16 at 17:57
  • Flags are just indicators of which field is present or not – Charles Okwuagwu Aug 11 '16 at 18:34
  • Please post a new questioon so other can benefit from this in a seperate thread – Charles Okwuagwu Aug 11 '16 at 18:34