class Discordrb::Message

A message on Discord that was sent to a text channel

Attributes

attachments[R]

@return [Array<Attachment>] the files attached to this message.

author[R]

@return [Member, User] the user that sent this message. (Will be a {Member} most of the time, it should only be a

{User} for old messages when the author has left the server since then)
channel[R]

@return [Channel] the channel in which this message was sent.

components[R]

@return [Array<Component>]

content[R]

@return [String] the content of this message.

edit_timestamp[R]

@return [Time] the timestamp at which this message was edited. ‘nil` if the message was never edited.

edited[R]

@return [true, false] whether the message was edited or not.

edited?[R]

@return [true, false] whether the message was edited or not.

edited_timestamp[R]

@return [Time] the timestamp at which this message was edited. ‘nil` if the message was never edited.

embeds[R]

@return [Array<Embed>] the embed objects contained in this message.

mention_everyone[R]

@return [true, false] whether the message mentioned everyone or not.

mention_everyone?[R]

@return [true, false] whether the message mentioned everyone or not.

mentions[R]

@return [Array<User>] the users that were mentioned in this message.

mentions_everyone?[R]

@return [true, false] whether the message mentioned everyone or not.

nonce[R]

@return [String] used for validating a message was sent.

pinned[R]

@return [true, false] whether the message is pinned or not.

pinned?[R]

@return [true, false] whether the message is pinned or not.

reactions[R]

@return [Array<Reaction>] the reaction objects contained in this message.

role_mentions[R]

@return [Array<Role>] the roles that were mentioned in this message.

server[R]

@return [Server, nil] the server in which this message was sent.

text[R]

@return [String] the content of this message.

timestamp[R]

@return [Time] the timestamp at which this message was sent.

to_s[R]

@return [String] the content of this message.

tts[R]

@return [true, false] whether the message used Text-To-Speech (TTS) or not.

tts?[R]

@return [true, false] whether the message used Text-To-Speech (TTS) or not.

type[R]

@return [Integer] what the type of the message is

user[R]

@return [Member, User] the user that sent this message. (Will be a {Member} most of the time, it should only be a

{User} for old messages when the author has left the server since then)
webhook_id[R]

@return [Integer, nil] the webhook ID that sent this message, or ‘nil` if it wasn’t sent through a webhook.

writer[R]

@return [Member, User] the user that sent this message. (Will be a {Member} most of the time, it should only be a

{User} for old messages when the author has left the server since then)

Public Class Methods

new(data, bot) click to toggle source

@!visibility private

# File lib/discordrb/data/message.rb, line 77
def initialize(data, bot)
  @bot = bot
  @content = data['content']
  @channel = bot.channel(data['channel_id'].to_i)
  @pinned = data['pinned']
  @type = data['type']
  @tts = data['tts']
  @nonce = data['nonce']
  @mention_everyone = data['mention_everyone']

  @referenced_message = Message.new(data['referenced_message'], bot) if data['referenced_message']
  @message_reference = data['message_reference']

  @server = @channel.server

  @webhook_id = data['webhook_id']&.to_i

  @author = if data['author']
              if @webhook_id
                # This is a webhook user! It would be pointless to try to resolve a member here, so we just create
                # a User and return that instead.
                Discordrb::LOGGER.debug("Webhook user: #{data['author']['id']}")
                User.new(data['author'].merge({ '_webhook' => true }), @bot)
              elsif @channel.private?
                # Turn the message user into a recipient - we can't use the channel recipient
                # directly because the bot may also send messages to the channel
                Recipient.new(bot.user(data['author']['id'].to_i), @channel, bot)
              else
                member = @channel.server.member(data['author']['id'].to_i)

                if member
                  member.update_data(data['member']) if data['member']
                  member.update_global_name(data['author']['global_name']) if data['author']['global_name']
                else
                  Discordrb::LOGGER.debug("Member with ID #{data['author']['id']} not cached (possibly left the server).")
                  member = if data['member']
                             member_data = data['author'].merge(data['member'])
                             Member.new(member_data, @server, bot)
                           else
                             @bot.ensure_user(data['author'])
                           end
                end

                member
              end
            end

  @timestamp = Time.parse(data['timestamp']) if data['timestamp']
  @edited_timestamp = data['edited_timestamp'].nil? ? nil : Time.parse(data['edited_timestamp'])
  @edited = !@edited_timestamp.nil?
  @id = data['id'].to_i

  @emoji = []

  @reactions = []

  data['reactions']&.each do |element|
    @reactions << Reaction.new(element)
  end

  @mentions = []

  data['mentions']&.each do |element|
    @mentions << bot.ensure_user(element)
  end

  @role_mentions = []

  # Role mentions can only happen on public servers so make sure we only parse them there
  if @channel.text?
    data['mention_roles']&.each do |element|
      @role_mentions << @channel.server.role(element.to_i)
    end
  end

  @attachments = []
  @attachments = data['attachments'].map { |e| Attachment.new(e, self, @bot) } if data['attachments']

  @embeds = []
  @embeds = data['embeds'].map { |e| Embed.new(e, self) } if data['embeds']

  @components = []
  @components = data['components'].map { |component_data| Components.from_data(component_data, @bot) } if data['components']
end

Public Instance Methods

all_reaction_users(limit: 100) click to toggle source

Returns a hash of all reactions to a message as keys and the users that reacted to it as values. @param limit [Integer] the limit of how many users to retrieve per distinct reaction emoji. ‘nil` will return all users @example Get all the users that reacted to a message for a giveaway.

