mtproto 0.0.15 → 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.rb +1 -1
- data/lib/mtproto/file_downloader.rb +122 -0
- data/lib/mtproto/tl/constructor_names.rb +314 -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/dialogs.rb +15 -10
- data/lib/mtproto/tl/objects/export_authorization.rb +17 -0
- data/lib/mtproto/tl/objects/exported_authorization.rb +32 -0
- data/lib/mtproto/tl/objects/forward_messages.rb +5 -2
- 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/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/reply_inline_markup.rb +30 -0
- data/lib/mtproto/tl/objects/reset_bot_commands.rb +45 -0
- data/lib/mtproto/tl/objects/send_media.rb +76 -4
- data/lib/mtproto/tl/objects/send_message.rb +4 -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 +6 -3
- data/lib/mtproto/tl/objects/set_bot_guest_chat_result.rb +84 -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 +16 -119
- 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 +25 -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
|
|
@@ -104,6 +104,7 @@ module MTProto
|
|
|
104
104
|
|
|
105
105
|
offset += 4 # unread_mentions_count
|
|
106
106
|
offset += 4 # unread_reactions_count
|
|
107
|
+
offset += 4 # unread_poll_votes_count (added in layer 227)
|
|
107
108
|
|
|
108
109
|
offset = schema.skip(data, offset) # notify_settings (PeerNotifySettings)
|
|
109
110
|
|
|
@@ -138,12 +139,12 @@ module MTProto
|
|
|
138
139
|
|
|
139
140
|
# --- Messages vector ---
|
|
140
141
|
|
|
141
|
-
# message#
|
|
142
|
+
# message#7600b9d3 flags:# flags2:#
|
|
142
143
|
# id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int
|
|
143
|
-
# peer_id:Peer saved_peer_id:flags.28?Peer
|
|
144
|
+
# from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer
|
|
144
145
|
# fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long
|
|
145
|
-
# via_business_bot_id:flags2.0?long
|
|
146
|
-
# date:int ...
|
|
146
|
+
# via_business_bot_id:flags2.0?long guestchat_via_from:flags2.19?Peer
|
|
147
|
+
# reply_to:flags.3?MessageReplyHeader date:int ...
|
|
147
148
|
#
|
|
148
149
|
# messageService#2b085862 flags:#
|
|
149
150
|
# id:int from_id:flags.8?Peer peer_id:Peer
|
|
@@ -189,11 +190,13 @@ module MTProto
|
|
|
189
190
|
|
|
190
191
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 8) # from_id (Peer)
|
|
191
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)
|
|
192
194
|
offset = schema.skip(data, offset) # peer_id (Peer, always present)
|
|
193
195
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 28) # saved_peer_id
|
|
194
196
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 2) # fwd_from
|
|
195
197
|
offset += 8 if flags.anybits?(1 << 11) # via_bot_id
|
|
196
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)
|
|
197
200
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 3) # reply_to
|
|
198
201
|
|
|
199
202
|
date = data[offset, 4].unpack1('L<')
|
|
@@ -278,7 +281,7 @@ module MTProto
|
|
|
278
281
|
[Chat.new(id: id, title: title, type: :chat), offset]
|
|
279
282
|
end
|
|
280
283
|
|
|
281
|
-
# channel#
|
|
284
|
+
# channel#1c32b11c flags:# flags2:#
|
|
282
285
|
# id:long access_hash:flags.13?long title:string
|
|
283
286
|
# username:flags.6?string photo:ChatPhoto date:int
|
|
284
287
|
# restriction_reason:flags.9?Vector<RestrictionReason>
|
|
@@ -320,7 +323,7 @@ module MTProto
|
|
|
320
323
|
if flags2.anybits?(1 << 0) # usernames Vector<Username>
|
|
321
324
|
offset = schema.skip_vector(data, offset) { |d, o| schema.skip(d, o) }
|
|
322
325
|
end
|
|
323
|
-
offset
|
|
326
|
+
offset = schema.skip(data, offset) if flags2.anybits?(1 << 4) # stories_max_id (layer 227: RecentStory)
|
|
324
327
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 7) # color (PeerColor)
|
|
325
328
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 8) # profile_color (PeerColor)
|
|
326
329
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 9) # emoji_status
|
|
@@ -373,7 +376,7 @@ module MTProto
|
|
|
373
376
|
|
|
374
377
|
USER_EMPTY = 0xd3bc4b7a
|
|
375
378
|
|
|
376
|
-
# user#
|
|
379
|
+
# user#31774388 flags:# flags2:#
|
|
377
380
|
# id:long access_hash:flags.0?long
|
|
378
381
|
# first_name:flags.1?string last_name:flags.2?string
|
|
379
382
|
# username:flags.3?string phone:flags.4?string
|
|
@@ -418,7 +421,9 @@ module MTProto
|
|
|
418
421
|
last_name = nil
|
|
419
422
|
last_name, offset = read_tl_string(data, offset) if flags.anybits?(1 << 2)
|
|
420
423
|
|
|
421
|
-
|
|
424
|
+
username = nil
|
|
425
|
+
username, offset = read_tl_string(data, offset) if flags.anybits?(1 << 3) # username
|
|
426
|
+
|
|
422
427
|
offset = skip_tl_string(data, offset) if flags.anybits?(1 << 4) # phone
|
|
423
428
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 5) # photo
|
|
424
429
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 6) # status
|
|
@@ -430,14 +435,14 @@ module MTProto
|
|
|
430
435
|
offset = skip_tl_string(data, offset) if flags.anybits?(1 << 22) # lang_code
|
|
431
436
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 30) # emoji_status
|
|
432
437
|
offset = schema.skip_vector(data, offset) { |d, o| schema.skip(d, o) } if flags2.anybits?(1 << 0) # usernames
|
|
433
|
-
offset
|
|
438
|
+
offset = schema.skip(data, offset) if flags2.anybits?(1 << 5) # stories_max_id (layer 227: RecentStory)
|
|
434
439
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 8) # color
|
|
435
440
|
offset = schema.skip(data, offset) if flags2.anybits?(1 << 9) # profile_color
|
|
436
441
|
offset += 4 if flags2.anybits?(1 << 12) # bot_active_users
|
|
437
442
|
offset += 8 if flags2.anybits?(1 << 14) # bot_verification_icon
|
|
438
443
|
offset += 8 if flags2.anybits?(1 << 15) # send_paid_messages_stars
|
|
439
444
|
|
|
440
|
-
[{ 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]
|
|
441
446
|
end
|
|
442
447
|
|
|
443
448
|
# --- TL string ---
|
|
@@ -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 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
|
|
@@ -7,19 +7,22 @@ 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, drop_author: false, drop_media_captions: false
|
|
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) }
|
|
17
18
|
@drop_author = drop_author
|
|
18
19
|
@drop_media_captions = drop_media_captions
|
|
20
|
+
@silent = silent
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def serialize
|
|
22
24
|
flags = 0
|
|
25
|
+
flags |= (1 << 5) if @silent
|
|
23
26
|
flags |= (1 << 11) if @drop_author
|
|
24
27
|
flags |= (1 << 12) if @drop_media_captions
|
|
25
28
|
|
|
@@ -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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'bot_command_scope'
|
|
4
|
+
|
|
5
|
+
module MTProto
|
|
6
|
+
module TL
|
|
7
|
+
# bots.getBotCommands — fetch the bot's commands for a given scope/language.
|
|
8
|
+
# Returns Vector<BotCommand>. Result parsing belongs to a later layer; this
|
|
9
|
+
# object only builds the request.
|
|
10
|
+
class GetBotCommands
|
|
11
|
+
include Binary
|
|
12
|
+
|
|
13
|
+
CONSTRUCTOR = 0xe34c0dd6
|
|
14
|
+
|
|
15
|
+
# scope: BotCommandScope hash (see BotCommandScope); defaults to default scope.
|
|
16
|
+
def initialize(scope: { type: :default }, lang_code: '')
|
|
17
|
+
@scope = scope
|
|
18
|
+
@lang_code = lang_code
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def serialize
|
|
22
|
+
result = u32_b(CONSTRUCTOR)
|
|
23
|
+
result += BotCommandScope.serialize(@scope)
|
|
24
|
+
result += serialize_tl_string(@lang_code)
|
|
25
|
+
result
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def serialize_tl_string(str)
|
|
31
|
+
bytes = str.to_s.encode('UTF-8').bytes
|
|
32
|
+
length = bytes.length
|
|
33
|
+
if length <= 253
|
|
34
|
+
[length] + bytes + padding(length + 1)
|
|
35
|
+
else
|
|
36
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def padding(current_length)
|
|
41
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
42
|
+
[0] * pad_length
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -7,10 +7,18 @@ module MTProto
|
|
|
7
7
|
|
|
8
8
|
CONSTRUCTOR = 0xbe5335be
|
|
9
9
|
INPUT_PHOTO_FILE_LOCATION = 0x40181ffe
|
|
10
|
+
INPUT_DOCUMENT_FILE_LOCATION = 0xbad07584
|
|
11
|
+
|
|
12
|
+
LOCATION_CONSTRUCTORS = {
|
|
13
|
+
photo: INPUT_PHOTO_FILE_LOCATION,
|
|
14
|
+
document: INPUT_DOCUMENT_FILE_LOCATION
|
|
15
|
+
}.freeze
|
|
10
16
|
|
|
11
17
|
# location: { id:, access_hash:, file_reference: (binary String), thumb_size: (String) }
|
|
12
|
-
|
|
18
|
+
# type: :photo for photos, :document for documents/voice/video/audio.
|
|
19
|
+
def initialize(location:, type: :photo, offset: 0, limit: 1024 * 1024)
|
|
13
20
|
@location = location
|
|
21
|
+
@type = type
|
|
14
22
|
@offset = offset
|
|
15
23
|
@limit = limit
|
|
16
24
|
end
|
|
@@ -27,7 +35,7 @@ module MTProto
|
|
|
27
35
|
private
|
|
28
36
|
|
|
29
37
|
def serialize_location
|
|
30
|
-
u32_b(
|
|
38
|
+
u32_b(LOCATION_CONSTRUCTORS.fetch(@type)) +
|
|
31
39
|
u64_b(@location[:id]) +
|
|
32
40
|
u64_b(@location[:access_hash]) +
|
|
33
41
|
serialize_tl_bytes(@location[:file_reference]) +
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class ImportAuthorization
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
def initialize(id:, bytes:)
|
|
9
|
+
@id = id
|
|
10
|
+
@bytes = bytes
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def serialize
|
|
14
|
+
u32_b(Constructors::AUTH_IMPORT_AUTHORIZATION) +
|
|
15
|
+
u64_b(@id) +
|
|
16
|
+
serialize_tl_bytes(@bytes)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def serialize_tl_bytes(value)
|
|
22
|
+
bytes = value.to_s.b.bytes
|
|
23
|
+
length = bytes.length
|
|
24
|
+
|
|
25
|
+
if length <= 253
|
|
26
|
+
[length] + bytes + padding(length + 1)
|
|
27
|
+
else
|
|
28
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def padding(current_length)
|
|
33
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
34
|
+
[0] * pad_length
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class KeyboardButtonCallback
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0xe62bc960
|
|
9
|
+
|
|
10
|
+
# data: raw callback payload bytes echoed back to the bot on press.
|
|
11
|
+
def initialize(text:, data:, requires_password: false)
|
|
12
|
+
@text = text
|
|
13
|
+
@data = data
|
|
14
|
+
@requires_password = requires_password
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def serialize
|
|
18
|
+
flags = 0
|
|
19
|
+
flags |= (1 << 0) if @requires_password
|
|
20
|
+
|
|
21
|
+
result = u32_b(CONSTRUCTOR)
|
|
22
|
+
result += u32_b(flags)
|
|
23
|
+
result += serialize_tl_string(@text)
|
|
24
|
+
result += serialize_tl_bytes(@data)
|
|
25
|
+
result
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def serialize_tl_string(str)
|
|
31
|
+
serialize_tl_bytes(str.to_s.encode('UTF-8').b)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def serialize_tl_bytes(bytes_str)
|
|
35
|
+
bytes = bytes_str.to_s.b.bytes
|
|
36
|
+
length = bytes.length
|
|
37
|
+
if length <= 253
|
|
38
|
+
[length] + bytes + padding(length + 1)
|
|
39
|
+
else
|
|
40
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def padding(current_length)
|
|
45
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
46
|
+
[0] * pad_length
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|