]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/plugins.rb
* less eager quit message reset
[user/henk/code/ruby/rbot.git] / lib / rbot / plugins.rb
index 5c5cdddc99416709ebabba65aff755625e2112e8..9a41610f6e4961b9fb6de8431e80b8674d8d6cfd 100644 (file)
@@ -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'
 
@@ -338,6 +341,15 @@ module Plugins
     # 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
 
@@ -561,6 +573,7 @@ module Plugins
         return :loaded
       rescue Exception => err
         # rescue TimeoutError, StandardError, NameError, LoadError, SyntaxError => err
+        raise if err.kind_of? DBFatal
         error report_error("#{desc}#{fname} load failed", err)
         bt = err.backtrace.select { |line|
           line.match(/^(\(eval\)|#{fname}):\d+/)
@@ -570,10 +583,27 @@ module Plugins
             "#{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 => err_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 err_in_err
+          end
+        end
         newerr.set_backtrace(bt)
         return newerr
       end
@@ -600,28 +630,39 @@ module Plugins
       debug "Core module and plugin loading paths cleared"
     end
 
-    # load plugins from pre-assigned list of directories
-    def scan
-      @failed.clear
-      @ignored.clear
-      @delegate_list.clear
-
+    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 = @core_module_dirs + @plugin_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
@@ -635,20 +676,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|
@@ -893,7 +942,7 @@ module Plugins
           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)
+            raise if err.kind_of?(DBFatal)
           end
         }
       else
@@ -909,7 +958,7 @@ module Plugins
             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)
+              raise if err.kind_of?(DBFatal)
             end
           end
         }
@@ -939,7 +988,7 @@ module Plugins
             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)
+              raise if err.kind_of?(DBFatal)
             end
             debug "Successfully delegated #{m.inspect}"
             return true