summaryrefslogtreecommitdiff
path: root/data/rbot/plugins/weather.rb
blob: e6284e458e49a0bb84ce97580ec260708509d077 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#
# Weather plugin for rbot
# by MrChucho (mrchucho@mrchucho.net)
# Copyright (C) 2006 Ralph M. Churchill
#
require 'open-uri'
require 'rexml/document'

class CurrentConditions
    def initialize(station)
        @station = station
        @url = "http://www.nws.noaa.gov/data/current_obs/#{@station.upcase}.xml"
        @etag = String.new
        @mtime = Time.mktime(0)
        @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
        end
        @current_conditions # +" Cached? "+ ((@iscached) ? "Y" : "N")
    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."
    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}"
        else
            ""
        end
    end
end

class MyWeatherPlugin < Plugin
  
  def help(plugin, topic="")
    "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" 
  end
  
  def initialize
    super
    # this plugin only wants to store strings
    class << @registry
      def store(val)
        val
      end
      def restore(val)
        val
      end
    end
    @cc_cache = Hash.new
  end
  
  def describe(m, where)
    if @cc_cache.has_key?(where) then
        met = @cc_cache[where]
    else
        met = CurrentConditions.new(where)
    end
    if met
      begin
        m.reply met.update
        @cc_cache[where] = met
      rescue => e
        m.reply e.message
      end
    else
      m.reply "couldn't find weather data for #{where}"
    end
  end

  def weather(m, params)
    if params[:where]
      @registry[m.sourcenick] = params[:where]
      describe(m,params[:where])
    else
      if @registry.has_key?(m.sourcenick)
        where = @registry[m.sourcenick]
        describe(m,where)
      else
        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."
      end
    end
  end
end

plugin = MyWeatherPlugin.new
plugin.map 'weather :where', :defaults => {:where => false}