gowalla 0.1.4 → 0.2.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.
@@ -1,5 +1,7 @@
1
1
  require 'hashie'
2
- require 'httparty'
2
+ require 'faraday'
3
+ require 'multi_json'
4
+ require 'oauth2'
3
5
 
4
6
  directory = File.expand_path(File.dirname(__FILE__))
5
7
 
@@ -7,6 +9,8 @@ Hash.send :include, Hashie::HashExtensions
7
9
 
8
10
  module Gowalla
9
11
 
12
+ VERSION = "0.2.0".freeze
13
+
10
14
  # config/initializers/gowalla.rb (for instance)
11
15
  #
12
16
  # Gowalla.configure do |config|
@@ -27,6 +31,7 @@ module Gowalla
27
31
  attr_accessor :api_key
28
32
  attr_accessor :username
29
33
  attr_accessor :password
34
+ attr_accessor :api_secret
30
35
  end
31
36
 
32
37
  end
@@ -1,134 +1,181 @@
1
+ require 'forwardable'
2
+
1
3
  module Gowalla
2
-
3
4
  class Client
4
- include HTTParty
5
- format :json
6
- base_uri "http://api.gowalla.com"
7
- headers({'Accept' => 'application/json', "User-Agent" => 'Ruby gem'})
5
+ extend Forwardable
6
+
7
+ attr_reader :username, :api_key, :api_secret
8
8
 
9
- attr_reader :username
9
+ def_delegators :oauth_client, :web_server, :authorize_url, :access_token_url
10
10
 
11
11
  def initialize(options={})
12
- api_key = options[:api_key] || Gowalla.api_key
12
+ @api_key = options[:api_key] || Gowalla.api_key
13
+ @api_secret = options[:api_secret] || Gowalla.api_secret
13
14
  @username = options[:username] || Gowalla.username
15
+ @access_token = options[:access_token]
14
16
  password = options[:password] || Gowalla.password
15
- self.class.basic_auth(@username, password) unless @username.nil?
16
- self.class.headers({'X-Gowalla-API-Key' => api_key }) unless api_key.nil?
17
- end
18
-
19
- def user(user_id=self.username)
20
- mashup(self.class.get("/users/#{user_id}"))
21
- end
22
-
23
- def events(user_id=self.username)
24
- mashup(self.class.get("/users/#{user_id}/events")).activity
25
- end
26
-
27
- def friends_events
28
- mashup(self.class.get("/visits/recent")).activity
29
- end
30
-
31
- def friend_requests(user_id=self.username)
32
- mashup(self.class.get("/users/#{user_id}/friend_requests")).friends_needing_approval
33
- end
34
-
35
- def friends(user_id=self.username)
36
- mashup(self.class.get("/users/#{user_id}/friends")).friends
37
- end
38
-
39
- def items(user_id=self.username)
40
- mashup(self.class.get("/users/#{user_id}/items")).items
41
- end
42
-
43
- def missing_items(user_id=self.username)
44
- mashup(self.class.get("/users/#{user_id}/items/missing")).items
45
- end
46
-
47
- def vaulted_items(user_id=self.username)
48
- mashup(self.class.get("/users/#{user_id}/items/vault")).items
49
- end
50
-
17
+ connection.basic_auth(@username, password) unless @api_secret
18
+ end
19
+
20
+ # Retrieve information about a specific user
21
+ #
22
+ # @param [String] user_id (authenticated basic auth user) User ID (screen name)
23
+ # @return [Hashie::Mash] User info
24
+ def user(user_id=nil)
25
+ user_id ||= username
26
+ handle_response(connection.get("/users/#{user_id}"))
27
+ end
28
+
29
+ # Retrieve information about a specific item
30
+ #
31
+ # @param [Integer] id Item ID
32
+ # @return [Hashie::Mash] item info
51
33
  def item(id)
