Config.register Config::ArrayValue.new('plugins.blacklist',
:default => [], :wizard => false, :requires_rescan => true,
:desc => "Plugins that should not be loaded")
+ Config.register Config::ArrayValue.new('plugins.whitelist',
+ :default => [], :wizard => false, :requires_rescan => true,
+ :desc => "Only whitelisted plugins will be loaded unless the list is empty")
module Plugins
require 'rbot/messagemapper'
@botmodule_triggers = Array.new
@handler = MessageMapper.new(self)
- @registry = Registry::Accessor.new(@bot, self.class.to_s.gsub(/^.*::/, ""))
+ @registry = @bot.registry_factory.create(@bot.path, self.class.to_s.gsub(/^.*::/, ''))
@manager.add_botmodule(self)
if self.respond_to?('set_language')
@priority ||= 1
end
- # Returns the symbol :BotModule
+ # Returns the symbol :BotModule
def botmodule_class
:BotModule
end
#
# This command is now superceded by the #map() command, which should be used
# instead whenever possible.
- #
+ #
def register(cmd, opts={})
raise ArgumentError, "Second argument must be a hash!" unless opts.kind_of?(Hash)
who = @manager.who_handles?(cmd)
# MessageMapper uses 'usage' as its default fallback method.
#
def usage(m, params = {})
+ if params[:failures].respond_to? :find
+ friendly = params[:failures].find do |f|
+ f.kind_of? MessageMapper::FriendlyFailure
+ end
+ if friendly
+ m.reply friendly.friendly
+ return
+ end
+ end
m.reply(_("incorrect usage, ask for help using '%{command}'") % {:command => "#{@bot.nick}: help #{m.plugin}"})
end
- # Define the priority of the module. During event delegation, lower
+ # Define the priority of the module. During event delegation, lower
# priority modules will be called first. Default priority is 1
def priority=(prio)
if @priority != prio
h[k] = Array.new
}
- @dirs = []
+ @core_module_dirs = []
+ @plugin_dirs = []
@failed = Array.new
@ignored = Array.new
"#{fname}#{$1}#{$3}"
}
}
- msg = err.to_str.gsub(/^\(eval\)(:\d+)(:in `.*')?(:.*)?/) { |m|
+ msg = err.to_s.gsub(/^\(eval\)(:\d+)(:in `.*')?(:.*)?/) { |m|
"#{fname}#{$1}#{$3}"
}
- newerr = err.class.new(msg)
+ begin
+ newerr = err.class.new(msg)
+ rescue ArgumentError => aerr_in_err
+ # Somebody should hang the ActiveSupport developers by their balls
+ # with barbed wire. Their MissingSourceFile extension to LoadError
+ # _expects_ a second argument, breaking the usual Exception interface
+ # (instead, the smart thing to do would have been to make the second
+ # parameter optional and run the code in the from_message method if
+ # it was missing).
+ # Anyway, we try to cope with this in the simplest possible way. On
+ # the upside, this new block can be extended to handle other similar
+ # idiotic approaches
+ if err.class.respond_to? :from_message
+ newerr = err.class.from_message(msg)
+ else
+ raise aerr_in_err
+ end
+ rescue NoMethodError => nmerr_in_err
+ # Another braindead extension to StandardError, OAuth2::Error,
+ # doesn't get a string as message, but a response
+ if err.respond_to? :response
+ newerr = err.class.new(err.response)
+ else
+ raise nmerr_in_err
+ end
+ end
newerr.set_backtrace(bt)
return newerr
end
private :load_botmodule_file
# add one or more directories to the list of directories to
- # load botmodules from
- #
- # TODO find a way to specify necessary plugins which _must_ be loaded
- #
- def add_botmodule_dir(*dirlist)
- @dirs += dirlist
- debug "Botmodule loading path: #{@dirs.join(', ')}"
+ # load core modules from
+ def add_core_module_dir(*dirlist)
+ @core_module_dirs += dirlist
+ debug "Core module loading paths: #{@core_module_dirs.join(', ')}"
end
- def clear_botmodule_dirs
- @dirs.clear
- debug "Botmodule loading path cleared"
+ # add one or more directories to the list of directories to
+ # load plugins from
+ def add_plugin_dir(*dirlist)
+ @plugin_dirs += dirlist
+ debug "Plugin loading paths: #{@plugin_dirs.join(', ')}"
end
- # load plugins from pre-assigned list of directories
- def scan
- @failed.clear
- @ignored.clear
- @delegate_list.clear
+ def clear_botmodule_dirs
+ @core_module_dirs.clear
+ @plugin_dirs.clear
+ debug "Core module and plugin loading paths cleared"
+ end
+ def scan_botmodules(opts={})
+ type = opts[:type]
processed = Hash.new
- @bot.config['plugins.blacklist'].each { |p|
- pn = p + ".rb"
- processed[pn.intern] = :blacklisted
- }
+ case type
+ when :core
+ dirs = @core_module_dirs
+ when :plugins
+ dirs = @plugin_dirs
- dirs = @dirs
- dirs.each {|dir|
- if(FileTest.directory?(dir))
- d = Dir.new(dir)
- d.sort.each {|file|
+ @bot.config['plugins.blacklist'].each { |p|
+ pn = p + ".rb"
+ processed[pn.intern] = :blacklisted
+ }
- next if(file =~ /^\./)
+ whitelist = @bot.config['plugins.whitelist'].map { |p|
+ p + ".rb"
+ }
+ end
- if processed.has_key?(file.intern)
+ dirs.each do |dir|
+ next unless FileTest.directory?(dir)
+ d = Dir.new(dir)
+ d.sort.each do |file|
+ next unless file =~ /\.rb$/
+ next if file =~ /^\./
+
+ case type
+ when :plugins
+ if !whitelist.empty? && !whitelist.include?(file)
+ @ignored << {:name => file, :dir => dir, :reason => :"not whitelisted" }
+ next
+ elsif processed.has_key?(file.intern)
@ignored << {:name => file, :dir => dir, :reason => processed[file.intern]}
next
end
@ignored << {:name => $1, :dir => dir, :reason => processed[$1.intern]}
next
end
+ end
- next unless(file =~ /\.rb$/)
-
+ begin
did_it = load_botmodule_file("#{dir}/#{file}", "plugin")
- case did_it
- when Symbol
- processed[file.intern] = did_it
- when Exception
- @failed << { :name => file, :dir => dir, :reason => did_it }
- end
+ rescue Exception => e
+ error e
+ did_it = e
+ end
- }
+ case did_it
+ when Symbol
+ processed[file.intern] = did_it
+ when Exception
+ @failed << { :name => file, :dir => dir, :reason => did_it }
+ end
end
- }
+ end
+ end
+
+ # load plugins from pre-assigned list of directories
+ def scan
+ @failed.clear
+ @ignored.clear
+ @delegate_list.clear
+
+ scan_botmodules(:type => :core)
+ scan_botmodules(:type => :plugins)
+
debug "finished loading plugins: #{status(true)}"
(core_modules + plugins).each { |p|
p.methods.grep(DEFAULT_DELEGATE_PATTERNS).each { |m|
end
def sort_modules
- @sorted_modules = (core_modules + plugins).sort do |a, b|
+ @sorted_modules = (core_modules + plugins).sort do |a, b|
a.priority <=> b.priority
end || []
rescue Exception => err
raise if err.kind_of?(SystemExit)
error report_error("#{p.botmodule_class} #{p.name} #{method}() failed:", err)
- raise if err.kind_of?(BDB::Fatal)
end
}
else
rescue Exception => err
raise if err.kind_of?(SystemExit)
error report_error("#{p.botmodule_class} #{p.name} #{method}() failed:", err)
- raise if err.kind_of?(BDB::Fatal)
end
end
}
rescue Exception => err
raise if err.kind_of?(SystemExit)
error report_error("#{p.botmodule_class} #{p.name} privmsg() failed:", err)
- raise if err.kind_of?(BDB::Fatal)
end
debug "Successfully delegated #{m.inspect}"
return true