zenpush 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ zenpush (0.1.0)
5
+ awesome_print (~> 1.0.0)
6
+ boson (~> 1.0)
7
+ httparty (~> 0.8.0)
8
+ json_pure (~> 1.5.1)
9
+ redcarpet (~> 2.1.0)
10
+
11
+ GEM
12
+ remote: http://rubygems.org/
13
+ specs:
14
+ awesome_print (1.0.2)
15
+ boson (1.1.0)
16
+ httparty (0.8.1)
17
+ multi_json
18
+ multi_xml
19
+ json_pure (1.5.4)
20
+ spruz (~> 0.2.8)
21
+ multi_json (1.1.0)
22
+ multi_xml (0.4.1)
23
+ rake (0.9.2.2)
24
+ redcarpet (2.1.0)
25
+ spruz (0.2.13)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ rake
32
+ zenpush!
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 0.1.0
2
+
3
+ * Original version
4
+ * List categories, forums, entries
5
+ * Convert entries from Markdown to HTML push them to Zendesk
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2012 CleverScale
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,73 @@
1
+ # ZenPush
2
+
3
+ This gem allows editing your Zendesk knowledge base in Markdown. It's a command-line tool.
4
+
5
+ ## Getting Started
6
+
7
+ $ gem install zenpush
8
+
9
+ Run it:
10
+
11
+ $ zenpush <command> <args>
12
+ $ zp <command> <args>
13
+
14
+ ## Requirements:
15
+
16
+ Only installs pure JSON gem json_pure by default. If you are able to install the C-extension json gem, it will use that instead.
17
+
18
+ Try:
19
+
20
+ $ gem install json zenpush
21
+
22
+ ## Configuration
23
+
24
+ Create a `zenpush.yml` file in your home directory. Here is an example:
25
+
26
+ ---
27
+ uri: https://myproduct.zendesk.com
28
+ user: email@address.com/token
29
+ password: LoDsQlEtBXSd8clW87DgWi0VNFod3U9xQggzwJEH
30
+
31
+ You can find your API token at https://myproduct.zendesk.com/settings/api.
32
+
33
+ ## Usage
34
+
35
+ ### Listing categories
36
+
37
+ $ zp categories
38
+
39
+ ### Listing forums
40
+
41
+ $ zp forums
42
+
43
+ ### Listing entries in a forum
44
+
45
+ $ zp entries -f <forum_id>
46
+ $ zp entries -F <forum_name>
47
+
48
+ ### Creating/updating an entry
49
+
50
+ Keep an organized folder of your categories, forums, and entries. Let's say I have the category "Documentation", containing a forum "REST API", and the entries "Introduction" and "Authentication"; you'll want to keep this file structure:
51
+
52
+ Documentation/REST API/Introduction.md
53
+ Documentation/REST API/Authentication.md
54
+
55
+ Creating or updating an entry:
56
+
57
+ $ zp push -f <path_to_markdown_file>
58
+
59
+ Following the previous example, you would type:
60
+
61
+ [~/KB/Documentation/REST API]$ zp push -f Authentication.md
62
+ [~/KB/Documentation]$ zp push -f REST API/Authentication.md
63
+ [~/KB]$ zp push -f REST Documentation/API/Authentication.md
64
+
65
+ The gem will automatically discover the category and forum name of a given entry file. It will also convert your Markdown syntax in HTML before sending it to Zendesk.
66
+
67
+ ### Check if an entry exists
68
+
69
+ $ zp exists? -f <path_to_markdown_file>
70
+
71
+ ## Contributors
72
+
73
+ * @nfo
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/setup"
2
+ Bundler::GemHelper.install_tasks
data/bin/zenpush ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'zenpush'
4
+ ZenPush::Runner.start
data/bin/zp ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'zenpush'
4
+ ZenPush::Runner.start
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+ require 'redcarpet/compat'
3
+
4
+ module ZenPush
5
+ class Markdown
6
+
7
+ # Convert a markdown file to HTML, removing all <code> tags,
8
+ # which make Zendesk remove carriage returns.
9
+ def self.to_zendesk_html(file)
10
+ ::Markdown.new(File.read(file)).to_html.gsub(/<\/?code>/, '')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+ require 'boson/runner'
3
+ require 'ap'
4
+
5
+ module ZenPush
6
+ class Runner < Boson::Runner
7
+
8
+ desc 'List categories'
9
+ def categories(options = {})
10
+ ap ZenPush.z.categories
11
+ end
12
+
13
+ desc 'List forums'
14
+ def forums(options = {})
15
+ ap ZenPush.z.forums
16
+ end
17
+
18
+ option :forum_id, :type => :numeric
19
+ desc 'List entries'
20
+ def entries(options = {})
21
+ ap ZenPush.z.entries(options[:forum_id])
22
+ end
23
+
24
+ desc 'Does the entry matching the given file exist ?'
25
+ option :file, :type => :string
26
+ def exists?(options = {})
27
+ category_name, forum_name, entry_title = ZenPush.file_to_category_forum_entry(options[:file])
28
+ entry = ZenPush.z.find_entry(category_name, forum_name, entry_title)
29
+ ap !!entry
30
+ end
31
+
32
+ desc 'Create or update an entry from the given file'
33
+ option :file, :type => :string
34
+ def push(options = {})
35
+ category_name, forum_name, entry_title = ZenPush.file_to_category_forum_entry(options[:file])
36
+
37
+ entry_body = ZenPush::Markdown.to_zendesk_html(options[:file])
38
+
39
+ entry = ZenPush.z.find_entry(category_name, forum_name, entry_title)
40
+ if entry
41
+ # UPDATE THE ENTRY
42
+ ap ZenPush.z.put_entry(entry['id'], entry_body)
43
+ else
44
+ forum = ZenPush.z.find_forum(category_name, forum_name)
45
+ if forum
46
+ # CREATE THE ENTRY
47
+ ap ZenPush.z.post_entry(forum['id'], entry_title, entry_body)
48
+ else
49
+ ap "Could not find a forum named '#{forum_name}' in the category '#{category_name}'"
50
+ exit(-1)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: UTF-8
2
+ module ZenPush
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,111 @@
1
+ # encoding: UTF-8
2
+ require 'json'
3
+ require 'yaml'
4
+ require 'httparty'
5
+
6
+ module ZenPush
7
+ class Zendesk
8
+ include HTTParty
9
+
10
+ headers 'Content-Type' => 'application/json'
11
+ # debug_output
12
+
13
+ def initialize(b = nil, u = nil, p = nil)
14
+ if b.nil? || u.nil? || p.nil?
15
+ creds = YAML.load_file(File.join(ENV['HOME'], '.zenpush.yml'))
16
+ b ||= creds['uri']
17
+ u ||= creds['user']
18
+ p ||= creds['password']
19
+ end
20
+
21
+ self.class.base_uri b + '/api/v1'
22
+ self.class.basic_auth u, p
23
+ end
24
+
25
+ def get(uri, options = {})
26
+ self.class.get(uri, options)
27
+ end
28
+
29
+ def post(uri, options = {})
30
+ self.class.post(uri, options)
31
+ end
32
+
33
+ def put(uri, options = {})
34
+ self.class.put(uri, options)
35
+ end
36
+
37
+ def delete(uri, options = {})
38
+ self.class.delete(uri, options)
39
+ end
40
+
41
+ def categories(options = {})
42
+ self.get('/categories.json', options).parsed_response
43
+ end
44
+
45
+ def category(category_id, options = {})
46
+ self.get("/categories/#{category_id}.json", options).parsed_response
47
+ end
48
+
49
+ def forums(options = {})
50
+ self.get('/forums.json', options).parsed_response
51
+ end
52
+
53
+ def forum(forum_id, options = {})
54
+ self.get("/forums/#{forum_id}.json", options).parsed_response
55
+ end
56
+
57
+ def users(options = {})
58
+ self.get('/users.json', options).parsed_response
59
+ end
60
+
61
+ def entries(forum_id, options = {})
62
+ self.get("/forums/#{forum_id}/entries.json", options).parsed_response
63
+ end
64
+
65
+ def entry(entry_id, options = {})
66
+ self.get("/entries/#{entry_id}.json", options).parsed_response
67
+ end
68
+
69
+ # Find category by name
70
+ def find_category(category_name, options = {})
71
+ self.categories.detect {|c| c['name'] == category_name}
72
+ end
73
+
74
+ # Find forum by name, knowing the category name
75
+ def find_forum(category_name, forum_name, options = {})
76
+ category = self.find_category(category_name, options)
77
+ if category
78
+ self.forums.detect {|f| f['name'] == forum_name}
79
+ end
80
+ end
81
+
82
+ # Find entry by name, knowing the forum name and category name
83
+ def find_entry(category_name, forum_name, entry_title, options = {})
84
+ forum = self.find_forum(category_name, forum_name, options)
85
+ if forum
86
+ self.entries(forum['id'], options).detect {|e| e['title'] == entry_title}
87
+ end
88
+ end
89
+
90
+ # Create an entry in the given forum id
91
+ def post_entry(forum_id, entry_title, entry_body, options = {})
92
+ self.post("/entries.json",
93
+ options.merge(
94
+ :body => { :entry => {
95
+ :forum_id => forum_id, :title => entry_title, :body => entry_body
96
+ } }.to_json
97
+ )
98
+ )
99
+ end
100
+
101
+ # Update an entry in the given forum id
102
+ def put_entry(entry_id, entry_body, options = {})
103
+ self.put("/entries/#{entry_id}.json",
104
+ options.merge(
105
+ :body => { :entry => { :body => entry_body } }.to_json
106
+ )
107
+ )
108
+ end
109
+
110
+ end
111
+ end
data/lib/zenpush.rb ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+ require 'zenpush/runner'
3
+ require 'zenpush/zendesk'
4
+ require 'zenpush/markdown'
5
+
6
+ module ZenPush
7
+ extend self
8
+
9
+ # Zendesk API
10
+ def z
11
+ @z ||= ZenPush::Zendesk.new
12
+ end
13
+
14
+ #
15
+ def file_to_category_forum_entry(file)
16
+ absolute_path = File.realpath(file)
17
+ parts = absolute_path.split('/')
18
+ entry_name = File.basename(absolute_path, '.md') # TODO support .markdown and make it case insensitive
19
+ forum_name = parts[-2]
20
+ category_name = parts[-3]
21
+ return category_name, forum_name, entry_name
22
+ end
23
+ end
data/zenpush.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # encoding: UTF-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "zenpush/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "zenpush"
7
+ s.version = ZenPush::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Nicolas Fouché"]
10
+ s.email = ["nicolas.fouche@cleverscale.com"]
11
+ s.homepage = "https://github.com/cleverscale/zenpush"
12
+ s.summary = "Push your markdown files to your Zendesk knowledge base"
13
+ s.description = "Push your markdown files to your Zendesk knowledge base"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ s.rdoc_options = ["--charset=UTF-8"]
20
+
21
+ s.add_dependency "boson", "~> 1.0" # Command line
22
+ s.add_dependency "httparty", "~> 0.8.0" # Zendesk API calls
23
+ s.add_dependency "redcarpet", "~> 2.1.0" # Markdown to HTML
24
+ s.add_dependency "awesome_print", "~> 1.0.0" # Colorized output of Zendesk responses
25
+ s.add_dependency "json_pure", "~> 1.5.1" # The C-gem "json" will still be used instead if it's installed
26
+
27
+ s.add_development_dependency "rake"
28
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zenpush
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nicolas Fouché
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: boson
16
+ requirement: &70100188010080 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70100188010080
25
+ - !ruby/object:Gem::Dependency
26
+ name: httparty
27
+ requirement: &70100188008860 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70100188008860
36
+ - !ruby/object:Gem::Dependency
37
+ name: redcarpet
38
+ requirement: &70100187769000 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.1.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70100187769000
47
+ - !ruby/object:Gem::Dependency
48
+ name: awesome_print
49
+ requirement: &70100187768300 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70100187768300
58
+ - !ruby/object:Gem::Dependency
59
+ name: json_pure
60
+ requirement: &70100187767540 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.5.1
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70100187767540
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: &70100187766900 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70100187766900
80
+ description: Push your markdown files to your Zendesk knowledge base
81
+ email:
82
+ - nicolas.fouche@cleverscale.com
83
+ executables:
84
+ - zenpush
85
+ - zp
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - .gitignore
90
+ - Gemfile
91
+ - Gemfile.lock
92
+ - History.txt
93
+ - LICENSE
94
+ - README.markdown
95
+ - Rakefile
96
+ - bin/zenpush
97
+ - bin/zp
98
+ - lib/zenpush.rb
99
+ - lib/zenpush/markdown.rb
100
+ - lib/zenpush/runner.rb
101
+ - lib/zenpush/version.rb
102
+ - lib/zenpush/zendesk.rb
103
+ - zenpush.gemspec
104
+ homepage: https://github.com/cleverscale/zenpush
105
+ licenses: []
106
+ post_install_message:
107
+ rdoc_options:
108
+ - --charset=UTF-8
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ segments:
118
+ - 0
119
+ hash: -3134286403274189971
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ segments:
127
+ - 0
128
+ hash: -3134286403274189971
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 1.8.17
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: Push your markdown files to your Zendesk knowledge base
135
+ test_files: []