geostock 0.0.2
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.
- data/.gitignore +4 -0
- data/Gemfile +8 -0
- data/Rakefile +1 -0
- data/geostock.gemspec +20 -0
- data/lib/geostock.rb +7 -0
- data/lib/geostock/api.rb +132 -0
- data/lib/geostock/util.rb +34 -0
- data/lib/geostock/version.rb +3 -0
- data/spec/lib/geostock/api_spec.rb +76 -0
- data/spec/spec_helper.rb +8 -0
- metadata +59 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/geostock.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "geostock/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "geostock"
|
7
|
+
s.version = GeoStock::VERSION
|
8
|
+
s.authors = ["CHIKURA Shinsaku"]
|
9
|
+
s.email = ["chsh@thinq.jp"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{GeoStock API for Ruby}
|
12
|
+
s.description = %q{GeoStock API for Ruby}
|
13
|
+
|
14
|
+
s.rubyforge_project = "geostock"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
data/lib/geostock.rb
ADDED
data/lib/geostock/api.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'base64'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'hmac'
|
6
|
+
require 'hmac-sha2'
|
7
|
+
require 'cgi'
|
8
|
+
|
9
|
+
module GeoStock
|
10
|
+
class API
|
11
|
+
REQUEST_EXPIRATION_TIME = 10 * 60 # 10 minutes
|
12
|
+
REQUEST_URI_BASE = 'http://geostock.jp/api'
|
13
|
+
|
14
|
+
def initialize(api_key, api_secret)
|
15
|
+
raise "API_KEY must be present." if api_key.nil?
|
16
|
+
raise "API_SECRET must be present." if api_secret.nil?
|
17
|
+
@api_token = api_key
|
18
|
+
@api_secret_token = api_secret
|
19
|
+
end
|
20
|
+
|
21
|
+
def collections
|
22
|
+
get :collections, refresh: 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_poi(col_name, value)
|
26
|
+
update_pois col_name, value
|
27
|
+
end
|
28
|
+
def update_pois(col_name, value)
|
29
|
+
post(:update_pois, col_name => value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_poi(value)
|
33
|
+
delete_pois(value)
|
34
|
+
end
|
35
|
+
def delete_pois(value)
|
36
|
+
post(:update_pois, value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_poi(col_name, uid)
|
40
|
+
get :get, col: col_name, id: uid
|
41
|
+
end
|
42
|
+
def get_all_pois(col_name)
|
43
|
+
get :get_all, col: col_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_collection(col_name)
|
47
|
+
create_collections col_name
|
48
|
+
end
|
49
|
+
def create_collections(*col_names)
|
50
|
+
col_names = [col_names].flatten
|
51
|
+
post(:update_collections, col_names)
|
52
|
+
end
|
53
|
+
def update_collection(value)
|
54
|
+
update_collections(value)
|
55
|
+
end
|
56
|
+
def update_collections(value)
|
57
|
+
post(:update_collections, value)
|
58
|
+
end
|
59
|
+
def delete_collection(col_name)
|
60
|
+
delete_collections(col_name)
|
61
|
+
end
|
62
|
+
def delete_collections(*col_names)
|
63
|
+
col_names = [col_names].flatten
|
64
|
+
post(:delete_collections, col_names)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def sign_request(value)
|
69
|
+
text = b64encode(generate_json(value))
|
70
|
+
cur = (Time.now.utc.to_i / REQUEST_EXPIRATION_TIME)
|
71
|
+
d = HMAC::SHA256.new(@api_secret_token)
|
72
|
+
d.update text
|
73
|
+
d.update cur.to_s
|
74
|
+
[d.hexdigest, text].join('.')
|
75
|
+
end
|
76
|
+
def b64encode(text)
|
77
|
+
Base64.encode64(text).tr('+/', '-_').gsub(/\n/, '')
|
78
|
+
end
|
79
|
+
def b64decode(text)
|
80
|
+
Base64.decode64(text.tr('-_', '+/').gsub(/\n/, ''))
|
81
|
+
end
|
82
|
+
def generate_json(value)
|
83
|
+
JSON.generate value
|
84
|
+
end
|
85
|
+
|
86
|
+
CMD2PATH = {
|
87
|
+
delete_collections: 'collections/delete',
|
88
|
+
update_collections: 'collections/update',
|
89
|
+
delete_pois: 'pois/delete',
|
90
|
+
update_pois: 'pois/update',
|
91
|
+
collections: 'collections'
|
92
|
+
}
|
93
|
+
def post(cmd, value)
|
94
|
+
params = { signed_request: sign_request(value)}
|
95
|
+
path = CMD2PATH[cmd]
|
96
|
+
raise "Unknown cmd:#{cmd}" unless path
|
97
|
+
uri = URI.parse("#{url_base}/#{path}")
|
98
|
+
post_to(uri, params)
|
99
|
+
end
|
100
|
+
def post_to(uri, params)
|
101
|
+
query_string = params_to_query(params)
|
102
|
+
resp = Net::HTTP.start(uri.host, uri.port) do |http|
|
103
|
+
http.send(:post, uri.path, query_string)
|
104
|
+
end
|
105
|
+
rb = JSON.parse(resp.body)
|
106
|
+
raise "Response body must be Hash or Array. (#{rb.class})" unless (rb.is_a?(Hash) || rb.is_a?(Array))
|
107
|
+
GeoStock::Response.from(rb, code: resp.code, message: rb.is_a?(Hash) ? rb['message'] : nil)
|
108
|
+
end
|
109
|
+
def get(cmd, params = {})
|
110
|
+
uri = URI.parse("#{url_base}/#{cmd}")
|
111
|
+
get_from(uri, params)
|
112
|
+
end
|
113
|
+
def get_from(uri, params = {})
|
114
|
+
query_string = params_to_query(params)
|
115
|
+
resp = Net::HTTP.start(uri.host, uri.port) do |http|
|
116
|
+
path = "#{uri.path}?#{query_string}"
|
117
|
+
http.send(:get, path)
|
118
|
+
end
|
119
|
+
rb = JSON.parse(resp.body)
|
120
|
+
raise "Response body must be Hash or Array. (#{rb.class})" unless (rb.is_a?(Hash) || rb.is_a?(Array))
|
121
|
+
GeoStock::Response.from(rb, code: resp.code, message: rb.is_a?(Hash) ? rb['message'] : nil)
|
122
|
+
end
|
123
|
+
def url_base
|
124
|
+
"#{REQUEST_URI_BASE}/#{@api_token}"
|
125
|
+
end
|
126
|
+
def params_to_query(params)
|
127
|
+
params.map do |key,value|
|
128
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
|
129
|
+
end.join("&")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module GeoStock
|
3
|
+
module Response
|
4
|
+
def self.from(value, opts = {})
|
5
|
+
case value
|
6
|
+
when Hash then ResponseHash.from(value, opts)
|
7
|
+
when Array then ResponseArray.from(value, opts)
|
8
|
+
else raise "Unexpected class. (#{value.class})"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class ResponseHash < Hash
|
13
|
+
attr_accessor :code, :message
|
14
|
+
def self.from(value, opts)
|
15
|
+
h = new
|
16
|
+
value.each do |k, v|
|
17
|
+
h[k] = v
|
18
|
+
end
|
19
|
+
h.code = opts[:code]
|
20
|
+
h.message = opts[:message]
|
21
|
+
h
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class ResponseArray < Array
|
25
|
+
attr_accessor :code, :message
|
26
|
+
def self.from(value, opts)
|
27
|
+
a = new
|
28
|
+
a.push *value
|
29
|
+
a.code = opts[:code]
|
30
|
+
a.message = opts[:message]
|
31
|
+
a
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe GeoStock::API do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@api_token = ENV['GEOSTOCK_API_TOKEN']
|
9
|
+
@api_secret_token = ENV['GEOSTOCK_API_SECRET']
|
10
|
+
GeoStock::API::REQUEST_URI_BASE = ENV['GEOSTOCK_API_REQUEST_BASE']
|
11
|
+
@api = GeoStock::API.new @api_token, @api_secret_token
|
12
|
+
@api.delete_collections 'hello', 'world'
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each) do
|
16
|
+
@api.delete_collections 'hello', 'world'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should manipulate collections' do
|
20
|
+
@api.collections.should == []
|
21
|
+
@api.create_collections 'hello', 'world'
|
22
|
+
@api.collections.should == ['hello', 'world']
|
23
|
+
@api.delete_collections 'hello'
|
24
|
+
@api.collections.should == ['world']
|
25
|
+
@api.delete_collections 'world'
|
26
|
+
@api.collections.should == []
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should manipulate pois.' do
|
30
|
+
@api = GeoStock::API.new @api_token, @api_secret_token
|
31
|
+
@api.create_collection 'world'
|
32
|
+
@api.update_pois 'world', [
|
33
|
+
{uid: '123', ll: '38.111234,138.44555', attrs: {
|
34
|
+
url: 'http://www.yahoo.co.jp/',
|
35
|
+
title: 'ほんじゃまか',
|
36
|
+
desc: '解説文'
|
37
|
+
}
|
38
|
+
}
|
39
|
+
]
|
40
|
+
@api.update_pois 'world', [
|
41
|
+
{uid: '124', ll: '38.111234,138.445551', attrs: {
|
42
|
+
url: 'http://www.yahoo.co.jp/',
|
43
|
+
title: 'メロン',
|
44
|
+
desc: 'くだもの'
|
45
|
+
}
|
46
|
+
}
|
47
|
+
]
|
48
|
+
poi_not_found = @api.get_poi('world', '125')
|
49
|
+
poi_not_found.code.should == '404'
|
50
|
+
poi_data = @api.get_poi('world', '124')
|
51
|
+
poi_data.should == {
|
52
|
+
'uid' =>'124',
|
53
|
+
'attrs' => { 'url' => 'http://www.yahoo.co.jp/',
|
54
|
+
'title' => 'メロン',
|
55
|
+
'desc' => 'くだもの'
|
56
|
+
},
|
57
|
+
'll' => '38.111234,138.445551'
|
58
|
+
}
|
59
|
+
|
60
|
+
pois = @api.get_all_pois('world')
|
61
|
+
pois.should == [
|
62
|
+
{'uid' => '123', 'll' => '38.111234,138.44555', 'attrs' => {
|
63
|
+
'url' => 'http://www.yahoo.co.jp/',
|
64
|
+
'title' => 'ほんじゃまか',
|
65
|
+
'desc' => '解説文'
|
66
|
+
}
|
67
|
+
},
|
68
|
+
{'uid' => '124', 'll' => '38.111234,138.445551', 'attrs' => {
|
69
|
+
'url' => 'http://www.yahoo.co.jp/',
|
70
|
+
'title' => 'メロン',
|
71
|
+
'desc' => 'くだもの'
|
72
|
+
}
|
73
|
+
}
|
74
|
+
]
|
75
|
+
end
|
76
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geostock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- CHIKURA Shinsaku
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-31 00:00:00.000000000 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
description: GeoStock API for Ruby
|
16
|
+
email:
|
17
|
+
- chsh@thinq.jp
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- Rakefile
|
25
|
+
- geostock.gemspec
|
26
|
+
- lib/geostock.rb
|
27
|
+
- lib/geostock/api.rb
|
28
|
+
- lib/geostock/util.rb
|
29
|
+
- lib/geostock/version.rb
|
30
|
+
- spec/lib/geostock/api_spec.rb
|
31
|
+
- spec/spec_helper.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: ''
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project: geostock
|
53
|
+
rubygems_version: 1.6.2
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: GeoStock API for Ruby
|
57
|
+
test_files:
|
58
|
+
- spec/lib/geostock/api_spec.rb
|
59
|
+
- spec/spec_helper.rb
|