mtproto 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/tl-schema.json +42686 -0
- data/ext/aes_ige/extconf.rb +3 -9
- data/ext/factorization/extconf.rb +2 -0
- data/lib/mtproto/auth_key_generator.rb +68 -105
- data/lib/mtproto/binary.rb +21 -0
- data/lib/mtproto/client/api/check_password.rb +41 -0
- data/lib/mtproto/client/api/export_login_token.rb +27 -0
- data/lib/mtproto/client/api/get_dialogs.rb +21 -0
- data/lib/mtproto/client/api/get_history.rb +20 -0
- data/lib/mtproto/client/api/get_updates_difference.rb +21 -0
- data/lib/mtproto/client/api/get_updates_state.rb +14 -0
- data/lib/mtproto/client/api/get_users.rb +14 -0
- data/lib/mtproto/client/api/import_login_token.rb +23 -0
- data/lib/mtproto/client/api/send_code.rb +21 -0
- data/lib/mtproto/client/api/sign_in.rb +27 -0
- data/lib/mtproto/client/api.rb +36 -0
- data/lib/mtproto/client/rpc/response.rb +63 -0
- data/lib/mtproto/client/rpc.rb +60 -127
- data/lib/mtproto/client.rb +143 -32
- data/lib/mtproto/crypto/dh_key_exchange.rb +1 -2
- data/lib/mtproto/crypto/dh_validator.rb +17 -19
- data/lib/mtproto/crypto/factorization.rb +1 -1
- data/lib/mtproto/crypto/rsa_key.rb +2 -2
- data/lib/mtproto/crypto/srp.rb +117 -0
- data/lib/mtproto/delegate_methods.rb +11 -0
- data/lib/mtproto/errors.rb +8 -0
- data/lib/mtproto/message/message.rb +85 -0
- data/lib/mtproto/session.rb +1 -1
- data/lib/mtproto/tl/constructor_names.rb +2271 -0
- data/lib/mtproto/tl/constructors.rb +99 -0
- data/lib/mtproto/tl/object.rb +25 -0
- data/lib/mtproto/tl/objects/account_password.rb +69 -0
- data/lib/mtproto/tl/objects/authorization.rb +70 -0
- data/lib/mtproto/tl/objects/check_password.rb +43 -0
- data/lib/mtproto/tl/objects/client_dh_inner_data.rb +45 -0
- data/lib/mtproto/tl/objects/dh_gen_response.rb +46 -0
- data/lib/mtproto/tl/objects/dialogs.rb +453 -0
- data/lib/mtproto/tl/objects/export_login_token.rb +48 -0
- data/lib/mtproto/tl/objects/get_config.rb +13 -0
- data/lib/mtproto/tl/objects/get_dialogs.rb +51 -0
- data/lib/mtproto/tl/objects/get_difference.rb +34 -0
- data/lib/mtproto/tl/objects/get_history.rb +49 -0
- data/lib/mtproto/tl/objects/get_password.rb +13 -0
- data/lib/mtproto/tl/objects/get_state.rb +13 -0
- data/lib/mtproto/tl/objects/get_users.rb +16 -0
- data/lib/mtproto/{type → tl/objects}/gzip_packed.rb +6 -6
- data/lib/mtproto/tl/objects/help_config.rb +76 -0
- data/lib/mtproto/tl/objects/import_login_token.rb +37 -0
- data/lib/mtproto/tl/objects/init_connection.rb +57 -0
- data/lib/mtproto/tl/objects/invoke_with_layer.rb +20 -0
- data/lib/mtproto/tl/objects/login_token.rb +78 -0
- data/lib/mtproto/{type → tl/objects}/message.rb +3 -3
- data/lib/mtproto/tl/objects/messages.rb +162 -0
- data/lib/mtproto/{type → tl/objects}/msg_container.rb +1 -3
- data/lib/mtproto/{type → tl/objects}/new_session_created.rb +1 -3
- data/lib/mtproto/tl/objects/pq_inner_data.rb +66 -0
- data/lib/mtproto/tl/objects/req_dh_params.rb +63 -0
- data/lib/mtproto/tl/objects/req_pq_multi.rb +21 -0
- data/lib/mtproto/tl/objects/res_pq.rb +73 -0
- data/lib/mtproto/{type → tl/objects}/rpc_error.rb +1 -4
- data/lib/mtproto/tl/objects/send_code.rb +47 -0
- data/lib/mtproto/tl/objects/sent_code.rb +79 -0
- data/lib/mtproto/tl/objects/server_dh_inner_data.rb +74 -0
- data/lib/mtproto/tl/objects/server_dh_params.rb +53 -0
- data/lib/mtproto/tl/objects/set_client_dh_params.rb +46 -0
- data/lib/mtproto/tl/objects/sign_in.rb +45 -0
- data/lib/mtproto/tl/objects/update.rb +77 -0
- data/lib/mtproto/tl/objects/update_short.rb +20 -0
- data/lib/mtproto/tl/objects/update_short_message.rb +65 -0
- data/lib/mtproto/tl/objects/updates_difference.rb +152 -0
- data/lib/mtproto/tl/objects/updates_state.rb +35 -0
- data/lib/mtproto/tl/objects/users.rb +83 -0
- data/lib/mtproto/tl/schema.rb +102 -0
- data/lib/mtproto/transport/abridged_packet_codec.rb +35 -12
- data/lib/mtproto/transport/connection.rb +23 -0
- data/lib/mtproto/transport/errors.rb +11 -0
- data/lib/mtproto/transport/packet.rb +19 -0
- data/lib/mtproto/transport/tcp_connection.rb +57 -46
- data/lib/mtproto/updates_poller.rb +37 -33
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +17 -27
- data/scripts/generate_constructors.rb +65 -0
- metadata +76 -61
- data/lib/mtproto/async/middleware/base.rb +0 -17
- data/lib/mtproto/async/middleware/flood_wait.rb +0 -42
- data/lib/mtproto/async/request.rb +0 -18
- data/lib/mtproto/async/request_queue.rb +0 -63
- data/lib/mtproto/async_client.rb +0 -201
- data/lib/mtproto/rpc/get_config.rb +0 -34
- data/lib/mtproto/rpc/get_contacts.rb +0 -29
- data/lib/mtproto/rpc/get_updates_difference.rb +0 -51
- data/lib/mtproto/rpc/get_updates_state.rb +0 -29
- data/lib/mtproto/rpc/get_users.rb +0 -29
- data/lib/mtproto/rpc/ping.rb +0 -33
- data/lib/mtproto/rpc/send_code.rb +0 -41
- data/lib/mtproto/rpc/send_message.rb +0 -47
- data/lib/mtproto/rpc/sign_in.rb +0 -48
- data/lib/mtproto/type/auth_key/dh_gen_response.rb +0 -37
- data/lib/mtproto/type/auth_key/req_dh_params.rb +0 -31
- data/lib/mtproto/type/auth_key/req_pq_multi.rb +0 -18
- data/lib/mtproto/type/auth_key/res_pq.rb +0 -62
- data/lib/mtproto/type/auth_key/server_dh_params.rb +0 -43
- data/lib/mtproto/type/auth_key/set_client_dh_params.rb +0 -25
- data/lib/mtproto/type/bad_msg_notification.rb +0 -46
- data/lib/mtproto/type/client_dh_inner_data.rb +0 -29
- data/lib/mtproto/type/code_settings.rb +0 -25
- data/lib/mtproto/type/config.rb +0 -124
- data/lib/mtproto/type/pq_inner_data.rb +0 -41
- data/lib/mtproto/type/rpc/auth/authorization.rb +0 -107
- data/lib/mtproto/type/rpc/auth/send_code.rb +0 -28
- data/lib/mtproto/type/rpc/auth/sent_code.rb +0 -36
- data/lib/mtproto/type/rpc/auth/sign_in.rb +0 -32
- data/lib/mtproto/type/rpc/contacts/contacts.rb +0 -155
- data/lib/mtproto/type/rpc/contacts/get_contacts.rb +0 -18
- data/lib/mtproto/type/rpc/help/config.rb +0 -35
- data/lib/mtproto/type/rpc/help/get_config.rb +0 -17
- data/lib/mtproto/type/rpc/init_connection.rb +0 -28
- data/lib/mtproto/type/rpc/invoke_with_layer.rb +0 -19
- data/lib/mtproto/type/rpc/messages/send_message.rb +0 -43
- data/lib/mtproto/type/rpc/messages/updates.rb +0 -87
- data/lib/mtproto/type/rpc/ping.rb +0 -18
- data/lib/mtproto/type/rpc/pong.rb +0 -46
- data/lib/mtproto/type/rpc/updates/difference.rb +0 -332
- data/lib/mtproto/type/rpc/updates/get_difference.rb +0 -42
- data/lib/mtproto/type/rpc/updates/get_state.rb +0 -17
- data/lib/mtproto/type/rpc/updates/state.rb +0 -59
- data/lib/mtproto/type/rpc/users/get_users.rb +0 -25
- data/lib/mtproto/type/rpc/users/users.rb +0 -99
- data/lib/mtproto/type/sent_code.rb +0 -128
- data/lib/mtproto/type/serializer.rb +0 -55
- data/lib/mtproto/type/server_dh_inner_data.rb +0 -85
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
module AuthKey
|
|
6
|
-
class ServerDHParams
|
|
7
|
-
CONSTRUCTOR = 0xd0e8075c
|
|
8
|
-
|
|
9
|
-
def self.parse(body)
|
|
10
|
-
constructor = body[0, 4].unpack1('L<')
|
|
11
|
-
raise "Unexpected constructor: 0x#{constructor.to_s(16)}" unless constructor == CONSTRUCTOR
|
|
12
|
-
|
|
13
|
-
offset = 4
|
|
14
|
-
|
|
15
|
-
nonce = body[offset, 16]
|
|
16
|
-
offset += 16
|
|
17
|
-
|
|
18
|
-
server_nonce = body[offset, 16]
|
|
19
|
-
offset += 16
|
|
20
|
-
|
|
21
|
-
length_byte = body[offset].ord
|
|
22
|
-
offset += 1
|
|
23
|
-
|
|
24
|
-
if length_byte == 254
|
|
25
|
-
length_bytes = body[offset, 3].bytes
|
|
26
|
-
encrypted_answer_length = length_bytes[0] | (length_bytes[1] << 8) | (length_bytes[2] << 16)
|
|
27
|
-
offset += 3
|
|
28
|
-
else
|
|
29
|
-
encrypted_answer_length = length_byte
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
encrypted_answer = body[offset, encrypted_answer_length]
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
nonce: nonce,
|
|
36
|
-
server_nonce: server_nonce,
|
|
37
|
-
encrypted_answer: encrypted_answer
|
|
38
|
-
}
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../serializer'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Type
|
|
7
|
-
module AuthKey
|
|
8
|
-
class SetClientDHParams
|
|
9
|
-
CONSTRUCTOR = 0xf5045f1f
|
|
10
|
-
|
|
11
|
-
def self.build(nonce:, server_nonce:, encrypted_data:)
|
|
12
|
-
raise ArgumentError, 'Nonce must be 16 bytes' unless nonce.bytesize == 16
|
|
13
|
-
raise ArgumentError, 'Server nonce must be 16 bytes' unless server_nonce.bytesize == 16
|
|
14
|
-
|
|
15
|
-
body = Serializer.serialize_int(CONSTRUCTOR)
|
|
16
|
-
body += nonce
|
|
17
|
-
body += server_nonce
|
|
18
|
-
body += Serializer.serialize_bytes(encrypted_data)
|
|
19
|
-
|
|
20
|
-
body
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
class BadMsgNotification
|
|
6
|
-
CONSTRUCTOR = 0xa7eff811
|
|
7
|
-
|
|
8
|
-
attr_reader :bad_msg_id, :bad_msg_seqno, :error_code
|
|
9
|
-
|
|
10
|
-
def self.deserialize(data)
|
|
11
|
-
offset = 4
|
|
12
|
-
bad_msg_id = data[offset, 8].unpack1('Q<')
|
|
13
|
-
offset += 8
|
|
14
|
-
|
|
15
|
-
bad_msg_seqno = data[offset, 4].unpack1('L<')
|
|
16
|
-
offset += 4
|
|
17
|
-
|
|
18
|
-
error_code = data[offset, 4].unpack1('L<')
|
|
19
|
-
|
|
20
|
-
new(bad_msg_id: bad_msg_id, bad_msg_seqno: bad_msg_seqno, error_code: error_code)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def initialize(bad_msg_id:, bad_msg_seqno:, error_code:)
|
|
24
|
-
@bad_msg_id = bad_msg_id
|
|
25
|
-
@bad_msg_seqno = bad_msg_seqno
|
|
26
|
-
@error_code = error_code
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def error_message
|
|
30
|
-
case @error_code
|
|
31
|
-
when 16 then "msg_id too low (client time is wrong)"
|
|
32
|
-
when 17 then "msg_id too high (client time needs sync)"
|
|
33
|
-
when 18 then "incorrect two lower order msg_id bits (must be divisible by 4)"
|
|
34
|
-
when 19 then "container msg_id is the same as previously received"
|
|
35
|
-
when 20 then "message too old"
|
|
36
|
-
when 32 then "msg_seqno too low"
|
|
37
|
-
when 33 then "msg_seqno too high"
|
|
38
|
-
when 34 then "even msg_seqno expected but odd received"
|
|
39
|
-
when 35 then "odd msg_seqno expected but even received"
|
|
40
|
-
when 48 then "incorrect server salt"
|
|
41
|
-
else "unknown error code #{@error_code}"
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'serializer'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Type
|
|
7
|
-
class ClientDHInnerData
|
|
8
|
-
CONSTRUCTOR = 0x6643b654
|
|
9
|
-
|
|
10
|
-
attr_reader :nonce, :server_nonce, :retry_id, :g_b
|
|
11
|
-
|
|
12
|
-
def initialize(nonce:, server_nonce:, retry_id:, g_b:)
|
|
13
|
-
@nonce = nonce
|
|
14
|
-
@server_nonce = server_nonce
|
|
15
|
-
@retry_id = retry_id
|
|
16
|
-
@g_b = g_b
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def serialize
|
|
20
|
-
data = Serializer.serialize_int(CONSTRUCTOR)
|
|
21
|
-
data += @nonce
|
|
22
|
-
data += @server_nonce
|
|
23
|
-
data += Serializer.serialize_long(@retry_id)
|
|
24
|
-
data += Serializer.serialize_bytes(@g_b)
|
|
25
|
-
data
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
class CodeSettings
|
|
6
|
-
CONSTRUCTOR = 0xad253d78
|
|
7
|
-
|
|
8
|
-
def self.serialize(settings = {})
|
|
9
|
-
body = Serializer.serialize_int(CONSTRUCTOR)
|
|
10
|
-
|
|
11
|
-
flags = 0
|
|
12
|
-
flags |= (1 << 0) if settings[:allow_flashcall]
|
|
13
|
-
flags |= (1 << 1) if settings[:current_number]
|
|
14
|
-
flags |= (1 << 4) if settings[:allow_app_hash]
|
|
15
|
-
flags |= (1 << 5) if settings[:allow_missed_call]
|
|
16
|
-
flags |= (1 << 7) if settings[:allow_firebase]
|
|
17
|
-
flags |= (1 << 9) if settings[:unknown_number]
|
|
18
|
-
|
|
19
|
-
body += Serializer.serialize_int(flags)
|
|
20
|
-
|
|
21
|
-
body
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
data/lib/mtproto/type/config.rb
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
class Config
|
|
6
|
-
CONSTRUCTOR = 0xcc1a241e
|
|
7
|
-
CONSTRUCTOR_ALT = 0x3072cfa1
|
|
8
|
-
|
|
9
|
-
attr_reader :flags, :date, :expires, :test_mode, :this_dc, :dc_options
|
|
10
|
-
|
|
11
|
-
def self.deserialize(data)
|
|
12
|
-
offset = 4
|
|
13
|
-
|
|
14
|
-
flags = data[offset, 4].unpack1('L<')
|
|
15
|
-
offset += 4
|
|
16
|
-
|
|
17
|
-
date = data[offset, 4].unpack1('L<')
|
|
18
|
-
offset += 4
|
|
19
|
-
|
|
20
|
-
expires = data[offset, 4].unpack1('L<')
|
|
21
|
-
offset += 4
|
|
22
|
-
|
|
23
|
-
test_mode = (data[offset, 4].unpack1('L<') == 0x997275b5)
|
|
24
|
-
offset += 4
|
|
25
|
-
|
|
26
|
-
this_dc = data[offset, 4].unpack1('L<')
|
|
27
|
-
offset += 4
|
|
28
|
-
|
|
29
|
-
dc_options_constructor = data[offset, 4].unpack1('L<')
|
|
30
|
-
offset += 4
|
|
31
|
-
|
|
32
|
-
raise "Expected vector constructor 0x1cb5c415, got 0x#{dc_options_constructor.to_s(16)}" unless dc_options_constructor == 0x1cb5c415
|
|
33
|
-
|
|
34
|
-
dc_options_count = data[offset, 4].unpack1('L<')
|
|
35
|
-
offset += 4
|
|
36
|
-
|
|
37
|
-
dc_options = []
|
|
38
|
-
dc_options_count.times do
|
|
39
|
-
dc_option, bytes_read = DcOption.deserialize_from(data[offset..])
|
|
40
|
-
dc_options << dc_option
|
|
41
|
-
offset += bytes_read
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
new(
|
|
45
|
-
flags: flags,
|
|
46
|
-
date: date,
|
|
47
|
-
expires: expires,
|
|
48
|
-
test_mode: test_mode,
|
|
49
|
-
this_dc: this_dc,
|
|
50
|
-
dc_options: dc_options
|
|
51
|
-
)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def initialize(flags:, date:, expires:, test_mode:, this_dc:, dc_options:)
|
|
55
|
-
@flags = flags
|
|
56
|
-
@date = date
|
|
57
|
-
@expires = expires
|
|
58
|
-
@test_mode = test_mode
|
|
59
|
-
@this_dc = this_dc
|
|
60
|
-
@dc_options = dc_options
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
class DcOption
|
|
65
|
-
attr_reader :id, :ip_address, :port, :flags
|
|
66
|
-
|
|
67
|
-
def self.deserialize_from(data)
|
|
68
|
-
offset = 0
|
|
69
|
-
|
|
70
|
-
constructor = data[offset, 4].unpack1('L<')
|
|
71
|
-
offset += 4
|
|
72
|
-
|
|
73
|
-
raise "Expected dcOption constructor 0x18b7a10d, got 0x#{constructor.to_s(16)}" unless constructor == 0x18b7a10d
|
|
74
|
-
|
|
75
|
-
flags = data[offset, 4].unpack1('L<')
|
|
76
|
-
offset += 4
|
|
77
|
-
|
|
78
|
-
id = data[offset, 4].unpack1('L<')
|
|
79
|
-
offset += 4
|
|
80
|
-
|
|
81
|
-
ip_length = data[offset].ord
|
|
82
|
-
offset += 1
|
|
83
|
-
|
|
84
|
-
ip_address = data[offset, ip_length]
|
|
85
|
-
offset += ip_length
|
|
86
|
-
|
|
87
|
-
padding = (4 - ((ip_length + 1) % 4)) % 4
|
|
88
|
-
offset += padding
|
|
89
|
-
|
|
90
|
-
port = data[offset, 4].unpack1('L<')
|
|
91
|
-
offset += 4
|
|
92
|
-
|
|
93
|
-
[new(id: id, ip_address: ip_address, port: port, flags: flags), offset]
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def initialize(id:, ip_address:, port:, flags:)
|
|
97
|
-
@id = id
|
|
98
|
-
@ip_address = ip_address
|
|
99
|
-
@port = port
|
|
100
|
-
@flags = flags
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def ipv6?
|
|
104
|
-
(@flags & 1) != 0
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def media_only?
|
|
108
|
-
(@flags & 2) != 0
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def tcpo_only?
|
|
112
|
-
(@flags & 4) != 0
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def cdn?
|
|
116
|
-
(@flags & 8) != 0
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def static?
|
|
120
|
-
(@flags & 16) != 0
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'serializer'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Type
|
|
7
|
-
class PQInnerData
|
|
8
|
-
CONSTRUCTOR_DC = 0xa9f55f95
|
|
9
|
-
CONSTRUCTOR_TEMP_DC = 0x56fddf88
|
|
10
|
-
|
|
11
|
-
attr_reader :pq, :p, :q, :nonce, :server_nonce, :new_nonce, :dc, :expires_in
|
|
12
|
-
|
|
13
|
-
def initialize(pq:, p:, q:, nonce:, server_nonce:, new_nonce:, dc:, expires_in: nil)
|
|
14
|
-
@pq = pq
|
|
15
|
-
@p = p
|
|
16
|
-
@q = q
|
|
17
|
-
@nonce = nonce
|
|
18
|
-
@server_nonce = server_nonce
|
|
19
|
-
@new_nonce = new_nonce
|
|
20
|
-
@dc = dc
|
|
21
|
-
@expires_in = expires_in
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def serialize
|
|
25
|
-
constructor = @expires_in ? CONSTRUCTOR_TEMP_DC : CONSTRUCTOR_DC
|
|
26
|
-
|
|
27
|
-
data = Serializer.serialize_int(constructor)
|
|
28
|
-
data += Serializer.serialize_bytes(Serializer.integer_to_bytes(@pq))
|
|
29
|
-
data += Serializer.serialize_bytes(Serializer.integer_to_bytes(@p))
|
|
30
|
-
data += Serializer.serialize_bytes(Serializer.integer_to_bytes(@q))
|
|
31
|
-
data += @nonce
|
|
32
|
-
data += @server_nonce
|
|
33
|
-
data += @new_nonce
|
|
34
|
-
|
|
35
|
-
data += Serializer.serialize_int(@expires_in) if @expires_in
|
|
36
|
-
|
|
37
|
-
data + Serializer.serialize_int(@dc)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../gzip_packed'
|
|
4
|
-
require_relative '../../rpc_error'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module Type
|
|
8
|
-
module RPC
|
|
9
|
-
module Auth
|
|
10
|
-
class Authorization
|
|
11
|
-
CONSTRUCTOR = 0x2ea2c0d4
|
|
12
|
-
CONSTRUCTOR_SIGN_UP_REQUIRED = 0x44747e9a
|
|
13
|
-
|
|
14
|
-
def self.parse(response)
|
|
15
|
-
constructor = response[0, 4].unpack1('L<')
|
|
16
|
-
|
|
17
|
-
if constructor == Type::GzipPacked::CONSTRUCTOR
|
|
18
|
-
response = Type::GzipPacked.unpack(response)
|
|
19
|
-
constructor = response[0, 4].unpack1('L<')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
if constructor == Type::RpcError::CONSTRUCTOR
|
|
23
|
-
error = Type::RpcError.deserialize(response)
|
|
24
|
-
raise MTProto::RpcError.new(error.error_code, error.error_message)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
if constructor == CONSTRUCTOR_SIGN_UP_REQUIRED
|
|
28
|
-
return { authorization: nil, sign_up_required: true }
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
if constructor == CONSTRUCTOR
|
|
32
|
-
offset = 4
|
|
33
|
-
|
|
34
|
-
# Parse flags
|
|
35
|
-
flags = response[offset, 4].unpack1('L<')
|
|
36
|
-
offset += 4
|
|
37
|
-
|
|
38
|
-
# tmp_sessions:flags.0?int
|
|
39
|
-
if (flags & (1 << 0)) != 0
|
|
40
|
-
offset += 4
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# otherwise_relogin_days:flags.1?int
|
|
44
|
-
if (flags & (1 << 1)) != 0
|
|
45
|
-
offset += 4
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# future_auth_token:flags.2?bytes
|
|
49
|
-
if (flags & (1 << 2)) != 0
|
|
50
|
-
first_byte = response[offset].unpack1('C')
|
|
51
|
-
|
|
52
|
-
if first_byte < 254
|
|
53
|
-
# Short format: 1 byte length + data + padding
|
|
54
|
-
token_len = first_byte
|
|
55
|
-
offset += 1 + token_len
|
|
56
|
-
padding = (4 - ((1 + token_len) % 4)) % 4
|
|
57
|
-
offset += padding
|
|
58
|
-
else
|
|
59
|
-
# Long format: 0xfe + 3 bytes length + data + padding
|
|
60
|
-
offset += 1
|
|
61
|
-
token_len = response[offset, 3].unpack('CCC').inject(0) {|sum, b| (sum << 8) + b}
|
|
62
|
-
offset += 3 + token_len
|
|
63
|
-
padding = (4 - ((4 + token_len) % 4)) % 4
|
|
64
|
-
offset += padding
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Parse User object
|
|
69
|
-
# user#20b1422 flags:# flags2:# id:long access_hash:flags.0?long ...
|
|
70
|
-
user_constructor = response[offset, 4].unpack1('L<')
|
|
71
|
-
offset += 4
|
|
72
|
-
|
|
73
|
-
user_flags = response[offset, 4].unpack1('L<')
|
|
74
|
-
offset += 4
|
|
75
|
-
|
|
76
|
-
user_flags2 = response[offset, 4].unpack1('L<')
|
|
77
|
-
offset += 4
|
|
78
|
-
|
|
79
|
-
# id:long (always present)
|
|
80
|
-
user_id = response[offset, 8].unpack1('Q<')
|
|
81
|
-
offset += 8
|
|
82
|
-
|
|
83
|
-
# access_hash:flags.0?long (conditional on flags.0)
|
|
84
|
-
access_hash = nil
|
|
85
|
-
if (user_flags & (1 << 0)) != 0
|
|
86
|
-
access_hash = response[offset, 8].unpack1('Q<')
|
|
87
|
-
offset += 8
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# We have what we need, skip the rest of User fields
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
authorization: true,
|
|
94
|
-
flags: flags,
|
|
95
|
-
sign_up_required: false,
|
|
96
|
-
user_id: user_id,
|
|
97
|
-
access_hash: access_hash
|
|
98
|
-
}
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
raise UnexpectedConstructorError.new(constructor)
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../serializer'
|
|
4
|
-
require_relative '../../code_settings'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module Type
|
|
8
|
-
module RPC
|
|
9
|
-
module Auth
|
|
10
|
-
class SendCode
|
|
11
|
-
CONSTRUCTOR = 0xa677244f
|
|
12
|
-
|
|
13
|
-
def self.build(phone_number:, api_id:, api_hash:, code_settings: {})
|
|
14
|
-
raise ArgumentError, 'phone_number is required' if phone_number.nil? || phone_number.empty?
|
|
15
|
-
|
|
16
|
-
query = [CONSTRUCTOR].pack('L<')
|
|
17
|
-
query += Serializer.serialize_string(phone_number)
|
|
18
|
-
query += Serializer.serialize_int(api_id)
|
|
19
|
-
query += Serializer.serialize_string(api_hash)
|
|
20
|
-
query += CodeSettings.serialize(code_settings)
|
|
21
|
-
|
|
22
|
-
query
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../gzip_packed'
|
|
4
|
-
require_relative '../../rpc_error'
|
|
5
|
-
require_relative '../../sent_code'
|
|
6
|
-
|
|
7
|
-
module MTProto
|
|
8
|
-
module Type
|
|
9
|
-
module RPC
|
|
10
|
-
module Auth
|
|
11
|
-
class SentCode
|
|
12
|
-
def self.parse(response)
|
|
13
|
-
constructor = response[0, 4].unpack1('L<')
|
|
14
|
-
|
|
15
|
-
if constructor == Type::GzipPacked::CONSTRUCTOR
|
|
16
|
-
response = Type::GzipPacked.unpack(response)
|
|
17
|
-
constructor = response[0, 4].unpack1('L<')
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
if constructor == Type::RpcError::CONSTRUCTOR
|
|
21
|
-
error = Type::RpcError.deserialize(response)
|
|
22
|
-
raise MTProto::RpcError.new(error.error_code, error.error_message)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
if constructor == Type::SentCode::CONSTRUCTOR
|
|
26
|
-
sent_code = Type::SentCode.deserialize(response)
|
|
27
|
-
sent_code.to_h
|
|
28
|
-
else
|
|
29
|
-
raise UnexpectedConstructorError.new(constructor)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../serializer'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Type
|
|
7
|
-
module RPC
|
|
8
|
-
module Auth
|
|
9
|
-
class SignIn
|
|
10
|
-
CONSTRUCTOR = 0x8d52a951
|
|
11
|
-
|
|
12
|
-
def self.build(phone_number:, phone_code_hash:, phone_code:)
|
|
13
|
-
raise ArgumentError, 'phone_number is required' if phone_number.nil? || phone_number.empty?
|
|
14
|
-
raise ArgumentError, 'phone_code_hash is required' if phone_code_hash.nil? || phone_code_hash.empty?
|
|
15
|
-
raise ArgumentError, 'phone_code is required' if phone_code.nil? || phone_code.empty?
|
|
16
|
-
|
|
17
|
-
flags = 0
|
|
18
|
-
flags |= (1 << 0) # phone_code present
|
|
19
|
-
|
|
20
|
-
query = [CONSTRUCTOR].pack('L<')
|
|
21
|
-
query += Serializer.serialize_int(flags)
|
|
22
|
-
query += Serializer.serialize_string(phone_number)
|
|
23
|
-
query += Serializer.serialize_string(phone_code_hash)
|
|
24
|
-
query += Serializer.serialize_string(phone_code)
|
|
25
|
-
|
|
26
|
-
query
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../gzip_packed'
|
|
4
|
-
require_relative '../../rpc_error'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module Type
|
|
8
|
-
module RPC
|
|
9
|
-
module Contacts
|
|
10
|
-
class Contacts
|
|
11
|
-
CONSTRUCTOR_CONTACTS = 0xeae87e42
|
|
12
|
-
CONSTRUCTOR_CONTACTS_NOT_MODIFIED = 0xb74ba9d2
|
|
13
|
-
VECTOR_CONSTRUCTOR = 0x1cb5c415
|
|
14
|
-
|
|
15
|
-
def self.parse(response)
|
|
16
|
-
offset = 0
|
|
17
|
-
|
|
18
|
-
constructor = response[offset, 4].unpack1('L<')
|
|
19
|
-
offset += 4
|
|
20
|
-
|
|
21
|
-
if constructor == Type::GzipPacked::CONSTRUCTOR
|
|
22
|
-
response = Type::GzipPacked.unpack(response)
|
|
23
|
-
constructor = response[0, 4].unpack1('L<')
|
|
24
|
-
offset = 4
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
if constructor == Type::RpcError::CONSTRUCTOR
|
|
28
|
-
error = Type::RpcError.deserialize(response)
|
|
29
|
-
raise MTProto::RpcError.new(error.error_code, error.error_message)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
case constructor
|
|
33
|
-
when CONSTRUCTOR_CONTACTS_NOT_MODIFIED
|
|
34
|
-
# contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
|
|
35
|
-
{
|
|
36
|
-
contacts: [],
|
|
37
|
-
users: []
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
when CONSTRUCTOR_CONTACTS
|
|
41
|
-
# contacts.contacts#eae87e42 contacts:Vector<Contact> saved_count:int users:Vector<User> = contacts.Contacts;
|
|
42
|
-
|
|
43
|
-
# Parse contacts vector
|
|
44
|
-
contacts, offset = parse_contacts_vector(response, offset)
|
|
45
|
-
|
|
46
|
-
# Parse saved_count
|
|
47
|
-
saved_count = response[offset, 4].unpack1('L<')
|
|
48
|
-
offset += 4
|
|
49
|
-
|
|
50
|
-
# Parse users vector
|
|
51
|
-
users, offset = parse_users_vector(response, offset)
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
contacts: contacts,
|
|
55
|
-
saved_count: saved_count,
|
|
56
|
-
users: users
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
else
|
|
60
|
-
raise "Unknown Contacts constructor: 0x#{constructor.to_s(16)}"
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def self.parse_contacts_vector(response, offset)
|
|
65
|
-
vector_constructor = response[offset, 4].unpack1('L<')
|
|
66
|
-
offset += 4
|
|
67
|
-
|
|
68
|
-
return [[], offset] unless vector_constructor == VECTOR_CONSTRUCTOR
|
|
69
|
-
|
|
70
|
-
count = response[offset, 4].unpack1('L<')
|
|
71
|
-
offset += 4
|
|
72
|
-
|
|
73
|
-
contacts = []
|
|
74
|
-
count.times do
|
|
75
|
-
contact, offset = parse_contact(response, offset)
|
|
76
|
-
contacts << contact if contact
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
[contacts, offset]
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def self.parse_contact(response, offset)
|
|
83
|
-
# contact#145ade0b user_id:long mutual:Bool
|
|
84
|
-
constructor = response[offset, 4].unpack1('L<')
|
|
85
|
-
offset += 4
|
|
86
|
-
|
|
87
|
-
return [nil, offset] unless constructor == 0x145ade0b
|
|
88
|
-
|
|
89
|
-
user_id = response[offset, 8].unpack1('Q<')
|
|
90
|
-
offset += 8
|
|
91
|
-
|
|
92
|
-
mutual_constructor = response[offset, 4].unpack1('L<')
|
|
93
|
-
offset += 4
|
|
94
|
-
mutual = mutual_constructor == 0x997275b5 # boolTrue
|
|
95
|
-
|
|
96
|
-
[{
|
|
97
|
-
user_id: user_id,
|
|
98
|
-
mutual: mutual
|
|
99
|
-
}, offset]
|
|
100
|
-
rescue StandardError
|
|
101
|
-
[nil, offset]
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def self.parse_users_vector(response, offset)
|
|
105
|
-
vector_constructor = response[offset, 4].unpack1('L<')
|
|
106
|
-
offset += 4
|
|
107
|
-
|
|
108
|
-
return [[], offset] unless vector_constructor == VECTOR_CONSTRUCTOR
|
|
109
|
-
|
|
110
|
-
count = response[offset, 4].unpack1('L<')
|
|
111
|
-
offset += 4
|
|
112
|
-
|
|
113
|
-
users = []
|
|
114
|
-
count.times do
|
|
115
|
-
user, offset = parse_user(response, offset)
|
|
116
|
-
users << user if user
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
[users, offset]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def self.parse_user(response, offset)
|
|
123
|
-
user_constructor = response[offset, 4].unpack1('L<')
|
|
124
|
-
offset += 4
|
|
125
|
-
|
|
126
|
-
# user#20b1422 flags:# flags2:# id:long access_hash:flags.0?long ...
|
|
127
|
-
return [nil, offset] unless user_constructor == 0x20b1422
|
|
128
|
-
|
|
129
|
-
flags = response[offset, 4].unpack1('L<')
|
|
130
|
-
offset += 4
|
|
131
|
-
|
|
132
|
-
flags2 = response[offset, 4].unpack1('L<')
|
|
133
|
-
offset += 4
|
|
134
|
-
|
|
135
|
-
user_id = response[offset, 8].unpack1('Q<')
|
|
136
|
-
offset += 8
|
|
137
|
-
|
|
138
|
-
access_hash = nil
|
|
139
|
-
if (flags & (1 << 0)) != 0
|
|
140
|
-
access_hash = response[offset, 8].unpack1('Q<')
|
|
141
|
-
offset += 8
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
[{
|
|
145
|
-
id: user_id,
|
|
146
|
-
access_hash: access_hash
|
|
147
|
-
}, offset]
|
|
148
|
-
rescue StandardError
|
|
149
|
-
[nil, offset]
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|