rtmilk 0.0.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -1,5 +1,28 @@
1
+ 2007-03-17 mootoh@gmail.com
2
+
3
+ * 0.3.0
4
+ based on rev36.
5
+ RTM::Note added.
6
+ That is used by taskMap.
7
+
8
+ 2007-03-16 mootoh@gmail.com
9
+
10
+ * 0.2.0
11
+ RTM::Task is now creatable/deletable in easy way.
12
+
13
+ 2007-03-10 mootoh@gmail.com
14
+
15
+ * CHANGELOG.txt:
16
+ all tests passed.
17
+
18
+ 2007-03-08 mootoh@gmail.com
19
+
20
+ * CHANGELOG.txt:
21
+ architecture totally rewrited.
22
+ add tasks.notes stuff.
23
+
1
24
  2007-02-05 mootoh@gmail.com
2
25
 
3
26
  * CHANGELOG.txt:
4
- packed gem.
27
+ packed gem.
5
28
 
data/History.txt ADDED
File without changes
data/Manifest.txt CHANGED
@@ -1,11 +1,25 @@
1
- Rakefile
2
1
  README.txt
2
+ Rakefile
3
3
  CHANGELOG.txt
4
4
  Manifest.txt
5
+ History.txt
5
6
  setup.rb
7
+ example/get.rb
8
+ lib/rtmilk/api/auth.rb
9
+ lib/rtmilk/api/lists.rb
10
+ lib/rtmilk/api/notes.rb
11
+ lib/rtmilk/api/tasks.rb
12
+ lib/rtmilk/api/timelines.rb
6
13
  lib/rtmilk/api.rb
14
+ lib/rtmilk/error.rb
7
15
  lib/rtmilk/version.rb
8
16
  lib/rtmilk.rb
17
+ test/auth_api_test.rb
18
+ test/error_test.rb
19
+ test/lists_api_test.rb
20
+ test/make_config.rb
21
+ test/notes_api_test.rb
22
+ test/Rakefile
23
+ test/tasks_api_test.rb
9
24
  test/test_helper.rb
10
- test/rtm_test.rb
11
- test/rtm_api_test.rb
25
+ test/timelines_api_test.rb
data/README.txt CHANGED
@@ -1,4 +1,3 @@
1
- README for rtmilk
2
- =================
1
+ = README for rtmilk
3
2
 
