mtproto 0.0.14 → 0.0.17

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/data/tl-schema.json +47158 -42684
  3. data/lib/mtproto/auth_key_generator.rb +2 -2
  4. data/lib/mtproto/client/api/export_authorization.rb +17 -0
  5. data/lib/mtproto/client/api/import_authorization.rb +23 -0
  6. data/lib/mtproto/client/api.rb +2 -0
  7. data/lib/mtproto/client/rpc.rb +33 -0
  8. data/lib/mtproto/client.rb +54 -1
  9. data/lib/mtproto/file_downloader.rb +122 -0
  10. data/lib/mtproto/tl/constructor_names.rb +324 -109
  11. data/lib/mtproto/tl/constructors.rb +16 -8
  12. data/lib/mtproto/tl/objects/bot_command_scope.rb +81 -0
  13. data/lib/mtproto/tl/objects/channels_join_channel.rb +1 -1
  14. data/lib/mtproto/tl/objects/channels_update_username.rb +42 -0
  15. data/lib/mtproto/tl/objects/contacts.rb +1 -1
  16. data/lib/mtproto/tl/objects/create_bot.rb +54 -0
  17. data/lib/mtproto/tl/objects/dialogs.rb +25 -10
  18. data/lib/mtproto/tl/objects/edit_access_settings.rb +46 -0
  19. data/lib/mtproto/tl/objects/export_authorization.rb +17 -0
  20. data/lib/mtproto/tl/objects/export_bot_token.rb +32 -0
  21. data/lib/mtproto/tl/objects/exported_authorization.rb +32 -0
  22. data/lib/mtproto/tl/objects/exported_bot_token.rb +27 -0
  23. data/lib/mtproto/tl/objects/forward_messages.rb +12 -3
  24. data/lib/mtproto/tl/objects/get_access_settings.rb +28 -0
  25. data/lib/mtproto/tl/objects/get_bot_callback_answer.rb +67 -0
  26. data/lib/mtproto/tl/objects/get_bot_commands.rb +46 -0
  27. data/lib/mtproto/tl/objects/get_file.rb +10 -2
  28. data/lib/mtproto/tl/objects/import_authorization.rb +38 -0
  29. data/lib/mtproto/tl/objects/input_keyboard_button_request_peer.rb +54 -0
  30. data/lib/mtproto/tl/objects/keyboard_button_callback.rb +50 -0
  31. data/lib/mtproto/tl/objects/message.rb +97 -21
  32. data/lib/mtproto/tl/objects/messages.rb +7 -74
  33. data/lib/mtproto/tl/objects/messages_get_messages.rb +26 -0
  34. data/lib/mtproto/tl/objects/reply_inline_markup.rb +30 -0
  35. data/lib/mtproto/tl/objects/reply_keyboard_markup.rb +35 -0
  36. data/lib/mtproto/tl/objects/request_peer_type_create_bot.rb +47 -0
  37. data/lib/mtproto/tl/objects/reset_bot_commands.rb +45 -0
  38. data/lib/mtproto/tl/objects/send_bot_requested_peer.rb +51 -0
  39. data/lib/mtproto/tl/objects/send_media.rb +87 -4
  40. data/lib/mtproto/tl/objects/send_message.rb +7 -2
  41. data/lib/mtproto/tl/objects/send_message_action.rb +48 -0
  42. data/lib/mtproto/tl/objects/set_bot_callback_answer.rb +54 -0
  43. data/lib/mtproto/tl/objects/set_bot_commands.rb +53 -0
  44. data/lib/mtproto/tl/objects/set_bot_guest_chat_result.rb +84 -0
  45. data/lib/mtproto/tl/objects/set_bot_info.rb +64 -0
  46. data/lib/mtproto/tl/objects/set_typing.rb +49 -0
  47. data/lib/mtproto/tl/objects/update_status.rb +24 -0
  48. data/lib/mtproto/tl/objects/updates.rb +117 -0
  49. data/lib/mtproto/tl/objects/updates_difference.rb +45 -69
  50. data/lib/mtproto/tl/objects/upload_profile_photo.rb +65 -0
  51. data/lib/mtproto/tl/reader.rb +188 -0
  52. data/lib/mtproto/transport/abridged_packet_codec.rb +5 -1
  53. data/lib/mtproto/unencrypted_message.rb +39 -0
  54. data/lib/mtproto/version.rb +1 -1
  55. data/lib/mtproto.rb +4 -1
  56. data/scripts/gen_constructor_names.rb +72 -0
  57. data/scripts/tl_to_json.rb +72 -0
  58. data/scripts/verify_ids.rb +33 -0
  59. metadata +38 -2
  60. data/lib/mtproto/message/message.rb +0 -85
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Regenerate lib/mtproto/tl/constructor_names.rb (the id -> name map used only for
5
+ # logging and error text) from the LOCAL data/tl-schema.json (current layer),
6
+ # preserving the stable MTProto transport-layer names the API schema lacks.
7
+ #
8
+ # Why not scripts/generate_constructors.rb: that one fetches
9
+ # core.telegram.org/schema/json, which is STALE (~layer 214, no guest mode), and
10
+ # overwrites constructors.rb. This one is offline and uses the migrated schema.
11
+ #
12
+ # Run: ruby scripts/gen_constructor_names.rb
13
+
14
+ require 'json'
15
+
16
+ root = File.expand_path('..', __dir__)
17
+ schema = JSON.parse(File.read(File.join(root, 'data/tl-schema.json')))
18
+ names_file = File.join(root, 'lib/mtproto/tl/constructor_names.rb')
19
+
20
+ api = {} # unsigned id => predicate/method name
21
+ api_names = {} # name => true
22
+ schema.fetch('constructors').each do |c|
23
+ api[c['id'].to_i & 0xffffffff] = c['predicate']
24
+ api_names[c['predicate']] = true
25
+ end
26
+ schema.fetch('methods').each do |m|
27
+ api[m['id'].to_i & 0xffffffff] = m['method']
28
+ api_names[m['method']] = true
29
+ end
30
+
31
+ # Preserve MTProto transport-layer names (rpc_result, msgs_ack, dh_gen_*, ...) that
32
+ # the API schema does not carry. An existing id absent from the API schema is
33
+ # transport-core UNLESS its name is an API predicate/method — that marks a pre-bump
34
+ # constructor whose id changed, so drop it (the current id is already in `api`).
35
+ core = {}
36
+ File.foreach(names_file) do |line|
37
+ next unless line =~ /0x([0-9a-fA-F]{8})\s*=>\s*'([^']+)'/
38
+
39
+ id = Regexp.last_match(1).to_i(16)
40
+ name = Regexp.last_match(2)
41
+ next if api.key?(id) || api_names.key?(name)
42
+
43
+ core[id] = name
44
+ end
45
+
46
+ entries = api.merge(core).sort.map { |id, name| format(" 0x%08x => '%s'", id, name) }
47
+
48
+ out = []
49
+ out << '# frozen_string_literal: true'
50
+ out << ''
51
+ out << '# rubocop:disable Metrics/ModuleLength'
52
+ out << ''
53
+ out << '# Auto-generated id -> constructor/method name map (logging + error messages).'
54
+ out << '# API names from data/tl-schema.json (current layer); MTProto transport-layer'
55
+ out << '# names preserved from the prior map.'
56
+ out << '# Run: ruby scripts/gen_constructor_names.rb'
57
+ out << ''
58
+ out << "require_relative 'constructors'"
59
+ out << ''
60
+ out << 'module MTProto'
61
+ out << ' module TL'
62
+ out << ' module ConstructorNames'
63
+ out << ' NAMES = {'
64
+ entries.each_with_index { |e, i| out << (i == entries.size - 1 ? e : "#{e},") }
65
+ out << ' }.freeze'
66
+ out << ' end'
67
+ out << ' end'
68
+ out << 'end'
69
+ out << '# rubocop:enable Metrics/ModuleLength'
70
+
71
+ File.write(names_file, "#{out.join("\n")}\n")
72
+ puts "wrote #{api.size + core.size} entries (#{api.size} api + #{core.size} transport-core)"
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # Convert a tdesktop-style TL schema (.tl) into mtproto-ruby's tl-schema.json
5
+ # format ({ "constructors": [...], "methods": [...] }, each entry
6
+ # { id (signed int32 string), predicate|method, params:[{name,type}], type }).
7
+ #
8
+ # Telegram's published core.telegram.org/schema JSON lags the live layer (it is
9
+ # still ~214 with no guest constructors), so the authoritative current source is
10
+ # tdesktop's Telegram/SourceFiles/mtproto/scheme/api.tl (layer 225).
11
+ #
12
+ # Usage: ruby tl_to_json.rb api.tl [mtproto.tl ...] > tl-schema.json
13
+
14
+ require 'json'
15
+
16
+ def signed32(hexid)
17
+ u = hexid.to_i(16)
18
+ u >= (1 << 31) ? u - (1 << 32) : u
19
+ end
20
+
21
+ # Params come straight from the .tl tokens: "name:type" where type is already in
22
+ # the gem's native form ("#", "flags.8?Peer", "Vector<Message>", "long", "!X").
23
+ # Skip generic declarations ("{X:Type}") and bare core noise ("#", "[", "t", "]").
24
+ def parse_params(tokens)
25
+ tokens.each_with_object([]) do |tok, acc|
26
+ next if tok.start_with?('{')
27
+ next unless tok.include?(':')
28
+
29
+ name, type = tok.split(':', 2)
30
+ acc << { 'name' => name, 'type' => type }
31
+ end
32
+ end
33
+
34
+ constructors = []
35
+ methods = []
36
+ section = :constructors
37
+
38
+ ARGV.each do |path|
39
+ File.foreach(path) do |raw|
40
+ line = raw.strip
41
+ next if line.empty? || line.start_with?('//')
42
+
43
+ if line == '---functions---'
44
+ section = :methods
45
+ next
46
+ end
47
+ if line == '---types---'
48
+ section = :constructors
49
+ next
50
+ end
51
+
52
+ next unless line.include?('=') && line.end_with?(';')
53
+
54
+ body = line[0..-2] # drop trailing ';'
55
+ lhs, rhs = body.split('=', 2)
56
+ lhs_tokens = lhs.split(/\s+/)
57
+ head = lhs_tokens.shift
58
+ next unless head&.include?('#') # skip id-less core types ("int ? = Int;")
59
+
60
+ name, hexid = head.split('#', 2)
61
+ entry = {
62
+ 'id' => signed32(hexid).to_s,
63
+ (section == :constructors ? 'predicate' : 'method') => name,
64
+ 'params' => parse_params(lhs_tokens),
65
+ 'type' => rhs.strip
66
+ }
67
+ (section == :constructors ? constructors : methods) << entry
68
+ end
69
+ end
70
+
71
+ warn "constructors=#{constructors.size} methods=#{methods.size}"
72
+ puts JSON.pretty_generate('constructors' => constructors, 'methods' => methods)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ # Flag every hardcoded 0x id in the gem's lib that is NOT a valid layer-227
3
+ # constructor/method id (api.tl). Survivors are either mtproto-layer ids (fine,
4
+ # they live in mtproto.tl) or genuinely-changed api ids (must be updated).
5
+ require 'set'
6
+
7
+ tl = ARGV[0]
8
+ libdir = ARGV[1]
9
+
10
+ ids = Set.new
11
+ names = {}
12
+ File.foreach(tl) do |l|
13
+ next unless l =~ /\A([\w.]+)#([0-9a-f]+)/
14
+ ids << Regexp.last_match(2).to_i(16)
15
+ names[Regexp.last_match(2).to_i(16)] = Regexp.last_match(1)
16
+ end
17
+ warn "api227 ids: #{ids.size}"
18
+
19
+ IGNORE = %w[0xffffffff 0x7fffffff 0x80000000 0x00000000 0xfffffffe].freeze
20
+ seen = {}
21
+ Dir.glob("#{libdir}/**/*.rb").each do |f|
22
+ File.foreach(f).with_index do |line, i|
23
+ line.scan(/0x[0-9a-fA-F]{6,8}/).each do |tok|
24
+ t = tok.downcase
25
+ next if IGNORE.include?(t)
26
+ next if ids.include?(t.to_i(16))
27
+ (seen[t] ||= []) << "#{File.basename(f)}:#{i + 1}"
28
+ end
29
+ end
30
+ end
31
+
32
+ puts "=== gem 0x ids NOT present as a layer-227 api constructor/method ==="
33
+ seen.sort.each { |tok, locs| puts format('%-12s %s', tok, locs.uniq.join(', ')) }
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.14
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Levenkov
@@ -63,6 +63,7 @@ files:
63
63
  - lib/mtproto/client.rb