52
- mashup(self.class.get("/items/#{id}"))
53
- end
54
-
55
- def pins(user_id=self.username)
56
- mashup(self.class.get("/users/#{user_id}/pins"))
57
- end
58
-
34
+ handle_response(connection.get("/items/#{id}"))
35
+ end
36
+
37
+ # Retrieve a list of the stamps the user has collected
38
+ #
39
+ # @param [String] user_id (authenticated basic auth user) User ID (screen name)
40
+ # @param [Integer] limit (20) limit per page
41
+ # @return [Hashie::Mash] stamps info
59
42
  def stamps(user_id=self.username, limit=20)
60
- mashup(self.class.get("/users/#{user_id}/stamps", :query => {:limit => limit})).stamps
43
+ response = connection.get do |req|
44
+ req.url "/users/#{user_id}/stamps", :limit => limit
45
+ end
46
+ handle_response(response).stamps
61
47
  end
62
-
48
+
49
+ # Retrieve a list of spots the user has visited most often
50
+ #
51
+ # @param [String] user_id (authenticated basic auth user) User ID (screen name)
52
+ # @return [Hashie::Mash] item info
63
53
  def top_spots(user_id=self.username)
64
- mashup(self.class.get("/users/#{user_id}/top_spots")).top_spots
54
+ handle_response(connection.get("/users/#{user_id}/top_spots")).top_spots
65
55
  end
66
-
67
- def visited_spots(user_id=self.username)
68
- mashup(self.class.get("/users/#{user_id}/visited_spots"))
69
- end
70
-
56
+
57
+ # Retrieve information about a specific trip
58
+ #
59
+ # @param [Integer] trip_id Trip ID
60
+ # @return [Hashie::Mash] trip info
71
61
  def trip(trip_id)
72
- mashup(self.class.get("/trips/#{trip_id}"))
62
+ handle_response(connection.get("/trips/#{trip_id}"))
73
63
  end
74
64
 
65
+ # Retrieve information about a specific spot
66
+ #
67
+ # @param [Integer] spot_id Spot ID
68
+ # @return [Hashie::Mash] Spot info
75
69
  def spot(spot_id)
76
- mashup(self.class.get("/spots/#{spot_id}"))
70
+ handle_response(connection.get("/spots/#{spot_id}"))
77
71
  end
78
72
 
73
+ # Retrieve a list of check-ins at a particular spot. Shows only the activity that is visible to a given user.
74
+ #
75
+ # @param [Integer] spot_id Spot ID
76
+ # @return [Hashie::Mash] Spot info
79
77
  def spot_events(spot_id)
80
- mashup(self.class.get("/spots/#{spot_id}/events")).activity
78
+ handle_response(connection.get("/spots/#{spot_id}/events")).activity
81
79
  end
82
80
 
81
+ # Retrieve a list of items available at a particular spot
82
+ #
83
+ # @param [Integer] spot_id Spot ID
84
+ # @return [Hashie::Mash] Spot info
83
85
  def spot_items(spot_id)
84
- mashup(self.class.get("/spots/#{spot_id}/items")).items
86
+ handle_response(connection.get("/spots/#{spot_id}/items")).items
85
87
  end
86
88
 
89
+ # Retrieve a list of spots within a specified distance of a location
90
+ #
91
+ # @option options [Float] :latitude Latitude of search location
92
+ # @option options [Float] :longitude Longitude of search location
93
+ # @option options [Integer] :radius Search radius (in meters)
94
+ # @return [Hashie::Mash] spots info
87
95
  def list_spots(options={})
88
96
  query = format_geo_options(options)
89
- mashup(self.class.get("/spots", :query => query)).spots
90
- end
91
-
92
- def featured_spots(options={})
93
- list_spots(options.merge(:featured => 1))
94
- end
95
-
96
- def bookmarked_spots(options={})
97
- list_spots(options.merge(:bookmarked => 1))
97
+ response = connection.get do |req|
98
+ req.url "/spots", query
99
+ end
100
+ handle_response(response).spots
98
101
  end
99
102
 
103
+ # List of trips
104
+ #
105
+ # @return [<Hashie::Mash>] trip info
100
106
  def trips(options={})
