instagram 0.11.0 → 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.
@@ -1,6 +1,23 @@
1
1
  module Instagram
2
2
  class Client
3
+ # Defines methods related to embedding
3
4
  module Embedding
5
+ # Returns information about the media associated with the given short link
6
+ #
7
+ # @overload oembed(url=nil, options={})
8
+ # @param url [String] An instagram short link
9
+ # @param options [Hash] A customizable set of options
10
+ # @option options [Integer] :maxheight Maximum height of returned media
11
+ # @option options [Integer] :maxwidth Maximum width of returned media
12
+ # @option options [Integer] :callback A JSON callback to be invoked
13
+ # @return [Hashie::Mash] Information about the media associated with given short link
14
+ # @example Return information about the media associated with http://instagr.am/p/BUG/
15
+ # Instagram.oembed(http://instagr.am/p/BUG/)
16
+ #
17
+ # @see http://instagram.com/developer/embedding/#oembed
18
+ # @format :json
19
+ # @authenticated false
20
+ # @rate_limited true
4
21
  def oembed(*args)
5
22
  url = args.first
6
23
  return nil unless url
@@ -14,7 +14,7 @@ module Instagram
14
14
  #
15
15
  # If getting this data of a protected user, you must be authenticated (and be allowed to see that user).
16
16
  # @rate_limited true
17
- # @see TODO:docs url
17
+ # @see http://instagram.com/developer/endpoints/likes/#get_media_likes
18
18
  def media_likes(id, *args)
19
19
  response = get("media/#{id}/likes")
20
20
  response
@@ -32,7 +32,7 @@ module Instagram
32
32
  #
33
33
  # If getting this data of a protected user, you must be authenticated (and be allowed to see that user).
34
34
  # @rate_limited true
35
- # @see TODO:docs url
35
+ # @see http://instagram.com/developer/endpoints/likes/#post_likes
36
36
  def like_media(id, options={})
37
37
  response = post("media/#{id}/likes", options)
38
38
  response
@@ -48,7 +48,7 @@ module Instagram
48
48
  # @format :json
49
49
  # @authenticated true
50
50
  # @rate_limited true
51
- # @see TODO:docs url
51
+ # @see http://instagram.com/developer/endpoints/likes/#delete_likes
52
52
  def unlike_media(id, options={})
53
53
  response = delete("media/#{id}/likes", options)
54
54
  response
@@ -12,7 +12,7 @@ module Instagram
12
12
  # @format :json
13
13
  # @authenticated false
14
14
  # @rate_limited true
15
- # @see TODO:docs url
15
+ # @see http://instagram.com/developer/endpoints/locations/#get_locations
16
16
  def location(id, *args)
17
17
  response = get("locations/#{id}")
18
18
  response
@@ -28,7 +28,7 @@ module Instagram
28
28
  # @return [Hashie::Mash]
29
29
  # @example Return a list of the most recent media items taken at the Instagram office
30
30
  # Instagram.location_recent_media(514276)
31
- # @see TODO:docs url
31
+ # @see http://instagram.com/developer/endpoints/locations/#get_locations_media_recent
32
32
  # @format :json
33
33
  # @authenticated false
34
34
  # @rate_limited true
@@ -50,7 +50,7 @@ module Instagram
50
50
  # Instagram.location_search("3fd66200f964a520c5f11ee3") (Schiller's Liquor Bar, 131 Rivington St., NY, NY 10002)
51
51
  # @example 2: Return locations around 37.7808851, -122.3948632 (164 S Park, SF, CA USA)
52
52
  # Instagram.location_search("37.7808851", "-122.3948632")
53
- # @see TODO:doc url
53
+ # @see http://instagram.com/developer/endpoints/locations/#get_locations_search
54
54
  # @format :json
55
55
  # @authenticated false
56
56
  # @rate_limited true
@@ -63,6 +63,9 @@ module Instagram
63
63
  when 2
64
64
  lat, lng = args
65
65
  response = get('locations/search', options.merge(:lat => lat, :lng => lng))
66
+ when 3
67
+ lat, lng, distance = args
68
+ response = get('locations/search', options.merge(:lat => lat, :lng => lng, :distance => distance))
66
69
  end
67
70
  response
68
71
  end
@@ -14,7 +14,7 @@ module Instagram
14
14
  #
15
15
  # If getting this data of a protected user, you must authenticate (and be allowed to see that user).
16
16
  # @rate_limited true
17
- # @see TODO:docs url
17
+ # @see http://instagram.com/developer/endpoints/media/#get_media
18
18
  def media_item(*args)
19
19
  id = args.first || 'self'
20
20
  response = get("media/#{id}")
@@ -28,7 +28,7 @@ module Instagram
28
28
  # @return [Hashie::Mash]
29
29
  # @example Returns a list of the overall most popular media
30
30
  # Instagram.media_popular
31
- # @see TODO:docs url
31
+ # @see http://instagram.com/developer/endpoints/media/#get_media_popular
32
32
  # @format :json
33
33
  # @authenticated false unless requesting it from a protected user
34
34
  #
@@ -50,7 +50,7 @@ module Instagram
50
50
  # @return [Hashie::Mash] A list of matching media
51
51
  # @example Return media around 37.7808851, -122.3948632 (164 S Park, SF, CA USA)
52
52
  # Instagram.media_search("37.7808851", "-122.3948632")
53
- # @see TODO:doc url
53
+ # @see http://instagram.com/developer/endpoints/media/#get_media_search
54
54
  # @format :json
55
55
  # @authenticated false
56
56
  # @rate_limited true
@@ -41,7 +41,7 @@ module Instagram
41
41
  # @option options [String, Integer] :object_id When specifying a location or tag use the location's ID or tag name respectively
42
42
  # @option options [String, Float] :lat The center latitude of an area, used when subscribing to a geography object
43
43
  # @option options [String, Float] :lng The center longitude of an area, used when subscribing to a geography object
44
- # @option options [String, Integer] :radius The distance in meters you'd like to capture around a given point
44
+ # @option options [String, Integer] :radius The distance in meters you'd like to capture around a given point
45
45
  #
46
46
  # Note that we only support "media" at this time, but we might support other types of subscriptions in the future.
47
47
  # @return [Hashie::Mash] The subscription created.
@@ -96,6 +96,61 @@ module Instagram
96
96
  response
97
97
  end
98
98
 
99
+ # As a security measure (to prevent DDoS attacks), Instagram sends a verification request to your server
100
+ # after you request a subscription.
101
+ # This method parses the challenge params and makes sure the call is legitimate.
102
+ #
103
+ # @param params the request parameters sent by Instagram. (You can pass in a Rails params hash.)
104
+ # @param verify_token the verify token sent in the {#subscribe subscription request}, if you provided one
105
+ #
106
+ # @yield verify_token if you need to compute the verification token
107
+ # (for instance, if your callback URL includes a record ID, which you look up
108
+ # and use to calculate a hash), you can pass meet_challenge a block, which
109
+ # will receive the verify_token received back from Instagram.
110
+ #
111
+ # @return the challenge string to be sent back to Instagram, or false if the request is invalid.
112
+ def meet_challenge(params, verify_token = nil, &verification_block)
113
+ if params["hub.mode"] == "subscribe" &&
114
+ # you can make sure this is legitimate through two ways
115
+ # if your store the token across the calls, you can pass in the token value
116
+ # and we'll make sure it matches
117
+ ((verify_token && params["hub.verify_token"] == verify_token) ||
118
+ # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
119
+ # you can pass in a block, which we'll call with the verify_token sent by Instagram
120
+ # if it's legit, return anything that evaluates to true; otherwise, return nil or false
121
+ (verification_block && yield(params["hub.verify_token"])))
122
+ params["hub.challenge"]
123
+ else
124
+ false
125
+ end
126
+ end
127
+
128
+ # Public: As a security measure, all updates from Instagram are signed using
129
+ # X-Hub-Signature: sha1=XXXX where XXX is the sha1 of the json payload
130
+ # using your application secret as the key.
131
+ #
132
+ # Example:
133
+ # # in Rails controller
134
+ # def receive_update
135
+ # if Instagram.validate_update(request.body, headers)
136
+ # ...
137
+ # else
138
+ # render text: "not authorized", status: 401
139
+ # end
140
+ # end
141
+ def validate_update(body, headers)
142
+ unless client_secret
143
+ raise ArgumentError, "client_secret must be set during configure"
144
+ end
145
+
146
+ if request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE'] and
147
+ signature_parts = request_signature.split('sha1=')
148
+ request_signature = signature_parts[1]
149
+ calculated_signature = OpenSSL::HMAC.hexdigest('sha1', client_secret, body)
150
+ calculated_signature == request_signature
151
+ end
152
+ end
153
+
99
154
  # Process a subscription notification JSON payload
100
155
  #
101
156
  # @overload process_subscription(json, &block)
@@ -124,7 +179,7 @@ module Instagram
124
179
  def process_subscription(json, options={}, &block)