64
64
  - lib/mtproto/client/api.rb
65
65
  - lib/mtproto/client/api/check_password.rb
66
+ - lib/mtproto/client/api/export_authorization.rb
66
67
  - lib/mtproto/client/api/export_login_token.rb
67
68
  - lib/mtproto/client/api/get_contacts.rb
68
69
  - lib/mtproto/client/api/get_dialogs.rb
@@ -70,6 +71,7 @@ files:
70
71
  - lib/mtproto/client/api/get_updates_difference.rb
71
72
  - lib/mtproto/client/api/get_updates_state.rb
72
73
  - lib/mtproto/client/api/get_users.rb
74
+ - lib/mtproto/client/api/import_authorization.rb
73
75
  - lib/mtproto/client/api/import_login_token.rb
74
76
  - lib/mtproto/client/api/send_code.rb
75
77
  - lib/mtproto/client/api/send_message.rb
@@ -88,7 +90,7 @@ files:
88
90
  - lib/mtproto/delegate_methods.rb
89
91
  - lib/mtproto/encrypted_message.rb
90
92
  - lib/mtproto/errors.rb
91
- - lib/mtproto/message/message.rb
93
+ - lib/mtproto/file_downloader.rb
92
94
  - lib/mtproto/message_id.rb
93
95
  - lib/mtproto/session.rb
94
96
  - lib/mtproto/tl/constructor_names.rb
@@ -96,6 +98,7 @@ files:
96
98
  - lib/mtproto/tl/object.rb
97
99
  - lib/mtproto/tl/objects/account_password.rb
98
100
  - lib/mtproto/tl/objects/authorization.rb
101
+ - lib/mtproto/tl/objects/bot_command_scope.rb
99
102
  - lib/mtproto/tl/objects/channels_create_channel.rb
100
103
  - lib/mtproto/tl/objects/channels_delete_messages.rb
101
104
  - lib/mtproto/tl/objects/channels_delete_participant_history.rb
@@ -105,15 +108,25 @@ files:
105
108
  - lib/mtproto/tl/objects/channels_join_channel.rb
106
109
  - lib/mtproto/tl/objects/channels_leave_channel.rb
107
110
  - lib/mtproto/tl/objects/channels_report_spam.rb
111
+ - lib/mtproto/tl/objects/channels_update_username.rb
108
112
  - lib/mtproto/tl/objects/check_password.rb
109
113
  - lib/mtproto/tl/objects/client_dh_inner_data.rb
110
114
  - lib/mtproto/tl/objects/contacts.rb
115
+ - lib/mtproto/tl/objects/create_bot.rb
111
116
  - lib/mtproto/tl/objects/delete_messages.rb
112
117
  - lib/mtproto/tl/objects/dh_gen_response.rb
113
118
  - lib/mtproto/tl/objects/dialogs.rb
119
+ - lib/mtproto/tl/objects/edit_access_settings.rb
114
120
  - lib/mtproto/tl/objects/edit_message.rb
121
+ - lib/mtproto/tl/objects/export_authorization.rb
122
+ - lib/mtproto/tl/objects/export_bot_token.rb
115
123
  - lib/mtproto/tl/objects/export_login_token.rb
124
+ - lib/mtproto/tl/objects/exported_authorization.rb
125
+ - lib/mtproto/tl/objects/exported_bot_token.rb
116
126
  - lib/mtproto/tl/objects/forward_messages.rb
127
+ - lib/mtproto/tl/objects/get_access_settings.rb
128
+ - lib/mtproto/tl/objects/get_bot_callback_answer.rb
129
+ - lib/mtproto/tl/objects/get_bot_commands.rb
117
130
  - lib/mtproto/tl/objects/get_channel_difference.rb
118
131
  - lib/mtproto/tl/objects/get_config.rb
119
132
  - lib/mtproto/tl/objects/get_contacts.rb
@@ -129,49 +142,72 @@ files:
129
142
  - lib/mtproto/tl/objects/get_users.rb