giveaway_participants = message.all_reaction_users

@return [Hash<String => Array<User>>] A hash mapping the string representation of a

reaction to an array of users.
# File lib/discordrb/data/message.rb, line 334
def all_reaction_users(limit: 100)
  all_reactions = @reactions.map { |r| { r.to_s => reacted_with(r, limit: limit) } }
  all_reactions.reduce({}, :merge)
end
await(key, attributes = {}, &block) click to toggle source

Add an {Await} for a message with the same user and channel. @see Bot#add_await @deprecated Will be changed to blocking behavior in v4.0. Use {#await!} instead.

# File lib/discordrb/data/message.rb, line 230
def await(key, attributes = {}, &block)
  @bot.add_await(key, Discordrb::Events::MessageEvent, { from: @author.id, in: @channel.id }.merge(attributes), &block)
end
await!(attributes = {}, &block) click to toggle source

Add a blocking {Await} for a message with the same user and channel. @see Bot#add_await!

# File lib/discordrb/data/message.rb, line 236
def await!(attributes = {}, &block)
  @bot.add_await!(Discordrb::Events::MessageEvent, { from: @author.id, in: @channel.id }.merge(attributes), &block)
end
await_reaction(key, attributes = {}, &block) click to toggle source

Add an {Await} for a reaction to be added on this message. @see Bot#add_await @deprecated Will be changed to blocking behavior in v4.0. Use {#await_reaction!} instead.

# File lib/discordrb/data/message.rb, line 243
def await_reaction(key, attributes = {}, &block)
  @bot.add_await(key, Discordrb::Events::ReactionAddEvent, { message: @id }.merge(attributes), &block)
end
await_reaction!(attributes = {}, &block) click to toggle source

Add a blocking {Await} for a reaction to be added on this message. @see Bot#add_await!

# File lib/discordrb/data/message.rb, line 249
def await_reaction!(attributes = {}, &block)
  @bot.add_await!(Discordrb::Events::ReactionAddEvent, { message: @id }.merge(attributes), &block)
end
buttons() click to toggle source

@return [Array<Components::Button>]

# File lib/discordrb/data/message.rb, line 393
def buttons
  results = @components.collect do |component|
    case component
    when Components::Button
      component
    when Components::ActionRow
      component.buttons
    end
  end

  results.flatten.compact
end
chat_input_command?() click to toggle source

Whether or not this message was of type “CHAT_INPUT_COMMAND” @return [true, false]

# File lib/discordrb/data/message.rb, line 379
def chat_input_command?
  @type == 20
end
create_reaction(reaction) click to toggle source

Reacts to a message. @param reaction [String, to_reaction] the unicode emoji or {Emoji}

