Skip to content

Instantly share code, notes, and snippets.

@oesmith
Created April 20, 2010 22:47
Show Gist options
  • Save oesmith/373186 to your computer and use it in GitHub Desktop.
Save oesmith/373186 to your computer and use it in GitHub Desktop.
#!/usr/bin/which ruby
#
# Script for adding tickets from Lighthouse to Things.
#
# Requires lighthouse-api and rb-appscript gems
#
# TODO: tags, priorities, more..?
#
# Copyright (c) 2010 Olly Smith
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
require 'rubygems'
require 'appscript'
require 'lighthouse'
# insert lighthouse account name and auth token here
Lighthouse.account = "xxxxxxxxx"
Lighthouse.token = "xxxxxxxxxxxxxxx"
things = Appscript.app('Things')
# get/create an area for the LH account
area_query = things.areas[Appscript.its.name.eq(Lighthouse.account)].get
if area_query.length == 0
puts "No project area\n"
area = things.make(
:new => :area, :with_properties => {:name => Lighthouse.account})
else
puts "Project area exists\n"
area = area_query.first
end
# iterate over all the projects
projects = Lighthouse::Project.find(:all)
things_projects = things.projects.get
projects.each do |project|
name = "LH:%s" % project.name
notes = "%s\n\n[#%d]" % [project.description, project.id]
# create/update the project in things
project_query = things_projects.select {
|x| x.notes.get.include?("[#%d]" % project.id)}
if project_query.length == 0
puts "Creating project %s\n" % project.name
properties = {:name => name, :notes => notes}
things_project = things.make(
:new => :project, :at => area, :with_properties => properties)
else
puts "Updating project %s\n" % project.name
things_project = project_query.first
things_project.name.set(name) if things_project.name.get != name
things_project.notes.set(notes) if things_project.notes.get != notes
end
# get the open states for the project
open_states = project.open_states.scan /^(\w+)\/([0-9a-fA-F]+).*$/
open_states = open_states.collect{|x| x[0]}
# get tickets from lighthouse. getting occasional random errors
# from the API, so wait and re-try if there's an exception
# raised
tickets = nil
while tickets == nil
begin
tickets = project.tickets
rescue
sleep(1)
end
end
# iterate over all the tickets
things_project_todos = things_project.to_dos.get
tickets.each do |ticket|
notes = "%s\n\n%s\n\n[#%d]" % [ticket.latest_body, ticket.url, ticket.number]
due_date = ticket.milestone_due_on
is_open = open_states.include?(ticket.state)
# create/update the ticket in things
ticket_query = things_project_todos.select {
|x| x.notes.get.include?("[#%d]" % ticket.number) }
if ticket_query.length == 0
if is_open
puts "Creating ticket %s\n" % ticket.title
properties = {
:name => ticket.title, :notes => notes}
properties[:due_date] = due_date if due_date
tkt = things_project.make(
:new => :to_do, :with_properties => properties)
else
puts "Skipping closed ticket %s\n" % ticket.title
end
else
puts "Updating ticket %s\n" % ticket.title
tkt = ticket_query.first
things_is_open = tkt.status.get == :open
if things_is_open
if not is_open
tkt.status.set(:completed)
end
else
if not is_open
things.delete(tkt)
end
end
tkt.name.set(ticket.title) if tkt.name.get != ticket.title
tkt.notes.set(notes) if tkt.notes.get != notes
tkt.due_date.set(due_date) if due_date and tkt.due_date.get != due_date
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment