mtproto 0.0.17 → 0.0.20

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.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'securerandom'
4
+ require_relative '../message_entity'
4
5
 
5
6
  module MTProto
6
7
  module TL
@@ -8,36 +9,69 @@ module MTProto
8
9
  include Binary
9
10
 
10
11
  INPUT_REPLY_TO_MESSAGE = 0x3bd4b7c2
12
+ INPUT_RICH_MESSAGE_MARKDOWN = 0x004b572c
11
13
 
12
- def initialize(peer:, message:, random_id: nil, reply_to: nil, reply_markup: nil, silent: false)
14
+ def initialize(peer:, message: '', random_id: nil, reply_to: nil, reply_markup: nil, silent: false,
15
+ entities: nil, rich_markdown: nil, quote_text: nil, quote_offset: nil)
13
16
  @peer = peer
14
17
  @message = message
15
18
  @random_id = random_id || SecureRandom.random_number(2**63)
16
19
  @reply_to = reply_to
17
20
  @reply_markup = reply_markup
18
21
  @silent = silent
22
+ @entities = entities
23
+ @rich_markdown = rich_markdown
24
+ @quote_text = quote_text
25
+ @quote_offset = quote_offset
19
26
  end
20
27
 
21
28
  def serialize
22
29
  flags = 0
23
30
  flags |= (1 << 0) if @reply_to
24
31
  flags |= (1 << 2) if @reply_markup
32
+ flags |= (1 << 3) if entities?
25
33
  flags |= (1 << 5) if @silent
34
+ flags |= (1 << 23) if @rich_markdown # rich_message
26
35
 
27
36
  result = u32_b(Constructors::MESSAGES_SEND_MESSAGE)
28
37
  result += u32_b(flags)
29
38
  result += serialize_input_peer
30
39
  result += serialize_reply_to if @reply_to
31
- result += serialize_tl_string(@message)
40
+ # Server-side rich markdown carries the whole message; the text field goes
41
+ # empty and no entities are sent (matches Telegram Desktop's sendRichMessage).
42
+ result += serialize_tl_string(@rich_markdown ? '' : @message)
32
43
  result += u64_b(@random_id)
33
44
  result += @reply_markup.serialize if @reply_markup
45
+ result += MessageEntities.serialize(@entities) if entities?
46
+ result += serialize_rich_markdown if @rich_markdown
34
47
  result
35
48
  end
36
49
 
37
50
  private
38
51
 
52
+ def entities?
53
+ @entities && !@entities.empty? && !@rich_markdown
54
+ end
55
+
56
+ # inputRichMessageMarkdown#004b572c flags:# rtl:flags.0?true noautolink:flags.1?true
57
+ # markdown:string files:flags.2?Vector<InputRichFile>. Text-only: flags=0, no files.
58
+ def serialize_rich_markdown
59
+ u32_b(INPUT_RICH_MESSAGE_MARKDOWN) + u32_b(0) + serialize_tl_string(@rich_markdown)
60
+ end
61
+
62
+ # inputReplyToMessage#3bd4b7c2 flags:# reply_to_msg_id:int quote_text:flags.2?string
63
+ # quote_offset:flags.4?int. A quote replies to @reply_to while pinning the exact
64
+ # fragment (@quote_text at @quote_offset in that message); Telegram validates the
65
+ # text against the original at the offset.
39
66
  def serialize_reply_to
40
- u32_b(INPUT_REPLY_TO_MESSAGE) + u32_b(0) + u32_b(@reply_to)
67
+ flags = 0
68
+ flags |= (1 << 2) if @quote_text
69
+ flags |= (1 << 4) unless @quote_offset.nil?
70
+
71
+ result = u32_b(INPUT_REPLY_TO_MESSAGE) + u32_b(flags) + u32_b(@reply_to)
72
+ result += serialize_tl_string(@quote_text) if @quote_text
73
+ result += u32_b(@quote_offset) unless @quote_offset.nil?
74
+ result
41
75
  end
42
76
 
43
77
  def serialize_input_peer
@@ -23,6 +23,21 @@ module MTProto
23
23
  end
24
24
  end
25
25
 
26
+ # Whether a top-level pushed message (as delivered to Client#on_update with
27
+ # its outer constructor and body) carries an updateLoginToken — the signal
28
+ # that a QR login token was scanned and accepted. Arrives bare or, in
29
+ # practice, wrapped in updateShort.
30
+ def self.login_token?(constructor, body)
31
+ case constructor
32
+ when Constructors::UPDATE_LOGIN_TOKEN
33
+ true
34
+ when Constructors::UPDATE_SHORT
35
+ UpdateShort.deserialize(body).update.type == 'login_token'
36
+ else
37
+ false
38
+ end
39
+ end
40
+
26
41
  class << self
