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.
- checksums.yaml +4 -4
- data/data/tl-schema.json +47158 -42684
- data/lib/mtproto/auth_key_generator.rb +2 -2
- data/lib/mtproto/client/api/export_authorization.rb +17 -0
- data/lib/mtproto/client/api/import_authorization.rb +23 -0
- data/lib/mtproto/client/api.rb +2 -0
- data/lib/mtproto/client/rpc.rb +33 -0
- data/lib/mtproto/client.rb +54 -1
- data/lib/mtproto/file_downloader.rb +122 -0
- data/lib/mtproto/tl/constructor_names.rb +324 -109
- data/lib/mtproto/tl/constructors.rb +16 -8
- data/lib/mtproto/tl/objects/bot_command_scope.rb +81 -0
- data/lib/mtproto/tl/objects/channels_join_channel.rb +1 -1
- data/lib/mtproto/tl/objects/channels_update_username.rb +42 -0
- data/lib/mtproto/tl/objects/contacts.rb +1 -1
- data/lib/mtproto/tl/objects/create_bot.rb +54 -0
- data/lib/mtproto/tl/objects/dialogs.rb +25 -10
- data/lib/mtproto/tl/objects/edit_access_settings.rb +46 -0
- data/lib/mtproto/tl/objects/export_authorization.rb +17 -0
- data/lib/mtproto/tl/objects/export_bot_token.rb +32 -0
- data/lib/mtproto/tl/objects/exported_authorization.rb +32 -0
- data/lib/mtproto/tl/objects/exported_bot_token.rb +27 -0
- data/lib/mtproto/tl/objects/forward_messages.rb +12 -3
- data/lib/mtproto/tl/objects/get_access_settings.rb +28 -0
- data/lib/mtproto/tl/objects/get_bot_callback_answer.rb +67 -0
- data/lib/mtproto/tl/objects/get_bot_commands.rb +46 -0
- data/lib/mtproto/tl/objects/get_file.rb +10 -2
- data/lib/mtproto/tl/objects/import_authorization.rb +38 -0
- data/lib/mtproto/tl/objects/input_keyboard_button_request_peer.rb +54 -0
- data/lib/mtproto/tl/objects/keyboard_button_callback.rb +50 -0
- data/lib/mtproto/tl/objects/message.rb +97 -21
- data/lib/mtproto/tl/objects/messages.rb +7 -74
- data/lib/mtproto/tl/objects/messages_get_messages.rb +26 -0
- data/lib/mtproto/tl/objects/reply_inline_markup.rb +30 -0
- data/lib/mtproto/tl/objects/reply_keyboard_markup.rb +35 -0
- data/lib/mtproto/tl/objects/request_peer_type_create_bot.rb +47 -0
- data/lib/mtproto/tl/objects/reset_bot_commands.rb +45 -0
- data/lib/mtproto/tl/objects/send_bot_requested_peer.rb +51 -0
- data/lib/mtproto/tl/objects/send_media.rb +87 -4
- data/lib/mtproto/tl/objects/send_message.rb +7 -2
- data/lib/mtproto/tl/objects/send_message_action.rb +48 -0
- data/lib/mtproto/tl/objects/set_bot_callback_answer.rb +54 -0
- data/lib/mtproto/tl/objects/set_bot_commands.rb +53 -0
- data/lib/mtproto/tl/objects/set_bot_guest_chat_result.rb +84 -0
- data/lib/mtproto/tl/objects/set_bot_info.rb +64 -0
- data/lib/mtproto/tl/objects/set_typing.rb +49 -0
- data/lib/mtproto/tl/objects/update_status.rb +24 -0
- data/lib/mtproto/tl/objects/updates.rb +117 -0
- data/lib/mtproto/tl/objects/updates_difference.rb +45 -69
- data/lib/mtproto/tl/objects/upload_profile_photo.rb +65 -0
- data/lib/mtproto/tl/reader.rb +188 -0
- data/lib/mtproto/transport/abridged_packet_codec.rb +5 -1
- data/lib/mtproto/unencrypted_message.rb +39 -0
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +4 -1
- data/scripts/gen_constructor_names.rb +72 -0
- data/scripts/tl_to_json.rb +72 -0
- data/scripts/verify_ids.rb +33 -0
- metadata +38 -2
- data/lib/mtproto/message/message.rb +0 -85
|
@@ -56,6 +56,9 @@ module MTProto
|
|
|
56
56
|
AUTH_SIGN_IN = 0x8d52a951
|
|
57
57
|
AUTH_AUTHORIZATION = 0x2ea2c0d4
|
|
58
58
|
AUTH_AUTHORIZATION_SIGN_UP_REQUIRED = 0x44747e9a
|
|
59
|
+
AUTH_EXPORT_AUTHORIZATION = 0xe5bfffcd
|
|
60
|
+
AUTH_EXPORTED_AUTHORIZATION = 0xb434e2b8
|
|
61
|
+
AUTH_IMPORT_AUTHORIZATION = 0xa57a7dad
|
|
59
62
|
AUTH_CHECK_PASSWORD = 0xd18b4d16
|
|
60
63
|
AUTH_EXPORT_LOGIN_TOKEN = 0xb7e085fe
|
|
61
64
|
AUTH_IMPORT_LOGIN_TOKEN = 0x95ac5ce4
|
|
@@ -70,7 +73,7 @@ module MTProto
|
|
|
70
73
|
|
|
71
74
|
# Users
|
|
72
75
|
USERS_GET_USERS = 0x0d91a548
|
|
73
|
-
USER =
|
|
76
|
+
USER = 0x31774388
|
|
74
77
|
|
|
75
78
|
# Contacts
|
|
76
79
|
CONTACTS_GET_CONTACTS = 0x5dd69e12
|
|
@@ -81,25 +84,30 @@ module MTProto
|
|
|
81
84
|
# Messages
|
|
82
85
|
MESSAGES_GET_DIALOGS = 0xa0f4cb4f
|
|
83
86
|
MESSAGES_GET_HISTORY = 0x4423e6c5
|
|
84
|
-
MESSAGES_SEND_MESSAGE =
|
|
85
|
-
MESSAGES_SEND_MEDIA =
|
|
86
|
-
MESSAGES_EDIT_MESSAGE =
|
|
87
|
+
MESSAGES_SEND_MESSAGE = 0xfef48f62
|
|
88
|
+
MESSAGES_SEND_MEDIA = 0x0330e77f
|
|
89
|
+
MESSAGES_EDIT_MESSAGE = 0xb106e66c
|
|
87
90
|
MESSAGES_DELETE_MESSAGES = 0xe58e95d2
|
|
88
91
|
|
|
89
92
|
# Upload + media
|
|
90
93
|
UPLOAD_SAVE_FILE_PART = 0xb304a621
|
|
91
94
|
INPUT_FILE = 0xf52ff27f
|
|
92
|
-
INPUT_MEDIA_UPLOADED_PHOTO =
|
|
95
|
+
INPUT_MEDIA_UPLOADED_PHOTO = 0x7d8375da
|
|
96
|
+
INPUT_MEDIA_UPLOADED_DOCUMENT = 0x037c9330
|
|
97
|
+
DOCUMENT_ATTRIBUTE_FILENAME = 0x15590068
|
|
98
|
+
DOCUMENT_ATTRIBUTE_AUDIO = 0x9852f9c6
|
|
93
99
|
MESSAGES_DIALOGS = 0x15ba6c40
|
|
94
100
|
MESSAGES_DIALOGS_SLICE = 0x71e094f3
|
|
95
|
-
MESSAGE =
|
|
96
|
-
DIALOG =
|
|
101
|
+
MESSAGE = 0x7600b9d3
|
|
102
|
+
DIALOG = 0xfc89f7f3
|
|
97
103
|
CHAT = 0x41cbf256
|
|
98
104
|
CHAT_FORBIDDEN = 0x6592a1a7
|
|
99
|
-
CHANNEL =
|
|
105
|
+
CHANNEL = 0x1c32b11c
|
|
100
106
|
CHANNEL_FORBIDDEN = 0x17d493d5
|
|
101
107
|
|
|
102
108
|
# Updates
|
|
109
|
+
UPDATES = 0x74ae4240
|
|
110
|
+
UPDATES_COMBINED = 0x725b04c3
|
|
103
111
|
UPDATE_NEW_MESSAGE = 0x1f2b0afd
|
|
104
112
|
UPDATE_SHORT = 0x78d4dec1
|
|
105
113
|
UPDATE_SHORT_MESSAGE = 0x313bc7f8
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
# Serializes a BotCommandScope — the `scope:` field shared by
|
|
6
|
+
# bots.setBotCommands / bots.resetBotCommands / bots.getBotCommands.
|
|
7
|
+
#
|
|
8
|
+
# scope is a hash:
|
|
9
|
+
# { type: :default }
|
|
10
|
+
# { type: :users }
|
|
11
|
+
# { type: :chats }
|
|
12
|
+
# { type: :chat_admins }
|
|
13
|
+
# { type: :peer, peer: <input_peer> }
|
|
14
|
+
# { type: :peer_admins, peer: <input_peer> }
|
|
15
|
+
# { type: :peer_user, peer: <input_peer>, user: <input_user> }
|
|
16
|
+
#
|
|
17
|
+
# input_peer is the same shape used elsewhere (e.g. SendMessage):
|
|
18
|
+
# { type: :self | :user | :chat | :channel, id:, access_hash: }
|
|
19
|
+
# input_user:
|
|
20
|
+
# { type: :self } or { id:, access_hash: }
|
|
21
|
+
module BotCommandScope
|
|
22
|
+
extend Binary
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
DEFAULT = 0x2f6cb2ab
|
|
27
|
+
USERS = 0x3c4f04d8
|
|
28
|
+
CHATS = 0x6fe1a881
|
|
29
|
+
CHAT_ADMINS = 0xb9aa606a
|
|
30
|
+
PEER = 0xdb9d897d
|
|
31
|
+
PEER_ADMINS = 0x3fd863d1
|
|
32
|
+
PEER_USER = 0x0a1321f3
|
|
33
|
+
|
|
34
|
+
INPUT_USER = 0xf21158c6
|
|
35
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
36
|
+
|
|
37
|
+
def serialize(scope)
|
|
38
|
+
scope ||= { type: :default }
|
|
39
|
+
case scope[:type]
|
|
40
|
+
when :default then u32_b(DEFAULT)
|
|
41
|
+
when :users then u32_b(USERS)
|
|
42
|
+
when :chats then u32_b(CHATS)
|
|
43
|
+
when :chat_admins then u32_b(CHAT_ADMINS)
|
|
44
|
+
when :peer then u32_b(PEER) + serialize_input_peer(scope[:peer])
|
|
45
|
+
when :peer_admins then u32_b(PEER_ADMINS) + serialize_input_peer(scope[:peer])
|
|
46
|
+
when :peer_user
|
|
47
|
+
u32_b(PEER_USER) + serialize_input_peer(scope[:peer]) + serialize_input_user(scope[:user])
|
|
48
|
+
else
|
|
49
|
+
raise ArgumentError, "Unknown bot command scope: #{scope[:type].inspect}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def serialize_input_peer(peer)
|
|
54
|
+
raise ArgumentError, 'scope requires peer:' if peer.nil?
|
|
55
|
+
|
|
56
|
+
case peer[:type]
|
|
57
|
+
when :self
|
|
58
|
+
u32_b(Constructors::INPUT_PEER_SELF)
|
|
59
|
+
when :user
|
|
60
|
+
u32_b(Constructors::INPUT_PEER_USER) + u64_b(peer[:id]) + u64_b(peer[:access_hash] || 0)
|
|
61
|
+
when :chat
|
|
62
|
+
u32_b(Constructors::INPUT_PEER_CHAT) + u64_b(peer[:id])
|
|
63
|
+
when :channel
|
|
64
|
+
u32_b(Constructors::INPUT_PEER_CHANNEL) + u64_b(peer[:id]) + u64_b(peer[:access_hash] || 0)
|
|
65
|
+
else
|
|
66
|
+
raise ArgumentError, "Unknown peer type: #{peer[:type].inspect}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def serialize_input_user(user)
|
|
71
|
+
raise ArgumentError, 'peer_user scope requires user:' if user.nil?
|
|
72
|
+
|
|
73
|
+
if user[:type] == :self
|
|
74
|
+
u32_b(INPUT_USER_SELF)
|
|
75
|
+
else
|
|
76
|
+
u32_b(INPUT_USER) + u64_b(user[:id]) + u64_b(user[:access_hash] || 0)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
# channels.updateUsername — assign a public username to a channel/supergroup.
|
|
6
|
+
# Returns Bool.
|
|
7
|
+
class ChannelsUpdateUsername
|
|
8
|
+
include Binary
|
|
9
|
+
|
|
10
|
+
CONSTRUCTOR = 0x3514b3de
|
|
11
|
+
|
|
12
|
+
def initialize(channel:, username:)
|
|
13
|
+
@channel = channel
|
|
14
|
+
@username = username
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def serialize
|
|
18
|
+
result = u32_b(CONSTRUCTOR)
|
|
19
|
+
result += u32_b(Constructors::INPUT_CHANNEL) + u64_b(@channel[:id]) + u64_b(@channel[:access_hash])
|
|
20
|
+
result += serialize_tl_string(@username)
|
|
21
|
+
result
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def serialize_tl_string(str)
|
|
27
|
+
bytes = str.encode('UTF-8').bytes
|
|
28
|
+
length = bytes.length
|
|
29
|
+
if length <= 253
|
|
30
|
+
[length] + bytes + padding(length + 1)
|
|
31
|
+
else
|
|
32
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def padding(current_length)
|
|
37
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
38
|
+
[0] * pad_length
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -68,7 +68,7 @@ module MTProto
|
|
|
68
68
|
[contacts, offset]
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
# User parsing mirrors TL::Dialogs.parse_user (user#
|
|
71
|
+
# User parsing mirrors TL::Dialogs.parse_user (user#31774388). Kept private here
|
|
72
72
|
# so this class can be used without instantiating Dialogs.
|
|
73
73
|
def parse_users_vector(data, offset)
|
|
74
74
|
offset += 4 # vector tag
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class CreateBot
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xe5b17f2b
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
|
|
12
|
+
# manager: { id:, access_hash: } or { type: :self }
|
|
13
|
+
def initialize(name:, username:, manager:, via_deeplink: false)
|
|
14
|
+
@name = name
|
|
15
|
+
@username = username
|
|
16
|
+
@manager = manager
|
|
17
|
+
@via_deeplink = via_deeplink
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize
|
|
21
|
+
flags = 0
|
|
22
|
+
flags |= (1 << 0) if @via_deeplink
|
|
23
|
+
|
|
24
|
+
result = u32_b(CONSTRUCTOR)
|
|
25
|
+
result += u32_b(flags)
|
|
26
|
+
result += serialize_tl_string(@name)
|
|
27
|
+
result += serialize_tl_string(@username)
|
|
28
|
+
result += if @manager[:type] == :self
|
|
29
|
+
u32_b(INPUT_USER_SELF)
|
|
30
|
+
else
|
|
31
|
+
u32_b(INPUT_USER) + u64_b(@manager[:id]) + u64_b(@manager[:access_hash] || 0)
|
|
32
|
+
end
|
|
33
|
+
result
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def serialize_tl_string(str)
|
|
39
|
+
bytes = str.encode('UTF-8').bytes
|
|
40
|
+
length = bytes.length
|
|
41
|
+
if length <= 253
|
|
42
|
+
[length] + bytes + padding(length + 1)
|
|
43
|
+
else
|
|
44
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def padding(current_length)
|
|
49
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
50
|
+
[0] * pad_length
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -51,6 +51,16 @@ module MTProto
|
|
|
51
51
|
new(dialogs: dialogs, chats: chats, users: users, count: count, message_dates: message_dates)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
# Parse a chats:Vector<Chat> / users:Vector<User> at an arbitrary offset.
|
|
55
|
+
# Reused by UpdatesDifference — the same vectors appear in updates.difference.
|
|
56
|
+
def self.chats_at(data, offset)
|
|
57
|
+
parse_chats_vector(data, offset)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.users_at(data, offset)
|
|
61
|
+
parse_users_vector(data, offset)
|
|
62
|
+
end
|
|
63
|
+
|
|
54
64
|
class << self
|
|
55
65
|
private
|
|
56
66
|
|
|
@@ -94,6 +104,7 @@ module MTProto
|
|
|
94
104
|
|
|
95
105
|
offset += 4 # unread_mentions_count
|
|
96
106
|
offset += 4 # unread_reactions_count
|
|
107
|
+
offset += 4 # unread_poll_votes_count (added in layer 227)
|
|
97
108
|
|
|
98
109
|
offset = schema.skip(data, offset) # notify_settings (PeerNotifySettings)
|
|
99
110
|
|
|
@@ -128,12 +139,12 @@ module MTProto
|
|
|
128
139
|
|
|
129
140
|
# --- Messages vector ---
|
|
130
141
|
|
|
131
|
-
# message#
|
|
142
|
+
# message#7600b9d3 flags:# flags2:#
|
|
132
143
|
# id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int
|
|
133
|
-
# peer_id:Peer saved_peer_id:flags.28?Peer
|
|
144
|
+
# from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer
|
|
134
145
|
# fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long
|
|
135
|
-
# via_business_bot_id:flags2.0?long
|
|
136
|
-
# date:int ...
|
|
146
|
+
# via_business_bot_id:flags2.0?long guestchat_via_from:flags2.19?Peer
|
|
147
|
+
# reply_to:flags.3?MessageReplyHeader date:int ...
|
|
137
148
|
#
|
|
138
149
|
# messageService#2b085862 flags:#
|
|
139
150
|
# id:int from_id:flags.8?Peer peer_id:Peer
|
|
@@ -179,11 +190,13 @@ module MTProto
|
|
|
179
190
|
|
|
180
191
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 8) # from_id (Peer)
|
|
181
192
|
offset += 4 if flags.anybits?(1 << 29) # from_boosts_applied
|
|
193
|
+
_, offset = read_tl_string(data, offset) if flags2.anybits?(1 << 12) # from_rank (layer 227)
|
|
182
194
|
offset = schema.skip(data, offset) # peer_id (Peer, always present)
|
|
183
195
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 28) # saved_peer_id
|
|
184
196
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 2) # fwd_from
|
|
185
197
|
offset += 8 if flags.anybits?(1 << 11) # via_bot_id
|
|
186
198
|
offset += 8 if flags2.anybits?(1 << 0) # via_business_bot_id
|
|
199
|
+
offset = schema.skip(data, offset) if flags2.anybits?(1 << 19) # guestchat_via_from (layer 227, Peer)
|
|
187
200
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 3) # reply_to
|
|
188
201
|
|
|
189
202
|
date = data[offset, 4].unpack1('L<')
|
|
@@ -268,7 +281,7 @@ module MTProto
|
|
|
268
281
|
[Chat.new(id: id, title: title, type: :chat), offset]
|
|
269
282
|
end
|
|
270
283
|
|
|
271
|
-
# channel#
|
|
284
|
+
# channel#1c32b11c flags:# flags2:#
|
|
272
285
|
# id:long access_hash:flags.13?long title:string
|
|
273
286
|
# username:flags.6?string photo:ChatPhoto date:int
|
|
274
287
|
# restriction_reason:flags.9?Vector<RestrictionReason>
|
|
@@ -310,7 +323,7 @@ module MTProto
|
|
|
310
323
|
if flags2.anybits?(1 << 0) # usernames Vector<Username>
|
|
311
324
|
offset = schema.skip_vector(data, offset) { |d, o| schema.skip(d, o) }
|
|
312
325
|
end
|
|
313
|
-
offset
|
|
326
|
+
offset = schema.skip(data, offset) if flags2.anybits?(1 << 4) # stories_max_id (layer 227: RecentStory)
|
|
314
327
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 7) # color (PeerColor)
|
|
315
328
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 8) # profile_color (PeerColor)
|
|
316
329
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 9) # emoji_status
|
|
@@ -363,7 +376,7 @@ module MTProto
|
|
|
363
376
|
|
|
364
377
|
USER_EMPTY = 0xd3bc4b7a
|
|
365
378
|
|
|
366
|
-
# user#
|
|
379
|
+
# user#31774388 flags:# flags2:#
|
|
367
380
|
# id:long access_hash:flags.0?long
|
|
368
381
|
# first_name:flags.1?string last_name:flags.2?string
|
|
369
382
|
# username:flags.3?string phone:flags.4?string
|
|
@@ -408,7 +421,9 @@ module MTProto
|
|
|
408
421
|
last_name = nil
|
|
409
422
|
last_name, offset = read_tl_string(data, offset) if flags.anybits?(1 << 2)
|
|
410
423
|
|
|
411
|
-
|
|
424
|
+
username = nil
|
|
425
|
+
username, offset = read_tl_string(data, offset) if flags.anybits?(1 << 3) # username
|
|
426
|
+
|
|
412
427
|
offset = skip_tl_string(data, offset) if flags.anybits?(1 << 4) # phone
|
|
413
428
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 5) # photo
|
|
414
429
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 6) # status
|
|
@@ -420,14 +435,14 @@ module MTProto
|
|
|
420
435
|
offset = skip_tl_string(data, offset) if flags.anybits?(1 << 22) # lang_code
|
|
421
436
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 30) # emoji_status
|
|
422
437
|
offset = schema.skip_vector(data, offset) { |d, o| schema.skip(d, o) } if flags2.anybits?(1 << 0) # usernames
|
|
423
|
-
offset
|
|
438
|
+
offset = schema.skip(data, offset) if flags2.anybits?(1 << 5) # stories_max_id (layer 227: RecentStory)
|
|
424
439
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 8) # color
|
|
425
440
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 9) # profile_color
|
|
426
441
|
offset += 4 if flags2.anybits?(1 << 12) # bot_active_users
|
|
427
442
|
offset += 8 if flags2.anybits?(1 << 14) # bot_verification_icon
|
|
428
443
|
offset += 8 if flags2.anybits?(1 << 15) # send_paid_messages_stars
|
|
429
444
|
|
|
430
|
-
[{ id: id, first_name: first_name, last_name: last_name, access_hash: access_hash }, offset]
|
|
445
|
+
[{ id: id, first_name: first_name, last_name: last_name, username: username, access_hash: access_hash }, offset]
|
|
431
446
|
end
|
|
432
447
|
|
|
433
448
|
# --- TL string ---
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class EditAccessSettings
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x31813cd8
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
|
|
12
|
+
# bot / add_users entries: { id:, access_hash: } or { type: :self }
|
|
13
|
+
def initialize(bot:, restricted: false, add_users: [])
|
|
14
|
+
@bot = bot
|
|
15
|
+
@restricted = restricted
|
|
16
|
+
@add_users = add_users
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def serialize
|
|
20
|
+
flags = 0
|
|
21
|
+
flags |= (1 << 0) if @restricted
|
|
22
|
+
flags |= (1 << 1) unless @add_users.empty?
|
|
23
|
+
|
|
24
|
+
result = u32_b(CONSTRUCTOR)
|
|
25
|
+
result += u32_b(flags)
|
|
26
|
+
result += serialize_input_user(@bot)
|
|
27
|
+
unless @add_users.empty?
|
|
28
|
+
result += u32_b(Constructors::VECTOR)
|
|
29
|
+
result += u32_b(@add_users.size)
|
|
30
|
+
@add_users.each { |u| result += serialize_input_user(u) }
|
|
31
|
+
end
|
|
32
|
+
result
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def serialize_input_user(user)
|
|
38
|
+
if user[:type] == :self
|
|
39
|
+
u32_b(INPUT_USER_SELF)
|
|
40
|
+
else
|
|
41
|
+
u32_b(INPUT_USER) + u64_b(user[:id]) + u64_b(user[:access_hash] || 0)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ExportAuthorization
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
def initialize(dc_id:)
|
|
9
|
+
@dc_id = dc_id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def serialize
|
|
13
|
+
u32_b(Constructors::AUTH_EXPORT_AUTHORIZATION) + u32_b(@dc_id)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ExportBotToken
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xbd0d99eb
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
BOOL_TRUE = 0x997275b5
|
|
12
|
+
BOOL_FALSE = 0xbc799737
|
|
13
|
+
|
|
14
|
+
# bot: { id:, access_hash: } or { type: :self }
|
|
15
|
+
def initialize(bot:, revoke: false)
|
|
16
|
+
@bot = bot
|
|
17
|
+
@revoke = revoke
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize
|
|
21
|
+
result = u32_b(CONSTRUCTOR)
|
|
22
|
+
result += if @bot[:type] == :self
|
|
23
|
+
u32_b(INPUT_USER_SELF)
|
|
24
|
+
else
|
|
25
|
+
u32_b(INPUT_USER) + u64_b(@bot[:id]) + u64_b(@bot[:access_hash] || 0)
|
|
26
|
+
end
|
|
27
|
+
result += u32_b(@revoke ? BOOL_TRUE : BOOL_FALSE)
|
|
28
|
+
result
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ExportedAuthorization
|
|
6
|
+
attr_reader :id, :bytes
|
|
7
|
+
|
|
8
|
+
def initialize(id:, bytes:)
|
|
9
|
+
@id = id
|
|
10
|
+
@bytes = bytes
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.deserialize(data)
|
|
14
|
+
constructor = data[0, 4].unpack1('L<')
|
|
15
|
+
raise UnexpectedConstructorError, constructor unless constructor == Constructors::AUTH_EXPORTED_AUTHORIZATION
|
|
16
|
+
|
|
17
|
+
id = data[4, 8].unpack1('Q<')
|
|
18
|
+
new(id: id, bytes: read_tl_bytes(data, 12))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.read_tl_bytes(data, offset)
|
|
22
|
+
first = data.getbyte(offset)
|
|
23
|
+
if first == 254
|
|
24
|
+
len = data.getbyte(offset + 1) | (data.getbyte(offset + 2) << 8) | (data.getbyte(offset + 3) << 16)
|
|
25
|
+
data[offset + 4, len]
|
|
26
|
+
else
|
|
27
|
+
data[offset + 1, first]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ExportedBotToken
|
|
6
|
+
CONSTRUCTOR = 0x3c60b621
|
|
7
|
+
|
|
8
|
+
attr_reader :token
|
|
9
|
+
|
|
10
|
+
def initialize(token:)
|
|
11
|
+
@token = token
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.deserialize(bytes)
|
|
15
|
+
body = bytes[4..]
|
|
16
|
+
first = body.getbyte(0)
|
|
17
|
+
token = if first == 254
|
|
18
|
+
len = body.getbyte(1) | (body.getbyte(2) << 8) | (body.getbyte(3) << 16)
|
|
19
|
+
body[4, len]
|
|
20
|
+
else
|
|
21
|
+
body[1, first]
|
|
22
|
+
end
|
|
23
|
+
new(token: token.force_encoding('UTF-8'))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -7,18 +7,27 @@ module MTProto
|
|
|
7
7
|
class ForwardMessages
|
|
8
8
|
include Binary
|
|
9
9
|
|
|
10
|
-
CONSTRUCTOR =
|
|
10
|
+
CONSTRUCTOR = 0x13704a7c
|
|
11
11
|
|
|
12
|
-
def initialize(from_peer:, to_peer:, ids:, random_ids: nil
|
|
12
|
+
def initialize(from_peer:, to_peer:, ids:, random_ids: nil, drop_author: false, drop_media_captions: false,
|
|
13
|
+
silent: false)
|
|
13
14
|
@from_peer = from_peer
|
|
14
15
|
@to_peer = to_peer
|
|
15
16
|
@ids = ids
|
|
16
17
|
@random_ids = random_ids || Array.new(ids.length) { SecureRandom.random_number(2**63) }
|
|
18
|
+
@drop_author = drop_author
|
|
19
|
+
@drop_media_captions = drop_media_captions
|
|
20
|
+
@silent = silent
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def serialize
|
|
24
|
+
flags = 0
|
|
25
|
+
flags |= (1 << 5) if @silent
|
|
26
|
+
flags |= (1 << 11) if @drop_author
|
|
27
|
+
flags |= (1 << 12) if @drop_media_captions
|
|
28
|
+
|
|
20
29
|
result = u32_b(CONSTRUCTOR)
|
|
21
|
-
result += u32_b(
|
|
30
|
+
result += u32_b(flags)
|
|
22
31
|
result += serialize_input_peer(@from_peer)
|
|
23
32
|
result += u32_b(Constructors::VECTOR) + u32_b(@ids.length)
|
|
24
33
|
@ids.each { |id| result += u32_b(id) }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class GetAccessSettings
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x213853a3
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
|
|
12
|
+
# bot: { id:, access_hash: } or { type: :self }
|
|
13
|
+
def initialize(bot:)
|
|
14
|
+
@bot = bot
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def serialize
|
|
18
|
+
result = u32_b(CONSTRUCTOR)
|
|
19
|
+
result += if @bot[:type] == :self
|
|
20
|
+
u32_b(INPUT_USER_SELF)
|
|
21
|
+
else
|
|
22
|
+
u32_b(INPUT_USER) + u64_b(@bot[:id]) + u64_b(@bot[:access_hash] || 0)
|
|
23
|
+
end
|
|
24
|
+
result
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
# messages.getBotCallbackAnswer — the press itself: the user client invokes
|
|
6
|
+
# this with the button's callback data; the server delivers an
|
|
7
|
+
# updateBotCallbackQuery to the bot and blocks until the bot answers (or
|
|
8
|
+
# times out), then returns messages.botCallbackAnswer.
|
|
9
|
+
class GetBotCallbackAnswer
|
|
10
|
+
include Binary
|
|
11
|
+
|
|
12
|
+
CONSTRUCTOR = 0x9342ca07
|
|
13
|
+
|
|
14
|
+
def initialize(peer:, msg_id:, data: nil, game: false)
|
|
15
|
+
@peer = peer
|
|
16
|
+
@msg_id = msg_id
|
|
17
|
+
@data = data
|
|
18
|
+
@game = game
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def serialize
|
|
22
|
+
flags = 0
|
|
23
|
+
flags |= (1 << 0) if @data
|
|
24
|
+
flags |= (1 << 1) if @game
|
|
25
|
+
|
|
26
|
+
result = u32_b(CONSTRUCTOR)
|
|
27
|
+
result += u32_b(flags)
|
|
28
|
+
result += serialize_input_peer
|
|
29
|
+
result += u32_b(@msg_id)
|
|
30
|
+
result += serialize_tl_bytes(@data) if @data
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def serialize_input_peer
|
|
37
|
+
case @peer[:type]
|
|
38
|
+
when :self
|
|
39
|
+
u32_b(Constructors::INPUT_PEER_SELF)
|
|
40
|
+
when :user
|
|
41
|
+
u32_b(Constructors::INPUT_PEER_USER) + u64_b(@peer[:id]) + u64_b(@peer[:access_hash] || 0)
|
|
42
|
+
when :chat
|
|
43
|
+
u32_b(Constructors::INPUT_PEER_CHAT) + u64_b(@peer[:id])
|
|
44
|
+
when :channel
|
|
45
|
+
u32_b(Constructors::INPUT_PEER_CHANNEL) + u64_b(@peer[:id]) + u64_b(@peer[:access_hash] || 0)
|
|
46
|
+
else
|
|
47
|
+
raise "Unknown peer type: #{@peer[:type]}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def serialize_tl_bytes(bytes_str)
|
|
52
|
+
bytes = bytes_str.to_s.b.bytes
|
|
53
|
+
length = bytes.length
|
|
54
|
+
if length <= 253
|
|
55
|
+
[length] + bytes + padding(length + 1)
|
|
56
|
+
else
|
|
57
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def padding(current_length)
|
|
62
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
63
|
+
[0] * pad_length
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|