instagram 1.1.4 → 1.1.5
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/lib/faraday/loud_logger.rb +75 -0
- data/lib/instagram/configuration.rb +6 -1
- data/lib/instagram/connection.rb +1 -0
- data/lib/instagram/request.rb +30 -9
- data/lib/instagram/version.rb +1 -1
- data/spec/instagram/api_spec.rb +67 -0
- data/spec/instagram_spec.rb +13 -0
- data/spec/spec_helper.rb +12 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTgwYTQ4MzU4NDI1ZmI4ZTM0MGNmZDIxM2I3ZTI3YWMyMDAyNDFlYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTdiYWFiNTliYjdlNzAyMjdhMGE1YThmNjFjNmE1YjdkZjgyY2NhZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTFjM2ViODI3NGE4ZTk4ZTM3Y2FlOTM3Nzk4MjFlYzgwYjEyMTE2YWUyODIz
|
10
|
+
MzY2ZmNhMTJlNzdhNWE3ZGY1NDkwMzIxNzJmYjI1ZWEzNWM2ZGIxZmI1ZTJi
|
11
|
+
MjJhYzVlZGQ4ZDVjYjE0OTQ4ZmMzNWQyOWZiOTQ4M2EyOTQwZDg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzhlODQzNzE2YjJjZTllMGRkNGIxNTg4NjAyMWFkOTZmYjgyY2U2ZWQzZjY2
|
14
|
+
ZGNkMGQ1MmQwNmI1NjcxMDY5ODczNjE0YTA1MDJlZGRkYTlmNDZjZWIwODQz
|
15
|
+
MTBmNjczNjBjOWE4MTBkMGM5ZGIxN2ZkNmYzNzc3YjcyMTJmZDE=
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module FaradayMiddleware
|
5
|
+
# @private
|
6
|
+
class LoudLogger < Faraday::Middleware
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
9
|
+
|
10
|
+
def initialize(app, options = {})
|
11
|
+
@app = app
|
12
|
+
@logger = options.fetch(:logger) {
|
13
|
+
require 'logger'
|
14
|
+
::Logger.new($stdout)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
start_time = Time.now
|
20
|
+
info { request_info(env) }
|
21
|
+
debug { request_debug(env) }
|
22
|
+
@app.call(env).on_complete do
|
23
|
+
end_time = Time.now
|
24
|
+
response_time = end_time - start_time
|
25
|
+
info { response_info(env, response_time) }
|
26
|
+
debug { response_debug(env) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def filter(output)
|
33
|
+
if ENV['INSTAGRAM_GEM_REDACT']
|
34
|
+
output = output.to_s.gsub(/client_id=[a-zA-Z0-9]*/,'client_id=[CLIENT-ID]')
|
35
|
+
output = output.to_s.gsub(/access_token=[a-zA-Z0-9]*/,'access_token=[ACCESS-TOKEN]')
|
36
|
+
else
|
37
|
+
output
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def request_info(env)
|
42
|
+
"Started %s request to: %s" % [ env[:method].to_s.upcase, filter(env[:url]) ]
|
43
|
+
end
|
44
|
+
|
45
|
+
def response_info(env, response_time)
|
46
|
+
"Response from %s; Status: %d; Time: %.1fms" % [ filter(env[:url]), env[:status], (response_time * 1_000.0) ]
|
47
|
+
end
|
48
|
+
|
49
|
+
def request_debug(env)
|
50
|
+
debug_message("Request", env[:request_headers], env[:body])
|
51
|
+
end
|
52
|
+
|
53
|
+
def response_debug(env)
|
54
|
+
debug_message("Response", env[:response_headers], env[:body])
|
55
|
+
end
|
56
|
+
|
57
|
+
def debug_message(name, headers, body)
|
58
|
+
<<-MESSAGE.gsub(/^ +([^ ])/m, '\\1')
|
59
|
+
#{name} Headers:
|
60
|
+
----------------
|
61
|
+
#{format_headers(headers)}
|
62
|
+
|
63
|
+
#{name} Body:
|
64
|
+
-------------
|
65
|
+
#{filter(body)}
|
66
|
+
MESSAGE
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_headers(headers)
|
70
|
+
length = headers.map {|k,v| k.to_s.size }.max
|
71
|
+
headers.map { |name, value| "#{name.to_s.ljust(length)} : #{filter(value)}" }.join("\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -18,7 +18,8 @@ module Instagram
|
|
18
18
|
:format,
|
19
19
|
:proxy,
|
20
20
|
:user_agent,
|
21
|
-
:no_response_wrapper
|
21
|
+
:no_response_wrapper,
|
22
|
+
:loud_logger,
|
22
23
|
].freeze
|
23
24
|
|
24
25
|
# By default, don't set a user access token
|
@@ -72,6 +73,9 @@ module Instagram
|
|
72
73
|
VALID_FORMATS = [
|
73
74
|
:json].freeze
|
74
75
|
|
76
|
+
# By default, don't turn on loud logging
|
77
|
+
DEFAULT_LOUD_LOGGER = nil
|
78
|
+
|
75
79
|
# @private
|
76
80
|
attr_accessor *VALID_OPTIONS_KEYS
|
77
81
|
|
@@ -107,6 +111,7 @@ module Instagram
|
|
107
111
|
self.proxy = DEFAULT_PROXY
|
108
112
|
self.user_agent = DEFAULT_USER_AGENT
|
109
113
|
self.no_response_wrapper= DEFAULT_NO_RESPONSE_WRAPPER
|
114
|
+
self.loud_logger = DEFAULT_LOUD_LOGGER
|
110
115
|
end
|
111
116
|
end
|
112
117
|
end
|
data/lib/instagram/connection.rb
CHANGED
data/lib/instagram/request.rb
CHANGED
@@ -5,31 +5,43 @@ module Instagram
|
|
5
5
|
# Defines HTTP request methods
|
6
6
|
module Request
|
7
7
|
# Perform an HTTP GET request
|
8
|
-
def get(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper())
|
9
|
-
request(:get, path, options, signature, raw, unformatted, no_response_wrapper)
|
8
|
+
def get(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper(), signed=false)
|
9
|
+
request(:get, path, options, signature, raw, unformatted, no_response_wrapper, signed)
|
10
10
|
end
|
11
11
|
|
12
12
|
# Perform an HTTP POST request
|
13
|
-
def post(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper())
|
14
|
-
request(:post, path, options, signature, raw, unformatted, no_response_wrapper)
|
13
|
+
def post(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper(), signed=false)
|
14
|
+
request(:post, path, options, signature, raw, unformatted, no_response_wrapper, signed)
|
15
15
|
end
|
16
16
|
|
17
17
|
# Perform an HTTP PUT request
|
18
|
-
def put(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper())
|
19
|
-
request(:put, path, options, signature, raw, unformatted, no_response_wrapper)
|
18
|
+
def put(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper(), signed=false)
|
19
|
+
request(:put, path, options, signature, raw, unformatted, no_response_wrapper, signed)
|
20
20
|
end
|
21
21
|
|
22
22
|
# Perform an HTTP DELETE request
|
23
|
-
def delete(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper())
|
24
|
-
request(:delete, path, options, signature, raw, unformatted, no_response_wrapper)
|
23
|
+
def delete(path, options={}, signature=false, raw=false, unformatted=false, no_response_wrapper=no_response_wrapper(), signed=false)
|
24
|
+
request(:delete, path, options, signature, raw, unformatted, no_response_wrapper, signed)
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
29
|
# Perform an HTTP request
|
30
|
-
def request(method, path, options, signature=false, raw=false, unformatted=false, no_response_wrapper=false)
|
30
|
+
def request(method, path, options, signature=false, raw=false, unformatted=false, no_response_wrapper=false, signed=false)
|
31
31
|
response = connection(raw).send(method) do |request|
|
32
32
|
path = formatted_path(path) unless unformatted
|
33
|
+
|
34
|
+
if signed == true
|
35
|
+
if client_id != nil
|
36
|
+
sig_options = options.merge({:client_id => client_id})
|
37
|
+
end
|
38
|
+
if access_token != nil
|
39
|
+
sig_options = options.merge({:access_token => access_token})
|
40
|
+
end
|
41
|
+
sig = generate_sig("/"+path, sig_options, client_secret)
|
42
|
+
options[:sig] = sig
|
43
|
+
end
|
44
|
+
|
33
45
|
case method
|
34
46
|
when :get, :delete
|
35
47
|
request.url(path, options)
|
@@ -57,5 +69,14 @@ module Instagram
|
|
57
69
|
return [ips, signature].join('|')
|
58
70
|
end
|
59
71
|
|
72
|
+
def generate_sig(endpoint, params, secret)
|
73
|
+
sig = endpoint
|
74
|
+
params.sort.map do |key, val|
|
75
|
+
sig += '|%s=%s' % [key, val]
|
76
|
+
end
|
77
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
78
|
+
return OpenSSL::HMAC.hexdigest(digest, secret, sig)
|
79
|
+
end
|
80
|
+
|
60
81
|
end
|
61
82
|
end
|
data/lib/instagram/version.rb
CHANGED
data/spec/instagram/api_spec.rb
CHANGED
@@ -43,6 +43,7 @@ describe Instagram::API do
|
|
43
43
|
:scope => 'comments relationships',
|
44
44
|
:user_agent => 'Custom User Agent',
|
45
45
|
:no_response_wrapper => true,
|
46
|
+
:loud_logger => true,
|
46
47
|
}
|
47
48
|
end
|
48
49
|
|
@@ -213,5 +214,71 @@ describe Instagram::API do
|
|
213
214
|
should have_been_made
|
214
215
|
end
|
215
216
|
end
|
217
|
+
|
218
|
+
describe "loud_logger param" do
|
219
|
+
|
220
|
+
before do
|
221
|
+
@client = Instagram::Client.new(:loud_logger => true)
|
222
|
+
end
|
223
|
+
|
224
|
+
context "outputs to STDOUT with faraday logs when enabled" do
|
225
|
+
before do
|
226
|
+
stub_get('users/self/feed.json').
|
227
|
+
to_return(:body => fixture("user_media_feed.json"), :headers => {:content_type => "application/json; charset=utf-8"})
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should return the body error message" do
|
231
|
+
output = capture_output do
|
232
|
+
@client.user_media_feed()
|
233
|
+
end
|
234
|
+
|
235
|
+
expect(output).to include 'INFO -- : Started GET request to: https://api.instagram.com/v1/users/self/feed.json'
|
236
|
+
expect(output).to include 'DEBUG -- : Response Headers:'
|
237
|
+
expect(output).to include "User-Agent : Instagram Ruby Gem #{Instagram::VERSION}"
|
238
|
+
expect(output).to include 'http://distillery.s3.amazonaws.com/media/2011/01/31/0f8e832c3dc6420bb6ddf0bd09f032f6_6.jpg'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context "shows STDOUT output when errors occur" do
|
243
|
+
|
244
|
+
before do
|
245
|
+
stub_get('users/self/feed.json').
|
246
|
+
to_return(:body => '{"meta":{"error_message": "Bad words are bad."}}', :status => 400)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should return the body error message" do
|
250
|
+
output = capture_output do
|
251
|
+
@client.user_media_feed() rescue nil
|
252
|
+
end
|
253
|
+
|
254
|
+
expect(output).to include 'INFO -- : Started GET request to: https://api.instagram.com/v1/users/self/feed.json'
|
255
|
+
expect(output).to include 'DEBUG -- : Response Headers:'
|
256
|
+
expect(output).to include "User-Agent : Instagram Ruby Gem #{Instagram::VERSION}"
|
257
|
+
expect(output).to include '{"meta":{"error_message": "Bad words are bad."}}'
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "will redact API keys if INSTAGRAM_GEM_REDACT=true" do
|
262
|
+
before do
|
263
|
+
stub_get('users/self/feed.json').
|
264
|
+
to_return(:body => fixture("user_media_feed.json"), :headers => {:content_type => "application/json; charset=utf-8"})
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should redact API keys" do
|
268
|
+
ENV.stub(:[]).with('http_proxy').and_return(nil)
|
269
|
+
ENV.stub(:[]).with('INSTAGRAM_GEM_REDACT').and_return('true')
|
270
|
+
|
271
|
+
output = capture_output do
|
272
|
+
@client.user_media_feed()
|
273
|
+
end
|
274
|
+
|
275
|
+
expect(output).to include 'INFO -- : Started GET request to: https://api.instagram.com/v1/users/self/feed.json'
|
276
|
+
expect(output).to include 'DEBUG -- : Response Headers:'
|
277
|
+
expect(output).to include "User-Agent : Instagram Ruby Gem #{Instagram::VERSION}"
|
278
|
+
expect(output).to include 'http://distillery.s3.amazonaws.com/media/2011/01/31/0f8e832c3dc6420bb6ddf0bd09f032f6_6.jpg'
|
279
|
+
expect(output).to include 'access_token=[ACCESS-TOKEN]'
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
216
283
|
end
|
217
284
|
end
|
data/spec/instagram_spec.rb
CHANGED
@@ -81,6 +81,19 @@ describe Instagram do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
describe ".loud_logger" do
|
85
|
+
it "should return the loud_logger status" do
|
86
|
+
Instagram.loud_logger.should == nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe ".loud_logger=" do
|
91
|
+
it "should set the loud_logger" do
|
92
|
+
Instagram.loud_logger = true
|
93
|
+
Instagram.loud_logger.should == true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
84
97
|
describe ".configure" do
|
85
98
|
|
86
99
|
Instagram::Configuration::VALID_OPTIONS_KEYS.each do |key|
|
data/spec/spec_helper.rb
CHANGED
@@ -18,6 +18,18 @@ RSpec.configure do |config|
|
|
18
18
|
config.include WebMock::API
|
19
19
|
end
|
20
20
|
|
21
|
+
def capture_output(&block)
|
22
|
+
begin
|
23
|
+
old_stdout = $stdout
|
24
|
+
$stdout = StringIO.new
|
25
|
+
block.call
|
26
|
+
result = $stdout.string
|
27
|
+
ensure
|
28
|
+
$stdout = old_stdout
|
29
|
+
end
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
21
33
|
def a_delete(path)
|
22
34
|
a_request(:delete, Instagram.endpoint + path)
|
23
35
|
end
|
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: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shayne Sweeney
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- README.md
|
158
158
|
- Rakefile
|
159
159
|
- instagram.gemspec
|
160
|
+
- lib/faraday/loud_logger.rb
|
160
161
|
- lib/faraday/oauth2.rb
|
161
162
|
- lib/faraday/raise_http_exception.rb
|
162
163
|
- lib/instagram.rb
|