mtproto 0.0.9 → 0.0.11
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 +1 -1
- data/ext/factorization/extconf.rb +1 -1
- 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.rb +8 -0
- data/lib/mtproto/client/rpc.rb +4 -7
- data/lib/mtproto/client.rb +7 -7
- data/lib/mtproto/errors.rb +8 -0
- data/lib/mtproto/tl/constructor_names.rb +2271 -0
- data/lib/mtproto/tl/constructors.rb +91 -2261
- data/lib/mtproto/tl/object.rb +1 -1
- data/lib/mtproto/tl/objects/account_password.rb +2 -5
- data/lib/mtproto/tl/objects/authorization.rb +2 -5
- data/lib/mtproto/tl/objects/check_password.rb +2 -5
- data/lib/mtproto/tl/objects/client_dh_inner_data.rb +1 -3
- data/lib/mtproto/tl/objects/dh_gen_response.rb +3 -7
- data/lib/mtproto/tl/objects/dialogs.rb +453 -0
- data/lib/mtproto/tl/objects/export_login_token.rb +2 -5
- data/lib/mtproto/tl/objects/get_config.rb +1 -3
- data/lib/mtproto/tl/objects/get_dialogs.rb +51 -0
- data/lib/mtproto/tl/objects/get_difference.rb +1 -3
- data/lib/mtproto/tl/objects/get_history.rb +49 -0
- data/lib/mtproto/tl/objects/get_password.rb +1 -3
- data/lib/mtproto/tl/objects/get_state.rb +1 -3
- data/lib/mtproto/tl/objects/get_users.rb +3 -7
- data/lib/mtproto/{type → tl/objects}/gzip_packed.rb +1 -3
- data/lib/mtproto/tl/objects/help_config.rb +4 -5
- data/lib/mtproto/tl/objects/import_login_token.rb +1 -3
- data/lib/mtproto/tl/objects/init_connection.rb +1 -3
- data/lib/mtproto/tl/objects/invoke_with_layer.rb +1 -3
- data/lib/mtproto/tl/objects/login_token.rb +3 -7
- data/lib/mtproto/{type → tl/objects}/message.rb +1 -1
- 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 +1 -4
- data/lib/mtproto/tl/objects/req_dh_params.rb +1 -3
- data/lib/mtproto/tl/objects/req_pq_multi.rb +1 -3
- data/lib/mtproto/tl/objects/res_pq.rb +2 -4
- data/lib/mtproto/{type → tl/objects}/rpc_error.rb +1 -3
- data/lib/mtproto/tl/objects/send_code.rb +2 -5
- data/lib/mtproto/tl/objects/sent_code.rb +4 -4
- data/lib/mtproto/tl/objects/server_dh_inner_data.rb +3 -3
- data/lib/mtproto/tl/objects/server_dh_params.rb +3 -3
- data/lib/mtproto/tl/objects/set_client_dh_params.rb +1 -3
- data/lib/mtproto/tl/objects/sign_in.rb +1 -3
- data/lib/mtproto/tl/objects/update.rb +3 -6
- data/lib/mtproto/tl/objects/update_short.rb +0 -2
- data/lib/mtproto/tl/objects/update_short_message.rb +0 -2
- data/lib/mtproto/tl/objects/updates_difference.rb +6 -11
- data/lib/mtproto/tl/objects/updates_state.rb +1 -3
- data/lib/mtproto/tl/objects/users.rb +2 -5
- data/lib/mtproto/tl/schema.rb +102 -0
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +6 -10
- metadata +15 -11
- 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/pq_inner_data.rb +0 -41
- data/lib/mtproto/type/serializer.rb +0 -55
- data/lib/mtproto/type/server_dh_inner_data.rb +0 -85
|
@@ -3,11 +3,6 @@
|
|
|
3
3
|
module MTProto
|
|
4
4
|
module TL
|
|
5
5
|
class UpdatesDifference
|
|
6
|
-
CONSTRUCTOR_EMPTY = 0x5d75a138
|
|
7
|
-
CONSTRUCTOR_DIFFERENCE = 0x00f49ca0
|
|
8
|
-
CONSTRUCTOR_SLICE = 0xa8fb1981
|
|
9
|
-
CONSTRUCTOR_TOO_LONG = 0x4afe8f6d
|
|
10
|
-
|
|
11
6
|
attr_reader :type, :date, :seq, :new_messages, :users, :pts, :state
|
|
12
7
|
|
|
13
8
|
def initialize(type:, date: nil, seq: nil, new_messages: [], users: [], pts: nil, state: nil)
|
|
@@ -24,11 +19,11 @@ module MTProto
|
|
|
24
19
|
constructor = data[0, 4].unpack1('L<')
|
|
25
20
|
|
|
26
21
|
case constructor
|
|
27
|
-
when
|
|
22
|
+
when Constructors::UPDATES_DIFFERENCE_EMPTY
|
|
28
23
|
parse_empty(data)
|
|
29
|
-
when
|
|
24
|
+
when Constructors::UPDATES_DIFFERENCE, Constructors::UPDATES_DIFFERENCE_SLICE
|
|
30
25
|
parse_difference(data, constructor)
|
|
31
|
-
when
|
|
26
|
+
when Constructors::UPDATES_DIFFERENCE_TOO_LONG
|
|
32
27
|
new(type: :too_long, pts: data[4, 4].unpack1('L<'))
|
|
33
28
|
else
|
|
34
29
|
warn "Unknown Difference constructor: 0x#{constructor.to_s(16)}, treating as empty"
|
|
@@ -57,7 +52,7 @@ module MTProto
|
|
|
57
52
|
users, = parse_users_vector(data, offset)
|
|
58
53
|
|
|
59
54
|
new(
|
|
60
|
-
type: constructor ==
|
|
55
|
+
type: constructor == Constructors::UPDATES_DIFFERENCE ? :difference : :slice,
|
|
61
56
|
new_messages: messages,
|
|
62
57
|
users: users
|
|
63
58
|
)
|
|
@@ -80,7 +75,7 @@ module MTProto
|
|
|
80
75
|
msg_constructor = data[offset, 4].unpack1('L<')
|
|
81
76
|
offset += 4
|
|
82
77
|
|
|
83
|
-
return [nil, offset] unless msg_constructor ==
|
|
78
|
+
return [nil, offset] unless msg_constructor == Constructors::MESSAGE
|
|
84
79
|
|
|
85
80
|
flags = data[offset, 4].unpack1('L<')
|
|
86
81
|
offset += 4
|
|
@@ -108,7 +103,7 @@ module MTProto
|
|
|
108
103
|
count.times do
|
|
109
104
|
user_constructor = data[offset, 4].unpack1('L<')
|
|
110
105
|
offset += 4
|
|
111
|
-
next unless user_constructor ==
|
|
106
|
+
next unless user_constructor == Constructors::USER
|
|
112
107
|
|
|
113
108
|
flags = data[offset, 4].unpack1('L<')
|
|
114
109
|
offset += 4
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module MTProto
|
|
4
4
|
module TL
|
|
5
5
|
class UpdatesState
|
|
6
|
-
CONSTRUCTOR = 0xa56c2a3e
|
|
7
|
-
|
|
8
6
|
attr_accessor :pts, :qts, :date, :seq, :unread_count
|
|
9
7
|
|
|
10
8
|
def initialize(pts:, qts:, date:, seq:, unread_count:)
|
|
@@ -17,7 +15,7 @@ module MTProto
|
|
|
17
15
|
|
|
18
16
|
def self.parse(data)
|
|
19
17
|
constructor = data[0, 4].unpack1('L<')
|
|
20
|
-
raise UnexpectedConstructorError, constructor unless constructor ==
|
|
18
|
+
raise UnexpectedConstructorError, constructor unless constructor == Constructors::UPDATES_STATE
|
|
21
19
|
|
|
22
20
|
offset = 4
|
|
23
21
|
pts = data[offset, 4].unpack1('L<')
|
|
@@ -3,15 +3,12 @@
|
|
|
3
3
|
module MTProto
|
|
4
4
|
module TL
|
|
5
5
|
class Users
|
|
6
|
-
VECTOR_CONSTRUCTOR = 0x1cb5c415
|
|
7
|
-
USER_CONSTRUCTOR = 0x020b1422
|
|
8
|
-
|
|
9
6
|
User = Struct.new(:id, :access_hash, :first_name, :last_name, :username, :phone, :flags, :flags2,
|
|
10
7
|
keyword_init: true)
|
|
11
8
|
|
|
12
9
|
def self.parse(data)
|
|
13
10
|
constructor = data[0, 4].unpack1('L<')
|
|
14
|
-
raise "Expected Vector constructor, got 0x#{constructor.to_s(16)}" unless constructor ==
|
|
11
|
+
raise "Expected Vector constructor, got 0x#{constructor.to_s(16)}" unless constructor == Constructors::VECTOR
|
|
15
12
|
|
|
16
13
|
offset = 4
|
|
17
14
|
count = data[offset, 4].unpack1('L<')
|
|
@@ -21,7 +18,7 @@ module MTProto
|
|
|
21
18
|
count.times do
|
|
22
19
|
user_constructor = data[offset, 4].unpack1('L<')
|
|
23
20
|
offset += 4
|
|
24
|
-
next unless user_constructor ==
|
|
21
|
+
next unless user_constructor == Constructors::USER
|
|
25
22
|
|
|
26
23
|
flags = data[offset, 4].unpack1('L<')
|
|
27
24
|
offset += 4
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module MTProto
|
|
6
|
+
module TL
|
|
7
|
+
class Schema
|
|
8
|
+
PRIMITIVES = {
|
|
9
|
+
'int' => 4, 'long' => 8, 'double' => 8,
|
|
10
|
+
'int128' => 16, 'int256' => 32
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
def initialize(path)
|
|
14
|
+
raw = JSON.parse(File.read(path))
|
|
15
|
+
@constructors = {}
|
|
16
|
+
raw['constructors'].each do |c|
|
|
17
|
+
uid = c['id'].to_i & 0xFFFFFFFF
|
|
18
|
+
@constructors[uid] = c['params']
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def skip(data, offset)
|
|
23
|
+
constructor = data[offset, 4].unpack1('L<')
|
|
24
|
+
offset += 4
|
|
25
|
+
skip_params(data, offset, constructor)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def skip_vector(data, offset, &block)
|
|
29
|
+
offset += 4 # vector constructor 0x1cb5c415
|
|
30
|
+
count = data[offset, 4].unpack1('L<')
|
|
31
|
+
offset += 4
|
|
32
|
+
count.times { offset = block ? yield(data, offset) : skip(data, offset) }
|
|
33
|
+
offset
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def skip_params(data, offset, constructor)
|
|
37
|
+
params = @constructors[constructor]
|
|
38
|
+
raise "Unknown constructor: 0x#{constructor.to_s(16).rjust(8, '0')}" unless params
|
|
39
|
+
|
|
40
|
+
flag_values = {}
|
|
41
|
+
|
|
42
|
+
params.each do |param|
|
|
43
|
+
type = param['type']
|
|
44
|
+
|
|
45
|
+
if type == '#'
|
|
46
|
+
flag_values[param['name']] = data[offset, 4].unpack1('L<')
|
|
47
|
+
offset += 4
|
|
48
|
+
next
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if (m = type.match(/\A(\w+)\.(\d+)\?(.+)\z/))
|
|
52
|
+
flag_name = m[1]
|
|
53
|
+
bit = m[2].to_i
|
|
54
|
+
inner_type = m[3]
|
|
55
|
+
next if inner_type == 'true'
|
|
56
|
+
next unless flag_values[flag_name]&.anybits?(1 << bit)
|
|
57
|
+
|
|
58
|
+
offset = skip_type(data, offset, inner_type)
|
|
59
|
+
else
|
|
60
|
+
offset = skip_type(data, offset, type)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
offset
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def skip_type(data, offset, type)
|
|
69
|
+
if (size = PRIMITIVES[type])
|
|
70
|
+
return offset + size
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
case type
|
|
74
|
+
when 'string', 'bytes'
|
|
75
|
+
skip_tl_string(data, offset)
|
|
76
|
+
when 'Bool'
|
|
77
|
+
offset + 4
|
|
78
|
+
when /\AVector<(.+)>\z/
|
|
79
|
+
inner = Regexp.last_match(1)
|
|
80
|
+
skip_vector(data, offset) { |d, o| skip_type(d, o, inner) }
|
|
81
|
+
else
|
|
82
|
+
skip(data, offset)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def skip_tl_string(data, offset)
|
|
87
|
+
first_byte = data.getbyte(offset)
|
|
88
|
+
if first_byte == 254
|
|
89
|
+
len = data.getbyte(offset + 1) |
|
|
90
|
+
(data.getbyte(offset + 2) << 8) |
|
|
91
|
+
(data.getbyte(offset + 3) << 16)
|
|
92
|
+
total = 4 + len
|
|
93
|
+
else
|
|
94
|
+
len = first_byte
|
|
95
|
+
total = 1 + len
|
|
96
|
+
end
|
|
97
|
+
padding = (4 - (total % 4)) % 4
|
|
98
|
+
offset + total + padding
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
data/lib/mtproto/version.rb
CHANGED
data/lib/mtproto.rb
CHANGED
|
@@ -11,20 +11,16 @@ require_relative 'mtproto/transport/tcp_connection'
|
|
|
11
11
|
require_relative 'mtproto/transport/connection'
|
|
12
12
|
require_relative 'mtproto/message/message'
|
|
13
13
|
require_relative 'mtproto/tl/constructors'
|
|
14
|
+
require_relative 'mtproto/tl/constructor_names'
|
|
14
15
|
require_relative 'mtproto/tl/object'
|
|
15
16
|
require_relative 'mtproto/tl/objects/update'
|
|
16
17
|
require_relative 'mtproto/tl/objects/update_short'
|
|
17
18
|
require_relative 'mtproto/tl/objects/update_short_message'
|
|
18
|
-
require_relative 'mtproto/
|
|
19
|
-
require_relative 'mtproto/
|
|
20
|
-
require_relative 'mtproto/
|
|
21
|
-
require_relative 'mtproto/
|
|
22
|
-
require_relative 'mtproto/
|
|
23
|
-
require_relative 'mtproto/type/bad_msg_notification'
|
|
24
|
-
require_relative 'mtproto/type/msg_container'
|
|
25
|
-
require_relative 'mtproto/type/new_session_created'
|
|
26
|
-
require_relative 'mtproto/type/rpc_error'
|
|
27
|
-
require_relative 'mtproto/type/gzip_packed'
|
|
19
|
+
require_relative 'mtproto/tl/objects/message'
|
|
20
|
+
require_relative 'mtproto/tl/objects/msg_container'
|
|
21
|
+
require_relative 'mtproto/tl/objects/new_session_created'
|
|
22
|
+
require_relative 'mtproto/tl/objects/rpc_error'
|
|
23
|
+
require_relative 'mtproto/tl/objects/gzip_packed'
|
|
28
24
|
require_relative 'mtproto/crypto/rsa_key'
|
|
29
25
|
require_relative 'mtproto/crypto/factorization'
|
|
30
26
|
require_relative 'mtproto/crypto/aes_ige'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mtproto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artem Levenkov
|
|
@@ -50,6 +50,7 @@ files:
|
|
|
50
50
|
- ".env.example"
|
|
51
51
|
- ".ruby-version"
|
|
52
52
|
- Rakefile
|
|
53
|
+
- data/tl-schema.json
|
|
53
54
|
- ext/aes_ige/aes_ige.c
|
|
54
55
|
- ext/aes_ige/extconf.rb
|
|
55
56
|
- ext/factorization/extconf.rb
|
|
@@ -61,6 +62,8 @@ files:
|
|
|
61
62
|
- lib/mtproto/client/api.rb
|
|
62
63
|
- lib/mtproto/client/api/check_password.rb
|
|
63
64
|
- lib/mtproto/client/api/export_login_token.rb
|
|
65
|
+
- lib/mtproto/client/api/get_dialogs.rb
|
|
66
|
+
- lib/mtproto/client/api/get_history.rb
|
|
64
67
|
- lib/mtproto/client/api/get_updates_difference.rb
|
|
65
68
|
- lib/mtproto/client/api/get_updates_state.rb
|
|
66
69
|
- lib/mtproto/client/api/get_users.rb
|
|
@@ -84,6 +87,7 @@ files:
|
|
|
84
87
|
- lib/mtproto/message/message.rb
|
|
85
88
|
- lib/mtproto/message_id.rb
|
|
86
89
|
- lib/mtproto/session.rb
|
|
90
|
+
- lib/mtproto/tl/constructor_names.rb
|
|
87
91
|
- lib/mtproto/tl/constructors.rb
|
|
88
92
|
- lib/mtproto/tl/object.rb
|
|
89
93
|
- lib/mtproto/tl/objects/account_password.rb
|
|
@@ -91,21 +95,30 @@ files:
|
|
|
91
95
|
- lib/mtproto/tl/objects/check_password.rb
|
|
92
96
|
- lib/mtproto/tl/objects/client_dh_inner_data.rb
|
|
93
97
|
- lib/mtproto/tl/objects/dh_gen_response.rb
|
|
98
|
+
- lib/mtproto/tl/objects/dialogs.rb
|
|
94
99
|
- lib/mtproto/tl/objects/export_login_token.rb
|
|
95
100
|
- lib/mtproto/tl/objects/get_config.rb
|
|
101
|
+
- lib/mtproto/tl/objects/get_dialogs.rb
|
|
96
102
|
- lib/mtproto/tl/objects/get_difference.rb
|
|
103
|
+
- lib/mtproto/tl/objects/get_history.rb
|
|
97
104
|
- lib/mtproto/tl/objects/get_password.rb
|
|
98
105
|
- lib/mtproto/tl/objects/get_state.rb
|
|
99
106
|
- lib/mtproto/tl/objects/get_users.rb
|
|
107
|
+
- lib/mtproto/tl/objects/gzip_packed.rb
|
|
100
108
|
- lib/mtproto/tl/objects/help_config.rb
|
|
101
109
|
- lib/mtproto/tl/objects/import_login_token.rb
|
|
102
110
|
- lib/mtproto/tl/objects/init_connection.rb
|
|
103
111
|
- lib/mtproto/tl/objects/invoke_with_layer.rb
|
|
104
112
|
- lib/mtproto/tl/objects/login_token.rb
|
|
113
|
+
- lib/mtproto/tl/objects/message.rb
|
|
114
|
+
- lib/mtproto/tl/objects/messages.rb
|
|
115
|
+
- lib/mtproto/tl/objects/msg_container.rb
|
|
116
|
+
- lib/mtproto/tl/objects/new_session_created.rb
|
|
105
117
|
- lib/mtproto/tl/objects/pq_inner_data.rb
|
|
106
118
|
- lib/mtproto/tl/objects/req_dh_params.rb
|
|
107
119
|
- lib/mtproto/tl/objects/req_pq_multi.rb
|
|
108
120
|
- lib/mtproto/tl/objects/res_pq.rb
|
|
121
|
+
- lib/mtproto/tl/objects/rpc_error.rb
|
|
109
122
|
- lib/mtproto/tl/objects/send_code.rb
|
|
110
123
|
- lib/mtproto/tl/objects/sent_code.rb
|
|
111
124
|
- lib/mtproto/tl/objects/server_dh_inner_data.rb
|
|
@@ -118,21 +131,12 @@ files:
|
|
|
118
131
|
- lib/mtproto/tl/objects/updates_difference.rb
|
|
119
132
|
- lib/mtproto/tl/objects/updates_state.rb
|
|
120
133
|
- lib/mtproto/tl/objects/users.rb
|
|
134
|
+
- lib/mtproto/tl/schema.rb
|
|
121
135
|
- lib/mtproto/transport/abridged_packet_codec.rb
|
|
122
136
|
- lib/mtproto/transport/connection.rb
|
|
123
137
|
- lib/mtproto/transport/errors.rb
|
|
124
138
|
- lib/mtproto/transport/packet.rb
|
|
125
139
|
- lib/mtproto/transport/tcp_connection.rb
|
|
126
|
-
- lib/mtproto/type/bad_msg_notification.rb
|
|
127
|
-
- lib/mtproto/type/client_dh_inner_data.rb
|
|
128
|
-
- lib/mtproto/type/gzip_packed.rb
|
|
129
|
-
- lib/mtproto/type/message.rb
|
|
130
|
-
- lib/mtproto/type/msg_container.rb
|
|
131
|
-
- lib/mtproto/type/new_session_created.rb
|
|
132
|
-
- lib/mtproto/type/pq_inner_data.rb
|
|
133
|
-
- lib/mtproto/type/rpc_error.rb
|
|
134
|
-
- lib/mtproto/type/serializer.rb
|
|
135
|
-
- lib/mtproto/type/server_dh_inner_data.rb
|
|
136
140
|
- lib/mtproto/updates_poller.rb
|
|
137
141
|
- lib/mtproto/version.rb
|
|
138
142
|
- scripts/generate_constructors.rb
|
|
@@ -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,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,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
module Serializer
|
|
6
|
-
module_function
|
|
7
|
-
|
|
8
|
-
def serialize_int(value)
|
|
9
|
-
[value].pack('L<')
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def serialize_long(value)
|
|
13
|
-
[value].pack('Q<')
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def serialize_int128(value)
|
|
17
|
-
value.is_a?(String) ? value : [value].pack('Q<Q<')
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def serialize_int256(value)
|
|
21
|
-
value.is_a?(String) ? value : [value].pack('Q<Q<Q<Q<')
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def serialize_bytes(bytes)
|
|
25
|
-
length = bytes.bytesize
|
|
26
|
-
|
|
27
|
-
if length <= 253
|
|
28
|
-
[length].pack('C').b + bytes.b + padding(length + 1)
|
|
29
|
-
else
|
|
30
|
-
[254].pack('C').b + [length].pack('L<')[0, 3].b + bytes.b + padding(length + 4)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def serialize_string(str)
|
|
35
|
-
serialize_bytes(str)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def padding(current_length)
|
|
39
|
-
pad_length = (4 - (current_length % 4)) % 4
|
|
40
|
-
("\x00" * pad_length).b
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def integer_to_bytes(int)
|
|
44
|
-
return "\x00" if int.zero?
|
|
45
|
-
|
|
46
|
-
bytes = []
|
|
47
|
-
while int > 0
|
|
48
|
-
bytes.unshift(int & 0xff)
|
|
49
|
-
int >>= 8
|
|
50
|
-
end
|
|
51
|
-
bytes.pack('C*')
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Type
|
|
5
|
-
class ServerDHInnerData
|
|
6
|
-
CONSTRUCTOR = 0xb5890dba
|
|
7
|
-
|
|
8
|
-
attr_reader :nonce, :server_nonce, :g, :dh_prime, :g_a, :server_time
|
|
9
|
-
|
|
10
|
-
def self.deserialize(data)
|
|
11
|
-
constructor = data[0, 4].unpack1('L<')
|
|
12
|
-
raise "Unexpected constructor: 0x#{constructor.to_s(16)}" unless constructor == CONSTRUCTOR
|
|
13
|
-
|
|
14
|
-
offset = 4
|
|
15
|
-
|
|
16
|
-
nonce = data[offset, 16]
|
|
17
|
-
offset += 16
|
|
18
|
-
|
|
19
|
-
server_nonce = data[offset, 16]
|
|
20
|
-
offset += 16
|
|
21
|
-
|
|
22
|
-
g = data[offset, 4].unpack1('L<')
|
|
23
|
-
offset += 4
|
|
24
|
-
|
|
25
|
-
dh_prime_length_byte = data[offset].ord
|
|
26
|
-
offset += 1
|
|
27
|
-
|
|
28
|
-
if dh_prime_length_byte == 254
|
|
29
|
-
length_bytes = data[offset, 3].bytes
|
|
30
|
-
dh_prime_length = length_bytes[0] | (length_bytes[1] << 8) | (length_bytes[2] << 16)
|
|
31
|
-
offset += 3
|
|
32
|
-
else
|
|
33
|
-
dh_prime_length = dh_prime_length_byte
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
dh_prime = data[offset, dh_prime_length]
|
|
37
|
-
offset += dh_prime_length
|
|
38
|
-
offset += padding_length(dh_prime_length_byte == 254 ? dh_prime_length + 4 : dh_prime_length + 1)
|
|
39
|
-
|
|
40
|
-
g_a_length_byte = data[offset].ord
|
|
41
|
-
offset += 1
|
|
42
|
-
|
|
43
|
-
if g_a_length_byte == 254
|
|
44
|
-
length_bytes = data[offset, 3].bytes
|
|
45
|
-
g_a_length = length_bytes[0] | (length_bytes[1] << 8) | (length_bytes[2] << 16)
|
|
46
|
-
offset += 3
|
|
47
|
-
else
|
|
48
|
-
g_a_length = g_a_length_byte
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
g_a = data[offset, g_a_length]
|
|
52
|
-
offset += g_a_length
|
|
53
|
-
offset += padding_length(g_a_length_byte == 254 ? g_a_length + 4 : g_a_length + 1)
|
|
54
|
-
|
|
55
|
-
server_time = data[offset, 4].unpack1('L<')
|
|
56
|
-
|
|
57
|
-
new(
|
|
58
|
-
nonce: nonce,
|
|
59
|
-
server_nonce: server_nonce,
|
|
60
|
-
g: g,
|
|
61
|
-
dh_prime: dh_prime,
|
|
62
|
-
g_a: g_a,
|
|
63
|
-
server_time: server_time
|
|
64
|
-
)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def initialize(nonce:, server_nonce:, g:, dh_prime:, g_a:, server_time:)
|
|
68
|
-
@nonce = nonce
|
|
69
|
-
@server_nonce = server_nonce
|
|
70
|
-
@g = g
|
|
71
|
-
@dh_prime = dh_prime
|
|
72
|
-
@g_a = g_a
|
|
73
|
-
@server_time = server_time
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def self.padding_length(length)
|
|
77
|
-
(4 - (length % 4)) % 4
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def padding_length(length)
|
|
81
|
-
self.class.padding_length(length)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|