jamescallmebrent-rumblr 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.rdoc ADDED
@@ -0,0 +1,24 @@
1
+ = License
2
+
3
+ (The MIT License)
4
+
5
+ Copyright (c) 2009 Brent Hargrave
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ = Rumblr
2
+
3
+ Rumblr is a Ruby client for http://www.tumblr.com XML API. It currently only provides read functionality; you can read User, Tumblelog and Post data.
4
+
5
+ = Overview
6
+
7
+ Rumblr maps the Tumblr API 'authenticate' and 'read' calls. User, Tumblelog and Post models have attributes provided by the API, as well as some convenience methods for common tasks.
8
+
9
+ Please read Tumblr's official documentation (http://tumblr.com/api/) to learn more the API.
10
+
11
+
12
+ == Dependencies
13
+
14
+ * Ruby >= 1.8.6 (not tested with previous versions)
15
+ * libxml-ruby >= 0.8.3
16
+
17
+
18
+ == Download and Installation
19
+
20
+ RubyGems[http://rubyforge.org/projects/rubygems/] is the preferred install method.
21
+ To get the latest version, simply type the following instruction into your command prompt:
22
+
23
+ $ sudo gem install jamescallmebrent-rumblr -s http://gems.github.com
24
+
25
+
26
+ == Getting Started
27
+
28
+ In order to use this library you need a valid Tumblr account.
29
+ Go to http://tumblr.com and register for a new account if you don't already have one.
30
+
31
+
32
+ === Sample usage:
33
+
34
+ require 'rumblr'
35
+ include Rumblr
36
+
37
+ user = User.login({:email => 'name@domain.com', :password => 'pass'})
38
+
39
+ user.tumblelogs.each do |log|
40
+ puts log.name # 'the tumblelogger'
41
+ puts log.type # 'public'
42
+ puts log.url # 'http://tumblelogger.tumblr.com/'
43
+ puts
44
+ end
45
+
46
+ tumblelog = user.primary_tumblelog
47
+
48
+ tumblelog.posts.each do |post|
49
+ puts post.type # 'quote'
50
+ puts post.url # 'http://tumblelogger.tumblr.com/post/12345/my-first-tumblr-post'
51
+ end
52
+
53
+
54
+ == Credits
55
+
56
+ Author:: {Brent Hargrave}[http://brenthargrave.info/] <brent.hargrave@gmail.com>
57
+
58
+
59
+ == FeedBack and Bug reports
60
+
61
+ Please email {Brent Hargrave}[mailto:brent.hargrave@gmail.com] with any questions or feedback.
62
+
63
+
64
+ == License
65
+
66
+ Copyright (c) 2009 Brent Hargrave. Rumblr is released under the MIT license.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 0
@@ -0,0 +1,141 @@
1
+ module Rumblr
2
+
3
+ class Client
4
+ include Singleton
5
+
6
+ # The default set of headers for each request.
7
+ DEFAULT_HEADER = {
8
+ 'User-Agent' => 'Rumblr',
9
+ 'Accept' => 'application/xml'
10
+ }
11
+
12
+ def authenticate(email,password)
13
+ raise ArgumentError unless (email && password)
14
+ user_credentials = { :email => email, :password => password }
15
+ uri = URI::HTTP.build({:path => '/api/authenticate'})
16
+ request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
17
+ request.set_form_data(user_credentials)
18
+
19
+ user_attributes = nil
20
+ complete_request(request) do |response_body|
21
+ user_attributes = parse_user_attributes_from(response_body)
22
+ user_attributes.merge!(user_credentials)
23
+ end
24
+ User.new(user_attributes)
25
+ end
26
+
27
+ def read(options={})
28
+ tumblelog, posts = nil, [] # initialize the return targets
29
+
30
+ uri = URI::HTTP.build({:path => '/api/read'})
31
+ request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
32
+ request.set_form_data(options)
33
+
34
+ raise(ArgumentError) unless (options && options[:url] && !options[:url].empty?)
35
+
36
+ request_url_host = URI.parse(options[:url]).host
37
+ complete_request(request,host=request_url_host) do |response_body|
38
+ parser, parser.string = XML::Parser.new, response_body
39
+ doc = parser.parse
40
+ # parse and map posts
41
+ posts = doc.find('//tumblr/posts/post').inject([]) do |array, element|
42
+ post_attrs = cleanup_hash(element.attributes.to_h)
43
+ # inner elements => sublcass-specific attribute hash
44
+ subclass_attrs = element.children.inject({'tags' => []}) do |hash, child|
45
+ hash['tags'] << child.content if (child.name[/tag/])
46
+ hash[child.name] = child.content
47
+ hash
48
+ end
49
+ # merge hashes, clean out cruft
50
+ inner_attrs = cleanup_hash(subclass_attrs)
51
+ inner_attrs.delete(:text)
52
+ inner_attrs.delete(:tag)
53
+ post_attrs.merge!(inner_attrs)
54
+ # turn attributes into proper model
55
+ klass = case post_attrs[:type]
56
+ when 'regular' then RegularPost
57
+ when 'photo' then PhotoPost
58
+ when 'quote' then QuotePost
59
+ when 'link' then LinkPost
60
+ when 'conversation' then ConversationPost
61
+ when 'video' then VideoPost
62
+ when 'audio' then AudioPost
63
+ else raise 'unknown post type'
64
+ end
65
+ post = klass.new(post_attrs)
66
+ array << post
67
+ array
68
+ end
69
+ # parse and map tumblelog
70
+ tumblelog_element = doc.find_first('//tumblr/tumblelog')
71
+ tumblelog_attrs = cleanup_hash(tumblelog_element.attributes.to_h)
72
+ tumblelog_attrs.merge!(:url => options[:url])
73
+ tumblelog = Tumblelog.new(tumblelog_attrs)
74
+ end
75
+ return tumblelog, posts
76
+ end
77
+
78
+
79
+ protected
80
+
81
+ # Starts and completes the given request. Returns or yields the response body.
82
+ def complete_request(request, host = URI.parse(Rumblr.api_url).host)
83
+ http = Net::HTTP.new(host)
84
+ # Set to debug http output.
85
+ # http.set_debug_output $stderr
86
+ response = http.start { |http| http.request(request) }
87
+
88
+ case response
89
+ when Net::HTTPSuccess then yield response.body if block_given?
90
+ when Net::HTTPBadRequest then raise Rumblr::RequestError, parse_error_message(response)
91
+ when Net::HTTPForbidden then raise Rumblr::AuthorizationError, parse_error_message(response)
92
+ when Net::HTTPNotFound then raise Rumblr::MissingResourceError, parse_error_message(response)
93
+ when Net::HTTPMovedPermanently then raise Rumblr::MovedResourceError, parse_error_message(response)
94
+ when Net::HTTPServerError then raise Rumblr::ServerError, connection_error_message
95
+ else raise "Received an unexpected HTTP response: #{response}"
96
+ end
97
+
98
+ response.body
99
+ end
100
+
101
+ # Extracts the error message from the response for the exception.
102
+ def parse_error_message(response)
103
+ response.body
104
+ end
105
+
106
+ def connection_error_message
107
+ "There was a problem connecting to Tumblr"
108
+ end
109
+
110
+
111
+ private
112
+
113
+ def parse_user_attributes_from(response_body)
114
+ parser, parser.string = XML::Parser.new, response_body
115
+ doc = parser.parse
116
+ tumblelogs = doc.find('//tumblr/tumblelog').inject([]) do |array, element|
117
+ tumblelog_attrs = cleanup_hash(element.attributes.to_h)
118
+ array << Tumblelog.new(tumblelog_attrs)
119
+ array
120
+ end
121
+ raw_user_attributes = doc.find('//tumblr/user').first.attributes.to_h
122
+ user_attributes = cleanup_hash(raw_user_attributes)
123
+ user_attributes.merge!(:tumblelogs => tumblelogs)
124
+ end
125
+
126
+ def cleanup_hash(attrs={})
127
+ clean_attrs = attrs.inject({}) do |hash,(key,value)|
128
+ mapped_key = key.gsub(/-/,'_').to_sym
129
+ mapped_value = case value
130
+ when /($1^|$yes^)/ then true
131
+ when /($0^|$no^)/ then false
132
+ else value
133
+ end
134
+ hash[mapped_key] = mapped_value
135
+ hash
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,51 @@
1
+ module Rumblr
2
+
3
+ # for attribute details, see Tumblr's documentation:
4
+ # http://www.tumblr.com/api
5
+ class Post < Resource
6
+ attr_reader :id, :url, :type, :unix_timestamp, :date_gmt, :date, :tags, :private
7
+
8
+ def initialize(attrs={})
9
+ @private = false
10
+ super
11
+ end
12
+
13
+ def private?
14
+ @private
15
+ end
16
+
17
+ def public?
18
+ !self.private?
19
+ end
20
+
21
+ end
22
+
23
+ class RegularPost < Post
24
+ attr_reader :title, :body
25
+ end
26
+
27
+ class PhotoPost < Post
28
+ attr_reader :source, :data, :caption, :click_through_url
29
+ end
30
+
31
+ class QuotePost < Post
32
+ attr_reader :quote, :source
33
+ end
34
+
35
+ class LinkPost < Post
36
+ attr_reader :name, :url, :description
37
+ end
38
+
39
+ class ConversationPost < Post
40
+ attr_reader :title, :conversation
41
+ end
42
+
43
+ class VideoPost < Post
44
+ attr_reader :embed, :data, :title, :caption
45
+ end
46
+
47
+ class AudioPost < Post
48
+ attr_reader :data, :caption
49
+ end
50
+
51
+ end
@@ -0,0 +1,13 @@
1
+ module Rumblr
2
+
3
+ class Resource
4
+
5
+ def initialize(attrs={})
6
+ attrs.each do |key,value|
7
+ self.instance_variable_set(:"@#{key.to_s}", value)
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,24 @@
1
+ module Rumblr
2
+
3
+ class Tumblelog < Resource
4
+ attr_reader :name, :timezone, :cname, :title, :url, :avatar_url, :is_primary,
5
+ :type, :private_id
6
+
7
+ def posts
8
+ return [] unless self.url
9
+ log, posts = Client.instance.read(:url => self.url)
10
+ return posts
11
+ end
12
+
13
+ class << self
14
+
15
+ def find_by_url(url)
16
+ log, posts = Client.instance.read(:url => url)
17
+ return log
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,23 @@
1
+ module Rumblr
2
+
3
+ class User < Resource
4
+ attr_reader :email, :password, :can_upload_video, :can_upload_aiff, :vimeo_login_url, :can_upload_audio
5
+
6
+ def tumblelogs
7
+ instance_variable_get(:@tumblelogs) || []
8
+ end
9
+
10
+ def primary_tumblelog
11
+ self.tumblelogs.find { |log| log.is_primary }
12
+ end
13
+
14
+ class << self
15
+ def login(attrs={})
16
+ email, password = attrs[:email], attrs[:password]
17
+ Client.instance.authenticate(email,password)
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
data/lib/rumblr.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Rumblr
2
+
3
+ class MissingResourceError < Exception; end
4
+ class MovedResourceError < Exception; end
5
+ class AuthorizationError < Exception; end
6
+ class RequestError < Exception; end
7
+ class ServerError < Exception; end
8
+
9
+ class << self
10
+ attr_accessor :api_url
11
+ end
12
+ end
13
+
14
+ Rumblr.api_url = "http://www.tumblr.com"
15
+
16
+ require 'rubygems'
17
+ require 'singleton'
18
+ require 'net/http'
19
+ require 'uri'
20
+ gem 'libxml-ruby', '>= 0.8.3'
21
+ require 'xml'
22
+ require 'pp'
23
+
24
+ require 'rumblr/client'
25
+ require 'rumblr/resource'
26
+ require 'rumblr/tumblelog'
27
+ require 'rumblr/user'
28
+ require 'rumblr/post'
@@ -0,0 +1,111 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Client do
6
+
7
+ it 'should not be able to be instantiated externally' do
8
+ lambda { Client.new }.should raise_error(NoMethodError)
9
+ end
10
+
11
+ it 'should be able to instantiate itself' do
12
+ lambda { Client.instance }.should_not raise_error
13
+ end
14
+
15
+ end
16
+
17
+ describe Client, "authentication" do
18
+
19
+ before(:each) { mock_successful(:authenticate) }
20
+
21
+ it 'should raise an ArgumentError without email' do
22
+ lambda do
23
+ @client.authenticate('email', nil)
24
+ end.should raise_error(ArgumentError)
25
+ end
26
+
27
+ it 'should raise an ArgumentError without password' do
28
+ lambda do
29
+ @client.authenticate(nil,'password')
30
+ end.should raise_error(ArgumentError)
31
+ end
32
+
33
+ it 'should return a User if successful' do
34
+ result = @client.authenticate('foo@foo.com','password')
35
+ result.should be_an_instance_of(User)
36
+ end
37
+
38
+ it "should include user's existing tumblelogs" do
39
+ user = @client.authenticate('foo@foo.com','password')
40
+ user.tumblelogs.size.should == 2
41
+ end
42
+
43
+ end
44
+
45
+ describe Client, "reading from a public tumblelog" do
46
+
47
+ it 'without a URL should raise an error' do
48
+ mock_successful(:anonymous_read)
49
+ lambda do
50
+ @client.read
51
+ end.should raise_error(ArgumentError)
52
+ end
53
+
54
+ it 'with an empty URL should raise an error' do
55
+ mock_successful(:anonymous_read)
56
+ lambda do
57
+ @client.read(:url => '')
58
+ end.should raise_error(ArgumentError)
59
+ end
60
+
61
+ describe 'without credentials' do
62
+
63
+ before(:each) do
64
+ mock_successful(:anonymous_read)
65
+ @tumblelog, posts = @client.read(:url => 'http://dummylog.tumblr.com/')
66
+ end
67
+
68
+ it 'should yield only posts' do
69
+ @tumblelog.posts.all? {|post| post.kind_of?(Post)}.should be_true
70
+ end
71
+
72
+ it 'should not include all posts, assuming some are private' do
73
+ @tumblelog.posts.size.should == 7
74
+ end
75
+
76
+ it 'should only include public posts' do
77
+ @tumblelog.posts.all? {|post| post.public? }.should be_true
78
+ end
79
+
80
+ it 'should not include any private posts' do
81
+ @tumblelog.posts.any? {|post| post.private? }.should be_false
82
+ end
83
+
84
+ end
85
+
86
+ describe 'with valid credentials' do
87
+
88
+ before(:each) do
89
+ mock_successful(:authenticated_read)
90
+ @tumblelog, posts = @client.read( :url => 'http://dummylog.tumblr.com/',
91
+ :email => 'valid',
92
+ :password => 'valid' )
93
+ end
94
+
95
+ it 'should include all tumblelog posts' do
96
+ @tumblelog.posts.size.should == 14
97
+ end
98
+
99
+ it 'should include all public posts' do
100
+ @tumblelog.posts.find_all {|p| p.public? }.size.should == 7
101
+ end
102
+
103
+ it 'should include private posts' do
104
+ @tumblelog.posts.find_all {|p| p.public? }.size.should == 7
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,25 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Post, 'instances' do
6
+
7
+ it 'should have attributes shared by every Post' do
8
+ Post.new.should respond_to(:id, :url, :type, :unix_timestamp, :date_gmt, :date, :tags, :private)
9
+ end
10
+
11
+ it 'private attribute should default to false' do
12
+ Post.new.private.should be_false
13
+ end
14
+
15
+ it 'should provide it private status' do
16
+ Post.new.should respond_to(:private?)
17
+ end
18
+
19
+ it 'should provide it public status (inverse of private status)' do
20
+ Post.new.should respond_to(:public?)
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,39 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Tumblelog, 'instances' do
6
+
7
+ it 'should have the attributes of a Tumblelog' do
8
+ Tumblelog.new.should respond_to( :name, :timezone, :cname, :title, :url,
9
+ :avatar_url, :is_primary, :type, :private_id)
10
+ end
11
+
12
+ it "' posts should initialize empty" do
13
+ Tumblelog.new.posts.should be_a_kind_of(Array)
14
+ end
15
+
16
+ end
17
+
18
+ describe Tumblelog, 'finder' do
19
+
20
+ describe 'provided a valid URL' do
21
+
22
+ it 'should successfully retrieve a tumblelog' do
23
+ mock_successful(:anonymous_read)
24
+ log = Tumblelog.find_by_url('valid_url')
25
+ log.should be_an_instance_of(Tumblelog)
26
+ end
27
+
28
+ it 'should retrieve a tumblelog with posts' do
29
+ mock_successful(:anonymous_read)
30
+ log = Tumblelog.find_by_url('valid_url')
31
+ log.posts.first.should be_a_kind_of(Post)
32
+ log.posts.first.type.should_not be_nil
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,69 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe User, 'initializing' do
6
+
7
+ it 'should have the attributes of a User' do
8
+ User.new.should respond_to( :email,
9
+ :password,
10
+ :can_upload_video,
11
+ :can_upload_aiff,
12
+ :vimeo_login_url,
13
+ :can_upload_audio )
14
+ end
15
+
16
+ it 'tumblelogs should initialize empty' do
17
+ User.new.tumblelogs.should be_a_kind_of(Array)
18
+ end
19
+
20
+ end
21
+
22
+ describe User, 'logging in' do
23
+
24
+ before(:each) do
25
+ mock_successful(:authenticate)
26
+ end
27
+
28
+ it 'should login with email and password' do
29
+ user = User.login(:email => 'valid_email', :password => 'valid_password')
30
+ user.should be_an_instance_of(User)
31
+ end
32
+
33
+ it 'should not initialize without email' do
34
+ lambda do
35
+ User.login(:email => nil, :password => 'valid_password')
36
+ end.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it 'should not initialize without password' do
40
+ lambda do
41
+ User.login(:email => 'valid_email', :password => nil)
42
+ end.should raise_error(ArgumentError)
43
+ end
44
+
45
+ end
46
+
47
+ describe User, ', once logged in,' do
48
+
49
+ before(:each) do
50
+ mock_successful(:authenticate)
51
+ @user = User.login(:email => 'valid_email', :password => 'valid_password')
52
+ end
53
+
54
+ it 'should provide one or more tumblelogs' do
55
+ @user.tumblelogs.size.should == 2
56
+ end
57
+
58
+ it 'should provide *only* tumblelogs' do
59
+ @user.tumblelogs.all? { |obj| obj.should be_an_instance_of(Tumblelog) }
60
+ end
61
+
62
+ it 'should provide a primary tumblelog' do
63
+ primary = @user.primary_tumblelog
64
+ primary.is_primary.should be_true
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,105 @@
1
+ $: << File.join(File.dirname(__FILE__), "/../lib" )
2
+
3
+ require 'spec'
4
+ require 'rumblr'
5
+
6
+ def mock_successful(request)
7
+ responses_to = {
8
+ :authenticate => successful_authenticate_xml,
9
+ :anonymous_read => successful_anonymous_read_xml,
10
+ :authenticated_read => successful_authenticated_read_xml,
11
+ :authenticated_write => successful_authenticated_write_xml
12
+ }
13
+
14
+ @client = Rumblr::Client.instance
15
+ # yes, this is cheating, but for now just concerned that xml is parsed right
16
+ @client.stub!(:complete_request).and_yield(responses_to[request])
17
+ end
18
+
19
+ def successful_authenticate_xml
20
+ response = <<-EOF
21
+ <?xml version="1.0" encoding="UTF-8"?>
22
+ <tumblr version="1.0">
23
+ <user can-upload-audio="1" can-upload-aiff="1" can-upload-video="0" vimeo-login-url="http://www.vimeo.com/services/foo"/>
24
+ <tumblelog title="" name="foo" url="http://foo.com/" type="public" avatar-url="http://assets.tumblr.com/images/default_avatar_foo.gif" is-primary="yes"/>
25
+ <tumblelog title="bar" private-id="000000" type="private"/>
26
+ </tumblr>
27
+ EOF
28
+ response.strip!
29
+ end
30
+
31
+ def successful_anonymous_read_xml
32
+ response = <<-EOF
33
+ <?xml version="1.0" encoding="UTF-8"?>
34
+ <tumblr version="1.0">
35
+ <tumblelog name="dummylog" timezone="US/Eastern" title="dummy tumblelog title">dummylog description</tumblelog>
36
+ <posts start="0" total="7">
37
+ <post id="78846368" url="http://dummylog.tumblr.com/post/78846368" type="video" date-gmt="2009-02-16 19:11:45 GMT" date="Mon, 16 Feb 2009 14:11:45" unix-timestamp="1234811505">
38
+ <video-caption>public video post caption</video-caption>
39
+ <video-source>http://www.youtube.com/watch?v=rPaWZOM1LnY</video-source>
40
+ <video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player>
41
+ <tag>sale</tag>
42
+ <tag>music</tag>
43
+ </post>
44
+ <post id="78846080" url="http://dummylog.tumblr.com/post/78846080" type="audio" date-gmt="2009-02-16 19:10:20 GMT" date="Mon, 16 Feb 2009 14:10:20" unix-timestamp="1234811420" audio-plays="0">
45
+ <audio-caption>public audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846080/TofwJxqCAk12g1e0ClxHx7gh&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player>
46
+ <tag>sale</tag>
47
+ </post>
48
+ <post id="78844911" url="http://dummylog.tumblr.com/post/78844911" type="conversation" date-gmt="2009-02-16 19:04:48 GMT" date="Mon, 16 Feb 2009 14:04:48" unix-timestamp="1234811088">
49
+ <conversation-title>public chat post title</conversation-title>
50
+ <conversation-text>me: public&#13;
51
+ you: chat&#13;
52
+ me: post&#13;
53
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">public&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">public&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line>
54
+ <tag>sale</tag>
55
+ </post>
56
+ <post id="78844351" url="http://dummylog.tumblr.com/post/78844351" type="link" date-gmt="2009-02-16 19:02:00 GMT" date="Mon, 16 Feb 2009 14:02:00" unix-timestamp="1234810920">
57
+ <link-text>public link post name</link-text><link-url>http://www.google.com</link-url>
58
+ <link-description>public link post description</link-description>
59
+ <tag>sale</tag>
60
+ </post>
61
+ <post id="78844076" url="http://dummylog.tumblr.com/post/78844076" type="quote" date-gmt="2009-02-16 19:01:06 GMT" date="Mon, 16 Feb 2009 14:01:06" unix-timestamp="1234810866">
62
+ <quote-text>public quote post content</quote-text>
63
+ <quote-source>public quote post source</quote-source>
64
+ <tag>sale</tag>
65
+ </post>
66
+ <post id="78841604" url="http://dummylog.tumblr.com/post/78841604" type="regular" date-gmt="2009-02-16 18:50:00 GMT" date="Mon, 16 Feb 2009 13:50:00" unix-timestamp="1234810200">
67
+ <regular-title>public text post title</regular-title>
68
+ <regular-body>public text post body</regular-body>
69
+ <tag>sale</tag>
70
+ </post>
71
+ <post id="78841444" url="http://dummylog.tumblr.com/post/78841444" type="photo" date-gmt="2009-02-16 18:49:00 GMT" date="Mon, 16 Feb 2009 13:49:00" unix-timestamp="1234810140">
72
+ <photo-caption>public photo post</photo-caption>
73
+ <photo-url max-width="500">http://21.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_500.jpg</photo-url>
74
+ <photo-url max-width="400">http://1.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_400.jpg</photo-url>
75
+ <photo-url max-width="250">http://22.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_250.jpg</photo-url>
76
+ <photo-url max-width="100">http://19.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_100.jpg</photo-url>
77
+ <photo-url max-width="75">http://2.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_75sq.jpg</photo-url>
78
+ <tag>sale</tag>
79
+ </post>
80
+ </posts>
81
+ </tumblr>
82
+ EOF
83
+ response.strip!
84
+ end
85
+
86
+ def successful_authenticated_read_xml
87
+ response = <<-EOF
88
+ <?xml version="1.0" encoding="UTF-8"?>
89
+ <tumblr version="1.0"><tumblelog name="dummylog" timezone="US/Eastern" title="dummy tumblelog title">dummy tumblelog description</tumblelog><posts start="0" total="7"><post id="78846474" url="http://dummylog.tumblr.com/post/78846474" type="video" date-gmt="2009-02-16 19:12:00 GMT" date="Mon, 16 Feb 2009 14:12:00" unix-timestamp="1234811520" private="true"><video-caption>private video post caption</video-caption><video-source>http://www.youtube.com/watch?v=rPaWZOM1LnY</video-source><video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player><tag>sale</tag><tag>tag2</tag><tag>music</tag></post><post id="78846368" url="http://dummylog.tumblr.com/post/78846368" type="video" date-gmt="2009-02-16 19:11:00 GMT" date="Mon, 16 Feb 2009 14:11:00" unix-timestamp="1234811460"><video-caption>public video post caption</video-caption><video-source>hilhttp://www.youtube.com/watch?v=rPaWZOM1LnY</video-source><video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player><tag>hilarious</tag></post><post id="78846150" url="http://dummylog.tumblr.com/post/78846150" type="audio" date-gmt="2009-02-16 19:10:43 GMT" date="Mon, 16 Feb 2009 14:10:43" unix-timestamp="1234811443" private="true" audio-plays="2"><audio-caption>private audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846150/TofwJxqCAk12gje4UYRllUwM&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player><tag>sale</tag></post><post id="78846080" url="http://dummylog.tumblr.com/post/78846080" type="audio" date-gmt="2009-02-16 19:10:00 GMT" date="Mon, 16 Feb 2009 14:10:00" unix-timestamp="1234811400" audio-plays="0"><audio-caption>public audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846080/TofwJxqCAk12g1e0ClxHx7gh&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player><tag>sale</tag><tag>music</tag></post><post id="78844968" url="http://dummylog.tumblr.com/post/78844968" type="conversation" date-gmt="2009-02-16 19:05:08 GMT" date="Mon, 16 Feb 2009 14:05:08" unix-timestamp="1234811108" private="true"><conversation-title>private chat post title</conversation-title><conversation-text>me: private&#13;
90
+ you: chat&#13;
91
+ me: post&#13;
92
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">private&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">private&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line><tag>sale</tag></post><post id="78844911" url="http://dummylog.tumblr.com/post/78844911" type="conversation" date-gmt="2009-02-16 19:04:48 GMT" date="Mon, 16 Feb 2009 14:04:48" unix-timestamp="1234811088"><conversation-title>public chat post title</conversation-title><conversation-text>me: public&#13;
93
+ you: chat&#13;
94
+ me: post&#13;
95
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">public&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">public&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line><tag>sale</tag></post><post id="78844625" url="http://dummylog.tumblr.com/post/78844625" type="link" date-gmt="2009-02-16 19:03:00 GMT" date="Mon, 16 Feb 2009 14:03:00" unix-timestamp="1234810980" private="true"><link-text>private link post name</link-text><link-url>http://www.google.com</link-url><link-description>private link post description</link-description><tag>sale</tag></post><post id="78844351" url="http://dummylog.tumblr.com/post/78844351" type="link" date-gmt="2009-02-16 19:02:00 GMT" date="Mon, 16 Feb 2009 14:02:00" unix-timestamp="1234810920"><link-text>public link post name</link-text><link-url>http://www.google.com</link-url><link-description>public link post description</link-description><tag>sale</tag></post><post id="78844076" url="http://dummylog.tumblr.com/post/78844076" type="quote" date-gmt="2009-02-16 19:01:06 GMT" date="Mon, 16 Feb 2009 14:01:06" unix-timestamp="1234810866"><quote-text>public quote post content</quote-text><quote-source>public quote post source</quote-source><tag>sale</tag></post><post id="78844136" url="http://dummylog.tumblr.com/post/78844136" type="quote" date-gmt="2009-02-16 19:01:00 GMT" date="Mon, 16 Feb 2009 14:01:00" unix-timestamp="1234810860" private="true"><quote-text>private quote post content</quote-text><quote-source>private quote post content</quote-source><tag>sale</tag></post><post id="78843778" url="http://dummylog.tumblr.com/post/78843778" type="photo" date-gmt="2009-02-16 18:59:40 GMT" date="Mon, 16 Feb 2009 13:59:40" unix-timestamp="1234810780" private="true"><photo-caption>private photo post</photo-caption><photo-url max-width="500">http://7.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_500.jpg</photo-url><photo-url max-width="400">http://6.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_400.jpg</photo-url><photo-url max-width="250">http://11.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_250.jpg</photo-url><photo-url max-width="100">http://11.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_100.jpg</photo-url><photo-url max-width="75">http://22.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_75sq.jpg</photo-url><tag>sale</tag></post><post id="78843501" url="http://dummylog.tumblr.com/post/78843501" type="regular" date-gmt="2009-02-16 18:58:00 GMT" date="Mon, 16 Feb 2009 13:58:00" unix-timestamp="1234810680" private="true"><regular-title>private text post title</regular-title><regular-body>private text post body</regular-body><tag>sale</tag></post><post id="78841604" url="http://dummylog.tumblr.com/post/78841604" type="regular" date-gmt="2009-02-16 18:50:00 GMT" date="Mon, 16 Feb 2009 13:50:00" unix-timestamp="1234810200"><regular-title>public text post title</regular-title><regular-body>public text post body</regular-body><tag>sale</tag></post><post id="78841444" url="http://dummylog.tumblr.com/post/78841444" type="photo" date-gmt="2009-02-16 18:49:00 GMT" date="Mon, 16 Feb 2009 13:49:00" unix-timestamp="1234810140"><photo-caption>public photo post</photo-caption><photo-url max-width="500">http://21.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_500.jpg</photo-url><photo-url max-width="400">http://1.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_400.jpg</photo-url><photo-url max-width="250">http://22.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_250.jpg</photo-url><photo-url max-width="100">http://19.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_100.jpg</photo-url><photo-url max-width="75">http://2.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_75sq.jpg</photo-url><tag>sale</tag></post></posts></tumblr>
96
+ EOF
97
+ response.strip!
98
+ end
99
+
100
+ def successful_authenticated_write_xml
101
+ response = <<-EOF
102
+ <?xml version="1.0" encoding="UTF-8"?>
103
+ EOF
104
+ response.strip!
105
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jamescallmebrent-rumblr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brent Hargrave
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-17 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: libxml-ruby
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.8.3
24
+ version:
25
+ description: Ruby client for the Tumblr API
26
+ email: brent.hargrave@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - LICENSE.rdoc
35
+ - README.rdoc
36
+ - VERSION.yml
37
+ - lib/rumblr
38
+ - lib/rumblr/client.rb
39
+ - lib/rumblr/post.rb
40
+ - lib/rumblr/resource.rb
41
+ - lib/rumblr/tumblelog.rb
42
+ - lib/rumblr/user.rb
43
+ - lib/rumblr.rb
44
+ - spec/rumblr
45
+ - spec/rumblr/client_spec.rb
46
+ - spec/rumblr/post_spec.rb
47
+ - spec/rumblr/tumblelog_spec.rb
48
+ - spec/rumblr/user_spec.rb
49
+ - spec/spec_helper.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/jamescallmebrent/rumblr
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --inline-source
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.2.0
74
+ signing_key:
75
+ specification_version: 2
76
+ summary: Ruby client for the Tumblr API
77
+ test_files: []
78
+