]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/remind.rb
chucknorris: read gzip stream before passing it to YAML.load
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / remind.rb
index f66c4fc8a40b79b7f9da4974df1c9f13cf6afc01..c10186f5861fd32c67a0604872f369678bde5f0f 100644 (file)
@@ -1,5 +1,3 @@
-require 'rbot/utils'
-
 class RemindPlugin < Plugin
   # read a time in string format, turn it into "seconds from now".
   # example formats handled are "5 minutes", "2 days", "five hours",
@@ -7,102 +5,13 @@ class RemindPlugin < Plugin
   #
   # Throws:: RunTimeError "invalid time string" on parse failure
   def timestr_offset(timestr)
-    case timestr
-      when (/^(\S+)\s+(\S+)$/)
-        mult = $1
-        unit = $2
-        if(mult =~ /^([\d.]+)$/)
-          num = $1.to_f
-          raise "invalid time string" unless num
-        else
-          case mult
-            when(/^(one|an|a)$/)
-              num = 1
-            when(/^two$/)
-              num = 2
-            when(/^three$/)
-              num = 3
-            when(/^four$/)
-              num = 4
-            when(/^five$/)
-              num = 5
-            when(/^six$/)
-              num = 6
-            when(/^seven$/)
-              num = 7
-            when(/^eight$/)
-              num = 8
-            when(/^nine$/)
-              num = 9
-            when(/^ten$/)
-              num = 10
-            when(/^fifteen$/)
-              num = 15
-            when(/^twenty$/)
-              num = 20
-            when(/^thirty$/)
-              num = 30
-            when(/^sixty$/)
-              num = 60
-            else
-              raise "invalid time string"
-          end
-        end
-        case unit
-          when (/^(s|sec(ond)?s?)$/)
-            return num
-          when (/^(m|min(ute)?s?)$/)
-            return num * 60
-          when (/^(h|h(ou)?rs?)$/)
-            return num * 60 * 60
-          when (/^(d|days?)$/)
-            return num * 60 * 60 * 24
-          else
-            raise "invalid time string"
-        end
-      when (/^(\d+):(\d+):(\d+)$/)
-        hour = $1.to_i
-        min = $2.to_i
-        sec = $3.to_i
-        now = Time.now
-        later = Time.mktime(now.year, now.month, now.day, hour, min, sec)
-        return later - now
-      when (/^(\d+):(\d+)$/)
-        hour = $1.to_i
-        min = $2.to_i
-        now = Time.now
-        later = Time.mktime(now.year, now.month, now.day, hour, min, now.sec)
-        return later - now
-      when (/^(\d+):(\d+)(am|pm)$/)
-        hour = $1.to_i
-        min = $2.to_i
-        ampm = $3
-        if ampm == "pm"
-          hour += 12
-        end
-        now = Time.now
-        later = Time.mktime(now.year, now.month, now.day, hour, min, now.sec)
-        return later - now
-      when (/^(\S+)$/)
-        num = 1
-        unit = $1
-        case unit
-          when (/^(s|sec(ond)?s?)$/)
-            return num
-          when (/^(m|min(ute)?s?)$/)
-            return num * 60
-          when (/^(h|h(ou)?rs?)$/)
-            return num * 60 * 60
-          when (/^(d|days?)$/)
-            return num * 60 * 60 * 24
-          else
-            raise "invalid time string"
-        end
-      else
-        raise "invalid time string"
-    end
+    Utils.parse_time_offset(timestr)
   end
 
+  class UnparsedPeriodError < RuntimeError ; end
+  class NegativePeriodError < RuntimeError ; end
+  class ShortRepeatError < RuntimeError ; end
+
   def initialize
     super
     @reminders = Hash.new
@@ -114,21 +23,25 @@ class RemindPlugin < Plugin
       }
     }
     @reminders.clear
+    super
   end
   def help(plugin, topic="")
     "reminder plugin: remind <who> [about] <message> in <time>, remind <who> [about] <message> every <time>, remind <who> [about] <message> at <time>, remind <who> no more [about] <message>, remind <who> no more. Generally <who> should be 'me', but you can remind others (nick or channel) if you have remind_others auth"
   end
-  def add_reminder(who, subject, timestr, repeat=false)
+  def add_reminder(m, who, subject, timestr, repeat=false)
     begin
       period = timestr_offset(timestr)
     rescue RuntimeError
-      return "couldn't parse that time string (#{timestr}) :("
+      raise UnparsedPeriodError
     end
+    raise NegativePeriodError if period <= 0
+    raise ShortRepeatError if period < 30 && repeat
+
     if(period <= 0)
       return "that time is in the past! (#{timestr})"
     end
     if(period < 30 && repeat)