101
107
  if user_id = options.delete(:user_id)
102
108
  options[:user_url] = "/users/#{user_id}"
103
109
  end
104
110
  query = format_geo_options(options)
105
- mashup(self.class.get("/trips", :query => query)).trips
106
- end
107
-
108
- def featured_trips(options={})
109
- trips(options.merge(:context => 'featured'))
110
- end
111
-
112
- def friends_trips(options={})
113
- trips(options.merge(:context => 'friends'))
111
+ response = connection.get do |req|
112
+ req.url "/trips", query
113
+ end
114
+ handle_response(response).trips
114
115
  end
115
-
116
+
117
+ # Lists all spot categories
118
+ #
119
+ # @return [<Hashie::Mash>] category info
116
120
  def categories
117
- mashup(self.class.get("/categories")).spot_categories
121
+ handle_response(connection.get("/categories")).spot_categories
118
122
  end
119
123
 
124
+ # Retrieve information about a specific category
125
+ #
126
+ # @param [Integer] id Category ID
127
+ # @return [Hashie::Mash] category info
120
128
  def category(id)
121
- mashup(self.class.get("/categories/#{id}"))
129
+ handle_response(connection.get("/categories/#{id}"))
122
130
  end
123
131
 
124
- def checkin(spot_id, options = {})
125
- query = format_geo_options(options)
132
+ # Check for missing access token
133
+ #
134
+ # @return [Boolean] whether or not to redirect to get an access token
135
+ def needs_access?
136
+ @api_secret and @access_token.to_s == ''
137
+ end
138
+
139
+ # Raw HTTP connection, either Faraday::Connection or OAuth2::AccessToken
140
+ #
141
+ # @return [OAuth2::Client]
142
+ def connection
126
143
 
127
- mashup(self.class.post("/checkins", :body => options, :query => { :spot_id => spot_id }))
144
+ if api_secret
145
+ @connection ||= OAuth2::AccessToken.new(oauth_client, @access_token)
146
+ else
147
+ headers = default_headers
148
+ headers['X-Gowalla-API-Key'] = api_key if api_key
149
+ @connection ||= Faraday::Connection.new \
150
+ :url => "http://api.gowalla.com",
151
+ :headers => headers
152
+ end
128
153
  end
129
154
 
155
+ # Provides raw access to the OAuth2 Client
156
+ #
157
+ # @return [OAuth2::Client]
158
+ def oauth_client
159
+ if @oauth_client
160
+ @oauth_client
161
+ else
162
+ conn ||= Faraday::Connection.new \
163
+ :url => "https://api.gowalla.com",
164
+ :headers => default_headers
165
+
166
+ oauth= OAuth2::Client.new(api_key, api_secret, oauth_options = {
167
+ :site => 'https://api.gowalla.com',
168
+ :authorize_url => 'https://gowalla.com/api/oauth/new',
169
+ :access_token_url => 'https://gowalla.com/api/oauth/token'
170
+ })
171
+ oauth.connection = conn
172
+ oauth
173
+ end
174
+ end
175
+
130
176
  private
131
177
 
178
+ # @private
132
179
  def format_geo_options(options={})
133
180
  options[:lat] = "+#{options[:lat]}" if options[:lat].to_i > 0
134
181
  options[:lng] = "+#{options[:lng]}" if options[:lng].to_i > 0
@@ -137,21 +184,33 @@ module Gowalla
137
184
  end
138
185
  options
139
186
  end
140
-
141
- def mashup(response)
142
- case response.code
187
+
188
+ # @private
189
+ def default_headers
190
+ headers = {
191
+ :accept => 'application/json',
192
+ :user_agent => 'Ruby gem'
193
+ }
194
+ end
195
+
196
+ # @private
197
+ def handle_response(response)
198
+ case response.status
143
199
  when 200
144
- if response.is_a?(Hash)
145
- Hashie::Mash.new(response)
200
+ body = response.respond_to?(:body) ? response.body : response
201
+ data = MultiJson.decode(body)
202
+ if data.is_a?(Hash)
203
+ Hashie::Mash.new(data)
146
204
  else
