class Plugins::Weather

Forecast is a Cinch plugin for getting the weather forecast. @original_author Jonah Ruiz <jonah@pixelhipsters.com> @author Liothen <liothen@flagrun.net>

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/Zeta/plugins/weather.rb, line 31
def initialize(*args)
  @api_src = %w{noaa owm}
  @store = Persist.new(File.join(Dir.home, '.zeta', 'cache', 'weather.pstore'))
  super
end

Public Instance Methods

set_location(msg, query) click to toggle source

?setw <location>

# File lib/Zeta/plugins/weather.rb, line 64
def set_location(msg, query)
  # Establish source
  src = query[/:\w+/].gsub(/:/, '') if query[/:\w+/]
  query = query.gsub(/:\w+/, '').strip if query

  # Sanity Check
  true_src = @api_src.include?(src) ? src : 'owm'
  data = send("#{true_src}_src", query)

  # Error
  return msg.reply "No results found for #{query}." if data.nil?

  # Store and display general location
  serial_location = "#{query}::#{src}"
  @store[msg.user.to_s] = serial_location unless data.nil?
  msg.reply "Your location is now set to #{data.ac.name}, #{data.ac.c}!"
end
weather(msg, query = nil) click to toggle source

?w <location>

# File lib/Zeta/plugins/weather.rb, line 38
def weather(msg, query = nil)
  # Pull data source and scrub query
  # Lookup user from pstore
  if !@store[msg.user.to_s].nil? && query.nil?
    stored_location, stored_source = @store[msg.user.to_s].split('::')
    stored_source = @api_src.include?(stored_source) ? stored_source : 'owm'
    data = send("#{stored_source}_src", stored_location)
    # location = geolookup(@store[msg.user.to_s])
    # data = wunderground_src(stored_location, false)
  elsif query.nil?
    return msg.reply 'No location set. ?setw <location> :(noaa|owm)'
  else
    # data = wu_src(query, true)
    src = query[/:\w+/].gsub(/:/, '') if query[/:\w+/]
    query = query.gsub(/:\w+/, '').strip if query
    true_src = @api_src.include?(src) ? src : 'owm'
    data = send("#{true_src}_src", query)
  end

  return msg.reply "No results found for #{query} with #{true_src} source." if data.nil?

  # return msg.reply 'Problem getting data. Try again later.' if data.nil?
  msg.reply(data.reply)
end

Private Instance Methods

noaa_src(location) click to toggle source

NOAA - graphical.weather.gov/xml/

# File lib/Zeta/plugins/weather.rb, line 123
def noaa_src(location)
  location = CGI.escape(location)

  ac = JSON.parse(
    RestClient.get("https://maps.googleapis.com/maps/api/geocode/json?address=#{location}&key=#{Config.secrets[:google]}").body,
    object_class: OpenStruct
  )
  return nil if ac.results.nil? ## Unable to locate

  ac = ac.results[0]
  lat = ac.geometry.location.lat
  lon = ac.geometry.location.lng

  stations = JSON.parse(
    RestClient.get("https://api.weather.gov/points/#{lat},#{lon}/stations/").body
  ) rescue nil

  return nil if stations.nil? ## Unable to find station. probably not in the USA

  parsed = JSON.parse(
    RestClient.get("#{CGI.escape(stations['observationStations'][0])}/observations/current").body,
    object_class: OpenStruct
  )

  data = parsed.properties
  data.ac = ac
  f = data.temperature.value * 9 / 5
  temp = "#{f.round(2)} F (#{data.temperature.value.to_i.round(2)} C) "
  wind = "Gusts: #{data.windGust.value} avg: #{data.windSpeed.value.to_i.round(2)}"
  feelslike = "#{data.windChill.value.to_i.round(2)} C"
  pressure = Unitwise(data.barometricPressure.value.to_f, 'Pa')

  data.reply = "NOAA ∴ #{ac.formatted_address} " \
              "≈ #{data.textDescription} #{temp} " \
              "≈ Feels like #{feelslike} " \
              "≈ Humidity: #{data.relativeHumidity.value.round(2)} " \
              "≈ Pressure: #{pressure.convert_to('[in_i\'Hg]').to_f.round(2)} in/Hg " \
              "(#{pressure.convert_to("kPa").to_f.round(2)} kPa) " \
              "≈ Wind: #{wind} ≈ Alerts:  ∴"
  return data
  # rescue
  #   data.reply = "Error fetching data"
end
owm_src(location) click to toggle source

Open Weather map - openweathermap.org/api

# File lib/Zeta/plugins/weather.rb, line 86
def owm_src(location)
  location = CGI.escape(location)

  ac = JSON.parse(
    RestClient.get(
      "https://maps.googleapis.com/maps/api/geocode/json?address=#{location}&key=#{Config.secrets[:google]}"
    ).body, object_class: OpenStruct
  )

  return nil if ac.results.nil? ## Unable to locate

  ac = ac.results[0]
  lat = ac.geometry.location.lat
  lon = ac.geometry.location.lng

  # Get Data
  data = JSON.parse(
    RestClient.get("https://api.openweathermap.org/data/2.5/weather?lat=#{lat}&lon=#{lon}&APPID=#{Config.secrets[:owm]}"
    ).body, object_class: OpenStruct
  )

  temp = Unitwise(data.main.temp, 'K') # Data is given in kelvin
  pressure = Unitwise(data.main.pressure.to_f, 'mbar')
  wind = Unitwise(data.wind.speed, 'kilometer')

  data.reply = "OWM ∴ #{ac.formatted_address} " \
              "≈ #{(Time.now.utc + data.timezone.seconds).strftime("%c")} " \
              "≈ #{data.weather[0].description},  #{temp.convert_to('[degF]').to_i.round(2)} F (#{temp.convert_to('Cel').to_i.round(2)} C) " \
              "≈ Humidity: #{data.main.humidity.to_i.round(2)}% " \
              "≈ Pressure: #{pressure.convert_to('[in_i\'Hg]').to_f.round(2)} in/Hg " \
              "(#{pressure.convert_to("kPa").to_f.round(2)} kPa) " \
              "≈ Wind: #{wind.convert_to('mile').to_i.round(2)} mph (#{wind.to_i.round(2)} km/h) ∴"

  return data
end