]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/time.rb
plugin(lart): refactor to use registry to persist
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / time.rb
index 4e7543c8be2317a0f6fc78f191602509985c4d0f..5c3189f60ad2d6b0164c215d036d4f22b33e1e97 100644 (file)
@@ -4,15 +4,24 @@
 # :title: Time Zone Plugin for rbot
 #
 # Author:: Ian Monroe <ian@monroe.nu>
+# Author:: Raine Virta <raine.virta@gmail.com>
 # Copyright:: (C) 2006 Ian Monroe
+# Copyright:: (C) 2010 Raine Virta
 # License:: MIT license
 
 require 'tzinfo'
 
 class TimePlugin < Plugin
-
   def help(plugin, topic="")
-  "time <time zone> to get the local time of a certain location. <time zone> can be <Continent/City> or <two character country code>. time <nick> to see the local time of that person if their time zone is set. time admin set <nick> <time zone> to set the time zone for another user. time [admin] reset [nick] to let the bot forget about the tzinfo about someone"
+    case topic
+    when "set"
+      _("usage: time set <Continent>/<City> -- setting your location allows the bot to calibrate time replies into your time zone, and other people to figure out what time it is for you")
+    else
+      _("usage: time <timestamp|time zone|nick> -- %{b}timestamp%{b}: get info about a specific time, relative to your own time zone | %{b}time zone%{b}: get local time of a certain location, <time zone> can be '<Continent>/<City>' or a two character country code | %{b}nick%{b}: get local time of another person, given they have set their location | see `%{prefix}help time set` on how to set your location") % {
+        :b => Bold,
+        :prefix => @bot.config['core.address_prefix'].first
+      }
+    end
   end
 
   def initialize
@@ -45,45 +54,60 @@ class TimePlugin < Plugin
     end
     ['/', '_'].each { |sp|
         arr = Array.new
-        zone.split(sp).each{ |s| 
+        zone.split(sp).each{ |s|
             s[0] = s[0,1].upcase
             s[1, s.length] = s[1, s.length].downcase if sp == '/'
             arr.push(s) }
             zone = arr.join( sp )
         }
-    
+
     tz = TZInfo::Timezone.get( zone )
     "#{tz.friendly_identifier} - #{tz.now.strftime( '%a %b %d %H:%M' )} #{tz.current_period.abbreviation}"
   end
 
   def showTime(m, params)
-    zone = params[:where].join('_')
-    if params[:where].size > 0 then
-      begin
-        m.reply getTime( m,  zone )
-      rescue TZInfo::InvalidTimezoneIdentifier
-        if @registry.has_key?( zone ) then
-          zone =  @registry[ zone ]
-          m.reply getTime( m,  zone )
-        else
-          m.reply "#{zone} is an unknown time."
-        end
-      end
+    nick = nil
+    zone = nil
+    speaker = false
+    case params[:where].size
+    when 0
+      nick = m.sourcenick
+      speaker = true
+    when 1
+      zone = params[:where].first
+      nick = m.channel.get_user(zone)
+      speaker = (nick == m.sourcenick)
     else
-      if @registry.has_key?( m.sourcenick) then
-        zone = @registry[ m.sourcenick ]
-        m.reply "#{m.sourcenick}: #{getTime( m,  zone )}"
+      zone = params[:where].join('_')
+    end
+
+    # now we have a non-nil nick iff we want user information
+    if nick
+      if @registry.has_key? nick
+        zone = @registry[nick]
       else
-        m.reply "#{m.sourcenick}: use time set <Continent/City> to set your timezone."
+        if speaker
+          msg = _("I don't know where you are, use %{pfx}time set <Continent>/<City> to let me know")
+        else
+          msg = _("I don't know where %{nick} is, (s)he should use %{pfx}time set <Continent>/<City> to let me know")
+        end
+        m.reply(msg % { :pfx => @bot.config['core.address_prefix'].first, :nick => nick })
+        return false
       end
     end
+
+    begin
+      m.reply getTime( m,  zone )
+    rescue TZInfo::InvalidTimezoneIdentifier
+      parse(m, params)
+    end
   end
 
   def setUserZone( m, params )
     if params[:where].size > 0 then
       s = setZone( m, m.sourcenick, params[:where].join('_') )
     else
-      m.reply "Requires Continent/City or country code"
+      m.reply "Requires <Continent>/<City> or country code"
     end
   end
 
@@ -95,7 +119,7 @@ class TimePlugin < Plugin
     if params[:who] and params[:where].size > 0 then
       s = setZone( m, params[:who], params[:where].join('_') )
     else
-      m.reply "Requires a nick and the Continent/City or country code"
+      m.reply "Requires a nick and the <Continent>/<City> or country code"
     end
   end
 
@@ -111,16 +135,81 @@ class TimePlugin < Plugin
     begin
       getTime( m,  zone )
     rescue TZInfo::InvalidTimezoneIdentifier
-      m.reply "#{zone} is an invalid timezone. Format is Continent/City or a two character country code."
+      m.reply "#{zone} is an invalid time zone. Format is <Continent>/<City> or a two character country code."
       return
     end
     @registry[ user ] = zone
-    m.reply "Ok, I'll remember that #{user} is on the #{zone} timezone"
+    m.reply "Ok, I'll remember that #{user} is on the #{zone} time zone"
   end
 
   def resetZone( m, user )
     @registry.delete(user)
-    m.reply "Ok, I've forgotten #{user}'s timezone"
+    m.reply "Ok, I've forgotten #{user}'s time zone"
+  end
+
+  def parse(m, params)
+    require 'time'
+    str = params[:where].to_s
+    now = Time.now
+
+    begin
+      time = begin
+        if zone = @registry[m.sourcenick]
+          on_timezone(zone) {
+            Time.parse str
+          }
+        else
+          Time.parse str
+        end
+      rescue ArgumentError => e
+        # Handle 28/9/1978, which is a valid date representation at least in Italy
+        if e.message == 'argument out of range'
+          str.tr!('/', '-')
+          Time.parse str
+        else
+          raise
+        end
+      end
+
+      offset = (time - now).abs
+      raise if offset < 0.1
+    rescue => e
+      if str.match(/^\d+$/)
+        time = Time.at(str.to_i)
+      else
+        m.reply _("unintelligible time")
+        return
+      end
+    end
+
+    if zone = @registry[m.sourcenick]
+      time = time.convert_zone(zone)
+    end
+
+    m.reply _("%{time} %{w} %{str}") % {
+      :time => time.strftime(_("%a, %d %b %Y %H:%M:%S %Z %z")),
+      :str  => Utils.timeago(time),
+      :w    => time >= now ? _("is") : _("was")
+    }
+  end
+
+  def on_timezone(to_zone)
+    original_zone = ENV["TZ"]
+    ENV["TZ"] = to_zone
+    ret = yield
+    ENV["TZ"] = original_zone
+    return ret
+  end
+end
+
+class ::Time
+  def convert_zone(to_zone)
+    original_zone = ENV["TZ"]
+    utc_time = dup.gmtime
+    ENV["TZ"] = to_zone
+    to_zone_time = utc_time.localtime
+    ENV["TZ"] = original_zone
+    return to_zone_time
   end
 end