]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/weather.rb
weather: refactor NWS output
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / weather.rb
index ab3ec908b1654769f66a65980fc88c3ce214b2c3..9d2b8aed5e3c368b49b62e30a3f6511d3fa8e4cd 100644 (file)
@@ -15,51 +15,55 @@ require 'rexml/document'
 
 # Wraps NOAA National Weather Service information
 class CurrentConditions
+  @@bot = Irc::Utils.bot
     def initialize(station)
         @station = station
-        @url = "http://www.nws.noaa.gov/data/current_obs/#{@station.upcase}.xml"
-        @etag = String.new
-        @mtime = Time.mktime(0)
+        @url = "http://www.nws.noaa.gov/data/current_obs/#{URI.encode @station.upcase}.xml"
         @current_conditions = String.new
-        @iscached = false
     end
     def update
-        begin
-            open(@url,"If-Modified-Since" => @mtime.rfc2822) do |feed|
-            # open(@url,"If-None-Match"=>@etag) do |feed|
-                @etag = feed.meta['etag']
-                @mtime = feed.last_modified
-                cc_doc = (REXML::Document.new feed).root
-                @iscached = false
-                @current_conditions = parse(cc_doc)
-            end
-        rescue OpenURI::HTTPError => e
-            case e
-            when /304/
-                @iscached = true
-            when /404/
-                raise "Data for #{@station} not found"
-            else
-                raise "Error retrieving data: #{e}"
-            end
+      begin
+        resp = @@bot.httputil.get_response(@url)
+        case resp
+        when Net::HTTPSuccess
+          cc_doc = (REXML::Document.new resp.body).root
+          @current_conditions = parse(cc_doc)
+        else
+          raise Net::HTTPError.new(_("couldn't get data for %{station} (%{message})") % {
+            :station => @station, :message => resp.message
+          }, resp)
+        end
+      rescue => e
+        if Net::HTTPError === e
+          raise
+        else
+          error e
+          raise "error retrieving data: #{e}"
         end
-        @current_conditions # +" Cached? "+ ((@iscached) ? "Y" : "N")
+      end
+      @current_conditions
     end
     def parse(cc_doc)
         cc = Hash.new
         cc_doc.elements.each do |c|
             cc[c.name.to_sym] = c.text
         end
-        "At #{cc[:observation_time_rfc822]}, the wind was #{cc[:wind_string]} at #{cc[:location]} (#{cc[:station_id]}). The temperature was #{cc[:temperature_string]}#{heat_index_or_wind_chill(cc)}, and the pressure was #{cc[:pressure_string]}. The relative humidity was #{cc[:relative_humidity]}%. Current conditions are #{cc[:weather]} with #{cc[:visibility_mi]}mi visibility."
+        cc[:time] = cc[:observation_time_rfc822]
+        cc[:wind] = cc[:wind_string]
+        cc[:temperature] = cc[:temperature_string]
+        cc[:heatindexorwindchill] = heat_index_or_wind_chill(cc)
+        cc[:pressure] = cc[:pressure_string]
+
+        _("At %{time} the conditions at %{location} (%{station_id}) were %{weather} with a visibility of %{visibility_mi}mi. The wind was %{wind} with %{relative_humidity}%% relative humidity. The temperature was %{temperature}%{heatindexorwindchill}, and the pressure was %{pressure}.") % cc
     end
 private
     def heat_index_or_wind_chill(cc)
         hi = cc[:heat_index_string]
         wc = cc[:windchill_string]
-        if hi != 'NA' then
-            " with a heat index of #{hi}"
-        elsif wc != 'NA' then
-            " with a windchill of #{wc}"
+        if hi and hi != 'NA' then
+            _(" with a heat index of %{hi}") % { :hi => hi }
+        elsif wc and wc != 'NA' then
+            _(" with a windchill of %{wc}") % { :wc => wc }
         else
             ""
         end
@@ -110,6 +114,14 @@ class WeatherPlugin < Plugin
       units = reg[2] rescue nil
     end
 
+    if !service
+      if where.sub!(/^station\s+/,'')
+        service = :nws
+      else
+        service = :wu
+      end
+    end
+
     if where.empty?
       debug "No weather location found for #{m.sourcenick}"
       m.reply "I don't know where you are yet, #{m.sourcenick}. See 'help weather nws' or 'help weather wu' for additional help"
@@ -153,6 +165,9 @@ class WeatherPlugin < Plugin
       begin
         m.reply met.update
         @nws_cache[where] = met
+      rescue Net::HTTPError => e
+        m.reply _("%{error}, will try WU service") % { :error => e.message }
+        wu_weather(m, where)
       rescue => e
         m.reply e.message
       end
@@ -161,7 +176,7 @@ class WeatherPlugin < Plugin
     end
   end
 
-  def wu_station(m, where, units)
+  def wu_station(m, where, units="")
     begin
       xml = @bot.httputil.get(@wu_station_url % [units, CGI.escape(where)])
       case xml
@@ -184,7 +199,7 @@ class WeatherPlugin < Plugin
     end
   end
 
-  def wu_weather(m, where, units)
+  def wu_weather(m, where, units="")
     begin
       xml = @bot.httputil.get(@wu_url % [units, CGI.escape(where)])
       case xml
@@ -203,7 +218,7 @@ class WeatherPlugin < Plugin
           m.reply "couldn't parse weather data from #{where}"
         end
         wu_out_special(m, xml)
-      when /<a href="\/(?:global\/stations|US\/\w\w)\//
+      when /<a href="\/auto\/mobile[^\/]+\/(?:global\/stations|[A-Z][A-Z])\//
         wu_weather_multi(m, xml)
       else
         debug xml
@@ -216,7 +231,7 @@ class WeatherPlugin < Plugin
 
   def wu_weather_multi(m, xml)
     # debug xml
-    stations = xml.scan(/<td>\s*(?:<a href="([^?"]+\?feature=[^"]+)"\s*[^>]*><img [^>]+><\/a>\s*)?<a href="\/(?:global\/stations|US\/(\w\w))\/([^"]*?)\.html">(.*?)<\/a>\s*:\s*(.*?)<\/td>/m)
+    stations = xml.scan(/<td>\s*(?:<a href="([^?"]+\?feature=[^"]+)"\s*[^>]*><img [^>]+><\/a>\s*)?<a href="\/auto\/mobile[^\/]+\/(?:global\/stations|([A-Z][A-Z]))\/([^"]*?)\.html">(.*?)<\/a>\s*:\s*(.*?)<\/td>/m)
     # debug stations
     m.reply "multiple stations available, use 'weather station <code>' or 'weather <city, state>' as appropriate, for one of the following (current temp shown):"
     stations.map! { |ar|