130
143
  - lib/mtproto/tl/objects/gzip_packed.rb
131
144
  - lib/mtproto/tl/objects/help_config.rb
145
+ - lib/mtproto/tl/objects/import_authorization.rb
132
146
  - lib/mtproto/tl/objects/import_bot_authorization.rb
133
147
  - lib/mtproto/tl/objects/import_login_token.rb
134
148
  - lib/mtproto/tl/objects/init_connection.rb
149
+ - lib/mtproto/tl/objects/input_keyboard_button_request_peer.rb
135
150
  - lib/mtproto/tl/objects/invite_to_channel.rb
136
151
  - lib/mtproto/tl/objects/invoke_with_layer.rb
152
+ - lib/mtproto/tl/objects/keyboard_button_callback.rb
137
153
  - lib/mtproto/tl/objects/login_token.rb
138
154
  - lib/mtproto/tl/objects/message.rb
139
155
  - lib/mtproto/tl/objects/messages.rb
156
+ - lib/mtproto/tl/objects/messages_get_messages.rb
140
157
  - lib/mtproto/tl/objects/msg_container.rb
141
158
  - lib/mtproto/tl/objects/new_session_created.rb
142
159
  - lib/mtproto/tl/objects/pq_inner_data.rb
143
160
  - lib/mtproto/tl/objects/raw_response.rb
161
+ - lib/mtproto/tl/objects/reply_inline_markup.rb
162
+ - lib/mtproto/tl/objects/reply_keyboard_markup.rb
144
163
  - lib/mtproto/tl/objects/req_dh_params.rb
145
164
  - lib/mtproto/tl/objects/req_pq_multi.rb
165
+ - lib/mtproto/tl/objects/request_peer_type_create_bot.rb
146
166
  - lib/mtproto/tl/objects/res_pq.rb
167
+ - lib/mtproto/tl/objects/reset_bot_commands.rb
147
168
  - lib/mtproto/tl/objects/resolve_username.rb
148
169
  - lib/mtproto/tl/objects/rpc_error.rb
149
170
  - lib/mtproto/tl/objects/save_file_part.rb
171
+ - lib/mtproto/tl/objects/send_bot_requested_peer.rb
150
172
  - lib/mtproto/tl/objects/send_code.rb
151
173
  - lib/mtproto/tl/objects/send_media.rb
152
174
  - lib/mtproto/tl/objects/send_message.rb
175
+ - lib/mtproto/tl/objects/send_message_action.rb
153
176
  - lib/mtproto/tl/objects/send_reaction.rb
154
177
  - lib/mtproto/tl/objects/sent_code.rb
155
178
  - lib/mtproto/tl/objects/server_dh_inner_data.rb
156
179
  - lib/mtproto/tl/objects/server_dh_params.rb
180
+ - lib/mtproto/tl/objects/set_bot_callback_answer.rb
181
+ - lib/mtproto/tl/objects/set_bot_commands.rb
182
+ - lib/mtproto/tl/objects/set_bot_guest_chat_result.rb
183
+ - lib/mtproto/tl/objects/set_bot_info.rb
157
184
  - lib/mtproto/tl/objects/set_client_dh_params.rb
185
+ - lib/mtproto/tl/objects/set_typing.rb
158
186
  - lib/mtproto/tl/objects/sign_in.rb
159
187
  - lib/mtproto/tl/objects/update.rb
160
188
  - lib/mtproto/tl/objects/update_short.rb
161
189
  - lib/mtproto/tl/objects/update_short_message.rb
162
190
  - lib/mtproto/tl/objects/update_short_sent_message.rb
191
+ - lib/mtproto/tl/objects/update_status.rb
163
192
  - lib/mtproto/tl/objects/update_username.rb
193
+ - lib/mtproto/tl/objects/updates.rb
164
194
  - lib/mtproto/tl/objects/updates_difference.rb
