mtproto 0.0.13 → 0.0.15
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/FUTURE.md +9 -0
- data/docs/test_architecture_level1.md +237 -0
- data/lib/mtproto/auth_key_generator.rb +5 -5
- data/lib/mtproto/client/api/get_contacts.rb +14 -0
- data/lib/mtproto/client/api/send_message.rb +15 -0
- data/lib/mtproto/client/api.rb +2 -0
- data/lib/mtproto/client/rpc/response.rb +1 -1
- data/lib/mtproto/client/rpc.rb +35 -2
- data/lib/mtproto/client.rb +81 -18
- data/lib/mtproto/tl/constructor_names.rb +10 -0
- data/lib/mtproto/tl/constructors.rb +26 -0
- data/lib/mtproto/tl/object.rb +1 -1
- data/lib/mtproto/tl/objects/account_password.rb +1 -1
- data/lib/mtproto/tl/objects/authorization.rb +1 -1
- data/lib/mtproto/tl/objects/channels_create_channel.rb +48 -0
- data/lib/mtproto/tl/objects/channels_delete_messages.rb +32 -0
- data/lib/mtproto/tl/objects/channels_delete_participant_history.rb +34 -0
- data/lib/mtproto/tl/objects/channels_edit_banned.rb +54 -0
- data/lib/mtproto/tl/objects/channels_get_messages.rb +33 -0
- data/lib/mtproto/tl/objects/channels_get_participant.rb +36 -0
- data/lib/mtproto/tl/objects/channels_join_channel.rb +22 -0
- data/lib/mtproto/tl/objects/channels_leave_channel.rb +22 -0
- data/lib/mtproto/tl/objects/channels_report_spam.rb +37 -0
- data/lib/mtproto/tl/objects/check_password.rb +1 -1
- data/lib/mtproto/tl/objects/client_dh_inner_data.rb +1 -1
- data/lib/mtproto/tl/objects/contacts.rb +156 -0
- data/lib/mtproto/tl/objects/create_bot.rb +54 -0
- data/lib/mtproto/tl/objects/delete_messages.rb +25 -0
- data/lib/mtproto/tl/objects/dh_gen_response.rb +1 -1
- data/lib/mtproto/tl/objects/dialogs.rb +18 -4
- data/lib/mtproto/tl/objects/edit_access_settings.rb +46 -0
- data/lib/mtproto/tl/objects/edit_message.rb +58 -0
- data/lib/mtproto/tl/objects/export_bot_token.rb +32 -0
- data/lib/mtproto/tl/objects/export_login_token.rb +1 -1
- data/lib/mtproto/tl/objects/exported_bot_token.rb +27 -0
- data/lib/mtproto/tl/objects/forward_messages.rb +55 -0
- data/lib/mtproto/tl/objects/get_access_settings.rb +28 -0
- data/lib/mtproto/tl/objects/get_channel_difference.rb +41 -0
- data/lib/mtproto/tl/objects/get_config.rb +1 -1
- data/lib/mtproto/tl/objects/get_contacts.rb +17 -0
- data/lib/mtproto/tl/objects/get_dialogs.rb +1 -1
- data/lib/mtproto/tl/objects/get_difference.rb +1 -1
- data/lib/mtproto/tl/objects/get_file.rb +54 -0
- data/lib/mtproto/tl/objects/get_full_channel.rb +29 -0
- data/lib/mtproto/tl/objects/get_full_user.rb +28 -0
- data/lib/mtproto/tl/objects/get_history.rb +1 -1
- data/lib/mtproto/tl/objects/get_messages_reactions.rb +39 -0
- data/lib/mtproto/tl/objects/get_password.rb +1 -1
- data/lib/mtproto/tl/objects/get_state.rb +1 -1
- data/lib/mtproto/tl/objects/get_users.rb +1 -1
- data/lib/mtproto/tl/objects/help_config.rb +1 -1
- data/lib/mtproto/tl/objects/import_bot_authorization.rb +44 -0
- data/lib/mtproto/tl/objects/import_login_token.rb +1 -1
- data/lib/mtproto/tl/objects/init_connection.rb +2 -2
- data/lib/mtproto/tl/objects/input_keyboard_button_request_peer.rb +54 -0
- data/lib/mtproto/tl/objects/invite_to_channel.rb +35 -0
- data/lib/mtproto/tl/objects/invoke_with_layer.rb +2 -2
- data/lib/mtproto/tl/objects/login_token.rb +2 -2
- data/lib/mtproto/tl/objects/messages.rb +1 -1
- data/lib/mtproto/tl/objects/messages_get_messages.rb +26 -0
- data/lib/mtproto/tl/objects/pq_inner_data.rb +1 -1
- data/lib/mtproto/tl/objects/raw_response.rb +29 -0
- data/lib/mtproto/tl/objects/reply_keyboard_markup.rb +35 -0
- data/lib/mtproto/tl/objects/req_dh_params.rb +1 -1
- data/lib/mtproto/tl/objects/req_pq_multi.rb +1 -1
- data/lib/mtproto/tl/objects/request_peer_type_create_bot.rb +47 -0
- data/lib/mtproto/tl/objects/res_pq.rb +1 -1
- data/lib/mtproto/tl/objects/resolve_username.rb +40 -0
- data/lib/mtproto/tl/objects/save_file_part.rb +40 -0
- data/lib/mtproto/tl/objects/send_bot_requested_peer.rb +51 -0
- data/lib/mtproto/tl/objects/send_code.rb +1 -1
- data/lib/mtproto/tl/objects/send_media.rb +96 -0
- data/lib/mtproto/tl/objects/send_message.rb +73 -0
- data/lib/mtproto/tl/objects/send_reaction.rb +68 -0
- data/lib/mtproto/tl/objects/sent_code.rb +1 -1
- data/lib/mtproto/tl/objects/server_dh_inner_data.rb +1 -1
- data/lib/mtproto/tl/objects/server_dh_params.rb +1 -1
- data/lib/mtproto/tl/objects/set_bot_commands.rb +50 -0
- data/lib/mtproto/tl/objects/set_bot_info.rb +64 -0
- data/lib/mtproto/tl/objects/set_client_dh_params.rb +1 -1
- data/lib/mtproto/tl/objects/sign_in.rb +1 -1
- data/lib/mtproto/tl/objects/update.rb +1 -1
- data/lib/mtproto/tl/objects/update_short.rb +2 -2
- data/lib/mtproto/tl/objects/update_short_message.rb +1 -1
- data/lib/mtproto/tl/objects/update_short_sent_message.rb +36 -0
- data/lib/mtproto/tl/objects/update_username.rb +39 -0
- data/lib/mtproto/tl/objects/updates_difference.rb +93 -14
- data/lib/mtproto/tl/objects/updates_state.rb +1 -1
- data/lib/mtproto/tl/objects/upload_profile_photo.rb +65 -0
- data/lib/mtproto/tl/objects/users.rb +1 -1
- data/lib/mtproto/version.rb +1 -1
- metadata +49 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class SetBotCommands
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x0517165a
|
|
9
|
+
BOT_COMMAND_SCOPE_DEFAULT = 0x2f6cb2ab
|
|
10
|
+
BOT_COMMAND = 0xc27ac8c7
|
|
11
|
+
|
|
12
|
+
# commands: array of { command:, description: }
|
|
13
|
+
def initialize(commands:, lang_code: '')
|
|
14
|
+
@commands = commands
|
|
15
|
+
@lang_code = lang_code
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def serialize
|
|
19
|
+
result = u32_b(CONSTRUCTOR)
|
|
20
|
+
result += u32_b(BOT_COMMAND_SCOPE_DEFAULT)
|
|
21
|
+
result += serialize_tl_string(@lang_code)
|
|
22
|
+
result += u32_b(Constructors::VECTOR)
|
|
23
|
+
result += u32_b(@commands.size)
|
|
24
|
+
@commands.each do |cmd|
|
|
25
|
+
result += u32_b(BOT_COMMAND)
|
|
26
|
+
result += serialize_tl_string(cmd[:command])
|
|
27
|
+
result += serialize_tl_string(cmd[:description])
|
|
28
|
+
end
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def serialize_tl_string(str)
|
|
35
|
+
bytes = str.to_s.encode('UTF-8').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
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class SetBotInfo
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x10cf3123
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
|
|
12
|
+
# bot: { id:, access_hash: } or { type: :self } (nil = the calling bot)
|
|
13
|
+
def initialize(bot: nil, lang_code: '', name: nil, about: nil, description: nil)
|
|
14
|
+
@bot = bot
|
|
15
|
+
@lang_code = lang_code
|
|
16
|
+
@name = name
|
|
17
|
+
@about = about
|
|
18
|
+
@description = description
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def serialize
|
|
22
|
+
flags = 0
|
|
23
|
+
flags |= (1 << 2) if @bot
|
|
24
|
+
flags |= (1 << 3) if @name
|
|
25
|
+
flags |= (1 << 0) if @about
|
|
26
|
+
flags |= (1 << 1) if @description
|
|
27
|
+
|
|
28
|
+
result = u32_b(CONSTRUCTOR)
|
|
29
|
+
result += u32_b(flags)
|
|
30
|
+
result += serialize_input_user(@bot) if @bot
|
|
31
|
+
result += serialize_tl_string(@lang_code)
|
|
32
|
+
result += serialize_tl_string(@name) if @name
|
|
33
|
+
result += serialize_tl_string(@about) if @about
|
|
34
|
+
result += serialize_tl_string(@description) if @description
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def serialize_input_user(user)
|
|
41
|
+
if user[:type] == :self
|
|
42
|
+
u32_b(INPUT_USER_SELF)
|
|
43
|
+
else
|
|
44
|
+
u32_b(INPUT_USER) + u64_b(user[:id]) + u64_b(user[:access_hash] || 0)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def serialize_tl_string(str)
|
|
49
|
+
bytes = str.to_s.encode('UTF-8').bytes
|
|
50
|
+
length = bytes.length
|
|
51
|
+
if length <= 253
|
|
52
|
+
[length] + bytes + padding(length + 1)
|
|
53
|
+
else
|
|
54
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def padding(current_length)
|
|
59
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
60
|
+
[0] * pad_length
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -10,9 +10,9 @@ module MTProto
|
|
|
10
10
|
@date = date
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def self.
|
|
13
|
+
def self.deserialize(bytes)
|
|
14
14
|
date = bytes[-4, 4].unpack1('l<')
|
|
15
|
-
update = Update.
|
|
15
|
+
update = Update.deserialize(bytes[4...-4])
|
|
16
16
|
new(update, date)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class UpdateShortSentMessage
|
|
6
|
+
attr_reader :flags, :id, :pts, :pts_count, :date
|
|
7
|
+
|
|
8
|
+
def initialize(flags:, id:, pts:, pts_count:, date:)
|
|
9
|
+
@flags = flags
|
|
10
|
+
@id = id
|
|
11
|
+
@pts = pts
|
|
12
|
+
@pts_count = pts_count
|
|
13
|
+
@date = date
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def out?
|
|
17
|
+
flags & (1 << 1) != 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.deserialize(bytes)
|
|
21
|
+
offset = 4 # skip constructor
|
|
22
|
+
flags = bytes[offset, 4].unpack1('L<')
|
|
23
|
+
offset += 4
|
|
24
|
+
id = bytes[offset, 4].unpack1('l<')
|
|
25
|
+
offset += 4
|
|
26
|
+
pts = bytes[offset, 4].unpack1('l<')
|
|
27
|
+
offset += 4
|
|
28
|
+
pts_count = bytes[offset, 4].unpack1('l<')
|
|
29
|
+
offset += 4
|
|
30
|
+
date = bytes[offset, 4].unpack1('l<')
|
|
31
|
+
|
|
32
|
+
new(flags: flags, id: id, pts: pts, pts_count: pts_count, date: date)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class UpdateUsername
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x3e0bdd7c
|
|
9
|
+
|
|
10
|
+
def initialize(username:)
|
|
11
|
+
@username = username
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def serialize
|
|
15
|
+
result = u32_b(CONSTRUCTOR)
|
|
16
|
+
result += serialize_tl_string(@username)
|
|
17
|
+
result
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def serialize_tl_string(str)
|
|
23
|
+
bytes = str.encode('UTF-8').bytes
|
|
24
|
+
length = bytes.length
|
|
25
|
+
|
|
26
|
+
if length <= 253
|
|
27
|
+
[length] + bytes + padding(length + 1)
|
|
28
|
+
else
|
|
29
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def padding(current_length)
|
|
34
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
35
|
+
[0] * pad_length
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../schema'
|
|
4
|
+
require_relative 'dialogs'
|
|
4
5
|
|
|
5
6
|
module MTProto
|
|
6
7
|
module TL
|
|
7
8
|
class UpdatesDifference
|
|
8
|
-
attr_reader :type, :date, :seq, :new_messages, :pts, :state
|
|
9
|
+
attr_reader :type, :date, :seq, :new_messages, :pts, :state, :chats, :users
|
|
9
10
|
|
|
10
11
|
SCHEMA_PATH = File.expand_path('../../../../data/tl-schema.json', __dir__)
|
|
11
12
|
|
|
12
|
-
def initialize(type:, date: nil, seq: nil, new_messages: [], pts: nil, state: nil)
|
|
13
|
+
def initialize(type:, date: nil, seq: nil, new_messages: [], pts: nil, state: nil, chats: [], users: [])
|
|
13
14
|
@type = type
|
|
14
15
|
@date = date
|
|
15
16
|
@seq = seq
|
|
16
17
|
@new_messages = new_messages
|
|
17
18
|
@pts = pts
|
|
18
19
|
@state = state
|
|
20
|
+
@chats = chats
|
|
21
|
+
@users = users
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
def self.schema
|
|
22
25
|
@schema ||= Schema.new(SCHEMA_PATH)
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
def self.
|
|
28
|
+
def self.deserialize(data)
|
|
26
29
|
constructor = data[0, 4].unpack1('L<')
|
|
27
30
|
|
|
28
31
|
case constructor
|
|
@@ -41,6 +44,11 @@ module MTProto
|
|
|
41
44
|
MESSAGE_CONSTRUCTOR = Constructors::MESSAGE
|
|
42
45
|
MESSAGE_SERVICE = 0x7a800e0a
|
|
43
46
|
MESSAGE_EMPTY = 0x90a6ca84
|
|
47
|
+
MESSAGE_REPLY_HEADER = 0x6917560b
|
|
48
|
+
MEDIA_PHOTO = 0x695150d7
|
|
49
|
+
MEDIA_DOCUMENT = 0x52d8ccd9
|
|
50
|
+
UPDATE_NEW_MESSAGE = 0x1f2b0afd
|
|
51
|
+
UPDATE_NEW_CHANNEL_MESSAGE = 0x62ba04d9
|
|
44
52
|
|
|
45
53
|
class << self
|
|
46
54
|
private
|
|
@@ -53,24 +61,48 @@ module MTProto
|
|
|
53
61
|
)
|
|
54
62
|
end
|
|
55
63
|
|
|
56
|
-
# updates.difference: new_messages new_encrypted_messages other_updates chats users state
|
|
64
|
+
# updates.difference: new_messages new_encrypted_messages other_updates chats users state.
|
|
65
|
+
# Channel/supergroup messages arrive in other_updates as
|
|
66
|
+
# updateNewChannelMessage (not in new_messages), so we mine those too; and
|
|
67
|
+
# chats/users carry the peers' access_hashes for the bot's peer cache.
|
|
57
68
|
def parse_difference(data, constructor)
|
|
58
69
|
offset = 4
|
|
59
70
|
|
|
60
71
|
messages, offset = parse_messages_vector(data, offset)
|
|
61
72
|
offset = schema.skip_vector(data, offset) # new_encrypted_messages
|
|
62
|
-
offset =
|
|
63
|
-
offset =
|
|
64
|
-
offset =
|
|
65
|
-
state = UpdatesState.
|
|
73
|
+
other_messages, offset = parse_other_updates(data, offset)
|
|
74
|
+
chats, offset = Dialogs.chats_at(data, offset)
|
|
75
|
+
users, offset = Dialogs.users_at(data, offset)
|
|
76
|
+
state = UpdatesState.deserialize(data[offset..])
|
|
66
77
|
|
|
67
78
|
new(
|
|
68
79
|
type: constructor == Constructors::UPDATES_DIFFERENCE ? :difference : :slice,
|
|
69
|
-
new_messages: messages,
|
|
70
|
-
state: state
|
|
80
|
+
new_messages: messages + other_messages,
|
|
81
|
+
chats: chats, users: users, state: state
|
|
71
82
|
)
|
|
72
83
|
end
|
|
73
84
|
|
|
85
|
+
# other_updates: Vector<Update>. Mine the message-bearing updates
|
|
86
|
+
# (updateNewMessage / updateNewChannelMessage — each is the update ctor,
|
|
87
|
+
# then an inner Message, then pts/pts_count); advance the rest via schema.
|
|
88
|
+
def parse_other_updates(data, offset)
|
|
89
|
+
offset += 4 # vector constructor
|
|
90
|
+
count = data[offset, 4].unpack1('L<')
|
|
91
|
+
offset += 4
|
|
92
|
+
|
|
93
|
+
messages = []
|
|
94
|
+
count.times do
|
|
95
|
+
ctor = data[offset, 4].unpack1('L<')
|
|
96
|
+
if [UPDATE_NEW_MESSAGE, UPDATE_NEW_CHANNEL_MESSAGE].include?(ctor)
|
|
97
|
+
inner_off = offset + 4
|
|
98
|
+
msg = extract_message(data, inner_off, data[inner_off, 4].unpack1('L<'))
|
|
99
|
+
messages << msg if msg
|
|
100
|
+
end
|
|
101
|
+
offset = schema.skip(data, offset)
|
|
102
|
+
end
|
|
103
|
+
[messages, offset]
|
|
104
|
+
end
|
|
105
|
+
|
|
74
106
|
def parse_messages_vector(data, offset)
|
|
75
107
|
offset += 4 # vector constructor
|
|
76
108
|
count = data[offset, 4].unpack1('L<')
|
|
@@ -97,20 +129,30 @@ module MTProto
|
|
|
97
129
|
id = data[offset, 4].unpack1('l<')
|
|
98
130
|
offset += 4
|
|
99
131
|
|
|
100
|
-
|
|
132
|
+
from_type = from_id = nil
|
|
133
|
+
from_type, from_id, offset = parse_peer(data, offset) if flags.anybits?(1 << 8) # from_id (Peer)
|
|
101
134
|
offset += 4 if flags.anybits?(1 << 29) # from_boosts_applied
|
|
102
135
|
peer_type, peer_id, offset = parse_peer(data, offset)
|
|
103
136
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 28) # saved_peer_id
|
|
104
137
|
offset = schema.skip(data, offset) if flags.anybits?(1 << 2) # fwd_from
|
|
105
138
|
offset += 8 if flags.anybits?(1 << 11) # via_bot_id
|
|
106
139
|
offset += 8 if flags2.anybits?(1 << 0) # via_business_bot_id
|
|
107
|
-
|
|
140
|
+
|
|
141
|
+
is_reply = false
|
|
142
|
+
reply_to_msg_id = nil
|
|
143
|
+
if flags.anybits?(1 << 3) # reply_to
|
|
144
|
+
reply_to_msg_id, is_reply = parse_reply_to(data, offset)
|
|
145
|
+
offset = schema.skip(data, offset)
|
|
146
|
+
end
|
|
108
147
|
|
|
109
148
|
date = data[offset, 4].unpack1('L<')
|
|
110
149
|
offset += 4
|
|
111
|
-
message_text, = read_tl_string(data, offset)
|
|
150
|
+
message_text, offset = read_tl_string(data, offset)
|
|
151
|
+
media = flags.anybits?(1 << 9) ? parse_media(data, offset) : nil
|
|
112
152
|
|
|
113
|
-
{ id: id, date: date, message: message_text, peer_type: peer_type, peer_id: peer_id
|
|
153
|
+
{ id: id, date: date, message: message_text, peer_type: peer_type, peer_id: peer_id,
|
|
154
|
+
from_type: from_type, from_id: from_id, out: flags.anybits?(1 << 1),
|
|
155
|
+
media: media, is_reply: is_reply, reply_to_msg_id: reply_to_msg_id }
|
|
114
156
|
end
|
|
115
157
|
|
|
116
158
|
def parse_peer(data, offset)
|
|
@@ -129,6 +171,43 @@ module MTProto
|
|
|
129
171
|
end
|
|
130
172
|
end
|
|
131
173
|
|
|
174
|
+
# messageReplyHeader: ctor, flags, reply_to_msg_id:flags.4?int (first payload
|
|
175
|
+
# field). A plain message in a forum topic carries this header (forum_topic
|
|
176
|
+
# flags.3) but is a reply only when it targets a message in the topic
|
|
177
|
+
# (reply_to_top_id flags.1). => [reply_to_msg_id, is_reply]
|
|
178
|
+
def parse_reply_to(data, offset)
|
|
179
|
+
return [nil, false] unless data[offset, 4].unpack1('L<') == MESSAGE_REPLY_HEADER
|
|
180
|
+
|
|
181
|
+
io = offset + 4
|
|
182
|
+
flags = data[io, 4].unpack1('L<')
|
|
183
|
+
io += 4
|
|
184
|
+
forum_topic = flags.anybits?(1 << 3)
|
|
185
|
+
msg_id = flags.anybits?(1 << 4) ? data[io, 4].unpack1('l<') : nil
|
|
186
|
+
[msg_id, forum_topic ? flags.anybits?(1 << 1) : true]
|
|
187
|
+
rescue StandardError
|
|
188
|
+
[nil, false]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Classify message media into :photo / :video / :audio / :document, or nil.
|
|
192
|
+
def parse_media(data, offset)
|
|
193
|
+
case data[offset, 4].unpack1('L<')
|
|
194
|
+
when MEDIA_PHOTO
|
|
195
|
+
:photo
|
|
196
|
+
when MEDIA_DOCUMENT
|
|
197
|
+
document_kind(data[offset + 4, 4].unpack1('L<'))
|
|
198
|
+
end
|
|
199
|
+
rescue StandardError
|
|
200
|
+
nil
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# messageMediaDocument flags: video flags.6 / round flags.7 / voice flags.8.
|
|
204
|
+
def document_kind(flags)
|
|
205
|
+
return :video if flags.anybits?(1 << 6) || flags.anybits?(1 << 7)
|
|
206
|
+
return :audio if flags.anybits?(1 << 8)
|
|
207
|
+
|
|
208
|
+
:document
|
|
209
|
+
end
|
|
210
|
+
|
|
132
211
|
def read_tl_string(data, offset)
|
|
133
212
|
first_byte = data.getbyte(offset)
|
|
134
213
|
if first_byte == 254
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module TL
|
|
5
|
+
class UploadProfilePhoto
|
|
6
|
+
include Binary
|
|
7
|
+
|
|
8
|
+
CONSTRUCTOR = 0x0388a3b5
|
|
9
|
+
INPUT_USER = 0xf21158c6
|
|
10
|
+
INPUT_USER_SELF = 0xf7c1b13f
|
|
11
|
+
INPUT_FILE = 0xf52ff27f
|
|
12
|
+
|
|
13
|
+
# bot: { id:, access_hash: } or { type: :self }; nil targets the calling bot
|
|
14
|
+
# file: { id:, parts:, name:, md5_checksum: }
|
|
15
|
+
def initialize(file:, bot: nil)
|
|
16
|
+
@bot = bot
|
|
17
|
+
@file = file
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize
|
|
21
|
+
flags = (1 << 0) # file
|
|
22
|
+
flags |= (1 << 5) if @bot
|
|
23
|
+
|
|
24
|
+
result = u32_b(CONSTRUCTOR)
|
|
25
|
+
result += u32_b(flags)
|
|
26
|
+
result += serialize_input_user(@bot) if @bot
|
|
27
|
+
result += serialize_input_file(@file)
|
|
28
|
+
result
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def serialize_input_user(user)
|
|
34
|
+
if user[:type] == :self
|
|
35
|
+
u32_b(INPUT_USER_SELF)
|
|
36
|
+
else
|
|
37
|
+
u32_b(INPUT_USER) + u64_b(user[:id]) + u64_b(user[:access_hash] || 0)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def serialize_input_file(file)
|
|
42
|
+
u32_b(INPUT_FILE) +
|
|
43
|
+
u64_b(file[:id]) +
|
|
44
|
+
u32_b(file[:parts]) +
|
|
45
|
+
serialize_tl_string(file[:name].to_s) +
|
|
46
|
+
serialize_tl_string(file[:md5_checksum].to_s)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def serialize_tl_string(str)
|
|
50
|
+
bytes = str.encode('UTF-8').bytes
|
|
51
|
+
length = bytes.length
|
|
52
|
+
if length <= 253
|
|
53
|
+
[length] + bytes + padding(length + 1)
|
|
54
|
+
else
|
|
55
|
+
[254] + u32_b(length)[0, 3] + bytes + padding(length + 4)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def padding(current_length)
|
|
60
|
+
pad_length = (4 - (current_length % 4)) % 4
|
|
61
|
+
[0] * pad_length
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -6,7 +6,7 @@ module MTProto
|
|
|
6
6
|
User = Struct.new(:id, :access_hash, :first_name, :last_name, :username, :phone, :flags, :flags2,
|
|
7
7
|
keyword_init: true)
|
|
8
8
|
|
|
9
|
-
def self.
|
|
9
|
+
def self.deserialize(data)
|
|
10
10
|
constructor = data[0, 4].unpack1('L<')
|
|
11
11
|
raise "Expected Vector constructor, got 0x#{constructor.to_s(16)}" unless constructor == Constructors::VECTOR
|
|
12
12
|
|
data/lib/mtproto/version.rb
CHANGED
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.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artem Levenkov
|
|
@@ -49,8 +49,10 @@ extra_rdoc_files: []
|
|
|
49
49
|
files:
|
|
50
50
|
- ".env.example"
|
|
51
51
|
- ".ruby-version"
|
|
52
|
+
- FUTURE.md
|
|
52
53
|
- Rakefile
|
|
53
54
|
- data/tl-schema.json
|
|
55
|
+
- docs/test_architecture_level1.md
|
|
54
56
|
- ext/aes_ige/aes_ige.c
|
|
55
57
|
- ext/aes_ige/extconf.rb
|
|
56
58
|
- ext/factorization/extconf.rb
|
|
@@ -62,6 +64,7 @@ files:
|
|
|
62
64
|
- lib/mtproto/client/api.rb
|
|
63
65
|
- lib/mtproto/client/api/check_password.rb
|
|
64
66
|
- lib/mtproto/client/api/export_login_token.rb
|
|
67
|
+
- lib/mtproto/client/api/get_contacts.rb
|
|
65
68
|
- lib/mtproto/client/api/get_dialogs.rb
|
|
66
69
|
- lib/mtproto/client/api/get_history.rb
|
|
67
70
|
- lib/mtproto/client/api/get_updates_difference.rb
|
|
@@ -69,6 +72,7 @@ files:
|
|
|
69
72
|
- lib/mtproto/client/api/get_users.rb
|
|
70
73
|
- lib/mtproto/client/api/import_login_token.rb
|
|
71
74
|
- lib/mtproto/client/api/send_code.rb
|
|
75
|
+
- lib/mtproto/client/api/send_message.rb
|
|
72
76
|
- lib/mtproto/client/api/sign_in.rb
|
|
73
77
|
- lib/mtproto/client/rpc.rb
|
|
74
78
|
- lib/mtproto/client/rpc/response.rb
|
|
@@ -92,44 +96,86 @@ files:
|
|
|
92
96
|
- lib/mtproto/tl/object.rb
|
|
93
97
|
- lib/mtproto/tl/objects/account_password.rb
|
|
94
98
|
- lib/mtproto/tl/objects/authorization.rb
|
|
99
|
+
- lib/mtproto/tl/objects/channels_create_channel.rb
|
|
100
|
+
- lib/mtproto/tl/objects/channels_delete_messages.rb
|
|
101
|
+
- lib/mtproto/tl/objects/channels_delete_participant_history.rb
|
|
102
|
+
- lib/mtproto/tl/objects/channels_edit_banned.rb
|
|
103
|
+
- lib/mtproto/tl/objects/channels_get_messages.rb
|
|
104
|
+
- lib/mtproto/tl/objects/channels_get_participant.rb
|
|
105
|
+
- lib/mtproto/tl/objects/channels_join_channel.rb
|
|
106
|
+
- lib/mtproto/tl/objects/channels_leave_channel.rb
|
|
107
|
+
- lib/mtproto/tl/objects/channels_report_spam.rb
|
|
95
108
|
- lib/mtproto/tl/objects/check_password.rb
|
|
96
109
|
- lib/mtproto/tl/objects/client_dh_inner_data.rb
|
|
110
|
+
- lib/mtproto/tl/objects/contacts.rb
|
|
111
|
+
- lib/mtproto/tl/objects/create_bot.rb
|
|
112
|
+
- lib/mtproto/tl/objects/delete_messages.rb
|
|
97
113
|
- lib/mtproto/tl/objects/dh_gen_response.rb
|
|
98
114
|
- lib/mtproto/tl/objects/dialogs.rb
|
|
115
|
+
- lib/mtproto/tl/objects/edit_access_settings.rb
|
|
116
|
+
- lib/mtproto/tl/objects/edit_message.rb
|
|
117
|
+
- lib/mtproto/tl/objects/export_bot_token.rb
|
|
99
118
|
- lib/mtproto/tl/objects/export_login_token.rb
|
|
119
|
+
- lib/mtproto/tl/objects/exported_bot_token.rb
|
|
120
|
+
- lib/mtproto/tl/objects/forward_messages.rb
|
|
121
|
+
- lib/mtproto/tl/objects/get_access_settings.rb
|
|
122
|
+
- lib/mtproto/tl/objects/get_channel_difference.rb
|
|
100
123
|
- lib/mtproto/tl/objects/get_config.rb
|
|
124
|
+
- lib/mtproto/tl/objects/get_contacts.rb
|
|
101
125
|
- lib/mtproto/tl/objects/get_dialogs.rb
|
|
102
126
|
- lib/mtproto/tl/objects/get_difference.rb
|
|
127
|
+
- lib/mtproto/tl/objects/get_file.rb
|
|
128
|
+
- lib/mtproto/tl/objects/get_full_channel.rb
|
|
129
|
+
- lib/mtproto/tl/objects/get_full_user.rb
|
|
103
130
|
- lib/mtproto/tl/objects/get_history.rb
|
|
131
|
+
- lib/mtproto/tl/objects/get_messages_reactions.rb
|
|
104
132
|
- lib/mtproto/tl/objects/get_password.rb
|
|
105
133
|
- lib/mtproto/tl/objects/get_state.rb
|
|
106
134
|
- lib/mtproto/tl/objects/get_users.rb
|
|
107
135
|
- lib/mtproto/tl/objects/gzip_packed.rb
|
|
108
136
|
- lib/mtproto/tl/objects/help_config.rb
|
|
137
|
+
- lib/mtproto/tl/objects/import_bot_authorization.rb
|
|
109
138
|
- lib/mtproto/tl/objects/import_login_token.rb
|
|
110
139
|
- lib/mtproto/tl/objects/init_connection.rb
|
|
140
|
+
- lib/mtproto/tl/objects/input_keyboard_button_request_peer.rb
|
|
141
|
+
- lib/mtproto/tl/objects/invite_to_channel.rb
|
|
111
142
|
- lib/mtproto/tl/objects/invoke_with_layer.rb
|
|
112
143
|
- lib/mtproto/tl/objects/login_token.rb
|
|
113
144
|
- lib/mtproto/tl/objects/message.rb
|
|
114
145
|
- lib/mtproto/tl/objects/messages.rb
|
|
146
|
+
- lib/mtproto/tl/objects/messages_get_messages.rb
|
|
115
147
|
- lib/mtproto/tl/objects/msg_container.rb
|
|
116
148
|
- lib/mtproto/tl/objects/new_session_created.rb
|
|
117
149
|
- lib/mtproto/tl/objects/pq_inner_data.rb
|
|
150
|
+
- lib/mtproto/tl/objects/raw_response.rb
|
|
151
|
+
- lib/mtproto/tl/objects/reply_keyboard_markup.rb
|
|
118
152
|
- lib/mtproto/tl/objects/req_dh_params.rb
|
|
119
153
|
- lib/mtproto/tl/objects/req_pq_multi.rb
|
|
154
|
+
- lib/mtproto/tl/objects/request_peer_type_create_bot.rb
|
|
120
155
|
- lib/mtproto/tl/objects/res_pq.rb
|
|
156
|
+
- lib/mtproto/tl/objects/resolve_username.rb
|
|
121
157
|
- lib/mtproto/tl/objects/rpc_error.rb
|
|
158
|
+
- lib/mtproto/tl/objects/save_file_part.rb
|
|
159
|
+
- lib/mtproto/tl/objects/send_bot_requested_peer.rb
|
|
122
160
|
- lib/mtproto/tl/objects/send_code.rb
|
|
161
|
+
- lib/mtproto/tl/objects/send_media.rb
|
|
162
|
+
- lib/mtproto/tl/objects/send_message.rb
|
|
163
|
+
- lib/mtproto/tl/objects/send_reaction.rb
|
|
123
164
|
- lib/mtproto/tl/objects/sent_code.rb
|
|
124
165
|
- lib/mtproto/tl/objects/server_dh_inner_data.rb
|
|
125
166
|
- lib/mtproto/tl/objects/server_dh_params.rb
|
|
167
|
+
- lib/mtproto/tl/objects/set_bot_commands.rb
|
|
168
|
+
- lib/mtproto/tl/objects/set_bot_info.rb
|
|
126
169
|
- lib/mtproto/tl/objects/set_client_dh_params.rb
|
|
127
170
|
- lib/mtproto/tl/objects/sign_in.rb
|
|
128
171
|
- lib/mtproto/tl/objects/update.rb
|
|
129
172
|
- lib/mtproto/tl/objects/update_short.rb
|
|
130
173
|
- lib/mtproto/tl/objects/update_short_message.rb
|
|
174
|
+
- lib/mtproto/tl/objects/update_short_sent_message.rb
|
|
175
|
+
- lib/mtproto/tl/objects/update_username.rb
|
|
131
176
|
- lib/mtproto/tl/objects/updates_difference.rb
|
|
132
177
|
- lib/mtproto/tl/objects/updates_state.rb
|
|
178
|
+
- lib/mtproto/tl/objects/upload_profile_photo.rb
|
|
133
179
|
- lib/mtproto/tl/objects/users.rb
|
|
134
180
|
- lib/mtproto/tl/schema.rb
|
|
135
181
|
- lib/mtproto/transport/abridged_packet_codec.rb
|
|
@@ -151,6 +197,8 @@ metadata:
|
|
|
151
197
|
rdoc_options: []
|
|
152
198
|
require_paths:
|
|
153
199
|
- lib
|
|
200
|
+
- ext/aes_ige
|
|
201
|
+
- ext/factorization
|
|
154
202
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
203
|
requirements:
|
|
156
204
|
- - ">="
|