X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fplugins.rb;h=e7905c505ad35dc4977b31ee24f8421eb11e67a8;hb=dd1b52cacce13c8c66d210215c3cfe38356e67cf;hp=d1bf073ac0e12132b1c9beeeb46959c56acb7d59;hpb=caffbfa94b84569fb64ed6ecb68f9ca960deca2a;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/plugins.rb b/lib/rbot/plugins.rb index d1bf073a..e7905c50 100644 --- a/lib/rbot/plugins.rb +++ b/lib/rbot/plugins.rb @@ -10,6 +10,9 @@ class Bot 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' @@ -179,6 +182,7 @@ module Plugins def initialize @manager = Plugins::manager @bot = @manager.bot + @priority = nil @botmodule_triggers = Array.new @@ -197,7 +201,7 @@ module Plugins @priority ||= 1 end - # Returns the symbol :BotModule + # Returns the symbol :BotModule def botmodule_class :BotModule end @@ -317,7 +321,7 @@ module Plugins # # 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) @@ -340,7 +344,7 @@ module Plugins 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 @@ -348,6 +352,20 @@ module Plugins @bot.plugins.mark_priorities_dirty end end + + # Directory name to be joined to the botclass to access data files. By + # default this is the plugin name itself, but may be overridden, for + # example by plugins that share their datafiles or for backwards + # compatibilty + def dirname + name + end + + # Filename for a datafile built joining the botclass, plugin dirname and + # actual file name + def datafile(*fname) + @bot.path dirname, *fname + end end # A CoreBotModule is a BotModule that provides core functionality. @@ -409,7 +427,8 @@ module Plugins h[k] = Array.new } - @dirs = [] + @core_module_dirs = [] + @plugin_dirs = [] @failed = Array.new @ignored = Array.new @@ -539,7 +558,7 @@ module Plugins desc = desc.to_s + " " if desc begin - plugin_string = IO.readlines(fname).join("") + plugin_string = IO.read(fname) debug "loading #{desc}#{fname}" plugin_module.module_eval(plugin_string, fname) return :loaded @@ -565,42 +584,58 @@ module Plugins 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 @@ -614,20 +649,28 @@ module Plugins @ignored << {:name => $1, :dir => dir, :reason => processed[$1.intern]} next end + end - next unless(file =~ /\.rb$/) + 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 + end + end + end - 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 + # 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) - } - end - } debug "finished loading plugins: #{status(true)}" (core_modules + plugins).each { |p| p.methods.grep(DEFAULT_DELEGATE_PATTERNS).each { |m| @@ -797,7 +840,7 @@ module Plugins 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 || [] @@ -942,7 +985,7 @@ module Plugins if method.to_sym == :privmsg delegate('ctcp_listen', m) if m.ctcp delegate('message', m) - privmsg(m) if m.address? + privmsg(m) if m.address? and not m.ignored? delegate('unreplied', m) unless m.replied else delegate(method, m)