#!/usr/bin/env ruby # # Biggest problem with this is that it checks everything. Needs # to be adjusted to only check N days and/or N tasks on Basecamp. # # Also has a problem in that Completed always wins. If you have a # task marked at completed, then mark it as open again on just one # side, it'll mark the other as completed if you run the sync again. # # All that said, it provides a basic, very rudimentary sync. # # TODO: # - Check Logbook for items if they don't exist in their current # current location in Things. # - Control how many items to actually check for syncing purposes # - Use local cache to determine what syncing has happened in the # past and try to be smart about future syncs. require 'basecamp' # you need to d/l the basecamp.rb file from Basecamp require 'appscript' # gem install rb-appscript require 'yaml' conf = YAML.load(File.open(ENV['HOME'] + "/.sync_things.yaml")) Basecamp.establish_connection!(conf['url'], conf['username'], conf['password'], true) bucket_names = { :inbox => 1, :today => 2, :next => 3, :someday => 5, } basecamp_bucket = {} on_basecamp = {} lists = Basecamp::TodoList.all(conf['basecamp_project']) lists.each do |list| name = list.name.downcase.to_sym basecamp_bucket[name] = {} if basecamp_bucket[name].nil? on_basecamp[name] = [] if on_basecamp[name].nil? list.todo_items.each do |item| begin if item.responsible_party_id == conf['current_user'] on_basecamp[name] << item.content basecamp_bucket[name][item.content] = item end rescue # I know, I know... end end end things = Appscript.app('Things') bucket_names.each do |name,key| things.lists[key].to_dos.get.each do |to_do| idx = on_basecamp[name].index(to_do.name.get) unless on_basecamp[name].nil? # not sure why, but this is sometimes nil if !idx.nil? puts "attempting to sync [#{to_do.name.get}]" # check to see if its been completed on Basecamp if basecamp_bucket[name][to_do.name.get].completed puts " - marking local as completed" to_do.status.set(:completed) else if to_do.status.get == :completed puts " - marking remote as completed" basecamp_bucket[name][to_do.name.get].complete! end end on_basecamp[name].delete(to_do.name.get) end end end # now start adding from basecamp to things on_basecamp.each do |bucket_name, entries| entries.each do |entry| puts "adding new entry [#{entry}]" things.lists[bucket_names[bucket_name]].make( :new => :to_do, :with_properties => { :name => entry } ) end end