Report abuse


			
#!/usr/bin/env ruby

MY_TASKO_ID = 1111   # Put your key here
MY_TASKO_KEY = 'aaa' # Put your Tasko API key here
MY_TASKS_DIR = File.join(ENV['HOME'], 'Tasks')

require 'yaml'
require 'digest/md5'
require 'xmlrpc/client'

class String
  def md5
    Digest::MD5::hexdigest(self)
  end
end

module XMLRPC
  module ParseContentType
    def parse_content_type(str)
      ["text/xml", "utf-8"]
    end
  end
end

class TaskoAPI
  XMLRPC::Config.module_eval { remove_const(:ENABLE_NIL_PARSER) }
  XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)

  URL = "http://taskodone.com/api"

  def initialize(id, pass)
    @id = id
    @pass = pass
  end

  def client
    XMLRPC::Client.new2(URL)
  end

  private :client

  def papers
    client.call("papers", @id, @pass)
  end

  def paper(name)
    client.call("paper", @id, @pass, name)
  end

  def rename(old, new)
    client.call("rename", @id, @pass, old, new)
  end

  def edit(name, data)
    client.call("edit", @id, @pass, name, data)
  end

  def newpaper(name, data = "")
    client.call("new", @id, @pass, name, data)
  end

  def delete(name)
    client.call("delete", @id, @pass, name)
  end
end

class TaskoSyncer
  EXT = '.taskpaper'

  def initialize(id, pass, dir = nil, summary_file = nil)
    @tasko = TaskoAPI.new(id, pass)
    @dir ||= File.join(ENV['HOME'], 'Tasks')
    @summary_file ||= File.join(ENV['HOME'], '.tasko.yml')
    @summary = YAML::load(File.read(@summary_file)) rescue {}
  end

  def write_task_file(paper, data)
    File.open(File.join(@dir, paper + '.taskpaper'), 'w') do |f|
      f.write data
    end
    update_summary(paper, data)
  end

  def update_summary(paper, data)
    @summary[paper] = data.md5
  end

  def save_summary
    File.open(@summary_file, 'w') do |f|
      f.write @summary.to_yaml
    end
  end

  def local_files
    Dir[File.join(@dir, "*#{EXT}")]
  end

  def summary_match?(paper, data)
    !@summary[paper].nil? and @summary[paper] == data.md5
  end

  def sync
    begin
      papers = @tasko.papers

      local_files.each do |file|
        paper = File.basename(file, EXT)
        data = File.read(file)

        if summary_match?(paper, data)
          remote_data = @tasko.paper(paper)
          if data != remote_data
            puts "Pulling #{paper}"
            write_task_file(paper, remote_data)
          end
          papers.delete(paper)          
        else
          puts "Pushing #{paper}"

          if papers.delete(paper)
            @tasko.edit(paper, data)
          else
            @tasko.newpaper(paper, data)
          end

          update_summary(paper, data)
        end
      end

      papers.each do |paper|
        if @summary[paper].nil?
          puts "Adding #{paper}"
          data = @tasko.paper(paper)
          write_task_file(paper, data)
        else
          puts "Deleting #{paper}"
          @tasko.delete(paper)
          @summary.delete(paper)
        end
      end

      save_summary
    rescue SocketError
      puts "No internet connection"
    end    
  end
end

TaskoSyncer.new(MY_TASKO_ID, MY_TASKO_KEY, MY_TASKS_DIR).sync