drink-socially 0.0.4
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/LICENSE +674 -0
- data/README.md +54 -0
- data/config/endpoints.yml +231 -0
- data/lib/drink-socially.rb +43 -0
- data/lib/drink-socially/api.rb +124 -0
- data/lib/drink-socially/api/credential.rb +69 -0
- data/lib/drink-socially/api/notification.rb +13 -0
- data/lib/drink-socially/api/object.rb +83 -0
- data/lib/drink-socially/api/pagination.rb +73 -0
- data/lib/drink-socially/api/rate_limit.rb +17 -0
- data/lib/drink-socially/api/url_tokenizer.rb +47 -0
- data/lib/drink-socially/config.rb +48 -0
- data/lib/drink-socially/extensions/hash.rb +17 -0
- data/lib/drink-socially/http_service.rb +61 -0
- data/lib/drink-socially/http_service/response.rb +27 -0
- data/lib/drink-socially/version.rb +8 -0
- data/spec/cases/drink-socially/api/credential_spec.rb +107 -0
- data/spec/cases/drink-socially/api/object_spec.rb +112 -0
- data/spec/cases/drink-socially/api/pagination_spec.rb +43 -0
- data/spec/cases/drink-socially/api/rate_limit_spec.rb +15 -0
- data/spec/cases/drink-socially/api/url_tokenizer_spec.rb +41 -0
- data/spec/cases/drink-socially/api_spec.rb +79 -0
- data/spec/cases/drink-socially/config_spec.rb +95 -0
- data/spec/cases/drink-socially/extensions/hash_spec.rb +17 -0
- data/spec/cases/drink-socially/http_service/response_spec.rb +38 -0
- data/spec/cases/drink-socially/http_service_spec.rb +70 -0
- data/spec/cases/drink-socially/version_spec.rb +14 -0
- data/spec/cases/drink-socially_spec.rb +41 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/config.yml +3 -0
- metadata +202 -0
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# drink-socially
|
2
|
+
|
3
|
+
[](http://travis-ci.org/NewRepublicBrewing/drink-socially)
|
4
|
+
[](https://gemnasium.com/NewRepublicBrewing/drink-socially)
|
5
|
+
[](https://codeclimate.com/github/NewRepublicBrewing/drink-socially)
|
6
|
+
|
7
|
+
A gem for interfacing with the Untappd API
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
Ruby 1.9
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Acting as a person
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'drink-socially'
|
19
|
+
|
20
|
+
# Per-user access token taken from OAuth
|
21
|
+
brundage = NRB::Untappd::API.new access_token: '7A23A8BEER81D2580E&CEFC405C60693AC476AA'
|
22
|
+
|
23
|
+
new_republic = brundage.brewery_info 8767
|
24
|
+
=> #<Hashie::Mash beer_count=13 beer_list=....
|
25
|
+
|
26
|
+
new_republic.brewery_name
|
27
|
+
=> "New Republic Brewing Company"
|
28
|
+
|
29
|
+
```
|
30
|
+
|
31
|
+
### Acting as an app
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# Get your id & secret from http://untappd.com/api/dashboard
|
35
|
+
new_republic_app = NRB::Untappd::API.new client_id: '645c10bc59f30e34d6fd265cfdeb75e', client_secret: '9ffe686c814207df12f9b0e0bc0cdab'
|
36
|
+
```
|
37
|
+
|
38
|
+
## Methods
|
39
|
+
|
40
|
+
### NRB::Untappd::API
|
41
|
+
|
42
|
+
`new` takes a user access token or a application id and secret. Once you have an instance of the API you can make calls on behalf of the user or application.
|
43
|
+
|
44
|
+
The Untappd api enforces a rate limit per token. After the first call you can ask your object the current limit with the `rate_limit` call.
|
45
|
+
|
46
|
+
```
|
47
|
+
brundage.rate_limit
|
48
|
+
=> @rate_limit= #<NRB::Untappd::API::RateLimit:0x930af6c @limit="100", @remaining="99">>
|
49
|
+
```
|
50
|
+
|
51
|
+
All API calls return an `NRB::Untappd::API::Response` object. You can access the full response object with the `last_response` method.
|
52
|
+
|
53
|
+
Full documentation for the API calls are detailed [in the wiki](drink-socially/wiki/api_calls). Also have a look at the [Untappd v4 API documentation](http://untappd.com/api/docs/v4) for details.
|
54
|
+
|
@@ -0,0 +1,231 @@
|
|
1
|
+
---
|
2
|
+
:accept_friend:
|
3
|
+
:endpoint: "friend/accept/:user_id:"
|
4
|
+
:required_args:
|
5
|
+
- :user_id
|
6
|
+
:verb: :post
|
7
|
+
|
8
|
+
:add_comment:
|
9
|
+
:endpoint: "checkin/addcomment/:checkin_id:"
|
10
|
+
:required_args:
|
11
|
+
- :checkin_id
|
12
|
+
- :comment
|
13
|
+
:results_path:
|
14
|
+
- :response
|
15
|
+
- :comments
|
16
|
+
- :items
|
17
|
+
:verb: :post
|
18
|
+
|
19
|
+
:add_to_wish_list:
|
20
|
+
:endpoint: user/wishlist/add
|
21
|
+
:method_aliases:
|
22
|
+
- :add_to_wishlist
|
23
|
+
:required_args:
|
24
|
+
- :bid
|
25
|
+
:results_path:
|
26
|
+
- :response
|
27
|
+
- :beer
|
28
|
+
|
29
|
+
:beer_checkins:
|
30
|
+
:endpoint: "beer/checkins/:bid:"
|
31
|
+
:method_aliases:
|
32
|
+
- :beer_feed
|
33
|
+
:required_args:
|
34
|
+
- :bid
|
35
|
+
:results_path:
|
36
|
+
- :response
|
37
|
+
- :checkins
|
38
|
+
- :items
|
39
|
+
|
40
|
+
:beer_info:
|
41
|
+
:endpoint: "beer/info/:bid:"
|
42
|
+
:required_args:
|
43
|
+
- :bid
|
44
|
+
:results_path:
|
45
|
+
- :response
|
46
|
+
- :beer
|
47
|
+
|
48
|
+
:beer_search:
|
49
|
+
:endpoint: search/beer
|
50
|
+
:required_args:
|
51
|
+
- :q
|
52
|
+
|
53
|
+
:brewery_checkins:
|
54
|
+
:endpoint: "brewery/checkins/:brewery_id:"
|
55
|
+
:method_aliases:
|
56
|
+
- :brewery_feed
|
57
|
+
:required_args:
|
58
|
+
- :brewery_id
|
59
|
+
:results_path:
|
60
|
+
- :response
|
61
|
+
- :checkins
|
62
|
+
- :items
|
63
|
+
|
64
|
+
:brewery_info:
|
65
|
+
:endpoint: "brewery/info/:brewery_id:"
|
66
|
+
:required_args:
|
67
|
+
- :brewery_id
|
68
|
+
:results_path:
|
69
|
+
- :response
|
70
|
+
- :brewery
|
71
|
+
|
72
|
+
:brewery_search:
|
73
|
+
:endpoint: search/brewery
|
74
|
+
:required_args:
|
75
|
+
- :q
|
76
|
+
:results_path:
|
77
|
+
- :response
|
78
|
+
- :brewery
|
79
|
+
- :items
|
80
|
+
|
81
|
+
:checkin_info:
|
82
|
+
:endpoint: "checkin/view/:checkin_id:"
|
83
|
+
:required_args:
|
84
|
+
- :checkin_id
|
85
|
+
:results_path:
|
86
|
+
- :response
|
87
|
+
- :checkin
|
88
|
+
|
89
|
+
:delete_comment:
|
90
|
+
:endpoint: "checkin/deletecomment/:comment_id:"
|
91
|
+
:method_aliases:
|
92
|
+
- :remove_comment
|
93
|
+
:required_args:
|
94
|
+
- :comment_id
|
95
|
+
:results_path:
|
96
|
+
- :response
|
97
|
+
- :comments
|
98
|
+
:verb: :post
|
99
|
+
|
100
|
+
:foursquare_venue_info:
|
101
|
+
:endpoint: "venue/foursquare_lookup/:venue_id:"
|
102
|
+
:required_args:
|
103
|
+
- :venue_id
|
104
|
+
:results_path:
|
105
|
+
- :response
|
106
|
+
- :venue
|
107
|
+
- :items
|
108
|
+
- :first
|
109
|
+
:verb: :post
|
110
|
+
|
111
|
+
:friend_feed:
|
112
|
+
:endpoint: checkin/recent
|
113
|
+
:results_path:
|
114
|
+
- :response
|
115
|
+
- :checkins
|
116
|
+
- :items
|
117
|
+
|
118
|
+
:news:
|
119
|
+
:endpoint: notifications
|
120
|
+
:results_path:
|
121
|
+
- :response
|
122
|
+
- :news
|
123
|
+
- :items
|
124
|
+
|
125
|
+
:notifications:
|
126
|
+
:endpoint: notifications
|
127
|
+
:results_path:
|
128
|
+
- :response
|
129
|
+
- :notifications
|
130
|
+
- :items
|
131
|
+
|
132
|
+
:pending_friends:
|
133
|
+
:endpoint: user/pending
|
134
|
+
:results_path:
|
135
|
+
- :response
|
136
|
+
|
137
|
+
:reject_friend:
|
138
|
+
:endpoint: "friend/reject/:user_id:"
|
139
|
+
:required_args:
|
140
|
+
- :user_id
|
141
|
+
:verb: :post
|
142
|
+
|
143
|
+
:remove_friend:
|
144
|
+
:endpoint: "friend/remove/:user_id:"
|
145
|
+
:required_args:
|
146
|
+
- :user_id
|
147
|
+
|
148
|
+
:remove_from_wish_list:
|
149
|
+
:endpoint: user/wishlist/remove
|
150
|
+
:method_aliases:
|
151
|
+
- :delete_from_wish_list
|
152
|
+
:required_args:
|
153
|
+
- :bid
|
154
|
+
|
155
|
+
:request_friend:
|
156
|
+
:endpoint: "friend/request/:user_id:"
|
157
|
+
:required_args:
|
158
|
+
- :user_id
|
159
|
+
|
160
|
+
:the_pub:
|
161
|
+
:endpoint: thepub
|
162
|
+
:results_path:
|
163
|
+
- :response
|
164
|
+
- :checkins
|
165
|
+
- :items
|
166
|
+
|
167
|
+
:trending:
|
168
|
+
:endpoint: beer/trending
|
169
|
+
|
170
|
+
:toast:
|
171
|
+
:endpoint: "checkin/toast/:checkin_id:"
|
172
|
+
:method_aliases:
|
173
|
+
- :add_toast
|
174
|
+
- :delete_toast
|
175
|
+
:required_args:
|
176
|
+
- :checkin_id
|
177
|
+
|
178
|
+
:user_badges:
|
179
|
+
:endpoint: "user/badges/:username:"
|
180
|
+
|
181
|
+
:user_distinct_beers:
|
182
|
+
:endpoint: "user/beers/:username:"
|
183
|
+
:method_aliases:
|
184
|
+
- :user_beers
|
185
|
+
:results_path:
|
186
|
+
- :response
|
187
|
+
- :beers
|
188
|
+
- :items
|
189
|
+
|
190
|
+
:user_feed:
|
191
|
+
:endpoint: "user/checkins/:username:"
|
192
|
+
:results_path:
|
193
|
+
- :response
|
194
|
+
- :checkins
|
195
|
+
- :items
|
196
|
+
|
197
|
+
:user_friends:
|
198
|
+
:endpoint: "user/friends/:username:"
|
199
|
+
:results_path:
|
200
|
+
- :response
|
201
|
+
- :items
|
202
|
+
|
203
|
+
:user_info:
|
204
|
+
:endpoint: "user/info/:username:"
|
205
|
+
:results_path:
|
206
|
+
- :response
|
207
|
+
- :user
|
208
|
+
|
209
|
+
:user_wish_list:
|
210
|
+
:endpoint: "user/wishlist/:username:"
|
211
|
+
:results_path:
|
212
|
+
- :response
|
213
|
+
- :beers
|
214
|
+
- :items
|
215
|
+
|
216
|
+
:venue_feed:
|
217
|
+
:endpoint: "venue/checkins/:venue_id:"
|
218
|
+
:required_args:
|
219
|
+
- :venue_id
|
220
|
+
:results_path:
|
221
|
+
- :response
|
222
|
+
- :checkins
|
223
|
+
- :items
|
224
|
+
|
225
|
+
:venue_info:
|
226
|
+
:endpoint: "venue/info/:venue_id:"
|
227
|
+
:required_args:
|
228
|
+
- :venue_id
|
229
|
+
:results_path:
|
230
|
+
- :response
|
231
|
+
- :venue
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'drink-socially/http_service'
|
2
|
+
require 'drink-socially/version'
|
3
|
+
require 'drink-socially/extensions/hash'
|
4
|
+
|
5
|
+
module NRB
|
6
|
+
module Untappd
|
7
|
+
|
8
|
+
autoload :API, 'drink-socially/api'
|
9
|
+
autoload :Config, 'drink-socially/config'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
attr_accessor :http_service
|
14
|
+
|
15
|
+
def config_file_path(key)
|
16
|
+
return key if File.absolute_path(key) == key
|
17
|
+
File.expand_path( File.join( config_dir, key ) )
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def load_config(args)
|
22
|
+
reader = args.delete(:config_reader) || Config
|
23
|
+
!! args[:filekey] && args[:filename] = config_file_path(args.delete(:filekey))
|
24
|
+
reader.new(args)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def make_request(args)
|
29
|
+
http_service.make_request args
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def config_dir
|
35
|
+
File.expand_path( File.join( File.dirname(__FILE__), '..', 'config' ) )
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
self.http_service = HTTPService
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module NRB
|
2
|
+
module Untappd
|
3
|
+
class API
|
4
|
+
|
5
|
+
API_VERSION = :v4 # Use NRB::Untappd::API.api_version instead
|
6
|
+
SERVER = 'api.untappd.com' # Use NRB::Untappd::API.server instead
|
7
|
+
|
8
|
+
autoload :Credential, 'drink-socially/api/credential'
|
9
|
+
autoload :Pagination, 'drink-socially/api/pagination'
|
10
|
+
autoload :RateLimit, 'drink-socially/api/rate_limit'
|
11
|
+
autoload :Object, 'drink-socially/api/object'
|
12
|
+
autoload :URLTokenizer, 'drink-socially/api/url_tokenizer'
|
13
|
+
|
14
|
+
attr_reader :credential, :endpoints, :rate_limit
|
15
|
+
|
16
|
+
def self.api_version; API_VERSION; end
|
17
|
+
def self.default_rate_limit_class; RateLimit; end
|
18
|
+
def self.default_response_class; Object; end
|
19
|
+
def self.requestor; NRB::Untappd; end
|
20
|
+
def self.server; SERVER; end
|
21
|
+
|
22
|
+
|
23
|
+
# http://untappd.com/api/docs/v4#checkin
|
24
|
+
# Required args: bid
|
25
|
+
def add_checkin(args)
|
26
|
+
validate_api_args args, :bid
|
27
|
+
t = Time.now
|
28
|
+
args[:endpoint] = 'checkin/add'
|
29
|
+
args[:gmt_offset] ||= t.gmt_offset / 3600
|
30
|
+
args[:timezone] ||= t.zone
|
31
|
+
args[:verb] = :post
|
32
|
+
api_call args
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def api_call(args)
|
37
|
+
endpoint = args.delete(:endpoint)
|
38
|
+
config = get_config endpoint
|
39
|
+
return unless config
|
40
|
+
|
41
|
+
validate_api_args args, *config[:required_args]
|
42
|
+
|
43
|
+
args.merge!(config)
|
44
|
+
|
45
|
+
args[:response_class] ||= self.class.default_response_class
|
46
|
+
|
47
|
+
tokenizer = URLTokenizer.new map: args, string: args.delete(:endpoint)
|
48
|
+
args[:url] = find_path_at tokenizer.tr
|
49
|
+
|
50
|
+
response = self.class.requestor.make_request(args)
|
51
|
+
@rate_limit = self.class.default_rate_limit_class.new(response.headers)
|
52
|
+
response
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def initialize(args={})
|
57
|
+
@api_version = args[:api_version] || self.class.api_version
|
58
|
+
@credential = args[:credential] || Credential.new(args.dup)
|
59
|
+
@server = args[:server] || self.class.server
|
60
|
+
define_endpoints_from(args)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def api_call_lambda(args)
|
66
|
+
lambda { |opts={}| api_call opts.merge({endpoint: args[:endpoint]}) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def credential_string_for_url
|
70
|
+
@credential.is_user? ? "?access_token=#{@credential.access_token}" : ""
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def define_endpoint_aliases(args)
|
75
|
+
return unless args[:orig]
|
76
|
+
args[:aliases].each do |name|
|
77
|
+
define_singleton_method name, api_call_lambda(endpoint: name)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def define_endpoints_from(args)
|
83
|
+
@endpoints = args[:endpoints] || NRB::Untappd.load_config(filekey: (args[:config_file] || 'endpoints.yml'))
|
84
|
+
@endpoints.each do |endpoint,endpoint_config|
|
85
|
+
define_singleton_method endpoint, api_call_lambda(endpoint: endpoint)
|
86
|
+
endpoint_config[:method_aliases] && define_endpoint_aliases(orig: endpoint, aliases: endpoint_config[:method_aliases])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def endpoint_base
|
92
|
+
"http://#{@server}/#{@api_version}/"
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def extract_info_from(response, *keys)
|
97
|
+
return unless response.success?
|
98
|
+
keys.inject(response.body) { |hash, key| hash[key] }
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def find_path_at(endpoint)
|
103
|
+
endpoint_base + endpoint.to_s + credential_string_for_url
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def get_config(endpoint)
|
108
|
+
config = @endpoints[endpoint]
|
109
|
+
return unless config
|
110
|
+
config[:verb] ||= :get
|
111
|
+
config
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def validate_api_args(args, *required_args)
|
116
|
+
raise ArgumentError.new("Please supply a hash") unless args.is_a?(Hash)
|
117
|
+
required_args.each do |arg|
|
118
|
+
raise ArgumentError.new("Missing required #{arg} parameter") unless !! args[arg]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|