2 BotConfig.register BotConfigArrayValue.new('core.address_prefix',
3 :default => [], :wizard => true,
4 :desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
12 # base user message class, all user messages derive from this
13 # (a user message is defined as having a source hostmask, a target
14 # nick/channel and a message part)
15 class BasicUserMessage
23 # when the message was received
26 # User that originated the message
29 # User/Channel message was sent to
32 # contents of the message
33 attr_accessor :message
35 # has the message been replied to/handled by a plugin?
36 attr_accessor :replied
38 # instantiate a new Message
39 # bot:: associated bot class
40 # server:: Server where the message took place
41 # source:: User that sent the message
42 # target:: User/Channel is destined for
43 # message:: actual message
44 def initialize(bot, server, source, target, message)
45 @msg_wants_id = false unless defined? @msg_wants_id
52 @message = BasicUserMessage.stripcolour message
57 if @msg_wants_id && @server.capabilities["identify-msg".to_sym]
58 if @message =~ /([-+])(.*)/
59 @identified = ($1=="+")
62 warning "Message does not have identification"
66 if target && target == @bot.myself
72 # Access the nick of the source
78 # Access the user@host of the source
81 "#{@source.user}@#{@source.host}"
84 # Was the message from an identified user?
89 # returns true if the message was addressed to the bot.
90 # This includes any private message to the bot, or any public message
91 # which looks like it's addressed to the bot, e.g. "bot: foo", "bot, foo",
92 # a kick message when bot was kicked etc.
97 # has this message been replied to by a plugin?
102 # strip mIRC colour escapes from a string
103 def BasicUserMessage.stripcolour(string)
104 return "" unless string
105 ret = string.gsub(/\cC\d\d?(?:,\d\d?)?/, "")
106 #ret.tr!("\x00-\x1f", "")
112 # class for handling IRC user messages. Includes some utilities for handling
113 # the message, for example in plugins.
114 # The +message+ member will have any bot addressing "^bot: " removed
115 # (address? will return true in this case)
116 class UserMessage < BasicUserMessage
118 # for plugin messages, the name of the plugin invoked by the message
121 # for plugin messages, the rest of the message, with the plugin name
125 # convenience member. Who to reply to (i.e. would be sourcenick for a
126 # privately addressed message, or target (the channel) for a publicly
130 # channel the message was in, nil for privately addressed messages
133 # for PRIVMSGs, true if the message was a CTCP ACTION (CTCP stuff
134 # will be stripped from the message)
137 # instantiate a new UserMessage
138 # bot:: associated bot class
139 # source:: hostmask of the message source
140 # target:: nick/channel message is destined for
141 # message:: message part
142 def initialize(bot, server, source, target, message)
143 super(bot, server, source, target, message)
149 if target == @bot.myself
159 # check for option extra addressing prefixes, e.g "|search foo", or
160 # "!version" - first match wins
161 bot.config['core.address_prefix'].each {|mprefix|
162 if @message.gsub!(/^#{Regexp.escape(mprefix)}\s*/, "")
168 # even if they used above prefixes, we allow for silly people who
169 # combine all possible types, e.g. "|rbot: hello", or
170 # "/msg rbot rbot: hello", etc
171 if @message.gsub!(/^\s*#{Regexp.escape(bot.nick)}\s*([:;,>]|\s)\s*/i, "")
175 if(@message =~ /^\001ACTION\s(.+)\001/)
180 # free splitting for plugins
181 @params = @message.dup
182 if @params.gsub!(/^\s*(\S+)[\s$]*/, "")
183 @plugin = $1.downcase
184 @params = nil unless @params.length > 0
188 # returns true for private messages, e.g. "/msg bot hello"
193 # returns true if the message was in a channel
202 # convenience method to reply to a message, useful in plugins. It's the
204 # <tt>@bot.say m.replyto, string</tt>
205 # So if the message is private, it will reply to the user. If it was
206 # in a channel, it will reply in the channel.
208 @bot.say @replyto, string
212 # convenience method to reply to a message with an action. It's the
214 # <tt>@bot.action m.replyto, string</tt>
215 # So if the message is private, it will reply to the user. If it was
216 # in a channel, it will reply in the channel.
218 @bot.action @replyto, string
222 # convenience method to reply "okay" in the current language to the
225 @bot.say @replyto, @bot.lang.get("okay")
230 # class to manage IRC PRIVMSGs
231 class PrivMessage < UserMessage
232 def initialize(bot, server, source, target, message)
238 # class to manage IRC NOTICEs
239 class NoticeMessage < UserMessage
240 def initialize(bot, server, source, target, message)
246 # class to manage IRC KICKs
247 # +address?+ can be used as a shortcut to see if the bot was kicked,
248 # basically, +target+ was kicked from +channel+ by +source+ with +message+
249 class KickMessage < BasicUserMessage
250 # channel user was kicked from
253 def initialize(bot, server, source, target, channel, message="")
254 super(bot, server, source, target, message)
259 # class to pass IRC Nick changes in. @message contains the old nickame,
260 # @sourcenick contains the new one.
261 class NickMessage < BasicUserMessage
262 def initialize(bot, server, source, oldnick, newnick)
263 super(bot, server, source, oldnick, newnick)
275 class QuitMessage < BasicUserMessage
276 def initialize(bot, server, source, target, message="")
277 super(bot, server, source, target, message)
281 class TopicMessage < BasicUserMessage
284 # topic set at (unixtime)
285 attr_reader :timestamp
286 # topic set on channel
289 def initialize(bot, server, source, channel, topic=ChannelTopic.new)
290 super(bot, server, source, channel, topic.text)
292 @timestamp = topic.set_on
297 # class to manage channel joins
298 class JoinMessage < BasicUserMessage
301 def initialize(bot, server, source, channel, message="")
302 super(bot, server, source, channel, message)
304 # in this case sourcenick is the nick that could be the bot
305 @address = (source == @bot.myself)
309 # class to manage channel parts
310 # same as a join, but can have a message too
311 class PartMessage < JoinMessage