125
180
  raise ArgumentError, "callbacks block expected" unless block_given?
126
181
 
127
- if options[:signature]
182
+ if options.has_key?(:signature)
128
183
  if !client_secret
129
184
  raise ArgumentError, "client_secret must be set during configure"
130
185
  end
@@ -12,7 +12,7 @@ module Instagram
12
12
  # @format :json
13
13
  # @authenticated false
14
14
  # @rate_limited true
15
- # @see TODO:docs url
15
+ # @see http://instagram.com/developer/endpoints/tags/#get_tags
16
16
  def tag(tag, *args)
17
17
  response = get("tags/#{tag}")
18
18
  response
@@ -21,20 +21,20 @@ module Instagram
21
21
  # Returns a list of recent media items for a given Instagram tag
22
22
  #
23
23
  # @overload tag_recent_media(tag, options={})
24
- # @param id [String] An Instagram tag name.
24
+ # @param tag-name [String] An Instagram tag name.
25
25
  # @param options [Hash] A customizable set of options.
26
26
  # @option options [Integer] :max_id (nil) Returns results with an ID less than (that is, older than) or equal to the specified ID.
27
- # @option options [Integer] :count (nil) Limits the number of results returned per page.
27
+ # @option options [Integer] :min_id (nil) Returns results with an ID greater than (that is, newer than) or equal to the specified ID.
28
28
  # @return [Hashie::Mash]
29
29
  # @example Return a list of the most recent media items tagged "cat"
30
30
  # Instagram.tag_recent_media('cat')
31
- # @see TODO:docs url
31
+ # @see http://instagram.com/developer/endpoints/tags/#get_tags_media_recent
32
32
  # @format :json
33
33
  # @authenticated false
34
34
  # @rate_limited true
35
35
  def tag_recent_media(id, *args)
36
36
  options = args.last.is_a?(Hash) ? args.pop : {}
37
- response = get("tags/#{id}/media/recent", options)
37
+ response = get("tags/#{id}/media/recent", options, false, false)
38
38
  response
39
39
  end
40
40
 
@@ -47,7 +47,7 @@ module Instagram
47
47
  # @param options [Hash] A customizable set of options.
48
48
  # @option options [Integer] :count The number of media items to retrieve.
49
49
  # @return [Hashie::Mash]
50
- # @see TODO:doc url
50
+ # @see http://instagram.com/developer/endpoints/tags/#get_tags_search
51
51
  # @example Return tags that start with "cat"
52
52
  # Instagram.tag_search("cat")
53
53
  def tag_search(query, options={})
@@ -14,7 +14,7 @@ module Instagram
14
14
  #
15
15
  # If getting this data of a protected user, you must authenticate (and be allowed to see that user).
16
16
  # @rate_limited true
17
- # @see TODO:docs url
17
+ # @see http://instagram.com/developer/endpoints/users/#get_users
18
18
  def user(*args)
19
19
  options = args.last.is_a?(Hash) ? args.pop : {}
20
20
  id = args.first || 'self'
@@ -31,7 +31,7 @@ module Instagram
31
31
  # @param options [Hash] A customizable set of options.
32
32
  # @option options [Integer] :count The number of users to retrieve.
33
33
  # @return [Hashie::Mash]
34
- # @see TODO:doc url
34
+ # @see http://instagram.com/developer/endpoints/users/#get_users_search
35
35
  # @example Return users that match "Shayne Sweeney"
36
36
  # Instagram.user_search("Shayne Sweeney")
37
37
  def user_search(query, options={})
@@ -54,7 +54,7 @@ module Instagram
54
54
  # @return [Hashie::Mash]
55
55
  # @example Return a list of users @mikeyk follows
56
56
  # Instagram.user_follows(4) # @mikeyk user ID being 4
57
- # @see TODO:docs url
57
+ # @see http://instagram.com/developer/endpoints/relationships/#get_users_follows
58
58
  # @format :json
59
59
  # @authenticated false unless requesting it from a protected user
60
60
  #
@@ -83,7 +83,7 @@ module Instagram
83
83
  # @return [Hashie::Mash]
84
84
  # @example Return a list of users @mikeyk is followed by
85
85
  # Instagram.user_followed_by(4) # @mikeyk user ID being 4
86
- # @see TODO:docs url
86
+ # @see http://instagram.com/developer/endpoints/relationships/#get_users_followed_by
87
87
  # @format :json
88
88
  # @authenticated false unless requesting it from a protected user
89
89
  #
@@ -96,7 +96,7 @@ module Instagram
96
96
  response
97
97
  end
98
98
 
99
- # Returns a list of users whom a given user is followed by
99
+ # Returns a list of users who have requested the currently authorized user's permission to follow
100
100
  #
101
101
  # @overload user_requested_by()
102
102
  # @param options [Hash] A customizable set of options.
@@ -107,16 +107,16 @@ module Instagram
107
107
  # @return [Hashie::Mash]
108
108
  # @example Return a list of users who have requested to follow the authenticated user
109
109
  # Instagram.user_requested_by()
110
- # @see TODO:docs url
110
+ # @see http://instagram.com/developer/endpoints/relationships/#get_incoming_requests
111
111
  # @format :json
112
- # @authenticated truei
112
+ # @authenticated true
113
113
  # @rate_limited true
114
114
  def user_requested_by()
115
115
  response = get("users/self/requested-by")
116
116
  response
117
117
  end
118
118
 
119
- # Returns most recent media items from the currently authorized user's feed.
119
+ # Returns most recent media items from the currently authorized user's feed
120
120
  #
121
121
  # @overload user_media_feed(options={})
122
122
  # @param options [Hash] A customizable set of options.
@@ -190,7 +190,7 @@ module Instagram
190
190
  # @return [Hashie::Mash]
191
191
  # @example Return the relationship status between the currently authenticated user and @mikeyk
192
192
  # Instagram.user_relationship(4) # @mikeyk user ID being 4
193
- # @see http://instagram.com/developer/endpoints/relationships/
193
+ # @see http://instagram.com/developer/endpoints/relationships/#get_relationship
194
194
  # @format :json
195
195
  # @authenticated true
196
196
  # @rate_limited true
@@ -207,7 +207,7 @@ module Instagram
207
207
  # @return [Hashie::Mash]
208
208
  # @example Request the current user to follow the target user
209
209
  # Instagram.follow_user(4)
210
- # @see http://instagram.com/developer/endpoints/relationships/
210
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
211
211
  # @format :json
212
212
  # @authenticated true
213
213
  # @rate_limited true
@@ -225,7 +225,7 @@ module Instagram
225
225
  # @return [Hashie::Mash]
226
226
  # @example Remove a follows relationship between the current user and the target user
227
227
  # Instagram.unfollow_user(4)
228
- # @see http://instagram.com/developer/endpoints/relationships/
228
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
229
229
  # @format :json
230
230
  # @authenticated true
231
231
  # @rate_limited true
@@ -243,7 +243,7 @@ module Instagram
243
243
  # @return [Hashie::Mash]
244
244
  # @example Block a relationship between the current user and the target user
245
245
  # Instagram.block_user(4)
246
- # @see http://instagram.com/developer/endpoints/relationships/
246
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
247
247
  # @format :json
248
248
  # @authenticated true
249
249
  # @rate_limited true
@@ -261,7 +261,7 @@ module Instagram
261
261
  # @return [Hashie::Mash]
262
262
  # @example Remove a relationship block between the current user and the target user
263
263
  # Instagram.unblock_user(4)
264
- # @see http://instagram.com/developer/endpoints/relationships/
264
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
265
265
  # @format :json
266
266
  # @authenticated true
267
267
  # @rate_limited true
@@ -279,7 +279,7 @@ module Instagram
279
279
  # @return [Hashie::Mash]
280
280
  # @example Approve a relationship request between the current user and the target user
281
281
  # Instagram.approve_user(4)
282
- # @see http://instagram.com/developer/endpoints/relationships/
282
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
283
283
  # @format :json
284
284
  # @authenticated true
285
285
  # @rate_limited true
@@ -297,7 +297,7 @@ module Instagram
297
297
  # @return [Hashie::Mash]
298
298
  # @example Deny a relationship request between the current user and the target user
299
299
  # Instagram.deny_user(4)
300
- # @see http://instagram.com/developer/endpoints/relationships/
300
+ # @see http://instagram.com/developer/endpoints/relationships/#post_relationship
301
301
  # @format :json
302
302
  # @authenticated true
303
303
  # @rate_limited true
@@ -2,6 +2,19 @@ module Instagram
2
2
  class Client
3
3
  # @private
4
4
  module Utils
5
+ # Returns the raw full response including all headers. Can be used to access the values for 'X-Ratelimit-Limit' and 'X-Ratelimit-Remaining'
6
+ # ==== Examples
7
+ #
8
+ # client = Instagram.client(:access_token => session[:access_token])
9
+ # response = client.utils_raw_response
10
+ # remaining = response.headers[:x_ratelimit_remaining]
11
+ # limit = response.headers[:x_ratelimit_limit]
12
+ #
13
+ def utils_raw_response
14
+ response = get('users/self/feed',nil,true)
15
+ response
16
+ end
17
+
5
18
  private
