troo 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +3 -0
- data/Gemfile.lock +4 -1
- data/README.md +7 -7
- data/Rakefile +2 -2
- data/config/en.yml +2 -0
- data/features/support/env.rb +0 -4
- data/lib/troo.rb +14 -26
- data/lib/troo/api/client.rb +28 -6
- data/lib/troo/api/endpoints.rb +42 -30
- data/lib/troo/api/response.rb +5 -0
- data/lib/troo/cli/main.rb +3 -0
- data/lib/troo/cli/wizard.rb +71 -0
- data/lib/troo/configuration.rb +29 -15
- data/lib/troo/debug.rb +9 -0
- data/lib/troo/decorators/resource.rb +8 -4
- data/lib/troo/launcher.rb +22 -12
- data/lib/troo/models/board.rb +2 -2
- data/lib/troo/models/card.rb +2 -2
- data/lib/troo/models/member.rb +1 -1
- data/lib/troo/models/refresh.rb +2 -2
- data/lib/troo/remote/list.rb +1 -1
- data/lib/troo/remote/member.rb +1 -1
- data/lib/troo/remote/persistence/board.rb +6 -10
- data/lib/troo/remote/persistence/card.rb +6 -10
- data/lib/troo/remote/persistence/comment.rb +6 -10
- data/lib/troo/remote/persistence/list.rb +6 -10
- data/lib/troo/remote/persistence/move_card.rb +6 -10
- data/lib/troo/troo.rb +3 -2
- data/lib/troo/version.rb +1 -1
- data/test/lib/troo/api/endpoints_test.rb +12 -22
- data/test/lib/troo/cli/commands/status_test.rb +1 -1
- data/test/lib/troo/cli/wizard_test.rb +44 -0
- data/test/lib/troo/configuration_test.rb +39 -0
- data/test/lib/troo/decorators/resource_test.rb +2 -1
- data/test/lib/troo/models/member_test.rb +1 -1
- data/test/support/fake_trello/fake_response.rb +1 -2
- data/test/support/fake_trello/server.rb +22 -14
- data/test/test_helper.rb +0 -5
- data/troo.gemspec +1 -0
- metadata +20 -6
- data/config/trello_api.yml +0 -19
- data/lib/troo/decorators/member.rb +0 -12
- data/test/lib/troo/decorators/member_test.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f4539888216b2fee0e90cc5a1cffd97a20e8d6d
|
4
|
+
data.tar.gz: e35fc3a74a984d5f3eb0a76f4331d69fe85f5f78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a90ddbf943db77a1544cf98590ba2d4fe2eb491edcfe99cbf254a2f792e88cfa6e7150bf9a71f230e5355e2d140f7a58ed19ede803a7d9db51cd06ca36bcf4db
|
7
|
+
data.tar.gz: 94686af4d0318e6fea58e6392ea4475dcb060a2ea00cd81af47168dca8fe5c227351f8053a72b9bdf0f0e019be16d64c9cf988e2c6bc9d33589ec2afedc6ec08
|
data/.simplecov
ADDED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
troo (0.0.
|
4
|
+
troo (0.0.12)
|
5
5
|
addressable
|
6
6
|
curses (= 1.0.1)
|
7
7
|
dispel
|
8
8
|
json
|
9
|
+
launchy
|
9
10
|
oauth
|
10
11
|
ohm (= 1.3.2)
|
11
12
|
ohm-contrib (= 1.2)
|
@@ -76,6 +77,8 @@ GEM
|
|
76
77
|
minitest (>= 3.0)
|
77
78
|
ice_nine (0.11.0)
|
78
79
|
json (1.8.1)
|
80
|
+
launchy (2.4.2)
|
81
|
+
addressable (~> 2.3)
|
79
82
|
listen (2.7.1)
|
80
83
|
celluloid (>= 0.15.2)
|
81
84
|
celluloid-io (>= 0.15.0)
|
data/README.md
CHANGED
@@ -29,6 +29,12 @@ Or install it yourself as:
|
|
29
29
|
|
30
30
|
You will need user authentication tokens to access your Trello account.
|
31
31
|
|
32
|
+
### Setup Wizard
|
33
|
+
|
34
|
+
Simply run `troo wizard` and follow the on screen instructions.
|
35
|
+
|
36
|
+
### Manually
|
37
|
+
|
32
38
|
1) Sign in to Trello in the normal way.
|
33
39
|
|
34
40
|
2) Create your developer key at Trello:
|
@@ -89,12 +95,6 @@ You will need user authentication tokens to access your Trello account.
|
|
89
95
|
|
90
96
|
troo version
|
91
97
|
|
92
|
-
## Todo
|
93
|
-
|
94
|
-
- Fix multitude of sins.
|
95
|
-
- Write cucumber integration tests.
|
96
|
-
- Convert dates/times to Time.iso8601().
|
97
|
-
|
98
98
|
## Testing
|
99
99
|
|
100
100
|
I've put a simple fake server together so that I'm not hitting the Trello API continuously. You can activate and use this too.
|
@@ -115,7 +115,7 @@ I've put a simple fake server together so that I'm not hitting the Trello API co
|
|
115
115
|
4) Run `server.rb`:
|
116
116
|
|
117
117
|
cd ./test/support/fake_trello
|
118
|
-
|
118
|
+
./server.rb
|
119
119
|
|
120
120
|
5) Have fun.
|
121
121
|
|
data/Rakefile
CHANGED
@@ -19,7 +19,7 @@ if File.exist?(Dir.home + '/.trooconf')
|
|
19
19
|
|
20
20
|
Rake::Task['cucumber'].execute
|
21
21
|
else
|
22
|
-
warn "\nConfiguration cannot be found, please run
|
23
|
-
"init
|
22
|
+
warn "\nConfiguration cannot be found, please run `troo " \
|
23
|
+
"init` or `./bin/troo init` first.\n"
|
24
24
|
exit(1)
|
25
25
|
end
|
data/config/en.yml
CHANGED
data/features/support/env.rb
CHANGED
data/lib/troo.rb
CHANGED
@@ -5,50 +5,38 @@ require_relative 'troo/version'
|
|
5
5
|
|
6
6
|
module Troo
|
7
7
|
ConfigurationNotFound = Class.new(StandardError)
|
8
|
-
|
8
|
+
ConfigurationAborted = Class.new(StandardError)
|
9
|
+
ExpiredAccessToken = Class.new(StandardError)
|
9
10
|
EndpointNotFound = Class.new(StandardError)
|
10
11
|
|
11
|
-
# @param []
|
12
12
|
# @param [String]
|
13
|
-
# @
|
13
|
+
# @param [String]
|
14
|
+
# @return [Troo::Configuration]
|
14
15
|
def self.configuration(file = Dir.home + '/.trooconf', env = 'default')
|
15
16
|
unless File.exist?(file)
|
16
|
-
warn "\nConfiguration cannot be found, please run
|
17
|
-
"init
|
18
|
-
file =
|
17
|
+
warn "\nConfiguration cannot be found, please run `troo " \
|
18
|
+
"init` or `./bin/troo init` first.\n"
|
19
|
+
file = root_path + '/config/trooconf.yml'
|
19
20
|
end
|
20
21
|
|
21
22
|
@configuration ||= Troo::Configuration.load(file, env)
|
22
23
|
end
|
23
24
|
|
24
|
-
# @
|
25
|
-
# @return []
|
26
|
-
def self.endpoints(version = 'version_1')
|
27
|
-
@endpoints ||= Troo::API::Endpoints
|
28
|
-
.load(configuration_path + '/trello_api.yml', version)
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return []
|
25
|
+
# @return [TrueClass]
|
32
26
|
def self.logger
|
33
27
|
@logger ||= Logger
|
34
|
-
.new(
|
28
|
+
.new(root_path + '/logs/troo.log').tap do |log|
|
35
29
|
log.formatter = proc do |mode, time, prog, msg|
|
36
|
-
"#{time.iso8601} #{
|
30
|
+
"\n" + Esc.green + "#{time.iso8601}:" + Esc.reset + " #{msg}\n"
|
37
31
|
end
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
35
|
+
def self.root_path
|
36
|
+
File.expand_path('../..', __FILE__)
|
37
|
+
end
|
38
|
+
|
41
39
|
# RestClient.log = log_dir + '/restclient.log'
|
42
40
|
|
43
41
|
Database.connect(configuration)
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def self.configuration_path
|
48
|
-
File.dirname(__FILE__) + '/../config'
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.log_path
|
52
|
-
File.dirname(__FILE__) + '/../logs'
|
53
|
-
end
|
54
42
|
end
|
data/lib/troo/api/client.rb
CHANGED
@@ -40,15 +40,25 @@ module Troo
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def empty_response?
|
43
|
-
parsed_response.empty?
|
43
|
+
return log(true) if parsed_response.empty?
|
44
|
+
false
|
44
45
|
end
|
45
46
|
|
46
47
|
def error_response?
|
47
|
-
response.is_a?(ErrorResponse)
|
48
|
+
return log(true) if response.is_a?(ErrorResponse)
|
49
|
+
false
|
48
50
|
end
|
49
51
|
|
50
52
|
def parsed_response
|
51
|
-
@parsed ||= Yajl::Parser.parse(
|
53
|
+
@parsed ||= Yajl::Parser.parse(response_body)
|
54
|
+
end
|
55
|
+
|
56
|
+
def response_body
|
57
|
+
data = response.body
|
58
|
+
File.open(filename, 'w') do |file_handle|
|
59
|
+
file_handle.write(data)
|
60
|
+
end
|
61
|
+
data
|
52
62
|
end
|
53
63
|
|
54
64
|
def response
|
@@ -69,7 +79,7 @@ module Troo
|
|
69
79
|
end
|
70
80
|
|
71
81
|
def urn
|
72
|
-
Troo.
|
82
|
+
Troo::API::Endpoints.interpolate(endpoint, interpolation)
|
73
83
|
end
|
74
84
|
|
75
85
|
def missing_parameters?
|
@@ -80,8 +90,9 @@ module Troo
|
|
80
90
|
Troo.configuration.allow_remote
|
81
91
|
end
|
82
92
|
|
83
|
-
def log
|
84
|
-
Troo.logger.debug(formatted_messages) if log?
|
93
|
+
def log(retval = nil)
|
94
|
+
Troo.logger.debug("\n" + formatted_messages) if log?
|
95
|
+
retval
|
85
96
|
end
|
86
97
|
|
87
98
|
def log?
|
@@ -115,6 +126,17 @@ module Troo
|
|
115
126
|
'Response' => response.body
|
116
127
|
}
|
117
128
|
end
|
129
|
+
|
130
|
+
def filename
|
131
|
+
filename = [Troo.root_path + '/tmp/', endpoint.to_s]
|
132
|
+
filename << '_' << external_id if external_id
|
133
|
+
filename << '.json'
|
134
|
+
filename.join
|
135
|
+
end
|
136
|
+
|
137
|
+
def external_id
|
138
|
+
interpolation[:external_id]
|
139
|
+
end
|
118
140
|
end
|
119
141
|
end
|
120
142
|
end
|
data/lib/troo/api/endpoints.rb
CHANGED
@@ -1,45 +1,57 @@
|
|
1
1
|
module Troo
|
2
2
|
module API
|
3
3
|
class Endpoints
|
4
|
-
include Virtus.value_object
|
5
|
-
|
6
|
-
values do
|
7
|
-
attribute :board_by_id
|
8
|
-
attribute :boards_all
|
9
|
-
attribute :card_by_id
|
10
|
-
attribute :cards_by_board_id
|
11
|
-
attribute :cards_by_list_id
|
12
|
-
attribute :comments_by_board_id
|
13
|
-
attribute :comments_by_card_id
|
14
|
-
attribute :comments_by_list_id
|
15
|
-
attribute :create_board
|
16
|
-
attribute :create_card
|
17
|
-
attribute :create_comment
|
18
|
-
attribute :create_list
|
19
|
-
attribute :list_by_id
|
20
|
-
attribute :lists_by_board_id
|
21
|
-
attribute :member_by_id
|
22
|
-
attribute :members_by_board_id
|
23
|
-
attribute :move_card_board
|
24
|
-
attribute :move_card_list
|
25
|
-
end
|
26
|
-
|
27
4
|
class << self
|
28
|
-
# @param [
|
29
|
-
# @param [
|
30
|
-
# @return [
|
31
|
-
def
|
32
|
-
new(
|
5
|
+
# @param [Symbol]
|
6
|
+
# @param [Hash]
|
7
|
+
# @return [String, EndpointNotFound]
|
8
|
+
def interpolate(endpoint, value = {})
|
9
|
+
new(endpoint, value).interpolate
|
33
10
|
end
|
34
11
|
end
|
35
12
|
|
13
|
+
# @param [Symbol]
|
14
|
+
# @param [Hash]
|
15
|
+
# @return [Troo::API::Endpoints]
|
16
|
+
def initialize(endpoint, value = {})
|
17
|
+
@endpoint, @value = endpoint, value
|
18
|
+
end
|
19
|
+
|
36
20
|
# @param [Symbol]
|
37
21
|
# @param [Hash]
|
38
22
|
# @return [String, EndpointNotFound]
|
39
|
-
def interpolate
|
40
|
-
|
23
|
+
def interpolate
|
24
|
+
endpoints.fetch(endpoint) % value
|
25
|
+
rescue KeyError
|
41
26
|
fail EndpointNotFound
|
42
27
|
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :endpoint, :value
|
32
|
+
|
33
|
+
def endpoints
|
34
|
+
{
|
35
|
+
boards_all: '/members/me/boards',
|
36
|
+
board_by_id: '/boards/%{external_id}',
|
37
|
+
card_by_id: '/cards/%{external_id}',
|
38
|
+
list_by_id: '/lists/%{external_id}',
|
39
|
+
member_by_id: '/members/%{external_id}',
|
40
|
+
cards_by_board_id: '/boards/%{external_id}/cards',
|
41
|
+
cards_by_list_id: '/lists/%{external_id}/cards',
|
42
|
+
comments_by_board_id: '/boards/%{external_id}/actions',
|
43
|
+
comments_by_card_id: '/cards/%{external_id}/actions',
|
44
|
+
comments_by_list_id: '/lists/%{external_id}/actions',
|
45
|
+
lists_by_board_id: '/boards/%{external_id}/lists',
|
46
|
+
members_by_board_id: '/boards/%{external_id}/members',
|
47
|
+
create_board: '/boards',
|
48
|
+
create_card: '/cards',
|
49
|
+
create_comment: '/cards/%{external_id}/actions/comments',
|
50
|
+
create_list: '/lists',
|
51
|
+
move_card_list: '/cards/%{external_id}/idList',
|
52
|
+
move_card_board: '/cards/%{external_id}/idBoard',
|
53
|
+
}
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
45
57
|
end
|
data/lib/troo/api/response.rb
CHANGED
@@ -18,11 +18,16 @@ module Troo
|
|
18
18
|
|
19
19
|
# @return [Response, ErrorResponse]
|
20
20
|
def build
|
21
|
+
raise ExpiredAccessToken if expired?
|
21
22
|
ok? ? Response.new(attributes) : ErrorResponse.new(attributes)
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
25
26
|
|
27
|
+
def expired?
|
28
|
+
code == '401'
|
29
|
+
end
|
30
|
+
|
26
31
|
def ok?
|
27
32
|
code == '200'
|
28
33
|
end
|
data/lib/troo/cli/main.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Troo
|
2
|
+
module CLI
|
3
|
+
class Wizard < ThorFixes
|
4
|
+
package_name 'wizard'
|
5
|
+
default_task :start
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
desc 'start', 'Run the configuration wizard to get started.'
|
9
|
+
def start
|
10
|
+
say Troo::Formatter.wordwrap(welcome_message)
|
11
|
+
|
12
|
+
proceed?
|
13
|
+
step_one!
|
14
|
+
|
15
|
+
say Troo::Formatter.wordwrap(step_one_message)
|
16
|
+
|
17
|
+
proceed?
|
18
|
+
step_two!
|
19
|
+
|
20
|
+
say 'All done! Run `troo` for further commands.'
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def connect_url(api_key)
|
26
|
+
"https://trello.com/1/connect?key=#{api_key}" \
|
27
|
+
"&name=troo&response_type=token&scope=read,write"
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_url
|
31
|
+
'https://trello.com/1/appKey/generate'
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
@config ||= Troo::Configuration.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def proceed?
|
39
|
+
raise ConfigurationAborted unless yes?(user_input('Proceed?'))
|
40
|
+
end
|
41
|
+
|
42
|
+
def step_one!
|
43
|
+
Launchy.open(generate_url)
|
44
|
+
config.api_key = ask(user_input('Key:'))
|
45
|
+
config.api_token = ask(user_input('Secret:'))
|
46
|
+
end
|
47
|
+
|
48
|
+
def step_two!
|
49
|
+
Launchy.open(connect_url(config.api_key))
|
50
|
+
config.api_oauth_token = ask(user_input('Token:'))
|
51
|
+
config.save(Dir.home + '/.trooconf', 'default')
|
52
|
+
end
|
53
|
+
|
54
|
+
def welcome_message
|
55
|
+
"Welcome to Troo. This wizard will help you configure your " \
|
56
|
+
"API credentials for Trello. First, you'll need to sign in " \
|
57
|
+
"to Trello in the normal way. Copy the API key and paste " \
|
58
|
+
"when prompted, then do the same for the secret.\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
def step_one_message
|
62
|
+
"Thank you. You must now allow this application to use " \
|
63
|
+
"Trello account. Copy and paste the token when prompted.\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
def user_input(value)
|
67
|
+
[Esc.yellow, value, Esc.reset].join
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/troo/configuration.rb
CHANGED
@@ -1,33 +1,47 @@
|
|
1
1
|
module Troo
|
2
2
|
class Configuration
|
3
|
-
include Virtus.
|
3
|
+
include Virtus.model
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
attribute :logs, Boolean, default: false
|
15
|
-
end
|
5
|
+
attribute :api_key
|
6
|
+
attribute :api_token
|
7
|
+
attribute :api_oauth_token
|
8
|
+
attribute :api_oauth_token_secret
|
9
|
+
attribute :allow_remote, Boolean, default: true
|
10
|
+
attribute :logs, Boolean, default: false
|
11
|
+
attribute :name, String, default: 'My Default Configuration'
|
12
|
+
attribute :api_url, String, default: 'https://api.trello.com/1'
|
13
|
+
attribute :database, Integer, default: 1
|
16
14
|
|
17
15
|
class << self
|
18
|
-
# @param []
|
19
16
|
# @param [String]
|
20
|
-
# @
|
17
|
+
# @param [String]
|
18
|
+
# @return [Troo::Configuration]
|
21
19
|
def load(file, env)
|
22
20
|
new(YAML.load_file(file)[env])
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
26
|
-
# @
|
24
|
+
# @param [String]
|
25
|
+
# @param [String]
|
26
|
+
# @return [TrueClass, FalseClass]
|
27
|
+
def save(file, env)
|
28
|
+
return true if File.open(file, 'w') do |file|
|
29
|
+
file.write configuration_yaml(env)
|
30
|
+
end
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [String]
|
27
35
|
def view
|
28
36
|
attributes.map do |label, value|
|
29
37
|
Preference.view(label: label, value: value)
|
30
38
|
end.join("\n")
|
31
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def configuration_yaml(env = 'default')
|
44
|
+
{ env => self.attributes }.to_yaml
|
45
|
+
end
|
32
46
|
end
|
33
47
|
end
|