mtproto 0.0.32 → 0.0.33
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/lib/mtproto/auth_key_generator.rb +3 -1
- data/lib/mtproto/client/api/resolve_username.rb +18 -0
- data/lib/mtproto/client/api.rb +1 -0
- data/lib/mtproto/crypto/dh_key_exchange.rb +2 -1
- data/lib/mtproto/tl/constructors.rb +1 -0
- data/lib/mtproto/tl/objects/authorization.rb +4 -3
- data/lib/mtproto/tl/objects/channel_difference.rb +13 -32
- data/lib/mtproto/tl/objects/contacts.rb +7 -89
- data/lib/mtproto/tl/objects/dialogs.rb +14 -352
- data/lib/mtproto/tl/objects/edit_message.rb +1 -1
- data/lib/mtproto/tl/objects/message.rb +14 -0
- data/lib/mtproto/tl/objects/message_service.rb +40 -0
- data/lib/mtproto/tl/objects/messages.rb +7 -32
- data/lib/mtproto/tl/objects/resolved_peer.rb +29 -0
- data/lib/mtproto/tl/objects/send_message.rb +1 -1
- data/lib/mtproto/tl/objects/update.rb +3 -35
- data/lib/mtproto/tl/objects/updates.rb +4 -6
- data/lib/mtproto/tl/objects/updates_difference.rb +9 -29
- data/lib/mtproto/tl/peers.rb +233 -0
- data/lib/mtproto/updates/event_builder.rb +20 -32
- data/lib/mtproto/updates/parser.rb +9 -8
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +1 -0
- metadata +5 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../reader'
|
|
4
|
+
require_relative '../peers'
|
|
4
5
|
require_relative 'message'
|
|
5
|
-
require_relative 'dialogs'
|
|
6
6
|
|
|
7
7
|
module MTProto
|
|
8
8
|
module TL
|
|
@@ -37,8 +37,8 @@ module MTProto
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
messages, callback_queries, guest_queries, offset = parse_updates_vector(data, 4)
|
|
40
|
-
users, offset =
|
|
41
|
-
chats, =
|
|
40
|
+
users, offset = Peers.users_at(data, offset)
|
|
41
|
+
chats, = Peers.chats_at(data, offset)
|
|
42
42
|
new(messages: messages, users: users, chats: chats,
|
|
43
43
|
callback_queries: callback_queries, guest_queries: guest_queries)
|
|
44
44
|
end
|
|
@@ -105,9 +105,7 @@ module MTProto
|
|
|
105
105
|
offset += 8
|
|
106
106
|
msg = Message.deserialize(data, offset, data[offset, 4].unpack1('L<'))
|
|
107
107
|
offset = Reader.schema.skip(data, offset) # message:Message
|
|
108
|
-
if flags.anybits?(1 << 0) # reference_messages
|
|
109
|
-
offset = Reader.schema.skip_vector(data, offset) { |d, o| Reader.schema.skip(d, o) }
|
|
110
|
-
end
|
|
108
|
+
offset = Reader.schema.skip_vector(data, offset) if flags.anybits?(1 << 0) # reference_messages
|
|
111
109
|
qts = data[offset, 4].unpack1('l<')
|
|
112
110
|
|
|
113
111
|
{ query_id: query_id, message: msg&.to_h, qts: qts }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../
|
|
3
|
+
require_relative '../reader'
|
|
4
|
+
require_relative '../peers'
|
|
4
5
|
require_relative 'message'
|
|
5
|
-
require_relative 'dialogs'
|
|
6
6
|
require_relative 'updates'
|
|
7
7
|
|
|
8
8
|
module MTProto
|
|
@@ -10,8 +10,6 @@ module MTProto
|
|
|
10
10
|
class UpdatesDifference
|
|
11
11
|
attr_reader :type, :date, :seq, :new_messages, :pts, :state, :chats, :users, :guest_queries, :managed_bots
|
|
12
12
|
|
|
13
|
-
SCHEMA_PATH = File.expand_path('../../../../data/tl-schema.json', __dir__)
|
|
14
|
-
|
|
15
13
|
def initialize(type:, date: nil, seq: nil, new_messages: [], pts: nil, state: nil, chats: [], users: [],
|
|
16
14
|
guest_queries: [], managed_bots: [])
|
|
17
15
|
@type = type
|
|
@@ -26,10 +24,6 @@ module MTProto
|
|
|
26
24
|
@managed_bots = managed_bots
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
def self.schema
|
|
30
|
-
@schema ||= Schema.new(SCHEMA_PATH)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
27
|
def self.deserialize(data)
|
|
34
28
|
constructor = data[0, 4].unpack1('L<')
|
|
35
29
|
|
|
@@ -68,11 +62,12 @@ module MTProto
|
|
|
68
62
|
def parse_difference(data, constructor)
|
|
69
63
|
offset = 4
|
|
70
64
|
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
raw_messages, offset = Message.vector_at(data, offset)
|
|
66
|
+
messages = raw_messages.map(&:to_h)
|
|
67
|
+
offset = Reader.schema.skip_vector(data, offset) # new_encrypted_messages
|
|
73
68
|
other_messages, guest_queries, managed_bots, offset = parse_other_updates(data, offset)
|
|
74
|
-
chats, offset =
|
|
75
|
-
users, offset =
|
|
69
|
+
chats, offset = Peers.chats_at(data, offset)
|
|
70
|
+
users, offset = Peers.users_at(data, offset)
|
|
76
71
|
state = UpdatesState.deserialize(data[offset..])
|
|
77
72
|
|
|
78
73
|
new(
|
|
@@ -86,7 +81,7 @@ module MTProto
|
|
|
86
81
|
|
|
87
82
|
# other_updates: Vector<Update>. Mine the message-bearing updates
|
|
88
83
|
# (updateNewMessage / updateNewChannelMessage — each is the update ctor,
|
|
89
|
-
# then an inner Message, then pts/pts_count); advance the rest via schema.
|
|
84
|
+
# then an inner Message, then pts/pts_count); advance the rest via Reader.schema.
|
|
90
85
|
def parse_other_updates(data, offset)
|
|
91
86
|
offset += 4 # vector constructor
|
|
92
87
|
count = data[offset, 4].unpack1('L<')
|
|
@@ -106,25 +101,10 @@ module MTProto
|
|
|
106
101
|
elsif ctor == UPDATE_MANAGED_BOT
|
|
107
102
|
managed_bots << { user_id: data[offset + 4, 8].unpack1('Q<'), bot_id: data[offset + 12, 8].unpack1('Q<') }
|
|
108
103
|
end
|
|
109
|
-
offset = schema.skip(data, offset)
|
|
104
|
+
offset = Reader.schema.skip(data, offset)
|
|
110
105
|
end
|
|
111
106
|
[messages, guest_queries, managed_bots, offset]
|
|
112
107
|
end
|
|
113
|
-
|
|
114
|
-
def parse_messages_vector(data, offset)
|
|
115
|
-
offset += 4 # vector constructor
|
|
116
|
-
count = data[offset, 4].unpack1('L<')
|
|
117
|
-
offset += 4
|
|
118
|
-
|
|
119
|
-
messages = []
|
|
120
|
-
count.times do
|
|
121
|
-
constructor = data[offset, 4].unpack1('L<')
|
|
122
|
-
msg = Message.deserialize(data, offset, constructor)
|
|
123
|
-
messages << msg.to_h if msg
|
|
124
|
-
offset = schema.skip(data, offset)
|
|
125
|
-
end
|
|
126
|
-
[messages, offset]
|
|
127
|
-
end
|
|
128
108
|
end
|
|
129
109
|
end
|
|
130
110
|
end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'reader'
|
|
4
|
+
|
|
5
|
+
module MTProto
|
|
6
|
+
module TL
|
|
7
|
+
module Peers
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
Chat = Struct.new(:id, :title, :type, :access_hash, :username, keyword_init: true)
|
|
11
|
+
|
|
12
|
+
def chats_at(data, offset)
|
|
13
|
+
offset += 4 # vector constructor
|
|
14
|
+
count = data[offset, 4].unpack1('L<')
|
|
15
|
+
offset += 4
|
|
16
|
+
|
|
17
|
+
chats = []
|
|
18
|
+
count.times do
|
|
19
|
+
chat, offset = parse_chat(data, offset)
|
|
20
|
+
chats << chat if chat
|
|
21
|
+
end
|
|
22
|
+
[chats, offset]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def parse_chat(data, offset)
|
|
26
|
+
constructor = data[offset, 4].unpack1('L<')
|
|
27
|
+
offset += 4
|
|
28
|
+
|
|
29
|
+
case constructor
|
|
30
|
+
when Constructors::CHAT
|
|
31
|
+
parse_basic_chat(data, offset)
|
|
32
|
+
when Constructors::CHANNEL
|
|
33
|
+
parse_channel(data, offset)
|
|
34
|
+
when Constructors::CHAT_FORBIDDEN
|
|
35
|
+
parse_chat_forbidden(data, offset)
|
|
36
|
+
when Constructors::CHANNEL_FORBIDDEN
|
|
37
|
+
parse_channel_forbidden(data, offset)
|
|
38
|
+
when CHAT_EMPTY
|
|
39
|
+
id = data[offset, 8].unpack1('Q<')
|
|
40
|
+
offset += 8
|
|
41
|
+
[Chat.new(id: id, title: '(empty)', type: :chat_empty), offset]
|
|
42
|
+
else
|
|
43
|
+
raise "Unknown Chat constructor: 0x#{constructor.to_s(16).rjust(8, '0')}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
CHAT_EMPTY = 0x29562865
|
|
48
|
+
|
|
49
|
+
# chat#41cbf256 flags:#
|
|
50
|
+
# id:long title:string photo:ChatPhoto
|
|
51
|
+
# participants_count:int date:int version:int
|
|
52
|
+
# migrated_to:flags.6?InputChannel
|
|
53
|
+
# admin_rights:flags.14?ChatAdminRights
|
|
54
|
+
# default_banned_rights:flags.18?ChatBannedRights
|
|
55
|
+
def parse_basic_chat(data, offset)
|
|
56
|
+
flags = data[offset, 4].unpack1('L<')
|
|
57
|
+
offset += 4
|
|
58
|
+
id = data[offset, 8].unpack1('Q<')
|
|
59
|
+
offset += 8
|
|
60
|
+
title, offset = Reader.read_tl_string(data, offset)
|
|
61
|
+
offset = Reader.schema.skip(data, offset) # photo (ChatPhoto)
|
|
62
|
+
offset += 4 # participants_count
|
|
63
|
+
offset += 4 # date
|
|
64
|
+
offset += 4 # version
|
|
65
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 6) # migrated_to (InputChannel)
|
|
66
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 14) # admin_rights
|
|
67
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 18) # default_banned_rights
|
|
68
|
+
|
|
69
|
+
[Chat.new(id: id, title: title, type: :chat), offset]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# channel#1c32b11c flags:# flags2:#
|
|
73
|
+
# id:long access_hash:flags.13?long title:string
|
|
74
|
+
# username:flags.6?string photo:ChatPhoto date:int
|
|
75
|
+
# restriction_reason:flags.9?Vector<RestrictionReason>
|
|
76
|
+
# admin_rights:flags.14?ChatAdminRights
|
|
77
|
+
# banned_rights:flags.15?ChatBannedRights
|
|
78
|
+
# default_banned_rights:flags.18?ChatBannedRights
|
|
79
|
+
# participants_count:flags.17?int
|
|
80
|
+
# usernames:flags2.0?Vector<Username>
|
|
81
|
+
# stories_max_id:flags2.4?int
|
|
82
|
+
# color:flags2.7?PeerColor profile_color:flags2.8?PeerColor
|
|
83
|
+
# emoji_status:flags2.9?EmojiStatus
|
|
84
|
+
# level:flags2.10?int subscription_until_date:flags2.11?int
|
|
85
|
+
# bot_verification_icon:flags2.13?long
|
|
86
|
+
# send_paid_messages_stars:flags2.14?long
|
|
87
|
+
# linked_monoforum_id:flags2.18?long
|
|
88
|
+
def parse_channel(data, offset)
|
|
89
|
+
flags = data[offset, 4].unpack1('L<')
|
|
90
|
+
offset += 4
|
|
91
|
+
flags2 = data[offset, 4].unpack1('L<')
|
|
92
|
+
offset += 4
|
|
93
|
+
id = data[offset, 8].unpack1('Q<')
|
|
94
|
+
offset += 8
|
|
95
|
+
access_hash = nil
|
|
96
|
+
if flags.anybits?(1 << 13)
|
|
97
|
+
access_hash = data[offset, 8].unpack1('Q<')
|
|
98
|
+
offset += 8
|
|
99
|
+
end
|
|
100
|
+
title, offset = Reader.read_tl_string(data, offset)
|
|
101
|
+
username = nil
|
|
102
|
+
username, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 6) # username
|
|
103
|
+
offset = Reader.schema.skip(data, offset) # photo (ChatPhoto)
|
|
104
|
+
offset += 4 # date
|
|
105
|
+
offset = Reader.schema.skip_vector(data, offset) if flags.anybits?(1 << 9) # restriction_reason
|
|
106
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 14) # admin_rights
|
|
107
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 15) # banned_rights
|
|
108
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 18) # default_banned_rights
|
|
109
|
+
offset += 4 if flags.anybits?(1 << 17) # participants_count
|
|
110
|
+
offset = Reader.schema.skip_vector(data, offset) if flags2.anybits?(1 << 0) # usernames Vector<Username>
|
|
111
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 4) # stories_max_id (layer 227: RecentStory)
|
|
112
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 7) # color (PeerColor)
|
|
113
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 8) # profile_color (PeerColor)
|
|
114
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 9) # emoji_status
|
|
115
|
+
offset += 4 if flags2.anybits?(1 << 10) # level
|
|
116
|
+
offset += 4 if flags2.anybits?(1 << 11) # subscription_until_date
|
|
117
|
+
offset += 8 if flags2.anybits?(1 << 13) # bot_verification_icon (long)
|
|
118
|
+
offset += 8 if flags2.anybits?(1 << 14) # send_paid_messages_stars (long)
|
|
119
|
+
offset += 8 if flags2.anybits?(1 << 18) # linked_monoforum_id (long)
|
|
120
|
+
|
|
121
|
+
type = flags.anybits?(1 << 8) ? :supergroup : :channel
|
|
122
|
+
[Chat.new(id: id, title: title, type: type, access_hash: access_hash, username: username), offset]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# chatForbidden#6592a1a7 id:long title:string
|
|
126
|
+
def parse_chat_forbidden(data, offset)
|
|
127
|
+
id = data[offset, 8].unpack1('Q<')
|
|
128
|
+
offset += 8
|
|
129
|
+
title, offset = Reader.read_tl_string(data, offset)
|
|
130
|
+
[Chat.new(id: id, title: title, type: :chat_forbidden), offset]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# channelForbidden#17d493d5 flags:#
|
|
134
|
+
# id:long access_hash:long title:string until_date:flags.16?int
|
|
135
|
+
def parse_channel_forbidden(data, offset)
|
|
136
|
+
flags = data[offset, 4].unpack1('L<')
|
|
137
|
+
offset += 4
|
|
138
|
+
id = data[offset, 8].unpack1('Q<')
|
|
139
|
+
offset += 8
|
|
140
|
+
access_hash = data[offset, 8].unpack1('Q<')
|
|
141
|
+
offset += 8
|
|
142
|
+
title, offset = Reader.read_tl_string(data, offset)
|
|
143
|
+
offset += 4 if flags.anybits?(1 << 16) # until_date
|
|
144
|
+
[Chat.new(id: id, title: title, type: :channel_forbidden, access_hash: access_hash), offset]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def users_at(data, offset)
|
|
148
|
+
offset += 4 # vector constructor
|
|
149
|
+
count = data[offset, 4].unpack1('L<')
|
|
150
|
+
offset += 4
|
|
151
|
+
|
|
152
|
+
users = []
|
|
153
|
+
count.times do
|
|
154
|
+
user, offset = parse_user(data, offset)
|
|
155
|
+
users << user if user
|
|
156
|
+
end
|
|
157
|
+
[users, offset]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
USER_EMPTY = 0xd3bc4b7a
|
|
161
|
+
|
|
162
|
+
# user#31774388 flags:# flags2:#
|
|
163
|
+
# id:long access_hash:flags.0?long
|
|
164
|
+
# first_name:flags.1?string last_name:flags.2?string
|
|
165
|
+
# username:flags.3?string phone:flags.4?string
|
|
166
|
+
# photo:flags.5?UserProfilePhoto status:flags.6?UserStatus
|
|
167
|
+
# bot_info_version:flags.14?int
|
|
168
|
+
# restriction_reason:flags.18?Vector<RestrictionReason>
|
|
169
|
+
# bot_inline_placeholder:flags.19?string
|
|
170
|
+
# lang_code:flags.22?string
|
|
171
|
+
# emoji_status:flags.30?EmojiStatus
|
|
172
|
+
# usernames:flags2.0?Vector<Username>
|
|
173
|
+
# stories_max_id:flags2.5?int
|
|
174
|
+
# color:flags2.8?PeerColor profile_color:flags2.9?PeerColor
|
|
175
|
+
# bot_active_users:flags2.12?int
|
|
176
|
+
# bot_verification_icon:flags2.14?long
|
|
177
|
+
# send_paid_messages_stars:flags2.15?long
|
|
178
|
+
def parse_user(data, offset)
|
|
179
|
+
constructor = data[offset, 4].unpack1('L<')
|
|
180
|
+
offset += 4
|
|
181
|
+
|
|
182
|
+
if constructor == USER_EMPTY
|
|
183
|
+
offset += 8 # id (long)
|
|
184
|
+
return [nil, offset]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
raise "Unknown User constructor: 0x#{constructor.to_s(16)}" unless constructor == Constructors::USER
|
|
188
|
+
|
|
189
|
+
flags = data[offset, 4].unpack1('L<')
|
|
190
|
+
offset += 4
|
|
191
|
+
flags2 = data[offset, 4].unpack1('L<')
|
|
192
|
+
offset += 4
|
|
193
|
+
id = data[offset, 8].unpack1('Q<')
|
|
194
|
+
offset += 8
|
|
195
|
+
access_hash = nil
|
|
196
|
+
if flags.anybits?(1 << 0)
|
|
197
|
+
access_hash = data[offset, 8].unpack1('Q<')
|
|
198
|
+
offset += 8
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
first_name = nil
|
|
202
|
+
first_name, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 1)
|
|
203
|
+
|
|
204
|
+
last_name = nil
|
|
205
|
+
last_name, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 2)
|
|
206
|
+
|
|
207
|
+
username = nil
|
|
208
|
+
username, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 3) # username
|
|
209
|
+
|
|
210
|
+
_, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 4) # phone
|
|
211
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 5) # photo
|
|
212
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 6) # status
|
|
213
|
+
offset += 4 if flags.anybits?(1 << 14) # bot_info_version
|
|
214
|
+
offset = Reader.schema.skip_vector(data, offset) if flags.anybits?(1 << 18) # restriction_reason
|
|
215
|
+
_, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 19) # bot_inline_placeholder
|
|
216
|
+
_, offset = Reader.read_tl_string(data, offset) if flags.anybits?(1 << 22) # lang_code
|
|
217
|
+
offset = Reader.schema.skip(data, offset) if flags.anybits?(1 << 30) # emoji_status
|
|
218
|
+
offset = Reader.schema.skip_vector(data, offset) if flags2.anybits?(1 << 0) # usernames
|
|
219
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 5) # stories_max_id (layer 227: RecentStory)
|
|
220
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 8) # color
|
|
221
|
+
offset = Reader.schema.skip(data, offset) if flags2.anybits?(1 << 9) # profile_color
|
|
222
|
+
offset += 4 if flags2.anybits?(1 << 12) # bot_active_users
|
|
223
|
+
offset += 8 if flags2.anybits?(1 << 14) # bot_verification_icon
|
|
224
|
+
offset += 8 if flags2.anybits?(1 << 15) # send_paid_messages_stars
|
|
225
|
+
|
|
226
|
+
[{ id: id, first_name: first_name, last_name: last_name, username: username,
|
|
227
|
+
is_bot: flags.anybits?(1 << 14), access_hash: access_hash }, offset]
|
|
228
|
+
end
|
|
229
|
+
private_class_method :parse_chat, :parse_basic_chat, :parse_channel,
|
|
230
|
+
:parse_chat_forbidden, :parse_channel_forbidden, :parse_user
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative '../tl/reader'
|
|
4
4
|
require_relative '../tl/objects/message'
|
|
5
|
+
require_relative '../tl/objects/message_service'
|
|
5
6
|
require_relative '../tl/objects/updates'
|
|
6
7
|
require_relative 'event'
|
|
7
8
|
|
|
@@ -27,7 +28,6 @@ module MTProto
|
|
|
27
28
|
UPDATE_BOT_GUEST_CHAT_QUERY = 0xcdd4093d
|
|
28
29
|
UPDATE_MANAGED_BOT = 0x4880ed9a
|
|
29
30
|
|
|
30
|
-
MESSAGE_SERVICE = 0x7a800e0a
|
|
31
31
|
ACTION_CHAT_ADD_USER = 0x15cefd00
|
|
32
32
|
ACTION_JOINED_BY_LINK = 0x031224c3
|
|
33
33
|
ACTION_CHAT_DELETE_USER = 0xa43f30cc
|
|
@@ -76,16 +76,13 @@ module MTProto
|
|
|
76
76
|
bot_id: data[offset + 12, 8].unpack1('Q<'))
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
#
|
|
80
|
-
#
|
|
79
|
+
# One message — an entry of a Vector<Message>, or the one inside an
|
|
80
|
+
# updateNew(Channel)Message — → a :message / :join / :leave Event, or nil.
|
|
81
81
|
# `channel` is the envelope's kind (true for a channelDifference), since the
|
|
82
82
|
# message itself doesn't say.
|
|
83
|
-
def message_or_service(data, offset, ctor, channel:)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
elsif ctor == MESSAGE_SERVICE
|
|
87
|
-
service_event(data, offset, channel: channel, pts: nil, pts_count: nil)
|
|
88
|
-
end
|
|
83
|
+
def message_or_service(data, offset, ctor, channel:, pts:, pts_count:)
|
|
84
|
+
message_event(data, offset, ctor, kind: :message, channel: channel, pts: pts, pts_count: pts_count) ||
|
|
85
|
+
service_event(data, offset, ctor, channel: channel, pts: pts, pts_count: pts_count)
|
|
89
86
|
end
|
|
90
87
|
|
|
91
88
|
# updateNew(Channel)Message: the update tag, an inner Message (plain message, or
|
|
@@ -95,11 +92,7 @@ module MTProto
|
|
|
95
92
|
inner_ctor = data[inner_off, 4].unpack1('L<')
|
|
96
93
|
pts, pts_count = pts_after(data, inner_off)
|
|
97
94
|
|
|
98
|
-
|
|
99
|
-
message_event(data, inner_off, inner_ctor, kind: :message, channel: channel, pts: pts, pts_count: pts_count)
|
|
100
|
-
elsif inner_ctor == MESSAGE_SERVICE
|
|
101
|
-
service_event(data, inner_off, channel: channel, pts: pts, pts_count: pts_count)
|
|
102
|
-
end
|
|
95
|
+
message_or_service(data, inner_off, inner_ctor, channel: channel, pts: pts, pts_count: pts_count)
|
|
103
96
|
end
|
|
104
97
|
|
|
105
98
|
def edit_message(data, offset, channel:)
|
|
@@ -127,19 +120,11 @@ module MTProto
|
|
|
127
120
|
|
|
128
121
|
# messageService carrying a membership action → a :join / :leave Event, else nil.
|
|
129
122
|
# peer_id is the service message's own chat (where the event happened).
|
|
130
|
-
def service_event(data, offset, channel:, pts:, pts_count:)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
io += 8 # flags + id
|
|
134
|
-
_from_type, from_id, io = TL::Reader.parse_peer(data, io) if flags.anybits?(1 << 8) # from_id
|
|
135
|
-
peer_type, peer_id, io = TL::Reader.parse_peer(data, io)
|
|
136
|
-
io = TL::Reader.schema.skip(data, io) if flags.anybits?(1 << 28) # saved_peer_id
|
|
137
|
-
io = TL::Reader.schema.skip(data, io) if flags.anybits?(1 << 3) # reply_to
|
|
138
|
-
io += 4 # date
|
|
139
|
-
action = data[io, 4].unpack1('L<')
|
|
140
|
-
id = data[offset + 8, 4].unpack1('l<')
|
|
123
|
+
def service_event(data, offset, ctor, channel:, pts:, pts_count:)
|
|
124
|
+
header = TL::MessageService.deserialize(data, offset, ctor)
|
|
125
|
+
return unless header
|
|
141
126
|
|
|
142
|
-
event = membership_event(data,
|
|
127
|
+
event = membership_event(data, header)
|
|
143
128
|
return unless event
|
|
144
129
|
|
|
145
130
|
event.channel = channel
|
|
@@ -150,19 +135,22 @@ module MTProto
|
|
|
150
135
|
nil
|
|
151
136
|
end
|
|
152
137
|
|
|
153
|
-
def membership_event(data,
|
|
154
|
-
|
|
138
|
+
def membership_event(data, header)
|
|
139
|
+
io = header.action_offset
|
|
140
|
+
case data[io, 4].unpack1('L<')
|
|
155
141
|
when ACTION_CHAT_ADD_USER
|
|
156
|
-
joined = from_id
|
|
142
|
+
joined = header.from_id
|
|
157
143
|
if data[io + 4, 4].unpack1('L<') == VECTOR && data[io + 8, 4].unpack1('L<').positive?
|
|
158
144
|
joined = data[io + 12, 8].unpack1('Q<')
|
|
159
145
|
end
|
|
160
|
-
Event.new(kind: :join, joined_user_id: joined,
|
|
146
|
+
Event.new(kind: :join, joined_user_id: joined,
|
|
147
|
+
peer_type: header.peer_type, peer_id: header.peer_id, msg_id: header.id)
|
|
161
148
|
when ACTION_JOINED_BY_LINK
|
|
162
|
-
Event.new(kind: :join, joined_user_id: from_id,
|
|
149
|
+
Event.new(kind: :join, joined_user_id: header.from_id,
|
|
150
|
+
peer_type: header.peer_type, peer_id: header.peer_id, msg_id: header.id)
|
|
163
151
|
when ACTION_CHAT_DELETE_USER
|
|
164
152
|
Event.new(kind: :leave, left_user_id: data[io + 4, 8].unpack1('Q<'),
|
|
165
|
-
peer_type: peer_type, peer_id: peer_id, msg_id: id)
|
|
153
|
+
peer_type: header.peer_type, peer_id: header.peer_id, msg_id: header.id)
|
|
166
154
|
end
|
|
167
155
|
end
|
|
168
156
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../tl/reader'
|
|
4
|
-
require_relative '../tl/
|
|
4
|
+
require_relative '../tl/peers'
|
|
5
5
|
require_relative '../tl/objects/updates_state'
|
|
6
6
|
require_relative 'event_builder'
|
|
7
7
|
|
|
@@ -74,8 +74,8 @@ module MTProto
|
|
|
74
74
|
# (updatesCombined only inserts seq_start before the trailing seq, past date).
|
|
75
75
|
def parse_updates(data)
|
|
76
76
|
events, channel_too_long, offset = updates_vector(data, 4)
|
|
77
|
-
users, offset = TL::
|
|
78
|
-
chats, offset = TL::
|
|
77
|
+
users, offset = TL::Peers.users_at(data, offset)
|
|
78
|
+
chats, offset = TL::Peers.chats_at(data, offset)
|
|
79
79
|
date = data[offset, 4].unpack1('L<')
|
|
80
80
|
attach_peers(events, users, chats)
|
|
81
81
|
Batch.new(events: events, users: users, chats: chats,
|
|
@@ -128,8 +128,8 @@ module MTProto
|
|
|
128
128
|
msg_events, offset = messages_vector(data, 4, channel: false)
|
|
129
129
|
offset = TL::Reader.schema.skip_vector(data, offset) # new_encrypted_messages
|
|
130
130
|
upd_events, channel_too_long, offset = updates_vector(data, offset)
|
|
131
|
-
chats, offset = TL::
|
|
132
|
-
users, offset = TL::
|
|
131
|
+
chats, offset = TL::Peers.chats_at(data, offset)
|
|
132
|
+
users, offset = TL::Peers.users_at(data, offset)
|
|
133
133
|
state = TL::UpdatesState.deserialize(data[offset..])
|
|
134
134
|
|
|
135
135
|
events = msg_events + upd_events
|
|
@@ -151,8 +151,8 @@ module MTProto
|
|
|
151
151
|
|
|
152
152
|
msg_events, offset = messages_vector(data, offset, channel: true)
|
|
153
153
|
upd_events, channel_too_long, offset = updates_vector(data, offset)
|
|
154
|
-
chats, offset = TL::
|
|
155
|
-
users, = TL::
|
|
154
|
+
chats, offset = TL::Peers.chats_at(data, offset)
|
|
155
|
+
users, = TL::Peers.users_at(data, offset)
|
|
156
156
|
|
|
157
157
|
events = msg_events + upd_events
|
|
158
158
|
attach_peers(events, users, chats)
|
|
@@ -169,7 +169,8 @@ module MTProto
|
|
|
169
169
|
|
|
170
170
|
events = []
|
|
171
171
|
count.times do
|
|
172
|
-
event = EventBuilder.message_or_service(data, offset, data[offset, 4].unpack1('L<'),
|
|
172
|
+
event = EventBuilder.message_or_service(data, offset, data[offset, 4].unpack1('L<'),
|
|
173
|
+
channel: channel, pts: nil, pts_count: nil)
|
|
173
174
|
events << event if event
|
|
174
175
|
offset = TL::Reader.schema.skip(data, offset)
|
|
175
176
|
end
|
data/lib/mtproto/version.rb
CHANGED
data/lib/mtproto.rb
CHANGED
|
@@ -14,6 +14,7 @@ require_relative 'mtproto/unencrypted_message'
|
|
|
14
14
|
require_relative 'mtproto/tl/constructors'
|
|
15
15
|
require_relative 'mtproto/tl/constructor_names'
|
|
16
16
|
require_relative 'mtproto/tl/reader'
|
|
17
|
+
require_relative 'mtproto/tl/peers'
|
|
17
18
|
require_relative 'mtproto/tl/message_entity'
|
|
18
19
|
require_relative 'mtproto/markdown'
|
|
19
20
|
require_relative 'mtproto/tl/object'
|
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.33
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artem Levenkov
|
|
@@ -80,6 +80,7 @@ files:
|
|
|
80
80
|
- lib/mtproto/client/api/import_bot_authorization.rb
|
|
81
81
|
- lib/mtproto/client/api/import_login_token.rb
|
|
82
82
|
- lib/mtproto/client/api/pin_message.rb
|
|
83
|
+
- lib/mtproto/client/api/resolve_username.rb
|
|
83
84
|
- lib/mtproto/client/api/send_code.rb
|
|
84
85
|
- lib/mtproto/client/api/send_message.rb
|
|
85
86
|
- lib/mtproto/client/api/set_typing.rb
|
|
@@ -170,6 +171,7 @@ files:
|
|
|
170
171
|
- lib/mtproto/tl/objects/keyboard_button_callback.rb
|
|
171
172
|
- lib/mtproto/tl/objects/login_token.rb
|
|
172
173
|
- lib/mtproto/tl/objects/message.rb
|
|
174
|
+
- lib/mtproto/tl/objects/message_service.rb
|
|
173
175
|
- lib/mtproto/tl/objects/messages.rb
|
|
174
176
|
- lib/mtproto/tl/objects/messages_add_chat_user.rb
|
|
175
177
|
- lib/mtproto/tl/objects/messages_create_chat.rb
|
|
@@ -186,6 +188,7 @@ files:
|
|
|
186
188
|
- lib/mtproto/tl/objects/res_pq.rb
|
|
187
189
|
- lib/mtproto/tl/objects/reset_bot_commands.rb
|
|
188
190
|
- lib/mtproto/tl/objects/resolve_username.rb
|
|
191
|
+
- lib/mtproto/tl/objects/resolved_peer.rb
|
|
189
192
|
- lib/mtproto/tl/objects/rpc_error.rb
|
|
190
193
|
- lib/mtproto/tl/objects/save_big_file_part.rb
|
|
191
194
|
- lib/mtproto/tl/objects/save_file_part.rb
|
|
@@ -219,6 +222,7 @@ files:
|
|
|
219
222
|
- lib/mtproto/tl/objects/updates_state.rb
|
|
220
223
|
- lib/mtproto/tl/objects/upload_profile_photo.rb
|
|
221
224
|
- lib/mtproto/tl/objects/users.rb
|
|
225
|
+
- lib/mtproto/tl/peers.rb
|
|
222
226
|
- lib/mtproto/tl/reader.rb
|
|
223
227
|
- lib/mtproto/tl/schema.rb
|
|
224
228
|
- lib/mtproto/transport/abridged_packet_codec.rb
|