rtmapi 0.5.2 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +11 -0
  2. data/lib/rtmapi.rb +214 -96
  3. 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
 
@@ -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.5'
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.get))
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
- class DateSet
497
-
498
- def initialize(startDate, rule)
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
- if rule =~ /BYMONTH=(.*?);/ then
531
- @byMonth = $1
532
- end
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
- if rule =~ /BYDAY=(.*?);/ then
535
- @byDay = $1
536
- #puts "byDay = #{@byDay}"
537
- end
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
- def to_s
541
- # after/every FREQ
542
- puts "UNIMPLETEMENT"
543
- # puts "#<DateSet: starts: #{@startDate.strftime("%m/%d/%Y")}, occurs: #{@frequency}, count: #{@count}, until: #{@untilDate}, byMonth: #{@byMonth}, byDay: #{@byDay}>"
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
- def includes?(date)
547
- return true if date == @startDate
548
- return false if @untilDate and date > @untilDate
549
-
550
- case @frequency
551
- when 'DAILY'
552
- #if @untilDate then
553
- # return (@startDate..@untilDate).include?(date)
554
- #end
555
- increment = @interval ? @interval : 1
556
- d = @startDate
557
- counter = 0
558
- until d > date
559
-
560
- if @count then
561
- counter += 1
562
- if counter >= @count
563
- return false
564
- end
565
- end
566
-
567
- d += (increment * SECONDS_PER_DAY)
568
- if d.day == date.day and
569
- d.year == date.year and
570
- d.month == date.month then
571
- puts "true for start: #{@startDate}, until: #{@untilDate}"
572
- return true
573
- end
574
-
575
- end
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
- end
585
-
586
- false
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
- attr_reader :frequency
590
- attr_accessor :startDate
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
- class RememberTheMilkTask < RememberTheMilkHash
595
- # The API is aware it's creating tasks. You may want to add semantics to a "task"
596
- # elsewhere in your program. This gives you that flexibility
597
- end
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
@@ -3,7 +3,7 @@ rubygems_version: 0.9.1
3
3
  specification_version: 1
4
4
  name: rtmapi
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.5.2
6
+ version: "0.6"
7
7
  date: 2007-02-01 00:00:00 -05:00
8
8
  summary: Simple library for interfacing with rememberthemilk.com.
9
9
  require_paths: