# File lib/rbot/plugins.rb, line 208
    def scan
      @failed = Array.new
      @ignored = Array.new
      processed = Hash.new

      @@bot.config['plugins.blacklist'].each { |p|
        pn = p + ".rb"
        processed[pn.intern] = :blacklisted
      }

      dirs = Array.new
      dirs << Config::datadir + "/plugins"
      dirs += @dirs
      dirs.reverse.each {|dir|
        if(FileTest.directory?(dir))
          d = Dir.new(dir)
          d.sort.each {|file|

            next if(file =~ /^\./)

            if processed.has_key?(file.intern)
              @ignored << {:name => file, :dir => dir, :reason => processed[file.intern]}
              next
            end

            if(file =~ /^(.+\.rb)\.disabled$/)
              # GB: Do we want to do this? This means that a disabled plugin in a directory
              #     will disable in all subsequent directories. This was probably meant
              #     to be used before plugins.blacklist was implemented, so I think
              #     we don't need this anymore
              processed[$1.intern] = :disabled
              @ignored << {:name => $1, :dir => dir, :reason => processed[$1.intern]}
              next
            end

            next unless(file =~ /\.rb$/)

            tmpfilename = "#{dir}/#{file}"

            # create a new, anonymous module to "house" the plugin
            # the idea here is to prevent namespace pollution. perhaps there
            # is another way?
            plugin_module = Module.new

            begin
              plugin_string = IO.readlines(tmpfilename).join("")
              debug "loading plugin #{tmpfilename}"
              plugin_module.module_eval(plugin_string, tmpfilename)
              processed[file.intern] = :loaded
            rescue Exception => err
              # rescue TimeoutError, StandardError, NameError, LoadError, SyntaxError => err
              warning "plugin #{tmpfilename} load failed\n" + err.inspect
              debug err.backtrace.join("\n")
              bt = err.backtrace.select { |line|
                line.match(/^(\(eval\)|#{tmpfilename}):\d+/)
              }
              bt.map! { |el|
                el.gsub(/^\(eval\)(:\d+)(:in `.*')?(:.*)?/) { |m|
                  "#{tmpfilename}#{$1}#{$3}"
                }
              }
              msg = err.to_str.gsub(/^\(eval\)(:\d+)(:in `.*')?(:.*)?/) { |m|
                "#{tmpfilename}#{$1}#{$3}"
              }
              newerr = err.class.new(msg)
              newerr.set_backtrace(bt)
              # debug "Simplified error: " << newerr.inspect
              # debug newerr.backtrace.join("\n")
              @failed << { :name => file, :dir => dir, :reason => newerr }
              # debug "Failures: #{@failed.inspect}"
            end
          }
        end
      }
    end