toodledo 1.3.1 → 1.3.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/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
|