# File lib/discordrb/data/message.rb, line 291
def create_reaction(reaction)
  reaction = reaction.to_reaction if reaction.respond_to?(:to_reaction)
  API::Channel.create_reaction(@bot.token, @channel.id, @id, reaction)
  nil
end
Also aliased as: react
delete(reason = nil) click to toggle source

Deletes this message.

# File lib/discordrb/data/message.rb, line 208
def delete(reason = nil)
  API::Channel.delete_message(@bot.token, @channel.id, @id, reason)
  nil
end
delete_all_reactions() click to toggle source

Removes all reactions from this message.

# File lib/discordrb/data/message.rb, line 355
def delete_all_reactions
  API::Channel.delete_all_reactions(@bot.token, @channel.id, @id)
end
delete_own_reaction(reaction) click to toggle source

Deletes this client’s reaction on this message. @param reaction [String, to_reaction] the reaction to remove

# File lib/discordrb/data/message.rb, line 349
def delete_own_reaction(reaction)
  reaction = reaction.to_reaction if reaction.respond_to?(:to_reaction)
  API::Channel.delete_own_reaction(@bot.token, @channel.id, @id, reaction)
end
delete_reaction(user, reaction) click to toggle source

Deletes a reaction made by a user on this message. @param user [User, String, Integer] the user or user ID who used this reaction @param reaction [String, to_reaction] the reaction to remove

# File lib/discordrb/data/message.rb, line 342
def delete_reaction(user, reaction)
  reaction = reaction.to_reaction if reaction.respond_to?(:to_reaction)
  API::Channel.delete_user_reaction(@bot.token, @channel.id, @id, reaction, user.resolve_id)
end
edit(new_content, new_embeds = nil, new_components = nil) click to toggle source

Edits this message to have the specified content instead. You can only edit your own messages. @param new_content [String] the new content the message should have. @param new_embeds [Hash, Discordrb::Webhooks::Embed, Array<Hash>, Array<Discordrb::Webhooks::Embed>, nil] The new embeds the message should have. If ‘nil` the message will be changed to have no embeds. @param new_components [View, Array<Hash>] The new components the message should have. If `nil` the message will be changed to have no components. @return [Message] the resulting message.

# File lib/discordrb/data/message.rb, line 199
def edit(new_content, new_embeds = nil, new_components = nil)
  new_embeds = (new_embeds.instance_of?(Array) ? new_embeds.map(&:to_hash) : [new_embeds&.to_hash]).compact
  new_components = new_components&.to_a || []

  response = API::Channel.edit_message(@bot.token, @channel.id, @id, new_content, [], new_embeds, new_components)
  Message.new(JSON.parse(response), @bot)
end
emoji() click to toggle source

@return [Array<Emoji>] the emotes that were used/mentioned in this message.

# File lib/discordrb/data/message.rb, line 264
def emoji
  return if @content.nil?
  return @emoji unless @emoji.empty?

  @emoji = @bot.parse_mentions(@content).select { |el| el.is_a? Discordrb::Emoji }
end
emoji?() click to toggle source

Check if any emoji were used in this message. @return [true, false] whether or not any emoji were used

# File lib/discordrb/data/message.rb, line 273
def emoji?
  emoji&.empty?
end
from_bot?() click to toggle source

@return [true, false] whether this message was sent by the current {Bot}.

# File lib/discordrb/data/message.rb, line 254
def from_bot?
  @author&.current_bot?
end
inspect() click to toggle source

The inspect method is overwritten to give more useful output

# File lib/discordrb/data/message.rb, line 360
def inspect
  "<Message content=\"#{@content}\" id=#{@id} timestamp=#{@timestamp} author=#{@author} channel=#{@channel}>"
end
message()
Alias for: to_message
my_reactions() click to toggle source

Returns the reactions made by the current bot or user. @return [Array<Reaction>] the reactions

# File lib/discordrb/data/message.rb, line 285
def my_reactions
  @reactions.select(&:me)
end
pin(reason = nil) click to toggle source

Pins this message

# File lib/discordrb/data/message.rb, line 214
def pin(reason = nil)
  API::Channel.pin_message(@bot.token, @channel.id, @id, reason)
  @pinned = true
  nil
end
react(reaction)
Alias for: create_reaction
reacted_with(reaction, limit: 100) click to toggle source

Returns the list of users who reacted with a certain reaction. @param reaction [String, to_reaction] the unicode emoji or {Emoji} @param limit [Integer] the limit of how many users to retrieve. ‘nil` will return all users @example Get all the users that reacted with a thumbs up.

