myself.nick
end
+ # nick wanted by the bot. This defaults to the irc.nick config value,
+ # but may be overridden by a manual !nick command
+ def wanted_nick
+ @wanted_nick || config['irc.nick']
+ end
+
+ # set the nick wanted by the bot
+ def wanted_nick=(wn)
+ if wn.nil? or wn.to_s.downcase == config['irc.nick'].downcase
+ @wanted_nick = nil
+ else
+ @wanted_nick = wn.to_s.dup
+ end
+ end
+
+
# bot inspection
# TODO multiserver
def inspect
Config.register Config::IntegerValue.new('server.reconnect_wait',
:default => 5, :validate => Proc.new{|v| v >= 0},
:desc => "Seconds to wait before attempting to reconnect, on disconnect")
- Config.register Config::FloatValue.new('server.sendq_delay',
- :default => 2.0, :validate => Proc.new{|v| v >= 0},
- :desc => "(flood prevention) the delay between sending messages to the server (in seconds)",
- :on_change => Proc.new {|bot, v| bot.socket.sendq_delay = v })
- Config.register Config::IntegerValue.new('server.sendq_burst',
- :default => 4, :validate => Proc.new{|v| v >= 0},
- :desc => "(flood prevention) max lines to burst to the server before throttling. Most ircd's allow bursts of up 5 lines",
- :on_change => Proc.new {|bot, v| bot.socket.sendq_burst = v })
Config.register Config::IntegerValue.new('server.ping_timeout',
:default => 30, :validate => Proc.new{|v| v >= 0},
:desc => "reconnect if server doesn't respond to PING within this many seconds (set to 0 to disable)")
+ Config.register Config::ArrayValue.new('server.nocolor_modes',
+ :default => ['c'], :wizard => false,
+ :requires_restart => false,
+ :desc => "List of channel modes that require messages to be without colors")
Config.register Config::StringValue.new('irc.nick', :default => "rbot",
:desc => "IRC nickname the bot should attempt to use", :wizard => true,
botclass = File.expand_path(botclass)
@botclass = botclass.gsub(/\/$/, "")
- unless FileTest.directory? botclass
+ if FileTest.directory? botclass
+ # compare the templates dir with the current botclass, and fill it in with
+ # any missing file.
+ # Sadly, FileUtils.cp_r doesn't have an :update option, so we have to do it
+ # manually
+ template = File.join Config::datadir, 'templates'
+ # note that we use the */** pattern because we don't want to match
+ # keywords.rbot, which gets deleted on load and would therefore be missing always
+ missing = Dir.chdir(template) { Dir.glob('*/**') } - Dir.chdir(botclass) { Dir.glob('*/**') }
+ missing.map do |f|
+ dest = File.join(botclass, f)
+ FileUtils.mkdir_p File.dirname dest
+ FileUtils.cp File.join(template, f), dest
+ end
+ else
log "no #{botclass} directory found, creating from templates.."
if FileTest.exist? botclass
error "file #{botclass} exists but isn't a directory"
debug "server.list is now #{@config['server.list'].inspect}"
end
- @socket = Irc::Socket.new(@config['server.list'], @config['server.bindhost'], @config['server.sendq_delay'], @config['server.sendq_burst'], :ssl => @config['server.ssl'])
+ @socket = Irc::Socket.new(@config['server.list'], @config['server.bindhost'], :ssl => @config['server.ssl'])
@client = Client.new
@plugins.scan
#
@quiet = Set.new
+ # the nick we want, if it's different from the irc.nick config value
+ # (e.g. as set by a !nick command)
+ @wanted_nick = nil
+
@client[:welcome] = proc {|data|
m = WelcomeMessage.new(self, server, data[:source], data[:target], data[:message])
@plugins.delegate("welcome", m)
@plugins.delegate("connect")
-
- @config['irc.join_channels'].each { |c|
- debug "autojoining channel #{c}"
- if(c =~ /^(\S+)\s+(\S+)$/i)
- join $1, $2
- else
- join c if(c)
- end
- }
}
# TODO the next two @client should go into rfc2812.rb, probably
}
@client[:privmsg] = proc { |data|
- m = PrivMessage.new(self, server, data[:source], data[:target], data[:message])
+ m = PrivMessage.new(self, server, data[:source], data[:target], data[:message], :handle_id => true)
# debug "Message source is #{data[:source].inspect}"
# debug "Message target is #{data[:target].inspect}"
# debug "Bot is #{myself.inspect}"
@plugins.irc_delegate('privmsg', m)
}
@client[:notice] = proc { |data|
- message = NoticeMessage.new(self, server, data[:source], data[:target], data[:message])
+ message = NoticeMessage.new(self, server, data[:source], data[:target], data[:message], :handle_id => true)
# pass it off to plugins that want to hear everything
@plugins.irc_delegate "notice", message
}
m.modes = data[:modes]
@plugins.delegate "modechange", m
}
+ @client[:whois] = proc {|data|
+ source = data[:source]
+ target = server.get_user(data[:whois][:nick])
+ m = WhoisMessage.new(self, server, source, target, data[:whois])
+ @plugins.delegate "whois", m
+ }
@client[:join] = proc {|data|
m = JoinMessage.new(self, server, data[:source], data[:channel], data[:message])
+ sendq("MODE #{data[:channel]}", nil, 0) if m.address?
@plugins.irc_delegate("join", m)
sendq("WHO #{data[:channel]}", data[:channel], 2) if m.address?
}
end
multi_line = original_message.to_s.gsub(/[\r\n]+/, "\n")
+
+ # if target is a channel with nocolor modes, strip colours
+ if where.kind_of?(Channel) and where.mode.any?(*config['server.nocolor_modes'])
+ multi_line.replace BasicUserMessage.strip_formatting(multi_line)
+ end
+
messages = Array.new
case opts[:newlines]
when :join
end
# set topic of channel +where+ to +topic+
- def topic(where, topic)
- sendq "TOPIC #{where} :#{topic}", where, 2
+ # can also be used to retrieve the topic of channel +where+
+ # by omitting the last argument
+ def topic(where, topic=nil)
+ if topic.nil?
+ sendq "TOPIC #{where}", where, 2
+ else
+ sendq "TOPIC #{where} :#{topic}", where, 2
+ end
end
def disconnect(message=nil)
end
# changing mode
- def mode(channel, mode, target)
+ def mode(channel, mode, target=nil)
sendq "MODE #{channel} #{mode} #{target}", channel, 2
end
+ # asking whois
+ def whois(nick, target=nil)
+ sendq "WHOIS #{target} #{nick}", nil, 0
+ end
+
# kicking a user
def kick(channel, user, msg)
sendq "KICK #{channel} #{user} :#{msg}", channel, 2