zendesk-tools 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5dbb43b53a5d36b8267fa908f235123036edb28
4
+ data.tar.gz: 49cc7c1bda607fcf622a777363ce58c907a835f4
5
+ SHA512:
6
+ metadata.gz: 62bbbe159db16acd407f30808ebb066215a04404a2c206f31ba681706304b71f0f3c5f8a1c8a07559840801e250ad1d6790cef131136821e9ce8fc4815f401ae
7
+ data.tar.gz: cc76ed280eead3c76219de63451da42b8300512f1fb1b6b3a7c016f3cfa9fc8b696fdca7ff287cfced5bd42eed526aaa84d06aa3ffd854448da5484c8c4cda92
data/.gitattributes ADDED
@@ -0,0 +1,22 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+ *.sln merge=union
7
+ *.csproj merge=union
8
+ *.vbproj merge=union
9
+ *.fsproj merge=union
10
+ *.dbproj merge=union
11
+
12
+ # Standard to msysgit
13
+ *.doc diff=astextplain
14
+ *.DOC diff=astextplain
15
+ *.docx diff=astextplain
16
+ *.DOCX diff=astextplain
17
+ *.dot diff=astextplain
18
+ *.DOT diff=astextplain
19
+ *.pdf diff=astextplain
20
+ *.PDF diff=astextplain
21
+ *.rtf diff=astextplain
22
+ *.RTF diff=astextplain
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zendesk-tools.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 FINN.no AS
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # ZendeskTools
2
+
3
+ Tools to automate common tasks in ZenDesk.
4
+
5
+ ## Installation
6
+
7
+ Install the gem:
8
+
9
+ $ gem install zendesk-tools --source "http://gems.finn.no"
10
+
11
+ ## Usage
12
+
13
+ Add a JSON config to ~/.zendesk-tools.json (TODO: make command line ovveride):
14
+
15
+ {
16
+
17
+ // mandatory
18
+ "username": "user@example.com",
19
+ "token": "your_token_here",
20
+
21
+ // optional
22
+ "log_level": "debug",
23
+ "log_file": "/some/path"
24
+
25
+ }
26
+
27
+ Clean suspended tickets:
28
+
29
+ $ zendesk-tools clean-suspended
30
+
31
+ Upload files to ticket:
32
+
33
+ $ zendesk-tools upload-files-to-ticket <ticket_id> <files>
34
+
35
+
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler/setup'
2
+ require 'rake/clean'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ CLEAN << "pkg"
7
+ CLEAN << "*.gem"
8
+
9
+ GEM_NAME = "zendesk-tools-#{ZendeskTools::VERSION}.gem"
10
+
11
+ zdt_gem = file "pkg/#{GEM_NAME}" do |t|
12
+ mkdir_p "pkg"
13
+ sh "gem build zendesk-tools.gemspec"
14
+ mv GEM_NAME, t.name
15
+ end
16
+
17
+ desc "Build #{zdt_gem.name}"
18
+ task :build => [:clean, zdt_gem.name]
19
+
data/bin/zendesk-tools ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'zendesk-tools'
4
+
5
+ cmd = ARGV.shift
6
+
7
+ if cmd.nil?
8
+ ZendeskTools.show_config
9
+ exit 1
10
+ end
11
+
12
+ case cmd
13
+ when 'clean-suspended'
14
+ ZendeskTools::CleanSuspended.run(ARGV)
15
+ when 'upload-files-to-ticket'
16
+ ZendeskTools::UploadFilesToTicket.run(ARGV)
17
+ when 'recover-suspended'
18
+ ZendeskTools::RecoverSuspended.run(ARGV)
19
+ else
20
+ abort "Sorry, I don't know how to #{cmd.inspect}"
21
+ end
@@ -0,0 +1,60 @@
1
+ require "zendesk-tools/version"
2
+ require "zendesk_api"
3
+ require 'json'
4
+ require 'pathname'
5
+ require 'pp'
6
+ require 'logger'
7
+ require 'log4r'
8
+ require 'log4r/config'
9
+
10
+ require 'zendesk-tools/loggable'
11
+ require 'zendesk-tools/command'
12
+ require 'zendesk-tools/clean_suspended'
13
+ require 'zendesk-tools/upload_files_to_ticket'
14
+ require 'zendesk-tools/recover_suspended'
15
+
16
+ module ZendeskTools
17
+ CONFIG_FILE = Pathname.new(File.expand_path("~/.zendesk-tools.json"))
18
+
19
+ def self.config
20
+ @config ||= (
21
+ if CONFIG_FILE.exist?
22
+ JSON.parse(CONFIG_FILE.read)
23
+ else
24
+ raise "Sorry, could not find JSON config in #{CONFIG_FILE}"
25
+ end
26
+ )
27
+ end
28
+
29
+ def self.show_config
30
+ pp config
31
+ end
32
+
33
+ def self.client
34
+ @client ||= (ZendeskAPI::Client.new do |c|
35
+ # Mandatory:
36
+
37
+ c.url = config['url'] || "https://finn.zendesk.com/api/v2"
38
+ c.username = config.fetch('username')
39
+ c.token = config.fetch('token')
40
+
41
+ # Optional:
42
+
43
+ if %w[debug trace].include? config['log_level']
44
+ c.logger = Loggable.logger_for("ZendeskAPI")
45
+ end
46
+
47
+ # Retry uses middleware to notify the user
48
+ # when hitting the rate limit, sleep automatically,
49
+ # then retry the request.
50
+ c.retry = true
51
+
52
+ # Changes Faraday adapter
53
+ # config.adapter = :patron
54
+
55
+ # Merged with the default client options hash
56
+ # config.client_options = { :ssl => false }
57
+ end
58
+ )
59
+ end
60
+ end
@@ -0,0 +1,40 @@
1
+ module ZendeskTools
2
+ class CleanSuspended < Command
3
+ include Loggable
4
+
5
+ DELETE_CAUSES = [
6
+ "Detected email as being from a system user",
7
+ "Detected as mail loop",
8
+ "Automated response mail"
9
+ ]
10
+
11
+ DELETE_SUBJECTS = [
12
+ "Returned mail: see transcript",
13
+ "Delivery Status Notification (Failure)",
14
+ "Undeliverable:",
15
+ "Kan ikke leveres:",
16
+ "Automatisk svar"
17
+ ]
18
+
19
+ def run
20
+ @client.suspended_tickets.each do |suspended_ticket|
21
+ if should_delete?(suspended_ticket)
22
+ log.info "Deleting: #{suspended_ticket.subject}"
23
+ suspended_ticket.destroy
24
+ else
25
+ log.info "Keeping: #{suspended_ticket.subject}"
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def should_delete?(suspended_ticket)
33
+ cause = suspended_ticket.cause
34
+ subject = suspended_ticket.subject
35
+
36
+ DELETE_CAUSES.any? { |delete_cause| cause.include?(delete_cause) } ||
37
+ DELETE_SUBJECTS.any? { |delete_subject| subject.include?(delete_subject) }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module ZendeskTools
2
+ class Command
3
+ include Loggable
4
+
5
+ def self.run(args)
6
+ new(ZendeskTools.client, args).run
7
+ end
8
+
9
+ def initialize(client, args)
10
+ @client = client
11
+ @args = args
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
2
+
3
+ module ZendeskTools
4
+ module Loggable
5
+ def self.logger_for(name)
6
+ name = self.class.name
7
+ log = Log4r::Logger.new(name)
8
+ formatter = Log4r::PatternFormatter.new(:pattern => "[%l @ %d] %c: %M")
9
+
10
+ log_file = ZendeskTools.config['log_file']
11
+ if log_file
12
+ FileUtils.mkdir_p File.dirname(log_file)
13
+
14
+ log.add Log4r::FileOutputter.new(name, :filename => log_file, :formatter => formatter)
15
+ else
16
+ outputter = Log4r::Outputter.stdout
17
+ outputter.formatter = formatter
18
+ log.add outputter
19
+ end
20
+
21
+ level = ZendeskTools.config['log_level']
22
+ if level
23
+ log.level = Log4r.const_get(level.to_s.upcase)
24
+ end
25
+
26
+ log
27
+ end
28
+
29
+ def log
30
+ @log ||= Loggable.logger_for(self.class.name)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,102 @@
1
+ require 'net/http'
2
+ require 'tmpdir'
3
+ require 'fileutils'
4
+
5
+ module ZendeskTools
6
+ class RecoverSuspended < Command
7
+ include Loggable
8
+
9
+ RECOVER_CAUSES = [
10
+ "End-user only allowed to update their own tickets"
11
+ ]
12
+
13
+ def initialize(*args)
14
+ super
15
+ @tmpdir = Dir.mktmpdir
16
+ end
17
+
18
+ def run
19
+ @client.suspended_tickets.each do |suspended_ticket|
20
+ if should_recover?(suspended_ticket)
21
+ log.info "Recovering: #{suspended_ticket.subject}"
22
+ # Logic for recovering the tickets
23
+ # Need to add logic for:
24
+ # * Grab ticket_id
25
+ ticket_id = suspended_ticket.ticket_id
26
+
27
+ # * Grab author_id
28
+ author_id = suspended_ticket.author.id
29
+
30
+ # * Grab content
31
+ content = suspended_ticket.content
32
+
33
+ # * Create new comment with correct author and content
34
+ ticket = @client.tickets.find(:id => ticket_id)
35
+ ticket.comment = ZendeskAPI::Ticket::Comment.new(@client, :value => content, :author_id => author_id)
36
+
37
+ # * Check for attachments and logic around that
38
+
39
+ suspended_ticket.attachments.each do |attachment|
40
+ url = attachment.fetch('content_url')
41
+ name = attachment.fetch('file_name')
42
+ path = File.join(@tmpdir, name)
43
+
44
+ log.info "downloading #{url}"
45
+
46
+ File.open(path, 'wb') { |file| download(url, file) }
47
+ ticket.comment.uploads << path
48
+ end
49
+
50
+ # * Save comment and upload it to zendesk
51
+
52
+ log.info "uploading"
53
+ ticket.save
54
+
55
+ # * delete/destroy the recovered ticket
56
+ suspended_ticket.destroy
57
+ log.info "cleaning up"
58
+ FileUtils.rm_rf @tmpdir
59
+ else
60
+ log.info "Not recovering: #{suspended_ticket.subject}"
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def download(url, destination)
68
+ uri = URI.parse(url)
69
+
70
+ resp = Net::HTTP.get_response(uri) do |response|
71
+ total = response.content_length
72
+ progress = 0
73
+ segment_count = 0
74
+
75
+ response.read_body do |segment|
76
+ progress += segment.length
77
+ segment_count += 1
78
+
79
+ if segment_count % 15 == 0
80
+ percent = (progress.to_f / total.to_f) * 100
81
+ print "\rDownloading #{url}: #{percent.to_i}% (#{progress} / #{total})"
82
+ $stdout.flush
83
+ segment_count = 0
84
+ end
85
+
86
+ destination.write(segment)
87
+ end
88
+ end
89
+
90
+ unless resp.kind_of?(Net::HTTPSuccess)
91
+ raise "ERROR:#{resp.code} for #{url}"
92
+ end
93
+ end
94
+
95
+ def should_recover?(suspended_ticket)
96
+ cause = suspended_ticket.cause
97
+ subject = suspended_ticket.subject
98
+
99
+ RECOVER_CAUSES.any? { |recover_cause| cause.include?(recover_cause) }
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ module ZendeskTools
4
+ class UploadFilesToTicket < Command
5
+
6
+ def run
7
+ ticket_id = @args.shift or raise ArgumentError, "sorry, jeg trenger en ticket id"
8
+ files = @args
9
+
10
+ raise ArgumentError, "trenger noen filer å laste opp" if files.empty?
11
+
12
+ ticket = @client.tickets.find(:id => ticket_id)
13
+ ticket or raise "fant ingen ticket med id #{ticket_id.inspect}"
14
+
15
+ ticket.comment = ZendeskAPI::Ticket::Comment.new(@client, :value => "Vedlegg fra #{ZendeskTools.config['username']}")
16
+
17
+ files.each do |e|
18
+ ticket.comment.uploads << e
19
+ end
20
+
21
+ print "Laster opp #{files.join ', '}..."
22
+ ticket.save
23
+ puts "ferdig."
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module ZendeskTools
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'zendesk-tools/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "zendesk-tools"
8
+ gem.version = ZendeskTools::VERSION
9
+ gem.authors = ["Jari Bakken", "Eivind Throndsen"]
10
+ gem.email = ["jari@finn.no", "eivind.throndsen@finn.no"]
11
+ gem.description = %q{Tools for FINNs ZenDesk}
12
+ gem.summary = %q{Tools for FINNs ZenDesk}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "zendesk_api", "~> 1.3.0"
21
+ gem.add_dependency "json"
22
+ gem.add_dependency "rake"
23
+ gem.add_dependency "geminabox"
24
+ gem.add_dependency "log4r"
25
+ gem.add_development_dependency "pry"
26
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zendesk-tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Jari Bakken
8
+ - Eivind Throndsen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-06-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: zendesk_api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 1.3.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 1.3.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: geminabox
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: log4r
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description: Tools for FINNs ZenDesk
99
+ email:
100
+ - jari@finn.no
101
+ - eivind.throndsen@finn.no
102
+ executables:
103
+ - zendesk-tools
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - .gitattributes
108
+ - .gitignore
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/zendesk-tools
114
+ - lib/zendesk-tools.rb
115
+ - lib/zendesk-tools/clean_suspended.rb
116
+ - lib/zendesk-tools/command.rb
117
+ - lib/zendesk-tools/loggable.rb
118
+ - lib/zendesk-tools/recover_suspended.rb
119
+ - lib/zendesk-tools/upload_files_to_ticket.rb
120
+ - lib/zendesk-tools/version.rb
121
+ - zendesk-tools.gemspec
122
+ homepage: ''
123
+ licenses: []
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.0.14
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Tools for FINNs ZenDesk
145
+ test_files: []