]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/plugins.rb
+ @bot.path and datafile methods
[user/henk/code/ruby/rbot.git] / lib / rbot / plugins.rb
index 9277d1838334d6262ad8cd77952f8dcbc4333125..9d5523e423c9f2a562e588666d1d46787d96a825 100644 (file)
@@ -96,6 +96,10 @@ module Plugins
   unreplied(PrivMessage)::
                          Called for a PRIVMSG which has not been replied to.
 
+  notice(NoticeMessage)::
+                         Called for all Notices. Please notice that in general
+                         should not be replied to.
+
   kick(KickMessage)::
                          Called when a user (or the bot) is kicked from a
                          channel the bot is in.
@@ -114,10 +118,20 @@ module Plugins
 
   nick(NickMessage)::
                          Called when a user (or the bot) changes Nick
+  modechange(ModeChangeMessage)::
+                         Called when a User or Channel mode is changed
   topic(TopicMessage)::
                          Called when a user (or the bot) changes a channel
                          topic
 
+  welcome(WelcomeMessage)::
+                         Called when the welcome message is received on
+                         joining a server succesfully.
+
+  motd(MotdMessage)::
+                         Called when the Message Of The Day is fully
+                         recevied from the server.
+
   connect::              Called when a server is joined successfully, but
                          before autojoin channels are joined (no params)
 
@@ -165,6 +179,7 @@ module Plugins
     def initialize
       @manager = Plugins::manager
       @bot = @manager.bot
+      @priority = nil
 
       @botmodule_triggers = Array.new
 
@@ -216,7 +231,7 @@ module Plugins
     # Signal to other BotModules that an even happened.
     #
     def call_event(ev, *args)
-      @bot.plugins.delegate('event_' + ev.to_s.gsub(/[^\w\?!]+/, '_'), *args)
+      @bot.plugins.delegate('event_' + ev.to_s.gsub(/[^\w\?!]+/, '_'), *(args.push Hash.new))
     end
 
     # call-seq: map(template, options)
@@ -334,6 +349,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.
@@ -519,11 +548,13 @@ module Plugins
       # the idea here is to prevent namespace pollution. perhaps there
       # is another way?
       plugin_module = Module.new
+      # each plugin uses its own textdomain, we bind it automatically here
+      bindtextdomain_to(plugin_module, "rbot-#{File.basename(fname, '.rb')}")
 
       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
@@ -790,15 +821,56 @@ module Plugins
       end
     end
 
-    # see if each plugin handles +method+, and if so, call it, passing
-    # +message+ as a parameter
+    # call-seq: delegate</span><span class="method-args">(method, m, opts={})</span>
+    # <span class="method-name">delegate</span><span class="method-args">(method, opts={})
+    #
+    # see if each plugin handles _method_, and if so, call it, passing
+    # _m_ as a parameter (if present). BotModules are called in order of
+    # priority from lowest to highest.
+    #
+    # If the passed _m_ is a BasicUserMessage and is marked as #ignored?, it
+    # will only be delegated to plugins with negative priority. Conversely, if
+    # it's a fake message (see BotModule#fake_message), it will only be
+    # delegated to plugins with positive priority.
+    #
+    # Note that _m_ can also be an exploded Array, but in this case the last
+    # element of it cannot be a Hash, or it will be interpreted as the options
+    # Hash for delegate itself. The last element can be a subclass of a Hash, though.
+    # To be on the safe side, you can add an empty Hash as last parameter for delegate
+    # when calling it with an exploded Array:
+    #   @bot.plugins.delegate(method, *(args.push Hash.new))
+    #
+    # Currently supported options are the following:
+    # :above ::
+    #   if specified, the delegation will only consider plugins with a priority
+    #   higher than the specified value
+    # :below ::
+    #   if specified, the delegation will only consider plugins with a priority
+    #   lower than the specified value
+    #
     def delegate(method, *args)
       # if the priorities order of the delegate list is dirty,
       # meaning some modules have been added or priorities have been
       # changed, then the delegate list will need to be sorted before
       # delegation.  This should always be true for the first delegation.
       sort_modules unless @sorted_modules
-        
+
+      opts = {}
+      opts.merge(args.pop) if args.last.class == Hash
+
+      m = args.first
+      if BasicUserMessage === m
+        # ignored messages should not be delegated
+        # to plugins with positive priority
+        opts[:below] ||= 0 if m.ignored?
+        # fake messages should not be delegated
+        # to plugins with negative priority
+        opts[:above] ||= 0 if m.recurse_depth > 0
+      end
+
+      above = opts[:above]
+      below = opts[:below]
+
       # debug "Delegating #{method.inspect}"
       ret = Array.new
       if method.match(DEFAULT_DELEGATE_PATTERNS)
@@ -808,7 +880,10 @@ module Plugins
         return [] unless @delegate_list.has_key?(m)
         @delegate_list[m].each { |p|
           begin
-            ret.push p.send(method, *args)
+            prio = p.priority
+            unless (above and above >= prio) or (below and below <= prio)
+              ret.push p.send(method, *args)
+            end
           rescue Exception => err
             raise if err.kind_of?(SystemExit)
             error report_error("#{p.botmodule_class} #{p.name} #{method}() failed:", err)
@@ -821,7 +896,10 @@ module Plugins
           if(p.respond_to? method)
             begin
               # debug "#{p.botmodule_class} #{p.name} responds"
-              ret.push p.send(method, *args)
+              prio = p.priority
+              unless (above and above >= prio) or (below and below <= prio)
+                ret.push p.send(method, *args)
+              end
             rescue Exception => err
               raise if err.kind_of?(SystemExit)
               error report_error("#{p.botmodule_class} #{p.name} #{method}() failed:", err)
@@ -879,7 +957,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)