4
- rtmilk is a "Remember the Milk" wrapper library.
3
+ rtmilk is a {Remember the Milk}[http://www.rememberthemilk.com/] wrapper library.
data/Rakefile CHANGED
@@ -30,6 +30,7 @@ RDOC_OPTS = ['--quiet', '--title', "rtmilk documentation",
30
30
  "--opname", "index.html",
31
31
  "--line-numbers",
32
32
  "--main", "README.txt",
33
+ "-diagram",
33
34
  "--inline-source"]
34
35
 
35
36
  class Hoe
data/example/get.rb ADDED
@@ -0,0 +1,43 @@
1
+ #
2
+ # simple example for rtm.rb
3
+ $LOAD_PATH << File.dirname(__FILE__) + '/../lib'
4
+ require 'rtmilk'
5
+
6
+ # -------------------------------------------------------------------
7
+ # API_KEY and SHARED_SECRET are required.
8
+ #
9
+ API_KEY = 'aaa'
10
+ SHARED_SECRET = 'bbb'
11
+
12
+ RTM::API.init(API_KEY, SHARED_SECRET)
13
+
14
+ # -------------------------------------------------------------------
15
+ # get auth url for read
16
+ #
17
+ frob = RTM::Auth::GetFrob.new.invoke
18
+ url = RTM::API.get_auth_url('read', frob)
19
+
20
+ puts 'access, login, and authenticate following uri on your browser,'
21
+ puts 'then hit return to continue'
22
+ puts ' ' + url
23
+
24
+ gets
25
+
26
+
27
+ res = RTM::Auth::GetToken.new(frob).invoke
28
+ token = res[:token]
29
+ RTM::API.token = token
30
+
31
+ # -------------------------------------------------------------------
32
+ # get all lists
33
+ #
34
+ #
35
+ lists = RTM::List.alive_all
36
+ lists.each { |l| puts l['name'] }
37
+
38
+ # -------------------------------------------------------------------
39
+ # get all tasks
40
+ #
41
+ #tasks = RTM::Tasks.new
42
+ #tasks.each { |t| puts t.name }
43
+
data/lib/rtmilk.rb CHANGED
@@ -5,191 +5,14 @@
5
5
  # $Id: rtm.rb 10 2006-12-30 06:37:24Z takayama $
6
6
  #
7
7
 
8
- require 'rtmilk/api.rb'
8
+ require 'rtmilk/error'
9
+ require 'rtmilk/api'
9
10
 
10
11
  =begin rdoc
11
12
  access Remember the Milk REST APIs.
12
13
  =end
13
14
  module RTM
14
15
 
15
- def RTM.get_timeline
16
- API::TimeLines.create
17
- end
18
-
19
- # use frob for Desktop Application.
20
- # perm should be one of ['read', 'write', 'delete'].
21
- def RTM.get_auth_url(h)
22
- raise unless API::PERMS.include?(h[:perm])
23
-
24
- API.auth_uri(API.params, h)
25
- end
26
-
27
- def RTM.get_frob
28
- API::Auth.getFrob
29
- end
30
-
31
-
32
- class Contact
33
- attr_accessor :id, :fullname, :username
34
-
35
- def initialize(id, full=nil, user=nil)
36
- @id = id
37
- @fullname = full
38
- @user = user
39
- end
40
- end # Contact
41
-
42
- class Group
43
- attr_accessor :id, :name
44
- end # Group
45
-
46
- class List
47
- attr_accessor :id, :name, :deleted, :locked, :archived, :position, :smart, :filter
48
-
49
- def initialize(h)
50
- @id = h['id']
51
- @name = h['name']
52
- @deleted = h['deleted'] == '0'
53
- @locked = h['locked'] == '1'
54
- @archived = h['archived'] == '1'
55
- @position = h['position']
56
- @smart = h['smart'] == '1'
57
- @filter = h['filter']
58
- end
59
-
60
- def setDefault
61
- end # setDefault
62
-
63
- def setName(name)
64
- end # setName
65
-
66
- def archive
67
- end # archive
68
-
69
- def unarchive
70
- end # unarchive
71
-
72
- def <=>(other)
73
- @name <=> other.name
74
- end
75
- end # List
76
-
77
- class Lists
78
- include Enumerable
79
-
80
- attr_accessor :ls
81
-
82
- def initialize
83
- @ls = API::Lists.getList.collect do |x|
84
- List.new x
85
- end
86
- end
87
-
88
- def each
89
- @ls.each do |x|
90
- yield x
91
- end
92
- end
93
-
94
- def Lists.add(name, filter=nil)
95
- timeline = RTM.get_timeline
96
- l = API::Lists.add(timeline, name, filter)
97
- List.new l
98
- end # add
99
-
100
- def [](i)
101
- to_a[i]
102
- end
103
-
104
- def size
105
- to_a.size
106
- end
107
- end # Lists
108
-
109
- class TaskSeries
110
- attr_accessor :id, :created, :modified, :name, :source,
111
- :tags, :participants, :notes, :task
112
-
113
- def initialize(h)
114
- @id = h['id'] if h['id']
115
- @created = h['created'] if h['created']
116
- @modified = h['modified'] if h['modified']
117
- @name = h['name'] if h['name']
118
- @source = h['source'] if h['source']
119
- @tags = h['tags'].first['tag'] if h['tags']
120
- @participants = h['participants'].first if h['participants']
121
- @notes = h['notes'].first if h['notes']
122
-
123
- if h['task']
124
- @task = h['task'].collect do |t|
125
- Task.new(t)
126
- end.flatten.compact
127
- end
128
- end
129
-
130
- class Task
131
- attr_accessor :id, :due, :has_due_time, :added, :completed,
132
- :deleted, :priority, :postponed, :estimate
133
-
134
- def initialize(h)
135
- @id = h['id'] if h['id']
136
- @due = h['due'] if h['due']
137
- @has_due_time = h['has_due_time'] == '1' if h['has_due_time']
138
- @added = h['added'] if h['added']
139
- @completed = h['completed'] if h['completed']
140
- @deleted = h['deleted'] if h['deleted']
141
- @priority = h['priority'] if h['priority']
142
- @postponed = h['postponed'] if h['postponed']
143
- @estimate = h['estimate'] if h['estimate']
144
- end
145
- end # Task
146
- end
147
-
148
- class Tasks
149
- include Enumerable
150
-
151
- attr_accessor :ts
152
-
153
- def initialize(list=nil, last=nil)
154
- @ts = API::Tasks.getList(list, last).collect do |x|
155
- if x['taskseries']
156
- x['taskseries'].collect do |t|
157
- TaskSeries.new t
158
- end
159
- else
160
- nil
161
- end
162
- end.flatten.compact
163
- end
164
-
165
- def each
166
- @ts.each do |x|
167
- yield x
168
- end
169
- end
170
-
171
- def Tasks.add(name, list)
172
- timeline = RTM.get_timeline
173
- t = API::Tasks.add(timeline, list, name)
174
- TaskSeries.new t
175
- end
176
-
177
- def Tasks.delete(series, task, list)
178
- timeline = RTM.get_timeline
179
- t = API::Tasks.delete(timeline, list, series, task)
180
- TaskSeries.new t
181
- end
182
-
183
- def [](i)
184
- to_a[i]
185
- end
186
-
187
- def size
188
- to_a.size
189
- end
190
-
191
- end # Tasks
192
-
193
16
  end # RTM
194
17
 
195
18
  # vim:fdm=indent
data/lib/rtmilk/api.rb CHANGED
@@ -2,8 +2,6 @@
2
2
  # for Remember the Milk REST API
3
3
  # http://www.rememberthemilk.com/services/api/overview.rtm
4
4
  #
5
- # $Id: api.rb 11 2007-01-08 04:02:44Z takayama $
6
- #
7
5
 
8
6
  require 'net/http'
9
7
  require 'digest/md5'
@@ -14,373 +12,110 @@ require 'uri'
14
12
  # access the {Remember the Milk}[http://www.rememberthemilk.com/] REST APIs.
15
13
  module RTM
16
14
 
17
- # API classes.
15
+ # API class
18
16
  class API
17
+
18
+ private
19
19
  RTM_URI = 'www.rememberthemilk.com'
20
20
  REST_PATH = '/services/rest/'
21
21
  AUTH_PATH = '/services/auth/'
22
-
23
22
  PERMS = ['read', 'write', 'delete']
24
23
 
25
- #--
26
- # -----------------------------------------------------------------
27
- # class methods
28
- #++
29
-
30
- def API.key ; @@key ; end
31
- def API.params ; @@params ; end
32
- def API.token ; @@token ; end
33
-
24
+ public
34
25
  # initialize the API context.
35
- # make sure to call this before using any API calls.
36
- def API.init(h)
37
- @@key = h[:key] if h.has_key? :key
38
- @@sec = h[:secret] if h.has_key? :secret
39
- @@frob = h[:frob] if h.has_key? :frob
40
- @@token = h[:token] if h.has_key? :token
26
+ def API.init(key, sec, option=nil)
27
+ @@key = key
28
+ @@sec = sec
29
+
30
+ if (option)
31
+ begin
32
+ @@token = option[:token] if option.has_key? :token
33
+ rescue => e
34
+ puts e.message
35
+ end
36
+ end
41
37
 
42
- @@params = { 'api_key' => @@key }
43
- @@http = Net::HTTP.new(RTM_URI)
44
38
  end
45
39
 
46
- # tailor parameters into request uri.
47
- def API.uri_req(params)
48
- r = REST_PATH + '?'
49
- r += params.collect { |k, v| [k, v].join('=') }.sort.join('&')
50
- r += '&api_sig=' + sign(params)
51
- URI.escape r
40
+ def API.token=(token)
41
+ @@token = token
52
42
  end
53
43
 
54
- # tailor parameters into auth uri.
55
- def API.uri_auth(params, h)
56
- p = params.dup
57
- p[:perms] = h[:perm]
58
- p[:frob] = h[:frob] if h[:frob]
59
- p[:callback] = h[:callback] if h[:callback]
44
+ # getter methods
45
+ def API.key; @@key; end
46
+ def API.token; @@token; end
47
+
48
+ # invoke a method
49
+ def invoke
50
+ response = Net::HTTP.get(RTM_URI, make_url)
51
+ # puts '--------------------------------------------------'
52
+ # puts response
53
+ # puts '--------------------------------------------------'
54
+ result = XmlSimple.new.xml_in(response)
55
+ ret = parse_result(result)
56
+ end
60
57
 
61
- r = AUTH_PATH + '?'
62
- r += p.collect { |k, v| [k, v].join('=') }.sort.join('&')
58
+ # get Auth URL (both desktop/webapp)
59
+ def API.get_auth_url(perms, frob=nil)
60
+ param = { :api_key => @@key, :perms => perms }
61
+ if frob
62
+ param['frob'] = frob
63
+ end
63
64
 
64
- r += '&api_sig=' + sign(p)
65
- r
66
- end
65
+ sig = API.sign(param)
67
66
 
68
- # construct auth uri from params.
69
- def API.auth_uri(params, h)
70
- RTM_URI + uri_auth(params, h)
67
+ r = 'http://' + RTM_URI + AUTH_PATH + '?'
68
+ r += param.collect { |k, v| [k, v].join('=') }.sort.join('&')
69
+ r += '&api_sig=' + sig
70
+ r
71
71
  end
72
72
 
73
- # process http request, return response.
74
- def API.request(uri)
75
- head, body = @@http.get(uri)
76
- res = XmlSimple.new.xml_in(body)
77
- raise Error, res if 'fail' == res['stat']
78
- res
73
+ def sign
74
+ API.sign(@param)
79
75
  end
80
76
 
81
- private
82
-
83
- # sign parameters.
84
- def API.sign(params)
77
+ private
78
+ # sign parameters
79
+ def API.sign(param)
85
80
  sig = @@sec
86
- sig += params.collect { |k, v| [k, v].join('') }.sort.join('')
87
- sig = Digest::MD5.hexdigest(sig)
81
+ sig += param.collect { |k, v| [k, v].join('') }.sort.join('')
82
+ Digest::MD5.hexdigest(sig)
88
83
  end
89
- end # API
90
84
 
91
- #--
92
- # ---------------------------------------------------------------
93
- # subclasses
94
- #++
95
-
96
- class API
97
- # Exception class, takes msg and code.
98
- class Error < StandardError
99
- def initialize(h)
100
- err = h['err'].first
101
- @code = err['code'].to_i
102
- msg = err['msg'] + ' (error code=' + err['code'] + ')'
103
- super(msg)
104
- end
85
+ def initialize(method, token=nil, timeline=nil)
86
+ @method = method
87
+ @token = token ? token : nil
88
+ @timeline = timeline ? timeline : nil
89
+ @param = {}
105
90
  end
106
91
 
107
- # rtm.auth API.
108
- class Auth
109
- METHOD = 'rtm.auth'
110
-
111
- # see spec[http://www.rememberthemilk.com/services/api/methods/rtm.auth.checkToken.rtm].
112
- def Auth.checkToken(token)
113
- p = API.params.dup
114
- p['method'] = METHOD + '.checkToken'
115
- p['auth_token'] = token
116
- res = API.request(API.uri_req(p))
117
- end
118
-
119
- # see spec[http://www.rememberthemilk.com/services/api/methods/rtm.auth.getFrob.rtm].
120
- def Auth.getFrob
121
- p = API.params.dup
122
- p['method'] = METHOD + '.getFrob'
123
-
124
- res = API.request(API.uri_req(p))
125
- res['frob'].first
126
- end
127
-
128
- # see {spec}[http://www.rememberthemilk.com/services/api/methods/rtm.auth.getToken.rtm].
129
- def Auth.getToken(frob)
130
- p = API.params.dup
131
- p['method'] = METHOD + '.getToken'
132
- p['frob'] = frob
133
-
134
- res = API.request(API.uri_req(p))
135
- res['auth'].first['token'].first
136
- end
137
- end # Auth
138
-
139
- class Contacts
140
- def Contacts.add
141
- end
142
-
143
- def Contacts.delete
144
- end
145
-
146
- def Contacts.getList
147
- end
148
- end # Contacts
149
-
150
- class Groups
151
- def Groups.add
152
- end
153
-
154
- def Groups.addContact
155
- end
156
-
157
- def Groups.delete
158
- end
159
-
160
- def Groups.getList
161
- end
162
-
163
- def Groups.removeContact
164
- end
165
- end # Groups
166
-
167
- class Lists
168
- METHOD = 'rtm.lists'
169
-
170
- def Lists.add(timeline, name, filter=nil)
171
- p = API.params.dup
172
- p['method'] = METHOD + '.add'
173
- p['auth_token'] = API.token
174
- p['timeline'] = timeline
175
- p['name'] = name
176
- p['filter'] = filter if filter
177
-
178
- res = API.request(API.uri_req(p))
179
- end
180
-
181
- def Lists.archive
182
- end
183
-
184
- def Lists.getList(alive_only=true)
185
- p = API.params.dup
186
- p['method'] = METHOD + '.getList'
187
- p['auth_token'] = API.token
188
-
189
- res = API.request(API.uri_req(p))
190
- lists = res['lists'].first['list']
191
-
192
- if alive_only
193
- lists.collect { |l| l if l['deleted'] == '0' }.compact
194
- else
195
- lists
196
- end
197
- end
198
-
199
- def Lists.setDefaultList
200
- end
201
-
202
- def Lists.setName
203
- end
204
-
205
- def Lists.unarchive
206
- end
207
- end # Lists
208
-
209
- class Reflection
210
- def Reflection.getMethodInfo
211
- end
212
-
213
- def Reflection.getMethods
214
- end
215
- end # Reflection
216
-
217
- class Settings
218
- def Settings.getList
219
- end
220
- end # Settings
221
-
222
- class Tasks
223
- METHOD = 'rtm.tasks'
224
-
225
- def Tasks.add(timeline, list, name)
226
- p = API.params.dup
227
- p['method'] = METHOD + '.add'
228
- p['auth_token'] = API.token
229
- p['timeline'] = timeline
230
- p['name'] = name
231
- p['list_id'] = list
232
-
233
- res = API.request(API.uri_req(p))
234
- res['list'].first['taskseries'].first
235
- end
236
-
237
- def Tasks.addTags
238
- end
239
-
240
- def Tasks.complete
241
- end
242
-
243
- def Tasks.delete(timeline, list, series, task)
244
- p = API.params.dup
245
- p['method'] = METHOD + '.delete'
246
- p['auth_token'] = API.token
247
- p['timeline'] = timeline
248
- p['list_id'] = list
249
- p['taskseries_id'] = series
250
- p['task_id'] = task
251
-
252
- res = API.request(API.uri_req(p))
253
- res['list'].first['taskseries'].first
254
- end
255
-
256
- def Tasks.getList(list=nil, last_sync=nil)
257
- p = API.params.dup
258
-
259
- p['method'] = METHOD + '.getList'
260
- p['auth_token'] = API.token
261
- p['list_id'] = list if list
262
- p['last_sync'] = last_sync if last_sync
263
-
264
- res = API.request(API.uri_req(p))
265
- res['tasks'].first['list']
266
- end
267
-
268
- def Tasks.moveProiority
269
- end
270
-
271
- def Tasks.moveTo
272
- end
273
-
274
- def Tasks.postpone
275
- end
276
-
277
- def Tasks.removeTags
278
- end
279
-
280
- def Tasks.setDueDate
281
- end
282
-
283
- def Tasks.setEstimate
284
- end
285
-
286
- def Tasks.setName
287
- end
288
-
289
- def Tasks.setPriority
290
- end
291
-
292
- def Tasks.setRecurrence
293
- end
294
-
295
- def Tasks.setTags
296
- end
297
-
298
- def Tasks.setURL
299
- end
300
-
301
- def Tasks.uncomplete
302
- end
303
-
304
- class Notes # TODO
305
- def Notes.add # TODO
306
- end
307
-
308
- def Notes.delete # TODO
309
- end
310
-
311
- def Notes.edit # TODO
312
- end
313
- end # Notes
314
- end # Tasks
315
-
316
- class Test # TODO
317
- METHOD = 'rtm.test'
318
-
319
- def Test.echo # TODO
320
- req = REST_PATH + '?method=' + METHOD + '.echo' + '&api_key=' + @k
321
- puts req
322
-
323
- r, b = @http.get(req)
324
- puts r
325
- puts b
326
- end
327
-
328
- def Test.login # TODO
329
- params = {
330
- 'method' => METHOD + '.login',
331
- 'api_key' => @k
332
- }
333
-
334
- sig = @s
335
- sig += params.collect { |k, v| [k, v].join('') }.sort.join('')
336
- puts "sig = " + sig
337
- sig = Digest::MD5.hexdigest(sig)
338
- puts "hexed sig = " + sig
339
-
340
- req = REST_PATH + '?'
341
- req += params.collect { |k, v| [k, v].join('=') }.sort.join('&')
342
- req += "&api_sig=" + sig
343
-
344
- puts "\n"
345
- puts "req = " + req
346
-
347
- r, b = @http.get(req)
348
- puts r
349
- puts b
350
- end
351
- end # Test
352
-
353
- class Time # TODO
354
- def Time.convert # TODO
355
- end
356
-
357
- def Time.parse # TODO
358
- end
359
- end # Time
360
-
361
- class TimeLines
362
- METHOD = 'rtm.timelines'
363
-
364
- def TimeLines.create
365
- p = API.params.dup
366
- p['method'] = METHOD + '.create'
367
- p['auth_token'] = API.token
368
-
369
- res = API.request(API.uri_req(p))
370
- t = res['timeline'].first
371
- end
372
- end # TimeLines
92
+ def make_url
93
+ r = REST_PATH + '?'
373
94
 
374
- class TimeZones # TODO
375
- def TimeZones.getList
376
- end
377
- end # TimeZones
95
+ @param = {} if @param == nil
96
+ @param['method'] = @method
97
+ @param['auth_token'] = @token unless @token == nil
98
+ @param['timeline'] = @timeline unless @timeline == nil
99
+ @param['api_key'] = @@key
100
+ r += @param.collect { |k, v| [k, v].join('=') }.sort.join('&')
101
+ r += '&api_sig=' + sign
102
+ URI.escape r
103
+ end
378
104
 
379
- class Transactions
380
- def Transactions.undo
105
+ protected
106
+ # parse result
107
+ def parse_result(result)
108
+ unless result['stat'] == 'ok'
109
+ raise RTM::Error, result['err'].first['msg']
381
110
  end
382
- end # Transactions
111
+ end
383
112
  end # API
384
113
 
385
114
  end # RTM
115
+ require 'rtmilk/api/auth'
116
+ require 'rtmilk/api/timelines'
117
+ require 'rtmilk/api/lists'
118
+ require 'rtmilk/api/tasks'
119
+ require 'rtmilk/api/notes'
120
+
386
121
  # vim:fdm=indent