]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/weather.rb
More lart plugins cleanup
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / weather.rb
1 #
2 # Weather plugin for rbot
3 # by MrChucho (mrchucho@mrchucho.net)
4 # Copyright (C) 2006 Ralph M. Churchill
5 #
6 require 'open-uri'
7 require 'rexml/document'
8
9 class CurrentConditions
10     def initialize(station)
11         @station = station
12         @url = "http://www.nws.noaa.gov/data/current_obs/#{@station.upcase}.xml"
13         @etag = String.new
14         @mtime = Time.mktime(0)
15         @current_conditions = String.new
16         @iscached = false
17     end
18     def update
19         begin
20             open(@url,"If-Modified-Since" => @mtime.rfc2822) do |feed|
21             # open(@url,"If-None-Match"=>@etag) do |feed|
22                 @etag = feed.meta['etag']
23                 @mtime = feed.last_modified
24                 cc_doc = (REXML::Document.new feed).root
25                 @iscached = false
26                 @current_conditions = parse(cc_doc)
27             end
28         rescue OpenURI::HTTPError => e
29             case e
30             when /304/:
31                 @iscached = true
32             when /404/:
33                 raise "Data for #{@station} not found"
34             else
35                 raise "Error retrieving data: #{e}"
36             end
37         end
38         @current_conditions # +" Cached? "+ ((@iscached) ? "Y" : "N")
39     end
40     def parse(cc_doc)
41         cc = Hash.new
42         cc_doc.elements.each do |c|
43             cc[c.name.to_sym] = c.text
44         end
45         "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."
46     end
47 private
48     def heat_index_or_wind_chill(cc)
49         hi = cc[:heat_index_string]
50         wc = cc[:windchill_string]
51         if hi != 'NA' then
52             " with a heat index of #{hi}"
53         elsif wc != 'NA' then
54             " with a windchill of #{wc}"
55         else
56             ""
57         end
58     end
59 end
60
61 class MyWeatherPlugin < Plugin
62   
63   def help(plugin, topic="")
64     "weather <STATION> => display the current conditions at the location specified by the STATION code [Lookup your STATION code at http://www.nws.noaa.gov/data/current_obs/ - this will also store the STATION against your nick, so you can later just say \"weather\", weather => display the current weather at the location you last asked for" 
65   end
66   
67   def initialize
68     super
69     # this plugin only wants to store strings
70     class << @registry
71       def store(val)
72         val
73       end
74       def restore(val)
75         val
76       end
77     end
78     @cc_cache = Hash.new
79   end
80   
81   def describe(m, where)
82     if @cc_cache.has_key?(where) then
83         met = @cc_cache[where]
84     else
85         met = CurrentConditions.new(where)
86     end
87     if met
88       begin
89         m.reply met.update
90         @cc_cache[where] = met
91       rescue => e
92         m.reply e.message
93       end
94     else
95       m.reply "couldn't find weather data for #{where}"
96     end
97   end
98
99   def weather(m, params)
100     if params[:where]
101       @registry[m.sourcenick] = params[:where]
102       describe(m,params[:where])
103     else
104       if @registry.has_key?(m.sourcenick)
105         where = @registry[m.sourcenick]
106         describe(m,where)
107       else
108         m.reply "I don't know where you are yet! Lookup your station at http://www.nws.noaa.gov/data/current_obs/ and tell me 'weather <station>', then I'll know."
109       end
110     end
111   end
112 end
113
114 plugin = MyWeatherPlugin.new
115 plugin.map 'weather :where', :defaults => {:where => false}