zenpush 0.1.0
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 +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +32 -0
- data/History.txt +5 -0
- data/LICENSE +18 -0
- data/README.markdown +73 -0
- data/Rakefile +2 -0
- data/bin/zenpush +4 -0
- data/bin/zp +4 -0
- data/lib/zenpush/markdown.rb +13 -0
- data/lib/zenpush/runner.rb +55 -0
- data/lib/zenpush/version.rb +4 -0
- data/lib/zenpush/zendesk.rb +111 -0
- data/lib/zenpush.rb +23 -0
- data/zenpush.gemspec +28 -0
- metadata +135 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
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
data/bin/zenpush
ADDED
data/bin/zp
ADDED
@@ -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,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: []
|