#require 'rubygems' require 'toodledo' class ToodleDoSyncer < OSX::NSObject def session return @session if @session unless @session apiKey=ToodleDoPreferences.apiKey password=ToodleDoPreferences.password if (! apiKey || apiKey.length < 0 || ! password || password.length < 0) then doErrorAlert return end begin @session = Toodledo::Session.new(ToodleDoPreferences.apiKey,ToodleDoPreferences.password) @session.connect() rescue @session=nil return nil end end @session end def doErrorAlert alrt=NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat("Error syncing ToodleDo. Check your API key and password!","OK",nil,nil,"") alrt.runModal end def clean(moc) return unless session session.get_tasks().each{ |t| session.delete_task(t.server_id); print "deleted task #{t.server_id}\n" } session.get_contexts().each {|c| session.delete_context(c.server_id); print "deleted context #{c.server_id}\n"} session.get_folders().each { |f| session.delete_folder(f.server_id); print "deleted folder #{f.server_id}\n"} moc.objectsForEntityNamed('Action').each { |a| a.toodleID=nil} moc.objectsForEntityNamed('Context').each { |c| c.toodleID=nil} end def makeToodleFolder(f) f.toodleID=session.add_folder(f.name(),false) print "added folder #{f.name()} #{f.toodleID}\n" end def makeToodleTask(t) return if t.toodleID? if t.parent? makeToodleTask(t.parent) end if t.isArea? makeToodleFolder(t) return end args ={} if (t.context?) makeToodleContext(t.context) args[:context]=t.context().toodleID() if t.context.toodleID? end args[:tag] = "F-" if (t.parent?) if (t.parent.isArea?) args[:folder]=t.parent.toodleID else args[:parent] = t.rootProject().toodleID if t.rootProject() != nil args[:folder] = t.rootArea().toodleID if t.rootArea() != nil end if (t.parent != t.rootProject() && t.parent != t.rootArea()) args[:tag] = "F- "+ t.parent.name end end if (t.isImportant? && t.isUrgent? && t.isNext?) args[:priority]=3 elsif (t.isImportant? && t.isUrgent?) args[:priority]=2 elsif (t.isImportant?) args[:priority]=1 elsif (t.isUrgent?) args[:priority]=0 end print "making task #{t.name()}, #{args}\n" begin t.toodleID=session.add_task(t.name(),args) print "added task #{t.name()} #{t.toodleID}\n" if t.done? || t.note? then args={} args[:completed]=t.done? args[:note]=t.noteString session.edit_task(t.toodleID,args) end return t.toodleID rescue print "error making a task on toodle\n" end return nil end def makeToodleContext(c) if (!c.toodleID?) print "adding context #{c.name}\n" c.toodleID=session.add_context(c.name) print "added context #{c.name} #{c.toodleID}\n" end end def findObjectByName(moc,entity,value) ed=NSEntityDescription.entityForName_inManagedObjectContext(entity,moc) request=NSFetchRequest.alloc.init request.setEntity(ed) pred=NSPredicate.predicateWithFormat_argumentArray("name BEGINSWITH[c] %@",[value]) request.setPredicate(pred) sort=NSSortDescriptor.alloc.initWithKey_ascending("name",true) request.setSortDescriptors([sort]) error=0 result=moc.executeFetchRequest_error(request,nil) return result[0] if result && result.count > 0 return nil end def pushCompleted(task) begin print "pushing done for #{task.title}\n" session.edit_task(task.server_id,{:completed=>'true'}) rescue end end def syncAll(moc) print "toodling\n" toodleC=session.get_contexts() toodleC.each do | c | ourC = findObjectByName(moc,"Context",c.name()) ourC.toodleID = c.server_id if ourC && !ourC.toodleID if (!ourC && c.name() != "--Context--") print "adding new Context #{c.name} from Toodle\n" newC = NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Context",moc) newC.toodleID = c.server_id newC.name=c.name() end end ourTasks=moc.objectsForEntityNamed('Action') return unless session # try to connect @toodleIDLookup={} ourTasks.each do |t| unless t.toodleID? print "Making #{t.name} on Toodledo\n" makeToodleTask(t) if t.name end @toodleIDLookup["#{t.toodleID}"]=t end #print @toodleIDLookup toodleT=session.get_tasks() toodleT.each do |t| if (t.tag && t.tag.match('F-')) # we put it there, we own it ourT=@toodleIDLookup[t.server_id] ourT=@toodleIDLookup["#{t.server_id}"] if !ourT if ourT then print "found our task on toodle\n" ourT.setDone(1) if t.completed? && !ourT.done? pushCompleted(t) if !t.completed? && ourT.done? else # we no longer have it, must be deleted print "deleting task #{t.title}/#{t.server_id} on Toodle\n" session.delete_task(t.server_id) end else # New to Toodle Do. Make it ours print "found a new todo on toodle. Importing #{t.title}\n" string = t.title ourTP=nil if (t.parent_id && @toodleIDLookup[t.parent_id]) ourTP = @toodleIDLookup[t.parent_id] end if t.context string << " @#{t.context.name}" end newA = NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Action",moc) newA.toodleID = t.server_id newA.smartName=string newA.setDone(1) if t.completed? newA.setParent(ourTP) if ourTP @toodleIDLookup["#{newA.toodleID}"]=newA s = t.tag if s s << " F-" else s="F-" end session.edit_task(t.server_id,{:tag => s}) end end end end