6
19
 
7
20
  # Returns the configured user name or the user name of the authenticated user
@@ -6,22 +6,22 @@ module Instagram
6
6
  module Configuration
7
7
  # An array of valid keys in the options hash when configuring a {Instagram::API}
8
8
  VALID_OPTIONS_KEYS = [
9
+ :access_token,
9
10
  :adapter,
10
11
  :client_id,
11
12
  :client_secret,
13
+ :connection_options,
12
14
  :scope,
13
- :access_token,
15
+ :redirect_uri,
14
16
  :endpoint,
15
17
  :format,
18
+ :proxy,
16
19
  :user_agent,
17
- :proxy
20
+ :no_response_wrapper
18
21
  ].freeze
19
22
 
20
- # An array of valid request/response formats
21
- #
22
- # @note Not all methods support the XML format.
23
- VALID_FORMATS = [
24
- :json].freeze
23
+ # By default, don't set a user access token
24
+ DEFAULT_ACCESS_TOKEN = nil
25
25
 
26
26
  # The adapter that will be used to connect if none is set
27
27
  #
@@ -34,14 +34,8 @@ module Instagram
34
34
  # By default, don't set an application secret
35
35
  DEFAULT_CLIENT_SECRET = nil
36
36
 
37
- # By default, don't set an application redirect uri
38
- DEFAULT_REDIRECT_URI = nil
39
-
40
- # By default, don't set a user access token
41
- DEFAULT_ACCESS_TOKEN = nil
42
-
43
- # By default, don't set a user scope
44
- DEFAULT_SCOPE = nil
37
+ # By default, don't set any connection options
38
+ DEFAULT_CONNECTION_OPTIONS = {}
45
39
 
46
40
  # The endpoint that will be used to connect if none is set
47
41
  #
@@ -56,9 +50,24 @@ module Instagram
56
50
  # By default, don't use a proxy server
57
51
  DEFAULT_PROXY = nil
58
52
 
53
+ # By default, don't set an application redirect uri
54
+ DEFAULT_REDIRECT_URI = nil
55
+
56
+ # By default, don't set a user scope
57
+ DEFAULT_SCOPE = nil
58
+
59
+ # By default, don't wrap responses with meta data (i.e. pagination)
60
+ DEFAULT_NO_RESPONSE_WRAPPER = false
61
+
59
62
  # The user agent that will be sent to the API endpoint if none is set
60
63
  DEFAULT_USER_AGENT = "Instagram Ruby Gem #{Instagram::VERSION}".freeze
61
64
 
65
+ # An array of valid request/response formats
66
+ #
67
+ # @note Not all methods support the XML format.
68
+ VALID_FORMATS = [
69
+ :json].freeze
70
+
62
71
  # @private
63
72
  attr_accessor *VALID_OPTIONS_KEYS
64
73
 
@@ -81,15 +90,18 @@ module Instagram
81
90
 
82
91
  # Reset all configuration options to defaults
83
92
  def reset
84
- self.adapter = DEFAULT_ADAPTER
85
- self.client_id = DEFAULT_CLIENT_ID
86
- self.client_secret = DEFAULT_CLIENT_SECRET
87
- self.scope = DEFAULT_SCOPE
88
- self.access_token = DEFAULT_ACCESS_TOKEN
89
- self.endpoint = DEFAULT_ENDPOINT
90
- self.format = DEFAULT_FORMAT
91
- self.user_agent = DEFAULT_USER_AGENT
92
- self.proxy = DEFAULT_PROXY
93
+ self.access_token = DEFAULT_ACCESS_TOKEN
94
+ self.adapter = DEFAULT_ADAPTER
95
+ self.client_id = DEFAULT_CLIENT_ID
96
+ self.client_secret = DEFAULT_CLIENT_SECRET
97
+ self.connection_options = DEFAULT_CONNECTION_OPTIONS
98
+ self.scope = DEFAULT_SCOPE
99
+ self.redirect_uri = DEFAULT_REDIRECT_URI
100
+ self.endpoint = DEFAULT_ENDPOINT
101
+ self.format = DEFAULT_FORMAT
102
+ self.proxy = DEFAULT_PROXY
103
+ self.user_agent = DEFAULT_USER_AGENT
104
+ self.no_response_wrapper= DEFAULT_NO_RESPONSE_WRAPPER
93
105
  end
94
106
  end
95
- end
107
+ end