rtmapi 0.5.2 → 0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +11 -0
- data/lib/rtmapi.rb +214 -96
- metadata +1 -1
    
        data/README
    CHANGED
    
    | @@ -143,6 +143,17 @@ But this will allow you to add special functionality to tasks | |
| 143 143 | 
             
            like).  If there is interest, we can do the same thing for 
         | 
| 144 144 | 
             
            groups, lists, etc etc.
         | 
| 145 145 |  | 
| 146 | 
            +
            RememberTheMilkTask also has a number of helper methods, so you can
         | 
| 147 | 
            +
            do this:
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            task = @rtm.tasks.getList.values[0].values[0]  # grabs 1st task off of first list returned by API
         | 
| 150 | 
            +
            modified_task = task.setTags "tag1,tag2"
         | 
| 151 | 
            +
            modified_task_2 = modified_task.addTags "tag3"
         | 
| 152 | 
            +
            modified_task.tags => ['tag1','tag2']
         | 
| 153 | 
            +
            modified_task_2.tags => ['tag1','tag2', 'tag3']
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            all the methods for rtm.tasks.* have helper methods defined (except for getList)
         | 
| 156 | 
            +
             | 
| 146 157 | 
             
            Dates
         | 
| 147 158 | 
             
            -----
         | 
| 148 159 |  | 
    
        data/lib/rtmapi.rb
    CHANGED
    
    | @@ -31,7 +31,7 @@ require 'xml/libxml' | |
| 31 31 | 
             
            #TODO:  allow specifying whether retval should be indexed by rtm_id or list name for lists
         | 
| 32 32 |  | 
| 33 33 | 
             
            class RememberTheMilk
         | 
| 34 | 
            -
              RUBY_API_VERSION = '0. | 
| 34 | 
            +
              RUBY_API_VERSION = '0.6'
         | 
| 35 35 | 
             
              # you can just put set these here so you don't have to pass them in with 
         | 
| 36 36 | 
             
              # every constructor call
         | 
| 37 37 | 
             
              API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
         | 
| @@ -59,8 +59,12 @@ class RememberTheMilk | |
| 59 59 | 
             
                @user_settings_cache[auth_token]
         | 
| 60 60 | 
             
              end
         | 
| 61 61 |  | 
| 62 | 
            +
              def get_timeline
         | 
| 63 | 
            +
                user[:timeline] ||= timelines.create
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
              
         | 
| 62 66 | 
             
              def time_to_user_tz( time )
         | 
