-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",
#
# 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
}
}
@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
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))
who = params.has_key?(:who) ? params[:who] : m.sourcenick
string = params[:string].to_s
debug "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
+ 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