class Rubirai::MessageChain

@!attribute [r] has_interpolation

@return [Boolean] if this message chain has interpolation called by {#interpolated_str}

Message chain

@!attribute [r] bot

@return [Bot] the bot object

@!attribute [r] id

@return [Integer, nil] the message id, may be `nil`

@!attribute [r] raw

@return [Hash{String => Object}, nil] the raw message chain, may be `nil`

@!attribute [r] send_time

@return [Integer, nil] the send time of the message chain, may be `nil`

@!attribute [r] messages

@return [Array<Message>] the raw message array

Constants

OBJ_INTERP_CHAR
OBJ_INTERP_LEN

Attributes

bot[R]
has_interpolation[R]
id[R]
messages[R]
raw[R]
send_time[R]

Public Class Methods

make(*messages, bot: nil) click to toggle source

Makes a message chain from a list of messages

@param messages [Array<Rubirai::Message, Rubirai::MessageChain, Hash, String, Object>] a list of messages @param bot [Rubirai::Bot, nil] @return [Rubirai::MessageChain] the message chain

# File lib/rubirai/messages/message_chain.rb, line 29
def self.make(*messages, bot: nil)
  chain = new(bot)
  result = []
  messages.map { |msg| Message.to_message(msg, bot) }.each do |msg|
    if !result.empty? && result[-1].is_a?(PlainMessage) && msg.is_a?(PlainMessage)
      result[-1] = PlainMessage.from(text: result[-1].text + msg.text, bot: bot)
    else
      result.append msg
    end
  end
  chain.extend(*result)
  chain
end
new(bot = nil, source = nil) click to toggle source

Don't use the constructor. Use {.make}.

@private @param bot [Rubirai::Bot, nil] @param source [Array, nil]

# File lib/rubirai/messages/message_chain.rb, line 93
def initialize(bot = nil, source = nil)
  @bot = bot
  @messages = []
  @has_interpolation = false
  @interpolated_str = nil
  @ipl_objs_map = {}
  @raw = source
  return unless source
  raise(MiraiError, 'source is not array') unless source.is_a? Array
  raise(MiraiError, 'length is zero') if source.empty?

  if source[0]['type'] == 'Source'
    @id = source[0]['id']
    @send_time = source[0]['time']
    extend(*source.drop(1))
  else
    extend(*source)
  end
end

Public Instance Methods

<<(*messages)
Alias for: extend
[](idx) click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 68
def [](idx)
  @messages[idx]
end
append(*messages)
Alias for: extend
chain_from_interpolated(str) click to toggle source

Get a new chain from interpolated string generated from the original message chain. The given interpolated string can be a substring of original one so that elements can be extracted easily.

@param str [String] the interpolated string @return [MessageChain] the message chain constructed

# File lib/rubirai/messages/interpolation.rb, line 35
def chain_from_interpolated(str)
  _interpolate_with_objects(str)
end
concat!(msg_chain) click to toggle source

Concats this message chain with another one

@param msg_chain [MessageChain] another message chain @return [MessageChain] self

# File lib/rubirai/messages/message_chain.rb, line 61
def concat!(msg_chain)
  msg_chain.messages.each do |msg|
    internal_append msg
  end
  self
end
each(&block) click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 72
def each(&block)
  @messages.each(&block)
end
empty?() click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 84
def empty?
  @messages.empty?
end
extend(*messages) click to toggle source

Append messages to this message chain

@param messages [Array<Rubirai::Message, Hash>] a list of messages @return [Rubirai::MessageChain] self

# File lib/rubirai/messages/message_chain.rb, line 47
def extend(*messages)
  messages.each do |msg|
    internal_append msg
  end
  self
end
Also aliased as: <<, append
get_object(obj_id) click to toggle source

Get the interpolated object by given id

@param obj_id [String] the object id @return [Message, nil] the message. `nil` if `obj_id` is malformed or not found.

# File lib/rubirai/messages/interpolation.rb, line 25
def get_object(obj_id)
  _get_object(obj_id)
end
interpolated_str() click to toggle source

Convert the message chain to an interpolated string.

@return [String]

# File lib/rubirai/messages/interpolation.rb, line 14
def interpolated_str
  return @interpolated_str if @has_interpolation
  @interpolated_str = _gen_interp_str
  @has_interpolation = true
  @interpolated_str
end
length() click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 76
def length
  @messages.length
end
size() click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 80
def size
  @messages.size
end
to_a() click to toggle source

Convert the message chain to an array of hashes.

@return [Array<Hash{String => Object}>]

# File lib/rubirai/messages/message_chain.rb, line 116
def to_a
  @messages.map(&:to_h)
end

Private Instance Methods

_gen_interp_str() click to toggle source
# File lib/rubirai/messages/interpolation.rb, line 44
def _gen_interp_str
  result = +''
  @messages.each do |msg|
    result << case msg
              when PlainMessage
                _transform_plain_txt(msg.text)
              else
                _transform_object(msg)
              end
  end
  result
end
_get_object(obj_id) click to toggle source
# File lib/rubirai/messages/interpolation.rb, line 68
def _get_object(obj_id)
  return nil if obj_id.length != OBJ_INTERP_LEN && obj_id.length != (OBJ_INTERP_LEN + 2)
  return @ipl_objs_map[obj_id] if obj_id.length == OBJ_INTERP_LEN
  return nil if obj_id[0] != OBJ_INTERP_CHAR || obj_id[-1] != OBJ_INTERP_CHAR

  @ipl_objs_map[obj_id[1...-1]]
end
_interpolate_with_objects(str) click to toggle source

@private @param str [String]

# File lib/rubirai/messages/interpolation.rb, line 78
def _interpolate_with_objects(str)
  sb = +''
  result = MessageChain.new(bot)
  i = 0
  while i < str.length
    if i == str.length - 1
      sb << str[i]
      break
    end

    if str[i] != OBJ_INTERP_CHAR
      sb << str[i]
      i += 1
      next
    end

    if str[i + 1] == OBJ_INTERP_CHAR
      sb << OBJ_INTERP_CHAR
      i += 1
    else
      result.append PlainMessage.from(text: sb) unless sb.empty?
      sb = str[i...i + OBJ_INTERP_LEN + 2]
      obj = _get_object(sb)
      i += OBJ_INTERP_LEN + 1
      unless obj.nil?
        result.append obj
        sb = +''
      end
    end

    i += 1
  end

  result.append PlainMessage.from(text: sb) unless sb.nil? || sb.empty?
  result
end
_transform_object(obj) click to toggle source
# File lib/rubirai/messages/interpolation.rb, line 61
def _transform_object(obj)
  obj_id = Utils.random_str(OBJ_INTERP_LEN)
  obj_id = Utils.random_str(OBJ_INTERP_LEN) while @ipl_objs_map.include?(obj_id)
  @ipl_objs_map[obj_id] = obj
  "#{OBJ_INTERP_CHAR}#{obj_id}#{OBJ_INTERP_CHAR}"
end
_transform_plain_txt(str) click to toggle source
# File lib/rubirai/messages/interpolation.rb, line 57
def _transform_plain_txt(str)
  str.gsub(OBJ_INTERP_CHAR, OBJ_INTERP_CHAR * 2)
end
internal_append(msg) click to toggle source
# File lib/rubirai/messages/message_chain.rb, line 122
def internal_append(msg)
  msg.must_be! [Message, MessageChain, Hash], RubiraiError, 'msg must be Message, MessageChain, or Hash'

  case msg
  when Message
    @messages.append msg
  when MessageChain
    @messages.append(*msg.messages)
  else
    @messages.append Message.build_from(msg, @bot)
  end

  self
end