geostock 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|