wl 0.0.3 → 0.0.4
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/lib/wl/cli.rb +15 -5
- data/lib/wl/client.rb +18 -5
- data/lib/wl/dotwl.rb +4 -0
- data/lib/wl/login.rb +1 -0
- data/lib/wl/task.rb +30 -0
- data/lib/wl/version.rb +1 -1
- data/lib/wl.rb +1 -0
- data/spec/cassettes/tasks.yml +125 -0
- data/spec/helpers/vcr.rb +1 -0
- data/spec/wl/cli_spec.rb +20 -3
- data/spec/wl/client_spec.rb +36 -4
- data/spec/wl/task_spec.rb +7 -0
- data/wl.gemspec +1 -0
- metadata +24 -3
data/lib/wl/cli.rb
CHANGED
@@ -4,22 +4,32 @@ require 'highline'
|
|
4
4
|
module Wl
|
5
5
|
class CLI < Thor
|
6
6
|
desc 'login', 'Logs in to Wunderlist'
|
7
|
-
option :email,
|
7
|
+
option :email, desc: 'Wunderlist email'
|
8
8
|
option :password, desc: 'Wunderlist password'
|
9
9
|
def login
|
10
|
-
email
|
10
|
+
email = options[:email] || ui.ask('Wunderlist email: ')
|
11
11
|
password = options[:password] || ui.ask('Wunderlist password: ') { |q| q.echo = '*' }
|
12
12
|
|
13
|
-
client = Wl::Client.new
|
14
13
|
login = client.login(email, password)
|
15
|
-
|
16
|
-
dotwl = Dotwl.new
|
17
14
|
dotwl.login(login)
|
18
15
|
|
19
16
|
say login.to_json
|
20
17
|
end
|
21
18
|
|
19
|
+
desc 'tasks', 'Lists all your tasks'
|
20
|
+
def tasks
|
21
|
+
say client.tasks.to_json
|
22
|
+
end
|
23
|
+
|
22
24
|
private
|
25
|
+
def client
|
26
|
+
@client ||= Wl::Client.new(dotwl: dotwl)
|
27
|
+
end
|
28
|
+
|
29
|
+
def dotwl
|
30
|
+
@dotwl ||= Dotwl.new
|
31
|
+
end
|
32
|
+
|
23
33
|
def ui
|
24
34
|
@ui ||= HighLine.new
|
25
35
|
end
|
data/lib/wl/client.rb
CHANGED
@@ -1,15 +1,28 @@
|
|
1
|
+
require 'shy'
|
1
2
|
require 'api_smith'
|
2
3
|
|
3
4
|
module Wl
|
4
|
-
class Client <
|
5
|
+
class Client < Shy.new(:dotwl)
|
6
|
+
include APISmith::Client
|
5
7
|
base_uri 'https://api.wunderlist.com/'
|
6
8
|
|
7
9
|
def login(email, password)
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
post('login', extra_query: {email: email, password: password}, transformer: Login)
|
11
|
+
end
|
12
|
+
|
13
|
+
def tasks
|
14
|
+
get('me/tasks', transformer: Task)
|
15
|
+
end
|
16
|
+
|
17
|
+
def base_request_options
|
18
|
+
if dotwl.token
|
19
|
+
{
|
20
|
+
headers: {
|
21
|
+
'Authorization' => "Bearer #{dotwl.token}"
|
22
|
+
}
|
23
|
+
}
|
11
24
|
else
|
12
|
-
|
25
|
+
super
|
13
26
|
end
|
14
27
|
end
|
15
28
|
end
|
data/lib/wl/dotwl.rb
CHANGED
data/lib/wl/login.rb
CHANGED
data/lib/wl/task.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'api_smith'
|
2
|
+
|
3
|
+
module Wl
|
4
|
+
class Task < APISmith::Smash
|
5
|
+
property :id
|
6
|
+
property :assignee_id
|
7
|
+
property :completed_at
|
8
|
+
property :created_at
|
9
|
+
property :created_by_id
|
10
|
+
property :deleted_at
|
11
|
+
property :due_date
|
12
|
+
property :list_id
|
13
|
+
property :local_identifier
|
14
|
+
property :note
|
15
|
+
property :owner_id
|
16
|
+
property :parent_id
|
17
|
+
property :position
|
18
|
+
property :recurrence_count
|
19
|
+
property :recurrence_type
|
20
|
+
property :recurring_parent_id
|
21
|
+
property :starred
|
22
|
+
property :title
|
23
|
+
property :type
|
24
|
+
property :updated_at
|
25
|
+
property :updated_by_id
|
26
|
+
property :user_id
|
27
|
+
property :version
|
28
|
+
property :errors
|
29
|
+
end
|
30
|
+
end
|
data/lib/wl/version.rb
CHANGED
data/lib/wl.rb
CHANGED
@@ -0,0 +1,125 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.wunderlist.com/me/tasks?
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- Bearer 131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Cache-Control:
|
18
|
+
- must-revalidate, private, max-age=0
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Date:
|
22
|
+
- Sun, 24 Mar 2013 07:31:29 GMT
|
23
|
+
Etag:
|
24
|
+
- ! '"778391fe24fb7fcae2a445c4b3a7982a"'
|
25
|
+
Server:
|
26
|
+
- nginx
|
27
|
+
Status:
|
28
|
+
- 200 OK
|
29
|
+
Vary:
|
30
|
+
- Accept-Encoding
|
31
|
+
X-6w-Client-Status:
|
32
|
+
- unknown
|
33
|
+
X-6w-Timestamp:
|
34
|
+
- '1364110288'
|
35
|
+
X-Rack-Cache:
|
36
|
+
- miss
|
37
|
+
X-Ratelimit-Delay-Hard:
|
38
|
+
- '0'
|
39
|
+
X-Ratelimit-Delay-Soft:
|
40
|
+
- '620'
|
41
|
+
X-Request-Id:
|
42
|
+
- 25225fa3fe737f995481ab2cc5ec4548
|
43
|
+
X-Server:
|
44
|
+
- ip-10-227-29-235
|
45
|
+
Transfer-Encoding:
|
46
|
+
- chunked
|
47
|
+
Connection:
|
48
|
+
- keep-alive
|
49
|
+
body:
|
50
|
+
encoding: US-ASCII
|
51
|
+
string: ! "[{\n \"id\": \"ACIdABLJbhA\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n
|
52
|
+
\ \"updated_at\": \"2013-03-24T07:31:24Z\",\n \"title\": \"Do something you
|
53
|
+
want\",\n \"starred\": false,\n \"note\": null,\n \"completed_at\": null,\n
|
54
|
+
\ \"local_identifier\": \"localId:web:ABcDEFGhIJk:Task:BLAHBLAHBLAHBLAH_01\",\n
|
55
|
+
\ \"recurrence_type\": null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\":
|
56
|
+
null,\n \"due_date\": null,\n \"parent_id\": null,\n \"created_by_id\":
|
57
|
+
\"ABcDEFGhIJk\",\n \"updated_by_id\": \"ABcDEFGhIJk\",\n \"completed_by_id\":
|
58
|
+
null,\n \"version\": 1,\n \"assignee_id\": null,\n \"type\": \"Task\",\n
|
59
|
+
\ \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\": \"ABcDEFGhIJk\",\n \"position\":
|
60
|
+
20.00006,\n \"list_id\": \"inbox\",\n \"deleted_at\": null\n}, {\n \"id\":
|
61
|
+
\"ACIdABLJbg4\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n \"updated_at\":
|
62
|
+
\"2013-03-24T07:31:24Z\",\n \"title\": \"Do something productive\",\n \"starred\":
|
63
|
+
false,\n \"note\": null,\n \"completed_at\": null,\n \"local_identifier\":
|
64
|
+
\"localId:web:ABcDEFGhIJk:Task:BLAHBLAHBLAHBLAH_02\",\n \"recurrence_type\":
|
65
|
+
null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\": null,\n \"due_date\":
|
66
|
+
null,\n \"parent_id\": null,\n \"created_by_id\": \"ABcDEFGhIJk\",\n \"updated_by_id\":
|
67
|
+
\"ABcDEFGhIJk\",\n \"completed_by_id\": null,\n \"version\": 1,\n \"assignee_id\":
|
68
|
+
null,\n \"type\": \"Task\",\n \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\":
|
69
|
+
\"ABcDEFGhIJk\",\n \"position\": 10.00003,\n \"list_id\": \"inbox\",\n \"deleted_at\":
|
70
|
+
null\n}, {\n \"id\": \"ACIdABLJbg0\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n
|
71
|
+
\ \"updated_at\": \"2013-03-24T07:31:24Z\",\n \"title\": \"Do something useful\",\n
|
72
|
+
\ \"starred\": false,\n \"note\": null,\n \"completed_at\": null,\n \"local_identifier\":
|
73
|
+
\"localId:web:ABcDEFGhIJk:Task:lw6d7911b474ef405b27406da031d526\",\n \"recurrence_type\":
|
74
|
+
null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\": null,\n \"due_date\":
|
75
|
+
null,\n \"parent_id\": null,\n \"created_by_id\": \"ABcDEFGhIJk\",\n \"updated_by_id\":
|
76
|
+
\"ABcDEFGhIJk\",\n \"completed_by_id\": null,\n \"version\": 1,\n \"assignee_id\":
|
77
|
+
null,\n \"type\": \"Task\",\n \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\":
|
78
|
+
\"ABcDEFGhIJk\",\n \"position\": 2.0e-05,\n \"list_id\": \"inbox\",\n \"deleted_at\":
|
79
|
+
null\n}]\n"
|
80
|
+
http_version:
|
81
|
+
recorded_at: Sun, 24 Mar 2013 07:31:29 GMT
|
82
|
+
- request:
|
83
|
+
method: get
|
84
|
+
uri: https://api.wunderlist.com/me/tasks?
|
85
|
+
body:
|
86
|
+
encoding: US-ASCII
|
87
|
+
string: ''
|
88
|
+
headers: {}
|
89
|
+
response:
|
90
|
+
status:
|
91
|
+
code: 401
|
92
|
+
message: Unauthorized
|
93
|
+
headers:
|
94
|
+
Cache-Control:
|
95
|
+
- no-cache
|
96
|
+
Content-Type:
|
97
|
+
- application/json; charset=utf-8
|
98
|
+
Date:
|
99
|
+
- Sun, 24 Mar 2013 07:47:46 GMT
|
100
|
+
Server:
|
101
|
+
- nginx
|
102
|
+
Status:
|
103
|
+
- 401 Unauthorized
|
104
|
+
X-6w-Client-Status:
|
105
|
+
- unknown
|
106
|
+
X-6w-Timestamp:
|
107
|
+
- '1364111266'
|
108
|
+
X-Rack-Cache:
|
109
|
+
- miss
|
110
|
+
X-Ratelimit-Delay-Hard:
|
111
|
+
- '0'
|
112
|
+
X-Ratelimit-Delay-Soft:
|
113
|
+
- '755'
|
114
|
+
X-Request-Id:
|
115
|
+
- 251d1dd71af0be5b5359ab58a956c367
|
116
|
+
Content-Length:
|
117
|
+
- '85'
|
118
|
+
Connection:
|
119
|
+
- keep-alive
|
120
|
+
body:
|
121
|
+
encoding: US-ASCII
|
122
|
+
string: ! '{"errors":{"message":"You must be authenticated to continue.","type":"unauthorized"}}'
|
123
|
+
http_version:
|
124
|
+
recorded_at: Sun, 24 Mar 2013 07:47:46 GMT
|
125
|
+
recorded_with: VCR 2.4.0
|
data/spec/helpers/vcr.rb
CHANGED
data/spec/wl/cli_spec.rb
CHANGED
@@ -2,13 +2,16 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Wl
|
4
4
|
describe CLI do
|
5
|
-
let(:dotwl) { double(Dotwl).as_null_object }
|
5
|
+
let(:dotwl) { double(Dotwl, token: nil).as_null_object }
|
6
6
|
|
7
7
|
subject do
|
8
|
-
Dotwl.stub(:new).and_return(dotwl)
|
9
8
|
Wl::CLI.start(args)
|
10
9
|
end
|
11
10
|
|
11
|
+
before do
|
12
|
+
Dotwl.stub(:new).and_return(dotwl)
|
13
|
+
end
|
14
|
+
|
12
15
|
context "by default" do
|
13
16
|
let(:args) { [] }
|
14
17
|
|
@@ -28,7 +31,7 @@ module Wl
|
|
28
31
|
|
29
32
|
it 'stores the token' do
|
30
33
|
dotwl.should_receive(:login).with(an_instance_of(Login))
|
31
|
-
subject
|
34
|
+
capture(:stdout) { subject }
|
32
35
|
end
|
33
36
|
|
34
37
|
context 'when an email and password are not provided' do
|
@@ -48,5 +51,19 @@ module Wl
|
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
54
|
+
|
55
|
+
describe 'tasks', vcr: {cassette_name: 'tasks'} do
|
56
|
+
let(:args) { %w"tasks" }
|
57
|
+
|
58
|
+
before do
|
59
|
+
dotwl.stub(token: '131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'prints all the tasks' do
|
63
|
+
output = capture(:stdout) { subject }
|
64
|
+
|
65
|
+
JSON.parse(output).should have(3).tasks
|
66
|
+
end
|
67
|
+
end
|
51
68
|
end
|
52
69
|
end
|
data/spec/wl/client_spec.rb
CHANGED
@@ -2,20 +2,52 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Wl
|
4
4
|
describe Client do
|
5
|
+
let(:dotwl) { double(Dotwl, token: nil) }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
Client.new(dotwl: dotwl)
|
9
|
+
end
|
10
|
+
|
5
11
|
describe '#login' do
|
6
12
|
context 'when the email address and password are accepted', vcr: {cassette_name: 'login'} do
|
7
13
|
it 'packages the api response in a Login object' do
|
8
14
|
response = subject.login('fake@example.com', 'fakepass')
|
9
15
|
response.should be_a(Login)
|
10
16
|
response.email.should == 'fake@example.com'
|
17
|
+
response.errors.should be_nil
|
11
18
|
end
|
12
19
|
end
|
13
20
|
|
14
21
|
context 'when something goes wrong' do
|
15
|
-
it '
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
it 'inserts the errors into the Login object', vcr: {cassette_name: 'login'} do
|
23
|
+
response = subject.login('fake@example.com', 'badpassword')
|
24
|
+
response.should be_a(Login)
|
25
|
+
response.email.should be_nil
|
26
|
+
response.errors['type'].should eq('not_found.no_such_user')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#tasks' do
|
32
|
+
context 'when the user has logged in', vcr: {cassette_name: 'tasks'} do
|
33
|
+
before do
|
34
|
+
dotwl.stub(token: '131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'lists all tasks' do
|
38
|
+
tasks = subject.tasks
|
39
|
+
tasks.map(&:title).should eq [
|
40
|
+
"Do something you want",
|
41
|
+
"Do something productive",
|
42
|
+
"Do something useful"
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when the user has not logged in', vcr: {cassette_name: 'tasks' } do
|
48
|
+
it 'fails gracefully' do
|
49
|
+
tasks = subject.tasks
|
50
|
+
tasks.errors['type'].should eq('unauthorized')
|
19
51
|
end
|
20
52
|
end
|
21
53
|
end
|
data/wl.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -59,6 +59,22 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: shy
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
79
|
name: bundler
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -163,8 +179,10 @@ files:
|
|
163
179
|
- lib/wl/client.rb
|
164
180
|
- lib/wl/dotwl.rb
|
165
181
|
- lib/wl/login.rb
|
182
|
+
- lib/wl/task.rb
|
166
183
|
- lib/wl/version.rb
|
167
184
|
- spec/cassettes/login.yml
|
185
|
+
- spec/cassettes/tasks.yml
|
168
186
|
- spec/helpers/capture_output.rb
|
169
187
|
- spec/helpers/vcr.rb
|
170
188
|
- spec/spec_helper.rb
|
@@ -172,6 +190,7 @@ files:
|
|
172
190
|
- spec/wl/client_spec.rb
|
173
191
|
- spec/wl/dotwl_spec.rb
|
174
192
|
- spec/wl/login_spec.rb
|
193
|
+
- spec/wl/task_spec.rb
|
175
194
|
- wl.gemspec
|
176
195
|
homepage: http://github.com/hiremaga/wl
|
177
196
|
licenses:
|
@@ -188,7 +207,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
207
|
version: '0'
|
189
208
|
segments:
|
190
209
|
- 0
|
191
|
-
hash:
|
210
|
+
hash: 110259217908952548
|
192
211
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
212
|
none: false
|
194
213
|
requirements:
|
@@ -197,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
216
|
version: '0'
|
198
217
|
segments:
|
199
218
|
- 0
|
200
|
-
hash:
|
219
|
+
hash: 110259217908952548
|
201
220
|
requirements: []
|
202
221
|
rubyforge_project:
|
203
222
|
rubygems_version: 1.8.25
|
@@ -207,6 +226,7 @@ summary: ! '`wl` is an unofficial Ruby client and command line interface for the
|
|
207
226
|
awesome Wunderlist'
|
208
227
|
test_files:
|
209
228
|
- spec/cassettes/login.yml
|
229
|
+
- spec/cassettes/tasks.yml
|
210
230
|
- spec/helpers/capture_output.rb
|
211
231
|
- spec/helpers/vcr.rb
|
212
232
|
- spec/spec_helper.rb
|
@@ -214,3 +234,4 @@ test_files:
|
|
214
234
|
- spec/wl/client_spec.rb
|
215
235
|
- spec/wl/dotwl_spec.rb
|
216
236
|
- spec/wl/login_spec.rb
|
237
|
+
- spec/wl/task_spec.rb
|