Skip to content

Instantly share code, notes, and snippets.

@rottmanj
Created March 28, 2012 19:37
Show Gist options
  • Save rottmanj/2229745 to your computer and use it in GitHub Desktop.
Save rottmanj/2229745 to your computer and use it in GitHub Desktop.
Lighthouse to Assembla Stuff
require "uri"
require "net/http"
require 'mime/types'
require 'crack/xml' # for just xml
class ImportsController < ApplicationController
$settings = {:username => '',
:password => '',
:space_url => '',
:file_path=>"#{File.expand_path(Rails.root)}/data/sweetyhigh_files/sweetyhigh/projects/87977-sweetyhightheg/tickets"}
def initialize()
uri = URI.parse(api_url)
port = 80
@http = Net::HTTP.new(uri.host, port)
extract_api_url
end
def milestones
milestones = Milestone.find(:all)
milestones.each do |m|
result = post_form("#{$settings[:space_url]}/milestones", :milestone => {
:title => m.milestone,
:description => '',
:due_date => trac_time_to_date(m.due_date, Date.today),
:skip_alerts => true,
:is_completed => false
}
)
end
end
def remove
tickets = Ticket.find(:all, :order=>"ticket_id ASC")
tickets.each do |d|
ticket = { :ticket => {
:number => d.ticket_id
}}
del_url = "#{$settings[:space_url]}/tickets/#{d.ticket_id}"
request = http_method :delete, del_url
request.form_data = rails_values ticket
response = @http.request(request)
end
end
def filedelete
request = http_method :get, "#{$settings[:space_url]}/documents"
response = @http.request(request)
files = Crack::XML.parse(response.body)
files = files["documents"]
files.each do |f|
request = http_method :delete, "#{$settings[:space_url]}/documents/#{f["id"]}"
response = @http.request(request)
end
end
def tickets
tickets = Ticket.find(:all, :order=>"ticket_id ASC")
json = ''
tickets.each do |t|
file_data = File.open("#{$settings[:file_path]}/#{t.ticket_directory}/ticket.json","r")
data = file_data.readlines.to_s
json = JSON.parse(data)
parsed_json = ActiveSupport::JSON.decode(json[0])
owner = User.find_by_lh_user_id(parsed_json["ticket"]["assigned_user_id"])
act_as = User.find_by_lh_user_id(parsed_json["ticket"]["creator_id"])
state = TicketStatus.find_by_old_name(parsed_json["ticket"]["state"])
milestone = Milestone.find_by_milestone_id(parsed_json["ticket"]["milestone_id"])
## Create Initial Ticket
ticket = { :ticket => {
:number => t.ticket_id,
:summary => parsed_json["ticket"]["title"],
:description => parsed_json["ticket"]["body"],
:assigned_to_id => owner.nil? ? '' : owner.as_user_id,
:acts_as_user_id => act_as.nil? ? '' : act_as.as_user_id,
:milestone_id => milestone.nil? ? '' : milestone.assembla_id,
:status => "#{state.new_name}",
:skip_alerts => true,
:priority=> (parsed_json["ticket"]["priority"] > 5) ? 5 :parsed_json["ticket"]["priority"],
:created_on => trac_time_to_date(parsed_json["ticket"]["created_at"]),
:updated_at => trac_time_to_date(parsed_json["ticket"]["updated_at"])
# :severity_id => row['type'],
# :version_id => row['version'],
# :resolution => row['resolution'],
}
}
t.update_attributes(:is_migrated=>true)
create = post_form("#{$settings[:space_url]}/tickets", ticket)
ticket_data = Crack::XML.parse(create.body)
ass_ticket_id = ticket_data["ticket"]["id"]
#update Tickets
versions = parsed_json["ticket"]["versions"]
versions.each do |v|
u_act_as = User.find_by_lh_user_id(v["user_id"].to_i)
u_state = TicketStatus.find_by_old_name(v["state"])
u_ticket = { :ticket => {
:number => t.ticket_id,
:skip_alerts => true,
:status => "#{u_state.new_name}",
:acts_as_user_id => u_act_as.nil? ? '' : u_act_as.as_user_id,
:updated_at => trac_time_to_date(v["updated_at"]),
:user_comment=> v["body"]
}
}
update = put_form("#{$settings[:space_url]}/tickets/#{t.ticket_id}", u_ticket)
end
attachments = parsed_json["ticket"]["attachments"]
if !attachments.nil?
attachments.each do |a|
if a.has_key?("image")
attach_path = "#{$settings[:file_path]}/#{t.ticket_directory}/#{a["image"]["filename"]}"
uploader = User.find_by_lh_user_id(a["image"]["uploader_id"].to_i)
File.open(attach_path) do |f|
# TODO Add some tag to documents
params = {
'document[file]' => f,
'document[name]' => a["image"]["filename"],
'document[skip_alerts]' => true,
'document[created_at]' => trac_time_to_date(a["image"]["created_at"]),
'document[updated_at]' => trac_time_to_date(a["image"]["created_at"]),
'document[created_by]' => uploader.nil? ? '' : uploader.as_user_id,
'document[updated_by]' => uploader.nil? ? '' : uploader.as_user_id,
'document[attachable_id]' => ass_ticket_id.to_s,
'document[attachable_type]' => 'Ticket'
}
print '.'
begin
upload_file params
rescue RemoteError =>e
# TODO count failing requests
p e
p params
end
end
end
end
end
end
end
def api_url
@api_url ||= extract_api_url
end
def extract_api_url
u = URI.parse($settings[:space_url])
u.path = u.path.split(/\//)[0..2].join('/')
@api_path = u.path
u.to_s
end
def post_form(api_uri, form_data)
request = http_method :post, api_uri
request.form_data = rails_values form_data
response = @http.request(request)
end
def put_form(api_uri, form_data)
request = http_method :put, api_uri
request.form_data = rails_values form_data
response = @http.request(request)
end
def get_list(api_uri)
request = http_method :get, api_uri
response = @http.request(request)
end
def upload_file(params)
api_uri = "#{@api_path}/documents"
mp = MultipartPost.new
query, headers = mp.prepare_query(params)
request = http_method :post, api_uri, headers
request.body = query
response = @http.request(request)
File.open("/tmp/upload-request.log", 'w') {|f| f.write(request.body) }
File.open("/tmp/upload-response.log", 'w') {|f| f.write(response.body) }
end
def trac_time_to_date(time, default = nil)
return default if time.to_i == 0
t = Time.at time.to_i
Date.new(t.year, t.month, t.day)
end
def trac_time_to_time(time, default = nil)
return default if time.to_i == 0
Time.at time.to_i
end
def http_method(method, api_uri, headers = { })
case method
when :get
klass = Net::HTTP::Get
when :post
klass = Net::HTTP::Post
when :put
klass = Net::HTTP::Put
when :delete
klass = Net::HTTP::Delete
else
raise 'Invalid method'
end
request = klass.new(api_uri, {'Accept' => 'application/xml'}.update(headers))
request.basic_auth $settings[:username], $settings[:password]
request
end
def rails_values params = { }
rez = { }
params.each do |k, v|
if v.is_a?(Hash)
rez.update(hash_param(k, v))
elsif v.is_a?(Time)
rez[k] = v.utc.strftime("%Y-%m-%d %H:%M:%S")
elsif v.is_a?(Date)
rez[k] = v.strftime("%Y-%m-%d")
else
rez[k] = v
end
end
rez
end
def hash_param key, value
rez = { }
value.each do |k, v|
rez["#{key}[#{k}]"] = v
end
rez
end
end
class FileParam
attr_accessor :k, :filename, :content
def initialize( k, filename, content )
@k = k
@filename = filename
@content = content
end
def to_multipart
#return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{filename}\"\r\n" + "Content-Transfer-Encoding: binary\r\n" + "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n "
# Don't escape mine
return "Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" + "Content-Transfer-Encoding: binary\r\n" + "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n"
end
end
class MultipartPost
BOUNDARY = 'tarsiers-rule0000'
HEADER = {"Content-type" => "multipart/form-data, boundary=" + BOUNDARY + " "}
def prepare_query (params)
fp = []
params.each {|k,v|
if v.respond_to?(:read)
fp.push(FileParam.new(k, v.path, v.read))
else
fp.push(Param.new(k,v))
end
}
query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
return query, HEADER
end
end
class Param
attr_accessor :k, :v
def initialize( k, v )
@k = k
@v = v
end
def to_multipart
#return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
# Don't escape mine...
return "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n"
end
end
class RemoteError < StandardError
attr_accessor :message, :body
def initialize(message, body)
self.message = message
self.body = body.to_s
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment