geocoder 1.6.4 → 1.7.0
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 +4 -4
- data/CHANGELOG.md +22 -0
- data/LICENSE +1 -1
- data/README.md +318 -230
- data/lib/geocoder/cache.rb +9 -1
- data/lib/geocoder/configuration.rb +1 -0
- data/lib/geocoder/ip_address.rb +6 -0
- data/lib/geocoder/lookup.rb +16 -2
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +53 -0
- data/lib/geocoder/lookups/bing.rb +1 -1
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geoip2.rb +4 -0
- data/lib/geocoder/lookups/ip2location.rb +10 -6
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +26 -1
- data/lib/geocoder/results/esri.rb +5 -2
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/ipregistry.rb +4 -8
- data/lib/geocoder/results/mapbox.rb +10 -4
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +1 -1
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/version.rb +1 -1
- metadata +14 -2
data/lib/geocoder/cache.rb
CHANGED
@@ -18,6 +18,8 @@ module Geocoder
|
|
18
18
|
when store.respond_to?(:read)
|
19
19
|
store.read key_for(url)
|
20
20
|
end
|
21
|
+
rescue => e
|
22
|
+
warn "Geocoder cache read error: #{e}"
|
21
23
|
end
|
22
24
|
|
23
25
|
##
|
@@ -32,6 +34,8 @@ module Geocoder
|
|
32
34
|
when store.respond_to?(:write)
|
33
35
|
store.write key_for(url), value
|
34
36
|
end
|
37
|
+
rescue => e
|
38
|
+
warn "Geocoder cache write error: #{e}"
|
35
39
|
end
|
36
40
|
|
37
41
|
##
|
@@ -60,7 +64,11 @@ module Geocoder
|
|
60
64
|
# Cache key for a given URL.
|
61
65
|
#
|
62
66
|
def key_for(url)
|
63
|
-
|
67
|
+
if url.match(/^#{prefix}/)
|
68
|
+
url
|
69
|
+
else
|
70
|
+
[prefix, url].join
|
71
|
+
end
|
64
72
|
end
|
65
73
|
|
66
74
|
##
|
data/lib/geocoder/ip_address.rb
CHANGED
data/lib/geocoder/lookup.rb
CHANGED
@@ -18,6 +18,14 @@ module Geocoder
|
|
18
18
|
all_services - [:test]
|
19
19
|
end
|
20
20
|
|
21
|
+
##
|
22
|
+
# Array of valid Lookup service names, excluding any that do not build their own HTTP requests.
|
23
|
+
# For example, Amazon Location Service uses the AWS gem, not HTTP REST requests, to fetch data.
|
24
|
+
#
|
25
|
+
def all_services_with_http_requests
|
26
|
+
all_services_except_test - [:amazon_location_service]
|
27
|
+
end
|
28
|
+
|
21
29
|
##
|
22
30
|
# All street address lookup services, default first.
|
23
31
|
#
|
@@ -53,7 +61,11 @@ module Geocoder
|
|
53
61
|
:test,
|
54
62
|
:latlon,
|
55
63
|
:amap,
|
56
|
-
:osmnames
|
64
|
+
:osmnames,
|
65
|
+
:melissa_street,
|
66
|
+
:amazon_location_service,
|
67
|
+
:geoapify,
|
68
|
+
:photon
|
57
69
|
]
|
58
70
|
end
|
59
71
|
|
@@ -63,6 +75,7 @@ module Geocoder
|
|
63
75
|
def ip_services
|
64
76
|
@ip_services ||= [
|
65
77
|
:baidu_ip,
|
78
|
+
:abstract_api,
|
66
79
|
:freegeoip,
|
67
80
|
:geoip2,
|
68
81
|
:maxmind,
|
@@ -77,7 +90,8 @@ module Geocoder
|
|
77
90
|
:db_ip_com,
|
78
91
|
:ipstack,
|
79
92
|
:ip2location,
|
80
|
-
:ipgeolocation
|
93
|
+
:ipgeolocation,
|
94
|
+
:ipqualityscore
|
81
95
|
]
|
82
96
|
end
|
83
97
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/abstract_api'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class AbstractApi < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Abstract API"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
def supported_protocols
|
18
|
+
[:https]
|
19
|
+
end
|
20
|
+
|
21
|
+
private # ---------------------------------------------------------------
|
22
|
+
|
23
|
+
def base_query_url(query)
|
24
|
+
"#{protocol}://ipgeolocation.abstractapi.com/v1/?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def query_url_params(query)
|
28
|
+
params = {api_key: configuration.api_key}
|
29
|
+
|
30
|
+
ip_address = query.sanitized_text
|
31
|
+
if ip_address.is_a?(String) && ip_address.length > 0
|
32
|
+
params[:ip_address] = ip_address
|
33
|
+
end
|
34
|
+
|
35
|
+
params.merge(super)
|
36
|
+
end
|
37
|
+
|
38
|
+
def results(query, reverse = false)
|
39
|
+
if doc = fetch_data(query)
|
40
|
+
[doc]
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/amazon_location_service'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class AmazonLocationService < Base
|
6
|
+
def results(query)
|
7
|
+
params = { **global_index_name, **query.options }
|
8
|
+
if query.reverse_geocode?
|
9
|
+
resp = client.search_place_index_for_position(**{ **params, position: query.coordinates.reverse })
|
10
|
+
else
|
11
|
+
resp = client.search_place_index_for_text(**{ **params, text: query.text })
|
12
|
+
end
|
13
|
+
resp.results.map(&:place)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def client
|
19
|
+
return @client if @client
|
20
|
+
require_sdk
|
21
|
+
keys = configuration.api_key
|
22
|
+
if keys
|
23
|
+
@client = Aws::LocationService::Client.new(
|
24
|
+
access_key_id: keys[:access_key_id],
|
25
|
+
secret_access_key: keys[:secret_access_key],
|
26
|
+
)
|
27
|
+
else
|
28
|
+
@client = Aws::LocationService::Client.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def require_sdk
|
33
|
+
begin
|
34
|
+
require 'aws-sdk-locationservice'
|
35
|
+
rescue LoadError
|
36
|
+
raise_error(Geocoder::ConfigurationError) ||
|
37
|
+
Geocoder.log(
|
38
|
+
:error,
|
39
|
+
"Couldn't load the Amazon Location Service SDK. " +
|
40
|
+
"Install it with: gem install aws-sdk-locationservice -v '~> 1.4'"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def global_index_name
|
46
|
+
if configuration[:index_name]
|
47
|
+
{ index_name: configuration[:index_name] }
|
48
|
+
else
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/geoapify'
|
5
|
+
|
6
|
+
module Geocoder
|
7
|
+
module Lookup
|
8
|
+
# https://apidocs.geoapify.com/docs/geocoding/api
|
9
|
+
class Geoapify < Base
|
10
|
+
def name
|
11
|
+
'Geoapify'
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_api_key_parts
|
15
|
+
['api_key']
|
16
|
+
end
|
17
|
+
|
18
|
+
def supported_protocols
|
19
|
+
[:https]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def base_query_url(query)
|
25
|
+
method = query.reverse_geocode? ? 'reverse' : 'search'
|
26
|
+
"https://api.geoapify.com/v1/geocode/#{method}?"
|
27
|
+
end
|
28
|
+
|
29
|
+
def results(query)
|
30
|
+
return [] unless (doc = fetch_data(query))
|
31
|
+
|
32
|
+
# The rest of the status codes should be already handled by the default
|
33
|
+
# functionality as the API returns correct HTTP response codes in most
|
34
|
+
# cases. There may be some unhandled cases still (such as over query
|
35
|
+
# limit reached) but there is not enough documentation to cover them.
|
36
|
+
case doc['statusCode']
|
37
|
+
when 500
|
38
|
+
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, doc['message'])
|
39
|
+
end
|
40
|
+
|
41
|
+
return [] unless doc['type'] == 'FeatureCollection'
|
42
|
+
return [] unless doc['features'] || doc['features'].present?
|
43
|
+
|
44
|
+
doc['features']
|
45
|
+
end
|
46
|
+
|
47
|
+
def query_url_params(query)
|
48
|
+
lang = query.language || configuration.language
|
49
|
+
params = { apiKey: configuration.api_key, lang: lang, limit: query.options[:limit] }
|
50
|
+
|
51
|
+
if query.reverse_geocode?
|
52
|
+
params.merge!(query_url_params_reverse(query))
|
53
|
+
else
|
54
|
+
params.merge!(query_url_params_coordinates(query))
|
55
|
+
end
|
56
|
+
|
57
|
+
params.merge!(super)
|
58
|
+
end
|
59
|
+
|
60
|
+
def query_url_params_coordinates(query)
|
61
|
+
{ text: query.sanitized_text }
|
62
|
+
end
|
63
|
+
|
64
|
+
def query_url_params_reverse(query)
|
65
|
+
{
|
66
|
+
lat: query.coordinates[0],
|
67
|
+
lon: query.coordinates[1]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -37,6 +37,10 @@ module Geocoder
|
|
37
37
|
def results(query)
|
38
38
|
return [] unless configuration[:file]
|
39
39
|
|
40
|
+
if @mmdb.respond_to?(:local_ip_alias) && !configuration[:local_ip_alias].nil?
|
41
|
+
@mmdb.local_ip_alias = configuration[:local_ip_alias]
|
42
|
+
end
|
43
|
+
|
40
44
|
result = @mmdb.lookup(query.to_s)
|
41
45
|
result.nil? ? [] : [result]
|
42
46
|
end
|
@@ -8,6 +8,10 @@ module Geocoder::Lookup
|
|
8
8
|
"IP2LocationApi"
|
9
9
|
end
|
10
10
|
|
11
|
+
def required_api_key_parts
|
12
|
+
['key']
|
13
|
+
end
|
14
|
+
|
11
15
|
def supported_protocols
|
12
16
|
[:http, :https]
|
13
17
|
end
|
@@ -15,15 +19,15 @@ module Geocoder::Lookup
|
|
15
19
|
private # ----------------------------------------------------------------
|
16
20
|
|
17
21
|
def base_query_url(query)
|
18
|
-
"#{protocol}://api.ip2location.com/?"
|
22
|
+
"#{protocol}://api.ip2location.com/v2/?"
|
19
23
|
end
|
20
24
|
|
21
25
|
def query_url_params(query)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
super.merge(
|
27
|
+
key: configuration.api_key,
|
28
|
+
ip: query.sanitized_text,
|
29
|
+
package: configuration[:package],
|
30
|
+
)
|
27
31
|
end
|
28
32
|
|
29
33
|
def results(query)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/ipqualityscore'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class Ipqualityscore < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"IPQualityScore"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
private # ---------------------------------------------------------------
|
18
|
+
|
19
|
+
def base_query_url(query)
|
20
|
+
"#{protocol}://ipqualityscore.com/api/json/ip/#{configuration.api_key}/#{query.sanitized_text}?"
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_response?(response)
|
24
|
+
if (json = parse_json(response.body))
|
25
|
+
success = json['success']
|
26
|
+
end
|
27
|
+
super && success == true
|
28
|
+
end
|
29
|
+
|
30
|
+
def results(query, reverse = false)
|
31
|
+
return [] unless doc = fetch_data(query)
|
32
|
+
|
33
|
+
return [doc] if doc['success']
|
34
|
+
|
35
|
+
case doc['message']
|
36
|
+
when /invalid (.*) key/i
|
37
|
+
raise_error Geocoder::InvalidApiKey ||
|
38
|
+
Geocoder.log(:warn, "#{name} API error: invalid api key.")
|
39
|
+
when /insufficient credits/, /exceeded your request quota/
|
40
|
+
raise_error Geocoder::OverQueryLimitError ||
|
41
|
+
Geocoder.log(:warn, "#{name} API error: query limit exceeded.")
|
42
|
+
when /invalid (.*) address/i
|
43
|
+
raise_error Geocoder::InvalidRequest ||
|
44
|
+
Geocoder.log(:warn, "#{name} API error: invalid request.")
|
45
|
+
end
|
46
|
+
|
47
|
+
[doc]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -30,7 +30,13 @@ module Geocoder::Lookup
|
|
30
30
|
def results(query)
|
31
31
|
if configuration[:file]
|
32
32
|
geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
|
33
|
-
|
33
|
+
geoip_instance = geoip_class.new(configuration[:file])
|
34
|
+
result =
|
35
|
+
if configuration[:package] == :country
|
36
|
+
geoip_instance.country(query.to_s)
|
37
|
+
else
|
38
|
+
geoip_instance.city(query.to_s)
|
39
|
+
end
|
34
40
|
result.nil? ? [] : [encode_hash(result.to_hash)]
|
35
41
|
elsif configuration[:package] == :city
|
36
42
|
addr = IPAddr.new(query.text).to_i
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/melissa_street"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class MelissaStreet < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"MelissaStreet"
|
9
|
+
end
|
10
|
+
|
11
|
+
def results(query)
|
12
|
+
return [] unless doc = fetch_data(query)
|
13
|
+
|
14
|
+
if doc["TransmissionResults"] == "GE05"
|
15
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
16
|
+
Geocoder.log(:warn, "Melissa service error: invalid API key.")
|
17
|
+
end
|
18
|
+
|
19
|
+
return doc["Records"]
|
20
|
+
end
|
21
|
+
|
22
|
+
private # ---------------------------------------------------------------
|
23
|
+
|
24
|
+
def base_query_url(query)
|
25
|
+
"#{protocol}://address.melissadata.net/v3/WEB/GlobalAddress/doGlobalAddress?"
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_url_params(query)
|
29
|
+
params = {
|
30
|
+
id: configuration.api_key,
|
31
|
+
format: "JSON",
|
32
|
+
a1: query.sanitized_text,
|
33
|
+
loc: query.options[:city],
|
34
|
+
admarea: query.options[:state],
|
35
|
+
postal: query.options[:postal],
|
36
|
+
ctry: query.options[:country]
|
37
|
+
}
|
38
|
+
params.merge(super)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/photon'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Photon < Base
|
6
|
+
def name
|
7
|
+
'Photon'
|
8
|
+
end
|
9
|
+
|
10
|
+
private # ---------------------------------------------------------------
|
11
|
+
|
12
|
+
def supported_protocols
|
13
|
+
[:https]
|
14
|
+
end
|
15
|
+
|
16
|
+
def base_query_url(query)
|
17
|
+
host = configuration[:host] || 'photon.komoot.io'
|
18
|
+
method = query.reverse_geocode? ? 'reverse' : 'api'
|
19
|
+
"#{protocol}://#{host}/#{method}?"
|
20
|
+
end
|
21
|
+
|
22
|
+
def results(query)
|
23
|
+
return [] unless (doc = fetch_data(query))
|
24
|
+
return [] unless doc['type'] == 'FeatureCollection'
|
25
|
+
return [] unless doc['features'] || doc['features'].present?
|
26
|
+
|
27
|
+
doc['features']
|
28
|
+
end
|
29
|
+
|
30
|
+
def query_url_params(query)
|
31
|
+
lang = query.language || configuration.language
|
32
|
+
params = { lang: lang, limit: query.options[:limit] }
|
33
|
+
|
34
|
+
if query.reverse_geocode?
|
35
|
+
params.merge!(query_url_params_reverse(query))
|
36
|
+
else
|
37
|
+
params.merge!(query_url_params_coordinates(query))
|
38
|
+
end
|
39
|
+
|
40
|
+
params.merge!(super)
|
41
|
+
end
|
42
|
+
|
43
|
+
def query_url_params_coordinates(query)
|
44
|
+
params = { q: query.sanitized_text }
|
45
|
+
|
46
|
+
if (bias = query.options[:bias])
|
47
|
+
params.merge!(lat: bias[:latitude], lon: bias[:longitude], location_bias_scale: bias[:scale])
|
48
|
+
end
|
49
|
+
|
50
|
+
if (filter = query_url_params_coordinates_filter(query))
|
51
|
+
params.merge!(filter)
|
52
|
+
end
|
53
|
+
|
54
|
+
params
|
55
|
+
end
|
56
|
+
|
57
|
+
def query_url_params_coordinates_filter(query)
|
58
|
+
filter = query.options[:filter]
|
59
|
+
return unless filter
|
60
|
+
|
61
|
+
bbox = filter[:bbox]
|
62
|
+
{
|
63
|
+
bbox: bbox.is_a?(Array) ? bbox.join(',') : bbox,
|
64
|
+
osm_tag: filter[:osm_tag]
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def query_url_params_reverse(query)
|
69
|
+
params = { lat: query.coordinates[0], lon: query.coordinates[1], radius: query.options[:radius] }
|
70
|
+
|
71
|
+
if (dsort = query.options[:distance_sort])
|
72
|
+
params[:distance_sort] = dsort ? 'true' : 'false'
|
73
|
+
end
|
74
|
+
|
75
|
+
if (filter = query_url_params_reverse_filter(query))
|
76
|
+
params.merge!(filter)
|
77
|
+
end
|
78
|
+
|
79
|
+
params
|
80
|
+
end
|
81
|
+
|
82
|
+
def query_url_params_reverse_filter(query)
|
83
|
+
filter = query.options[:filter]
|
84
|
+
return unless filter
|
85
|
+
|
86
|
+
{ query_string_filter: filter[:string] }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder
|
4
|
+
module Result
|
5
|
+
class AbstractApi < Base
|
6
|
+
|
7
|
+
##
|
8
|
+
# Geolocation
|
9
|
+
|
10
|
+
def state
|
11
|
+
@data['region']
|
12
|
+
end
|
13
|
+
|
14
|
+
def state_code
|
15
|
+
@data['region_iso_code']
|
16
|
+
end
|
17
|
+
|
18
|
+
def city
|
19
|
+
@data["city"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def city_geoname_id
|
23
|
+
@data["city_geoname_id"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def region_geoname_id
|
27
|
+
@data["region_geoname_id"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def postal_code
|
31
|
+
@data["postal_code"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def country
|
35
|
+
@data["country"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def country_code
|
39
|
+
@data["country_code"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def country_geoname_id
|
43
|
+
@data["country_geoname_id"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def country_is_eu
|
47
|
+
@data["country_is_eu"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def continent
|
51
|
+
@data["continent"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def continent_code
|
55
|
+
@data["continent_code"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def continent_geoname_id
|
59
|
+
@data["continent_geoname_id"]
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Security
|
64
|
+
|
65
|
+
def is_vpn?
|
66
|
+
@data.dig "security", "is_vpn"
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Timezone
|
71
|
+
|
72
|
+
def timezone_name
|
73
|
+
@data.dig "timezone", "name"
|
74
|
+
end
|
75
|
+
|
76
|
+
def timezone_abbreviation
|
77
|
+
@data.dig "timezone", "abbreviation"
|
78
|
+
end
|
79
|
+
|
80
|
+
def timezone_gmt_offset
|
81
|
+
@data.dig "timezone", "gmt_offset"
|
82
|
+
end
|
83
|
+
|
84
|
+
def timezone_current_time
|
85
|
+
@data.dig "timezone", "current_time"
|
86
|
+
end
|
87
|
+
|
88
|
+
def timezone_is_dst
|
89
|
+
@data.dig "timezone", "is_dst"
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Flag
|
94
|
+
|
95
|
+
def flag_emoji
|
96
|
+
@data.dig "flag", "emoji"
|
97
|
+
end
|
98
|
+
|
99
|
+
def flag_unicode
|
100
|
+
@data.dig "flag", "unicode"
|
101
|
+
end
|
102
|
+
|
103
|
+
def flag_png
|
104
|
+
@data.dig "flag", "png"
|
105
|
+
end
|
106
|
+
|
107
|
+
def flag_svg
|
108
|
+
@data.dig "flag", "svg"
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Currency
|
113
|
+
|
114
|
+
def currency_currency_name
|
115
|
+
@data.dig "currency", "currency_name"
|
116
|
+
end
|
117
|
+
|
118
|
+
def currency_currency_code
|
119
|
+
@data.dig "currency", "currency_code"
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Connection
|
124
|
+
|
125
|
+
def connection_autonomous_system_number
|
126
|
+
@data.dig "connection", "autonomous_system_number"
|
127
|
+
end
|
128
|
+
|
129
|
+
def connection_autonomous_system_organization
|
130
|
+
@data.dig "connection", "autonomous_system_organization"
|
131
|
+
end
|
132
|
+
|
133
|
+
def connection_connection_type
|
134
|
+
@data.dig "connection", "connection_type"
|
135
|
+
end
|
136
|
+
|
137
|
+
def connection_isp_name
|
138
|
+
@data.dig "connection", "isp_name"
|
139
|
+
end
|
140
|
+
|
141
|
+
def connection_organization_name
|
142
|
+
@data.dig "connection", "organization_name"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|