tenka 1.0.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 +7 -0
- data/README +24 -0
- data/Rakefile +33 -0
- data/doc/TODO +0 -0
- data/lib/tenka_client.rb +176 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 724361046f8874506dff4a9eaaabc8ff9fcb28fa
|
4
|
+
data.tar.gz: 52735cb687afdaf5a5ef8cf5c183511c70f0abab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c083c3566b6a72c9e01bbc3e62c6f939c9d129de9bc1cc2bac859cd86b4f4efbcad4556672fbbfe4fa63934474579de87a78580ff0773fca7d2a3b1c3f82ee4c
|
7
|
+
data.tar.gz: 601e02c7fb7ef93f3a4614548d32f933535839b7c5ce6314e1093951fd3b3476168fdcf168928a6e8fa7f26f3b7c891a6df085a65e4031c2b4f5418a8a4c67d5
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems/package_task'
|
2
|
+
require 'rdoc/task'
|
3
|
+
|
4
|
+
$: << "#{File.dirname(__FILE__)}/lib"
|
5
|
+
|
6
|
+
spec = eval File.read(Dir['*.gemspec'][0])
|
7
|
+
|
8
|
+
Rake::RDocTask.new(:doc) { |t|
|
9
|
+
t.main = 'README'
|
10
|
+
t.rdoc_files.include 'lib/**/*.rb', 'doc/*', 'bin/*', 'ext/**/*.c',
|
11
|
+
'ext/**/*.rb'
|
12
|
+
t.options << '-S' << '-N'
|
13
|
+
t.rdoc_dir = 'doc/rdoc'
|
14
|
+
}
|
15
|
+
|
16
|
+
Gem::PackageTask.new(spec) { |pkg|
|
17
|
+
pkg.need_tar_bz2 = true
|
18
|
+
}
|
19
|
+
desc "Cleans out the packaged files."
|
20
|
+
task(:clean) {
|
21
|
+
FileUtils.rm_rf 'pkg'
|
22
|
+
}
|
23
|
+
|
24
|
+
desc "Builds and installs the gem for #{spec.name}"
|
25
|
+
task(:install => :package) {
|
26
|
+
g = "pkg/#{spec.name}-#{spec.version}.gem"
|
27
|
+
system "gem install -l #{g}"
|
28
|
+
}
|
29
|
+
|
30
|
+
desc "Runs IRB, automatically require()ing #{spec.name}."
|
31
|
+
task(:irb) {
|
32
|
+
exec "irb -Ilib -r#{spec.name}"
|
33
|
+
}
|
data/doc/TODO
ADDED
File without changes
|
data/lib/tenka_client.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# Copyright © 2017-2018 Rekka Labs (https://rekka.io/)
|
2
|
+
# See LICENSE for licensing information.
|
3
|
+
|
4
|
+
%w(
|
5
|
+
json
|
6
|
+
|
7
|
+
uri cgi net/http
|
8
|
+
set
|
9
|
+
).each &method(:require)
|
10
|
+
|
11
|
+
module Tenka
|
12
|
+
# The main class for the client.
|
13
|
+
# TODO: Provide usage examples here.
|
14
|
+
class Client
|
15
|
+
# The defaults when initializing a client.
|
16
|
+
# `host` specifies the hostname to connect to. You probably won't
|
17
|
+
# need to change this.
|
18
|
+
# `ssl` turns HTTPS on or off. If you are using an API key, you
|
19
|
+
# probably want to leave it on.
|
20
|
+
# `port` specifies the port to connect to.
|
21
|
+
DefaultOpts = {
|
22
|
+
host: 'api.tenka.io',
|
23
|
+
port: 443,
|
24
|
+
ssl: true,
|
25
|
+
api_key: nil,
|
26
|
+
}.freeze
|
27
|
+
DefaultOpts.each_key { |k| define_method(k) { opts[k] } }
|
28
|
+
|
29
|
+
# For endpoints that require units to be specified, this is the
|
30
|
+
# list of units.
|
31
|
+
Units = Set.new %w(
|
32
|
+
mile
|
33
|
+
km
|
34
|
+
)
|
35
|
+
|
36
|
+
attr_accessor :opts, :last_resp,
|
37
|
+
:last_error,
|
38
|
+
:rate_limit_calls_left,
|
39
|
+
:api_tokens_left
|
40
|
+
|
41
|
+
# Creates a new client. To simplify the API, the client carries
|
42
|
+
# information in the form of state, and thus is not thread-safe;
|
43
|
+
# you should instantiate one client per thread that accesses Tenka.
|
44
|
+
def initialize opts = {}
|
45
|
+
self.opts = DefaultOpts.merge(opts)
|
46
|
+
|
47
|
+
# If they don't specify a port but they do turn off SSL, we set
|
48
|
+
# the port to 80.
|
49
|
+
if !opts.has_key?(port) && !ssl
|
50
|
+
self.opts[:port] = 80
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def last_error
|
55
|
+
return nil if !last_resp || last_resp.code[0] == '2'
|
56
|
+
h = begin
|
57
|
+
JSON.parse(last_resp.body)
|
58
|
+
rescue JSON::ParserError => e
|
59
|
+
# TODO: Might wanna dependency-inject a logger for cases
|
60
|
+
# like this.
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
h
|
65
|
+
end
|
66
|
+
|
67
|
+
# The individual endpoints follow:
|
68
|
+
|
69
|
+
# Reverse-geocode a latitude/longitude pair.
|
70
|
+
def containing_lat_long lat, long
|
71
|
+
ok, body = get('/containing/lat-long', lat: lat, long: long)
|
72
|
+
ok && body
|
73
|
+
end
|
74
|
+
alias_method :containing_lat_lon, :containing_lat_long
|
75
|
+
|
76
|
+
# Reverse-geocode a ZIP code centroid. (Tenka only supports US ZIPs
|
77
|
+
# for now, but this is not enforced client-side.)
|
78
|
+
#
|
79
|
+
# Note that ZIP codes often describe very odd shapes; they are based
|
80
|
+
# on postal service routes rather than geographical boundaries.
|
81
|
+
# As a result, the centroid may lie in a different city than any
|
82
|
+
# single point within the actual boundaries of the ZIP code. (ZIP
|
83
|
+
# centroids are popular because of their granularity, but they should
|
84
|
+
# be used with caution.)
|
85
|
+
#
|
86
|
+
# ZIP codes can start with leading zeroes. It is advised to
|
87
|
+
# use a string to represent a ZIP code rather than an integer.
|
88
|
+
def containing_zip zip
|
89
|
+
ok, body = get('/containing/zip', zip: zip)
|
90
|
+
ok && body
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a list of ZIP codes whose centroids are within a given
|
94
|
+
# radius of another ZIP code's centroid. (See the remarks about
|
95
|
+
# centroids in #containing_zip.)
|
96
|
+
def nearby_zip zip, radius, units = 'mile'
|
97
|
+
unless Units.include?(units)
|
98
|
+
raise ArgumentError, "Invalid unit #{units}. Must be one "\
|
99
|
+
"of #{Units.to_a.join(', ')}."
|
100
|
+
end
|
101
|
+
ok, body = get('/nearby/zip',
|
102
|
+
zip: zip, radius: radius, units: units)
|
103
|
+
ok && body['zips']
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns the number of calls your API token has left, as well as
|
107
|
+
# how many calls you can make before you hit the rate limit for the
|
108
|
+
# server.
|
109
|
+
#
|
110
|
+
# This information is automatically gathered (whether your API key
|
111
|
+
# is valid or not) on every request, so you can also just check
|
112
|
+
# Tenka::Client#rate_limit_calls_left and Tenka::Client#api_tokens_left.
|
113
|
+
#
|
114
|
+
# Making a request against this endpoint does not reduce the number
|
115
|
+
# of API tokens you have left. (It does count towards the rate limit.)
|
116
|
+
#
|
117
|
+
# A 404 from this endpoint indicates that your API key is invalid.
|
118
|
+
def calls_left
|
119
|
+
ok, body = get('/tokens-remaining')
|
120
|
+
ok && {
|
121
|
+
rate_limit: rate_limit_calls_left,
|
122
|
+
api_limit: api_tokens_left,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def get path, query = nil
|
129
|
+
req_headers = {}
|
130
|
+
if api_key
|
131
|
+
req_headers['API-Token'] = api_key
|
132
|
+
end
|
133
|
+
path = path + h2query(query) if query
|
134
|
+
http_req Net::HTTP::Get.new(path, req_headers)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns [true/false, parsed_body, response_object].
|
138
|
+
def http_req req, body = nil
|
139
|
+
resp = Net::HTTP.start(host, port, use_ssl: ssl) { |h|
|
140
|
+
h.request req, body
|
141
|
+
}
|
142
|
+
body = JSON.parse(resp.body)
|
143
|
+
self.last_resp = resp
|
144
|
+
update_counters!
|
145
|
+
|
146
|
+
# Error detection is easy for Tenka.
|
147
|
+
[resp.code[0] == '2', body]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Check rate limits and API tokens remaining in the headers that came
|
151
|
+
# back;
|
152
|
+
def update_counters!
|
153
|
+
if l = last_resp['rate-limit-calls-left']
|
154
|
+
self.rate_limit_calls_left = l.to_i
|
155
|
+
end
|
156
|
+
|
157
|
+
if l = last_resp['api-token-calls-remaining']
|
158
|
+
self.api_tokens_left = l.to_i
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def server_uri
|
163
|
+
# Under normal circumstances, `host` shouldn't change (just start
|
164
|
+
# a new client).
|
165
|
+
@_server_uri ||= URI("http#{ssl ? 's' : ''}://#{host}/")
|
166
|
+
end
|
167
|
+
|
168
|
+
def h2query h
|
169
|
+
'?' <<
|
170
|
+
h.map { |k,v|
|
171
|
+
(CGI.escape(k.to_s) << '=' << CGI.escape(v.to_s)).
|
172
|
+
gsub('+', '%20')
|
173
|
+
}.join('&')
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tenka
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pete Elmore
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: |
|
28
|
+
Tenka is a REST API that lets you do GIS operations. It makes it easy
|
29
|
+
to add intelligence about the earth to your applications.
|
30
|
+
email:
|
31
|
+
- pete@tenka.io
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files:
|
35
|
+
- doc/TODO
|
36
|
+
- README
|
37
|
+
files:
|
38
|
+
- README
|
39
|
+
- Rakefile
|
40
|
+
- doc/TODO
|
41
|
+
- lib/tenka_client.rb
|
42
|
+
homepage: https://github.com/tenka/tenka-client-ruby
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.2.0
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.6.11
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: A client for Tenka's REST API.
|
66
|
+
test_files: []
|