Skip to content

Instantly share code, notes, and snippets.

@tswicegood
Created October 1, 2009 20:13
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save tswicegood/199212 to your computer and use it in GitHub Desktop.
Save tswicegood/199212 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_username
password: your_password
current_user: your_current_user_id (pull it out of your edit 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(3786988)
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
@xeospeed
Copy link

xeospeed commented Dec 7, 2013

Does this only work with Basecamp Classic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment