shabng 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/DOC/CommandRef.rdoc +60 -0
  2. data/LICENSE +27 -0
  3. data/README +30 -0
  4. data/bin/shabng +140 -0
  5. data/lib/post.rb +113 -0
  6. data/shabng.gemspec +55 -0
  7. metadata +132 -0
@@ -0,0 +1,60 @@
1
+ = Using shabng
2
+
3
+ Shabng is a command line client for accessing the blogging service at http://shabng.com. Visit the site to sign up for a free account and create your first blog. Once done, you'll be given an API key; you'll use this to access the service from any Ruby-fied console.
4
+
5
+ == Installing Shabng
6
+
7
+ Currently only available as a Ruby Gem, run:
8
+
9
+ sudo gem install shabng
10
+
11
+ == Initial setup
12
+
13
+ Simply run the command, and you'll be guided through the setup steps:
14
+
15
+ shabng
16
+
17
+ You'll be asked to enter the API key, and to choose your editing app.
18
+
19
+ == Creating a new post
20
+
21
+ shabng new
22
+
23
+ You'll be prompted to give your new post a title. Your editor will then open, and you can write your post. Save and close the document, and Shabng will save it on the server with a Draft status (unpublished).
24
+
25
+ == Editing a post
26
+
27
+ Shabng lets you edit posts based on an action, followed by an ID number to act upon. The process involves first getting the ID you want. If you're editing a post you just wrote, the *new* action responds with the ID so you can proceed immediately. Otherwise, you can use the list command:
28
+
29
+ shabng list
30
+
31
+ And you'll see a list of all your posts. Now, when editing, you can choose the attribute to edit (currently title, body, pubdate and categories). Here are a few examples:
32
+
33
+ shabng edit title 3
34
+ shabng edit body 2
35
+ shabng edit pubdate 4
36
+ shabng edit categories 1
37
+
38
+ Just follow the instructions to complete the steps.
39
+
40
+ == Going live with a post
41
+
42
+ When you're ready to go live with your post, issue the push command:
43
+
44
+ shabng push 3
45
+
46
+ if you change your mind, use the pull command:
47
+
48
+ shabng pull 3
49
+
50
+ == Managing Categories
51
+
52
+ You can create the categories that you attach to your post. For example:
53
+
54
+ shabng new category
55
+
56
+ Follow the prompt to create a new category name.
57
+
58
+ == Support
59
+
60
+ If you need further assistance, visit http://shabng.com.
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2010, Aaron Vegh
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the author/s, nor the names of the project's
15
+ contributors may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,30 @@
1
+ = Shabang#!
2
+
3
+ Shabang is a blogging service for those who prefer to blog from the command line. Sign up for a free account at http://shabng.com. Once you've created your account and picked a name for your blog, you'll get an API key to interact with that blog using this command line program.
4
+
5
+ Shabang is written in Ruby, and uses the rest-client library to interact with the web service. You may modify this code, or re-implement it in other languages if you wish; it's presented as-is for your hacking pleasure.
6
+
7
+ == Authors
8
+
9
+ * Aaron Vegh (aaron@innoveghtive.com and @aaronvegh on Twitter)
10
+
11
+ == Installation
12
+
13
+ If you're using RubyGems, you can install it via:
14
+
15
+ $ sudo gem install shabang
16
+
17
+ We'll provide additional install instructions as those methods become available. It's early days, folks.
18
+
19
+ == Instructions
20
+
21
+ See the DOC file for using Shabang.
22
+
23
+ == Support
24
+
25
+ Have problems? Contact Aaron Vegh (aaron@innoveghtive.com). Try to be nice.
26
+
27
+ == License
28
+
29
+ See the LICENSE file included with the distribution for licensing and
30
+ copyright details.
data/bin/shabng ADDED
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'parseconfig'
5
+ require 'rest-client'
6
+ require 'console_editor'
7
+ require 'xmlsimple'
8
+ require 'ap'
9
+ require 'post.rb'
10
+
11
+ SB_VERSION = "0.0.2"
12
+
13
+ # get configuration file
14
+ # and conduct testing to ensure proper setup
15
+ config_path = File.expand_path('~/.shabng.conf')
16
+ if File.exists?(config_path)
17
+ conf = ParseConfig.new(config_path)
18
+ else
19
+ puts "New user detected."
20
+ print "Enter your blog key (from the web site): "
21
+ key = STDIN.gets.chomp
22
+ config = "apikey = " + key
23
+
24
+ puts "Choose your text editor from this list: "
25
+ puts "nano, vi, emacs, mate, bbedit"
26
+ editor = STDIN.gets.chomp
27
+ config += "\neditor = " + editor
28
+
29
+ conf_file = File.open(config_path, "w+")
30
+ conf_file.write config
31
+
32
+ puts "New config file written."
33
+ exit
34
+ end
35
+
36
+ @apikey = conf.get_value("apikey")
37
+ @editor = conf.get_value("editor")
38
+ @urlstring = "http://shabng.com"
39
+
40
+ # with our initial data set, let's check the server for a proper connection
41
+ # this will be done in the guise of a client update check.
42
+ # probably not entirely efficient to make this ping on every request, but I'm lazy.
43
+
44
+ check = RestClient.get @urlstring + "/accounts/version", :params=>{:api_key=>@apikey}
45
+
46
+ if check
47
+ vstring = XmlSimple.xml_in(check)
48
+ version = vstring["version"].first
49
+ if version != SB_VERSION
50
+ puts "A newer version of shabng is available. Please run 'sudo gem update shabng'."
51
+ end
52
+ else
53
+ puts "There are problems connecting to the server. Check the site to confirm."
54
+ exit
55
+ end
56
+
57
+ arg = ARGV[0]
58
+ arg2 = ARGV[1]
59
+ arg3 = ARGV[2]
60
+
61
+ if arg == "list"
62
+ # list all blog posts
63
+ puts "Here are your blog postings..."
64
+ @post = Post.new(@urlstring, @apikey)
65
+ @post.list
66
+
67
+ elsif arg == "new"
68
+ if arg2.nil? || arg2 == "post"
69
+ # create new blog post
70
+ print "Enter post title: "
71
+ title = STDIN.gets.chomp
72
+ eval "#{@editor} '/tmp/#{title}'"
73
+ @post = Post.new(@urlstring, @apikey, @editor)
74
+ @post.title = title
75
+ @post.body = File.new("/tmp/"+title).read
76
+ @post.publication_date = Time.now
77
+ @post.status = "Draft"
78
+ @post.add
79
+ elsif arg2 == "category"
80
+ print "Enter new category name: "
81
+ category = STDIN.gets.chomp
82
+ @post = Post.new(@urlstring, @apikey)
83
+ @post.newcat(category)
84
+ end
85
+
86
+ elsif arg == "edit"
87
+ # edit existing blog post
88
+ if arg2.nil?
89
+ puts "Please specify an element to edit: title, body, pubdate, categories."
90
+ elsif arg3.nil?
91
+ puts "Please specify a post to edit using the ID from the list command."
92
+ else
93
+ @post = Post.new(@urlstring, @apikey, @editor)
94
+ @post.edit(arg2, arg3)
95
+ end
96
+
97
+ elsif arg == "push"
98
+ if arg2.nil?
99
+ puts "Use a post ID with this argument to specify what to push live."
100
+ else
101
+ @post = Post.new(@urlstring, @apikey)
102
+ @post.push(arg2)
103
+ end
104
+
105
+ elsif arg == "pull"
106
+ if arg2.nil?
107
+ puts "Use a post ID with this argument to specify what to remove from your blog."
108
+ else
109
+ @post = Post.new(@urlstring, @apikey)
110
+ @post.pull(arg2)
111
+ end
112
+
113
+ # hold off on delete until rest-client supports params with delete request, so we can authenticate!
114
+ # https://github.com/archiloque/rest-client/issues#issue/48
115
+ elsif arg == "delete"
116
+ # delete blog post
117
+ if arg2.nil?
118
+ puts "Use a post ID with this argument to specify what to delete from your blog."
119
+ else
120
+ @post = Post.new(@urlstring, @apikey)
121
+ @post.destroy(arg2)
122
+ end
123
+
124
+ elsif arg == "setup"
125
+ # create database and perform initial setup
126
+
127
+
128
+
129
+ elsif arg == "create_database"
130
+ @name = @newname
131
+
132
+ elsif arg == "help"
133
+
134
+
135
+ else
136
+ puts "Shabng version " + SB_VERSION + "."
137
+ puts "Run with 'new' to create a new post."
138
+ puts "Run with 'list' to view existing posts."
139
+ end
140
+
data/lib/post.rb ADDED
@@ -0,0 +1,113 @@
1
+ require 'rubygems'
2
+ require 'rest-client'
3
+ require 'xmlsimple'
4
+ require 'time'
5
+ require 'ap'
6
+ class Post
7
+
8
+ attr_accessor :title, :body, :publication_date, :status, :blogid, :apikey
9
+
10
+ def initialize(urlstring, apikey, editor="nano")
11
+ @urlstring = urlstring
12
+ @apikey = apikey
13
+ @editor = editor
14
+ end
15
+
16
+ def add
17
+ save = RestClient.post @urlstring + "/posts", :api_key=>@apikey, :post => {:title=>title, :body=>body, :publication_date=>publication_date, :status=>status}
18
+ post = XmlSimple.xml_in(save)
19
+ file_contents = File.new("/tmp/"+title).read
20
+ puts "Blog post has been saved with ID " + post["id"].first["content"]
21
+ end
22
+
23
+ def list
24
+ docs = RestClient.get @urlstring + "/posts", :params=>{:api_key=>@apikey}
25
+ posts = XmlSimple.xml_in(docs)
26
+ if posts["post"].nil? == false
27
+ posts["post"].each do |d|
28
+ pubdate = Time.parse(d["publication-date"].first["content"])
29
+ puts "[" + d["id"].first["content"] + "] " + d["title"].first + " - " + pubdate.strftime("%Y-%m-%d") + " - " + d["status"].first
30
+ end
31
+ else
32
+ puts "No postings yet. Use the new command to create your first!"
33
+ end
34
+ end
35
+
36
+ def edit(action, sel)
37
+ xml = RestClient.get @urlstring + "/posts/" + sel + "/edit", :params=>{:api_key => @apikey}
38
+ post = XmlSimple.xml_in(xml)
39
+ body = post["body"].first
40
+ title = post["title"].first
41
+
42
+ if action == "body"
43
+ # edit chosen doc
44
+ filename = "/tmp/"+title
45
+ tempfile = File.new(filename, "w")
46
+ tempfile.write body
47
+ tempfile.close
48
+ puts "Editing with " + @editor
49
+ eval "#{@editor} '#{filename}'"
50
+
51
+ newbody = File.new(filename, "r").read
52
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :post => {:body=>newbody}
53
+
54
+ elsif action == "title"
55
+ print "Enter new title [" + title + "]: "
56
+ newtitle = STDIN.gets.chomp
57
+ if newtitle != title && newtitle != ""
58
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :post => {:title=>newtitle}
59
+ end
60
+
61
+ elsif action == "pubdate"
62
+ print "Enter new publication date [YYYY-MM-DD]: "
63
+ newdate = STDIN.gets.chomp
64
+ parseddate = Time.parse(newdate)
65
+ if parseddate
66
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :post => {:publication_date=>parseddate}
67
+ else
68
+ puts "Incorrect date format. Please try again."
69
+ end
70
+
71
+ elsif action == "categories"
72
+ # get all categories
73
+ xml = RestClient.get @urlstring + "/categories", :params=>{:api_key => @apikey}
74
+ post = XmlSimple.xml_in(xml)
75
+ require 'rubygems'
76
+ require 'ap'
77
+ #ap(post)
78
+ post["category"].each do |c|
79
+ puts "[" + c["id"].first["content"] + "] " + c["name"].first
80
+ end
81
+ puts "Enter a comma-separated list of category IDs: "
82
+ cats = STDIN.gets.chomp
83
+ cats = cats.gsub(" ", "").split(",")
84
+
85
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :categories=>cats
86
+
87
+ end
88
+
89
+ puts "Blog post has been saved!"
90
+
91
+ end
92
+
93
+ def newcat(cat)
94
+ save = RestClient.post @urlstring + "/categories", :api_key => @apikey, :category=>cat
95
+ puts "New category has been saved!"
96
+ end
97
+
98
+ def push(sel)
99
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :post => {:status=>"Published"}
100
+ puts "Your post is now live."
101
+ end
102
+
103
+ def pull(sel)
104
+ save = RestClient.put @urlstring + "/posts/" + sel, :api_key => @apikey, :post => {:status=>"Draft"}
105
+ puts "Your post has been pulled."
106
+ end
107
+
108
+ def destroy(sel)
109
+ save = RestClient.delete @urlstring + "/posts/" + sel, :params=>{:api_key => @apikey}
110
+ puts "Your post has been deleted."
111
+ end
112
+
113
+ end
data/shabng.gemspec ADDED
@@ -0,0 +1,55 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+ s.rubygems_version = '0.0.2'
5
+
6
+ ## Leave these as is they will be modified for you by the rake gemspec task.
7
+ ## If your rubyforge_project name is different, then edit it and comment out
8
+ ## the sub! line in the Rakefile
9
+ s.name = 'shabng'
10
+ s.version = '0.0.2'
11
+ s.date = '2010-11-10'
12
+ s.rubyforge_project = 'shabng'
13
+
14
+ ## Make sure your summary is short. The description may be as long
15
+ ## as you like.
16
+ s.summary = "Manage your blog from the command line."
17
+ s.description = "Shabng is a blogging service for those who prefer to blog from the command line. Sign up for a free account at http://shabng.com. Once you've created your account and picked a name for your blog, you'll get an API key to interact with that blog using this command line program."
18
+
19
+ ## List the primary authors. If there are a bunch of authors, it's probably
20
+ ## better to set the email to an email list or something. If you don't have
21
+ ## a custom homepage, consider using your GitHub URL or the like.
22
+ s.authors = ["Aaron Vegh"]
23
+ s.email = 'aaron@innoveghtive.com'
24
+ s.homepage = 'http://shabng.com'
25
+
26
+ s.require_paths = %w[lib bin]
27
+
28
+ s.rdoc_options = ["--charset=UTF-8"]
29
+ s.extra_rdoc_files = %w[README LICENSE DOC/CommandRef.rdoc]
30
+
31
+ s.add_dependency('parseconfig')
32
+ s.add_dependency('rest-client')
33
+ s.add_dependency('console_editor')
34
+ s.add_dependency('xml-simple', ">= 1.0.12")
35
+
36
+ s.executables << 'shabng'
37
+
38
+ ## Leave this section as-is. It will be automatically generated from the
39
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
40
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
41
+ # = MANIFEST =
42
+ s.files = %w[
43
+ LICENSE
44
+ README
45
+ shabng.gemspec
46
+ bin/shabng
47
+ lib/post.rb
48
+ DOC/CommandRef.rdoc
49
+ ]
50
+ # = MANIFEST =
51
+
52
+ ## Test files will be grabbed from the file list. Make sure the path glob
53
+ ## matches what you actually use.
54
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
55
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shabng
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Aaron Vegh
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-10 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: parseconfig
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rest-client
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: console_editor
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: xml-simple
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 15
72
+ segments:
73
+ - 1
74
+ - 0
75
+ - 12
76
+ version: 1.0.12
77
+ type: :runtime
78
+ version_requirements: *id004
79
+ description: Shabng is a blogging service for those who prefer to blog from the command line. Sign up for a free account at http://shabng.com. Once you've created your account and picked a name for your blog, you'll get an API key to interact with that blog using this command line program.
80
+ email: aaron@innoveghtive.com
81
+ executables:
82
+ - shabng
83
+ extensions: []
84
+
85
+ extra_rdoc_files:
86
+ - README
87
+ - LICENSE
88
+ - DOC/CommandRef.rdoc
89
+ files:
90
+ - LICENSE
91
+ - README
92
+ - shabng.gemspec
93
+ - bin/shabng
94
+ - lib/post.rb
95
+ - DOC/CommandRef.rdoc
96
+ has_rdoc: true
97
+ homepage: http://shabng.com
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ - bin
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirements: []
125
+
126
+ rubyforge_project: shabng
127
+ rubygems_version: 1.3.7
128
+ signing_key:
129
+ specification_version: 2
130
+ summary: Manage your blog from the command line.
131
+ test_files: []
132
+