hexorx-rumblr 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE.rdoc +24 -0
- data/README.rdoc +59 -0
- data/Rakefile +48 -0
- data/VERSION.yml +4 -0
- data/lib/rumblr/client.rb +146 -0
- data/lib/rumblr/post.rb +102 -0
- data/lib/rumblr/resource.rb +13 -0
- data/lib/rumblr/tumblelog.rb +30 -0
- data/lib/rumblr/user.rb +27 -0
- data/lib/rumblr.rb +28 -0
- data/rumblr.gemspec +60 -0
- data/spec/rumblr/client_spec.rb +145 -0
- data/spec/rumblr/post_spec.rb +29 -0
- data/spec/rumblr/tumblelog_spec.rb +64 -0
- data/spec/rumblr/user_spec.rb +69 -0
- data/spec/spec_helper.rb +106 -0
- metadata +85 -0
data/.gitignore
ADDED
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,59 @@
|
|
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 the 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 about 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
|
+
post = RegularPost.new(:title => "Post Title", :body => "Just a regular post!")
|
54
|
+
Client.instance.write(post, {:email => 'name@domain.com', :password => 'pass'})
|
55
|
+
|
56
|
+
|
57
|
+
== License
|
58
|
+
|
59
|
+
Copyright (c) 2009 Brent Hargrave. Rumblr is released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |s|
|
6
|
+
summary = %Q{Ruby client for the Tumblr API}
|
7
|
+
|
8
|
+
s.name = "rumblr"
|
9
|
+
s.summary = summary
|
10
|
+
s.email = "brent.hargrave@gmail.com"
|
11
|
+
s.homepage = "http://github.com/jamescallmebrent/rumblr"
|
12
|
+
s.description = summary
|
13
|
+
s.authors = ["Brent Hargrave", "Benny Wong"]
|
14
|
+
s.add_dependency('libxml-ruby', '>= 0.8.3')
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/rdoctask'
|
21
|
+
Rake::RDocTask.new do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'rumblr'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README*')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'spec/rake/spectask'
|
30
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
31
|
+
t.libs << 'lib' << 'spec'
|
32
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
33
|
+
end
|
34
|
+
|
35
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
36
|
+
t.libs << 'lib' << 'spec'
|
37
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
38
|
+
t.rcov = true
|
39
|
+
end
|
40
|
+
|
41
|
+
begin
|
42
|
+
require 'cucumber/rake/task'
|
43
|
+
Cucumber::Rake::Task.new(:features)
|
44
|
+
rescue LoadError
|
45
|
+
puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
46
|
+
end
|
47
|
+
|
48
|
+
task :default => :spec
|
data/VERSION.yml
ADDED
@@ -0,0 +1,146 @@
|
|
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 = User.new(user_attributes)
|
25
|
+
user.tumblelogs.each{ |tumblelog| tumblelog.user = user }
|
26
|
+
user
|
27
|
+
end
|
28
|
+
|
29
|
+
def read(options={})
|
30
|
+
tumblelog, posts = nil, [] # initialize the return targets
|
31
|
+
|
32
|
+
uri = URI::HTTP.build({:path => '/api/read'})
|
33
|
+
request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
34
|
+
request.set_form_data(options)
|
35
|
+
|
36
|
+
raise(ArgumentError) unless (options && options[:url] && !options[:url].empty?)
|
37
|
+
|
38
|
+
request_url_host = URI.parse(options[:url]).host
|
39
|
+
complete_request(request,host=request_url_host) do |response_body|
|
40
|
+
parser = XML::Parser.string(response_body)
|
41
|
+
doc = parser.parse
|
42
|
+
# parse and map tumblelog
|
43
|
+
tumblelog_element = doc.find_first('//tumblr/tumblelog')
|
44
|
+
tumblelog_attrs = cleanup_hash(tumblelog_element.attributes.to_h)
|
45
|
+
tumblelog_attrs.merge!(:url => options[:url])
|
46
|
+
tumblelog = Tumblelog.new(tumblelog_attrs)
|
47
|
+
# parse and map posts
|
48
|
+
posts = doc.find('//tumblr/posts/post').inject([]) do |array, element|
|
49
|
+
post_attrs = cleanup_hash(element.attributes.to_h)
|
50
|
+
# inner elements => sublcass-specific attribute hash
|
51
|
+
subclass_attrs = element.children.inject({'tags' => []}) do |hash, child|
|
52
|
+
hash['tags'] << child.content if (child.name[/tag/])
|
53
|
+
hash[child.name] = child.content
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
# merge hashes, clean out cruft
|
57
|
+
inner_attrs = cleanup_hash(subclass_attrs)
|
58
|
+
inner_attrs.delete(:text)
|
59
|
+
inner_attrs.delete(:tag)
|
60
|
+
post_attrs.merge!(inner_attrs)
|
61
|
+
# turn attributes into proper model
|
62
|
+
klass = Rumblr.const_get(Post::TYPES[post_attrs[:type]])
|
63
|
+
raise 'unknown post type' unless klass
|
64
|
+
post = klass.new(post_attrs)
|
65
|
+
post.tumblelog = tumblelog
|
66
|
+
array << post
|
67
|
+
array
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return tumblelog, posts
|
71
|
+
end
|
72
|
+
|
73
|
+
def write(post, creds)
|
74
|
+
raise(ArgumentError) unless post && post.is_a?(Post)
|
75
|
+
raise(ArgumentError) unless creds
|
76
|
+
uri = URI::HTTP.build(:path => "/api/write")
|
77
|
+
request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
78
|
+
request.set_form_data(creds.merge(:type => Post::TYPES.invert[post.class]).merge(post.attribute_hash))
|
79
|
+
request_url_host = URI.parse(uri.request_uri).host
|
80
|
+
complete_request(request)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
# Starts and completes the given request. Returns or yields the response body.
|
87
|
+
def complete_request(request, host = URI.parse(Rumblr.api_url).host)
|
88
|
+
http = Net::HTTP.new(host)
|
89
|
+
# Set to debug http output.
|
90
|
+
# http.set_debug_output $stderr
|
91
|
+
response = http.start { |http| http.request(request) }
|
92
|
+
|
93
|
+
case response
|
94
|
+
when Net::HTTPSuccess then yield response.body if block_given?
|
95
|
+
when Net::HTTPBadRequest then raise Rumblr::RequestError, parse_error_message(response)
|
96
|
+
when Net::HTTPForbidden then raise Rumblr::AuthorizationError, parse_error_message(response)
|
97
|
+
when Net::HTTPNotFound then raise Rumblr::MissingResourceError, parse_error_message(response)
|
98
|
+
when Net::HTTPMovedPermanently then raise Rumblr::MovedResourceError, parse_error_message(response)
|
99
|
+
when Net::HTTPServerError then raise Rumblr::ServerError, connection_error_message
|
100
|
+
else raise "Received an unexpected HTTP response: #{response}"
|
101
|
+
end
|
102
|
+
|
103
|
+
response.body
|
104
|
+
end
|
105
|
+
|
106
|
+
# Extracts the error message from the response for the exception.
|
107
|
+
def parse_error_message(response)
|
108
|
+
response.body
|
109
|
+
end
|
110
|
+
|
111
|
+
def connection_error_message
|
112
|
+
"There was a problem connecting to Tumblr"
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def parse_user_attributes_from(response_body)
|
119
|
+
parser = XML::Parser.string response_body
|
120
|
+
doc = parser.parse
|
121
|
+
tumblelogs = doc.find('//tumblr/tumblelog').inject([]) do |array, element|
|
122
|
+
tumblelog_attrs = cleanup_hash(element.attributes.to_h)
|
123
|
+
array << Tumblelog.new(tumblelog_attrs)
|
124
|
+
array
|
125
|
+
end
|
126
|
+
raw_user_attributes = doc.find('//tumblr/user').first.attributes.to_h
|
127
|
+
user_attributes = cleanup_hash(raw_user_attributes)
|
128
|
+
user_attributes.merge!(:tumblelogs => tumblelogs)
|
129
|
+
end
|
130
|
+
|
131
|
+
def cleanup_hash(attrs={})
|
132
|
+
clean_attrs = attrs.inject({}) do |hash,(key,value)|
|
133
|
+
mapped_key = key.gsub(/-/,'_').to_sym
|
134
|
+
mapped_value = case value
|
135
|
+
when /($1^|$yes^)/ then true
|
136
|
+
when /($0^|$no^)/ then false
|
137
|
+
else value
|
138
|
+
end
|
139
|
+
hash[mapped_key] = mapped_value
|
140
|
+
hash
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
data/lib/rumblr/post.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module Rumblr
|
2
|
+
|
3
|
+
# for attribute details, see Tumblr's documentation:
|
4
|
+
# http://www.tumblr.com/api
|
5
|
+
class Post < Resource
|
6
|
+
|
7
|
+
TYPES = {
|
8
|
+
'regular' => "RegularPost",
|
9
|
+
'photo' => "PhotoPost",
|
10
|
+
'quote' => "QuotePost",
|
11
|
+
'link' => "LinkPost",
|
12
|
+
'conversation' => "ConversationPost",
|
13
|
+
'video' => "VideoPost",
|
14
|
+
'audio' => "AudioPost"
|
15
|
+
}
|
16
|
+
|
17
|
+
attr_reader :id, :url, :type, :unix_timestamp, :date_gmt, :date, :tags, :private
|
18
|
+
attr_accessor :tumblelog
|
19
|
+
|
20
|
+
def initialize(attrs={})
|
21
|
+
@private = false
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def private?
|
26
|
+
@private
|
27
|
+
end
|
28
|
+
|
29
|
+
def public?
|
30
|
+
!self.private?
|
31
|
+
end
|
32
|
+
|
33
|
+
def attribute_hash
|
34
|
+
{:date => date}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class RegularPost < Post
|
40
|
+
attr_accessor :title, :body
|
41
|
+
|
42
|
+
def attribute_hash
|
43
|
+
super.merge(:title => title, :body => body)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
class PhotoPost < Post
|
49
|
+
attr_accessor :source, :data, :caption, :click_through_url
|
50
|
+
|
51
|
+
def attribute_hash
|
52
|
+
super.merge(:source => source, :data => data, :caption => caption, :click_through_url => click_through_url)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class QuotePost < Post
|
58
|
+
attr_accessor :quote, :source
|
59
|
+
|
60
|
+
def attribute_hash
|
61
|
+
super.merge(:quote => quote, :source => source)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class LinkPost < Post
|
67
|
+
attr_accessor :name, :url, :description
|
68
|
+
|
69
|
+
def attribute_hash
|
70
|
+
super.merge(:name => name, :url => url, :description => description)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class ConversationPost < Post
|
76
|
+
attr_accessor :title, :conversation
|
77
|
+
|
78
|
+
def attribute_hash
|
79
|
+
super.merge(:title => title, :conversation => conversation)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
class VideoPost < Post
|
85
|
+
attr_accessor :embed, :data, :title, :caption
|
86
|
+
|
87
|
+
def attribute_hash
|
88
|
+
super.merge(:embed => embed, :data => data, :title => title, :caption => caption)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
class AudioPost < Post
|
94
|
+
attr_accessor :data, :caption
|
95
|
+
|
96
|
+
def attribute_hash
|
97
|
+
super.merge(:data => data, :caption => caption)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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
|
+
attr_accessor :user
|
7
|
+
|
8
|
+
def posts(options={})
|
9
|
+
return [] unless self.url
|
10
|
+
options.reverse_merge!(:url => self.url)
|
11
|
+
log, posts = Client.instance.read(options)
|
12
|
+
return posts
|
13
|
+
end
|
14
|
+
|
15
|
+
def primary?
|
16
|
+
is_primary == "yes"
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
|
21
|
+
def find_by_url(url)
|
22
|
+
log, posts = Client.instance.read(:url => url)
|
23
|
+
return log
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/rumblr/user.rb
ADDED
@@ -0,0 +1,27 @@
|
|
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.primary? }
|
12
|
+
end
|
13
|
+
|
14
|
+
def auth
|
15
|
+
{:email => self.email, :password => self.password}
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def login(attrs={})
|
20
|
+
email, password = attrs[:email], attrs[:password]
|
21
|
+
Client.instance.authenticate(email,password)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
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'
|
data/rumblr.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{rumblr}
|
5
|
+
s.version = "0.0.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Brent Hargrave", "Benny Wong"]
|
9
|
+
s.date = %q{2009-05-30}
|
10
|
+
s.description = %q{Ruby client for the Tumblr API}
|
11
|
+
s.email = %q{brent.hargrave@gmail.com}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"LICENSE.rdoc",
|
14
|
+
"README.rdoc"
|
15
|
+
]
|
16
|
+
s.files = [
|
17
|
+
".gitignore",
|
18
|
+
"LICENSE.rdoc",
|
19
|
+
"README.rdoc",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION.yml",
|
22
|
+
"lib/rumblr.rb",
|
23
|
+
"lib/rumblr/client.rb",
|
24
|
+
"lib/rumblr/post.rb",
|
25
|
+
"lib/rumblr/resource.rb",
|
26
|
+
"lib/rumblr/tumblelog.rb",
|
27
|
+
"lib/rumblr/user.rb",
|
28
|
+
"rumblr.gemspec",
|
29
|
+
"spec/rumblr/client_spec.rb",
|
30
|
+
"spec/rumblr/post_spec.rb",
|
31
|
+
"spec/rumblr/tumblelog_spec.rb",
|
32
|
+
"spec/rumblr/user_spec.rb",
|
33
|
+
"spec/spec_helper.rb"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/jamescallmebrent/rumblr}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.3}
|
39
|
+
s.summary = %q{Ruby client for the Tumblr API}
|
40
|
+
s.test_files = [
|
41
|
+
"spec/rumblr/client_spec.rb",
|
42
|
+
"spec/rumblr/post_spec.rb",
|
43
|
+
"spec/rumblr/tumblelog_spec.rb",
|
44
|
+
"spec/rumblr/user_spec.rb",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_runtime_dependency(%q<libxml-ruby>, [">= 0.8.3"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0.8.3"])
|
56
|
+
end
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0.8.3"])
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,145 @@
|
|
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
|
+
describe Client, "writing to a public tumblelog" do
|
112
|
+
|
113
|
+
before(:each) do
|
114
|
+
mock_successful(:authenticated_read)
|
115
|
+
@tumblelog, posts = @client.read( :url => 'http://dummylog.tumblr.com/',
|
116
|
+
:email => 'valid',
|
117
|
+
:password => 'valid' )
|
118
|
+
mock_successful(:authenticated_write)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should raise an ArgumentError without post' do
|
122
|
+
lambda do
|
123
|
+
@client.write(nil, {:email => 'valid', :password => 'valid'})
|
124
|
+
end.should raise_error(ArgumentError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should raise an ArgumentError if post is incorrect class' do
|
128
|
+
lambda do
|
129
|
+
@client.write("", {:email => 'valid', :password => 'valid'})
|
130
|
+
end.should raise_error(ArgumentError)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should raise an ArgumentError without creds' do
|
134
|
+
lambda do
|
135
|
+
@client.write(Rumblr::Post.new, nil)
|
136
|
+
end.should raise_error(ArgumentError)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should return an id' do
|
140
|
+
@client.write(Rumblr::Post.new, {:email => 'valid', :password => 'valid'}).should == "10001"
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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, :tumblelog)
|
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
|
+
it 'should provide a hash of attributes and values for API' do
|
24
|
+
Post.new.should respond_to(:attribute_hash)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
describe Tumblelog, 'user' do
|
40
|
+
|
41
|
+
describe 'logged in' do
|
42
|
+
|
43
|
+
before(:each) do
|
44
|
+
mock_successful(:authenticate)
|
45
|
+
@user = User.login(:email => 'valid_email', :password => 'valid_password')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have a user associated with it' do
|
49
|
+
@user.primary_tumblelog.user.should_not be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'not logged in' do
|
55
|
+
|
56
|
+
it 'should not have a user if anonymous read' do
|
57
|
+
mock_successful(:anonymous_read)
|
58
|
+
Tumblelog.find_by_url('valid_url').user.should be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
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 == 'yes'
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,106 @@
|
|
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
|
+
if request == :authenticated_write
|
16
|
+
@client.stub!(:complete_request).and_return(responses_to[request])
|
17
|
+
else
|
18
|
+
# yes, this is cheating, but for now just concerned that xml is parsed right
|
19
|
+
@client.stub!(:complete_request).and_yield(responses_to[request])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def successful_authenticate_xml
|
24
|
+
response = <<-EOF
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
26
|
+
<tumblr version="1.0">
|
27
|
+
<user can-upload-audio="1" can-upload-aiff="1" can-upload-video="0" vimeo-login-url="http://www.vimeo.com/services/foo"/>
|
28
|
+
<tumblelog title="" name="foo" url="http://foo.com/" type="public" avatar-url="http://assets.tumblr.com/images/default_avatar_foo.gif" is-primary="yes"/>
|
29
|
+
<tumblelog title="bar" private-id="000000" type="private"/>
|
30
|
+
</tumblr>
|
31
|
+
EOF
|
32
|
+
response.strip!
|
33
|
+
end
|
34
|
+
|
35
|
+
def successful_anonymous_read_xml
|
36
|
+
response = <<-EOF
|
37
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
38
|
+
<tumblr version="1.0">
|
39
|
+
<tumblelog name="dummylog" timezone="US/Eastern" title="dummy tumblelog title">dummylog description</tumblelog>
|
40
|
+
<posts start="0" total="7">
|
41
|
+
<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">
|
42
|
+
<video-caption>public video post caption</video-caption>
|
43
|
+
<video-source>http://www.youtube.com/watch?v=rPaWZOM1LnY</video-source>
|
44
|
+
<video-player><object width="400" height="336"><param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1"></param><param name="wmode" value="transparent"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"></embed></object></video-player>
|
45
|
+
<tag>sale</tag>
|
46
|
+
<tag>music</tag>
|
47
|
+
</post>
|
48
|
+
<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">
|
49
|
+
<audio-caption>public audio post description</audio-caption><audio-player><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&color=FFFFFF" height="27" width="207" quality="best"></embed></audio-player>
|
50
|
+
<tag>sale</tag>
|
51
|
+
</post>
|
52
|
+
<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">
|
53
|
+
<conversation-title>public chat post title</conversation-title>
|
54
|
+
<conversation-text>me: public
|
55
|
+
you: chat
|
56
|
+
me: post
|
57
|
+
you: dialogue</conversation-text><conversation><line name="me" label="me:">public </line><line name="you" label="you:">chat </line><line name="me" label="me:">post </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 </conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat </conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post </conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line>
|
58
|
+
<tag>sale</tag>
|
59
|
+
</post>
|
60
|
+
<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">
|
61
|
+
<link-text>public link post name</link-text><link-url>http://www.google.com</link-url>
|
62
|
+
<link-description>public link post description</link-description>
|
63
|
+
<tag>sale</tag>
|
64
|
+
</post>
|
65
|
+
<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">
|
66
|
+
<quote-text>public quote post content</quote-text>
|
67
|
+
<quote-source>public quote post source</quote-source>
|
68
|
+
<tag>sale</tag>
|
69
|
+
</post>
|
70
|
+
<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">
|
71
|
+
<regular-title>public text post title</regular-title>
|
72
|
+
<regular-body>public text post body</regular-body>
|
73
|
+
<tag>sale</tag>
|
74
|
+
</post>
|
75
|
+
<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">
|
76
|
+
<photo-caption>public photo post</photo-caption>
|
77
|
+
<photo-url max-width="500">http://21.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_500.jpg</photo-url>
|
78
|
+
<photo-url max-width="400">http://1.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_400.jpg</photo-url>
|
79
|
+
<photo-url max-width="250">http://22.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_250.jpg</photo-url>
|
80
|
+
<photo-url max-width="100">http://19.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_100.jpg</photo-url>
|
81
|
+
<photo-url max-width="75">http://2.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_75sq.jpg</photo-url>
|
82
|
+
<tag>sale</tag>
|
83
|
+
</post>
|
84
|
+
</posts>
|
85
|
+
</tumblr>
|
86
|
+
EOF
|
87
|
+
response.strip!
|
88
|
+
end
|
89
|
+
|
90
|
+
def successful_authenticated_read_xml
|
91
|
+
response = <<-EOF
|
92
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
93
|
+
<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><object width="400" height="336"><param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1"></param><param name="wmode" value="transparent"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"></embed></object></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><object width="400" height="336"><param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1"></param><param name="wmode" value="transparent"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"></embed></object></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><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&color=FFFFFF" height="27" width="207" quality="best"></embed></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><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&color=FFFFFF" height="27" width="207" quality="best"></embed></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
|
94
|
+
you: chat
|
95
|
+
me: post
|
96
|
+
you: dialogue</conversation-text><conversation><line name="me" label="me:">private </line><line name="you" label="you:">chat </line><line name="me" label="me:">post </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 </conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat </conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post </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
|
97
|
+
you: chat
|
98
|
+
me: post
|
99
|
+
you: dialogue</conversation-text><conversation><line name="me" label="me:">public </line><line name="you" label="you:">chat </line><line name="me" label="me:">post </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 </conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat </conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post </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>
|
100
|
+
EOF
|
101
|
+
response.strip!
|
102
|
+
end
|
103
|
+
|
104
|
+
def successful_authenticated_write_xml
|
105
|
+
"10001"
|
106
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hexorx-rumblr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brent Hargrave
|
8
|
+
- Benny Wong
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-05-30 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: libxml-ruby
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.8.3
|
25
|
+
version:
|
26
|
+
description: Ruby client for the Tumblr API
|
27
|
+
email: brent.hargrave@gmail.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- LICENSE.rdoc
|
34
|
+
- README.rdoc
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE.rdoc
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- VERSION.yml
|
41
|
+
- lib/rumblr.rb
|
42
|
+
- lib/rumblr/client.rb
|
43
|
+
- lib/rumblr/post.rb
|
44
|
+
- lib/rumblr/resource.rb
|
45
|
+
- lib/rumblr/tumblelog.rb
|
46
|
+
- lib/rumblr/user.rb
|
47
|
+
- rumblr.gemspec
|
48
|
+
- spec/rumblr/client_spec.rb
|
49
|
+
- spec/rumblr/post_spec.rb
|
50
|
+
- spec/rumblr/tumblelog_spec.rb
|
51
|
+
- spec/rumblr/user_spec.rb
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
has_rdoc: false
|
54
|
+
homepage: http://github.com/jamescallmebrent/rumblr
|
55
|
+
licenses:
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --charset=UTF-8
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Ruby client for the Tumblr API
|
80
|
+
test_files:
|
81
|
+
- spec/rumblr/client_spec.rb
|
82
|
+
- spec/rumblr/post_spec.rb
|
83
|
+
- spec/rumblr/tumblelog_spec.rb
|
84
|
+
- spec/rumblr/user_spec.rb
|
85
|
+
- spec/spec_helper.rb
|