tumblr_client 0.6.11 → 0.7.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.
- data/.gitignore +10 -1
- data/.travis.yml +10 -0
- data/README.md +30 -11
- data/lib/tumblr/blog.rb +50 -64
- data/lib/tumblr/client.rb +8 -6
- data/lib/tumblr/config.rb +7 -9
- data/lib/tumblr/connection.rb +12 -7
- data/lib/tumblr/helpers.rb +14 -9
- data/lib/tumblr/post.rb +96 -99
- data/lib/tumblr/request.rb +13 -0
- data/lib/tumblr/request/oauth.rb +21 -21
- data/lib/tumblr/tagged.rb +9 -14
- data/lib/tumblr/user.rb +37 -36
- data/lib/tumblr/version.rb +5 -0
- data/lib/tumblr_client.rb +7 -2
- data/spec/examples/blog_spec.rb +185 -0
- data/spec/examples/client_spec.rb +46 -0
- data/spec/examples/post_spec.rb +186 -0
- data/spec/examples/tagged_spec.rb +31 -0
- data/spec/examples/user_spec.rb +114 -0
- data/spec/spec_helper.rb +7 -0
- data/{tumblr.gemspec → tumblr_client.gemspec} +4 -2
- metadata +34 -10
- data/.path +0 -1
- data/Gemfile.lock +0 -43
data/lib/tumblr/request.rb
CHANGED
@@ -11,6 +11,16 @@ module Tumblr
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
# get a redirect url
|
15
|
+
def get_redirect_url(path, params = {})
|
16
|
+
response = get_response path, params
|
17
|
+
if response.status == 301
|
18
|
+
response.headers['Location']
|
19
|
+
else
|
20
|
+
response.body['meta']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
14
24
|
# Performs a get request
|
15
25
|
def get(path, params={})
|
16
26
|
respond get_response(path, params)
|
@@ -18,6 +28,9 @@ module Tumblr
|
|
18
28
|
|
19
29
|
# Performs post request
|
20
30
|
def post(path, params={})
|
31
|
+
if Array === params[:tags]
|
32
|
+
params[:tags] = params[:tags].join(',')
|
33
|
+
end
|
21
34
|
response = connection.post do |req|
|
22
35
|
req.url path
|
23
36
|
req.body = params unless params.empty?
|
data/lib/tumblr/request/oauth.rb
CHANGED
@@ -7,22 +7,22 @@ require 'base64'
|
|
7
7
|
module Tumblr
|
8
8
|
module Request
|
9
9
|
class TumblrOAuth < Faraday::Middleware
|
10
|
+
|
10
11
|
def call(env)
|
11
|
-
if env[:method].to_s ==
|
12
|
-
|
13
|
-
|
12
|
+
if env[:method].to_s == 'get'
|
13
|
+
params = Faraday::Utils.parse_query(env[:url].query) || {}
|
14
|
+
url = "#{env[:url].scheme}://#{env[:url].host}#{env[:url].path}"
|
14
15
|
else
|
15
|
-
|
16
|
-
|
16
|
+
params = env[:body] || {}
|
17
|
+
url = env[:url]
|
17
18
|
end
|
18
19
|
signature_params = params
|
19
20
|
params.each do |key, value|
|
20
21
|
signature_params = {} if value.respond_to?(:content_type)
|
21
22
|
end
|
22
|
-
env[:request_headers][
|
23
|
-
env[:request_headers][
|
24
|
-
env[:request_headers][
|
25
|
-
|
23
|
+
env[:request_headers]['Authorization'] = self.oauth_gen(env[:method], url, signature_params)
|
24
|
+
env[:request_headers]['Content-type'] = 'application/x-www-form-urlencoded'
|
25
|
+
env[:request_headers]['Host'] = @options[:api_host]
|
26
26
|
|
27
27
|
@app.call(env)
|
28
28
|
end
|
@@ -37,36 +37,36 @@ module Tumblr
|
|
37
37
|
params[:oauth_signature_method] = 'HMAC-SHA1'
|
38
38
|
params[:oauth_timestamp] = Time.now.to_i
|
39
39
|
params[:oauth_token] = @options[:token]
|
40
|
-
params[:oauth_version] =
|
40
|
+
params[:oauth_version] = '1.0'
|
41
41
|
params[:oauth_signature] = self.oauth_sig(method, url, params)
|
42
|
-
|
42
|
+
|
43
43
|
header = []
|
44
44
|
params.each do |key, value|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
if key.to_s.include?('oauth')
|
46
|
+
header << "#{key.to_s}=#{value}"
|
47
|
+
end
|
48
48
|
end
|
49
49
|
|
50
50
|
"OAuth #{header.join(", ")}"
|
51
|
-
|
52
51
|
end
|
53
|
-
|
52
|
+
|
54
53
|
def oauth_sig(method, url, params)
|
55
54
|
parts = [method.upcase, URI.encode(url.to_s, /[^a-z0-9\-\.\_\~]/i)]
|
56
|
-
|
55
|
+
|
57
56
|
#sort the parameters
|
58
57
|
params = Hash[params.sort_by{ |key, value| key.to_s}]
|
59
|
-
|
58
|
+
|
60
59
|
encoded = []
|
61
60
|
params.each do |key, value|
|
62
|
-
|
61
|
+
encoded << "#{key.to_s}=#{URI.encode(value.to_s, /[^a-z0-9\-\.\_\~]/i)}"
|
63
62
|
end
|
64
63
|
|
65
|
-
parts << URI.encode(encoded.join(
|
66
|
-
signature_base = parts.join(
|
64
|
+
parts << URI.encode(encoded.join('&'), /[^a-z0-9\-\.\_\~]/i)
|
65
|
+
signature_base = parts.join('&')
|
67
66
|
secret = "#{@options[:consumer_secret]}&#{@options[:token_secret]}"
|
68
67
|
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, secret, signature_base)).chomp.gsub(/\n/, '')
|
69
68
|
end
|
69
|
+
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
data/lib/tumblr/tagged.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
1
|
module Tumblr
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
params.merge!(options)
|
11
|
-
end
|
12
|
-
if valid_options(@@standard_options, options)
|
13
|
-
get("v2/tagged", params)
|
14
|
-
end
|
15
|
-
end
|
2
|
+
module Tagged
|
3
|
+
|
4
|
+
def tagged(tag, options={})
|
5
|
+
validate_options([:before, :limit, :filter], options)
|
6
|
+
|
7
|
+
params = { :tag => tag, :api_key => @consumer_key }
|
8
|
+
params.merge!(options)
|
9
|
+
get("v2/tagged", params)
|
16
10
|
end
|
11
|
+
|
17
12
|
end
|
18
13
|
end
|
data/lib/tumblr/user.rb
CHANGED
@@ -1,40 +1,41 @@
|
|
1
1
|
module Tumblr
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
2
|
+
module User
|
3
|
+
|
4
|
+
def info
|
5
|
+
get('v2/user/info')
|
6
|
+
end
|
7
|
+
|
8
|
+
def dashboard(options = {})
|
9
|
+
valid_opts = [:limit, :offset, :type, :since_id, :reblog_info, :notes_info]
|
10
|
+
validate_options(valid_opts, options)
|
11
|
+
get('v2/user/dashboard', options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def likes(options = {})
|
15
|
+
validate_options([:limit, :offset], options)
|
16
|
+
get('v2/user/likes', options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def following(options = {})
|
20
|
+
validate_options([:limit, :offset], options)
|
21
|
+
get('v2/user/following', options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def follow(url)
|
25
|
+
post('v2/user/follow', :url => url)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unfollow(url)
|
29
|
+
post('v2/user/unfollow', :url => url)
|
30
|
+
end
|
31
|
+
|
32
|
+
def like(id, reblog_key)
|
33
|
+
post('v2/user/like', :id => id, :reblog_key => reblog_key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def unlike(id, reblog_key)
|
37
|
+
post('v2/user/unlike', :id => id, :reblog_key => reblog_key)
|
38
38
|
end
|
39
|
+
|
39
40
|
end
|
40
41
|
end
|
data/lib/tumblr_client.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'tumblr/client'
|
2
|
+
require 'tumblr/config'
|
3
3
|
|
4
4
|
module Tumblr
|
5
|
+
|
6
|
+
autoload :VERSION, File.join(File.dirname(__FILE__), 'tumblr/version')
|
7
|
+
|
5
8
|
extend Config
|
9
|
+
|
6
10
|
class << self
|
7
11
|
def new(options={})
|
8
12
|
Tumblr::Client.new(options)
|
9
13
|
end
|
10
14
|
end
|
15
|
+
|
11
16
|
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tumblr::Blog do
|
4
|
+
|
5
|
+
let(:blog_name) { 'seejohnrun.tumblr.com' }
|
6
|
+
let(:consumer_key) { 'ckey' }
|
7
|
+
let(:client) do
|
8
|
+
Tumblr::Client.new :consumer_key => consumer_key
|
9
|
+
end
|
10
|
+
|
11
|
+
describe :blog_info do
|
12
|
+
|
13
|
+
it 'should make the proper request' do
|
14
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/info", {
|
15
|
+
:api_key => consumer_key
|
16
|
+
}).and_return 'response'
|
17
|
+
r = client.blog_info blog_name
|
18
|
+
r.should == 'response'
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe :avatar do
|
24
|
+
|
25
|
+
context 'when supplying a size' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
client.should_receive(:get_redirect_url).once.with("v2/blog/#{blog_name}/avatar/128").
|
29
|
+
and_return('url')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should construct the request properly' do
|
33
|
+
r = client.avatar blog_name, 128
|
34
|
+
r.should == 'url'
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when no size is specified' do
|
40
|
+
|
41
|
+
before do
|
42
|
+
client.should_receive(:get_redirect_url).once.with("v2/blog/#{blog_name}/avatar").
|
43
|
+
and_return('url')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should construct the request properly' do
|
47
|
+
r = client.avatar blog_name
|
48
|
+
r.should == 'url'
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe :followers do
|
56
|
+
|
57
|
+
context 'with invalid parameters' do
|
58
|
+
|
59
|
+
it 'should raise an error' do
|
60
|
+
lambda {
|
61
|
+
client.followers blog_name, :not => 'an option'
|
62
|
+
}.should raise_error ArgumentError
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with valid parameters' do
|
68
|
+
|
69
|
+
before do
|
70
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/followers", {
|
71
|
+
:limit => 1
|
72
|
+
}).and_return('response')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should construct the request properly' do
|
76
|
+
r = client.followers blog_name, :limit => 1
|
77
|
+
r.should == 'response'
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
describe :blog_likes do
|
85
|
+
|
86
|
+
context 'with invalid parameters' do
|
87
|
+
|
88
|
+
it 'should raise an error' do
|
89
|
+
lambda {
|
90
|
+
client.blog_likes blog_name, :not => 'an option'
|
91
|
+
}.should raise_error ArgumentError
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'with valid parameters' do
|
97
|
+
|
98
|
+
before do
|
99
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/likes", {
|
100
|
+
:limit => 1,
|
101
|
+
:api_key => consumer_key
|
102
|
+
}).and_return('response')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should construct the request properly' do
|
106
|
+
r = client.blog_likes blog_name, :limit => 1
|
107
|
+
r.should == 'response'
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
describe :posts do
|
115
|
+
|
116
|
+
context 'without a type supplied' do
|
117
|
+
|
118
|
+
before do
|
119
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/posts", {
|
120
|
+
:limit => 1,
|
121
|
+
:api_key => consumer_key
|
122
|
+
}).and_return('response')
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should construct the request properly' do
|
126
|
+
r = client.posts blog_name, :limit => 1
|
127
|
+
r.should == 'response'
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when supplying a type' do
|
133
|
+
|
134
|
+
before do
|
135
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/posts/audio", {
|
136
|
+
:limit => 1,
|
137
|
+
:api_key => consumer_key,
|
138
|
+
:type => 'audio'
|
139
|
+
}).and_return('response')
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should construct the request properly' do
|
143
|
+
r = client.posts blog_name, :limit => 1, :type => 'audio'
|
144
|
+
r.should == 'response'
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
# These are all just lists of posts with pagination
|
152
|
+
[:queue, :draft, :submissions].each do |type|
|
153
|
+
|
154
|
+
ext = type == :submissions ? 'submission' : type.to_s # annoying
|
155
|
+
|
156
|
+
describe type do
|
157
|
+
|
158
|
+
context 'when using parameters other than limit & offset' do
|
159
|
+
|
160
|
+
it 'should raise an error' do
|
161
|
+
lambda {
|
162
|
+
client.send type, blog_name, :not => 'an option'
|
163
|
+
}.should raise_error ArgumentError
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'with valid options' do
|
169
|
+
|
170
|
+
it 'should construct the call properly' do
|
171
|
+
limit = 5
|
172
|
+
client.should_receive(:get).once.with("v2/blog/#{blog_name}/posts/#{ext}", {
|
173
|
+
:limit => limit
|
174
|
+
}).and_return('response')
|
175
|
+
r = client.send type, blog_name, :limit => limit
|
176
|
+
r.should == 'response'
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tumblr::Client do
|
4
|
+
|
5
|
+
context 'when using the generic copy' do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@key = 'thekey'
|
9
|
+
Tumblr.configure do |c|
|
10
|
+
c.consumer_key = @key
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should give new clients those credentials' do
|
15
|
+
client = Tumblr::Client.new
|
16
|
+
client.credentials[:consumer_key].should == @key
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have it\'s own credentials' do
|
20
|
+
Tumblr.credentials[:consumer_key].should == @key
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be able to make a new client (using these credentials)' do
|
24
|
+
Tumblr.new.should be_a(Tumblr::Client)
|
25
|
+
Tumblr.new.credentials[:consumer_key].should == @key
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when using custom copies of the client' do
|
31
|
+
|
32
|
+
before do
|
33
|
+
@client1 = Tumblr::Client.new(:consumer_key => 'key1')
|
34
|
+
@client2 = Tumblr::Client.new(:consumer_key => 'key2')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should keep them separate' do
|
38
|
+
[
|
39
|
+
@client1.credentials[:consumer_key],
|
40
|
+
@client2.credentials[:consumer_key]
|
41
|
+
].uniq.count.should == 2
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|