presser 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.presser +11 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +37 -0
- data/Rakefile +23 -0
- data/bin/presser +10 -0
- data/lib/blog_post.rb +134 -0
- data/lib/local_file.rb +44 -0
- data/lib/presser/version.rb +3 -0
- data/lib/presser.rb +117 -0
- data/lib/presser_doc.rb +43 -0
- data/lib/presser_opts.rb +177 -0
- data/lib/presser_xmlrpc.rb +172 -0
- data/post_template.txt +12 -0
- data/presser.gemspec +23 -0
- data/spec/dont_git_this.rb +14 -0
- data/spec/post_spec.rb +143 -0
- data/spec/presser_doc_spec.rb +12 -0
- data/spec/presser_opts_spec.rb +38 -0
- data/spec/presser_spec.rb +14 -0
- data/spec/test_presser_net_spec.rb +24 -0
- data/spec/yaml_spec.rb +64 -0
- metadata +106 -0
data/.gitignore
ADDED
data/.presser
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm gemset use presser
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Presser
|
2
|
+
|
3
|
+
Presser is a command-line program to post and upload to a Wordpress blog.
|
4
|
+
|
5
|
+
It's pretty raw, but it (barely) scratches my itch, so it might not get updated for a bit.
|
6
|
+
|
7
|
+
To run it: either install it as a gem ("rake -T" to see the rake options to do that) and run "presser", or run the bin/presser script.
|
8
|
+
|
9
|
+
The command "presser -h" will get you a list of options.
|
10
|
+
|
11
|
+
## Configuration
|
12
|
+
|
13
|
+
In order to talk to WordPress, presser needs to talk to your WordPress's xmlrpc.php file, and will need your username and password.
|
14
|
+
|
15
|
+
You can provide those on the command line, or make a .presser file in your home directoru. Running:
|
16
|
+
|
17
|
+
presser -c
|
18
|
+
|
19
|
+
will get presser to create a sample .presser file for you. You will then need to edit it, but it's a simple file, and should be self-explanatory. The sample file will contain more options than presser will actually read. (Like I said, it's pretty raw.) But just set the username, password, and url, and either ignore or delete the rest.
|
20
|
+
|
21
|
+
## Uploading files
|
22
|
+
|
23
|
+
Presser will upload a file for you. Use this command:
|
24
|
+
|
25
|
+
presser -U filename
|
26
|
+
|
27
|
+
Presser will upload the file and print out the url where the uploaded file can be found.
|
28
|
+
|
29
|
+
## New posts
|
30
|
+
|
31
|
+
Use the post_template.txt file as a template for new posts. Shocker.
|
32
|
+
|
33
|
+
Copy the file and edit it. Then post it with:
|
34
|
+
|
35
|
+
presser -o filename
|
36
|
+
|
37
|
+
Edit it some more. Update the post with the same command.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
namespace :specs do
|
5
|
+
Rspec = "rspec --tty --color"
|
6
|
+
|
7
|
+
desc "Run all specs"
|
8
|
+
task :all do |t|
|
9
|
+
sh "#{Rspec} spec/*.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run doc specs"
|
13
|
+
task :docs do |t|
|
14
|
+
sh "#{Rspec} spec/presser_doc_spec.rb"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run config specs"
|
18
|
+
task :config do |t|
|
19
|
+
sh "#{Rspec} spec/yaml_spec.rb"
|
20
|
+
sh "#{Rspec} spec/presser_opts_spec.rb"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/bin/presser
ADDED
data/lib/blog_post.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
module Presser
|
3
|
+
class BlogPost
|
4
|
+
attr_accessor :title, :body, :link, :categories, :postid, :post_status
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@categories = []
|
8
|
+
@post_status = ""
|
9
|
+
@postid = "-1"
|
10
|
+
@link = "http://www.google.com"
|
11
|
+
@reading_header = true
|
12
|
+
@post_file_items = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_filename filename
|
16
|
+
bp = BlogPost.new
|
17
|
+
bp.load_from_file filename
|
18
|
+
bp
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.make_file_from_struct presserDoc
|
22
|
+
File.open(BlogPost.new_post_filename, "w") do |f|
|
23
|
+
f.puts presserDoc.to_s
|
24
|
+
end
|
25
|
+
BlogPost.new_post_filename
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_from_file filename
|
29
|
+
parse_all_lines filename
|
30
|
+
@title = @post_file_items["title"] || ""
|
31
|
+
@body = @post_file_items["body"] || ""
|
32
|
+
@link = @post_file_items["link"] || ""
|
33
|
+
@postid = @post_file_items["postid"] || ""
|
34
|
+
end
|
35
|
+
|
36
|
+
# get the values from a metaWeblog struct
|
37
|
+
def parse_struct struct
|
38
|
+
@title = struct["title"] || ""
|
39
|
+
@body = struct["body"] || ""
|
40
|
+
@link = struct["link"] || ""
|
41
|
+
@postid = struct["postid"] || ""
|
42
|
+
@post_status = struct["post_status"] || ""
|
43
|
+
@categories = struct["categories"] || ""
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_string str
|
47
|
+
lines = str.split("\n")
|
48
|
+
parse_all_lines lines
|
49
|
+
end
|
50
|
+
|
51
|
+
# Read through a file
|
52
|
+
# put all the items describing its post into @post_file_items
|
53
|
+
def parse_all_lines filename
|
54
|
+
lines = []
|
55
|
+
File.readlines(filename).each do |line|
|
56
|
+
lines << line
|
57
|
+
end
|
58
|
+
parse_array_of_lines lines
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_array_of_lines lines
|
62
|
+
body = ""
|
63
|
+
lines.each do |line|
|
64
|
+
line = line.strip
|
65
|
+
if @reading_header
|
66
|
+
parse_header_line line
|
67
|
+
else
|
68
|
+
body << line << "\n"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
# puts "post_file_items: #{@post_file_items}"
|
72
|
+
@title = @post_file_items["title"] || "Default title"
|
73
|
+
@post_file_items["body"] = body
|
74
|
+
end
|
75
|
+
|
76
|
+
def parse_header_line line
|
77
|
+
if line == "# End of header"
|
78
|
+
@reading_header = false
|
79
|
+
else
|
80
|
+
if line =~ /(.*):(.*)/
|
81
|
+
# puts "match: #{line}"
|
82
|
+
key = $1.strip
|
83
|
+
val = $2.strip
|
84
|
+
@post_file_items[key] = val
|
85
|
+
else
|
86
|
+
# puts "No match: #{line}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
str = %Q{# Beginning of header
|
93
|
+
title: #{@title}
|
94
|
+
link: #{@link}
|
95
|
+
categories: #{@categories}
|
96
|
+
postid: #{@postid}
|
97
|
+
post_status: #{@post_status}
|
98
|
+
# End of header
|
99
|
+
#{@body}}
|
100
|
+
end
|
101
|
+
|
102
|
+
def save_new_post
|
103
|
+
str = %Q{# Beginning of header
|
104
|
+
title: #{@title}
|
105
|
+
categories: #{@categories}
|
106
|
+
# End of header
|
107
|
+
|
108
|
+
}
|
109
|
+
# File.open(BlogPost.new_post_filename, "w") { |file| file.puts str }
|
110
|
+
f = File.open(BlogPost.new_post_filename, "w")
|
111
|
+
f.puts str
|
112
|
+
f.flush
|
113
|
+
f.close
|
114
|
+
BlogPost.new_post_filename
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.new_post_filename
|
118
|
+
prefix = "presser_post_"
|
119
|
+
@numfiles ||= Dir.glob(prefix + "*").length
|
120
|
+
@new_file_name ||= prefix + (@numfiles + 1).to_s + ".md"
|
121
|
+
end
|
122
|
+
|
123
|
+
def save_to_file filename
|
124
|
+
File.open(filename, "w") { |file| file.puts to_s }
|
125
|
+
end
|
126
|
+
|
127
|
+
def dumpself
|
128
|
+
puts "Dumping self"
|
129
|
+
puts "title: #{@title}"
|
130
|
+
puts "body: #{@body}"
|
131
|
+
puts "link: #{@link}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/local_file.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Presser
|
3
|
+
class LocalFile
|
4
|
+
attr_accessor :title, :body, :params
|
5
|
+
def initialize filename
|
6
|
+
@in_header = true
|
7
|
+
@body = ""
|
8
|
+
@filename = filename
|
9
|
+
@params = {}
|
10
|
+
parse_all_lines
|
11
|
+
# puts "The title: #{@title}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_all_lines
|
15
|
+
File.readlines(@filename).each do |line|
|
16
|
+
line = line.strip
|
17
|
+
if @in_header
|
18
|
+
parse_line line
|
19
|
+
else
|
20
|
+
# puts "Body: '#{line}'"
|
21
|
+
body << line << "\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
# puts "params: #{@params}"
|
25
|
+
@title = params["title"] || "Default title"
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_line line
|
29
|
+
if line == "# End of header"
|
30
|
+
@in_header = false
|
31
|
+
else
|
32
|
+
if line =~ /(.*):(.*)/
|
33
|
+
# puts "match: #{line}"
|
34
|
+
key = $1.strip
|
35
|
+
val = $2.strip
|
36
|
+
@params[key] = val
|
37
|
+
else
|
38
|
+
# puts "No match: #{line}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/presser.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'presser_opts'
|
2
|
+
require 'net/http'
|
3
|
+
require 'xmlrpc/client'
|
4
|
+
require 'presser_xmlrpc'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Presser
|
8
|
+
|
9
|
+
class Presser
|
10
|
+
CONFIGFILE = "#{ENV['HOME']}/.presser"
|
11
|
+
def initialize(args, filename=nil)
|
12
|
+
@args = args
|
13
|
+
|
14
|
+
filename ||= CONFIGFILE
|
15
|
+
load_config_file filename
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_config_file filename
|
19
|
+
@options = PresserOpts.new Array.new @args
|
20
|
+
if File.exists? filename
|
21
|
+
@options.load_file filename
|
22
|
+
# @options.parse Array.new @args
|
23
|
+
end
|
24
|
+
@options
|
25
|
+
end
|
26
|
+
|
27
|
+
def parsed_options
|
28
|
+
@options.parsed
|
29
|
+
end
|
30
|
+
|
31
|
+
def response
|
32
|
+
@response.body
|
33
|
+
end
|
34
|
+
|
35
|
+
def do_getPostStatus
|
36
|
+
rpc = PresserXmlrpc.new @options.parsed
|
37
|
+
result = rpc.call_xmlrpc rpc.options_for_getPostStatus
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_post postid
|
42
|
+
rpc = PresserXmlrpc.new @options.parsed
|
43
|
+
struct = rpc.get_post postid
|
44
|
+
filename = BlogPost.make_file_from_struct struct
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete_post postid
|
48
|
+
rpc = PresserXmlrpc.new @options.parsed
|
49
|
+
rpc.delete_post postid
|
50
|
+
end
|
51
|
+
|
52
|
+
def run
|
53
|
+
|
54
|
+
# if @options.parsed.use_config_file
|
55
|
+
# load_config_file @options.parsed.config_file_name
|
56
|
+
# end
|
57
|
+
|
58
|
+
rpc = PresserXmlrpc.new @options.parsed
|
59
|
+
|
60
|
+
if @options.parsed.upload_file
|
61
|
+
puts rpc.upload_file @options.parsed.file_to_upload
|
62
|
+
end
|
63
|
+
|
64
|
+
if @options.parsed.get_post
|
65
|
+
filename = get_post @options.parsed.postid
|
66
|
+
run_vim filename
|
67
|
+
end
|
68
|
+
|
69
|
+
if @options.parsed.post_file
|
70
|
+
filename = @options.parsed.file_to_post
|
71
|
+
|
72
|
+
postid = rpc.post_file filename
|
73
|
+
# When doing a new pots, we want to get the info after
|
74
|
+
# WP creates the post ... mostly, we want to put the
|
75
|
+
# postid into our local source file.
|
76
|
+
# The get_post call throws an exception if we're
|
77
|
+
# just updating a post, rather than doing a new post.
|
78
|
+
# But in that case, we don't need to get the post id,
|
79
|
+
# so we can safely ignore the exception.
|
80
|
+
begin
|
81
|
+
struct = rpc.get_post postid
|
82
|
+
File.open(filename, "w") { |file| file.puts struct.to_s }
|
83
|
+
rescue
|
84
|
+
end
|
85
|
+
|
86
|
+
if not postid == true
|
87
|
+
puts postid
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if @options.parsed.make_new_post
|
92
|
+
bp = BlogPost.new
|
93
|
+
filename = bp.save_new_post
|
94
|
+
run_vim filename
|
95
|
+
end
|
96
|
+
|
97
|
+
if @options.parsed.make_config_file
|
98
|
+
puts @options.save_to_file
|
99
|
+
end
|
100
|
+
|
101
|
+
if @options.parsed.delete_post
|
102
|
+
delete_post @options.parsed.postid
|
103
|
+
end
|
104
|
+
|
105
|
+
if @options.parsed.show_config
|
106
|
+
puts @options.to_yaml
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def run_vim filename
|
111
|
+
return unless @options.parsed.use_vim
|
112
|
+
puts "run vim with file: #{filename}"
|
113
|
+
system("mvim #{filename}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
data/lib/presser_doc.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module Presser
|
4
|
+
|
5
|
+
class PresserDoc
|
6
|
+
attr_accessor :categories, :postid, :post_status
|
7
|
+
def initialize *args
|
8
|
+
@title = args[0] || "This is the title"
|
9
|
+
@link = args[1] || "http://www.google.com"
|
10
|
+
@description = args[2] || "This is the description"
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
str = %Q{# Beginning of header
|
15
|
+
title: #{@title}
|
16
|
+
link: #{@link}
|
17
|
+
postid: #{postid}
|
18
|
+
post_status: #{post_status}
|
19
|
+
# End of header
|
20
|
+
#{@description}}
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_doc
|
24
|
+
doc = REXML::Document.new
|
25
|
+
item = doc.add_element "struct"
|
26
|
+
title = item.add_element 'title'
|
27
|
+
link = item.add_element "link"
|
28
|
+
description = item.add_element "description"
|
29
|
+
|
30
|
+
description.text = @description
|
31
|
+
title.text = @title
|
32
|
+
link.text = @link
|
33
|
+
|
34
|
+
# str = ""
|
35
|
+
# doc.write(str, 2)
|
36
|
+
# puts str
|
37
|
+
str = ""
|
38
|
+
doc.write str
|
39
|
+
str
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/presser_opts.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
# Usage: presser [options]
|
6
|
+
# -h, --help Print out this message
|
7
|
+
# -c, --configfile [STRING] create a config file
|
8
|
+
# -d, --deletepost INTEGER delete a post
|
9
|
+
# -g, --getpost INTEGER delete a post
|
10
|
+
# -o, --post STRING Post the named file
|
11
|
+
# -p, --password STRING WordPress admin password
|
12
|
+
# -u, --username STRING WordPress admin username
|
13
|
+
# -U, --upload STRING Upload a file
|
14
|
+
# -r, --url STRING WordPress xmlrpc url
|
15
|
+
|
16
|
+
|
17
|
+
module Presser
|
18
|
+
class PresserOpts
|
19
|
+
def initialize(args, path="")
|
20
|
+
@parsed = OpenStruct.new
|
21
|
+
parse(args)
|
22
|
+
if not path == ""
|
23
|
+
@parsed.config_file_name = path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_yaml yaml_string
|
28
|
+
# new_opts = PresserOpts.new []
|
29
|
+
yaml = YAML::load(yaml_string)
|
30
|
+
|
31
|
+
@parsed.username = yaml["username"]
|
32
|
+
@parsed.password = yaml["password"]
|
33
|
+
@parsed.url = yaml["url"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_yaml
|
37
|
+
str = "verbose: #{parsed.verbose}\n"
|
38
|
+
str << "username: #{parsed.username}\n"
|
39
|
+
str << "password: #{parsed.password}\n"
|
40
|
+
str << "url: #{parsed.url}\n"
|
41
|
+
str << "file_to_upload: #{parsed.file_to_upload}\n"
|
42
|
+
str << "upload_file: #{parsed.upload_file}\n"
|
43
|
+
str << "pretend: #{parsed.pretend}\n"
|
44
|
+
str << "post_file: #{parsed.post_file}\n"
|
45
|
+
str << "file_to_post: #{parsed.file_to_post}\n"
|
46
|
+
str << "make_config_file: #{parsed.make_config_file}\n"
|
47
|
+
str << "config_file_name: #{parsed.config_file_name}\n"
|
48
|
+
str
|
49
|
+
end
|
50
|
+
|
51
|
+
def config_file_name= filename
|
52
|
+
@parsed.config_file_name = filename
|
53
|
+
end
|
54
|
+
|
55
|
+
def parsed= val
|
56
|
+
@parsed = val
|
57
|
+
end
|
58
|
+
|
59
|
+
def parsed
|
60
|
+
@parsed
|
61
|
+
end
|
62
|
+
|
63
|
+
def save_to_file
|
64
|
+
File.open(@parsed.config_file_name, 'w+') do |file|
|
65
|
+
file.puts to_yaml
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_file filename
|
70
|
+
yaml = File.new(filename).read
|
71
|
+
load_yaml yaml
|
72
|
+
end
|
73
|
+
|
74
|
+
def config_file_contents
|
75
|
+
str = ""
|
76
|
+
str << "username: #{@parsed.username}\n"
|
77
|
+
str << "password: #{@parsed.password}\n"
|
78
|
+
str << "url: #{@parsed.url}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse(args)
|
82
|
+
@parsed.verbose ||= false
|
83
|
+
@parsed.username ||= "WaltKelly"
|
84
|
+
@parsed.password ||= "pogo"
|
85
|
+
@parsed.url ||= "http://wordpress/wp/xmlrpc.php"
|
86
|
+
@parsed.file_to_upload ||= ""
|
87
|
+
@parsed.upload_file ||= false
|
88
|
+
@parsed.pretend ||= false
|
89
|
+
@parsed.post_file ||= false
|
90
|
+
@parsed.file_to_post ||= ""
|
91
|
+
@parsed.make_config_file ||= false
|
92
|
+
@parsed.make_new_post ||= false
|
93
|
+
@parsed.use_config_file ||= true
|
94
|
+
@parsed.config_file_name ||= "#{ENV['HOME']}/.presser"
|
95
|
+
@parsed.delete_post ||= false
|
96
|
+
@parsed.get_post ||= false
|
97
|
+
@parsed.postid ||= ""
|
98
|
+
@parsed.show_config ||= false
|
99
|
+
@parsed.use_vim ||= false
|
100
|
+
|
101
|
+
@optionParser = OptionParser.new do |opts|
|
102
|
+
opts.banner = "Usage: presser [options]"
|
103
|
+
# opts.separator = ""
|
104
|
+
|
105
|
+
opts.on('-h', "--help", "Print out this message") do |url|
|
106
|
+
puts opts
|
107
|
+
end
|
108
|
+
|
109
|
+
opts.on("-c", "--configfile [STRING]", "create a config file") do |filename|
|
110
|
+
@parsed.make_config_file = true
|
111
|
+
if filename
|
112
|
+
@parsed.config_file_name = filename.strip
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
opts.on("-d", "--deletepost INTEGER", "delete a post") do |postid|
|
117
|
+
@parsed.delete_post = true
|
118
|
+
@parsed.postid = postid
|
119
|
+
end
|
120
|
+
|
121
|
+
opts.on("-f", "--useconfigfile [STRING]", "use a config file") do |filename|
|
122
|
+
@parsed.use_config_file = true
|
123
|
+
if filename
|
124
|
+
@parsed.config_file_name = filename.strip
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
opts.on("-g", "--getpost INTEGER", "get a post") do |postid|
|
129
|
+
@parsed.get_post = true
|
130
|
+
@parsed.postid = postid
|
131
|
+
end
|
132
|
+
|
133
|
+
opts.on("-n", "--new", "Make a new blank post file") do |postid|
|
134
|
+
@parsed.make_new_post = true
|
135
|
+
@parsed.postid = postid
|
136
|
+
end
|
137
|
+
|
138
|
+
opts.on("-o", "--post STRING", "Post the named file") do |filename|
|
139
|
+
@parsed.post_file = true
|
140
|
+
@parsed.file_to_post = filename.strip
|
141
|
+
end
|
142
|
+
|
143
|
+
opts.on('-s', '--show', 'Show the current configuration') do |password|
|
144
|
+
puts "PresserOpts: show config is true"
|
145
|
+
@parsed.show_config = true
|
146
|
+
end
|
147
|
+
|
148
|
+
opts.on('-p', '--password STRING', 'WordPress admin password') do |password|
|
149
|
+
@parsed.password = password.strip
|
150
|
+
end
|
151
|
+
|
152
|
+
opts.on('-u', '--username STRING', 'WordPress admin username') do |username|
|
153
|
+
@parsed.username = username.strip
|
154
|
+
end
|
155
|
+
|
156
|
+
opts.on('-U', '--upload STRING', 'Upload a file') do |filename|
|
157
|
+
@parsed.upload_file = true
|
158
|
+
@parsed.file_to_upload = filename.strip
|
159
|
+
end
|
160
|
+
|
161
|
+
opts.on('-r STRING', '--url STRING', 'WordPress xmlrpc url') do |url|
|
162
|
+
@parsed.url = url.strip
|
163
|
+
end
|
164
|
+
|
165
|
+
opts.on('-v', '--vim', 'Open vim') do |url|
|
166
|
+
@parsed.use_vim = true
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
@optionParser.parse!(args)
|
172
|
+
@parsed
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'xmlrpc/client'
|
2
|
+
require 'local_file'
|
3
|
+
require 'blog_post'
|
4
|
+
require 'presser_doc'
|
5
|
+
|
6
|
+
module Presser
|
7
|
+
|
8
|
+
class PresserXmlrpc
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
@opt = opts
|
12
|
+
end
|
13
|
+
|
14
|
+
def call_xmlrpc(opts)
|
15
|
+
# puts "call_xmlrpc: opts = #{opts}"
|
16
|
+
server = XMLRPC::Client.new2(opts[:url])
|
17
|
+
result = server.call(opts[:method], opts[:options])
|
18
|
+
end
|
19
|
+
|
20
|
+
def blog_id
|
21
|
+
# Return the id for the first blog
|
22
|
+
@blogid ||= getUsersBlogs[0]["blogid"]
|
23
|
+
@blogid
|
24
|
+
end
|
25
|
+
|
26
|
+
def getUsersBlogs
|
27
|
+
options = { :url => @opt.url, :method => "wp.getUsersBlogs",
|
28
|
+
:options => [@opt.username, @opt.password] }
|
29
|
+
call_xmlrpc options
|
30
|
+
end
|
31
|
+
def getPostStatusList
|
32
|
+
options = { :url => @opt.url, :method => "wp.getPostStatusList",
|
33
|
+
:options => [blog_id, @opt.username, @opt.password] }
|
34
|
+
call_xmlrpc options
|
35
|
+
end
|
36
|
+
def getTags
|
37
|
+
options = { :url => @opt.url, :method => "wp.getTags",
|
38
|
+
:options => [blog_id, @opt.username, @opt.password] }
|
39
|
+
call_xmlrpc options
|
40
|
+
end
|
41
|
+
def getRecentPosts
|
42
|
+
options = { :url => @opt.url, :method => "metaWeblog.getRecentPosts",
|
43
|
+
:options => [blog_id, @opt.username, @opt.password] }
|
44
|
+
result = call_xmlrpc options
|
45
|
+
result
|
46
|
+
end
|
47
|
+
def getPageList
|
48
|
+
options = { :url => @opt.url, :method => "wp.getPageList",
|
49
|
+
:options => [blog_id, @opt.username, @opt.password] }
|
50
|
+
result = call_xmlrpc options
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def upload_file filename
|
55
|
+
struct = {
|
56
|
+
"name" => File.basename(filename),
|
57
|
+
"type" => file_type_from_name(filename),
|
58
|
+
"bits" => encode64(filename),
|
59
|
+
"overwrite" => false
|
60
|
+
}
|
61
|
+
options = { :url => @opt.url, :method => "wp.uploadFile",
|
62
|
+
:options => [blog_id, @opt.username, @opt.password, struct] }
|
63
|
+
result = call_xmlrpc options
|
64
|
+
result = result["url"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def file_type_from_name filename
|
68
|
+
ext = File.extname(filename).sub(/\./, '').downcase
|
69
|
+
|
70
|
+
# http://www.w3schools.com/media/media_mimeref.asp
|
71
|
+
types = {
|
72
|
+
"txt" => "text/plain",
|
73
|
+
"jpg" => "image/jpeg",
|
74
|
+
"jpeg" => "image/jpeg",
|
75
|
+
"png" => "image/png",
|
76
|
+
"gif" => "image/gif",
|
77
|
+
"tif" => "image/tif",
|
78
|
+
"tiff" => "image/tiff",
|
79
|
+
"pdf" => "application/pdf",
|
80
|
+
"doc" => "application/msword",
|
81
|
+
"rtf" => "application/rtf",
|
82
|
+
"xls" => "application/vnd.ms-excel",
|
83
|
+
"mp3" => "audo/mpeg"
|
84
|
+
}
|
85
|
+
types[ext]
|
86
|
+
end
|
87
|
+
|
88
|
+
def encode64 filename
|
89
|
+
# http://perfectionlabstips.wordpress.com/2008/11/20/encoding-files-to-base64-representation-directly-from-command-line/
|
90
|
+
# ruby -e 'print [IO.read(File.join(Dir.pwd, ARGV[0]))].pack("m")'
|
91
|
+
# XMLRPC::Base64.new([IO.read(filename)].pack("m0"))
|
92
|
+
# http://blog.bitcrowd.net/upload-a-file-to-a-wordpress-blog-via-xml-rpc-wp-uploadfile/
|
93
|
+
XMLRPC::Base64.new(File.open(filename).read)
|
94
|
+
end
|
95
|
+
|
96
|
+
def post_file(filename, publish = true)
|
97
|
+
bp = BlogPost.from_filename filename
|
98
|
+
|
99
|
+
struct = {
|
100
|
+
"title" => bp.title,
|
101
|
+
"link" => bp.link,
|
102
|
+
"categories" => [],
|
103
|
+
#"categories" => bp.categories,
|
104
|
+
# "postid" => bp.postid,
|
105
|
+
"post_status" => bp.post_status,
|
106
|
+
"description" => bp.body
|
107
|
+
}
|
108
|
+
if bp.postid == ""
|
109
|
+
options = { :url => @opt.url, :method => "metaWeblog.newPost",
|
110
|
+
:options => [blog_id, @opt.username, @opt.password,
|
111
|
+
struct, publish] }
|
112
|
+
else
|
113
|
+
# struct["postid"] = bp.postid
|
114
|
+
options = { :url => @opt.url, :method => "metaWeblog.editPost",
|
115
|
+
:options => [bp.postid.to_i, @opt.username, @opt.password, struct, publish] }
|
116
|
+
end
|
117
|
+
postid = call_xmlrpc options
|
118
|
+
postid
|
119
|
+
end
|
120
|
+
|
121
|
+
# This returns a PresserDoc with the post contents
|
122
|
+
# I've put a sample of the struct returned by wordpress at the end of this file
|
123
|
+
def get_post(postid)
|
124
|
+
options = { :url => @opt.url, :method => "metaWeblog.getPost",
|
125
|
+
:options => [postid, @opt.username, @opt.password] }
|
126
|
+
|
127
|
+
struct = call_xmlrpc options
|
128
|
+
doc = PresserDoc.new struct["title"], struct["link"], struct["description"]
|
129
|
+
doc.categories = struct["categories"]
|
130
|
+
doc.postid = struct["postid"]
|
131
|
+
doc.post_status = struct["post_status"]
|
132
|
+
doc
|
133
|
+
end
|
134
|
+
|
135
|
+
def delete_post(postid)
|
136
|
+
options = { :url => @opt.url, :method => "blogger.deletePost",
|
137
|
+
:options => ["", postid, @opt.username, @opt.password, ""] }
|
138
|
+
|
139
|
+
result = call_xmlrpc options
|
140
|
+
result
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Struct returned by metaWeblog.getPost:
|
147
|
+
# {
|
148
|
+
# "dateCreated"=>#<XMLRPC::DateTime:0x00000100d96d80 @year=2011, @month=3, @day=5, @hour=2, @min=40, @sec=4>,
|
149
|
+
# "userid"=>"1",
|
150
|
+
# "postid"=>119,
|
151
|
+
# "description"=>"This is the body\nof the file.\n\nThis is [a link](http://www.google.com).",
|
152
|
+
# "title"=>"Put your title here",
|
153
|
+
# "link"=>"http://wordpress/wp/?p=119",
|
154
|
+
# "permaLink"=>"http://wordpress/wp/?p=119",
|
155
|
+
# "categories"=>["Uncategorized"],
|
156
|
+
# "mt_excerpt"=>"",
|
157
|
+
# "mt_text_more"=>"",
|
158
|
+
# "mt_allow_comments"=>1,
|
159
|
+
# "mt_allow_pings"=>1,
|
160
|
+
# "mt_keywords"=>"",
|
161
|
+
# "wp_slug"=>"put-your-title-here-7",
|
162
|
+
# "wp_password"=>"",
|
163
|
+
# "wp_author_id"=>"1",
|
164
|
+
# "wp_author_display_name"=>"jeff",
|
165
|
+
# "date_created_gmt"=>#<XMLRPC::DateTime:0x00000100db5ac8 @year=2011, @month=3, @day=5, @hour=2, @min=40, @sec=4>,
|
166
|
+
# "post_status"=>"publish",
|
167
|
+
# "custom_fields"=>[{"id"=>"180", "key"=>"_encloseme", "value"=>"1"}],
|
168
|
+
# "wp_post_format"=>"standard",
|
169
|
+
# "sticky"=>false
|
170
|
+
# }
|
171
|
+
#
|
172
|
+
|
data/post_template.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Beginning of header
|
2
|
+
title: A newer title
|
3
|
+
link: http://www.jeffroush.com/technotes/2011/10/23/a-newer-title/
|
4
|
+
postid: 1247
|
5
|
+
post_status: publish
|
6
|
+
# End of header
|
7
|
+
This is the body
|
8
|
+
of the file.
|
9
|
+
|
10
|
+
This is [a link](http://www.google.com).
|
11
|
+
|
12
|
+
And it works. Woo hoo!
|
data/presser.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "presser/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "presser"
|
7
|
+
s.version = Presser::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = "Jeff Roush"
|
10
|
+
s.email = "jeff@jeffroush.com"
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{A Ruby-based cli WordPress client}
|
13
|
+
s.description = %q{Nothing concrete yet -- just noodling.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "presser"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = "presser"
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
data/spec/post_spec.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'presser_xmlrpc'
|
2
|
+
require 'presser'
|
3
|
+
|
4
|
+
module Presser
|
5
|
+
|
6
|
+
# This assumes that you've created a config file with
|
7
|
+
# valid blog connection data, and that
|
8
|
+
# the string sample_post_filename specifies it.
|
9
|
+
describe BlogPost do
|
10
|
+
before(:each) do
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
delete_sample_file
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should read the source text file correctly" do
|
18
|
+
make_sample_file
|
19
|
+
bp = BlogPost.from_filename sample_post_filename
|
20
|
+
bp.title.should eql("Put your title here")
|
21
|
+
bp.postid.should eql("")
|
22
|
+
|
23
|
+
lines = sample_post_text.split("\n")
|
24
|
+
# puts lines.inspect
|
25
|
+
# Make sure that posting increases the line count
|
26
|
+
# Parse the returned string, and get the post id
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should parse a metaWeblog struct" do
|
30
|
+
bp = BlogPost.new
|
31
|
+
bp.parse_struct sample_metaWeblog_struct
|
32
|
+
bp.title.should eql("Put your title here")
|
33
|
+
# bp.postid.should eql(119)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should update the source text file" do
|
37
|
+
make_sample_file
|
38
|
+
bp_initial = BlogPost.from_filename sample_post_filename
|
39
|
+
|
40
|
+
post_sample_file
|
41
|
+
|
42
|
+
bp_result = BlogPost.from_filename sample_post_filename
|
43
|
+
|
44
|
+
bp_result.title.should eql bp_initial.title
|
45
|
+
bp_result.postid.should_not eql ""
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should delete a post when told to" do
|
49
|
+
make_sample_file
|
50
|
+
post_sample_file
|
51
|
+
bp_result = BlogPost.from_filename sample_post_filename
|
52
|
+
|
53
|
+
postid = bp_result.postid
|
54
|
+
delete_result = delete_post postid
|
55
|
+
delete_result.should be_true # always returns true. Even for failure.
|
56
|
+
|
57
|
+
null_post = get_post postid
|
58
|
+
null_post.should be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should read the config file correctly" do
|
62
|
+
make_sample_file
|
63
|
+
presser = Presser.new ["-o #{sample_post_filename}"], config_file_name
|
64
|
+
presser.parsed_options.username.should eql("jeff")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should create a new post for a new file"
|
68
|
+
|
69
|
+
def make_sample_file
|
70
|
+
File.open(sample_post_filename, "w") { |file| file.puts sample_post_text }
|
71
|
+
end
|
72
|
+
|
73
|
+
def post_sample_file
|
74
|
+
presser = Presser.new ["-o #{sample_post_filename}"], config_file_name
|
75
|
+
presser.run
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_post postid
|
79
|
+
presser = Presser.new ["-g #{postid}"], config_file_name
|
80
|
+
presser.run
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_post postid
|
84
|
+
presser = Presser.new ["-d #{postid}"], config_file_name
|
85
|
+
presser.delete_post postid
|
86
|
+
end
|
87
|
+
|
88
|
+
def delete_sample_file
|
89
|
+
`rm -f #{sample_post_filename}`
|
90
|
+
end
|
91
|
+
|
92
|
+
def sample_post_filename
|
93
|
+
"sample_post.md"
|
94
|
+
end
|
95
|
+
|
96
|
+
def sample_post_text
|
97
|
+
%Q{# Beginning of header
|
98
|
+
title: Put your title here
|
99
|
+
# End of header
|
100
|
+
|
101
|
+
This is the body
|
102
|
+
of the file.
|
103
|
+
|
104
|
+
This is [a link](http://www.google.com).
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def config_file_name
|
109
|
+
"presser_config_file.yml"
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# "dateCreated"=>#<XMLRPC::DateTime:0x00000100d96d80 @year=2011, @month=3, @day=5, @hour=2, @min=40, @sec=4>,
|
114
|
+
def sample_metaWeblog_struct
|
115
|
+
{
|
116
|
+
"dateCreated"=>"01/01/2011",
|
117
|
+
"userid"=>"1",
|
118
|
+
"description"=>"This is the body\nof the file.\n\nThis is [a link](http://www.google.com).",
|
119
|
+
"title"=>"Put your title here",
|
120
|
+
"link"=>"http://wordpress/wp/?p=119",
|
121
|
+
"permaLink"=>"http://wordpress/wp/?p=119",
|
122
|
+
"categories"=>["Uncategorized"],
|
123
|
+
"mt_excerpt"=>"",
|
124
|
+
"mt_text_more"=>"",
|
125
|
+
"mt_allow_comments"=>1,
|
126
|
+
"mt_allow_pings"=>1,
|
127
|
+
"mt_keywords"=>"",
|
128
|
+
"wp_slug"=>"put-your-title-here-7",
|
129
|
+
"wp_password"=>"",
|
130
|
+
"wp_author_id"=>"1",
|
131
|
+
"wp_author_display_name"=>"jeff",
|
132
|
+
"post_status"=>"publish",
|
133
|
+
"custom_fields"=>[{"id"=>"180", "key"=>"_encloseme", "value"=>"1"}],
|
134
|
+
"wp_post_format"=>"standard",
|
135
|
+
"sticky"=>false
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
# Struct returned by metaWeblog.getPost:
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'presser'
|
2
|
+
require 'presser_opts'
|
3
|
+
require 'dont_git_this'
|
4
|
+
|
5
|
+
describe "Presser defaults" do
|
6
|
+
before(:each) do
|
7
|
+
@pr = Presser::Presser.new([""])
|
8
|
+
@config_filename = "temp_config.txt"
|
9
|
+
`rm -f #{@config_filename}`
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have default username of WaltKelly" do
|
13
|
+
@pr.parsed_options.username.should eql('WaltKelly')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have default password of pogo" do
|
17
|
+
@pr.parsed_options.password.should eql('pogo')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have default url of my test machine" do
|
21
|
+
@pr.parsed_options.url = "http://wordpress/wp/xmlrpc.php"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should generate the correct options string for the config file" do
|
25
|
+
argv = ["-u #{Presser::NoGit.username}",
|
26
|
+
"-p #{Presser::NoGit.password}",
|
27
|
+
"-U #{Presser::NoGit.url}"]
|
28
|
+
|
29
|
+
str = %Q{username: #{Presser::NoGit.username}
|
30
|
+
password: #{Presser::NoGit.password}
|
31
|
+
url: #{Presser::NoGit.url}}
|
32
|
+
|
33
|
+
opts = Presser::PresserOpts.new argv
|
34
|
+
opts.config_file_contents.should eql(str)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'presser'
|
2
|
+
|
3
|
+
describe "Presser defaults" do
|
4
|
+
before(:each) do
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should override saved options with command line" do
|
8
|
+
pr = Presser::Presser.new(["-U foo", "-p mikey"], "presser_config_file.yml")
|
9
|
+
pr.parsed_options.url.should eql("foo")
|
10
|
+
pr.parsed_options.username.should eql("jeff")
|
11
|
+
pr.parsed_options.password.should eql("mikey")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'presser'
|
2
|
+
require 'presser_xmlrpc'
|
3
|
+
require 'dont_git_this'
|
4
|
+
|
5
|
+
describe "Presser net access" do
|
6
|
+
before(:each) do
|
7
|
+
# @pr = Presser::Presser.new(["-u #{Presser::NoGit.username}", "-p #{Presser::NoGit.password}"])
|
8
|
+
@pr = Presser::Presser.new(["-U foo", "-u mikey"], "presser_config_file.yml")
|
9
|
+
|
10
|
+
# @rpc = Presser::PresserXmlrpc.new @pr.parsed_options
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be an xmlrpc client" do
|
14
|
+
# puts "@pr: #{@pr.parsed_options.inspect}"
|
15
|
+
# @rpc.getUsersBlogs.length.should eql(1)
|
16
|
+
# @rpc.getPostStatusList.length.should eql(4)
|
17
|
+
# @rpc.getTags.length.should eql(0)
|
18
|
+
# @rpc.getPageList.length.should eql(1)
|
19
|
+
# @rpc.getRecentPosts.length.should eql(2)
|
20
|
+
# @rpc.newPost
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
data/spec/yaml_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'presser_opts'
|
2
|
+
|
3
|
+
module Presser
|
4
|
+
describe PresserOpts do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
`rm -f #{test_config_file}`
|
8
|
+
@opts = PresserOpts.from_yaml dummy_yaml
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
`rm -f #{test_config_file}`
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should restore from yaml string" do
|
16
|
+
@opts.parsed.password.should eql("foo")
|
17
|
+
end
|
18
|
+
it "should generate a yaml string" do
|
19
|
+
@opts.to_yaml.should eql(dummy_yaml)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should save the config to a file" do
|
23
|
+
|
24
|
+
@opts.parsed.config_file_name.should eql(test_config_file)
|
25
|
+
File.exists?(@opts.parsed.config_file_name).should be_false
|
26
|
+
@opts.save_to_file
|
27
|
+
File.exists?(@opts.parsed.config_file_name).should be_true
|
28
|
+
|
29
|
+
File.new(test_config_file).read.should eql dummy_yaml
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should load from a config file" do
|
33
|
+
@opts.save_to_file
|
34
|
+
opts2 = PresserOpts.from_file test_config_file
|
35
|
+
|
36
|
+
@opts.parsed.config_file_name.should eql(opts2.parsed.config_file_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# ******************************************************
|
41
|
+
# Define some strings for testing
|
42
|
+
#
|
43
|
+
def test_config_file
|
44
|
+
"temp_config_file.txt"
|
45
|
+
end
|
46
|
+
|
47
|
+
def dummy_yaml
|
48
|
+
%Q{verbose: false
|
49
|
+
username: WaltKelly
|
50
|
+
password: foo
|
51
|
+
url: http://wordpress/wp/xmlrpc.php
|
52
|
+
file_to_upload:
|
53
|
+
upload_file: false
|
54
|
+
pretend: false
|
55
|
+
post_file: false
|
56
|
+
file_to_post:
|
57
|
+
make_config_file: false
|
58
|
+
config_file_name: #{test_config_file}
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: presser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jeff Roush
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-10-23 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Nothing concrete yet -- just noodling.
|
35
|
+
email: jeff@jeffroush.com
|
36
|
+
executables:
|
37
|
+
- presser
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .presser
|
45
|
+
- .rvmrc
|
46
|
+
- Gemfile
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- bin/presser
|
50
|
+
- lib/blog_post.rb
|
51
|
+
- lib/local_file.rb
|
52
|
+
- lib/presser.rb
|
53
|
+
- lib/presser/version.rb
|
54
|
+
- lib/presser_doc.rb
|
55
|
+
- lib/presser_opts.rb
|
56
|
+
- lib/presser_xmlrpc.rb
|
57
|
+
- post_template.txt
|
58
|
+
- presser.gemspec
|
59
|
+
- spec/dont_git_this.rb
|
60
|
+
- spec/post_spec.rb
|
61
|
+
- spec/presser_doc_spec.rb
|
62
|
+
- spec/presser_opts_spec.rb
|
63
|
+
- spec/presser_spec.rb
|
64
|
+
- spec/test_presser_net_spec.rb
|
65
|
+
- spec/yaml_spec.rb
|
66
|
+
homepage: ""
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project: presser
|
95
|
+
rubygems_version: 1.8.11
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: A Ruby-based cli WordPress client
|
99
|
+
test_files:
|
100
|
+
- spec/dont_git_this.rb
|
101
|
+
- spec/post_spec.rb
|
102
|
+
- spec/presser_doc_spec.rb
|
103
|
+
- spec/presser_opts_spec.rb
|
104
|
+
- spec/presser_spec.rb
|
105
|
+
- spec/test_presser_net_spec.rb
|
106
|
+
- spec/yaml_spec.rb
|