thumbs_up_reactions = message.reacted_with("\u{1F44D}")

@return [Array<User>] the users who used this reaction

# File lib/discordrb/data/message.rb, line 305
def reacted_with(reaction, limit: 100)
  reaction = reaction.to_reaction if reaction.respond_to?(:to_reaction)
  reaction = reaction.to_s if reaction.respond_to?(:to_s)

  get_reactions = proc do |fetch_limit, after_id = nil|
    resp = API::Channel.get_reactions(@bot.token, @channel.id, @id, reaction, nil, after_id, fetch_limit)
    return JSON.parse(resp).map { |d| User.new(d, @bot) }
  end

  # Can be done without pagination
  return get_reactions.call(limit) if limit && limit <= 100

  paginator = Paginator.new(limit, :down) do |last_page|
    if last_page && last_page.count < 100
      []
    else
      get_reactions.call(100, last_page&.last&.id)
    end
  end

  paginator.to_a
end
reactions?() click to toggle source

Check if any reactions were used in this message. @return [true, false] whether or not this message has reactions

# File lib/discordrb/data/message.rb, line 279
def reactions?
  !@reactions.empty?
end
referenced_message() click to toggle source

@return [Message, nil] the Message this Message was sent in reply to.

# File lib/discordrb/data/message.rb, line 384
def referenced_message
  return @referenced_message if @referenced_message
  return nil unless @message_reference

  referenced_channel = @bot.channel(@message_reference['channel_id'])
  @referenced_message = referenced_channel.message(@message_reference['message_id'])
end
reply(content) click to toggle source

Replies to this message with the specified content. @deprecated Please use {#respond}. @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error. @return (see respond) @see Channel#send_message

# File lib/discordrb/data/message.rb, line 167
def reply(content)
  @channel.send_message(content)
end
reply!(content, tts: false, embed: nil, attachments: nil, allowed_mentions: {}, mention_user: false, components: nil) click to toggle source

Responds to this message as an inline reply. @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error. @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech. @param embed [Hash, Discordrb::Webhooks::Embed, nil] The rich embed to append to this message. @param attachments [Array<File>] Files that can be referenced in embeds via ‘attachment://file.png` @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings @param mention_user [true, false] Whether the user that is being replied to should be pinged by the reply. @param components [View, Array<Hash>] Interaction components to associate with this message. @return (see respond)

# File lib/discordrb/data/message.rb, line 180
def reply!(content, tts: false, embed: nil, attachments: nil, allowed_mentions: {}, mention_user: false, components: nil)
  allowed_mentions = { parse: [] } if allowed_mentions == false
  allowed_mentions = allowed_mentions.to_hash.transform_keys(&:to_sym)
  allowed_mentions[:replied_user] = mention_user

  respond(content, tts, embed, attachments, allowed_mentions, self, components)
end
reply?() click to toggle source

Whether or not this message was sent in reply to another message @return [true, false]

# File lib/discordrb/data/message.rb, line 373
def reply?
  !@referenced_message.nil?
end
respond(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil) click to toggle source

(see Channel#send_message)

# File lib/discordrb/data/message.rb, line 189
def respond(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil)
  @channel.send_message(content, tts, embed, attachments, allowed_mentions, message_reference, components)
end
to_message() click to toggle source

to_message -> self or message @return [Discordrb::Message]

# File lib/discordrb/data/message.rb, line 408
def to_message
  self
end
Also aliased as: message
unpin(reason = nil) click to toggle source

Unpins this message

# File lib/discordrb/data/message.rb, line 221
def unpin(reason = nil)
  API::Channel.unpin_message(@bot.token, @channel.id, @id, reason)
  @pinned = false
  nil
end
webhook?() click to toggle source

@return [true, false] whether this message has been sent over a webhook.

# File lib/discordrb/data/message.rb, line 259
def webhook?
  !@webhook_id.nil?
end