jordandobson-posterous 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -5
- data/Manifest.txt +3 -3
- data/README.txt +60 -23
- data/Rakefile +3 -4
- data/bin/posterous +2 -0
- data/lib/posterous.rb +109 -0
- data/test/test_posterous.rb +414 -0
- metadata +12 -12
- data/bin/wordpress +0 -3
- data/lib/wordpress.rb +0 -99
- data/test/test_wordpress.rb +0 -133
data/History.txt
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
=== 1.0
|
1
|
+
=== 0.1.0 / 2009-05-19
|
2
2
|
|
3
3
|
* 1 major enhancement
|
4
4
|
|
5
|
-
*
|
6
|
-
|
7
|
-
=== 1.
|
5
|
+
* Birthday!
|
6
|
+
|
7
|
+
=== 0.1.2 / 2009-05-29
|
8
8
|
|
9
9
|
* 1 major enhancement
|
10
10
|
|
11
|
-
*
|
11
|
+
* Updated the class to accept date, private, autopost, tags
|
12
12
|
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -1,34 +1,36 @@
|
|
1
|
-
=
|
1
|
+
= posterous
|
2
2
|
|
3
|
-
|
3
|
+
http://github.com/jordandobson/Posterous/tree/master
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
The
|
7
|
+
The Posterous gem provides posting to Posterous.com using your email, password, site id(if you have multiple sites) and your blog content. With this gem, you have access to add an entry on posterous by providing these options a title, body text, date, tags, set to autopost, set private, posted by source name and a posted by source link to Posterous. You can include no options or all options.
|
8
8
|
|
9
|
-
Posting images with posts, posting only images and pulling down your posts will be available
|
9
|
+
Posting images with posts, posting only images and pulling down your posts will be available soon. The Posterous API was unstable when this version of the gem was created.
|
10
10
|
|
11
11
|
== FEATURES/PROBLEMS:
|
12
12
|
|
13
|
-
*
|
14
|
-
*
|
13
|
+
* All Fields are optional
|
14
|
+
* Media files are not yet implemented
|
15
15
|
* Posting Only, Reading & Images are not yet included
|
16
|
-
* Check if a
|
17
|
-
* Check if a
|
18
|
-
*
|
19
|
-
*
|
16
|
+
* Check if a users email and password are a valid account
|
17
|
+
* Check if a user has a valid site
|
18
|
+
* Check if a specified site_id is valid for their account
|
19
|
+
* Get their primary Site ID
|
20
|
+
* This is very well throughly tested
|
20
21
|
|
21
22
|
== SYNOPSIS:
|
22
23
|
|
23
24
|
1. Instantiate your account
|
24
25
|
|
25
|
-
* You can provide just the
|
26
|
+
* You can provide just the email and password
|
26
27
|
|
27
|
-
account =
|
28
|
+
account = Posterous.new('email_address', 'password')
|
28
29
|
|
29
30
|
* Or you can provide the ID as a string or integer
|
30
31
|
|
31
|
-
account =
|
32
|
+
account = Posterous.new('email_address', 'password', 68710)
|
33
|
+
account = Posterous.new('email_address', 'password', '68710')
|
32
34
|
|
33
35
|
2. Get more info about the user's account if you need it
|
34
36
|
|
@@ -36,25 +38,37 @@ Posting images with posts, posting only images and pulling down your posts will
|
|
36
38
|
|
37
39
|
account.valid_user?
|
38
40
|
|
39
|
-
* Check if the specified
|
41
|
+
* Check if the user has a site and if they specified a Site ID check it's valid
|
40
42
|
|
41
|
-
account.
|
43
|
+
account.has_site?
|
42
44
|
|
43
|
-
* Get the users
|
45
|
+
* Get the users primary site ID (In case they have two)
|
44
46
|
|
45
|
-
account.
|
47
|
+
account.get_primary_site
|
46
48
|
|
47
49
|
* Get a list of your sites and additional info
|
48
50
|
|
49
|
-
account.
|
51
|
+
account.get_account_info
|
50
52
|
|
51
|
-
3. Setup your post
|
53
|
+
3. Setup your post with any or all of these optional fields
|
52
54
|
|
53
|
-
* You
|
55
|
+
* You can set your id at this point or when it's instantiated
|
56
|
+
|
57
|
+
account.site_id = account.get_primary_site or specific site ID
|
58
|
+
|
59
|
+
* Set these optional fields
|
54
60
|
|
55
61
|
account.title = "My Title"
|
56
62
|
account.body = "My Body Text"
|
63
|
+
account.source = "Glue"
|
64
|
+
account.source_url = "http://GlueNow.com"
|
57
65
|
account.tags = ["Glue", "Posterous", "Ruby", "Made By Squad"]
|
66
|
+
account.date = Time.now
|
67
|
+
|
68
|
+
* Call these methods to set them
|
69
|
+
|
70
|
+
account.set_to_private
|
71
|
+
account.set_to_autopost
|
58
72
|
|
59
73
|
4. Add your post to Posterous.com
|
60
74
|
|
@@ -66,17 +80,40 @@ Posting images with posts, posting only images and pulling down your posts will
|
|
66
80
|
|
67
81
|
* Your response should look something like this if successful
|
68
82
|
|
69
|
-
response #=> { "rsp" => { "post" => { "title" => "My Title", "url" => "http://
|
83
|
+
response #=> { "rsp" => { "post" => { "title" => "My Title", "url" => "http://post.ly/dFW", "id" => "848898", "longurl" => "http://glue.posterous.com/687985" }, "stat" => "ok" } }
|
70
84
|
|
71
85
|
* See the tests for this gem for failure responses and responses for other methods
|
72
86
|
|
87
|
+
|
88
|
+
# MORE INFO
|
89
|
+
|
90
|
+
* URL
|
91
|
+
|
92
|
+
http://posterous.com/api/newpost
|
93
|
+
|
94
|
+
* IMPLEMENTED FIELDS - All are optional
|
95
|
+
|
96
|
+
"site_id" Optional. Id of the site to post to.
|
97
|
+
"title" Optional. Title of post
|
98
|
+
"body" Optional. Body of post
|
99
|
+
"source" Optional. The name of your application or website
|
100
|
+
"sourceLink" Optional. Link to your application or website
|
101
|
+
"date" Optional. In GMT. Any parsable format. Cannot be in the future.
|
102
|
+
"tags" Optional. Comma separate tags
|
103
|
+
"autopost" Optional. 0 or 1.
|
104
|
+
"private" Optional. 0 or 1.
|
105
|
+
|
106
|
+
* UNIMPLEMENTED FIELDS - These will likely be implemented in a future release
|
107
|
+
|
108
|
+
"media" Optional. File data. Multiple files OK
|
109
|
+
|
73
110
|
== REQUIREMENTS:
|
74
111
|
|
75
|
-
*
|
112
|
+
* HTTPparty, & Mocha (For Tests)
|
76
113
|
|
77
114
|
== INSTALL:
|
78
115
|
|
79
|
-
* sudo gem install
|
116
|
+
* sudo gem install posterous -include-dependencies
|
80
117
|
|
81
118
|
== LICENSE:
|
82
119
|
|
data/Rakefile
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
-
require './lib/
|
5
|
+
require './lib/posterous.rb'
|
6
6
|
|
7
|
-
Hoe.new('
|
8
|
-
# p.rubyforge_name = 'wordpressx' # if different than lowercase project name
|
7
|
+
Hoe.new('posterous', Posterous::VERSION) do |p|
|
9
8
|
p.developer('Jordan Dobson', 'jordan.dobson@madebysquad.com')
|
10
|
-
p.extra_deps = ['
|
9
|
+
p.extra_deps = ['httparty', 'mocha']
|
11
10
|
end
|
12
11
|
|
13
12
|
# vim: syntax=Ruby
|
data/bin/posterous
ADDED
data/lib/posterous.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
class PosterousAuthError < StandardError; end
|
5
|
+
class PosterousTagError < StandardError; end
|
6
|
+
class PosterousSiteError < StandardError; end
|
7
|
+
|
8
|
+
###
|
9
|
+
### FUTURE PLANS
|
10
|
+
###
|
11
|
+
# * Include media with your post
|
12
|
+
# * Post only a media file and get a url for it back
|
13
|
+
# * Allow reading in posterous posts
|
14
|
+
# * Include more usage examples outside of readme
|
15
|
+
|
16
|
+
class Posterous
|
17
|
+
|
18
|
+
VERSION = '0.1.2'
|
19
|
+
DOMAIN = 'posterous.com'
|
20
|
+
POST_PATH = '/api/newpost'
|
21
|
+
AUTH_PATH = '/api/getsites'
|
22
|
+
|
23
|
+
include HTTParty
|
24
|
+
base_uri DOMAIN
|
25
|
+
|
26
|
+
attr_accessor :title, :body, :source, :source_url, :date, :tags
|
27
|
+
attr_reader :site_id, :private_post, :autopost
|
28
|
+
|
29
|
+
def initialize user, pass, site_id = nil
|
30
|
+
raise PosterousAuthError, 'Either Username or Password is blank and/or not a string.' if \
|
31
|
+
!user.is_a?(String) || !pass.is_a?(String) || user == "" || pass == ""
|
32
|
+
self.class.basic_auth user, pass
|
33
|
+
@site_id = site_id ? site_id.to_s : site_id
|
34
|
+
@source = @body = @title = @source_url = @date = @media = @tags = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def site_id= id
|
38
|
+
@site_id = id.to_s
|
39
|
+
end
|
40
|
+
def tags= ary
|
41
|
+
raise PosterousTagError, 'Tags must add from be in an array' if !ary.is_a?(Array)
|
42
|
+
@tags = ary.join(", ")
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_user?
|
46
|
+
res = get_account_info
|
47
|
+
return false unless res.is_a?(Hash)
|
48
|
+
res["stat"] == "ok" ? true : false
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_site?
|
52
|
+
res = get_account_info
|
53
|
+
return false unless res.is_a?(Hash)
|
54
|
+
if res["site"].is_a?(Hash)
|
55
|
+
@site_id && @site_id == res["site"]["id"] || !@site_id ? true : false
|
56
|
+
elsif res["site"].is_a?(Array)
|
57
|
+
res["site"].each do |site|
|
58
|
+
return true if @site_id && @site_id == site["id"]
|
59
|
+
end
|
60
|
+
false
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_primary_site
|
67
|
+
res = get_account_info
|
68
|
+
raise PosterousSiteError, "Couldn't find a primary site. Check login and password is valid." \
|
69
|
+
unless res.is_a?(Hash) && res["stat"] == "ok" && res["site"]
|
70
|
+
site_list = res["site"].is_a?(Array) ? res["site"] : [res["site"]]
|
71
|
+
site_list.each do |site|
|
72
|
+
return site["id"] if site["primary"] == "true"
|
73
|
+
end
|
74
|
+
return nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_to_private
|
78
|
+
@private_post = 1
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_to_autopost
|
82
|
+
@autopost = 1
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_query
|
86
|
+
options = { :site_id => @site_id,
|
87
|
+
:autopost => @autopost,
|
88
|
+
:private => @private_post,
|
89
|
+
:date => @date,
|
90
|
+
:tags => @tags }
|
91
|
+
|
92
|
+
query = { :title => @title,
|
93
|
+
:body => @body,
|
94
|
+
:source => @source,
|
95
|
+
:sourceLink => @source_url }
|
96
|
+
|
97
|
+
options.delete_if { |k,v| !v }
|
98
|
+
query.merge!(options)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_account_info
|
102
|
+
self.class.post(AUTH_PATH, :query => {})["rsp"]
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_post
|
106
|
+
self.class.post(POST_PATH, :query => build_query)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,414 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'posterous'
|
3
|
+
require 'mocha'
|
4
|
+
|
5
|
+
class TestPosterous < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@e = "email"
|
9
|
+
@p = "password"
|
10
|
+
|
11
|
+
@new_obj = Posterous.new(@e, @p)
|
12
|
+
@new_obj_with_id = Posterous.new(@e, @p, "174966")
|
13
|
+
@new_obj_with_bad_id = Posterous.new(@e, @p, "badID")
|
14
|
+
@new_obj_with_invalid_id = Posterous.new(@e, @p, "666")
|
15
|
+
|
16
|
+
@private_url_path = /[.]posterous[.]com\/private\//
|
17
|
+
|
18
|
+
@resp_ok ={ "rsp" => {
|
19
|
+
"site" => {
|
20
|
+
"name" => "ruby-posterous's posterous",
|
21
|
+
"primary" => "true", "private"=>"false",
|
22
|
+
"url" => "http://ruby-posterous.posterous.com",
|
23
|
+
"id" => "174966" },
|
24
|
+
"stat" => "ok" }}
|
25
|
+
|
26
|
+
@resp_fail ={ "rsp" => {
|
27
|
+
"err" => {
|
28
|
+
"msg" => "Invalid Posterous email or password",
|
29
|
+
"code" => "3001" },
|
30
|
+
"stat" => "fail" }}
|
31
|
+
|
32
|
+
@resp_ok_2_sites ={ "rsp" => {
|
33
|
+
"site" => [{
|
34
|
+
"name" => "ruby-posterous's posterous",
|
35
|
+
"primary" => "false",
|
36
|
+
"private" => "false",
|
37
|
+
"url" => "http://ruby-posterous.posterous.com",
|
38
|
+
"id" => "174966"
|
39
|
+
}, {
|
40
|
+
"name" => "uw-ruby",
|
41
|
+
"primary" => "true",
|
42
|
+
"private" => "false",
|
43
|
+
"url" => "http://uwruby.posterous.com",
|
44
|
+
"id" => "175260" }],
|
45
|
+
"stat" => "ok" }}
|
46
|
+
|
47
|
+
@good_response ={ "site" => {
|
48
|
+
"name" => "ruby-posterous's posterous",
|
49
|
+
"primary" => "true",
|
50
|
+
"private" => "false",
|
51
|
+
"url" => "http://ruby-posterous.posterous.com",
|
52
|
+
"id" => "174966" },
|
53
|
+
"stat" => "ok" }
|
54
|
+
|
55
|
+
@good_response_2_sites ={ "rsp" => {
|
56
|
+
"site" => [{
|
57
|
+
"name" => "ruby-posterous's posterous",
|
58
|
+
"primary" => "true",
|
59
|
+
"private" => "false",
|
60
|
+
"url" => "http://ruby-posterous.posterous.com",
|
61
|
+
"id" => "174966"
|
62
|
+
}, {
|
63
|
+
"name" => "uw-ruby",
|
64
|
+
"primary" => "false",
|
65
|
+
"private" => "false",
|
66
|
+
"url" => "http://uwruby.posterous.com",
|
67
|
+
"id" => "175260" }],
|
68
|
+
"stat" => "ok" }}
|
69
|
+
|
70
|
+
@bad_response ={ "err" => {
|
71
|
+
"msg" => "Invalid Posterous email or password",
|
72
|
+
"code" => "3001" },
|
73
|
+
"stat" => "fail" }
|
74
|
+
|
75
|
+
@post_success ={ "rsp" => {
|
76
|
+
"post" => {
|
77
|
+
"title" => "Untitled",
|
78
|
+
"url" => "http://post.ly/dFW",
|
79
|
+
"id" => "848898",
|
80
|
+
"longurl" => "http://glue.posterous.com/687985" },
|
81
|
+
"stat" => "ok" }}
|
82
|
+
|
83
|
+
@post_title_success ={"rsp" => {
|
84
|
+
"post" => {
|
85
|
+
"title" => "My Title",
|
86
|
+
"url" => "http://post.ly/dFW",
|
87
|
+
"id" => "848898",
|
88
|
+
"longurl" => "http://glue.posterous.com/687985" },
|
89
|
+
"stat" => "ok" }}
|
90
|
+
|
91
|
+
@post_invalid_site ={ "rsp" => {
|
92
|
+
"err" => {
|
93
|
+
"msg" => "Invalid site id",
|
94
|
+
"code" => "3002" },
|
95
|
+
"stat" => "fail" }}
|
96
|
+
|
97
|
+
@post_access_error ={ "rsp" => {
|
98
|
+
"err" => {
|
99
|
+
"msg" => "User does not have access to this site",
|
100
|
+
"code" => "3003" },
|
101
|
+
"stat" => "fail" }}
|
102
|
+
|
103
|
+
@post_bad_account ={ "rsp" => {
|
104
|
+
"err" => {
|
105
|
+
"msg" => "Invalid Posterous email or password",
|
106
|
+
"code" => "3001" },
|
107
|
+
"stat" => "fail" }}
|
108
|
+
|
109
|
+
@post_private_good ={ "rsp" => {
|
110
|
+
"post" => {
|
111
|
+
"title" => "Posterous test",
|
112
|
+
"url" => "http://post.ly/gxK",
|
113
|
+
"id" => "891064",
|
114
|
+
"longurl" => "http://glue.posterous.com/private/tGIEAateBy" },
|
115
|
+
"stat" => "ok" }}
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_raises_if_username_is_blank
|
119
|
+
assert_raise PosterousAuthError do
|
120
|
+
Posterous.new('', @p)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_raises_if_password_is_blank
|
125
|
+
assert_raise PosterousAuthError do
|
126
|
+
Posterous.new(@e, '')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_raises_if_password_is_not_srting
|
131
|
+
assert_raise PosterousAuthError do
|
132
|
+
Posterous.new(@e, 666)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_raises_if_username_is_not_srting
|
137
|
+
assert_raise PosterousAuthError do
|
138
|
+
Posterous.new(666, @p)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_site_id_can_be_witheld
|
143
|
+
actual = Posterous.new(@e, @p)
|
144
|
+
assert_equal nil, actual.site_id
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_site_id_can_be_provided
|
148
|
+
actual = Posterous.new(@e, @p, '174966')
|
149
|
+
assert_equal '174966', actual.site_id
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_site_id_is_converted_to_string
|
153
|
+
actual = Posterous.new(@e, @p, 174966)
|
154
|
+
assert_equal '174966', actual.site_id
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_user_is_valid
|
158
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
159
|
+
assert_equal true, @new_obj.valid_user?
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_user_is_invalid
|
163
|
+
Posterous.stubs(:post).returns(@resp_fail)
|
164
|
+
assert_equal false, @new_obj.valid_user?
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_user_is_invalid_when_response_isnt_hash
|
168
|
+
Posterous.stubs(:post).returns("666")
|
169
|
+
assert_equal false, @new_obj.valid_user?
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_ping_success_hash_adjustment
|
173
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
174
|
+
assert_equal @good_response, @new_obj.get_account_info
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_ping_fail_hash_adjustment
|
178
|
+
Posterous.stubs(:post).returns(@resp_fail)
|
179
|
+
assert_equal @bad_response, @new_obj.get_account_info
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_has_site_is_successful
|
183
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
184
|
+
assert_equal true, @new_obj.has_site?
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_has_site_successful_if_site_id_matches_only_result
|
188
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
189
|
+
assert_equal true, @new_obj_with_id.has_site?
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_has_site_fails_if_site_id_doesnt_match_only_result
|
193
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
194
|
+
assert_equal false, @new_obj_with_bad_id.has_site?
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_has_site_is_successful_on_multiple_when_specified
|
198
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
199
|
+
assert_equal true, @new_obj_with_id.has_site?
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_has_site_fails_if_specified_and_site_id_not_listed
|
203
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
204
|
+
assert_equal false, @new_obj_with_bad_id.has_site?
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_has_site_fails_when_multiple_and_site_not_specified
|
208
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
209
|
+
assert_equal false, @new_obj.has_site?
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_has_site_fails_with_error_response
|
213
|
+
Posterous.stubs(:post).returns(@resp_fail)
|
214
|
+
assert_equal false, @new_obj.has_site?
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_has_site_fails_if_response_isnt_hash
|
218
|
+
Posterous.stubs(:post).returns("666")
|
219
|
+
assert_equal false, @new_obj.has_site?
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_tags_are_added_correctly
|
223
|
+
@new_obj.tags = []
|
224
|
+
assert_equal @new_obj.tags, ""
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_tags_single_is_correctly
|
228
|
+
@new_obj.tags = ["Glue"]
|
229
|
+
assert_equal @new_obj.tags, "Glue"
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_tags_single_is_correctly
|
233
|
+
@new_obj.tags = ["Glue"]
|
234
|
+
assert_equal @new_obj.tags, "Glue"
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_tags_single_is_correctly_joined
|
238
|
+
@new_obj.tags = ["Glue", "Posterous", "Ruby on Rails"]
|
239
|
+
assert_equal @new_obj.tags, "Glue, Posterous, Ruby on Rails"
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_raises_if_tags_not_set_as_array
|
243
|
+
assert_raise PosterousTagError do
|
244
|
+
@new_obj.tags = "hello, "
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_gets_primary_single_site
|
249
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
250
|
+
assert_equal @resp_ok["rsp"]["site"]["id"], @new_obj.get_primary_site
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_gets_primary_site_from_multiple_listing
|
254
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
255
|
+
assert_equal @resp_ok_2_sites["rsp"]["site"][1]["id"], @new_obj.get_primary_site
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_gets_primary_site_raises_on_error
|
259
|
+
Posterous.stubs(:post).returns(@resp_fail)
|
260
|
+
assert_raise PosterousSiteError do
|
261
|
+
@new_obj.get_primary_site
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_gets_primary_site_is_passed_to_overide_site_id
|
266
|
+
Posterous.stubs(:post).returns(@resp_ok_2_sites)
|
267
|
+
original = @new_obj_with_id.site_id
|
268
|
+
@new_obj_with_id.site_id = @new_obj_with_id.get_primary_site
|
269
|
+
updated = @new_obj_with_id.site_id
|
270
|
+
assert_not_equal original, updated
|
271
|
+
assert_equal @resp_ok_2_sites["rsp"]["site"][1]["id"], updated
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_gets_primary_site_is_set_to_site_id
|
275
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
276
|
+
original = @new_obj.site_id
|
277
|
+
@new_obj.site_id = @new_obj.get_primary_site
|
278
|
+
updated = @new_obj_with_id.site_id
|
279
|
+
assert_not_equal original, updated
|
280
|
+
assert_equal @resp_ok["rsp"]["site"]["id"], updated
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_gets_primary_site_is_set_to_site_id
|
284
|
+
Posterous.stubs(:post).returns(@resp_ok)
|
285
|
+
original = @new_obj.site_id
|
286
|
+
@new_obj.site_id = @new_obj.get_primary_site
|
287
|
+
updated = @new_obj_with_id.site_id
|
288
|
+
assert_not_equal original, updated
|
289
|
+
assert_equal @resp_ok["rsp"]["site"]["id"], updated
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_builds_query_without_site_id
|
293
|
+
expected = { :source => nil, :title => nil, :body => nil, :sourceLink => nil}
|
294
|
+
assert_equal expected, @new_obj.build_query
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_builds_query_with_site_id
|
298
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :site_id => "174966", :title => nil }
|
299
|
+
assert_equal expected, @new_obj_with_id.build_query
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_builds_query_with_all_fields_set_without_site_id
|
303
|
+
@new_obj.title = "My Title"
|
304
|
+
@new_obj.body = "My Body"
|
305
|
+
@new_obj.source = "The Tubes"
|
306
|
+
@new_obj.source_url = "http://TheTubes.com"
|
307
|
+
expected = { :source => "The Tubes", :body => "My Body", :sourceLink => "http://TheTubes.com", :title => "My Title" }
|
308
|
+
assert_equal expected, @new_obj.build_query
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_builds_query_with_date_option
|
312
|
+
date = Time.now
|
313
|
+
@new_obj.date = date
|
314
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :title => nil, :date => date }
|
315
|
+
assert_equal expected, @new_obj.build_query
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_builds_query_with_private_option
|
319
|
+
@new_obj.set_to_private
|
320
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :title => nil, :private => 1 }
|
321
|
+
assert_equal expected, @new_obj.build_query
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_builds_query_with_autopost_option
|
325
|
+
@new_obj.set_to_autopost
|
326
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :title => nil, :autopost => 1 }
|
327
|
+
assert_equal expected, @new_obj.build_query
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_builds_query_with_site_id
|
331
|
+
@new_obj.site_id = 20
|
332
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :site_id => "20", :title => nil }
|
333
|
+
assert_equal expected, @new_obj.build_query
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_builds_query_with_all_options_set
|
337
|
+
date = Time.now
|
338
|
+
@new_obj.date = date
|
339
|
+
@new_obj.site_id = 20
|
340
|
+
@new_obj.set_to_private
|
341
|
+
expected = { :source => nil, :body => nil, :sourceLink => nil, :site_id => "20", :title => nil, :private => 1, :date => date }
|
342
|
+
assert_equal expected, @new_obj.build_query
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_builds_query_with_all_fields_set_and_site_id
|
346
|
+
@new_obj_with_id.title = "My Title"
|
347
|
+
@new_obj_with_id.body = "My Body"
|
348
|
+
@new_obj_with_id.source = "The Tubes"
|
349
|
+
@new_obj_with_id.source_url = "http://TheTubes.com"
|
350
|
+
expected = { :source => "The Tubes", :body => "My Body", :sourceLink => "http://TheTubes.com", :site_id => "174966", :title => "My Title" }
|
351
|
+
assert_equal expected, @new_obj_with_id.build_query
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_add_post_successful
|
355
|
+
Posterous.stubs(:post).returns(@post_success)
|
356
|
+
expected = @post_success
|
357
|
+
assert_equal expected, @new_obj.add_post
|
358
|
+
end
|
359
|
+
|
360
|
+
def test_add_post_successful_no_content
|
361
|
+
Posterous.stubs(:post).returns(@post_success)
|
362
|
+
actual = @new_obj.add_post
|
363
|
+
assert actual["rsp"]["post"].is_a?(Hash)
|
364
|
+
assert_equal "ok", actual["rsp"]["stat"]
|
365
|
+
assert_equal "Untitled", actual["rsp"]["post"]["title"]
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_add_post_successful_with_title_content
|
369
|
+
Posterous.stubs(:post).returns(@post_title_success)
|
370
|
+
@new_obj.title = "My Title"
|
371
|
+
actual = @new_obj.add_post
|
372
|
+
assert_equal "My Title", actual["rsp"]["post"]["title"]
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_add_post_invalid_site_id_fails
|
376
|
+
Posterous.stubs(:post).returns(@post_invalid_site)
|
377
|
+
actual = @new_obj_with_bad_id.add_post
|
378
|
+
assert_equal "fail", actual["rsp"]["stat"]
|
379
|
+
assert_equal nil, actual["rsp"]["post"]
|
380
|
+
assert_equal "Invalid site id", actual["rsp"]["err"]["msg"]
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_add_post_no_access_fails
|
384
|
+
Posterous.stubs(:post).returns(@post_access_error)
|
385
|
+
actual = @new_obj_with_invalid_id.add_post
|
386
|
+
assert_equal "fail", actual["rsp"]["stat"]
|
387
|
+
assert_equal nil, actual["rsp"]["post"]
|
388
|
+
assert_match "not have access", actual["rsp"]["err"]["msg"]
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_add_post_invalid_account_info
|
392
|
+
Posterous.stubs(:post).returns(@post_bad_account)
|
393
|
+
actual = Posterous.new("666", "666").add_post
|
394
|
+
assert_equal "fail", actual["rsp"]["stat"]
|
395
|
+
assert_equal nil, actual["rsp"]["post"]
|
396
|
+
assert_match "Invalid Posterous", actual["rsp"]["err"]["msg"]
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_add_post_is_private_by_default
|
400
|
+
Posterous.stubs(:post).returns(@post_success)
|
401
|
+
actual = @new_obj.add_post
|
402
|
+
assert_equal "ok", actual["rsp"]["stat"]
|
403
|
+
assert_no_match @private_url_path, actual["rsp"]["post"]["longurl"]
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_add_post_is_made_private
|
407
|
+
Posterous.stubs(:post).returns(@post_private_good)
|
408
|
+
@new_obj.set_to_private
|
409
|
+
actual = @new_obj.add_post
|
410
|
+
assert_equal "ok", actual["rsp"]["stat"]
|
411
|
+
assert_match @private_url_path, actual["rsp"]["post"]["longurl"]
|
412
|
+
end
|
413
|
+
|
414
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jordandobson-posterous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Dobson
|
@@ -9,8 +9,8 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
13
|
-
default_executable:
|
12
|
+
date: 2009-05-29 00:00:00 -07:00
|
13
|
+
default_executable: posterous
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: hoe
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 1.8.3
|
24
24
|
version:
|
25
|
-
description: The
|
25
|
+
description: The Posterous gem provides posting to Posterous.com using your email, password, site id(if you have multiple sites) and your blog content.
|
26
26
|
email:
|
27
27
|
- jordan.dobson@madebysquad.com
|
28
28
|
executables: []
|
@@ -38,11 +38,11 @@ files:
|
|
38
38
|
- Manifest.txt
|
39
39
|
- README.txt
|
40
40
|
- Rakefile
|
41
|
-
- bin/
|
42
|
-
- lib/
|
43
|
-
- test/
|
44
|
-
has_rdoc:
|
45
|
-
homepage: http://github.com/jordandobson/
|
41
|
+
- bin/posterous
|
42
|
+
- lib/posterous.rb
|
43
|
+
- test/test_posterous.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/jordandobson/posterous/tree/master
|
46
46
|
post_install_message:
|
47
47
|
rdoc_options:
|
48
48
|
- --main
|
@@ -63,10 +63,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
63
|
version:
|
64
64
|
requirements: []
|
65
65
|
|
66
|
-
rubyforge_project:
|
66
|
+
rubyforge_project: posterous
|
67
67
|
rubygems_version: 1.2.0
|
68
68
|
signing_key:
|
69
69
|
specification_version: 2
|
70
|
-
summary:
|
70
|
+
summary: The Posterous gem provides posting to Posterous.com using your email, password, site id(if you have multiple sites) and your blog content. With this gem, you have access to post a title, body text, posting source and a source link to Posterous. Posting images and pulling down your posts will be available soon. They were made available a day before this was completed.
|
71
71
|
test_files:
|
72
|
-
- test/
|
72
|
+
- test/test_posterous.rb
|
data/bin/wordpress
DELETED
data/lib/wordpress.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'mechanize'
|
3
|
-
|
4
|
-
module Wordpress
|
5
|
-
|
6
|
-
VERSION = '0.1.1'
|
7
|
-
|
8
|
-
class AuthError < StandardError; end
|
9
|
-
class PostError < StandardError; end
|
10
|
-
|
11
|
-
class Client
|
12
|
-
|
13
|
-
DEFAULT_URL = 'http://wordpress.com/wp-login.php'
|
14
|
-
LOGIN_FORM = 'loginform'
|
15
|
-
POST_FORM = 'post'
|
16
|
-
IS_ADMIN = 'body.wp-admin'
|
17
|
-
IS_LOGIN = 'body.login'
|
18
|
-
|
19
|
-
attr_accessor :title, :body
|
20
|
-
attr_reader :login_url, :username, :password, :tags, :post_url
|
21
|
-
|
22
|
-
def initialize usr, pwd, login_url = DEFAULT_URL
|
23
|
-
raise AuthError, "Blank Username or Password or not a string." \
|
24
|
-
if !usr.is_a?(String) || !pwd.is_a?(String) || usr == '' || pwd == ''
|
25
|
-
|
26
|
-
raise AuthError, "Url should end with wp-login.php" \
|
27
|
-
unless login_url =~ /\/wp-login[.]php$/
|
28
|
-
|
29
|
-
@username = usr
|
30
|
-
@password = pwd
|
31
|
-
@login_url = login_url
|
32
|
-
@agent = nil
|
33
|
-
@post_url = nil
|
34
|
-
end
|
35
|
-
|
36
|
-
def tags= ary
|
37
|
-
raise TagError, 'Tags must added using an array' if !ary.is_a?(Array)
|
38
|
-
@tags = ary.join(", ")
|
39
|
-
end
|
40
|
-
|
41
|
-
def valid_login_page?
|
42
|
-
lf = login_page.form(LOGIN_FORM)
|
43
|
-
lf && lf.log ? true : false
|
44
|
-
end
|
45
|
-
|
46
|
-
def valid_user?
|
47
|
-
logged_into? dashboard_page
|
48
|
-
end
|
49
|
-
|
50
|
-
def blog_url
|
51
|
-
a = dashboard_page.search("#{IS_ADMIN} #wphead h1 a")
|
52
|
-
return a.first['href'] if a.first && a.first['href']
|
53
|
-
nil
|
54
|
-
end
|
55
|
-
|
56
|
-
def add_post
|
57
|
-
post_form = dashboard_page.form(POST_FORM)
|
58
|
-
raise PostError, "Missing QuickPress form on users dashboard page." unless post_form
|
59
|
-
raise PostError, "A post requires a title or body." if !@title && !@body
|
60
|
-
post_form = build_post(post_form)
|
61
|
-
build_response @agent.submit(post_form, post_form.buttons.last)
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def login_page
|
67
|
-
@agent = WWW::Mechanize.new #if !@agent
|
68
|
-
@agent.get @login_url
|
69
|
-
end
|
70
|
-
|
71
|
-
def dashboard_page
|
72
|
-
page = login_page
|
73
|
-
login_form = page.form(LOGIN_FORM)
|
74
|
-
if login_form
|
75
|
-
login_form.log = @username
|
76
|
-
login_form.pwd = @password
|
77
|
-
page = @agent.submit login_form
|
78
|
-
end
|
79
|
-
page
|
80
|
-
end
|
81
|
-
|
82
|
-
def logged_into? page
|
83
|
-
!page.search(IS_ADMIN).empty?
|
84
|
-
end
|
85
|
-
|
86
|
-
def build_post f
|
87
|
-
f.post_title = @title
|
88
|
-
f.content = @body
|
89
|
-
f.tags_input = @tags
|
90
|
-
f
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_response page
|
94
|
-
return true
|
95
|
-
#get preview url & if it's not there send back error response
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|
data/test/test_wordpress.rb
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
require "test/unit"
|
2
|
-
require "wordpress"
|
3
|
-
#
|
4
|
-
|
5
|
-
######
|
6
|
-
# USED TO TEST PRIVATE METHODS
|
7
|
-
class Class
|
8
|
-
def private_methods
|
9
|
-
m = self.private_instance_methods
|
10
|
-
self.class_eval { public(*m) }
|
11
|
-
yield
|
12
|
-
self.class_eval { private(*m) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
class TestWordpress < Test::Unit::TestCase
|
18
|
-
|
19
|
-
def setup
|
20
|
-
@u = 'jordandobson'
|
21
|
-
@p = 'password'
|
22
|
-
|
23
|
-
@account = Wordpress::Client.new @u, @p
|
24
|
-
@account_bad = Wordpress::Client.new @u, 'x'
|
25
|
-
@account_invalid_login_page = Wordpress::Client.new @u, @p, 'http://is.gd/wp-login.php'
|
26
|
-
|
27
|
-
@admin_pg = Nokogiri::HTML( Nokogiri::HTML::Builder.new { html { body( :class => 'wp-admin') } }.to_html )
|
28
|
-
@login_pg = Nokogiri::HTML( Nokogiri::HTML::Builder.new { html { body( :class => 'login' ) } }.to_html )
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_sets_account_info_on_initialize
|
32
|
-
actual = Wordpress::Client.new @u, @p
|
33
|
-
assert_equal [@u, @p], [actual.username, actual.password]
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_raises_if_username_is_blank
|
37
|
-
assert_raise Wordpress::AuthError do
|
38
|
-
Wordpress::Client.new "", @p
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_raises_if_password_is_blank
|
43
|
-
assert_raise Wordpress::AuthError do
|
44
|
-
Wordpress::Client.new @u, ""
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_raises_if_password_is_not_srting
|
49
|
-
assert_raise Wordpress::AuthError do
|
50
|
-
Wordpress::Client.new @u, 00
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_raises_if_username_is_not_srting
|
55
|
-
assert_raise Wordpress::AuthError do
|
56
|
-
Wordpress::Client.new 00, @p
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_login_url_uses_default_if_witheld
|
61
|
-
assert_equal Wordpress::Client::DEFAULT_URL, @account.login_url
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_uses_url_does_not_raise
|
65
|
-
assert_equal 'http://is.gd/wp-login.php', @account_invalid_login_page.login_url
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_raises_on_bad_login_url
|
69
|
-
assert_raise Wordpress::AuthError do
|
70
|
-
Wordpress::Client.new @u, @p, 'http://bad.login/url.php'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_login_page_is_valid
|
75
|
-
actual = Wordpress::Client.new @u, @p
|
76
|
-
assert_equal true, actual.valid_login_page?
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_login_page_is_invalid
|
80
|
-
assert_equal false, @account_invalid_login_page.valid_login_page?
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_is_a_valid_user
|
84
|
-
assert_equal true, @account.valid_user?
|
85
|
-
end
|
86
|
-
|
87
|
-
def test_is_an_invalid_user
|
88
|
-
assert_equal false, @account_bad.valid_user?
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_is_a_valid_hosted_user
|
92
|
-
account = Wordpress::Client.new('nonbreakablespace', 'Password1', 'http://blog.nonbreakablespace.com/wp-login.php')
|
93
|
-
assert_equal true, account.valid_user?
|
94
|
-
end
|
95
|
-
def test_returns_blog_url
|
96
|
-
expected = 'http://blog.nonbreakablespace.com/'
|
97
|
-
account = Wordpress::Client.new('nonbreakablespace', 'Password1', "#{expected}wp-login.php")
|
98
|
-
assert_equal expected, account.blog_url
|
99
|
-
# Need to stub dashboard_page
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_returns_blog_url_bad
|
103
|
-
account = Wordpress::Client.new(@u, @p, 'http://is.gd/wp-login.php')
|
104
|
-
assert_nil account.blog_url
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_private_logged_in_is_true
|
108
|
-
Wordpress::Client.private_methods { assert_equal true, @account.logged_into?(@admin_pg) }
|
109
|
-
end
|
110
|
-
|
111
|
-
def test_private_logged_in_is_false
|
112
|
-
Wordpress::Client.private_methods { assert_equal false, @account.logged_into?(@login_pg) }
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_add_post_raises_without_title_or_body
|
116
|
-
assert_raise Wordpress::PostError do
|
117
|
-
@account.add_post
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_add_post_raises_without_post_form
|
122
|
-
assert_raise Wordpress::PostError do
|
123
|
-
@account_bad.add_post
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_add_post_adds_post
|
128
|
-
@account.title = Time.now
|
129
|
-
@account.body = "updated next"
|
130
|
-
@account.add_post
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|