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