weathercom 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +23 -0
- data/README.md +7 -0
- data/lib/weathercom.rb +13 -0
- data/lib/weathercom/client.rb +159 -0
- data/lib/weathercom/daily_forecast.rb +45 -0
- data/lib/weathercom/day_part_forecast.rb +45 -0
- data/lib/weathercom/forecast_methods.rb +15 -0
- data/lib/weathercom/geocoded_location.rb +25 -0
- data/lib/weathercom/hourly_forecast.rb +36 -0
- data/lib/weathercom/location.rb +59 -0
- data/lib/weathercom/metadata.rb +26 -0
- data/lib/weathercom/observation.rb +55 -0
- data/lib/weathercom/wwir_forecast.rb +25 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6a1cd129b393ad377eee8ab97d03889911468403c697df53e513e8fc6fb8feb7
|
4
|
+
data.tar.gz: 70f9251e341bf65aeef8a718e6e57a7628f6e1491c3c3487b3a80e049fc1c2f9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 68303cb4b06e1b9c6d359ff489b56b1914de287e8b28b6f134c11da873e1da917af7fdbd9ee1fd5c70db347a3cb142a3ce8c80ba31effc32db17314e6402369a
|
7
|
+
data.tar.gz: 3a2d5409025765ed4e2217dc7daa9ffe7ebc273928bb1742a30c7d9bfc0f62decf5725bae6f3ae4df0223eb8d2f81d02e69536788ea34dce5b4b4b768da0213d
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
=====================
|
3
|
+
|
4
|
+
Copyright (c) 2018 Oleg Pudeyev
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/lib/weathercom.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
|
4
|
+
require 'weathercom/client'
|
5
|
+
require 'weathercom/location'
|
6
|
+
require 'weathercom/metadata'
|
7
|
+
require 'weathercom/geocoded_location'
|
8
|
+
require 'weathercom/forecast_methods'
|
9
|
+
require 'weathercom/day_part_forecast'
|
10
|
+
require 'weathercom/daily_forecast'
|
11
|
+
require 'weathercom/hourly_forecast'
|
12
|
+
require 'weathercom/wwir_forecast'
|
13
|
+
require 'weathercom/observation'
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class Client
|
4
|
+
class ApiError < StandardError
|
5
|
+
def initialize(message, status: nil)
|
6
|
+
super(message)
|
7
|
+
@status = status
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :status
|
11
|
+
end
|
12
|
+
|
13
|
+
class ApiKeyScrapeError < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(api_key: nil, cache: nil)
|
17
|
+
@configured_api_key = api_key
|
18
|
+
@cache = cache
|
19
|
+
@connection ||= Faraday.new("https://api.weather.com") do |f|
|
20
|
+
f.request :url_encoded
|
21
|
+
#f.response :detailed_logger
|
22
|
+
f.adapter Faraday.default_adapter
|
23
|
+
f.headers['user-agent'] = 'Mozilla/5.0 (Compatible)'
|
24
|
+
end
|
25
|
+
if api_key.nil?
|
26
|
+
@api_key = cache.get('weathercom:api_key')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :configured_api_key
|
31
|
+
attr_reader :connection
|
32
|
+
|
33
|
+
def api_key
|
34
|
+
configured_api_key or begin
|
35
|
+
@api_key ||= scrape_api_key
|
36
|
+
if @cache
|
37
|
+
@cache.set('weathercom:api_key', @api_key)
|
38
|
+
end
|
39
|
+
@api_key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private def clear_api_key
|
44
|
+
@api_key = nil
|
45
|
+
if @cache
|
46
|
+
@cache.set('weathercom:api_key', nil)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_json(url)
|
51
|
+
request_json(:get, url)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_json_with_cache(url)
|
55
|
+
request_json_with_cache(:get, url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def request_json(meth, url)
|
59
|
+
attempt = 1
|
60
|
+
loop do
|
61
|
+
if url.include?('?')
|
62
|
+
full_url = "#{url}&apiKey=#{URI.encode(api_key)}"
|
63
|
+
else
|
64
|
+
full_url = "#{url}?apiKey=#{URI.encode(api_key)}"
|
65
|
+
end
|
66
|
+
|
67
|
+
response = connection.send(meth) do |req|
|
68
|
+
req.url(full_url)
|
69
|
+
end
|
70
|
+
if response.status == 401 && configured_api_key.nil? && attempt == 1
|
71
|
+
clear_api_key
|
72
|
+
attempt += 1
|
73
|
+
next
|
74
|
+
end
|
75
|
+
unless response.status == 200
|
76
|
+
error = nil
|
77
|
+
begin
|
78
|
+
error = JSON.parse(response.body)['error']
|
79
|
+
rescue
|
80
|
+
end
|
81
|
+
msg = "Weathercom #{meth.to_s.upcase} #{url} failed: #{response.status}"
|
82
|
+
if error
|
83
|
+
msg += ": #{error}"
|
84
|
+
end
|
85
|
+
raise ApiError.new(msg, status: response.status)
|
86
|
+
end
|
87
|
+
return JSON.parse(response.body)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def request_json_with_cache(meth, url)
|
92
|
+
cache_key = "weathercom:#{meth}:#{url}"
|
93
|
+
if @cache && (data = @cache.get(cache_key))
|
94
|
+
if data.key?('metadata') && data['metadata'].key?('expire_time_gmt') &&
|
95
|
+
data['metadata']['expire_time_gmt'] > Time.now.to_i
|
96
|
+
then
|
97
|
+
return data
|
98
|
+
end
|
99
|
+
@cache.set(cache_key, nil)
|
100
|
+
end
|
101
|
+
|
102
|
+
request_json(meth, url).tap do |data|
|
103
|
+
if @cache
|
104
|
+
@cache.set(cache_key, data)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# endpoints
|
110
|
+
|
111
|
+
def geocode(query, ttl: nil)
|
112
|
+
if @cache && ttl
|
113
|
+
cache_key = "weathercom:geocode:#{query}"
|
114
|
+
result = @cache.get(cache_key)
|
115
|
+
if result && result['expires_at'] && result['expires_at'] > Time.now.to_i
|
116
|
+
return GeocodedLocation.new(result['location'], self)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
payload = raw_geocode(query)
|
121
|
+
|
122
|
+
if @cache && ttl
|
123
|
+
@cache.set(cache_key, 'expires_at' => Time.now.to_i + ttl, 'location' => payload)
|
124
|
+
end
|
125
|
+
|
126
|
+
GeocodedLocation.new(payload, self)
|
127
|
+
end
|
128
|
+
|
129
|
+
def location(lat, lng)
|
130
|
+
Location.new(lat, lng, self)
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
API_KEY_URL = "https://www.wunderground.com/weather/us/ny/new-york"
|
136
|
+
|
137
|
+
def scrape_api_key
|
138
|
+
resp = connection.get(API_KEY_URL)
|
139
|
+
if resp.status != 200
|
140
|
+
raise ApiKeyScrapeError, "Non-200 status while scraping API key: #{resp.status}"
|
141
|
+
end
|
142
|
+
|
143
|
+
unless resp.body =~ /apiKey=([a-zA-Z0-9]{10,})/
|
144
|
+
raise ApiKeyScrapeError, "Could not locate API key in response"
|
145
|
+
end
|
146
|
+
|
147
|
+
$1
|
148
|
+
end
|
149
|
+
|
150
|
+
def raw_geocode(query)
|
151
|
+
url = "/v3/location/search?language=EN&query=#{URI.encode(query)}&format=json"
|
152
|
+
payload = get_json(url)
|
153
|
+
payload = Hash[payload['location'].map do |key, values|
|
154
|
+
[key, values.first]
|
155
|
+
end]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class DailyForecast
|
4
|
+
include ForecastMethods
|
5
|
+
|
6
|
+
def initialize(info, metadata)
|
7
|
+
@info = info.dup.freeze
|
8
|
+
@metadata = metadata
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :metadata
|
12
|
+
|
13
|
+
%w(expire_time_gmt fcst_valid fcst_valid_local
|
14
|
+
num dow night
|
15
|
+
max_temp min_temp
|
16
|
+
torcon stormcon
|
17
|
+
blurb blurb_author narrative
|
18
|
+
qualifier_code qualifier
|
19
|
+
qpf snow_qpf snow_range snow_phrase snow_code
|
20
|
+
lunar_phase_day lunar_phase_code sunrise sunset moonrise moonset
|
21
|
+
).each do |m|
|
22
|
+
define_method(m) do
|
23
|
+
@info[m]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :start_timestamp :fcst_valid
|
28
|
+
alias :expire_timestamp :expire_time_gmt
|
29
|
+
|
30
|
+
def day_forecast
|
31
|
+
@day_forecast ||= if @info.key?('day')
|
32
|
+
DayPartForecast.new(@info['day'])
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def night_forecast
|
39
|
+
@night_forecast ||= DayPartForecast.new(@info['night'])
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class DayPartForecast
|
4
|
+
|
5
|
+
def initialize(info)
|
6
|
+
@info = info.dup.freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
%w(
|
10
|
+
fcst_valid fcst_valid_local
|
11
|
+
day_ind thunder_enum
|
12
|
+
daypart_name long_daypart_name alt_daypart_name
|
13
|
+
thunder_enum_phrase
|
14
|
+
num temp hi wc rh icon_extd icon_code wxman
|
15
|
+
phrase_12char phrase_22char phrase_32char
|
16
|
+
subphrase_pt1 subphrase_pt2 subphrase_pt3
|
17
|
+
pop precip_type
|
18
|
+
wspd wdir wdir_cardinal
|
19
|
+
clds
|
20
|
+
pop_phrase temp_phrase accumulation_phrase wind_phrase
|
21
|
+
shortcast narrative
|
22
|
+
qpf snow_qpf
|
23
|
+
snow_range snow_phrase snow_code
|
24
|
+
vocal_key qualifier_code qualifier
|
25
|
+
uv_index_raw uv_index uv_warning uv_desc
|
26
|
+
golf_index golf_category
|
27
|
+
).each do |m|
|
28
|
+
define_method(m) do
|
29
|
+
@info[m]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :start_timestamp :fcst_valid
|
34
|
+
alias :precip_probability :pop
|
35
|
+
alias :phrase :phrase_32char
|
36
|
+
|
37
|
+
# Narrative without the temperature and wind speed, which is available
|
38
|
+
# via other attributes
|
39
|
+
def cut_narrative
|
40
|
+
narrative.sub(/\..*/, '')
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class GeocodedLocation < Location
|
4
|
+
def initialize(info, client)
|
5
|
+
info = info.dup
|
6
|
+
super(info.delete('latitude'), info.delete('longitude'), client)
|
7
|
+
@info = info.freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
%w(address admin_district admin_district_code city country country_code
|
11
|
+
display_name iana_time_zone locale neighborhood place_id postal_code
|
12
|
+
postal_key disputed_area loc_id location_category pws_id type
|
13
|
+
).each do |m|
|
14
|
+
key = m.gsub(/_(\w)/) { |match| $1.upcase }
|
15
|
+
define_method(m) do
|
16
|
+
@info[key]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
alias :state_name :admin_district
|
21
|
+
alias :state_abbr :admin_district_code
|
22
|
+
alias :zipcode :postal_code
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class HourlyForecast
|
4
|
+
include ForecastMethods
|
5
|
+
|
6
|
+
def initialize(info, metadata)
|
7
|
+
@info = info.dup.freeze
|
8
|
+
@metadata = metadata
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :metadata
|
12
|
+
|
13
|
+
%w(
|
14
|
+
expire_time_gmt fcst_valid fcst_valid_local
|
15
|
+
num day_ind dow
|
16
|
+
temp feels_like dewpt pop precip_type severity
|
17
|
+
hi wc qpf snow_qpf rh wspd wdir wdir_cardinal gust clds vis mslp
|
18
|
+
uv_index_raw uv_index uv_warning uv_desc golf_index golf_category
|
19
|
+
icon_extd wxman icon_code
|
20
|
+
phrase_12char phrase_22char phrase_32char
|
21
|
+
subphrase_pt1 subphrase_pt2 subphrase_pt3
|
22
|
+
).each do |m|
|
23
|
+
define_method(m) do
|
24
|
+
@info[m]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
alias :start_timestamp :fcst_valid
|
29
|
+
alias :expire_timestamp :expire_time_gmt
|
30
|
+
|
31
|
+
alias :precip_probability :pop
|
32
|
+
alias :phrase :phrase_32char
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class Location
|
4
|
+
def initialize(lat, lng, client)
|
5
|
+
@lat, @lng, @client = lat, lng, client
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :lat
|
9
|
+
attr_reader :lng
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
def current_observation
|
13
|
+
payload = client.get_json_with_cache("#{url_prefix}/observations/current.json")
|
14
|
+
Observation.new(payload['observation'], Metadata.new(payload['metadata']))
|
15
|
+
end
|
16
|
+
|
17
|
+
def daily_forecasts_5
|
18
|
+
payload = client.get_json_with_cache("#{url_prefix}/forecast/daily/5day.json?#{query}")
|
19
|
+
payload['forecasts'].map do |info|
|
20
|
+
DailyForecast.new(info, Metadata.new(payload['metadata']))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def daily_forecasts_10
|
25
|
+
payload = client.get_json_with_cache("#{url_prefix}/forecast/daily/10day.json?#{query}")
|
26
|
+
payload['forecasts'].map do |info|
|
27
|
+
DailyForecast.new(info, Metadata.new(payload['metadata']))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alias :daily_forecasts :daily_forecasts_10
|
32
|
+
|
33
|
+
def hourly_forecasts_240
|
34
|
+
payload = client.get_json_with_cache("#{url_prefix}/forecast/hourly/240hour.json?#{query}")
|
35
|
+
payload['forecasts'].map do |info|
|
36
|
+
HourlyForecast.new(info, Metadata.new(payload['metadata']))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias :hourly_forecasts :hourly_forecasts_240
|
41
|
+
|
42
|
+
# When Will It Rain Forecast
|
43
|
+
def wwir_forecast
|
44
|
+
payload = client.get_json_with_cache("#{url_prefix}/forecast/wwir.json?#{query}")
|
45
|
+
WwirForecast.new(payload['forecast'], Metadata.new(payload['metadata']))
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def url_prefix
|
51
|
+
"/v1/geocode/#{URI.encode(lat.to_s)}/#{URI.encode(lng.to_s)}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def query
|
55
|
+
"units=e"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class Metadata
|
4
|
+
|
5
|
+
def initialize(info)
|
6
|
+
@info = info.dup.freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
%w(
|
10
|
+
language transaction_id version latitude longitude expire_time_gmt status_code
|
11
|
+
).each do |m|
|
12
|
+
define_method(m) do
|
13
|
+
@info[m]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
alias :lat :latitude
|
18
|
+
alias :lng :longitude
|
19
|
+
|
20
|
+
def expires_at
|
21
|
+
@expires_at ||= Time.at(expire_time_gmt)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class Observation
|
4
|
+
include ForecastMethods
|
5
|
+
|
6
|
+
def initialize(info, metadata)
|
7
|
+
@info = info.dup.freeze
|
8
|
+
@metadata = metadata
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :metadata
|
12
|
+
|
13
|
+
%w(
|
14
|
+
expire_time_gmt obs_time obs_time_local
|
15
|
+
day_ind dow
|
16
|
+
obs_qualifier_code obs_qualifier_severity
|
17
|
+
ptend_code ptend_desc sky_cover clds
|
18
|
+
wdir wdir_cardinal
|
19
|
+
icon_code icon_extd wxman
|
20
|
+
sunrise sunset
|
21
|
+
uv_index uv_warning uv_desc
|
22
|
+
phrase_12char phrase_22char phrase_32char
|
23
|
+
vocal_key imperial
|
24
|
+
).each do |m|
|
25
|
+
define_method(m) do
|
26
|
+
@info[m]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def sunrise_at
|
31
|
+
Time.parse(sunrise)
|
32
|
+
end
|
33
|
+
|
34
|
+
def sunset_at
|
35
|
+
Time.parse(sunset)
|
36
|
+
end
|
37
|
+
|
38
|
+
def day?
|
39
|
+
day_ind == 'Y'
|
40
|
+
end
|
41
|
+
|
42
|
+
%w(wspd gust vis mslp altimeter temp dewpt rh wc hi temp_change_24hour
|
43
|
+
temp_max_24hour temp_min_24hour pchange feels_like snow_1hour snow_6hour
|
44
|
+
snow_24hour snow_7day ceiling precip_1hour precip_6hour precip_24hour
|
45
|
+
precip_mtd precip_ytd precip_2day precip_3day precip_7day obs_qualifier_100char
|
46
|
+
obs_qualifier_50char obs_qualifier_32char
|
47
|
+
).each do |m|
|
48
|
+
define_method(m) do
|
49
|
+
@info['imperial'][m]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Weathercom
|
2
|
+
|
3
|
+
class WwirForecast
|
4
|
+
include ForecastMethods
|
5
|
+
|
6
|
+
def initialize(info, metadata)
|
7
|
+
@info = info.dup.freeze
|
8
|
+
@metadata = metadata
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :metadata
|
12
|
+
|
13
|
+
%w(
|
14
|
+
expire_time_gmt fcst_valid fcst_valid_local
|
15
|
+
overall_type phrase terse_phrase phrase_template terse_phrase_template
|
16
|
+
precip_day precip_time_24hr precip_time_12hr precip_time_iso time_zone_abbrv
|
17
|
+
).each do |m|
|
18
|
+
define_method(m) do
|
19
|
+
@info[m]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: weathercom
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Oleg Pudeyev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Weather.com API client
|
14
|
+
email: oleg@olegp.name
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- LICENSE
|
20
|
+
- README.md
|
21
|
+
- lib/weathercom.rb
|
22
|
+
- lib/weathercom/client.rb
|
23
|
+
- lib/weathercom/daily_forecast.rb
|
24
|
+
- lib/weathercom/day_part_forecast.rb
|
25
|
+
- lib/weathercom/forecast_methods.rb
|
26
|
+
- lib/weathercom/geocoded_location.rb
|
27
|
+
- lib/weathercom/hourly_forecast.rb
|
28
|
+
- lib/weathercom/location.rb
|
29
|
+
- lib/weathercom/metadata.rb
|
30
|
+
- lib/weathercom/observation.rb
|
31
|
+
- lib/weathercom/wwir_forecast.rb
|
32
|
+
homepage: https://github.com/p/weathercom
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
metadata: {}
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options:
|
38
|
+
- "--charset=UTF-8"
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubygems_version: 3.0.1
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: Weather.com API client
|
56
|
+
test_files: []
|