165
195
  - lib/mtproto/tl/objects/updates_state.rb
196
+ - lib/mtproto/tl/objects/upload_profile_photo.rb
166
197
  - lib/mtproto/tl/objects/users.rb
198
+ - lib/mtproto/tl/reader.rb
167
199
  - lib/mtproto/tl/schema.rb
168
200
  - lib/mtproto/transport/abridged_packet_codec.rb
169
201
  - lib/mtproto/transport/connection.rb
170
202
  - lib/mtproto/transport/errors.rb
171
203
  - lib/mtproto/transport/packet.rb
172
204
  - lib/mtproto/transport/tcp_connection.rb
205
+ - lib/mtproto/unencrypted_message.rb
173
206
  - lib/mtproto/version.rb
207
+ - scripts/gen_constructor_names.rb
174
208
  - scripts/generate_constructors.rb
209
+ - scripts/tl_to_json.rb
210
+ - scripts/verify_ids.rb
175
211
  - tmp/.keep
176
212
  homepage: https://github.com/alev-pro/mtproto-ruby
177
213
  licenses:
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MTProto
4
- class Message
5
- include Binary
6
- extend Binary
7
-
8
- attr_reader :auth_key_id, :msg_id, :body,
9
- :msg_key, :encrypted_data,
10
- :server_salt, :session_id, :seq_no
11
-
12
- def initialize(body, msg_id: self.class.generate_msg_id, auth_key_id: 0)
13
- @auth_key_id = auth_key_id
14
- @msg_id = msg_id
15
- @body = body
16
- end
17
-
18
- def self.parse(packet)
19
- data = packet.data
20
- auth_key_id = b_u64(data[0, 8])
21
-
22
- if auth_key_id.zero?
23
- parse_unencrypted(data)
24
- else
25
- parse_encrypted(data, auth_key_id)
26
- end
27
- end
28
-
29
- def encrypted?
30
- !@auth_key_id.zero?
31
- end
32
-
33
- def decrypt(auth_key:, sender: :server)
34
- raise 'Message is not encrypted' unless encrypted?
35
-
36
- keys = Crypto::MessageKey.derive_aes_key_iv(auth_key, @msg_key, sender: sender)
37
- plaintext = Crypto::AES_IGE.decrypt_ige(@encrypted_data, keys[:aes_key], keys[:aes_iv])
38
-
39
- expected_msg_key = Crypto::MessageKey.generate_msg_key(auth_key, plaintext, sender: sender)
40
- raise 'msg_key mismatch!' unless @msg_key == expected_msg_key
41
-
42
- offset = 0
43
- @server_salt = plaintext[offset, 8].unpack1('Q<')
44
- offset += 8
45
- @session_id = plaintext[offset, 8].unpack1('Q<')
46
- offset += 8
47
- @msg_id = plaintext[offset, 8].unpack1('Q<')
48
- offset += 8
49
- @seq_no = plaintext[offset, 4].unpack1('L<')
50
- offset += 4
51
- body_length = plaintext[offset, 4].unpack1('L<')
52
- offset += 4
53
- @body = plaintext[offset, body_length].bytes
54
-
55
- self
56
- end
57
-
58
- def bytes
59
- u64_b(@auth_key_id) +
60
- u64_b(@msg_id) +
61
- u32_b(@body.length) +
62
- @body
63
- end
64
-
65
- def self.generate_msg_id
66
- (Time.now.to_f * (2**32)).to_i & ~3
67
- end
68
-
69
- private_class_method def self.parse_unencrypted(data)
70
- msg_id = b_u64(data[8, 8])
71
- body_length = b_u32(data[16, 4])
72
- body = data[20, body_length]
73
-
74
- new(body, msg_id: msg_id, auth_key_id: 0)
75
- end
76
-
77
- private_class_method def self.parse_encrypted(data, auth_key_id)
78
- msg = allocate
79
- msg.instance_variable_set(:@auth_key_id, auth_key_id)
80
- msg.instance_variable_set(:@msg_key, data[8, 16].pack('C*'))
81
- msg.instance_variable_set(:@encrypted_data, data[24..].pack('C*'))
82
- msg
83
- end
84
- end
85
- end