rufus-rtm 0.1
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.txt +144 -0
- data/lib/rufus/rtm.rb +39 -0
- data/lib/rufus/rtm/base.rb +101 -0
- data/lib/rufus/rtm/credentials.rb +122 -0
- data/lib/rufus/rtm/resources.rb +347 -0
- data/test/tasks_test.rb +80 -0
- data/test/test.rb +4 -0
- metadata +69 -0
data/README.txt
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
|
2
|
+
= rufus-rtm
|
3
|
+
|
4
|
+
|
5
|
+
== getting it
|
6
|
+
|
7
|
+
sudo gem install -y rufus-rtm
|
8
|
+
|
9
|
+
or at
|
10
|
+
|
11
|
+
http://rubyforge.org/frs/?group_id=4812
|
12
|
+
|
13
|
+
|
14
|
+
== credentials
|
15
|
+
|
16
|
+
'rufus-rtm' expects to find RTM credentials in the environment. It will look for :
|
17
|
+
|
18
|
+
* RTM_API_KEY
|
19
|
+
* RTM_SHARED_SECRET
|
20
|
+
* RTM_FROB
|
21
|
+
* RTM_AUTH_TOKEN
|
22
|
+
|
23
|
+
You have to apply for the first two ones at http://www.rememberthemilk.com/services/api/keys.rtm
|
24
|
+
|
25
|
+
Once you have the API key and the shared secret, you have to get the frob and the auth token. Fire your 'irb' and
|
26
|
+
|
27
|
+
>> require 'rubygems'
|
28
|
+
>> require 'rufus/rtm'
|
29
|
+
|
30
|
+
please visit this URL with your browser and then hit 'enter' :
|
31
|
+
|
32
|
+
http://www.rememberthemilk.com/services/auth/?api_sig=70036e47c38da170fee431f04e29e8f0&frob=fa794036814b78fddf3e5641fe7c37f80e7d91fc&perms=delete&api_key=7f07e4fc5a944bf8c02a7d1e45c79346
|
33
|
+
|
34
|
+
visit, the given URL, you should finally be greeted by a message like "You have successfully authorized the application API Application. You may now close this window and continue the authentication process with the application that sent you here.", hit enter...
|
35
|
+
|
36
|
+
ok, now getting auth token...
|
37
|
+
|
38
|
+
here are your RTM_FROB and RTM_AUTH_TOKEN, make sure to place them
|
39
|
+
in your environment :
|
40
|
+
|
41
|
+
export RTM_FROB=3cef465718317b837eec2faeb5340fe777d55c7c
|
42
|
+
export RTM_AUTH_TOKEN=ca0022d705ea1831543b7cdd2d7e3d707a0e1efb
|
43
|
+
|
44
|
+
make then sure that all the 4 variables are set in the environment you use for running 'rufus-rtm'.
|
45
|
+
|
46
|
+
|
47
|
+
== usage
|
48
|
+
|
49
|
+
require 'rubygems'
|
50
|
+
require 'rufus/rtm'
|
51
|
+
|
52
|
+
#
|
53
|
+
# listing tasks
|
54
|
+
|
55
|
+
tasks = Task.find
|
56
|
+
# finding all the tasks
|
57
|
+
|
58
|
+
tasks = Task.find :filter => "status:incomplete"
|
59
|
+
# finding all the incomplete tasks
|
60
|
+
|
61
|
+
tasks.each do |task|
|
62
|
+
|
63
|
+
puts "task id #{task.task_id}"
|
64
|
+
puts " #{task.name} (#{task.tags.join(",")})"
|
65
|
+
puts
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# adding a task
|
70
|
+
|
71
|
+
task = Task.add! "study this rufus-rtm gem"
|
72
|
+
# gets added to the 'Inbox' by default
|
73
|
+
|
74
|
+
puts "task id is #{task.task_id}"
|
75
|
+
|
76
|
+
#
|
77
|
+
# enumerating lists
|
78
|
+
|
79
|
+
lists = List.find
|
80
|
+
|
81
|
+
w = lists.find { |l| l.name == 'Work' }
|
82
|
+
|
83
|
+
puts "my Work list id is #{w.list_id}"
|
84
|
+
|
85
|
+
#
|
86
|
+
# adding a task to a list
|
87
|
+
|
88
|
+
task = Task.add! "work, more work", w.list_id
|
89
|
+
|
90
|
+
#
|
91
|
+
# completing a task
|
92
|
+
|
93
|
+
task.complete!
|
94
|
+
|
95
|
+
#
|
96
|
+
# deleting a task
|
97
|
+
|
98
|
+
task.delete!
|
99
|
+
|
100
|
+
|
101
|
+
Note that the methods that change the state of the Remember The Milk dataset have names ending with an exclamation mark.
|
102
|
+
|
103
|
+
|
104
|
+
= features yet to implement
|
105
|
+
|
106
|
+
* tags modifications
|
107
|
+
* smart lists
|
108
|
+
* ...
|
109
|
+
|
110
|
+
|
111
|
+
= dependencies
|
112
|
+
|
113
|
+
The gem 'rufus-verbs' (http://rufus.rubyforge.org/rufus-verbs)
|
114
|
+
|
115
|
+
|
116
|
+
== mailing list
|
117
|
+
|
118
|
+
On the rufus-ruby list[http://groups.google.com/group/rufus-ruby] :
|
119
|
+
|
120
|
+
http://groups.google.com/group/rufus-ruby
|
121
|
+
|
122
|
+
|
123
|
+
== issue tracker
|
124
|
+
|
125
|
+
http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
|
126
|
+
|
127
|
+
|
128
|
+
== source
|
129
|
+
|
130
|
+
http://rufus.rubyforge.org/svn/trunk/rtm
|
131
|
+
|
132
|
+
svn checkout http://rufus.rubyforge.org/svn/trunk/rtm
|
133
|
+
|
134
|
+
|
135
|
+
== author
|
136
|
+
|
137
|
+
John Mettraux, jmettraux@gmail.com
|
138
|
+
http://jmettraux.wordpress.com
|
139
|
+
|
140
|
+
|
141
|
+
== license
|
142
|
+
|
143
|
+
MIT
|
144
|
+
|
data/lib/rufus/rtm.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
#
|
24
|
+
# (MIT license)
|
25
|
+
#++
|
26
|
+
#
|
27
|
+
|
28
|
+
#
|
29
|
+
# John Mettraux
|
30
|
+
#
|
31
|
+
# Made in Japan
|
32
|
+
#
|
33
|
+
# 2008/02/07
|
34
|
+
#
|
35
|
+
|
36
|
+
require 'rufus/rtm/base'
|
37
|
+
require 'rufus/rtm/credentials'
|
38
|
+
require 'rufus/rtm/resources'
|
39
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
#
|
24
|
+
# (MIT license)
|
25
|
+
#++
|
26
|
+
#
|
27
|
+
|
28
|
+
#
|
29
|
+
# John Mettraux
|
30
|
+
#
|
31
|
+
# Made in Japan
|
32
|
+
#
|
33
|
+
# 2008/02/07
|
34
|
+
#
|
35
|
+
|
36
|
+
require 'rubygems'
|
37
|
+
require 'rufus/verbs'
|
38
|
+
|
39
|
+
require 'json'
|
40
|
+
require 'md5'
|
41
|
+
|
42
|
+
include Rufus::Verbs
|
43
|
+
|
44
|
+
|
45
|
+
module Rufus
|
46
|
+
module RTM
|
47
|
+
|
48
|
+
AUTH_ENDPOINT = "http://www.rememberthemilk.com/services/auth/"
|
49
|
+
REST_ENDPOINT = "http://api.rememberthemilk.com/services/rest/"
|
50
|
+
|
51
|
+
#
|
52
|
+
# Signs the RTM request (sets the 'api_sig' parameter).
|
53
|
+
#
|
54
|
+
def self.sign (params) #:nodoc:
|
55
|
+
|
56
|
+
sig = MD5.md5(SHARED_SECRET + params.sort.flatten.join)
|
57
|
+
params['api_sig'] = sig.to_s
|
58
|
+
|
59
|
+
params
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Calls an API method (milk the cow).
|
64
|
+
#
|
65
|
+
def self.milk (params={}) #:nodoc:
|
66
|
+
|
67
|
+
sleep 1
|
68
|
+
|
69
|
+
endpoint = params.delete :endpoint
|
70
|
+
endpoint = AUTH_ENDPOINT if endpoint == :auth
|
71
|
+
endpoint = endpoint || REST_ENDPOINT
|
72
|
+
|
73
|
+
ps = params.inject({}) do |r, (k, v)|
|
74
|
+
r[k.to_s] = v
|
75
|
+
r
|
76
|
+
end
|
77
|
+
|
78
|
+
ps['api_key'] = API_KEY
|
79
|
+
ps['format'] = "json"
|
80
|
+
|
81
|
+
ps['frob'] = FROB if FROB
|
82
|
+
ps['auth_token'] = AUTH_TOKEN if AUTH_TOKEN
|
83
|
+
|
84
|
+
sign ps
|
85
|
+
|
86
|
+
res = get endpoint, :query => ps
|
87
|
+
|
88
|
+
JSON.parse(res.body)["rsp"]
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Requests a timeline from RTM.
|
93
|
+
#
|
94
|
+
def self.get_timeline #:nodoc:
|
95
|
+
|
96
|
+
milk(:method => "rtm.timelines.create")['timeline']
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,122 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
#
|
24
|
+
# (MIT license)
|
25
|
+
#++
|
26
|
+
#
|
27
|
+
|
28
|
+
#
|
29
|
+
# John Mettraux
|
30
|
+
#
|
31
|
+
# Made in Japan
|
32
|
+
#
|
33
|
+
# 2008/02/07
|
34
|
+
#
|
35
|
+
|
36
|
+
module Rufus::RTM
|
37
|
+
|
38
|
+
def self.auth_get_frob #:nodoc:
|
39
|
+
|
40
|
+
r = milk :method => "rtm.auth.getFrob"
|
41
|
+
r["frob"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.auth_get_frob_and_url #:nodoc:
|
45
|
+
|
46
|
+
frob = auth_get_frob
|
47
|
+
|
48
|
+
p = {}
|
49
|
+
p['api_key'] = API_KEY
|
50
|
+
p['perms'] = "delete"
|
51
|
+
p['frob'] = frob
|
52
|
+
sign p
|
53
|
+
|
54
|
+
[
|
55
|
+
frob,
|
56
|
+
AUTH_ENDPOINT + "?" + p.collect { |k, v| "#{k}=#{v}" }.join("&")
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.auth_get_token (frob) #:nodoc:
|
61
|
+
|
62
|
+
begin
|
63
|
+
milk(:method => "rtm.auth.getToken", :frob => frob)['auth']['token']
|
64
|
+
rescue Exception => e
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# ensuring the credentials are present...
|
71
|
+
|
72
|
+
API_KEY = ENV['RTM_API_KEY']
|
73
|
+
SHARED_SECRET = ENV['RTM_SHARED_SECRET']
|
74
|
+
|
75
|
+
raise "API_KEY missing from environment, cannot use Rufus::RTM" \
|
76
|
+
unless API_KEY
|
77
|
+
|
78
|
+
FROB = ENV['RTM_FROB']
|
79
|
+
AUTH_TOKEN = ENV['RTM_AUTH_TOKEN']
|
80
|
+
|
81
|
+
unless FROB
|
82
|
+
|
83
|
+
frob, auth_url = auth_get_frob_and_url
|
84
|
+
|
85
|
+
puts <<-EOS
|
86
|
+
|
87
|
+
please visit this URL with your browser and then hit 'enter' :
|
88
|
+
|
89
|
+
#{auth_url}
|
90
|
+
|
91
|
+
EOS
|
92
|
+
|
93
|
+
STDIN.gets
|
94
|
+
puts "ok, now getting auth token...\n"
|
95
|
+
|
96
|
+
auth_token = auth_get_token frob
|
97
|
+
|
98
|
+
if auth_token
|
99
|
+
|
100
|
+
puts <<-EOS
|
101
|
+
|
102
|
+
here are your RTM_FROB and RTM_AUTH_TOKEN, make sure to place them
|
103
|
+
in your environment :
|
104
|
+
|
105
|
+
export RTM_FROB=#{frob}
|
106
|
+
export RTM_AUTH_TOKEN=#{auth_token}
|
107
|
+
|
108
|
+
EOS
|
109
|
+
else
|
110
|
+
|
111
|
+
puts <<-EOS
|
112
|
+
|
113
|
+
couldn't get auth token, please retry...
|
114
|
+
|
115
|
+
EOS
|
116
|
+
end
|
117
|
+
|
118
|
+
exit 0
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
@@ -0,0 +1,347 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
#
|
24
|
+
# (MIT license)
|
25
|
+
#++
|
26
|
+
#
|
27
|
+
|
28
|
+
#
|
29
|
+
# John Mettraux
|
30
|
+
#
|
31
|
+
# Made in Japan
|
32
|
+
#
|
33
|
+
# 2008/02/07
|
34
|
+
#
|
35
|
+
|
36
|
+
module Rufus::RTM
|
37
|
+
|
38
|
+
#
|
39
|
+
# A parent class for Task, List and co.
|
40
|
+
#
|
41
|
+
# Never use directly.
|
42
|
+
#
|
43
|
+
class MilkResource
|
44
|
+
|
45
|
+
def initialize (hsh)
|
46
|
+
|
47
|
+
@hsh = hsh
|
48
|
+
@operations = []
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Saves the instance back to RTM.
|
53
|
+
#
|
54
|
+
def save!
|
55
|
+
|
56
|
+
# TODO : compact !
|
57
|
+
|
58
|
+
@operations.reverse.each do |method_name, args|
|
59
|
+
|
60
|
+
self.class.execute method_name, args
|
61
|
+
end
|
62
|
+
@operations = []
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
#
|
68
|
+
# a class method for listing attributes that can be found
|
69
|
+
# in the hash reply coming from RTM...
|
70
|
+
#
|
71
|
+
def self.milk_attr (*att_names) #:nodoc:
|
72
|
+
|
73
|
+
att_names.each do |att_name|
|
74
|
+
class_eval """
|
75
|
+
def #{att_name}
|
76
|
+
@hsh['#{att_name}']
|
77
|
+
end
|
78
|
+
"""
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Calls the milk() method (interacts with the RTM API).
|
84
|
+
#
|
85
|
+
def self.execute (method_name, args={})
|
86
|
+
|
87
|
+
args[:method] = "rtm.#{resource_name}.#{method_name}"
|
88
|
+
|
89
|
+
Rufus::RTM.milk args
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Returns the name of the resource as the API knows it
|
94
|
+
# (for example 'tasks' or 'lists').
|
95
|
+
#
|
96
|
+
def self.resource_name
|
97
|
+
|
98
|
+
self.to_s.split("::")[-1].downcase + "s"
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Simply calls the timeline() class method.
|
103
|
+
#
|
104
|
+
def timeline
|
105
|
+
|
106
|
+
MilkResource.timeline
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Returns the current timeline (fetches one if none has yet
|
111
|
+
# been prepared).
|
112
|
+
#
|
113
|
+
def self.timeline
|
114
|
+
|
115
|
+
@timeline ||= Rufus::RTM.get_timeline
|
116
|
+
end
|
117
|
+
|
118
|
+
def queue_operation (method_name, args)
|
119
|
+
|
120
|
+
@operations << [ method_name, args ]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# The RTM Task class.
|
126
|
+
#
|
127
|
+
class Task < MilkResource
|
128
|
+
|
129
|
+
def self.task_attr (*att_names) #:nodoc:
|
130
|
+
|
131
|
+
att_names.each do |att_name|
|
132
|
+
class_eval """
|
133
|
+
def #{att_name}
|
134
|
+
@hsh['task']['#{att_name}']
|
135
|
+
end
|
136
|
+
"""
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
attr_reader \
|
141
|
+
:list_id,
|
142
|
+
:taskseries_id,
|
143
|
+
:task_id,
|
144
|
+
:tags
|
145
|
+
|
146
|
+
milk_attr \
|
147
|
+
:name,
|
148
|
+
:modified,
|
149
|
+
:participants,
|
150
|
+
:url,
|
151
|
+
:notes,
|
152
|
+
:location_id,
|
153
|
+
:created,
|
154
|
+
:source
|
155
|
+
|
156
|
+
task_attr \
|
157
|
+
:completed,
|
158
|
+
:added,
|
159
|
+
:postponed,
|
160
|
+
:priority,
|
161
|
+
:deleted,
|
162
|
+
:has_due_time,
|
163
|
+
:estimate,
|
164
|
+
:due
|
165
|
+
|
166
|
+
def initialize (list_id, h)
|
167
|
+
|
168
|
+
super(h)
|
169
|
+
|
170
|
+
t = h['task']
|
171
|
+
|
172
|
+
@list_id = list_id
|
173
|
+
@taskseries_id = h['id']
|
174
|
+
@task_id = t['id']
|
175
|
+
|
176
|
+
@tags = TagArray.new self, h['tags']
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Deletes the task.
|
181
|
+
#
|
182
|
+
def delete!
|
183
|
+
|
184
|
+
self.class.execute "delete", prepare_api_args
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Marks the task as completed.
|
189
|
+
#
|
190
|
+
def complete!
|
191
|
+
|
192
|
+
self.class.execute "complete", prepare_api_args
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Sets the tags for the task.
|
197
|
+
#
|
198
|
+
def tags= (tags)
|
199
|
+
|
200
|
+
tags = tags.split(",") if tags.is_a?(String)
|
201
|
+
|
202
|
+
@tags = TagArray.new(list_id, tags)
|
203
|
+
|
204
|
+
queue_operation("setTasks", tags.join(","))
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.find (params={})
|
208
|
+
|
209
|
+
parse_tasks(execute("getList", params))
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
# Adds a new task (and returns it).
|
214
|
+
#
|
215
|
+
def self.add! (name, list_id=nil)
|
216
|
+
|
217
|
+
args = {}
|
218
|
+
args[:name] = name
|
219
|
+
args[:list_id] = list_id if list_id
|
220
|
+
args[:timeline] = Rufus::RTM.get_timeline
|
221
|
+
|
222
|
+
h = execute "add", args
|
223
|
+
|
224
|
+
parse_tasks(h)[0]
|
225
|
+
end
|
226
|
+
|
227
|
+
protected
|
228
|
+
|
229
|
+
def prepare_api_args
|
230
|
+
{
|
231
|
+
:timeline => timeline,
|
232
|
+
:list_id => list_id,
|
233
|
+
:taskseries_id => taskseries_id,
|
234
|
+
:task_id => task_id
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.parse_tasks (o)
|
239
|
+
|
240
|
+
o = if o.is_a?(Hash)
|
241
|
+
|
242
|
+
r = o[resource_name]
|
243
|
+
o = r if r
|
244
|
+
o['list']
|
245
|
+
end
|
246
|
+
|
247
|
+
o = [ o ] unless o.is_a?(Array)
|
248
|
+
# Nota bene : not the same thing as o = Array(o)
|
249
|
+
|
250
|
+
o.inject([]) do |r, h|
|
251
|
+
|
252
|
+
list_id = h['id']
|
253
|
+
s = h['taskseries']
|
254
|
+
r += parse_taskseries(list_id, s) if s
|
255
|
+
r
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.parse_taskseries (list_id, o)
|
260
|
+
|
261
|
+
o = [ o ] unless o.is_a?(Array)
|
262
|
+
o.collect { |s| self.new list_id, s }
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class List < MilkResource
|
267
|
+
|
268
|
+
attr \
|
269
|
+
:list_id
|
270
|
+
|
271
|
+
milk_attr \
|
272
|
+
:name, :sort_order, :smart, :archived, :deleted, :position, :locked
|
273
|
+
|
274
|
+
def initialize (h)
|
275
|
+
|
276
|
+
super
|
277
|
+
@list_id = h['id']
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.find
|
281
|
+
|
282
|
+
execute("getList")[resource_name]['list'].collect do |h|
|
283
|
+
self.new h
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
# An array of tasks.
|
290
|
+
#
|
291
|
+
class TagArray #:nodoc:
|
292
|
+
include Enumerable
|
293
|
+
|
294
|
+
def initialize (task, tags)
|
295
|
+
|
296
|
+
@task = task
|
297
|
+
|
298
|
+
@tags = if tags.is_a?(Array)
|
299
|
+
tags
|
300
|
+
else
|
301
|
+
tags['tag']
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def << (tag)
|
306
|
+
|
307
|
+
@tags << tag
|
308
|
+
|
309
|
+
args = prepare_api_args
|
310
|
+
args[:tags] = tag
|
311
|
+
|
312
|
+
@task.queue_operation "addTags", args
|
313
|
+
end
|
314
|
+
|
315
|
+
def delete (tag)
|
316
|
+
|
317
|
+
@tags.delete tag
|
318
|
+
|
319
|
+
args = prepare_api_args
|
320
|
+
args[:tags] = tag
|
321
|
+
|
322
|
+
@task.queue_operation "removeTags", args
|
323
|
+
end
|
324
|
+
|
325
|
+
def clear
|
326
|
+
|
327
|
+
@tags.clear
|
328
|
+
|
329
|
+
args = prepare_api_args
|
330
|
+
args[:tags] = ''
|
331
|
+
|
332
|
+
@task.queue_operation "setTags", args
|
333
|
+
end
|
334
|
+
|
335
|
+
def join (s)
|
336
|
+
|
337
|
+
@tags.join s
|
338
|
+
end
|
339
|
+
|
340
|
+
def each
|
341
|
+
|
342
|
+
@tags.each { |e| yield e }
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
347
|
+
|
data/test/tasks_test.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-rtm
|
4
|
+
#
|
5
|
+
# John Mettraux at openwfe.org
|
6
|
+
#
|
7
|
+
# Tue Feb 5 18:16:55 JST 2008
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
require 'rufus/rtm'
|
13
|
+
|
14
|
+
include Rufus::RTM
|
15
|
+
|
16
|
+
|
17
|
+
class TasksTest < Test::Unit::TestCase
|
18
|
+
|
19
|
+
#def setup
|
20
|
+
#end
|
21
|
+
|
22
|
+
#def teardown
|
23
|
+
#end
|
24
|
+
|
25
|
+
def test_0
|
26
|
+
|
27
|
+
taskname = "milk the cow #{Time.now.to_i}"
|
28
|
+
|
29
|
+
t0 = Task.add! taskname
|
30
|
+
|
31
|
+
assert_kind_of Task, t0
|
32
|
+
assert_equal taskname, t0.name
|
33
|
+
|
34
|
+
ts = Task.find
|
35
|
+
|
36
|
+
#puts "tasks : #{ts.size}"
|
37
|
+
|
38
|
+
t1 = ts.find { |t| t.task_id == t0.task_id }
|
39
|
+
assert_equal taskname, t1.name
|
40
|
+
assert_equal "", t1.tags.join(",")
|
41
|
+
|
42
|
+
ts = Task.find :filter => "status:incomplete"
|
43
|
+
|
44
|
+
#puts "incomplete tasks : #{ts.size}"
|
45
|
+
|
46
|
+
t1 = ts.find { |t| t.task_id == t0.task_id }
|
47
|
+
assert_equal taskname, t1.name
|
48
|
+
|
49
|
+
t1.delete!
|
50
|
+
|
51
|
+
ts = Task.find :filter => "status:incomplete"
|
52
|
+
|
53
|
+
t1 = ts.find { |t| t.task_id == t0.task_id }
|
54
|
+
assert_nil t1
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_1
|
58
|
+
|
59
|
+
lists = List.find
|
60
|
+
assert_not_nil(lists.find { |e| e.name == "Inbox" })
|
61
|
+
|
62
|
+
work = lists.find { |e| e.name == "Work" }
|
63
|
+
|
64
|
+
taskname = "more work #{Time.now.to_i}"
|
65
|
+
|
66
|
+
t0 = Task.add! taskname, work.list_id
|
67
|
+
|
68
|
+
tasks = Task.find :list_id => work.list_id, :filer => "status:incomplete"
|
69
|
+
|
70
|
+
assert_not_nil(tasks.find { |t| t.task_id == t0.task_id })
|
71
|
+
|
72
|
+
t0.complete!
|
73
|
+
|
74
|
+
tasks = Task.find :list_id => work.list_id, :filer => "status:completed"
|
75
|
+
assert_not_nil(tasks.find { |t| t.task_id == t0.task_id })
|
76
|
+
|
77
|
+
t0.delete!
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
data/test/test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rufus-rtm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Mettraux
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-14 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rufus-verbs
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description:
|
25
|
+
email: jmettraux@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README.txt
|
32
|
+
files:
|
33
|
+
- lib/rufus
|
34
|
+
- lib/rufus/rtm
|
35
|
+
- lib/rufus/rtm/base.rb
|
36
|
+
- lib/rufus/rtm/credentials.rb
|
37
|
+
- lib/rufus/rtm/resources.rb
|
38
|
+
- lib/rufus/rtm.rb
|
39
|
+
- test/tasks_test.rb
|
40
|
+
- test/test.rb
|
41
|
+
- README.txt
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://rufus.rubyforge.org/rufus-rtm
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements:
|
62
|
+
- rufus-verbs
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 0.9.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 2
|
67
|
+
summary: yet another RememberTheMilk wrapper
|
68
|
+
test_files:
|
69
|
+
- test/test.rb
|