Skip to content

Instantly share code, notes, and snippets.

@awalker
Forked from tswicegood/sync_things.rb
Created October 25, 2011 21:39
Show Gist options
  • Save awalker/1314400 to your computer and use it in GitHub Desktop.
Save awalker/1314400 to your computer and use it in GitHub Desktop.
Simple Ruby script to sync Basecamp and Things to-dos.
---
url: yoursubdomain.basecamphq.com
username: your_api_token
password: X
current_user: your_current_user_id (pull it out of your edit URL)
basecamp_project: your_project_id (in URL)
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment