tumblr_client 0.6.11 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,11 @@
1
1
  *.gem
2
- .DS_Store
2
+ .DS_Store
3
+
4
+ *.swp
5
+ *.swo
6
+
7
+ tmp
8
+ coverage
9
+ .rspec
10
+
11
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ script: 'rspec spec'
2
+ notifications:
3
+ email:
4
+ - john.crepezzi@gmail.com
5
+ branches:
6
+ only:
7
+ - master
8
+ rvm:
9
+ - 1.9.2
10
+ - 1.9.3
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Tumblr Ruby Gem
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/codingjester/tumblr_client.png)](http://travis-ci.org/codingjester/tumblr_client)
4
+
3
5
  This is a ruby wrapper for the Tumblr v2 API. There should be support for all endpoints
4
6
  currently available on the [Tumblr API](http://www.tumblr.com/docs/en/api/v2).
5
7
 
@@ -18,10 +20,10 @@ your life easier when using the v2 api. If you need to do the full oauth workflo
18
20
  Configuration for the gem is actually pretty easy:
19
21
 
20
22
  Tumblr.configure do |config|
21
- config.consumer_key = "consumer_key"
22
- config.consumer_secret = "consumer_secret"
23
- config.oauth_token = "access_token"
24
- config.oauth_token_secret = "access_token_secret"
23
+ config.consumer_key = "consumer_key"
24
+ config.consumer_secret = "consumer_secret"
25
+ config.oauth_token = "access_token"
26
+ config.oauth_token_secret = "access_token_secret"
25
27
  end
26
28
 
27
29
  Once you have your configuration squared away it's time to make some requests!
@@ -33,27 +35,31 @@ That's it! You now have a client that can make any request to the Tumblr API.
33
35
  ### Some quick examples
34
36
 
35
37
  Getting user information:
36
-
38
+
37
39
  >> client.info
38
40
 
39
41
  Getting a specific blog's posts and type:
40
-
42
+
41
43
  #Grabbing a specific blogs posts
42
44
  >> client.posts("codingjester.tumblr.com")
43
-
44
- #Grabbing only the last 10 photos off the blog
45
+
46
+ #Grabbing only the last 10 photos off the blog
45
47
  >> client.posts("codingjester.tumblr.com", :type => "photo", :limit => 10)
46
48
 
47
49
 
48
50
  Posting some photos to Tumblr:
49
51
 
50
- #Uploads a great photoset
52
+ # Uploads a great photoset
51
53
  >> client.photo("codingjester.tumblr.com", {:data => ['/path/to/pic.jpg', '/path/to/pic.jpg']})
52
54
 
55
+ # You can also post with the raw data
56
+ >> raw = File.open('/path/to/pic.jpg', 'rb').read
57
+ >> client.photo('codingjester.tumblr.com', :data_raw => [raw]
58
+
53
59
  ### The irb Console
54
60
 
55
61
  Finally, there is an irb console packaged with the gem that should help you test any calls you want to make.
56
- The magic here is that you have a ```.tumblr``` file in your home directory. Inside this file it's just a basic
62
+ The magic here is that you have a `.tumblr` file in your home directory. Inside this file it's just a basic
57
63
  YAML layout with four lines:
58
64
 
59
65
  consumer_key: "your_consumer_key"
@@ -61,12 +67,25 @@ YAML layout with four lines:
61
67
  oauth_token: "your_access_token"
62
68
  oauth_token_secret: "your_access_token_secret"
63
69
 
64
- From there, you should be able to run any of the above commands, with no problem! Just fire off the command ```tumblr``
70
+ From there, you should be able to run any of the above commands, with no problem! Just fire off the command `tumblr`
65
71
  from the terminal and you should be dropped into a console.
66
72
 
73
+ ---
74
+
75
+ The first time that you go to use the irb console, if you have no `.tumblr`
76
+ file, it will walk you through the process of generating one. You will
77
+ be prompted for your consumer_key and consumer_secret (which you can get
78
+ here: http://www.tumblr.com/oauth/register) and then sent out to the site
79
+ to verify your account. Once you verify, you will be redirected to your
80
+ redirect URL (localhost by default) and copy the `oauth_verifier` back into the
81
+ console. Then you're all set!
67
82
 
68
83
  ### Contributions and Pull Requests
69
84
 
70
85
  No request is too small and I encourage everyone to get involved. As you can see, we're sorely lacking in tests! So
71
86
  please if you would like to contribute, let me know and throw me a pull request!
72
87
 
88
+
89
+ ### Requirements
90
+
91
+ * Ruby >= 1.9.2
data/lib/tumblr/blog.rb CHANGED
@@ -1,73 +1,59 @@
1
1
  module Tumblr
2
- class Client
3
- module Blog
4
-
5
- @@standard_options = [:type, :id, :tag, :limit, :offset, :reblog_info, :notes_info, :filter]
6
- #
7
- #Gets the info about the blog
8
- #
9
- def blog_info(blog_name)
10
- get("v2/blog/#{blog_name}/info", {:api_key => @consumer_key})
11
- end
2
+ module Blog
12
3
 
13
- #
14
- # Gets the avatar URL of specified size
15
- #
16
- def avatar(blog_name, size = nil)
17
- response = get_response("v2/blog/#{blog_name}/avatar", :size => size)
18
- if response.status == 301
19
- response.headers['Location']
20
- end
21
- end
4
+ # Gets the info about the blog
5
+ def blog_info(blog_name)
6
+ get("v2/blog/#{blog_name}/info", :api_key => @consumer_key)
7
+ end
22
8
 
23
- #
24
- # Gets the list of followers for the blog
25
- #
26
- def followers(blog_name, options={})
27
- if valid_options([:limit, :offset], options)
28
- get("v2/blog/#{blog_name}/followers", options)
29
- end
30
- end
31
-
32
- #
33
- # Gets the list of likes for the blog
34
- #
35
- def blog_likes(blog_name, options={})
36
- if valid_options([:limit, :offset], options)
37
- url = "v2/blog/#{blog_name}/likes"
38
- params = {:api_key => @consumer_key}
39
- unless options.empty?
40
- params.merge!(options)
41
- end
42
- get(url, params)
43
- end
44
- end
9
+ # Gets the avatar URL of specified size
10
+ def avatar(blog_name, size = nil)
11
+ url = "v2/blog/#{blog_name}/avatar"
12
+ url = "#{url}/#{size}" if size
13
+ get_redirect_url(url)
14
+ end
45
15
 
46
- def posts(blog_name, options={})
47
- url = "v2/blog/#{blog_name}/posts"
48
-
49
- if options.has_key?(:type)
50
- url = "#{url}/#{options[:type]}"
51
- end
52
-
53
- params = {:api_key => @consumer_key}
54
- unless options.empty?
55
- params.merge!(options)
56
- end
57
- get(url, params)
58
- end
16
+ # Gets the list of followers for the blog
17
+ def followers(blog_name, options = {})
18
+ validate_options([:limit, :offset], options)
19
+ get("v2/blog/#{blog_name}/followers", options)
20
+ end
59
21
 
60
- def queue(blog_name)
61
- get("v2/blog/#{blog_name}/posts/queue", {})
62
- end
63
-
64
- def draft(blog_name)
65
- get("v2/blog/#{blog_name}/posts/draft", {})
66
- end
67
-
68
- def submissions(blog_name)
69
- get("v2/blog/#{blog_name}/posts/submission", {})
22
+ # Gets the list of likes for the blog
23
+ def blog_likes(blog_name, options = {})
24
+ validate_options([:limit, :offset], options)
25
+ url = "v2/blog/#{blog_name}/likes"
26
+
27
+ params = { :api_key => @consumer_key }
28
+ params.merge! options
29
+ get(url, params)
30
+ end
31
+
32
+ def posts(blog_name, options = {})
33
+ url = "v2/blog/#{blog_name}/posts"
34
+ if options.has_key?(:type)
35
+ url = "#{url}/#{options[:type]}"
70
36
  end
37
+
38
+ params = { :api_key => @consumer_key }
39
+ params.merge! options
40
+ get(url, params)
41
+ end
42
+
43
+ def queue(blog_name, options = {})
44
+ validate_options([:limit, :offset], options)
45
+ get("v2/blog/#{blog_name}/posts/queue", options)
71
46
  end
47
+
48
+ def draft(blog_name, options = {})
49
+ validate_options([:limit, :offset], options)
50
+ get("v2/blog/#{blog_name}/posts/draft", options)
51
+ end
52
+
53
+ def submissions(blog_name, options = {})
54
+ validate_options([:limit, :offset], options)
55
+ get("v2/blog/#{blog_name}/posts/submission", options)
56
+ end
57
+
72
58
  end
73
59
  end
data/lib/tumblr/client.rb CHANGED
@@ -8,14 +8,15 @@ require 'tumblr/helpers'
8
8
 
9
9
  module Tumblr
10
10
  class Client
11
+
11
12
  include Tumblr::Request
12
- include Tumblr::Client::Blog
13
- include Tumblr::Client::User
14
- include Tumblr::Client::Post
15
- include Tumblr::Client::Tagged
16
- include Tumblr::Client::Helper
13
+ include Tumblr::Blog
14
+ include Tumblr::User
15
+ include Tumblr::Post
16
+ include Tumblr::Tagged
17
+ include Tumblr::Helper
17
18
  include Tumblr::Connection
18
-
19
+
19
20
  def initialize(attrs= {})
20
21
  attrs = Tumblr.options.merge(attrs)
21
22
  Config::VALID_OPTIONS_KEYS.each do |key|
@@ -35,5 +36,6 @@ module Tumblr
35
36
  :token_secret => @oauth_token_secret
36
37
  }
37
38
  end
39
+
38
40
  end
39
41
  end
data/lib/tumblr/config.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module Tumblr
2
-
3
2
  module Config
4
3
 
5
4
  VALID_OPTIONS_KEYS = [
@@ -8,29 +7,28 @@ module Tumblr
8
7
  :oauth_token,
9
8
  :oauth_token_secret
10
9
  ]
11
-
10
+
12
11
  attr_accessor *VALID_OPTIONS_KEYS
13
12
 
14
13
  def configure
15
14
  yield self
16
15
  self
17
16
  end
18
-
17
+
19
18
  def options
20
19
  options = {}
21
- VALID_OPTIONS_KEYS.each{ |k| options[k] = send(k) }
20
+ VALID_OPTIONS_KEYS.each{ |pname| options[pname] = send(pname) }
22
21
  options
23
22
  end
24
23
 
25
24
  def credentials
26
25
  {
27
- :consumer_key => consumer_key,
28
- :consumer_secret => consumer_secret,
29
- :token => oauth_token,
30
- :token_secret => oauth_token_secret
26
+ :consumer_key => consumer_key,
27
+ :consumer_secret => consumer_secret,
28
+ :token => oauth_token,
29
+ :token_secret => oauth_token_secret
31
30
  }
32
31
  end
33
32
 
34
33
  end
35
-
36
34
  end
@@ -4,21 +4,26 @@ require 'tumblr/request/oauth'
4
4
 
5
5
  module Tumblr
6
6
  module Connection
7
+
7
8
  def connection(options={})
9
+ host = api_host
8
10
  default_options = {
9
11
  :headers => {
10
- :accept => "application/json",
11
- :user_agent => "Tumblr v1.0"
12
+ :accept => 'application/json',
13
+ :user_agent => "tumblr_client (ruby) - #{Tumblr::VERSION}"
12
14
  },
13
- :url => "http://#{api_host}/"
15
+ :url => "http://#{host}/"
14
16
  }
15
- Faraday.new("http://#{api_host}/", default_options.merge(options)) do |builder|
16
- data = { :api_host => api_host }.merge(credentials)
17
- builder.use Tumblr::Request::TumblrOAuth, data unless credentials.empty?
17
+ Faraday.new("http://#{host}/", default_options.merge(options)) do |builder|
18
+ data = { :api_host => host }.merge(credentials)
19
+ unless credentials.empty?
20
+ builder.use Tumblr::Request::TumblrOAuth, data
21
+ end
18
22
  builder.use Faraday::Request::UrlEncoded
19
- builder.use FaradayMiddleware::ParseJson, :content_type => "application/json"
23
+ builder.use FaradayMiddleware::ParseJson, :content_type => 'application/json'
20
24
  builder.use Faraday::Adapter::NetHttp
21
25
  end
22
26
  end
27
+
23
28
  end
24
29
  end
@@ -1,14 +1,19 @@
1
1
  module Tumblr
2
- class Client
3
- module Helper
4
-
5
- def valid_options(valid_opts, opts)
6
- bad_opts = opts.select { |val| !valid_opts.include?(val) }
7
- if !bad_opts.empty?
8
- raise Exception, "Invalid options passed, Only #{valid_opts} allowed."
9
- end
10
- return true
2
+ module Helper
3
+
4
+ def validate_options(valid_opts, opts)
5
+ bad_opts = opts.select { |val| !valid_opts.include?(val) }
6
+ if bad_opts.any?
7
+ raise ArgumentError.new "Invalid options (#{bad_opts.keys.join(', ')}) passed, only #{valid_opts} allowed."
11
8
  end
12
9
  end
10
+
11
+ def validate_no_collision(options, attributes)
12
+ count = attributes.count { |attr| options.has_key?(attr) }
13
+ if count > 1
14
+ raise ArgumentError.new "Can only use one of: #{attributes.join(', ')} (Found #{count})"
15
+ end
16
+ end
17
+
13
18
  end
14
19
  end
data/lib/tumblr/post.rb CHANGED
@@ -1,113 +1,110 @@
1
1
  module Tumblr
2
- class Client
3
- module Post
4
-
5
- @@standard_post_options = [:state, :tags, :tweet, :date, :markdown, :slug, :format]
6
-
7
- def edit(blog_name, options={})
8
- post("v2/blog/#{blog_name}/post/edit", options)
9
- end
2
+ module Post
10
3
 
11
- #Don't be lazy and create a nice interface
12
- def reblog(blog_name, options={})
13
- post("v2/blog/#{blog_name}/post/reblog", options)
14
- end
15
-
16
- def delete(blog_name, id)
17
- post("v2/blog/#{blog_name}/post/delete", {:id => id})
18
- end
4
+ STANDARD_POST_OPTIONS = [:state, :tags, :tweet, :date, :markdown, :slug, :format]
19
5
 
20
- def photo(blog_name, options={})
21
- valid_opts = @@standard_post_options + [:caption, :link, :data, :source, :photoset_layout]
22
- if valid_options(valid_opts, options)
23
- options[:type] = "photo"
24
- if (options.has_key?(:data) && options.has_key?(:source))
25
- raise Exception, "You can only use one parameter, either source or data."
26
- end
27
- if options.has_key?(:source) && options[:source].kind_of?(Array)
28
- count = 0
29
- options[:source].each do |src|
30
- options["source[#{count}]"] = src
31
- count += 1
32
- end
33
- options.delete(:source)
34
- end
35
- if options.has_key?(:data)
36
- #Probably can be refactored
37
- if options[:data].kind_of?(Array)
38
- count = 0
39
- options[:data].each do |filepath|
40
- options["data[#{count}]"] = File.open(filepath, 'rb').read()
41
- count += 1
42
- end
43
- options.delete(:data)
44
- else
45
- options[:data] = File.open(options[:data],'rb').read()
46
- end
47
- end
48
- post("v2/blog/#{blog_name}/post", options)
49
- end
50
- end
51
-
52
- def quote(blog_name, options={})
53
- valid_opts = @@standard_post_options + [:quote, :source]
54
- if valid_options(valid_opts, options)
55
- options[:type] = "quote"
56
- post("v2/blog/#{blog_name}/post", options)
57
- end
58
- end
6
+ def edit(blog_name, options = {})
7
+ post("v2/blog/#{blog_name}/post/edit", options)
8
+ end
59
9
 
60
- def text(blog_name, options={})
61
- valid_opts = @@standard_post_options + [:title, :body]
62
- if valid_options(valid_opts, options)
63
- options[:type] = "text"
64
- post("v2/blog/#{blog_name}/post", options)
65
- end
66
- end
10
+ def reblog(blog_name, options = {})
11
+ post("v2/blog/#{blog_name}/post/reblog", options)
12
+ end
67
13
 
68
- def link(blog_name, options={})
69
- valid_opts = @@standard_post_options + [:title, :url, :description]
70
- if valid_options(valid_opts, options)
71
- options[:type] = "link"
72
- post("v2/blog/#{blog_name}/post", options)
73
- end
74
- end
14
+ def delete(blog_name, id)
15
+ post("v2/blog/#{blog_name}/post/delete", :id => id)
16
+ end
17
+
18
+ def photo(blog_name, options = {})
19
+ valid_opts = STANDARD_POST_OPTIONS + [:caption, :link, :data, :data_raw, :source, :photoset_layout]
20
+ validate_options(valid_opts, options)
21
+ validate_no_collision options, [:data, :source]
75
22
 
76
- def chat(blog_name, options={})
77
- valid_opts = @@standard_post_options + [:title, :conversation]
78
- if valid_options(valid_opts, options)
79
- options[:type] = "chat"
80
- post("v2/blog/#{blog_name}/post", options)
23
+ # Allow source to be passed as an Array
24
+ if options.has_key?(:source) && options[:source].kind_of?(Array)
25
+ options[:source].each.with_index do |src, idx|
26
+ options["source[#{idx}]"] = src
81
27
  end
28
+ options.delete(:source)
82
29
  end
83
30
 
84
- def audio(blog_name, options={})
85
- valid_opts = @@standard_post_options + [:data, :caption, :external_url]
86
- if valid_options(valid_opts, options)
87
- options[:type] = "audio"
88
- if (options.has_key?(:data) && options.has_key?(:external_url))
89
- raise Exception, "You can only use one parameter, either data or external url."
90
- end
91
- if(options.has_key?(:data))
92
- options[:data] = File.open(options[:data],'rb').read()
93
- end
94
- post("v2/blog/#{blog_name}/post", options)
31
+ options[:type] = 'photo'
32
+ extract_data!(options)
33
+ post("v2/blog/#{blog_name}/post", options)
34
+ end
35
+
36
+ def quote(blog_name, options = {})
37
+ valid_opts = STANDARD_POST_OPTIONS + [:quote, :source]
38
+ validate_options(valid_opts, options)
39
+
40
+ options[:type] = 'quote'
41
+ post("v2/blog/#{blog_name}/post", options)
42
+ end
43
+
44
+ def text(blog_name, options = {})
45
+ valid_opts = STANDARD_POST_OPTIONS + [:title, :body]
46
+ validate_options(valid_opts, options)
47
+
48
+ options[:type] = 'text'
49
+ post("v2/blog/#{blog_name}/post", options)
50
+ end
51
+
52
+ def link(blog_name, options = {})
53
+ valid_opts = STANDARD_POST_OPTIONS + [:title, :url, :description]
54
+ validate_options(valid_opts, options)
55
+
56
+ options[:type] = 'link'
57
+ post("v2/blog/#{blog_name}/post", options)
58
+ end
59
+
60
+ def chat(blog_name, options = {})
61
+ valid_opts = STANDARD_POST_OPTIONS + [:title, :conversation]
62
+ validate_options(valid_opts, options)
63
+
64
+ options[:type] = 'chat'
65
+ post("v2/blog/#{blog_name}/post", options)
66
+ end
67
+
68
+ def audio(blog_name, options = {})
69
+ valid_opts = STANDARD_POST_OPTIONS + [:data, :data_raw, :caption, :external_url]
70
+ validate_options(valid_opts, options)
71
+ validate_no_collision options, [:data, :external_url]
72
+
73
+ options[:type] = 'audio'
74
+ extract_data!(options)
75
+ post("v2/blog/#{blog_name}/post", options)
76
+ end
77
+
78
+ def video(blog_name, options = {})
79
+ valid_opts = STANDARD_POST_OPTIONS + [:data, :data_raw, :embed, :caption]
80
+ validate_options(valid_opts, options)
81
+ validate_no_collision options, [:data, :embed]
82
+
83
+ options[:type] = 'video'
84
+ extract_data!(options)
85
+ post("v2/blog/#{blog_name}/post", options)
86
+ end
87
+
88
+ private
89
+
90
+ # Look for the various ways that data can be passed, and normalize
91
+ # the result in this hash
92
+ def extract_data!(options)
93
+ validate_no_collision options, [:data, :data_raw]
94
+ if options.has_key?(:data)
95
+ data = options.delete :data
96
+ data = [data] unless Array === data
97
+ data.each.with_index do |filepath, idx|
98
+ options["data[#{idx}]"] = File.open(filepath, 'rb').read
95
99
  end
96
- end
97
-
98
- def video(blog_name, options={})
99
- valid_opts = @@standard_post_options + [:data, :embed, :caption]
100
- if valid_options(valid_opts, options)
101
- options[:type] = "video"
102
- if (options.has_key?(:data) && options.has_key?(:embed))
103
- raise Exception, "You can only use one parameter, either data or embed."
104
- end
105
- if(options.has_key?(:data))
106
- options[:data] = File.open(options[:data],'rb').read()
107
- end
108
- post("v2/blog/#{blog_name}/post", options)
100
+ elsif options.has_key?(:data_raw)
101
+ data_raw = options.delete :data_raw
102
+ data_raw = [data_raw] unless Array === data_raw
103
+ data_raw.each.with_index do |dr, idx|
104
+ options["data[#{idx}]"] = dr
109
105
  end
110
106
  end
111
107
  end
112
- end
108
+
109
+ end
113
110
  end