toodledo 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -2
- data/Manifest.txt +1 -1
- data/Rakefile +6 -3
- data/bin/toodledo +0 -0
- data/lib/toodledo.rb +4 -3
- data/lib/toodledo/session.rb +91 -13
- data/test/session_test.rb +8 -0
- data/test/toodledo_functional_test.rb +6 -5
- metadata +36 -8
data/History.txt
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
== 1.3.
|
1
|
+
== 1.3.2 / 2010-02-16
|
2
2
|
|
3
|
-
*
|
3
|
+
* Added file caching for token (will write to $HOME/.toodledo/tokens/<user_id> file)
|
4
|
+
* Added patch for the app_id (thx to Greg Miller)
|
5
|
+
* Added serveroffset to get_server_info call.
|
6
|
+
|
7
|
+
== 1.3.1 / ?
|
8
|
+
|
9
|
+
* Fix some bugs.
|
4
10
|
|
5
11
|
== 1.3.0 / 2008-05-31
|
6
12
|
|
data/Manifest.txt
CHANGED
@@ -18,8 +18,8 @@ lib/toodledo/command_line/interactive_command.rb
|
|
18
18
|
lib/toodledo/command_line/list_contexts_command.rb
|
19
19
|
lib/toodledo/command_line/list_folders_command.rb
|
20
20
|
lib/toodledo/command_line/list_goals_command.rb
|
21
|
-
lib/toodledo/command_line/list_tasks_command.rb
|
22
21
|
lib/toodledo/command_line/list_tasks_by_context_command.rb
|
22
|
+
lib/toodledo/command_line/list_tasks_command.rb
|
23
23
|
lib/toodledo/command_line/parser_helper.rb
|
24
24
|
lib/toodledo/command_line/setup_command.rb
|
25
25
|
lib/toodledo/command_line/stdin_command.rb
|
data/Rakefile
CHANGED
@@ -5,17 +5,20 @@ require 'hoe'
|
|
5
5
|
$:.unshift(File.dirname(__FILE__) + "/lib")
|
6
6
|
require 'toodledo'
|
7
7
|
|
8
|
-
Hoe.
|
8
|
+
Hoe.spec('toodledo') do |p|
|
9
9
|
p.rubyforge_name = 'toodledo'
|
10
|
+
p.version = Toodledo::VERSION
|
10
11
|
p.author = 'Will Sargent'
|
11
12
|
p.email = 'will@tersesystems.com'
|
12
13
|
p.summary = 'A command line client and API to Toodledo'
|
13
14
|
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
14
|
-
p.url =
|
15
|
+
p.url = "http://gemcutter.org/gems/toodledo"
|
15
16
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
17
|
p.rsync_args << ' --exclude=statsvn/'
|
17
18
|
p.test_globs = ["test/**/*_test.rb"]
|
18
|
-
p.extra_deps
|
19
|
+
p.extra_deps << ['cmdparse', '>= 0']
|
20
|
+
p.extra_deps << ['highline', '>= 0']
|
21
|
+
p.extra_dev_deps << [ 'flexmock', '>= 0']
|
19
22
|
end
|
20
23
|
|
21
24
|
# vim: syntax=Ruby
|
data/bin/toodledo
CHANGED
File without changes
|
data/lib/toodledo.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
module Toodledo
|
6
6
|
|
7
7
|
# Required for gem
|
8
|
-
VERSION = '1.3.
|
8
|
+
VERSION = '1.3.2'
|
9
9
|
|
10
10
|
# Returns the configuration object.
|
11
11
|
def self.get_config()
|
@@ -49,8 +49,9 @@ module Toodledo
|
|
49
49
|
base_url = connection['url']
|
50
50
|
user_id = connection['user_id']
|
51
51
|
password = connection['password']
|
52
|
-
|
53
|
-
|
52
|
+
app_id = connection['app_id'] || 'ruby_app'
|
53
|
+
|
54
|
+
session = Session.new(user_id, password, logger, app_id)
|
54
55
|
|
55
56
|
base_url = Session::DEFAULT_API_URL if (base_url == nil)
|
56
57
|
session.connect(base_url, proxy)
|
data/lib/toodledo/session.rb
CHANGED
@@ -7,6 +7,7 @@ require 'net/https'
|
|
7
7
|
require 'openssl/ssl'
|
8
8
|
require 'rexml/document'
|
9
9
|
require 'logger'
|
10
|
+
require 'fileutils'
|
10
11
|
|
11
12
|
module Toodledo
|
12
13
|
|
@@ -25,8 +26,9 @@ module Toodledo
|
|
25
26
|
'Connection' => 'keep-alive',
|
26
27
|
'Keep-Alive' => '300'
|
27
28
|
}
|
28
|
-
|
29
|
-
|
29
|
+
|
30
|
+
# The key should be good for four hours.
|
31
|
+
EXPIRATION_TIME_IN_SECS = 60 * 60 * 4
|
30
32
|
|
31
33
|
DATE_FORMAT = '%Y-%m-%d'
|
32
34
|
|
@@ -34,18 +36,19 @@ module Toodledo
|
|
34
36
|
|
35
37
|
TIME_FORMAT = '%I:%M %p'
|
36
38
|
|
37
|
-
attr_accessor :logger
|
38
|
-
|
39
|
-
attr_reader :base_url, :user_id, :proxy
|
39
|
+
attr_accessor :logger
|
40
|
+
|
41
|
+
attr_reader :base_url, :user_id, :proxy, :app_id
|
40
42
|
|
41
43
|
# Creates a new session, using the given user name and password.
|
42
44
|
# throws InvalidConfigurationError if user_id or password are nil.
|
43
|
-
def initialize(user_id, password, logger = nil)
|
45
|
+
def initialize(user_id, password, logger = nil, app_id = nil)
|
44
46
|
raise InvalidConfigurationError.new("Nil user_id") if (user_id == nil)
|
45
47
|
raise InvalidConfigurationError.new("Nil password") if (password == nil)
|
46
48
|
|
47
49
|
@user_id = user_id
|
48
50
|
@password = password
|
51
|
+
@app_id = app_id
|
49
52
|
|
50
53
|
@folders = nil
|
51
54
|
@contexts = nil
|
@@ -87,7 +90,7 @@ module Toodledo
|
|
87
90
|
# Get the proxy information if it exists.
|
88
91
|
@proxy = proxy
|
89
92
|
|
90
|
-
session_token = get_token(@user_id)
|
93
|
+
session_token = get_token(@user_id, @app_id)
|
91
94
|
key = md5(md5(@password).to_s + session_token + @user_id);
|
92
95
|
|
93
96
|
@key = key
|
@@ -105,12 +108,13 @@ module Toodledo
|
|
105
108
|
|
106
109
|
# Returns true if the session has expired.
|
107
110
|
def expired?
|
111
|
+
return false
|
108
112
|
#logger.debug("expired?") too annoying
|
109
113
|
|
110
114
|
# The key is only good for an hour. If it's been over an hour,
|
111
115
|
# then we count it as expired.
|
112
|
-
return true if (@start_time == nil)
|
113
|
-
return (Time.now - @start_time > EXPIRATION_TIME_IN_SECS)
|
116
|
+
#return true if (@start_time == nil)
|
117
|
+
#return (Time.now - @start_time > EXPIRATION_TIME_IN_SECS)
|
114
118
|
end
|
115
119
|
|
116
120
|
# Returns a parsable URI object from the base API URL and the parameters.
|
@@ -221,11 +225,80 @@ module Toodledo
|
|
221
225
|
end
|
222
226
|
|
223
227
|
# Gets the token method, given the id.
|
224
|
-
def get_token(user_id)
|
228
|
+
def get_token(user_id, app_id)
|
225
229
|
raise "Nil user_id" if (user_id == nil || user_id.empty?)
|
226
230
|
|
231
|
+
# If there is no token file, or the token file is out of date, pull in
|
232
|
+
# a fresh token from the server and write it to the file system.
|
233
|
+
token = read_token(user_id)
|
234
|
+
unless token
|
235
|
+
token = get_uncached_token(user_id, app_id)
|
236
|
+
write_token(user_id, token)
|
237
|
+
end
|
238
|
+
|
239
|
+
return token
|
240
|
+
end
|
241
|
+
|
242
|
+
# Reads a token from the file system, if the given user_id exists and the
|
243
|
+
# token is not too old.
|
244
|
+
def read_token(user_id)
|
245
|
+
token_path = get_token_file(user_id)
|
246
|
+
unless token_path
|
247
|
+
logger.debug("read_token: no token found for #{user_id.inspect}, returning nil")
|
248
|
+
return nil
|
249
|
+
end
|
250
|
+
|
251
|
+
if is_too_old(token_path)
|
252
|
+
File.delete(token_path)
|
253
|
+
return nil
|
254
|
+
end
|
255
|
+
|
256
|
+
token = File.read(token_path)
|
257
|
+
token
|
258
|
+
end
|
259
|
+
|
260
|
+
# Returns true if the file is more than an hour old, false otherwise.
|
261
|
+
def is_too_old(token_path)
|
262
|
+
last_modified_time = File.new(token_path).mtime
|
263
|
+
expiration_time = Time.now - EXPIRATION_TIME_IN_SECS
|
264
|
+
too_old = expiration_time - last_modified_time > 0
|
265
|
+
|
266
|
+
logger.debug "is_too_old: time = #{last_modified_time}, expires = #{expiration_time}, too_old = #{too_old}"
|
267
|
+
|
268
|
+
return too_old
|
269
|
+
end
|
270
|
+
|
271
|
+
# Gets there full path of the token file.
|
272
|
+
def get_token_file(user_id)
|
273
|
+
tokens_dir = get_tokens_directory()
|
274
|
+
token_path = File.expand_path(File.join(tokens_dir, user_id))
|
275
|
+
unless File.exist?(token_path)
|
276
|
+
return nil
|
277
|
+
end
|
278
|
+
token_path
|
279
|
+
end
|
280
|
+
|
281
|
+
# Make sure that there is a ".toodledo/tokens" directory.
|
282
|
+
def get_tokens_directory()
|
283
|
+
toodledo_dir = "~/.toodledo"
|
284
|
+
tokens_path = File.expand_path(File.join(toodledo_dir, "tokens"))
|
285
|
+
FileUtils.mkdir_p tokens_path
|
286
|
+
tokens_path
|
287
|
+
end
|
288
|
+
|
289
|
+
# Writes the token file to the filesystem.
|
290
|
+
def write_token(user_id, token)
|
291
|
+
logger.debug("write_token: user_id = #{user_id.inspect}, token = #{token.inspect}")
|
292
|
+
token_path = File.expand_path(File.join(get_tokens_directory(), user_id))
|
293
|
+
File.open(token_path, 'w') {|f| f.write(token) }
|
294
|
+
end
|
295
|
+
|
296
|
+
# Calls the server to get a token.
|
297
|
+
def get_uncached_token(user_id, app_id)
|
227
298
|
params = { :userid => user_id }
|
228
|
-
|
299
|
+
params.merge!({:appid => app_id}) unless app_id.nil?
|
300
|
+
result = call('getToken', params)
|
301
|
+
|
229
302
|
return result.text
|
230
303
|
end
|
231
304
|
|
@@ -314,11 +387,13 @@ module Toodledo
|
|
314
387
|
|
315
388
|
unixtime = result.elements['unixtime'].text.to_i
|
316
389
|
server_date = Time.at(unixtime)
|
317
|
-
|
390
|
+
server_offset = result.elements['serveroffset'].text.to_i
|
391
|
+
token_expires = result.elements['tokenexpires'].text.to_f
|
318
392
|
hash = {
|
319
393
|
:unixtime => unixtime,
|
320
394
|
:date => server_date,
|
321
|
-
:tokenexpires => token_expires
|
395
|
+
:tokenexpires => token_expires,
|
396
|
+
:serveroffset => server_offset,
|
322
397
|
}
|
323
398
|
|
324
399
|
return hash
|
@@ -574,6 +649,9 @@ module Toodledo
|
|
574
649
|
# Handle completion.
|
575
650
|
handle_boolean(myhash, params, :completed)
|
576
651
|
|
652
|
+
# Handle star
|
653
|
+
handle_boolean(myhash, params, :star)
|
654
|
+
|
577
655
|
# repeat: use the map to change from the symbol to the raw numeric value.
|
578
656
|
handle_repeat(myhash, params)
|
579
657
|
|
data/test/session_test.rb
CHANGED
@@ -24,6 +24,14 @@ class SessionTest < Test::Unit::TestCase
|
|
24
24
|
def teardown
|
25
25
|
@session.disconnect()
|
26
26
|
end
|
27
|
+
|
28
|
+
def test_handle_app_id_in_session
|
29
|
+
new_sess = Toodledo::Session.new('userid', 'password', nil, 'appid')
|
30
|
+
flexmock(new_sess, :get_token => 'token')
|
31
|
+
new_sess.connect()
|
32
|
+
assert_not_nil new_sess.app_id
|
33
|
+
end
|
34
|
+
|
27
35
|
|
28
36
|
def test_handle_goal_with_name()
|
29
37
|
params = { :goal => 'goal_name' }
|
@@ -18,14 +18,15 @@ class ToodledoFunctionalTest < Test::Unit::TestCase
|
|
18
18
|
@email = 'will.sargent+toodledo_ruby_api@gmail.com'
|
19
19
|
@user_id = 'td479be708d8bd7'
|
20
20
|
@password = 'toodledo'
|
21
|
+
@app_id = 'ruby-functional-test'
|
21
22
|
|
22
23
|
# proxy = { 'host' => '127.0.0.1', 'port' => '8080'}
|
23
24
|
proxy = nil
|
24
25
|
|
25
26
|
logger = Logger.new(STDOUT)
|
26
27
|
logger.level = Logger::DEBUG
|
27
|
-
|
28
|
-
@session = Session.new(@user_id, @password, logger)
|
28
|
+
|
29
|
+
@session = Session.new(@user_id, @password, logger, @app_id)
|
29
30
|
@session.connect(base_url, proxy)
|
30
31
|
end
|
31
32
|
|
@@ -149,14 +150,14 @@ class ToodledoFunctionalTest < Test::Unit::TestCase
|
|
149
150
|
assert info_hash[:alias] == 'will.sargent+toodledo_rub'
|
150
151
|
assert info_hash[:pro] == false
|
151
152
|
assert info_hash[:dateformat] == 0
|
152
|
-
assert info_hash[:timezone] ==
|
153
|
+
assert info_hash[:timezone] == -2
|
153
154
|
assert info_hash[:hidemonths] == 6
|
154
155
|
assert info_hash[:hotlistpriority] == 3
|
155
156
|
assert info_hash[:hotlistduedate] == 14
|
156
157
|
|
157
158
|
# Doesn't seem to work.
|
158
|
-
#
|
159
|
-
assert info_hash[:lastdelete]
|
159
|
+
#assert info_hash[:lastaddedit] != nil
|
160
|
+
#assert info_hash[:lastdelete] == nil
|
160
161
|
end
|
161
162
|
|
162
163
|
def test_get_deleted()
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toodledo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Sargent
|
@@ -9,11 +9,12 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-02-16 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: cmdparse
|
17
|
+
type: :runtime
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
@@ -23,6 +24,17 @@ dependencies:
|
|
23
24
|
version:
|
24
25
|
- !ruby/object:Gem::Dependency
|
25
26
|
name: highline
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: flexmock
|
37
|
+
type: :development
|
26
38
|
version_requirement:
|
27
39
|
version_requirements: !ruby/object:Gem::Requirement
|
28
40
|
requirements:
|
@@ -32,14 +44,28 @@ dependencies:
|
|
32
44
|
version:
|
33
45
|
- !ruby/object:Gem::Dependency
|
34
46
|
name: hoe
|
47
|
+
type: :development
|
35
48
|
version_requirement:
|
36
49
|
version_requirements: !ruby/object:Gem::Requirement
|
37
50
|
requirements:
|
38
51
|
- - ">="
|
39
52
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
53
|
+
version: 2.4.0
|
41
54
|
version:
|
42
|
-
description:
|
55
|
+
description: |-
|
56
|
+
== DESCRIPTION:
|
57
|
+
|
58
|
+
This is a Ruby API and client for http://toodledo.com, a task management
|
59
|
+
website. It implements all of the calls from Toodledo's developer API, and
|
60
|
+
provides a nice wrapper around the functionality.
|
61
|
+
|
62
|
+
The client allows you to work with Toodledo from the command line. It will
|
63
|
+
work in either interactive or command line mode.
|
64
|
+
|
65
|
+
You can also use the client in your shell scripts, or use the API directly
|
66
|
+
as part of a web application. Custom private RSS feed? Want to have the Mac
|
67
|
+
read out your top priority? Input tasks through Quicksilver? Print out
|
68
|
+
tasks with a BetaBrite? It can all happen.
|
43
69
|
email: will@tersesystems.com
|
44
70
|
executables:
|
45
71
|
- toodledo
|
@@ -70,8 +96,8 @@ files:
|
|
70
96
|
- lib/toodledo/command_line/list_contexts_command.rb
|
71
97
|
- lib/toodledo/command_line/list_folders_command.rb
|
72
98
|
- lib/toodledo/command_line/list_goals_command.rb
|
73
|
-
- lib/toodledo/command_line/list_tasks_command.rb
|
74
99
|
- lib/toodledo/command_line/list_tasks_by_context_command.rb
|
100
|
+
- lib/toodledo/command_line/list_tasks_command.rb
|
75
101
|
- lib/toodledo/command_line/parser_helper.rb
|
76
102
|
- lib/toodledo/command_line/setup_command.rb
|
77
103
|
- lib/toodledo/command_line/stdin_command.rb
|
@@ -92,7 +118,9 @@ files:
|
|
92
118
|
- test/session_test.rb
|
93
119
|
- test/toodledo_functional_test.rb
|
94
120
|
has_rdoc: true
|
95
|
-
homepage: http://
|
121
|
+
homepage: http://gemcutter.org/gems/toodledo
|
122
|
+
licenses: []
|
123
|
+
|
96
124
|
post_install_message:
|
97
125
|
rdoc_options:
|
98
126
|
- --main
|
@@ -114,9 +142,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
142
|
requirements: []
|
115
143
|
|
116
144
|
rubyforge_project: toodledo
|
117
|
-
rubygems_version: 1.
|
145
|
+
rubygems_version: 1.3.5
|
118
146
|
signing_key:
|
119
|
-
specification_version:
|
147
|
+
specification_version: 3
|
120
148
|
summary: A command line client and API to Toodledo
|
121
149
|
test_files:
|
122
150
|
- test/client_test.rb
|