-      return "repeats of less than 30 seconds are forbidden"
+      return
     end
     if(!@reminders.has_key?(who))
       @reminders[who] = Hash.new
@@ -138,19 +51,19 @@ class RemindPlugin < Plugin
 
     if(repeat)
       @reminders[who][subject] = @bot.timer.add(period) {
-        time = Time.now + period
-        tstr = time.strftime("%H:%M:%S")
+        tstr = (Time.now + period).strftime("%H:%M:%S")
         @bot.say who, "repeat reminder (next at #{tstr}): #{subject}"
       }
     else
       @reminders[who][subject] = @bot.timer.add_once(period) {
-        time = Time.now + period
-        tstr = time.strftime("%H:%M:%S")
+        tstr = Time.now.strftime("%H:%M:%S")
         @bot.say who, "reminder (#{tstr}): #{subject}"
       }
     end
-    return false
+
+    m.okay
   end
+
   def del_reminder(who, subject=nil)
     if(subject)
       if(@reminders.has_key?(who) && @reminders[who].has_key?(subject))
@@ -175,54 +88,67 @@ class RemindPlugin < Plugin
   def remind(m, params)
     who = params.has_key?(:who) ? params[:who] : m.sourcenick
     string = params[:string].to_s
-    puts "in remind, string is: #{string}"
-    if(string =~ /^(.*)\s+in\s+(.*)$/)
-      subject = $1
-      period = $2
-      if(err = add_reminder(who, subject, period))
-        m.reply "incorrect usage: " + err
-        return
+    debug "in remind, string is: #{string}"
+    tried = []
+
+    begin
+      if !tried.include?(:in) and string =~ /^(.*)\s+in\s+(.*)$/
+        subject = $1
+        period = $2
+        tried << :in
+        add_reminder(m, who, subject, period)
+        return true
       end
-    elsif(string =~ /^(.*)\s+every\s+(.*)$/)
-      subject = $1
-      period = $2
-      if(err = add_reminder(who, subject, period, true))
-        m.reply "incorrect usage: " + err
-        return
+
+      if !tried.include?(:every) and string =~ /^(.*)\s+every\s+(.*)$/
+        subject = $1
+        period = $2
+        tried << :every
+        add_reminder(m, who, subject, period, true)
+        return true
       end
-    elsif(string =~ /^(.*)\s+at\s+(.*)$/)
-      subject = $1
-      time = $2
-      if(err = add_reminder(who, subject, time))
-        m.reply "incorrect usage: " + err
-        return
+
+      if !tried.include?(:at) and string =~ /^(.*)\s+at\s+(.*)$/
+        subject = $1
+        time = $2
+        tried << :at
+        add_reminder(m, who, subject, time)
+        return true
       end
-    else
+
       usage(m)
-      return
+      return false
+    rescue NegativePeriodError
+      m.reply "that time is in the past! (#{timestr})"
+      return false
+    rescue ShortRepeatError
+      m.reply "repeats of less than 30 seconds are forbidden"
+      return false
+    rescue UnparsedPeriodError
+      retry
     end
-    m.okay
+
   end
+
   def no_more(m, params)
     who = params.has_key?(:who) ? params[:who] : m.sourcenick
-    deleted = params.has_key?(:string) ? 
+    deleted = params.has_key?(:string) ?
               del_reminder(who, params[:string].to_s) : del_reminder(who)
     if deleted
       m.okay
-    else 
+    else
       m.reply "but I wasn't going to :/"
     end
   end
 end
 plugin = RemindPlugin.new
+
+plugin.default_auth('other', false)
+
 plugin.map 'remind me no more', :action => 'no_more'
-plugin.map 'remind me no more about *string', :action => 'no_more'
-plugin.map 'remind me no more *string', :action => 'no_more'
-plugin.map 'remind me about *string'
-plugin.map 'remind me *string'
-plugin.map 'remind :who no more', :auth => 'remind_other', :action => 'no_more'
-plugin.map 'remind :who no more about *string', :auth => 'remind_other', :action => 'no_more'
-plugin.map 'remind :who no more *string', :auth => 'remind_other', :action => 'no_more'
-plugin.map 'remind :who about *string', :auth => 'remind_other'
-plugin.map 'remind :who *string', :auth => 'remind_other'
+plugin.map 'remind me no more [about] *string', :action => 'no_more'
+plugin.map 'remind me [about] *string'
+plugin.map 'remind :who no more', :auth_path => 'other', :action => 'no_more'
+plugin.map 'remind :who no more [about] *string', :auth_path => 'other', :action => 'no_more'
+plugin.map 'remind :who [about] *string', :auth_path => 'other'