mtproto 0.0.8 → 0.0.9
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/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_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 +28 -0
- data/lib/mtproto/client/rpc/response.rb +63 -0
- data/lib/mtproto/client/rpc.rb +61 -125
- data/lib/mtproto/client.rb +142 -31
- 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/message/message.rb +85 -0
- data/lib/mtproto/session.rb +1 -1
- data/lib/mtproto/tl/constructors.rb +2269 -0
- data/lib/mtproto/tl/object.rb +25 -0
- data/lib/mtproto/tl/objects/account_password.rb +72 -0
- data/lib/mtproto/tl/objects/authorization.rb +73 -0
- data/lib/mtproto/tl/objects/check_password.rb +46 -0
- data/lib/mtproto/tl/objects/client_dh_inner_data.rb +47 -0
- data/lib/mtproto/tl/objects/dh_gen_response.rb +50 -0
- data/lib/mtproto/tl/objects/export_login_token.rb +51 -0
- data/lib/mtproto/tl/objects/get_config.rb +15 -0
- data/lib/mtproto/tl/objects/get_difference.rb +36 -0
- data/lib/mtproto/tl/objects/get_password.rb +15 -0
- data/lib/mtproto/tl/objects/get_state.rb +15 -0
- data/lib/mtproto/tl/objects/get_users.rb +20 -0
- data/lib/mtproto/tl/objects/help_config.rb +77 -0
- data/lib/mtproto/tl/objects/import_login_token.rb +39 -0
- data/lib/mtproto/tl/objects/init_connection.rb +59 -0
- data/lib/mtproto/tl/objects/invoke_with_layer.rb +22 -0
- data/lib/mtproto/tl/objects/login_token.rb +82 -0
- data/lib/mtproto/tl/objects/pq_inner_data.rb +69 -0
- data/lib/mtproto/tl/objects/req_dh_params.rb +65 -0
- data/lib/mtproto/tl/objects/req_pq_multi.rb +23 -0
- data/lib/mtproto/tl/objects/res_pq.rb +75 -0
- data/lib/mtproto/tl/objects/send_code.rb +50 -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 +48 -0
- data/lib/mtproto/tl/objects/sign_in.rb +47 -0
- data/lib/mtproto/tl/objects/update.rb +80 -0
- data/lib/mtproto/tl/objects/update_short.rb +22 -0
- data/lib/mtproto/tl/objects/update_short_message.rb +67 -0
- data/lib/mtproto/tl/objects/updates_difference.rb +157 -0
- data/lib/mtproto/tl/objects/updates_state.rb +37 -0
- data/lib/mtproto/tl/objects/users.rb +86 -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/type/bad_msg_notification.rb +10 -10
- data/lib/mtproto/type/gzip_packed.rb +5 -3
- data/lib/mtproto/type/message.rb +2 -2
- data/lib/mtproto/type/rpc_error.rb +0 -1
- data/lib/mtproto/updates_poller.rb +37 -33
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +11 -17
- data/scripts/generate_constructors.rb +65 -0
- metadata +62 -51
- 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/code_settings.rb +0 -25
- data/lib/mtproto/type/config.rb +0 -124
- 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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class Object
|
|
6
|
+
extend Binary
|
|
7
|
+
|
|
8
|
+
attr_reader :constructor, :payload
|
|
9
|
+
|
|
10
|
+
def initialize(constructor, payload)
|
|
11
|
+
@constructor = constructor
|
|
12
|
+
@payload = payload
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.parse(message)
|
|
16
|
+
body = message.body
|
|
17
|
+
constructor_id = b_u32(body[0, 4])
|
|
18
|
+
constructor = Constructors::NAMES.fetch(constructor_id)
|
|
19
|
+
payload = body[4..]
|
|
20
|
+
|
|
21
|
+
new(constructor, payload)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class AccountPassword
|
|
6
|
+
CONSTRUCTOR = 0x957b50fb
|
|
7
|
+
ALGO_SHA256_MOD_POW = 0x3a912d4a
|
|
8
|
+
|
|
9
|
+
attr_reader :has_password, :current_algo, :srp_b, :srp_id
|
|
10
|
+
|
|
11
|
+
def initialize(has_password:, current_algo: nil, srp_b: nil, srp_id: nil)
|
|
12
|
+
@has_password = has_password
|
|
13
|
+
@current_algo = current_algo
|
|
14
|
+
@srp_b = srp_b
|
|
15
|
+
@srp_id = srp_id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.parse(data)
|
|
19
|
+
constructor = data[0, 4].unpack1('L<')
|
|
20
|
+
raise UnexpectedConstructorError, constructor unless constructor == CONSTRUCTOR
|
|
21
|
+
|
|
22
|
+
offset = 4
|
|
23
|
+
flags = data[offset, 4].unpack1('L<')
|
|
24
|
+
offset += 4
|
|
25
|
+
|
|
26
|
+
has_password = flags.anybits?(1 << 2)
|
|
27
|
+
|
|
28
|
+
return new(has_password: false) unless has_password
|
|
29
|
+
|
|
30
|
+
algo_constructor = data[offset, 4].unpack1('L<')
|
|
31
|
+
offset += 4
|
|
32
|
+
|
|
33
|
+
current_algo = nil
|
|
34
|
+
if algo_constructor == ALGO_SHA256_MOD_POW
|
|
35
|
+
salt1, offset = read_tl_bytes(data, offset)
|
|
36
|
+
salt2, offset = read_tl_bytes(data, offset)
|
|
37
|
+
g = data[offset, 4].unpack1('l<')
|
|
38
|
+
offset += 4
|
|
39
|
+
p, offset = read_tl_bytes(data, offset)
|
|
40
|
+
|
|
41
|
+
current_algo = { salt1: salt1, salt2: salt2, g: g, p: p }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
srp_b, offset = read_tl_bytes(data, offset)
|
|
45
|
+
srp_id = data[offset, 8].unpack1('Q<')
|
|
46
|
+
|
|
47
|
+
new(has_password: true, current_algo: current_algo, srp_b: srp_b, srp_id: srp_id)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class << self
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def read_tl_bytes(data, offset)
|
|
54
|
+
first_byte = data.getbyte(offset)
|
|
55
|
+
if first_byte < 254
|
|
56
|
+
len = first_byte
|
|
57
|
+
bytes = data[offset + 1, len]
|
|
58
|
+
total = 1 + len
|
|
59
|
+
else
|
|
60
|
+
len = data.getbyte(offset + 1) |
|
|
61
|
+
(data.getbyte(offset + 2) << 8) |
|
|
62
|
+
(data.getbyte(offset + 3) << 16)
|
|
63
|
+
bytes = data[offset + 4, len]
|
|
64
|
+
total = 4 + len
|
|
65
|
+
end
|
|
66
|
+
padding = (4 - (total % 4)) % 4
|
|
67
|
+
[bytes, offset + total + padding]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class Authorization
|
|
6
|
+
CONSTRUCTOR = 0x2ea2c0d4
|
|
7
|
+
CONSTRUCTOR_SIGN_UP_REQUIRED = 0x44747e9a
|
|
8
|
+
|
|
9
|
+
attr_reader :user_id, :access_hash, :flags, :sign_up_required
|
|
10
|
+
|
|
11
|
+
def initialize(user_id: nil, access_hash: nil, flags: 0, sign_up_required: false)
|
|
12
|
+
@user_id = user_id
|
|
13
|
+
@access_hash = access_hash
|
|
14
|
+
@flags = flags
|
|
15
|
+
@sign_up_required = sign_up_required
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def authorization?
|
|
19
|
+
!@sign_up_required && @user_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.parse(data)
|
|
23
|
+
constructor = data[0, 4].unpack1('L<')
|
|
24
|
+
|
|
25
|
+
return new(sign_up_required: true) if constructor == CONSTRUCTOR_SIGN_UP_REQUIRED
|
|
26
|
+
raise UnexpectedConstructorError, constructor unless constructor == CONSTRUCTOR
|
|
27
|
+
|
|
28
|
+
offset = 4
|
|
29
|
+
|
|
30
|
+
flags = data[offset, 4].unpack1('L<')
|
|
31
|
+
offset += 4
|
|
32
|
+
|
|
33
|
+
offset += 4 if flags.anybits?(1 << 0) # tmp_sessions
|
|
34
|
+
offset += 4 if flags.anybits?(1 << 1) # otherwise_relogin_days
|
|
35
|
+
|
|
36
|
+
offset = skip_tl_bytes(data, offset) if flags.anybits?(1 << 2) # future_auth_token
|
|
37
|
+
|
|
38
|
+
# user#20b1422 flags:# flags2:# id:long access_hash:flags.0?long ...
|
|
39
|
+
offset += 4 # user constructor
|
|
40
|
+
|
|
41
|
+
user_flags = data[offset, 4].unpack1('L<')
|
|
42
|
+
offset += 4
|
|
43
|
+
|
|
44
|
+
offset += 4 # flags2
|
|
45
|
+
|
|
46
|
+
user_id = data[offset, 8].unpack1('Q<')
|
|
47
|
+
offset += 8
|
|
48
|
+
|
|
49
|
+
access_hash = nil
|
|
50
|
+
access_hash = data[offset, 8].unpack1('Q<') if user_flags.anybits?(1 << 0)
|
|
51
|
+
|
|
52
|
+
new(user_id: user_id, access_hash: access_hash, flags: flags)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class << self
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def skip_tl_bytes(data, offset)
|
|
59
|
+
first_byte = data.getbyte(offset)
|
|
60
|
+
if first_byte < 254
|
|
61
|
+
total = 1 + first_byte
|
|
62
|
+
else
|
|
63
|
+
len = data.getbyte(offset + 1) |
|
|
64
|
+
(data.getbyte(offset + 2) << 8) |
|
|
65
|
+
(data.getbyte(offset + 3) << 16)
|
|
66
|
+
total = 4 + len
|
|
67
|
+
end
|
|
68
|
+
offset + total + ((4 - (total % 4)) % 4)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class CheckPassword
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xd18b4d16
|
|
9
|
+
INPUT_CHECK_PASSWORD_SRP = 0xd27ff082
|
|
10
|
+
|
|
11
|
+
attr_reader :srp_id, :a, :m1
|
|
12
|
+
|
|
13
|
+
def initialize(srp_id:, a:, m1:)
|
|
14
|
+
@srp_id = srp_id
|
|
15
|
+
@a = a
|
|
16
|
+
@m1 = m1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def body
|
|
20
|
+
u32_b(CONSTRUCTOR) +
|
|
21
|
+
u32_b(INPUT_CHECK_PASSWORD_SRP) +
|
|
22
|
+
u64_b(@srp_id) +
|
|
23
|
+
serialize_tl_bytes(@a) +
|
|
24
|
+
serialize_tl_bytes(@m1)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def serialize_tl_bytes(data)
|
|
30
|
+
bytes = data.bytes
|
|
31
|
+
length = bytes.length
|
|
32
|
+
|
|
33
|
+
if length <= 253
|
|
34
|
+
[length] + bytes + padding(length + 1)
|
|
35
|
+
else
|
|
36
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def padding(current_length)
|
|
41
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
42
|
+
[0] * pad_length
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ClientDHInnerData
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
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 body
|
|
20
|
+
result = u32_b(CONSTRUCTOR)
|
|
21
|
+
result += @nonce.bytes
|
|
22
|
+
result += @server_nonce.bytes
|
|
23
|
+
result += u64_b(@retry_id)
|
|
24
|
+
result += serialize_tl_bytes(@g_b.bytes)
|
|
25
|
+
|
|
26
|
+
result
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def serialize_tl_bytes(bytes)
|
|
32
|
+
length = bytes.length
|
|
33
|
+
|
|
34
|
+
if length <= 253
|
|
35
|
+
[length] + bytes + padding(length + 1)
|
|
36
|
+
else
|
|
37
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def padding(current_length)
|
|
42
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
43
|
+
[0] * pad_length
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class DHGenResponse
|
|
6
|
+
extend Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR_OK = 0x3bcbf734
|
|
9
|
+
CONSTRUCTOR_RETRY = 0x46dc1fb9
|
|
10
|
+
CONSTRUCTOR_FAIL = 0xa69dae02
|
|
11
|
+
|
|
12
|
+
attr_reader :status, :nonce, :server_nonce, :new_nonce_hash
|
|
13
|
+
|
|
14
|
+
def self.parse(message)
|
|
15
|
+
data = message.body
|
|
16
|
+
constructor = b_u32(data[0, 4])
|
|
17
|
+
|
|
18
|
+
status = case constructor
|
|
19
|
+
when CONSTRUCTOR_OK then :ok
|
|
20
|
+
when CONSTRUCTOR_RETRY then :retry
|
|
21
|
+
when CONSTRUCTOR_FAIL then :fail
|
|
22
|
+
else raise "Unexpected constructor: 0x#{constructor.to_s(16)}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
offset = 4
|
|
26
|
+
nonce = data[offset, 16].pack('C*')
|
|
27
|
+
offset += 16
|
|
28
|
+
server_nonce = data[offset, 16].pack('C*')
|
|
29
|
+
offset += 16
|
|
30
|
+
new_nonce_hash = data[offset, 16].pack('C*')
|
|
31
|
+
|
|
32
|
+
new(
|
|
33
|
+
status: status,
|
|
34
|
+
nonce: nonce,
|
|
35
|
+
server_nonce: server_nonce,
|
|
36
|
+
new_nonce_hash: new_nonce_hash
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def initialize(status:, nonce:, server_nonce:, new_nonce_hash:)
|
|
43
|
+
@status = status
|
|
44
|
+
@nonce = nonce
|
|
45
|
+
@server_nonce = server_nonce
|
|
46
|
+
@new_nonce_hash = new_nonce_hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ExportLoginToken
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xb7e085fe
|
|
9
|
+
VECTOR_CONSTRUCTOR = 0x1cb5c415
|
|
10
|
+
|
|
11
|
+
attr_reader :api_id, :api_hash, :except_ids
|
|
12
|
+
|
|
13
|
+
def initialize(api_id:, api_hash:, except_ids: [])
|
|
14
|
+
@api_id = api_id
|
|
15
|
+
@api_hash = api_hash
|
|
16
|
+
@except_ids = except_ids
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def body
|
|
20
|
+
u32_b(CONSTRUCTOR) +
|
|
21
|
+
u32_b(@api_id) +
|
|
22
|
+
serialize_tl_string(@api_hash) +
|
|
23
|
+
serialize_vector_long(@except_ids)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def serialize_vector_long(ids)
|
|
29
|
+
result = u32_b(VECTOR_CONSTRUCTOR) + u32_b(ids.length)
|
|
30
|
+
ids.each { |id| result += u64_b(id) }
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def serialize_tl_string(str)
|
|
35
|
+
bytes = str.encode('UTF-8').bytes
|
|
36
|
+
length = bytes.length
|
|
37
|
+
|
|
38
|
+
if length <= 253
|
|
39
|
+
[length] + bytes + padding(length + 1)
|
|
40
|
+
else
|
|
41
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def padding(current_length)
|
|
46
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
47
|
+
[0] * pad_length
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class GetDifference
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x19c2f763
|
|
9
|
+
|
|
10
|
+
attr_reader :pts, :date, :qts, :pts_limit, :pts_total_limit, :qts_limit
|
|
11
|
+
|
|
12
|
+
def initialize(pts:, date:, qts:, pts_limit: nil, pts_total_limit: nil, qts_limit: nil)
|
|
13
|
+
@pts = pts
|
|
14
|
+
@date = date
|
|
15
|
+
@qts = qts
|
|
16
|
+
@pts_limit = pts_limit
|
|
17
|
+
@pts_total_limit = pts_total_limit
|
|
18
|
+
@qts_limit = qts_limit
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def body
|
|
22
|
+
flags = 0
|
|
23
|
+
flags |= (1 << 0) if @pts_limit
|
|
24
|
+
flags |= (1 << 1) if @pts_total_limit
|
|
25
|
+
flags |= (1 << 2) if @qts_limit
|
|
26
|
+
|
|
27
|
+
result = u32_b(CONSTRUCTOR) + u32_b(flags) + u32_b(@pts)
|
|
28
|
+
result += u32_b(@pts_limit) if @pts_limit
|
|
29
|
+
result += u32_b(@pts_total_limit) if @pts_total_limit
|
|
30
|
+
result += u32_b(@date) + u32_b(@qts)
|
|
31
|
+
result += u32_b(@qts_limit) if @qts_limit
|
|
32
|
+
result
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class GetUsers
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x0d91a548
|
|
9
|
+
VECTOR_CONSTRUCTOR = 0x1cb5c415
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
|
|
12
|
+
def body
|
|
13
|
+
u32_b(CONSTRUCTOR) +
|
|
14
|
+
u32_b(VECTOR_CONSTRUCTOR) +
|
|
15
|
+
u32_b(1) +
|
|
16
|
+
u32_b(INPUT_USER_SELF)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class HelpConfig
|
|
6
|
+
CONSTRUCTOR = 0xcc1a241e
|
|
7
|
+
CONSTRUCTOR_ALT = 0x3072cfa1
|
|
8
|
+
|
|
9
|
+
attr_reader :flags, :date, :expires, :test_mode, :this_dc, :dc_options
|
|
10
|
+
|
|
11
|
+
def initialize(flags:, date:, expires:, test_mode:, this_dc:, dc_options:)
|
|
12
|
+
@flags = flags
|
|
13
|
+
@date = date
|
|
14
|
+
@expires = expires
|
|
15
|
+
@test_mode = test_mode
|
|
16
|
+
@this_dc = this_dc
|
|
17
|
+
@dc_options = dc_options
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.parse(data)
|
|
21
|
+
constructor = data[0, 4].unpack1('L<')
|
|
22
|
+
raise UnexpectedConstructorError, constructor unless [CONSTRUCTOR, CONSTRUCTOR_ALT].include?(constructor)
|
|
23
|
+
|
|
24
|
+
offset = 4
|
|
25
|
+
flags = data[offset, 4].unpack1('L<')
|
|
26
|
+
offset += 4
|
|
27
|
+
date = data[offset, 4].unpack1('L<')
|
|
28
|
+
offset += 4
|
|
29
|
+
expires = data[offset, 4].unpack1('L<')
|
|
30
|
+
offset += 4
|
|
31
|
+
test_mode = data[offset, 4].unpack1('L<') == 0x997275b5
|
|
32
|
+
offset += 4
|
|
33
|
+
this_dc = data[offset, 4].unpack1('L<')
|
|
34
|
+
offset += 4
|
|
35
|
+
|
|
36
|
+
offset += 4 # vector constructor
|
|
37
|
+
dc_count = data[offset, 4].unpack1('L<')
|
|
38
|
+
offset += 4
|
|
39
|
+
|
|
40
|
+
dc_options = []
|
|
41
|
+
dc_count.times do
|
|
42
|
+
dc_option, offset = parse_dc_option(data, offset)
|
|
43
|
+
dc_options << dc_option
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
new(
|
|
47
|
+
flags: flags, date: date, expires: expires,
|
|
48
|
+
test_mode: test_mode, this_dc: this_dc, dc_options: dc_options
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def parse_dc_option(data, offset)
|
|
56
|
+
offset += 4 # constructor
|
|
57
|
+
flags = data[offset, 4].unpack1('L<')
|
|
58
|
+
offset += 4
|
|
59
|
+
id = data[offset, 4].unpack1('L<')
|
|
60
|
+
offset += 4
|
|
61
|
+
|
|
62
|
+
ip_len = data.getbyte(offset)
|
|
63
|
+
offset += 1
|
|
64
|
+
ip_address = data[offset, ip_len]
|
|
65
|
+
offset += ip_len
|
|
66
|
+
padding = (4 - ((ip_len + 1) % 4)) % 4
|
|
67
|
+
offset += padding
|
|
68
|
+
|
|
69
|
+
port = data[offset, 4].unpack1('L<')
|
|
70
|
+
offset += 4
|
|
71
|
+
|
|
72
|
+
[{ id: id, ip_address: ip_address, port: port, flags: flags }, offset]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ImportLoginToken
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x95ac5ce4
|
|
9
|
+
|
|
10
|
+
attr_reader :token
|
|
11
|
+
|
|
12
|
+
def initialize(token:)
|
|
13
|
+
@token = token
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def body
|
|
17
|
+
u32_b(CONSTRUCTOR) + serialize_tl_bytes(@token)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def serialize_tl_bytes(data)
|
|
23
|
+
bytes = data.bytes
|
|
24
|
+
length = bytes.length
|
|
25
|
+
|
|
26
|
+
if length <= 253
|
|
27
|
+
[length] + bytes + padding(length + 1)
|
|
28
|
+
else
|
|
29
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def padding(current_length)
|
|
34
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
35
|
+
[0] * pad_length
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class InitConnection
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xc1cd5ea9
|
|
9
|
+
|
|
10
|
+
attr_reader :api_id, :device_model, :system_version, :app_version,
|
|
11
|
+
:system_lang_code, :lang_pack, :lang_code, :query
|
|
12
|
+
|
|
13
|
+
def initialize(api_id:, device_model:, system_version:, app_version:,
|
|
14
|
+
system_lang_code:, lang_pack:, lang_code:, query:)
|
|
15
|
+
@api_id = api_id
|
|
16
|
+
@device_model = device_model
|
|
17
|
+
@system_version = system_version
|
|
18
|
+
@app_version = app_version
|
|
19
|
+
@system_lang_code = system_lang_code
|
|
20
|
+
@lang_pack = lang_pack
|
|
21
|
+
@lang_code = lang_code
|
|
22
|
+
@query = query
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def body
|
|
26
|
+
flags = 0
|
|
27
|
+
|
|
28
|
+
result = u32_b(CONSTRUCTOR)
|
|
29
|
+
result += u32_b(flags)
|
|
30
|
+
result += u32_b(@api_id)
|
|
31
|
+
result += serialize_tl_string(@device_model)
|
|
32
|
+
result += serialize_tl_string(@system_version)
|
|
33
|
+
result += serialize_tl_string(@app_version)
|
|
34
|
+
result += serialize_tl_string(@system_lang_code)
|
|
35
|
+
result += serialize_tl_string(@lang_pack)
|
|
36
|
+
result += serialize_tl_string(@lang_code)
|
|
37
|
+
result + @query.body
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def serialize_tl_string(str)
|
|
43
|
+
bytes = str.encode('UTF-8').bytes
|
|
44
|
+
length = bytes.length
|
|
45
|
+
|
|
46
|
+
if length <= 253
|
|
47
|
+
[length] + bytes + padding(length + 1)
|
|
48
|
+
else
|
|
49
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def padding(current_length)
|
|
54
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
55
|
+
[0] * pad_length
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class InvokeWithLayer
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xda9b0d0d
|
|
9
|
+
|
|
10
|
+
attr_reader :layer, :query
|
|
11
|
+
|
|
12
|
+
def initialize(layer:, query:)
|
|
13
|
+
@layer = layer
|
|
14
|
+
@query = query
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def body
|
|
18
|
+
u32_b(CONSTRUCTOR) + u32_b(@layer) + @query.body
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|