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.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/LICENSE.md +27 -17
- data/PATENTS.md +23 -0
- data/README.md +129 -46
- data/instagram.gemspec +18 -6
- data/lib/faraday/raise_http_exception.rb +4 -0
- data/lib/instagram/api.rb +8 -0
- data/lib/instagram/client.rb +2 -2
- data/lib/instagram/client/comments.rb +3 -3
- data/lib/instagram/client/embedding.rb +17 -0
- data/lib/instagram/client/likes.rb +3 -3
- data/lib/instagram/client/locations.rb +6 -3
- data/lib/instagram/client/media.rb +3 -3
- data/lib/instagram/client/subscriptions.rb +57 -2
- data/lib/instagram/client/tags.rb +6 -6
- data/lib/instagram/client/users.rb +15 -15
- data/lib/instagram/client/utils.rb +13 -0
- data/lib/instagram/configuration.rb +37 -25
- data/lib/instagram/connection.rb +1 -1
- data/lib/instagram/error.rb +6 -0
- data/lib/instagram/oauth.rb +2 -0
- data/lib/instagram/request.rb +4 -4
- data/lib/instagram/version.rb +1 -1
- data/spec/faraday/response_spec.rb +30 -0
- data/spec/instagram/api_spec.rb +97 -21
- data/spec/instagram/client/locations_spec.rb +24 -0
- data/spec/instagram/client/subscriptions_spec.rb +8 -5
- data/spec/instagram/client/tags_spec.rb +1 -0
- data/spec/instagram/client_spec.rb +1 -1
- metadata +23 -9
data/lib/instagram/connection.rb
CHANGED
@@ -11,7 +11,7 @@ module Instagram
|
|
11
11
|
:headers => {'Accept' => "application/#{format}; charset=utf-8", 'User-Agent' => user_agent},
|
12
12
|
:proxy => proxy,
|
13
13
|
:url => endpoint,
|
14
|
-
}
|
14
|
+
}.merge(connection_options)
|
15
15
|
|
16
16
|
Faraday::Connection.new(options) do |connection|
|
17
17
|
connection.use FaradayMiddleware::InstagramOAuth2, client_id, access_token
|
data/lib/instagram/error.rb
CHANGED
@@ -11,9 +11,15 @@ module Instagram
|
|
11
11
|
# Raised when Instagram returns the HTTP status code 500
|
12
12
|
class InternalServerError < Error; end
|
13
13
|
|
14
|
+
# Raised when Instagram returns the HTTP status code 502
|
15
|
+
class BadGateway < Error; end
|
16
|
+
|
14
17
|
# Raised when Instagram returns the HTTP status code 503
|
15
18
|
class ServiceUnavailable < Error; end
|
16
19
|
|
20
|
+
# Raised when Instagram returns the HTTP status code 504
|
21
|
+
class GatewayTimeout < Error; end
|
22
|
+
|
17
23
|
# Raised when a subscription payload hash is invalid
|
18
24
|
class InvalidSignature < Error; end
|
19
25
|
end
|
data/lib/instagram/oauth.rb
CHANGED
@@ -5,6 +5,7 @@ module Instagram
|
|
5
5
|
def authorize_url(options={})
|
6
6
|
options[:response_type] ||= "code"
|
7
7
|
options[:scope] ||= scope if !scope.nil? && !scope.empty?
|
8
|
+
options[:redirect_uri] ||= self.redirect_uri
|
8
9
|
params = authorization_params.merge(options)
|
9
10
|
connection.build_url("/oauth/authorize/", params).to_s
|
10
11
|
end
|
@@ -12,6 +13,7 @@ module Instagram
|
|
12
13
|
# Return an access token from authorization
|
13
14
|
def get_access_token(code, options={})
|
14
15
|
options[:grant_type] ||= "authorization_code"
|
16
|
+
options[:redirect_uri] ||= self.redirect_uri
|
15
17
|
params = access_token_params.merge(options)
|
16
18
|
post("/oauth/access_token/", params.merge(:code => code), raw=false, unformatted=true, no_response_wrapper=true)
|
17
19
|
end
|
data/lib/instagram/request.rb
CHANGED
@@ -2,22 +2,22 @@ module Instagram
|
|
2
2
|
# Defines HTTP request methods
|
3
3
|
module Request
|
4
4
|
# Perform an HTTP GET request
|
5
|
-
def get(path, options={}, raw=false, unformatted=false, no_response_wrapper=
|
5
|
+
def get(path, options={}, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper)
|
6
6
|
request(:get, path, options, raw, unformatted, no_response_wrapper)
|
7
7
|
end
|
8
8
|
|
9
9
|
# Perform an HTTP POST request
|
10
|
-
def post(path, options={}, raw=false, unformatted=false, no_response_wrapper=
|
10
|
+
def post(path, options={}, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper)
|
11
11
|
request(:post, path, options, raw, unformatted, no_response_wrapper)
|
12
12
|
end
|
13
13
|
|
14
14
|
# Perform an HTTP PUT request
|
15
|
-
def put(path, options={}, raw=false, unformatted=false, no_response_wrapper=
|
15
|
+
def put(path, options={}, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper)
|
16
16
|
request(:put, path, options, raw, unformatted, no_response_wrapper)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Perform an HTTP DELETE request
|
20
|
-
def delete(path, options={}, raw=false, unformatted=false, no_response_wrapper=
|
20
|
+
def delete(path, options={}, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper)
|
21
21
|
request(:delete, path, options, raw, unformatted, no_response_wrapper)
|
22
22
|
end
|
23
23
|
|
data/lib/instagram/version.rb
CHANGED
@@ -39,4 +39,34 @@ describe Faraday::Response do
|
|
39
39
|
end.to raise_error(Instagram::BadRequest, /Bad words are bad./)
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
context 'when a 502 is raised with an HTML response' do
|
44
|
+
before do
|
45
|
+
stub_get('users/self/feed.json').to_return(
|
46
|
+
:body => '<html><body><h1>502 Bad Gateway</h1> The server returned an invalid or incomplete response. </body></html>',
|
47
|
+
:status => 502
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should raise an Instagram::BadGateway' do
|
52
|
+
lambda do
|
53
|
+
@client.user_media_feed()
|
54
|
+
end.should raise_error(Instagram::BadGateway)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when a 504 is raised with an HTML response' do
|
59
|
+
before do
|
60
|
+
stub_get('users/self/feed.json').to_return(
|
61
|
+
:body => '<html> <head><title>504 Gateway Time-out</title></head> <body bgcolor="white"> <center><h1>504 Gateway Time-out</h1></center> <hr><center>nginx</center> </body> </html>',
|
62
|
+
:status => 504
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should raise an Instagram::GatewayTimeout' do
|
67
|
+
lambda do
|
68
|
+
@client.user_media_feed()
|
69
|
+
end.should raise_error(Instagram::GatewayTimeout)
|
70
|
+
end
|
71
|
+
end
|
42
72
|
end
|
data/spec/instagram/api_spec.rb
CHANGED
@@ -30,15 +30,18 @@ describe Instagram::API do
|
|
30
30
|
|
31
31
|
before do
|
32
32
|
@configuration = {
|
33
|
-
:client_id => 'CID',
|
34
|
-
:client_secret => 'CS',
|
35
|
-
:scope => 'comments relationships',
|
36
33
|
:access_token => 'AT',
|
37
34
|
:adapter => :typhoeus,
|
35
|
+
:client_id => 'CID',
|
36
|
+
:client_secret => 'CS',
|
37
|
+
:connection_options => { :ssl => { :verify => true } },
|
38
|
+
:redirect_uri => 'http://http://localhost:4567/oauth/callback',
|
38
39
|
:endpoint => 'http://tumblr.com/',
|
39
40
|
:format => :xml,
|
40
41
|
:proxy => 'http://shayne:sekret@proxy.example.com:8080',
|
42
|
+
:scope => 'comments relationships',
|
41
43
|
:user_agent => 'Custom User Agent',
|
44
|
+
:no_response_wrapper => true,
|
42
45
|
}
|
43
46
|
end
|
44
47
|
|
@@ -53,16 +56,42 @@ describe Instagram::API do
|
|
53
56
|
|
54
57
|
context "after initilization" do
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
let(:api) { Instagram::API.new }
|
60
|
+
|
61
|
+
before do
|
58
62
|
@configuration.each do |key, value|
|
59
63
|
api.send("#{key}=", value)
|
60
64
|
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should override module configuration after initialization" do
|
61
68
|
@keys.each do |key|
|
62
69
|
api.send(key).should == @configuration[key]
|
63
70
|
end
|
64
71
|
end
|
72
|
+
|
73
|
+
describe "#connection" do
|
74
|
+
it "should use the connection_options" do
|
75
|
+
Faraday::Connection.should_receive(:new).with(include(:ssl => { :verify => true }))
|
76
|
+
api.send(:connection)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#config' do
|
84
|
+
subject { Instagram::API.new }
|
85
|
+
|
86
|
+
let(:config) do
|
87
|
+
c = {}; @keys.each {|key| c[key] = key }; c
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns a hash representing the configuration" do
|
91
|
+
@keys.each do |key|
|
92
|
+
subject.send("#{key}=", key)
|
65
93
|
end
|
94
|
+
subject.config.should == config
|
66
95
|
end
|
67
96
|
end
|
68
97
|
|
@@ -112,29 +141,76 @@ describe Instagram::API do
|
|
112
141
|
url.should_not include("scope")
|
113
142
|
end
|
114
143
|
end
|
144
|
+
|
145
|
+
describe "redirect_uri" do
|
146
|
+
it "should fall back to configuration redirect_uri if not passed as option" do
|
147
|
+
redirect_uri = 'http://localhost:4567/oauth/callback'
|
148
|
+
params = { :redirect_uri => redirect_uri }
|
149
|
+
client = Instagram::Client.new(params)
|
150
|
+
url = client.authorize_url()
|
151
|
+
url.should =~ /redirect_uri=#{URI.escape(redirect_uri, Regexp.union('/',':'))}/
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should override configuration redirect_uri if passed as option" do
|
155
|
+
redirect_uri_config = 'http://localhost:4567/oauth/callback_config'
|
156
|
+
params = { :redirect_uri => redirect_uri_config }
|
157
|
+
client = Instagram::Client.new(params)
|
158
|
+
redirect_uri_option = 'http://localhost:4567/oauth/callback_option'
|
159
|
+
options = { :redirect_uri => redirect_uri_option }
|
160
|
+
url = client.authorize_url(options)
|
161
|
+
url.should =~ /redirect_uri=#{URI.escape(redirect_uri_option, Regexp.union('/',':'))}/
|
162
|
+
end
|
163
|
+
end
|
115
164
|
end
|
116
165
|
|
117
166
|
describe ".get_access_token" do
|
118
167
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
168
|
+
describe "common functionality" do
|
169
|
+
before do
|
170
|
+
@client = Instagram::Client.new(:client_id => "CID", :client_secret => "CS")
|
171
|
+
@url = @client.send(:connection).build_url("/oauth/access_token/").to_s
|
172
|
+
stub_request(:post, @url).
|
173
|
+
with(:body => {:client_id => "CID", :client_secret => "CS", :redirect_uri => "http://localhost:4567/oauth/callback", :grant_type => "authorization_code", :code => "C"}).
|
174
|
+
to_return(:status => 200, :body => fixture("access_token.json"), :headers => {})
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should get the correct resource" do
|
178
|
+
@client.get_access_token(code="C", :redirect_uri => "http://localhost:4567/oauth/callback")
|
179
|
+
a_request(:post, @url).
|
180
|
+
with(:body => {:client_id => "CID", :client_secret => "CS", :redirect_uri => "http://localhost:4567/oauth/callback", :grant_type => "authorization_code", :code => "C"}).
|
181
|
+
should have_been_made
|
182
|
+
end
|
126
183
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
184
|
+
it "should return a hash with an access_token and user data" do
|
185
|
+
response = @client.get_access_token(code="C", :redirect_uri => "http://localhost:4567/oauth/callback")
|
186
|
+
response.access_token.should == "at"
|
187
|
+
response.user.username.should == "mikeyk"
|
188
|
+
end
|
132
189
|
end
|
133
190
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
191
|
+
describe "redirect_uri param" do
|
192
|
+
|
193
|
+
before do
|
194
|
+
@redirect_uri_config = "http://localhost:4567/oauth/callback_config"
|
195
|
+
@client = Instagram::Client.new(:client_id => "CID", :client_secret => "CS", :redirect_uri => @redirect_uri_config)
|
196
|
+
@url = @client.send(:connection).build_url("/oauth/access_token/").to_s
|
197
|
+
stub_request(:post, @url)
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should fall back to configuration redirect_uri if not passed as option" do
|
201
|
+
@client.get_access_token(code="C")
|
202
|
+
a_request(:post, @url).
|
203
|
+
with(:body => hash_including({:redirect_uri => @redirect_uri_config})).
|
204
|
+
should have_been_made
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should override configuration redirect_uri if passed as option" do
|
208
|
+
redirect_uri_option = "http://localhost:4567/oauth/callback_option"
|
209
|
+
@client.get_access_token(code="C", :redirect_uri => redirect_uri_option)
|
210
|
+
a_request(:post, @url).
|
211
|
+
with(:body => hash_including({:redirect_uri => redirect_uri_option})).
|
212
|
+
should have_been_made
|
213
|
+
end
|
138
214
|
end
|
139
215
|
end
|
140
216
|
end
|
@@ -74,6 +74,30 @@ describe Instagram::Client do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
describe ".location_search_lat_lng_distance" do
|
78
|
+
|
79
|
+
before do
|
80
|
+
stub_get("locations/search.#{format}").
|
81
|
+
with(:query => {:access_token => @client.access_token}).
|
82
|
+
with(:query => {:lat => "37.7808851", :lng => "-122.3948632", :distance => "5000"}).
|
83
|
+
to_return(:body => fixture("location_search.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should get the correct resource by lat/lng/distance" do
|
87
|
+
@client.location_search("37.7808851", "-122.3948632", "5000")
|
88
|
+
a_get("locations/search.#{format}").
|
89
|
+
with(:query => {:access_token => @client.access_token}).
|
90
|
+
with(:query => {:lat => "37.7808851", :lng => "-122.3948632", :distance => "5000"}).
|
91
|
+
should have_been_made
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return an array of user search results" do
|
95
|
+
locations = @client.location_search("37.7808851", "-122.3948632", "5000")
|
96
|
+
locations.should be_a Array
|
97
|
+
locations.first.name.should == "Instagram"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
77
101
|
describe ".location_search_foursquare_v2_id" do
|
78
102
|
|
79
103
|
before do
|
@@ -136,11 +136,14 @@ describe Instagram::Client do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
it "should raise an Instagram::InvalidSignature error" do
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
139
|
+
invalid_signatures = ["31337H4X0R", nil]
|
140
|
+
invalid_signatures.each do |signature|
|
141
|
+
lambda do
|
142
|
+
@client.process_subscription(@json, :signature => signature ) do |handler|
|
143
|
+
# hi
|
144
|
+
end
|
145
|
+
end.should raise_error(Instagram::InvalidSignature)
|
146
|
+
end
|
144
147
|
end
|
145
148
|
end
|
146
149
|
end
|
@@ -5,7 +5,7 @@ describe Instagram::Client do
|
|
5
5
|
client = Instagram::Client.new
|
6
6
|
endpoint = URI.parse(client.endpoint)
|
7
7
|
connection = client.send(:connection).build_url(nil).to_s
|
8
|
-
(connection
|
8
|
+
(connection).should == endpoint.to_s
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should not cache the user account across clients" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: instagram
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shayne Sweeney
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -61,7 +61,7 @@ dependencies:
|
|
61
61
|
version: '0.7'
|
62
62
|
- - <
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: '0.
|
64
|
+
version: '0.10'
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -71,21 +71,27 @@ dependencies:
|
|
71
71
|
version: '0.7'
|
72
72
|
- - <
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '0.
|
74
|
+
version: '0.10'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: faraday_middleware
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- -
|
79
|
+
- - ! '>='
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '0.8'
|
82
|
+
- - <
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0.10'
|
82
85
|
type: :runtime
|
83
86
|
prerelease: false
|
84
87
|
version_requirements: !ruby/object:Gem::Requirement
|
85
88
|
requirements:
|
86
|
-
- -
|
89
|
+
- - ! '>='
|
87
90
|
- !ruby/object:Gem::Version
|
88
91
|
version: '0.8'
|
92
|
+
- - <
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0.10'
|
89
95
|
- !ruby/object:Gem::Dependency
|
90
96
|
name: multi_json
|
91
97
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,6 +138,7 @@ files:
|
|
132
138
|
- .yardopts
|
133
139
|
- Gemfile
|
134
140
|
- LICENSE.md
|
141
|
+
- PATENTS.md
|
135
142
|
- README.md
|
136
143
|
- Rakefile
|
137
144
|
- instagram.gemspec
|
@@ -213,9 +220,16 @@ files:
|
|
213
220
|
homepage: https://github.com/Instagram/instagram-ruby-gem
|
214
221
|
licenses: []
|
215
222
|
metadata: {}
|
216
|
-
post_install_message: ! "********************************************************************************\n\
|
217
|
-
|
218
|
-
|
223
|
+
post_install_message: ! "********************************************************************************\n\nInstagram
|
224
|
+
REST and Search APIs\n------------------------------\nOur developer site documents
|
225
|
+
all the Instagram REST and Search APIs.\n(http://instagram.com/developer)\n\nBlog\n----------------------------\nThe
|
226
|
+
Developer Blog features news and important announcements about the Instagram Platform.
|
227
|
+
\nYou will also find tutorials and best practices to help you build great platform
|
228
|
+
integrations.\nMake sure to subscribe to the RSS feed so you don't miss out on new
|
229
|
+
posts: \n(http://developers.instagram.com).\n\nCommunity\n----------------------\nThe
|
230
|
+
Stack Overflow community is a great place to ask API related questions or if you
|
231
|
+
need help with your code.\nMake sure to tag your questions with the Instagram tag
|
232
|
+
to get fast answers from other fellow developers and members of the Instagram team.\n(http://stackoverflow.com/questions/tagged/instagram/)\n\n********************************************************************************\n"
|
219
233
|
rdoc_options: []
|
220
234
|
require_paths:
|
221
235
|
- lib
|