147
- if response.first.is_a?(Hash)
148
- response.map{|item| Hashie::Mash.new(item)}
205
+ if data.first.is_a?(Hash)
206
+ data.map{|item| Hashie::Mash.new(item)}
149
207
  else
150
- response
208
+ data
151
209
  end
152
210
  end
153
211
  end
154
212
  end
213
+
155
214
 
156
215
  end
157
216
 
@@ -0,0 +1,168 @@
1
+ require 'helper'
2
+
3
+ class GowallaTest < Test::Unit::TestCase
4
+
5
+ context "When using the Gowalla API" do
6
+ setup do
7
+ @client = Gowalla::Client.new(:username => 'pengwynn', :password => '0U812', :api_key => 'gowallawallabingbang')
8
+ end
9
+
10
+ context "and working with Spots" do
11
+ should "Retrieve a list of spots within a specified distance of a location" do
12
+ stub_get("http://pengwynn:0U812@api.gowalla.com/spots?lat=%2B33.237593417&lng=-96.960559033&radius=50", "spots.json")
13
+ spots = @client.list_spots(:lat => 33.237593417, :lng => -96.960559033, :radius => 50)
14
+ spots.first.name.should == 'Gnomb Bar'
15
+ spots.first.radius_meters.should == 50
16
+ end
17
+
18
+ should "Retrieve a list of spots within a specified bounds" do
19
+ stub_get("http://pengwynn:0U812@api.gowalla.com/spots?sw=%2839.25565142103586%2C%20-8.717308044433594%29&nw=%2839.31411296530539%2C%20-8.490715026855469%29", "spots.json")
20
+ spots = @client.list_spots(:sw => "(39.25565142103586, -8.717308044433594)", :nw => "(39.31411296530539, -8.490715026855469)")
21
+ spots.first.name.should == 'Gnomb Bar'
22
+ end
23
+
24
+ should "Retrieve information about a specific spot" do
25
+ stub_get('http://pengwynn:0U812@api.gowalla.com/spots/18568', 'spot.json')
26
+ spot = @client.spot(18568)
27
+ spot.name.should == "Wahoo's"
28
+ spot.twitter_username.should == 'Wahoos512'
29
+ spot.spot_categories.first.name.should == 'Mexican'
30
+ end
31
+
32
+ should "retrieve a list of check-ins at a particular spot. Shows only the activity that is visible to a given user" do
33
+ stub_get('http://pengwynn:0U812@api.gowalla.com/spots/452593/events', 'events.json')
34
+ events = @client.spot_events(452593)
35
+ events.first[:type].should == 'checkin'
36
+ events.first.user.last_name.should == 'Mack'
37
+ end
38
+
39
+ should "retrieve a list of items available at a particular spot" do
40
+ stub_get('http://pengwynn:0U812@api.gowalla.com/spots/18568/items', 'items.json')
41
+ items = @client.spot_items(18568)
42
+ items.first.issue_number.should == 27868
43
+ items.first.name.should == 'Bowl of Noodles'
44
+ end
45
+
46
+ should "lists all spot categories" do
47
+ stub_get("http://pengwynn:0U812@api.gowalla.com/categories", "categories.json")
48
+ categories = @client.categories
49
+ categories.size.should == 9
50
+ categories.first.name.should == 'Architecture & Buildings'
51
+ categories.first.description.should == 'Bridge, Corporate, Home, Church, etc.'
52
+ categories.first.spot_categories.size.should == 15
53
+ categories.first.spot_categories.first.name.should == 'Bridge'
54
+ end
55
+
56
+ should "retrieve information about a specific category" do
57
+ stub_get("http://pengwynn:0U812@api.gowalla.com/categories/1", "category.json")
58
+ category = @client.category(1)
59
+ category.name.should == 'Coffee Shop'
60
+ end
61
+ end
62
+
63
+ context "and working with Users" do
64
+
65
+ should "retrieve information about a specific user" do
66
+ stub_get('http://pengwynn:0U812@api.gowalla.com/users/sco', 'user.json')
67
+ user = @client.user('sco')
68
+ user.bio.should == "CTO & co-founder of Gowalla. Ruby/Cocoa/JavaScript developer. Game designer. Author. Indoorsman."
69
+ user.stamps_count.should == 506
70
+ end
71
+
72
+ should "retrieve a list of the stamps the user has collected" do
73
+ stub_get('http://pengwynn:0U812@api.gowalla.com/users/1707/stamps?limit=20', 'stamps.json')
74
+ stamps = @client.stamps(1707)
75
+ stamps.size.should == 20
76
+ stamps.first.spot.name.should == "Muck-N-Dave's Texas BBQ"
77
+ stamps.first.spot.address.locality.should == 'Austin'
78
+ end
79
+
80
+ should "retrieve a list of spots the user has visited most often" do
81
+ stub_get('http://pengwynn:0U812@api.gowalla.com/users/1707/top_spots', 'top_spots.json')
82
+ top_spots = @client.top_spots(1707)
83
+ top_spots.size.should == 10
84
+ top_spots.first.name.should == 'Juan Pelota Cafe'
85
+ top_spots.first.user_checkins_count.should == 30
86
+ end
87
+
88
+ end
89
+
90
+ context "and working with Items" do
91
+ should "retrieve information about a specific item" do
92
+ stub_get('http://pengwynn:0U812@api.gowalla.com/items/607583', 'item.json')
93
+ item = @client.item(607583)
94
+ item.issue_number.should == 13998
95
+ item.name.should == 'Sweets'
96
+ item.determiner.should == 'some'
97
+ end
98
+ end
99
+
100
+ context "and working with Trips" do
101
+ should "retrieve a list of trips" do
102
+ stub_get('http://pengwynn:0U812@api.gowalla.com/trips', 'trips.json')
103
+ trips = @client.trips
104
+ trips.first.name.should == 'London Pub Crawl'
105
+ trips.first.spots.first.url.should == '/spots/164009'
106
+ end
107
+
108
+ should "retrieve information about a specific trip" do
109
+ stub_get('http://pengwynn:0U812@api.gowalla.com/trips/1', 'trip.json')
110
+ trip = @client.trip(1)
111
+ trip.creator.last_name.should == 'Gowalla'
112
+ trip.map_bounds.east.should == -63.457031
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ context "when using basic auth" do
119
+ should "configure api_key, username, and password for easy access" do
120
+
121
+ Gowalla.configure do |config|
122
+ config.api_key = 'api_key'
123
+ config.api_secret = nil
124
+ config.username = 'username'
125
+ config.password = 'password'
126
+ end
127
+
128
+ @client = Gowalla::Client.new
129
+
130
+ stub_get('http://username:password@api.gowalla.com/trips', 'trips.json')
131
+ trips = @client.trips
132
+
133
+ @client.username.should == 'username'
134
+ end
135
+ end
136
+
137
+ context "when using OAuth2" do
138
+
139
+ setup do
140
+ Gowalla.configure do |config|
141
+ config.api_key = 'api_key'
142
+ config.api_secret = 'api_secret'
143
+ end
144
+
145
+ @client = Gowalla::Client.new
146
+ end
147
+
148
+ should "confiure api_key, api_secret" do
149
+ @client.api_secret.should == 'api_secret'
150
+ @client.oauth_client.id.should == 'api_key'
151
+ end
152
+
153
+ should "create an OAuth2 client" do
154
+ @client.oauth_client.class.to_s.should == "OAuth2::Client"
155
+ end
156
+
157
+ should "create an OAuth2 connection" do
158
+ @client.connection.class.to_s.should == "OAuth2::AccessToken"
159
+ end
160
+
161
+ should "indicate if it needs an access_token" do
162
+ @client.needs_access?.should == true
163
+ end
164
+
165
+ end
166
+
167
+
168
+ end