class Weathercom::Client

Constants

API_KEY_URL

Attributes

configured_api_key[R]
connection[R]

Public Class Methods

new(api_key: nil, cache: nil) click to toggle source
# File lib/weathercom/client.rb, line 16
def initialize(api_key: nil, cache: nil)
  @configured_api_key = api_key
  @cache = cache
  @connection ||= Faraday.new("https://api.weather.com") do |f|
    f.request :url_encoded
    #f.response :detailed_logger
    f.adapter Faraday.default_adapter
    f.headers['user-agent'] = 'Mozilla/5.0 (Compatible)'
  end
  if api_key.nil?
    @api_key = cache.get('weathercom:api_key')
  end
end

Public Instance Methods

api_key() click to toggle source
# File lib/weathercom/client.rb, line 33
def api_key
  configured_api_key or begin
    @api_key ||= scrape_api_key
    if @cache
      @cache.set('weathercom:api_key', @api_key)
    end
    @api_key
  end
end
geocode(query, ttl: nil) click to toggle source

endpoints

# File lib/weathercom/client.rb, line 111
def geocode(query, ttl: nil)
  if @cache && ttl
    cache_key = "weathercom:geocode:#{query}"
    result = @cache.get(cache_key)
    if result && result['expires_at'] && result['expires_at'] > Time.now.to_i
      return GeocodedLocation.new(result['location'], self)
    end
  end

  payload = raw_geocode(query)

  if @cache && ttl
    @cache.set(cache_key, 'expires_at' => Time.now.to_i + ttl, 'location' => payload)
  end

  GeocodedLocation.new(payload, self)
end
get_json(url) click to toggle source
# File lib/weathercom/client.rb, line 50
def get_json(url)
  request_json(:get, url)
end
get_json_with_cache(url) click to toggle source
# File lib/weathercom/client.rb, line 54
def get_json_with_cache(url)
  request_json_with_cache(:get, url)
end
location(lat, lng) click to toggle source
# File lib/weathercom/client.rb, line 129
def location(lat, lng)
  Location.new(lat, lng, self)
end
request_json(meth, url) click to toggle source
# File lib/weathercom/client.rb, line 58
def request_json(meth, url)
  attempt = 1
  loop do
    if url.include?('?')
      full_url = "#{url}&apiKey=#{URI.encode(api_key)}"
    else
      full_url = "#{url}?apiKey=#{URI.encode(api_key)}"
    end

    response = connection.send(meth) do |req|
      req.url(full_url)
    end
    if response.status == 401 && configured_api_key.nil? && attempt == 1
      clear_api_key
      attempt += 1
      next
    end
    unless response.status == 200
      error = nil
      begin
        error = JSON.parse(response.body)['error']
      rescue
      end
      msg = "Weathercom #{meth.to_s.upcase} #{url} failed: #{response.status}"
      if error
        msg += ": #{error}"
      end
      raise ApiError.new(msg, status: response.status)
    end
    return JSON.parse(response.body)
  end
end
request_json_with_cache(meth, url) click to toggle source
# File lib/weathercom/client.rb, line 91
def request_json_with_cache(meth, url)
  cache_key = "weathercom:#{meth}:#{url}"
  if @cache && (data = @cache.get(cache_key))
    if data.key?('metadata') && data['metadata'].key?('expire_time_gmt') &&
      data['metadata']['expire_time_gmt'] > Time.now.to_i
    then
      return data
    end
    @cache.set(cache_key, nil)
  end

  request_json(meth, url).tap do |data|
    if @cache
      @cache.set(cache_key, data)
    end
  end
end

Private Instance Methods

clear_api_key() click to toggle source
# File lib/weathercom/client.rb, line 43
        def clear_api_key
  @api_key = nil
  if @cache
    @cache.set('weathercom:api_key', nil)
  end
end
raw_geocode(query) click to toggle source
# File lib/weathercom/client.rb, line 150
def raw_geocode(query)
  url = "/v3/location/search?language=EN&query=#{URI.encode(query)}&format=json"
  payload = get_json(url)
  payload = Hash[payload['location'].map do |key, values|
    [key, values.first]
  end]
end
scrape_api_key() click to toggle source
# File lib/weathercom/client.rb, line 137
def scrape_api_key
  resp = connection.get(API_KEY_URL)
  if resp.status != 200
    raise ApiKeyScrapeError, "Non-200 status while scraping API key: #{resp.status}"
  end

  unless resp.body =~ /apiKey=([a-zA-Z0-9]{10,})/
    raise ApiKeyScrapeError, "Could not locate API key in response"
  end

  $1
end