Skip to content

Instantly share code, notes, and snippets.

@zenhob
Created May 19, 2010 05:47
Show Gist options
  • Save zenhob/405992 to your computer and use it in GitHub Desktop.
Save zenhob/405992 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby -rubygems
require 'faraday'
require 'trollop'
require 'fileutils'
class ZenDesk2Tender
include FileUtils
attr_reader :opts, :conn
EXPORT_DIR = '.export-data'
def initialize
@author_email = {}
@opts = Trollop::options do
banner <<-EOM
Usage:
#{$0} -e <email> -p <password> -s <subdomain>
Prerequisites:
# Ruby gems
gem install faraday -v "~>0.4.5"
gem install trollop
gem install yajl-ruby
# Python tools (must be in your PATH)
html2text.py: http://www.aaronsw.com/2002/html2text/
Options:
EOM
opt :email, "user email address", :type => String
opt :password, "user password", :type => String
opt :subdomain, "subdomain", :type => String
end
[:email, :password, :subdomain ].each do |option|
Trollop::die option, "is required" if opts[option].nil?
end
if `which html2text.py`.empty?
puts 'missing prerequisite: html2text.py is not in your PATH'
exit
end
@conn = Faraday::Connection.new("http://#{opts[:subdomain]}.zendesk.com") do |b|
b.adapter :net_http
b.response :yajl
end
conn.basic_auth(opts[:email], opts[:password])
end
def export_users
response = conn.get('users.json')
if response.success?
dir_name = File.join(EXPORT_DIR,'users')
mkdir_p dir_name
response.body.each do |user|
File.open(File.join(dir_name, "#{user['email'].gsub(/\W+/,'_')}.json"), "w") do |file|
@author_email[user['id']] = user['email']
file.puts(Yajl::Encoder.encode(
:name => user['name'],
:email => user['email'],
:created_at => user['created_at'],
:updated_at => user['updated_at'],
:state => %w[user support support][user['roles']]
))
end
end
else
puts "failed to get users:"
puts response.inspect
end
end
def export_categories
response = conn.get('forums.json')
if response.success?
dir_name = File.join(EXPORT_DIR,'categories')
mkdir_p dir_name
response.body.each do |forum|
File.open(File.join(dir_name, "#{forum['id']}.json"), "w") do |file|
file.puts(Yajl::Encoder.encode(
:name => forum['name'],
:summary => forum['description']
))
end
export_discussions(forum['id'])
end
else
puts "failed to get categories:"
puts response.inspect
end
end
def author_email user_id
@author_email[user_id] ||= begin
# the cache should be populated during export_users but we'll attempt
# to fetch unrecognized ids just in case
conn.get("users/#{user_id}.json").body['email'] rescue nil
end
end
def dump_body entry, body
File.open(File.join("tmp", "#{entry['id']}_body.html"), "w") do |file|
file.write(body)
end
end
def load_body entry
`html2text.py /$PWD/tmp/#{entry['id']}_body.html`
end
def export_discussions forum_id
response = conn.get("forums/#{forum_id}/entries.json")
if response.success?
dir_name = File.join(EXPORT_DIR,'categories', forum_id.to_s)
mkdir_p dir_name
mkdir_p 'tmp'
response.body.each do |entry|
File.open(File.join(dir_name, "#{entry['id']}.json"), "w") do |file|
comments = entry['posts'].map do |post|
dump_body entry, post['body']
{
:body => load_body(entry),
:author_email => author_email(post['user_id']),
:created_at => post['created_at'],
:updated_at => post['updated_at'],
}
end
dump_body entry, entry['body']
file.puts(Yajl::Encoder.encode(
:title => entry['title'],
:comments => [{
:body => load_body(entry),
:author_email => author_email(entry['submitter_id']),
:created_at => entry['created_at'],
:updated_at => entry['updated_at'],
}] + comments
))
rm "tmp/#{entry['id']}_body.html"
end
end
else
puts "failed to get entries for forum #{forum_id}:"
puts response.inspect
end
end
def create_archive
export_file = "export_#{opts[:subdomain]}.tgz"
system "tar -zcf #{export_file} -C #{EXPORT_DIR} ."
system "rm -rf #{EXPORT_DIR}"
puts "created #{export_file}"
end
def self.run
exporter = new
exporter.export_users
exporter.export_categories
exporter.create_archive
end
end
ZenDesk2Tender.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment