Class: MTProto::TL::Updates

Inherits:
Object
  • Object
show all
Defined in:
lib/mtproto/tl/objects/updates.rb

Overview

The live ‘updates`#74ae4240 / `updatesCombined`#725b04c3 push container a bot receives in real time (as opposed to the `updates.getDifference` reply UpdatesDifference handles). Mines the message-bearing updates into structured messages — including any media — and returns the senders in users[] for the peer/access_hash cache. Each update is advanced via Schema#skip, so an update type we don’t model never drops the ones we do.

Constant Summary collapse

UPDATE_NEW_MESSAGE =
0x1f2b0afd
UPDATE_NEW_CHANNEL_MESSAGE =
0x62ba04d9
UPDATE_BOT_CALLBACK_QUERY =
0xb9cfc48d
UPDATE_BOT_GUEST_CHAT_QUERY =
0xcdd4093d

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(messages:, users:, chats:, callback_queries: [], guest_queries: []) ⇒ Updates

Returns a new instance of Updates.



23
24
25
26
27
28
29
# File 'lib/mtproto/tl/objects/updates.rb', line 23

def initialize(messages:, users:, chats:, callback_queries: [], guest_queries: [])
  @messages = messages
  @users = users
  @chats = chats
  @callback_queries = callback_queries
  @guest_queries = guest_queries
end

Instance Attribute Details

#callback_queriesObject (readonly)

Returns the value of attribute callback_queries.



16
17
18
# File 'lib/mtproto/tl/objects/updates.rb', line 16

def callback_queries
  @callback_queries
end

#chatsObject (readonly)

Returns the value of attribute chats.



16
17
18
# File 'lib/mtproto/tl/objects/updates.rb', line 16

def chats
  @chats
end

#guest_queriesObject (readonly)

Returns the value of attribute guest_queries.



16
17
18
# File 'lib/mtproto/tl/objects/updates.rb', line 16

def guest_queries
  @guest_queries
end

#messagesObject (readonly)

Returns the value of attribute messages.



16
17
18
# File 'lib/mtproto/tl/objects/updates.rb', line 16

def messages
  @messages
end

#usersObject (readonly)

Returns the value of attribute users.



16
17
18
# File 'lib/mtproto/tl/objects/updates.rb', line 16

def users
  @users
end

Class Method Details

.deserialize(data) ⇒ Object

updates: updates:Vector<Update> users:Vector<User> chats:Vector<Chat> … (updatesCombined adds a seq_start before seq; both share this prefix).



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/mtproto/tl/objects/updates.rb', line 33

def self.deserialize(data)
  constructor = data[0, 4].unpack1('L<')
  unless [Constructors::UPDATES, Constructors::UPDATES_COMBINED].include?(constructor)
    return new(messages: [], users: [], chats: [], callback_queries: [], guest_queries: [])
  end

  messages, callback_queries, guest_queries, offset = parse_updates_vector(data, 4)
  users, offset = Dialogs.users_at(data, offset)
  chats, = Dialogs.chats_at(data, offset)
  new(messages: messages, users: users, chats: chats,
    callback_queries: callback_queries, guest_queries: guest_queries)
end

.extract_callback_query(data, offset) ⇒ Object

updateBotCallbackQuery#b9cfc48d flags:# query_id:long user_id:long peer:Peer

msg_id:int chat_instance:long data:flags.0?bytes game_short_name:flags.1?string

A bot receives this when a user taps an inline callback button; the data is the button’s callback payload. The outer loop advances past it via Schema#skip.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/mtproto/tl/objects/updates.rb', line 74

def self.extract_callback_query(data, offset)
  offset += 4 # constructor
  flags = data[offset, 4].unpack1('L<')
  offset += 4
  query_id = data[offset, 8].unpack1('Q<')
  offset += 8
  user_id = data[offset, 8].unpack1('Q<')
  offset += 8
  peer_type, peer_id, offset = Reader.parse_peer(data, offset)
  msg_id = data[offset, 4].unpack1('l<')
  offset += 4
  offset += 8 # chat_instance (unused)
  payload = nil
  payload, = Reader.read_tl_bytes(data, offset) if flags.anybits?(1 << 0)

  { query_id: query_id, user_id: user_id, peer_type: peer_type, peer_id: peer_id,
    msg_id: msg_id, data: payload }
end

.extract_guest_query(data, offset) ⇒ Object

updateBotGuestChatQuery#cdd4093d flags:# query_id:long message:Message

reference_messages:flags.0?Vector<Message> qts:int

A guest-mode bot receives this when a user @-mentions it in a chat it is NOT a member of; the inner message is the mentioning message (sender in from_id). The bot answers once with messages.setBotGuestChatResult(query_id, result). The outer loop advances past the whole update via Schema#skip, so this only needs to read the fields we surface (query_id + the parsed message + qts).



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mtproto/tl/objects/updates.rb', line 100

def self.extract_guest_query(data, offset)
  offset += 4 # constructor
  flags = data[offset, 4].unpack1('L<')
  offset += 4
  query_id = data[offset, 8].unpack1('Q<')
  offset += 8
  msg = Message.deserialize(data, offset, data[offset, 4].unpack1('L<'))
  offset = Reader.schema.skip(data, offset) # message:Message
  if flags.anybits?(1 << 0) # reference_messages:Vector<Message>
    offset = Reader.schema.skip_vector(data, offset) { |d, o| Reader.schema.skip(d, o) }
  end
  qts = data[offset, 4].unpack1('l<')

  { query_id: query_id, message: msg&.to_h, qts: qts }
end

.parse_updates_vector(data, offset) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/mtproto/tl/objects/updates.rb', line 46

def self.parse_updates_vector(data, offset)
  offset += 4 # vector constructor
  count = data[offset, 4].unpack1('L<')
  offset += 4

  messages = []
  callback_queries = []
  guest_queries = []
  count.times do
    ctor = data[offset, 4].unpack1('L<')
    if [UPDATE_NEW_MESSAGE, UPDATE_NEW_CHANNEL_MESSAGE].include?(ctor)
      inner = offset + 4
      msg = Message.deserialize(data, inner, data[inner, 4].unpack1('L<'))
      messages << msg.to_h if msg
    elsif ctor == UPDATE_BOT_CALLBACK_QUERY
      callback_queries << extract_callback_query(data, offset)
    elsif ctor == UPDATE_BOT_GUEST_CHAT_QUERY
      guest_queries << extract_guest_query(data, offset)
    end
    offset = Reader.schema.skip(data, offset)
  end
  [messages, callback_queries, guest_queries, offset]
end