]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/alias.rb
lart plugin: replace "me" with sourcenick
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / alias.rb
index 900df2c4049d860baf67ce65295a77e68287a810..a587736ccff862eaeb21873b532ac35ed2c7e952 100644 (file)
@@ -29,6 +29,7 @@
 #   to detect and stop this, but a few recursive calls can still cause spamming
 
 require 'yaml'
+require 'set'
 
 class AliasPlugin < Plugin
   # an exception raised when loading or getting input of invalid alias definitions
@@ -42,12 +43,17 @@ class AliasPlugin < Plugin
     @data_path = "#{@bot.botclass}/alias/"
     @data_file = "#{@data_path}/aliases.yaml"
     # hash of alias => command entries
-    @aliases = if File.exist?(@data_file)
-                 YAML.load_file(@data_file)
-               else
-                 Hash.new
+    data = nil
+    aliases = if File.exist?(@data_file) &&
+                 (data = YAML.load_file(@data_file)) &&
+                 data.respond_to?(:each_pair)
+                data
+              else
+                warning _("Data file is not found or corrupt, reinitializing data")
+                Hash.new
                end
-    @aliases.each_pair do |a, c|
+    @aliases = Hash.new
+    aliases.each_pair do |a, c|
       begin
         add_alias(a, c)
       rescue AliasDefinitionError
@@ -58,8 +64,8 @@ class AliasPlugin < Plugin
   end 
 
   def save 
-    Dir.mkdir(@data_path) unless File.exist?(@data_path)
-    File.open(@data_file, 'w') {|f| f.write @aliases.to_yaml}
+    FileUtils.mkdir_p(@data_path)
+    Utils.safe_save(@data_file) {|f| f.write @aliases.to_yaml}
   end
 
   def cmd_add(m, params)
@@ -103,11 +109,17 @@ class AliasPlugin < Plugin
     # each alias is implemented by adding a message map, whose handler creates a message
     # containing the aliased command
 
-    command.grep(/<(\w+)>/) {$1}.all? {|s| text =~ /(?:^|\s)[:*]#{s}(?:\s|$)/ } or
-      raise AliasDefinitionError.new(_('Not all substitutions in command text have matching arguments in alias text'))
+    command.scan(/<(\w+)>/).flatten.to_set ==
+      text.split.grep(/\A[:*](\w+)\Z/) {$1}.to_set or
+      raise AliasDefinitionError.new(_('The arguments in alias must match the substitutions in command, and vice versa'))
     
+    begin
+      map text, :action => :"alias_handle<#{text}>", :auth_path => 'run'
+    rescue
+      raise AliasDefinitionError.new(_('Error mapping %{text} as command: %{error}') %
+                                     {:text => text, :error => $!})
+    end
     @aliases[text] = command
-    map text, :action => :"alias_handle<#{text}>", :auth_path => 'run'
   end
 
   def respond_to?(name, include_private=false)
@@ -116,6 +128,7 @@ class AliasPlugin < Plugin
 
   def method_missing(name, *args, &block)
     if name.to_s =~ /\Aalias_handle<(.+)>\Z/
+      text = $1
       m, params = args
       # messages created by alias handler will have a depth method, which returns the 
       # depth of "recursion" caused by the message
@@ -125,11 +138,11 @@ class AliasPlugin < Plugin
         return
       end
 
-      command = @aliases[$1]
+      command = @aliases[text]
       if command
         # create a fake message containing the intended command
         new_msg = PrivMessage.new(@bot, m.server, m.server.user(m.source), m.target,
-                                    command.gsub(/<(\w+)>/) {|arg| params[:"#{$1}"].to_s})
+                  command.gsub(/<(\w+)>/) {|arg| params[:"#{$1}"].to_s})
         # tag incremented depth on the message
         class << new_msg
           self
@@ -137,7 +150,8 @@ class AliasPlugin < Plugin
 
         @bot.plugins.privmsg(new_msg)
       else
-        m.reply _("Error handling the alias, the command is not defined")
+        m.reply(_("Error handling the alias, The alias %{text} is not defined or has beeen removed. I will stop responding to it after rescan,") %
+                {:text => text})
       end
     else
       super(name, *args, &block)
@@ -147,7 +161,15 @@ class AliasPlugin < Plugin
   def help(plugin, topic='')
     case topic
     when ''
-      _('Create and use aliases for commands. Topics: create, commands')
+      if plugin == 'alias' # FIXME find out plugin name programmatically
+        _('Create and use aliases for commands. Topics: create, commands')
+      else
+        # show definition of all aliases whose first word is the parameter of the help
+        # command
+        @aliases.keys.select {|a| a[/\A(\w+)/, 1] == plugin}.map do |a|
+          "#{a} => #{@aliases[a]}"
+        end.join ' | '
+      end
     when 'create'
       _('"alias <text> => <command>" => add text as an alias of command. Text can contain placeholders marked with : or * for :words and *multiword arguments. The command can contain placeholders enclosed with < > which will be substituded with argument values. For example: alias googlerbot *terms => google site:linuxbrit.co.uk/rbot/ <terms>')
     when 'commands'