+#-- vim:sw=2:et
+#++
+#
+# :title: IRC message datastructures
+
module Irc
- BotConfig.register BotConfigArrayValue.new('core.address_prefix',
- :default => [], :wizard => true,
- :desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
- )
- BotConfig.register BotConfigBooleanValue.new('core.reply_with_nick',
- :default => false, :wizard => true,
- :desc => "if true, the bot will prepend the nick to what he has to say when replying (e.g. 'markey: you can't do that!')"
- )
- BotConfig.register BotConfigStringValue.new('core.nick_postfix',
- :default => ':', :wizard => true,
- :desc => "when replying with nick put this character after the nick of the user the bot is replying to"
- )
+ class Bot
+ module Config
+ Config.register ArrayValue.new('core.address_prefix',
+ :default => [], :wizard => true,
+ :desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
+ )
+
+ Config.register BooleanValue.new('core.reply_with_nick',
+ :default => false, :wizard => true,
+ :desc => "if true, the bot will prepend the nick to what he has to say when replying (e.g. 'markey: you can't do that!')"
+ )
+
+ Config.register StringValue.new('core.nick_postfix',
+ :default => ':', :wizard => true,
+ :desc => "when replying with nick put this character after the nick of the user the bot is replying to"
+ )
+ end
+ end
+
# Define standard IRC attriubtes (not so standard actually,
# but the closest thing we have ...)
Reverse = "\026"
Italic = "\011"
NormalText = "\017"
+ AttributeRx = /#{Bold}|#{Underline}|#{Reverse}|#{Italic}|#{NormalText}/
# Color is prefixed by \003 and followed by optional
# foreground and background specifications, two-digits-max
# Convert a String or Symbol into a color number
def Irc.find_color(data)
- if Integer === data
+ "%02d" % if Integer === data
data
else
f = if String === data
def Irc.color(fg=nil,bg=nil)
str = Color.dup
if fg
- str << Irc.find_color(fg).to_s
+ str << Irc.find_color(fg)
end
if bg
- str << "," << Irc.find_color(bg).to_s
+ str << "," << Irc.find_color(bg)
end
return str
end
# contents of the message
attr_accessor :message
+ # contents of the message (for logging purposes)
+ attr_accessor :logmessage
+
# has the message been replied to/handled by a plugin?
attr_accessor :replied
+ # should the message be ignored?
+ attr_accessor :ignored
+ alias :ignored? :ignored
+
+ # set this to true if the method that delegates the message is run in a thread
+ attr_accessor :in_thread
+ alias :in_thread? :in_thread
+
# instantiate a new Message
# bot:: associated bot class
# server:: Server where the message took place
@message = BasicUserMessage.stripcolour message
@replied = false
@server = server
+ @ignored = false
+ @in_thread = false
@identified = false
if @msg_wants_id && @server.capabilities[:"identify-msg"]
warning "Message does not have identification"
end
end
+ @logmessage = @message.dup
if target && target == @bot.myself
@address = true
"#{@source.user}@#{@source.host}" rescue @source.to_s
end
+ # Access the botuser corresponding to the source, if any
+ #
+ def botuser
+ source.botuser rescue @bot.auth.everyone
+ end
+
+
# Was the message from an identified user?
def identified?
return @identified
end
+ # class for handling welcome messages from the server
+ class WelcomeMessage < BasicUserMessage
+ end
+
+ # class for handling MOTD from the server. Yes, MotdMessage
+ # is somewhat redundant, but it fits with the naming scheme
+ class MotdMessage < BasicUserMessage
+ end
+
# class for handling IRC user messages. Includes some utilities for handling
# the message, for example in plugins.
# The +message+ member will have any bot addressing "^bot: " removed
@address = true
end
- if(@message =~ /^\001(\S+)\s(.+)\001/)
+ if(@message =~ /^\001(\S+)(\s(.+))?\001/)
@ctcp = $1
- @message = $2
+ # FIXME need to support quoting of NULL and CR/LF, see
+ # http://www.irchelp.org/irchelp/rfc/ctcpspec.html
+ @message = $3 || String.new
@action = @ctcp == 'ACTION'
debug "Received CTCP command #{@ctcp} with options #{@message} (action? #{@action})"
+ @logmessage = @message.dup
end
# free splitting for plugins
# the nick or core.reply_with_nick is set to false
#
def reply(string, options={})
- if @bot.config['core.reply_with_nick'] and not string =~ /\b#{@source}\b/
+ if @bot.config['core.reply_with_nick'] and not string =~ /(?:^|\W)#{Regexp.escape(@source.to_s)}(?:$|\W)/
return nickreply(string, options)
end
plainreply(string, options)
@replied = true
end
- # send a CTCP response, i.e. a private notice to the sender
- def ctcp_reply(command, string, options={})
- @bot.ctcp_notice @source, command, string, options
+ # send a CTCP response, i.e. a private NOTICE to the sender
+ # with the same CTCP command and the reply as a parameter
+ def ctcp_reply(string, options={})
+ @bot.ctcp_notice @source, @ctcp, string, options
end
# convenience method to reply "okay" in the current language to the
plainokay
end
+ # send a NOTICE to the message source
+ #
+ def notify(msg,opts={})
+ @bot.notice(sourcenick, msg, opts)
+ end
+
end
# class to manage IRC PRIVMSGs
end
end
+ # class to manage IRC INVITEs
+ # +address?+ can be used as a shortcut to see if the bot was invited,
+ # which should be true except for server bugs
+ class InviteMessage < BasicUserMessage
+ # channel user was invited to
+ attr_reader :channel
+
+ def initialize(bot, server, source, target, channel, message="")
+ super(bot, server, source, target, message)
+ @channel = channel
+ end
+ end
+
# class to pass IRC Nick changes in. @message contains the old nickame,
# @sourcenick contains the new one.
class NickMessage < BasicUserMessage
+ attr_accessor :is_on
def initialize(bot, server, source, oldnick, newnick)
super(bot, server, source, oldnick, newnick)
+ @is_on = []
end
def oldnick
end
end
+ # class to manage mode changes
+ class ModeChangeMessage < BasicUserMessage
+ attr_accessor :modes
+ def initialize(bot, server, source, target, message="")
+ super(bot, server, source, target, message)
+ @address = (source == @bot.myself)
+ @modes = []
+ end
+ end
+
+ # class to manage NAME replies
+ class NamesMessage < BasicUserMessage
+ attr_accessor :users
+ def initialize(bot, server, source, target, message="")
+ super(bot, server, source, target, message)
+ @users = []
+ end
+ end
+
class QuitMessage < BasicUserMessage
+ attr_accessor :was_on
def initialize(bot, server, source, target, message="")
super(bot, server, source, target, message)
+ @was_on = []
end
end
# topic set on channel
attr_reader :channel
+ # :info if topic info, :set if topic set
+ attr_accessor :info_or_set
def initialize(bot, server, source, channel, topic=ChannelTopic.new)
super(bot, server, source, channel, topic.text)
@topic = topic
@timestamp = topic.set_on
@channel = channel
+ @info_or_set = nil
end
end
# same as a join, but can have a message too
class PartMessage < JoinMessage
end
+
+ class UnknownMessage < BasicUserMessage
+ end
end