class Cinch::Message
This class serves two purposes. For one, it simply represents incoming messages and allows for querying various details (who sent the message, what kind of message it is, etc).
At the same time, it allows responding to messages, which means sending messages to either users or channels.
Attributes
@return [String, nil] The action message @since 2.0.0
@return [Bot] @since 1.1.0
@return [Channel] The channel in which this message was sent
@return [String]
@return [Array<String>, nil]
@return [String, nil] the command part of an CTCP message
@return [String, nil] the CTCP message, without 001 control characters
@return [Integer, nil] the numeric error code, if any
@return [Array<Symbol>]
@return [String, nil]
@return [Array<String>]
@return [String]
@return [String]
@return [String, nil]
The STATUSMSG mode a channel message was sent to.
Some IRC
servers allow sending messages limited to people in a channel who have a certain mode. For example, by sending a message to `+#channel`, only people who are voiced, or have a higher mode (op) will receive the message.
This attribute contains the mode character the message was sent to, or nil if it was a normal message. For the previous example, this attribute would be set to `āvā`, for voiced.
@return [String, nil] @since 2.3.0
@return [Target]
@return [Time] @since 2.0.0
@return [User] The user who sent this message
Public Class Methods
# File lib/cinch/message.rb, line 88 def initialize(msg, bot) @raw = msg @bot = bot @matches = { ctcp: {}, action: {}, other: {} } @events = [] @time = Time.now @statusmsg_mode = nil parse if msg end
Public Instance Methods
@return [Boolean] true if the message is an action (/me) @since 2.0.0
# File lib/cinch/message.rb, line 150 def action? @ctcp_command == "ACTION" end
Reply to a message with an action.
For its behaviour with regard to STATUSMSG, see {#reply}.
@param [String] text the action message @return [void]
# File lib/cinch/message.rb, line 213 def action_reply(text) text = text.to_s reply_target.action(text) end
@return [Boolean] true if this message was sent in a channel
# File lib/cinch/message.rb, line 139 def channel? !@channel.nil? end
@return [Boolean] true if the message is an CTCP message
# File lib/cinch/message.rb, line 144 def ctcp? !!(@params.last =~ /\001.+\001/) end
Reply to a CTCP message
@return [void]
# File lib/cinch/message.rb, line 230 def ctcp_reply(answer) return unless ctcp? @user.notice "\001#{@ctcp_command} #{answer}\001" end
@return [Boolean] true if the message describes an error
# File lib/cinch/message.rb, line 134 def error? !@error.nil? end
@api private @return [MatchData]
# File lib/cinch/message.rb, line 158 def match(regexp, type, strip_colors) text = "" case type when :ctcp text = ctcp_message when :action text = action_message else text = message.to_s type = :other end text = Cinch::Formatting.unformat(text) if strip_colors @matches[type][regexp] ||= text.match(regexp) end
@return [Boolean] true if the message is an numeric reply (as
opposed to a command)
# File lib/cinch/message.rb, line 129 def numeric_reply? !!@command.match(/^\d{3}$/) end
@api private @return [void]
# File lib/cinch/message.rb, line 100 def parse match = @raw.match(/\A(?:@([^ ]+) )?(?::(\S+) )?(\S+)(.*)/) tags, @prefix, @command, raw_params = match.captures if @bot.irc.network.ngametv? @prefix = "%s!%s@%s" % [@prefix, @prefix, @prefix] if @prefix != "ngame" end @params = parse_params(raw_params) @tags = parse_tags(tags) @user = parse_user @channel, @statusmsg_mode = parse_channel @target = @channel || @user @server = parse_server @error = parse_error @message = parse_message @ctcp_message = parse_ctcp_message @ctcp_command = parse_ctcp_command @ctcp_args = parse_ctcp_args @action_message = parse_action_message end
Replies to a message, automatically determining if it was a channel or a private message.
If the message is a STATUSMSG, i.e. it was send to `+#channel` or `@#channel` instead of `#channel`, the reply will be sent as the same kind of STATUSMSG. See {#statusmsg_mode} for more information on STATUSMSG.
@param [String] text the message @param [Boolean] prefix if prefix is true and the message was in
a channel, the reply will be prefixed by the nickname of whoever send the mesage
@return [void]
# File lib/cinch/message.rb, line 190 def reply(text, prefix = false) text = text.to_s text = text.split("\n").map { |l| "#{user.nick}: #{l}" }.join("\n") if @channel && prefix reply_target.send(text) end
Like {#action_reply}, but using {Target#safe_action} instead
@param (see action_reply
) @return (see action_reply
)
# File lib/cinch/message.rb, line 222 def safe_action_reply(text) text = text.to_s reply_target.safe_action(text) end
@return [String] @since 1.1.0
# File lib/cinch/message.rb, line 240 def to_s "#<Cinch::Message @raw=#{@raw.chomp.inspect} @params=#{@params.inspect} channel=#{@channel.inspect} user=#{@user.inspect}>" end
Private Instance Methods
# File lib/cinch/message.rb, line 384 def parse_action_message # has to be called after parse_ctcp_message return nil unless action? @ctcp_message.split(" ", 2).last end
# File lib/cinch/message.rb, line 308 def parse_channel # has to be called after parse_params return nil if @params.empty? case @command when "INVITE", Constants::RPL_CHANNELMODEIS.to_s, Constants::RPL_BANLIST.to_s @bot.channel_list.find_ensured(@params[1]) when Constants::RPL_NAMEREPLY.to_s @bot.channel_list.find_ensured(@params[2]) else # Note that this will also find channels for messages that # don't actually include a channel parameter. For example # `QUIT :#sometext` will be interpreted as a channel. The # alternative to the currently used heuristic would be to # hardcode a list of commands that provide a channel argument. ch, status = privmsg_channel_name(@params.first) if ch.nil? && numeric_reply? && @params.size > 1 ch, status = privmsg_channel_name(@params[1]) end return @bot.channel_list.find_ensured(ch), status if ch end end
# File lib/cinch/message.rb, line 377 def parse_ctcp_args # has to be called after parse_ctcp_message return unless ctcp? @ctcp_message.split(" ")[1..-1] end
# File lib/cinch/message.rb, line 370 def parse_ctcp_command # has to be called after parse_ctcp_message return unless ctcp? @ctcp_message.split(" ").first end
# File lib/cinch/message.rb, line 362 def parse_ctcp_message # has to be called after parse_params return unless ctcp? @params.last =~ /\001(.+)\001/ Regexp.last_match(1) end
# File lib/cinch/message.rb, line 349 def parse_error return @command.to_i if numeric_reply? && @command[/[45]\d\d/] end
# File lib/cinch/message.rb, line 353 def parse_message # has to be called after parse_params if error? @error.to_s elsif regular_command? @params.last end end
# File lib/cinch/message.rb, line 257 def parse_params(raw_params) params = [] if match = raw_params.match(/(?:^:| :)(.*)$/) params = match.pre_match.split(" ") params << match[1] else params = raw_params.split(" ") end params end
# File lib/cinch/message.rb, line 342 def parse_server return unless @prefix return if @prefix =~ /[@!]/ @prefix[/^(\S+)/, 1] end
# File lib/cinch/message.rb, line 296 def parse_user return unless @prefix nick = @prefix[/^(\S+)!/, 1] user = @prefix[/^\S+!(\S+)@/, 1] host = @prefix[/@(\S+)$/, 1] return nil if nick.nil? @bot.user_list.find_ensured(user, nick, host) end
# File lib/cinch/message.rb, line 331 def privmsg_channel_name(s) chantypes = @bot.irc.isupport["CHANTYPES"] statusmsg = @bot.irc.isupport["STATUSMSG"] if statusmsg.include?(s[0]) && chantypes.include?(s[1]) status = @bot.irc.isupport["PREFIX"].invert[s[0]] [s[1..-1], status] elsif chantypes.include?(s[0]) [s, nil] end end
# File lib/cinch/message.rb, line 253 def regular_command? !numeric_reply? # a command can only be numeric or "regular"⦠end
# File lib/cinch/message.rb, line 246 def reply_target return @target if @channel.nil? || @statusmsg_mode.nil? prefix = @bot.irc.isupport["PREFIX"][@statusmsg_mode] Target.new(prefix + @channel.name, @bot) end
# File lib/cinch/message.rb, line 272 def to_symbol(string) string.tr("-", "_").downcase.to_sym end