| 63 | 
            -
                return time unless(@use_user_tz && @auth_token && defined?(TZInfo::Timezone | 
| 67 | 
            +
                return time unless(@use_user_tz && @auth_token && defined?(TZInfo::Timezone))
         | 
| 64 68 | 
             
                begin
         | 
| 65 69 | 
             
                  unless defined?(@user_settings_cache[auth_token]) && defined?(@user_settings_cache[auth_token][:tz])
         | 
| 66 70 | 
             
                    @user_settings_cache[auth_token] = settings.getList
         | 
| @@ -296,7 +300,7 @@ class RememberTheMilk | |
| 296 300 | 
             
                tasks = RememberTheMilkHash.new
         | 
| 297 301 |  | 
| 298 302 | 
             
                list.each do |taskseries_as_hash|
         | 
| 299 | 
            -
                  taskseries = RememberTheMilkTask.new.merge(taskseries_as_hash)
         | 
| 303 | 
            +
                  taskseries = RememberTheMilkTask.new(self).merge(taskseries_as_hash)
         | 
| 300 304 |  | 
| 301 305 | 
             
                  taskseries[:parent_list] = list_id  # parent pointers are nice
         | 
| 302 306 | 
             
                  taskseries[:tasks] = taskseries.arrayify_value(:task)
         | 
| @@ -489,109 +493,223 @@ class RememberTheMilkHash < Hash | |
| 489 493 | 
             
            end
         | 
| 490 494 |  | 
| 491 495 |  | 
| 496 | 
            +
            ## TODO -- better rrule support.  start here with this code, commented out for now
         | 
| 492 497 | 
             
            ## DateSet is to manage rrules
         | 
| 493 498 | 
             
            ## this comes from the iCal ruby module as mentioned here:
         | 
| 494 499 | 
             
            ## http://www.macdevcenter.com/pub/a/mac/2003/09/03/rubycocoa.html
         | 
| 495 500 |  | 
| 496 | 
            -
             | 
| 497 | 
            -
             | 
| 498 | 
            -
             | 
| 499 | 
            -
                    @startDate = startDate
         | 
| 500 | 
            -
                    @frequency = nil
         | 
| 501 | 
            -
                    @count = nil
         | 
| 502 | 
            -
                    @untilDate = nil
         | 
| 503 | 
            -
                    @byMonth = nil
         | 
| 504 | 
            -
                    @byDay = nil
         | 
| 505 | 
            -
                    @starts = nil
         | 
| 506 | 
            -
                    if not rule.nil? then
         | 
| 507 | 
            -
                      @starts = rule.every == 1 ? 'every' : 'after'
         | 
| 508 | 
            -
                      parseRecurrenceRule(rule.rule)
         | 
| 509 | 
            -
                    end
         | 
| 510 | 
            -
                end
         | 
| 511 | 
            -
                
         | 
| 512 | 
            -
                def parseRecurrenceRule(rule)
         | 
| 513 | 
            -
                  
         | 
| 514 | 
            -
                    if rule =~ /FREQ=(.*?);/ then
         | 
| 515 | 
            -
                        @frequency = $1
         | 
| 516 | 
            -
                    end
         | 
| 517 | 
            -
                    
         | 
| 518 | 
            -
                    if rule =~ /COUNT=(\d*)/ then
         | 
| 519 | 
            -
                        @count = $1.to_i
         | 
| 520 | 
            -
                    end
         | 
| 521 | 
            -
                    
         | 
| 522 | 
            -
                    if rule =~ /UNTIL=(.*?)[;\r]/ then
         | 
| 523 | 
            -
                        @untilDate = DateParser.parse($1)
         | 
| 524 | 
            -
                    end
         | 
| 525 | 
            -
                    
         | 
| 526 | 
            -
                    if rule =~ /INTERVAL=(\d*)/ then
         | 
| 527 | 
            -
                        @interval = $1.to_i
         | 
| 528 | 
            -
                    end
         | 
| 501 | 
            +
            # The API is aware it's creating tasks.  You may want to add semantics to a "task"
         | 
| 502 | 
            +
            # elsewhere in your program.  This gives you that flexibility
         | 
| 503 | 
            +
            # plus, we've added some helper methods
         | 
| 529 504 |  | 
| 530 | 
            -
             | 
| 531 | 
            -
             | 
| 532 | 
            -
             | 
| 505 | 
            +
            class RememberTheMilkTask < RememberTheMilkHash
         | 
| 506 | 
            +
              attr_accessor :rtm
         | 
| 507 | 
            +
              
         | 
| 508 | 
            +
              def timeline
         | 
| 509 | 
            +
                @timeline ||= rtm.get_timeline  # this caches timelines per user
         | 
| 510 | 
            +
              end
         | 
| 533 511 |  | 
| 534 | 
            -
             | 
| 535 | 
            -
             | 
| 536 | 
            -
             | 
| 537 | 
            -
             | 
| 512 | 
            +
              def initialize( rtm_api_handle=nil )
         | 
| 513 | 
            +
                super
         | 
| 514 | 
            +
                @rtm = rtm_api_handle   # keep track of this so we can do setters (see factory below)
         | 
| 515 | 
            +
              end
         | 
| 516 | 
            +
              
         | 
| 517 | 
            +
              def task() tasks[-1] end
         | 
| 518 | 
            +
              def taskseries_id() rtm_id end
         | 
| 519 | 
            +
              def task_id() task.rtm_id end
         | 
| 520 | 
            +
              def list_id() parent_list end
         | 
| 521 | 
            +
              def due() task.due  end
         | 
| 522 | 
            +
             | 
| 523 | 
            +
              def has_due?()      due.class == Time                end
         | 
| 524 | 
            +
              def has_due_time?() task.has_due_time == '1'         end
         | 
| 525 | 
            +
              def complete?()     task[:completed] != ''          end
         | 
| 526 | 
            +
              def to_s
         | 
| 527 | 
            +
                "#{parent_list}/#{taskseries_id}/#{task_id}: #{name}"
         | 
| 528 | 
            +
              end
         | 
| 529 | 
            +
             | 
| 530 | 
            +
              def due_display
         | 
| 531 | 
            +
                if has_due? 
         | 
| 532 | 
            +
                  if has_due_time?
         | 
| 533 | 
            +
                    due.strftime("%a %d %b %y at %I:%M%p")
         | 
| 534 | 
            +
                  else
         | 
| 535 | 
            +
                    due.strftime("%a %d %b %y")
         | 
| 536 | 
            +
                  end
         | 
| 537 | 
            +
                else 
         | 
| 538 | 
            +
                  '[no due date]'
         | 
| 538 539 | 
             
                end
         | 
| 539 | 
            -
             | 
| 540 | 
            -
             | 
| 541 | 
            -
             | 
| 542 | 
            -
             | 
| 543 | 
            -
             | 
| 540 | 
            +
              end
         | 
| 541 | 
            +
             | 
| 542 | 
            +
              @@BeginningOfEpoch = Time.parse("Jan 1 1904") # kludgey.. sure.  life's a kludge. deal with it.
         | 
| 543 | 
            +
              include Comparable
         | 
| 544 | 
            +
              def <=>(other)
         | 
| 545 | 
            +
                due = (has_key?(:tasks) && tasks.class == Array) ? task[:due] : nil
         | 
| 546 | 
            +
                due = @@BeginningOfEpoch unless due.class == Time
         | 
| 547 | 
            +
                other_due = (other.has_key?(:tasks) && other.tasks.class == Array) ? other.task[:due] : nil
         | 
| 548 | 
            +
                other_due = @@BeginningOfEpoch unless other_due.class == Time
         | 
| 549 | 
            +
             | 
| 550 | 
            +
                # sort based on due date, then priority, then name
         | 
| 551 | 
            +
                # if 0 was false in ruby, we could have done
         | 
| 552 | 
            +
                # prio <=> other_due || due <=> other_due || self['name'].to_s <=> other['name'].to_s
         | 
| 553 | 
            +
                # but it's not, so oh well....
         | 
| 554 | 
            +
                prio = priority.to_i
         | 
| 555 | 
            +
                prio += 666 if prio == 0  # prio of 0 is no priority which means it should show up below 1-3
         | 
| 556 | 
            +
                other_prio = other.priority.to_i
         | 
| 557 | 
            +
                other_prio += 666 if other_prio == 0
         | 
| 558 | 
            +
             | 
| 559 | 
            +
                if prio != other_prio
         | 
| 560 | 
            +
                  return prio <=> other_prio
         | 
| 561 | 
            +
                elsif due != other_due
         | 
| 562 | 
            +
                  return due <=> other_due
         | 
| 563 | 
            +
                else 
         | 
| 564 | 
            +
                  # TODO: should this be case insensitive?  
         | 
| 565 | 
            +
                  return self[:name].to_s <=> other[:name].to_s
         | 
| 544 566 | 
             
                end
         | 
| 545 | 
            -
             | 
| 546 | 
            -
             | 
| 547 | 
            -
             | 
| 548 | 
            -
             | 
| 549 | 
            -
             | 
| 550 | 
            -
             | 
| 551 | 
            -
             | 
| 552 | 
            -
             | 
| 553 | 
            -
             | 
| 554 | 
            -
             | 
| 555 | 
            -
             | 
| 556 | 
            -
             | 
| 557 | 
            -
             | 
| 558 | 
            -
             | 
| 559 | 
            -
             | 
| 560 | 
            -
             | 
| 561 | 
            -
             | 
| 562 | 
            -
             | 
| 563 | 
            -
             | 
| 564 | 
            -
             | 
| 565 | 
            -
             | 
| 566 | 
            -
             | 
| 567 | 
            -
             | 
| 568 | 
            -
             | 
| 569 | 
            -
             | 
| 570 | 
            -
             | 
| 571 | 
            -
             | 
| 572 | 
            -
             | 
| 573 | 
            -
             | 
| 574 | 
            -
             | 
| 575 | 
            -
             | 
| 576 | 
            -
                            
         | 
| 577 | 
            -
                        when 'WEEKLY'
         | 
| 578 | 
            -
                            return true if @startDate.wday == date.wday
         | 
| 579 | 
            -
                            
         | 
| 580 | 
            -
                        when 'MONTHLY'
         | 
| 581 | 
            -
                            
         | 
| 582 | 
            -
                        when 'YEARLY'
         | 
| 567 | 
            +
              end
         | 
| 568 | 
            +
              
         | 
| 569 | 
            +
              # Factory Methods... 
         | 
| 570 | 
            +
              # these are for methods that take arguments and apply to the taskseries
         | 
| 571 | 
            +
              # if you have RememberTheMilkTask called task, you might do:
         | 
| 572 | 
            +
              #  task.addTags( 'tag1, tag2, tag3' )
         | 
| 573 | 
            +
              #  task.setRecurrence   # turns off all rrules
         | 
| 574 | 
            +
              #  task.complete  # marks last task as complete
         | 
| 575 | 
            +
              #  task.setDueDate # unsets due date for last task
         | 
| 576 | 
            +
              #  task.setDueDate( nil, :task_id => task.tasks[0].id )  # unsets due date for first task in task array
         | 
| 577 | 
            +
              #  task.setDueDate( "tomorrow at 1pm", :parse => 1 )  # sets due date for last task to tomorrow at 1pm
         | 
| 578 | 
            +
              [['addTags','tags'], ['setTags', 'tags'], ['removeTags', 'tags'], ['setName', 'name'],
         | 
| 579 | 
            +
               ['setRecurrence', 'repeat'], ['complete', ''], ['uncomplete', ''], ['setDueDate', 'due'], 
         | 
| 580 | 
            +
                ['setPriority', 'priority'], ['movePriority', 'direction'], ['setEstimate', 'estimate'],
         | 
| 581 | 
            +
                ['setURL', 'url'], ['postpone', ''], ['delete', ''] ].each do |method_name, arg|
         | 
| 582 | 
            +
                  class_eval <<-RTM_METHOD
         | 
| 583 | 
            +
                 def #{method_name} ( value=nil, args={} )
         | 
| 584 | 
            +
                   if @rtm == nil
         | 
| 585 | 
            +
                    raise RememberTheMilkAPIError.new( :code => '667', :msg => "#{method_name} called without a handle to an rtm object [#{self.to_s}]" )
         | 
| 586 | 
            +
                   end
         | 
| 587 | 
            +
                   method_args = {}
         | 
| 588 | 
            +
                   method_args["#{arg}"] = value if "#{arg}" != '' && value
         | 
| 589 | 
            +
                   method_args[:timeline] = timeline
         | 
| 590 | 
            +
                   method_args[:list_id] = list_id
         | 
| 591 | 
            +
                   method_args[:taskseries_id] = taskseries_id
         | 
| 592 | 
            +
                   method_args[:task_id] = task_id
         | 
| 593 | 
            +
                   method_args.merge!( args )
         | 
| 594 | 
            +
                   @rtm.call_api_method( "tasks.#{method_name}", method_args )  # returns the modified task
         | 
| 595 | 
            +
                 end
         | 
| 596 | 
            +
                 RTM_METHOD
         | 
| 597 | 
            +
              end
         | 
| 583 598 |  | 
| 584 | 
            -
             | 
| 585 | 
            -
             | 
| 586 | 
            -
             | 
| 599 | 
            +
              # We have to do this because moveTo takes a "from_list_id", not "list_id", so the above factory
         | 
| 600 | 
            +
              #  wouldn't work.  sigh.
         | 
| 601 | 
            +
              def moveTo( to_list_id, args = {} )
         | 
| 602 | 
            +
                if @rtm == nil
         | 
| 603 | 
            +
                  raise RememberTheMilkAPIError.new( :code => '667', :msg => "moveTO called without a handle to an rtm object [#{self.to_s}]" )
         | 
| 587 604 | 
             
                end
         | 
| 588 | 
            -
                
         | 
| 589 | 
            -
                 | 
| 590 | 
            -
                 | 
| 605 | 
            +
                method_args = {}
         | 
| 606 | 
            +
                method_args[:timeline] = timeline
         | 
| 607 | 
            +
                method_args[:from_list_id] = list_id
         | 
| 608 | 
            +
                method_args[:to_list_id] = to_list_id
         | 
| 609 | 
            +
                method_args[:taskseries_id] = taskseries_id
         | 
| 610 | 
            +
                method_args[:task_id] = task_id
         | 
| 611 | 
            +
                method_args.merge( args )
         | 
| 612 | 
            +
                @rtm.call_api_method( :moveTo, method_args )
         | 
| 613 | 
            +
              end
         | 
| 614 | 
            +
             | 
| 591 615 | 
             
            end
         | 
| 592 616 |  | 
| 593 617 |  | 
| 594 | 
            -
             | 
| 595 | 
            -
             | 
| 596 | 
            -
             | 
| 597 | 
            -
             | 
| 618 | 
            +
            # 
         | 
| 619 | 
            +
            # class DateSet
         | 
| 620 | 
            +
            #     
         | 
| 621 | 
            +
            #     def initialize(startDate, rule)
         | 
| 622 | 
            +
            #         @startDate = startDate
         | 
| 623 | 
            +
            #         @frequency = nil
         | 
| 624 | 
            +
            #         @count = nil
         | 
| 625 | 
            +
            #         @untilDate = nil
         | 
| 626 | 
            +
            #         @byMonth = nil
         | 
| 627 | 
            +
            #         @byDay = nil
         | 
| 628 | 
            +
            #         @starts = nil
         | 
| 629 | 
            +
            #         if not rule.nil? then
         | 
| 630 | 
            +
            #           @starts = rule.every == 1 ? 'every' : 'after'
         | 
| 631 | 
            +
            #           parseRecurrenceRule(rule.rule)
         | 
| 632 | 
            +
            #         end
         | 
| 633 | 
            +
            #     end
         | 
| 634 | 
            +
            #     
         | 
| 635 | 
            +
            #     def parseRecurrenceRule(rule)
         | 
| 636 | 
            +
            #       
         | 
| 637 | 
            +
            #         if rule =~ /FREQ=(.*?);/ then
         | 
| 638 | 
            +
            #             @frequency = $1
         | 
| 639 | 
            +
            #         end
         | 
| 640 | 
            +
            #         
         | 
| 641 | 
            +
            #         if rule =~ /COUNT=(\d*)/ then
         | 
| 642 | 
            +
            #             @count = $1.to_i
         | 
| 643 | 
            +
            #         end
         | 
| 644 | 
            +
            #         
         | 
| 645 | 
            +
            #         if rule =~ /UNTIL=(.*?)[;\r]/ then
         | 
| 646 | 
            +
            #             @untilDate = DateParser.parse($1)
         | 
| 647 | 
            +
            #         end
         | 
| 648 | 
            +
            #         
         | 
| 649 | 
            +
            #         if rule =~ /INTERVAL=(\d*)/ then
         | 
| 650 | 
            +
            #             @interval = $1.to_i
         | 
| 651 | 
            +
            #         end
         | 
| 652 | 
            +
            # 
         | 
| 653 | 
            +
            #         if rule =~ /BYMONTH=(.*?);/ then
         | 
| 654 | 
            +
            #             @byMonth = $1
         | 
| 655 | 
            +
            #         end
         | 
| 656 | 
            +
            # 
         | 
| 657 | 
            +
            #         if rule =~ /BYDAY=(.*?);/ then
         | 
| 658 | 
            +
            #             @byDay = $1
         | 
| 659 | 
            +
            #             #puts "byDay = #{@byDay}"
         | 
| 660 | 
            +
            #         end
         | 
| 661 | 
            +
            #     end
         | 
| 662 | 
            +
            #     
         | 
| 663 | 
            +
            #     def to_s
         | 
| 664 | 
            +
            #       # after/every  FREQ
         | 
| 665 | 
            +
            #          puts "UNIMPLETEMENT"
         | 
| 666 | 
            +
            # #        puts "#<DateSet: starts: #{@startDate.strftime("%m/%d/%Y")}, occurs: #{@frequency}, count: #{@count}, until: #{@untilDate}, byMonth: #{@byMonth}, byDay: #{@byDay}>"
         | 
| 667 | 
            +
            #     end
         | 
| 668 | 
            +
            #     
         | 
| 669 | 
            +
            #     def includes?(date)
         | 
| 670 | 
            +
            #         return true if date == @startDate
         | 
| 671 | 
            +
            #         return false if @untilDate and date > @untilDate
         | 
| 672 | 
            +
            #         
         | 
| 673 | 
            +
            #         case @frequency
         | 
| 674 | 
            +
            #             when 'DAILY'
         | 
| 675 | 
            +
            #                 #if @untilDate then
         | 
| 676 | 
            +
            #                 #   return (@startDate..@untilDate).include?(date)
         | 
| 677 | 
            +
            #                 #end
         | 
| 678 | 
            +
            #                 increment = @interval ? @interval : 1
         | 
| 679 | 
            +
            #                 d = @startDate
         | 
| 680 | 
            +
            #                 counter = 0
         | 
| 681 | 
            +
            #                 until d > date
         | 
| 682 | 
            +
            #                     
         | 
| 683 | 
            +
            #                     if @count then
         | 
| 684 | 
            +
            #                         counter += 1
         | 
| 685 | 
            +
            #                         if counter >= @count
         | 
| 686 | 
            +
            #                             return false
         | 
| 687 | 
            +
            #                         end
         | 
| 688 | 
            +
            #                     end
         | 
| 689 | 
            +
            # 
         | 
| 690 | 
            +
            #                     d += (increment * SECONDS_PER_DAY)
         | 
| 691 | 
            +
            #                     if  d.day == date.day and 
         | 
| 692 | 
            +
            #                         d.year == date.year and 
         | 
| 693 | 
            +
            #                         d.month == date.month then
         | 
| 694 | 
            +
            #                         puts "true for start: #{@startDate}, until: #{@untilDate}"
         | 
| 695 | 
            +
            #                         return true
         | 
| 696 | 
            +
            #                     end
         | 
| 697 | 
            +
            # 
         | 
| 698 | 
            +
            #                 end
         | 
| 699 | 
            +
            #                 
         | 
| 700 | 
            +
            #             when 'WEEKLY'
         | 
| 701 | 
            +
            #                 return true if @startDate.wday == date.wday
         | 
| 702 | 
            +
            #                 
         | 
| 703 | 
            +
            #             when 'MONTHLY'
         | 
| 704 | 
            +
            #                 
         | 
| 705 | 
            +
            #             when 'YEARLY'
         | 
| 706 | 
            +
            # 
         | 
| 707 | 
            +
            #         end
         | 
| 708 | 
            +
            #         
         | 
| 709 | 
            +
            #         false
         | 
| 710 | 
            +
            #     end
         | 
| 711 | 
            +
            #     
         | 
| 712 | 
            +
            #     attr_reader :frequency  
         | 
| 713 | 
            +
            #     attr_accessor :startDate
         | 
| 714 | 
            +
            # end
         | 
| 715 | 
            +
            # 
         | 
    
        metadata
    CHANGED