27
42
  private
28
43
 
@@ -41,21 +41,48 @@ module MTProto
41
41
  end
42
42
  end
43
43
 
44
- # messageReplyHeader: ctor, flags, reply_to_msg_id:flags.4?int (first payload
45
- # field). A plain message in a forum topic carries this header (forum_topic
46
- # flags.3) but is a reply only when it targets a message in the topic
47
- # (reply_to_top_id flags.1). => [reply_to_msg_id, is_reply]
44
+ # messageReplyHeader#1b97dd66: flags, then (in wire order) reply_to_msg_id
45
+ # flags.4?int, reply_to_peer_id flags.0?Peer, reply_from flags.5?MessageFwdHeader,
46
+ # reply_media flags.8?MessageMedia, reply_to_top_id flags.1?int, quote_text
47
+ # flags.6?string, quote_entities flags.7?Vector<MessageEntity>, quote_offset
48
+ # flags.10?int. A manual quote sets flags.9 and carries quote_text/offset — the
49
+ # fragment the user selected out of the replied-to message. The quote fields sit
50
+ # past the variable-length reply_from/reply_media, so we walk the whole header to
51
+ # reach them (reply_from/reply_media are sized via the schema). A plain message
52
+ # in a forum topic carries this header (forum_topic flags.3) but is a reply only
53
+ # when it targets a message in the topic (reply_to_top_id flags.1). Returns a
54
+ # descriptor hash, or nil for a non-messageReplyHeader (e.g. a story reply).
48
55
  def parse_reply_to(data, offset)
49
- return [nil, false] unless data[offset, 4].unpack1('L<') == MESSAGE_REPLY_HEADER
56
+ return unless data[offset, 4].unpack1('L<') == MESSAGE_REPLY_HEADER
50
57
 
51
58
  io = offset + 4
52
59
  flags = data[io, 4].unpack1('L<')
53
60
  io += 4
54
61
  forum_topic = flags.anybits?(1 << 3)
55
- msg_id = flags.anybits?(1 << 4) ? data[io, 4].unpack1('l<') : nil
56
- [msg_id, forum_topic ? flags.anybits?(1 << 1) : true]
62
+
63
+ msg_id = nil
64
+ if flags.anybits?(1 << 4) # reply_to_msg_id
65
+ msg_id = data[io, 4].unpack1('l<')
66
+ io += 4
67
+ end
68
+
69
+ peer_type = peer_id = nil
70
+ peer_type, peer_id, io = parse_peer(data, io) if flags.anybits?(1 << 0) # reply_to_peer_id
71
+
72
+ io = schema.skip(data, io) if flags.anybits?(1 << 5) # reply_from
73
+ io = schema.skip(data, io) if flags.anybits?(1 << 8) # reply_media
74
+ io += 4 if flags.anybits?(1 << 1) # reply_to_top_id
75
+
76
+ quote_text = nil
77
+ quote_text, io = read_tl_string(data, io) if flags.anybits?(1 << 6)
78
+ io = schema.skip_vector(data, io) if flags.anybits?(1 << 7) # quote_entities
79
+ quote_offset = flags.anybits?(1 << 10) ? data[io, 4].unpack1('l<') : nil
80
+
81
+ { msg_id: msg_id, is_reply: forum_topic ? flags.anybits?(1 << 1) : true,
82
+ is_quote: flags.anybits?(1 << 9), quote_text: quote_text, quote_offset: quote_offset,
83
+ peer_type: peer_type, peer_id: peer_id }
57
84
  rescue StandardError
58
- [nil, false]
85
+ nil
59
86
  end
60
87
 
61
88
  # Classify message media into :photo / :video / :audio / :document, or nil.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MTProto
4
- VERSION = '0.0.17'
4
+ VERSION = '0.0.20'
5
5
  end
data/lib/mtproto.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative 'mtproto/version'
4
4
  require_relative 'mtproto/errors'
5
5
  require_relative 'mtproto/binary'
6
+ require_relative 'mtproto/dc'
6
7
  require_relative 'mtproto/delegate_methods'
7
8
  require_relative 'mtproto/transport/errors'
8
9
  require_relative 'mtproto/transport/packet'
@@ -13,6 +14,8 @@ require_relative 'mtproto/unencrypted_message'
13
14
  require_relative 'mtproto/tl/constructors'
14
15
  require_relative 'mtproto/tl/constructor_names'
15
16
  require_relative 'mtproto/tl/reader'
17
+ require_relative 'mtproto/tl/message_entity'
18
+ require_relative 'mtproto/markdown'
16
19
  require_relative 'mtproto/tl/object'
17
20
  require_relative 'mtproto/tl/objects/update'
18
21
  require_relative 'mtproto/tl/objects/update_short'
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.17
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Levenkov
@@ -65,6 +65,8 @@ files:
65
65
  - lib/mtproto/client/api/check_password.rb
66
66
  - lib/mtproto/client/api/export_authorization.rb
67
67
  - lib/mtproto/client/api/export_login_token.rb
68
+ - lib/mtproto/client/api/get_bot_callback_answer.rb
69
+ - lib/mtproto/client/api/get_channel_difference.rb
68
70
  - lib/mtproto/client/api/get_contacts.rb
69
71
  - lib/mtproto/client/api/get_dialogs.rb
70
72
  - lib/mtproto/client/api/get_history.rb
@@ -72,6 +74,7 @@ files:
72
74
  - lib/mtproto/client/api/get_updates_state.rb
73
75
  - lib/mtproto/client/api/get_users.rb
74
76
  - lib/mtproto/client/api/import_authorization.rb
77
+ - lib/mtproto/client/api/import_bot_authorization.rb
75
78
  - lib/mtproto/client/api/import_login_token.rb
76
79
  - lib/mtproto/client/api/send_code.rb
77
80
  - lib/mtproto/client/api/send_message.rb
@@ -87,21 +90,27 @@ files:
87
90
  - lib/mtproto/crypto/rsa_key.rb
88
91
  - lib/mtproto/crypto/rsa_pad.rb
89
92
  - lib/mtproto/crypto/srp.rb
93
+ - lib/mtproto/dc.rb
90
94
  - lib/mtproto/delegate_methods.rb
91
95
  - lib/mtproto/encrypted_message.rb
92
96
  - lib/mtproto/errors.rb
93
97
  - lib/mtproto/file_downloader.rb
98
+ - lib/mtproto/markdown.rb
94
99
  - lib/mtproto/message_id.rb
95
100
  - lib/mtproto/session.rb
96
101
  - lib/mtproto/tl/constructor_names.rb
97
102
  - lib/mtproto/tl/constructors.rb
103
+ - lib/mtproto/tl/message_entity.rb
98
104
  - lib/mtproto/tl/object.rb
99
105
  - lib/mtproto/tl/objects/account_password.rb
100
106
  - lib/mtproto/tl/objects/authorization.rb
107
+ - lib/mtproto/tl/objects/bot_callback_answer.rb
101
108
  - lib/mtproto/tl/objects/bot_command_scope.rb
109
+ - lib/mtproto/tl/objects/channel_difference.rb
102
110
  - lib/mtproto/tl/objects/channels_create_channel.rb
103
111
  - lib/mtproto/tl/objects/channels_delete_messages.rb
104
112
  - lib/mtproto/tl/objects/channels_delete_participant_history.rb
113
+ - lib/mtproto/tl/objects/channels_edit_admin.rb
105
114
  - lib/mtproto/tl/objects/channels_edit_banned.rb
106
115
  - lib/mtproto/tl/objects/channels_get_messages.rb
107
116
  - lib/mtproto/tl/objects/channels_get_participant.rb
@@ -127,6 +136,7 @@ files:
127
136
  - lib/mtproto/tl/objects/get_access_settings.rb
128
137
  - lib/mtproto/tl/objects/get_bot_callback_answer.rb
129
138
  - lib/mtproto/tl/objects/get_bot_commands.rb
139
+ - lib/mtproto/tl/objects/get_bot_info.rb
130
140
  - lib/mtproto/tl/objects/get_channel_difference.rb
131
141
  - lib/mtproto/tl/objects/get_config.rb
132
142
  - lib/mtproto/tl/objects/get_contacts.rb
@@ -153,6 +163,8 @@ files:
153
163
  - lib/mtproto/tl/objects/login_token.rb
154
164
  - lib/mtproto/tl/objects/message.rb
155
165
  - lib/mtproto/tl/objects/messages.rb
166
+ - lib/mtproto/tl/objects/messages_add_chat_user.rb
167
+ - lib/mtproto/tl/objects/messages_create_chat.rb
156
168
  - lib/mtproto/tl/objects/messages_get_messages.rb
157
169
  - lib/mtproto/tl/objects/msg_container.rb
158
170
  - lib/mtproto/tl/objects/new_session_created.rb