lionel_richie 0.0.1 → 0.1.0

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/README.md CHANGED
@@ -49,6 +49,55 @@ You should now be ready to run the export:
49
49
 
50
50
  $ lionel
51
51
 
52
+ ## Crafting the Export
53
+
54
+ ```ruby
55
+
56
+ LionelRichie.export do
57
+ # Card Id
58
+ b { id }
59
+
60
+ # Card Link
61
+ c { link }
62
+
63
+ # Ready date
64
+ d do
65
+ ready_action = card.first_action do |a|
66
+ (a.create? && a.board_id == trello_board_id) || a.moved_to?("Ready")
67
+ end
68
+ format_date(ready_action.date) if ready_action
69
+ end
70
+
71
+ # In Progress date
72
+ e { date_moved_to("In Progress") }
73
+
74
+ # Code Review date
75
+ f { date_moved_to("Code Review") }
76
+
77
+ # Review date
78
+ g { date_moved_to("Review") }
79
+
80
+ # Deploy date
81
+ h { date_moved_to("Deploy") }
82
+
83
+ # Completed date
84
+ i { date_moved_to("Completed") }
85
+
86
+ # Type
87
+ j { type }
88
+
89
+ # Project
90
+ k { project }
91
+
92
+ # Estimate
93
+ l { estimate }
94
+
95
+ # Due Date
96
+ m { due_date }
97
+ end
98
+ ```
99
+
100
+
52
101
  ## Contributing
53
102
 
54
103
  1. Fork it
data/bin/lionel CHANGED
@@ -1,109 +1,43 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
3
+ # Trap interrupts to quit cleanly. See
4
+ # https://twitter.com/mitchellh/status/283014103189053442
5
+ Signal.trap("INT") { exit 1 }
4
6
 
5
7
  require 'lionel_richie'
6
8
 
7
- Trello.configure do |c|
8
- c.developer_public_key = ENV['TRELLO_KEY']
9
- c.member_token = ENV['TRELLO_TOKEN']
9
+ # Output message to $stderr, prefixed with the program name
10
+ def pute(*args)
11
+ first = args.shift.dup
12
+ first.insert(0, "#{$0}: ")
13
+ args.unshift(first)
14
+ $stderr.puts(*args)
10
15
  end
11
16
 
12
- board_id = ENV['TRELLO_BOARD_ID']
13
- board = Trello::Board.find(board_id)
14
-
15
- cards = []
16
- board.lists.each do |list|
17
- list.cards.each do |card|
18
- cards << card
19
- end
20
- end
21
-
22
- session = GoogleDrive.login_with_oauth(ENV['GOOGLE_TOKEN'])
23
-
24
- sp = session.spreadsheet_by_key(ENV['GOOGLE_DOC_ID'])
25
- ws = sp.worksheets[0]
26
-
27
- start_row = 2
28
- rows = ws.rows.size
29
-
30
- card_ids = cards.map(&:id)
31
-
32
- def sync_row(ws, row, card)
33
- puts "syncing row[#{row}] with #{card.name}"
34
- ws["B#{row}"] = card.id
35
-
36
- # Card link
37
- ws["C#{row}"] = %Q[=HYPERLINK("#{card.url}", "#{card.name.gsub(/"/, "")}")]
38
-
39
- actions = card.actions
40
- actions = actions.select { |a| a.data["listBefore"].present? }
41
-
42
- # Ready date
43
- ws["D#{row}"] = action_date(actions) do |a|
44
- (a.type == "createCard" && a.data["board"]["id"] == board_id) ||
45
- a.data["listAfter"]["name"] =~ /ready/i
17
+ begin
18
+ Lionel::CLI.start(ARGV)
19
+
20
+ rescue GoogleDrive::Error, GoogleDrive::AuthenticationError => e
21
+ @attempts ||= 0
22
+ @attempts += 1
23
+ Lionel::GoogleAuthentication.new.refresh
24
+ if @attempts < 2
25
+ retry
26
+ else
27
+ puts e.class
28
+ puts "-" * e.class.name.size
29
+ pute e.message
30
+ puts "Unable to access Google Drive"
31
+ puts "run 'lionel authorize'"
46
32
  end
47
33
 
48
- # In Progress date
49
- ws["E#{row}"] = action_date(actions) { |a| a.data["listAfter"]["name"] =~ /^in progress/i }
50
-
51
- # Code Review date
52
- ws["F#{row}"] = action_date(actions) { |a| a.data["listAfter"]["name"] =~ /^code review/i }
53
-
54
- # Review date
55
- ws["G#{row}"] = action_date(actions) { |a| a.data["listAfter"]["name"] =~ /^review/i }
56
-
57
- # Deploy date
58
- ws["H#{row}"] = action_date(actions) { |a| a.data["listAfter"]["name"] =~ /^deploy/i }
34
+ rescue Trello::Error, Trello::InvalidAccessToken => e
35
+ puts "Unable to access Trello"
36
+ puts "run 'lionel authorize'"
59
37
 
60
- # Completed date
61
- ws["I#{row}"] = action_date(actions) { |a| a.data["listAfter"]["name"] =~ /^completed/i }
62
-
63
- # Type
64
- labels = card.labels.map(&:name)
65
- type = labels.detect { |l| l.downcase =~ %r{bug|chore|task}i } || 'story'
66
- ws["J#{row}"] = type
67
-
68
- # Estimate
69
- match = card.name.match(/\[(?<estimate>\w)\]/)
70
- ws["L#{row}"] = match[:estimate] if match
71
-
72
- rescue Trello::Error => e
73
- puts e.inspect
74
- puts card.inspect
75
- end
76
-
77
- def action_date(actions, &block)
78
- actions = actions.select(&block)
79
- return "" if actions.empty?
80
- action = actions.sort { |a, b| a.date <=> b.date }.first
81
- action.date.strftime("%m/%d/%Y")
82
- end
83
-
84
- card_rows = {}
85
-
86
- # Find existing rows for current cards
87
- (start_row..rows).each do |row|
88
- cell_id = ws["B#{row}"]
89
- next unless cell_id.present?
90
- card = cards.find { |c| c.id == cell_id }
91
- next unless card.present?
92
- card_rows[row] = card
93
- end
94
-
95
- # Set available rows for new cards
96
- new_cards = cards - card_rows.values
97
- new_cards.each_with_index do |card, i|
98
- row = rows + i + 1
99
- card_rows[row] = card
38
+ rescue StandardError => e
39
+ puts e.class
40
+ puts "-" * e.class.name.size
41
+ pute e.message
42
+ raise e
100
43
  end
101
-
102
- card_rows.each do |row, card|
103
- sleep 1
104
- Timeout.timeout(5) { sync_row(ws, row, card) }
105
- end
106
-
107
- ws.save
108
-
109
- puts "exiting"
data/lib/lionel.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'yajl'
2
+ require 'trello'
3
+ require 'google_drive'
4
+ require 'launchy'
5
+ require 'thor'
6
+ require 'lionel/version'
7
+ require 'lionel/cli'
8
+ require 'lionel/configuration'
9
+ require 'lionel/configurable'
10
+ require 'lionel/export'
11
+ require 'lionel/proxy_action'
12
+ require 'lionel/proxy_card'
13
+ require 'lionel/proxy_worksheet'
14
+ require 'lionel/trello_authentication'
15
+ require 'lionel/google_authentication'
16
+
17
+ module Lionel
18
+ end
data/lib/lionel/cli.rb ADDED
@@ -0,0 +1,65 @@
1
+ module Lionel
2
+ class CLI < Thor
3
+
4
+ def initialize(*)
5
+ @configuration = Lionel::Configuration.instance
6
+ super
7
+ end
8
+
9
+ desc "authorize PROVIDER", "Allows application to request user authorization for provider (google|trello)"
10
+ def authorize(provider)
11
+ case provider
12
+ when 'trello'
13
+ auth = Lionel::TrelloAuthentication.new
14
+
15
+ Launchy.open(auth.trello_key_url)
16
+ auth.trello_key = ask "Enter trello key:"
17
+
18
+ Launchy.open(auth.trello_token_url)
19
+ auth.trello_token = ask "Enter trello token:"
20
+
21
+ auth.save
22
+ when 'google'
23
+ auth = Lionel::GoogleAuthentication.new
24
+
25
+ Launchy.open(auth.api_console_url)
26
+ auth.google_client_id = ask("Enter your google client id:")
27
+ auth.google_client_secret = ask("Enter your google client secret:")
28
+
29
+ Launchy.open(auth.authorize_url)
30
+ auth.retrieve_access_token ask("Enter your google key:")
31
+
32
+ auth.save
33
+ else
34
+ "Provider not recognized: #{provider}"
35
+ end
36
+ end
37
+
38
+ desc "export", "Saves Trello export to Google Docs"
39
+ method_option "print", :aliases => "-p", :type => :boolean, :default => false, :desc => "Print results instead of saving them to Google Docs."
40
+ def export
41
+ export = Lionel::Export.new
42
+
43
+ unless export.has_sources?
44
+ export.trello_board_id = ask("Enter a trello board id to export from:")
45
+ export.google_doc_id = ask("Enter a google doc id to export to:")
46
+ export.save
47
+ end
48
+
49
+ export.authenticate
50
+
51
+ welcome = "Trello? Is it me you're looking for?"
52
+ say welcome
53
+ say '=' * welcome.size
54
+
55
+ export.download
56
+
57
+ if options['print']
58
+ export.rows.each { |row| say row }
59
+ else
60
+ export.upload
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+ module Lionel
2
+ module Configurable
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ def configuration
8
+ Configuration.instance
9
+ end
10
+
11
+ def save
12
+ configuration.save(data)
13
+ end
14
+
15
+ def data
16
+ {}
17
+ end
18
+
19
+ end
20
+
21
+ module ClassMethods
22
+
23
+ def config_accessor(*args)
24
+ attr_writer(*args)
25
+
26
+ args.each do |reader|
27
+ define_method(reader) do
28
+ instance_variable_get("@#{reader}") || configuration.send(reader)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,79 @@
1
+ require 'singleton'
2
+
3
+ module Lionel
4
+ class Configuration
5
+ include Singleton
6
+ attr_reader :path, :data
7
+
8
+ FILE_NAME = '.lionelrc'
9
+ CONFIG_ACCESSORS = [
10
+ :trello_key, :trello_token, :trello_board_id,
11
+ :google_token, :google_refresh_token,
12
+ :google_client_id, :google_client_secret,
13
+ :google_doc_id
14
+ ]
15
+
16
+ def self.config_accessor(*args)
17
+ delegate(*args, to: :data)
18
+
19
+ args.each do |accessor|
20
+ define_method("#{accessor}=") do |value|
21
+ data.send("#{accessor}=", value)
22
+ write
23
+ end
24
+ end
25
+ end
26
+
27
+ config_accessor(*CONFIG_ACCESSORS)
28
+
29
+ def initialize
30
+ @path = File.join(File.expand_path("~"), FILE_NAME)
31
+ @data = OpenStruct.new(load_data)
32
+ end
33
+
34
+ def save(attrs = {})
35
+ attrs.each do |accessor, value|
36
+ data.send("#{accessor}=", value)
37
+ end
38
+ write
39
+ end
40
+
41
+ def load_data
42
+ load_file
43
+ rescue Errno::ENOENT
44
+ puts "Couldn't load file, falling back to ENV"
45
+ default_data
46
+ end
47
+
48
+ def default_data
49
+ # {
50
+ # 'trello_key' => ENV['TRELLO_KEY'],
51
+ # 'trello_token' => ENV['TRELLO_TOKEN'],
52
+ # 'trello_board_id' => ENV['TRELLO_BOARD_ID'],
53
+ # 'google_token' => ENV['GOOGLE_TOKEN'],
54
+ # 'google_refresh_token' => ENV['GOOGLE_REFRESH_TOKEN'],
55
+ # 'google_doc_id' => ENV['GOOGLE_DOC_ID']
56
+ # 'google_client_id' => ENV['GOOGLE_CLIENT_ID']
57
+ # 'google_client_secret' => ENV['GOOGLE_CLIENT_SECRET']
58
+ # }
59
+ {}.tap do |data|
60
+ CONFIG_ACCESSORS.each do |name|
61
+ data[name] = ENV[name.to_s.upcase]
62
+ end
63
+ end
64
+ end
65
+
66
+ def load_file
67
+ require 'yaml'
68
+ YAML.load_file(@path)
69
+ end
70
+
71
+ def write
72
+ require 'yaml'
73
+ File.open(@path, File::RDWR|File::TRUNC|File::CREAT, 0600) do |rcfile|
74
+ rcfile.write @data.marshal_dump.to_yaml
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,162 @@
1
+ module Lionel
2
+ class Export
3
+ include Configurable
4
+
5
+ config_accessor :google_doc_id, :trello_board_id
6
+
7
+ def has_sources?
8
+ trello_board_id && google_doc_id
9
+ end
10
+
11
+ def data
12
+ {
13
+ trello_board_id: trello_board_id,
14
+ google_doc_id: google_doc_id
15
+ }
16
+ end
17
+
18
+ def board
19
+ @board ||= Trello::Board.find(trello_board_id)
20
+ end
21
+
22
+ def cards
23
+ cards ||= [].tap do |c|
24
+ # iterate over active lists rather
25
+ # than retrieving all historical cards;
26
+ # trello api returns association proxy
27
+ # that does not respond to "flatten"
28
+ board.lists.each do |list|
29
+ list.cards.each do |card|
30
+ c << card
31
+ end
32
+ end
33
+ end.map { |c| Lionel::ProxyCard.new(c) }
34
+ end
35
+
36
+ def spreadsheet
37
+ @spreadsheet ||= google_session.spreadsheet_by_key(google_doc_id)
38
+ end
39
+
40
+ def worksheet
41
+ @worksheet ||= Lionel::ProxyWorksheet.new(spreadsheet.worksheets[0])
42
+ end
43
+
44
+ def download
45
+ puts "Exporting trello board '#{board.name}' (#{trello_board_id}) to " + "google doc '#{spreadsheet.title}' (#{google_doc_id})"
46
+
47
+ start_row = 2
48
+ rows = worksheet.size
49
+
50
+ card_rows = {}
51
+
52
+ # Find existing rows for current cards
53
+ (start_row..rows).each do |row|
54
+ cell_id = worksheet["B",row]
55
+ next unless cell_id.present?
56
+ card = cards.find { |c| c.id == cell_id }
57
+ next unless card.present?
58
+ card_rows[row] = card
59
+ end
60
+
61
+ # Set available rows for new cards
62
+ new_cards = cards - card_rows.values
63
+ new_cards.each_with_index do |card, i|
64
+ row = rows + i + 1
65
+ card_rows[row] = card
66
+ end
67
+
68
+ card_rows.each do |row, card|
69
+ Timeout.timeout(5) { sync_row(row, card) }
70
+ end
71
+ end
72
+
73
+ class CardMap
74
+ include Enumerable
75
+
76
+ attr_reader :cards, :worksheet
77
+
78
+ def initialize(cards, worksheet)
79
+ @cards, @worksheet = cards, worksheet
80
+ end
81
+
82
+ def each(&block)
83
+ card_rows.each(&block)
84
+ end
85
+
86
+ def card_rows
87
+ @card_rows ||= {}.tap do |map|
88
+ end
89
+ end
90
+ end
91
+
92
+ def upload
93
+ worksheet.save
94
+ end
95
+
96
+ def rows
97
+ worksheet.rows
98
+ end
99
+
100
+ def sync_row(row, card)
101
+ puts "row[#{row}] : #{card.name}"
102
+
103
+ worksheet["B",row] = card.id
104
+
105
+ # Card link
106
+ worksheet["C",row] = card.link
107
+
108
+ # Ready date
109
+ ready_action = card.first_action do |a|
110
+ (a.create? && a.board_id == trello_board_id) || a.moved_to?("Ready")
111
+ end
112
+ worksheet["D",row] = card.format_date(ready_action.date) if ready_action
113
+
114
+ # In Progress date
115
+ worksheet["E",row] = card.date_moved_to("In Progress")
116
+
117
+ # Code Review date
118
+ worksheet["F",row] = card.date_moved_to("Code Review")
119
+
120
+ # Review date
121
+ worksheet["G",row] = card.date_moved_to("Review")
122
+
123
+ # Deploy date
124
+ worksheet["H",row] = card.date_moved_to("Deploy")
125
+
126
+ # Completed date
127
+ worksheet["I",row] = card.date_moved_to("Completed")
128
+
129
+ # Type
130
+ worksheet["J",row] = card.type
131
+
132
+ # Project
133
+ worksheet["K",row] = card.project
134
+
135
+ # Estimate
136
+ worksheet["L",row] = card.estimate
137
+
138
+ # Due Date
139
+ worksheet["M",row] = card.due_date
140
+
141
+ rescue Trello::Error => e
142
+ puts e.inspect
143
+ puts card.inspect
144
+ end
145
+
146
+ def authenticate
147
+ return if @authenticated
148
+ trello_session.configure
149
+ google_session
150
+ @authenticated
151
+ end
152
+
153
+ def google_session
154
+ @google_session ||= GoogleDrive.login_with_oauth(configuration.google_token)
155
+ end
156
+
157
+ def trello_session
158
+ @trello_session ||= TrelloAuthentication.new
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,58 @@
1
+ module Lionel
2
+ class GoogleAuthentication
3
+ include Configurable
4
+
5
+ attr_reader :access_token
6
+ config_accessor :google_client_id, :google_client_secret
7
+
8
+ def data
9
+ raise "No access token" unless access_token
10
+ {
11
+ google_token: access_token.token,
12
+ google_refresh_token: access_token.refresh_token,
13
+ google_client_id: google_client_id,
14
+ google_client_secret: google_client_secret
15
+ }
16
+ end
17
+
18
+ def retrieve_access_token(authorization_code)
19
+ @access_token = client.auth_code.get_token(authorization_code,
20
+ :redirect_uri => "urn:ietf:wg:oauth:2.0:oob")
21
+ end
22
+
23
+ def refresh
24
+ return false unless refresh_token
25
+
26
+ current_token = OAuth2::AccessToken.from_hash(client,
27
+ {:refresh_token => refresh_token, :expires_at => 36000})
28
+ @access_token = current_token.refresh! # returns new access_token
29
+ end
30
+
31
+ def authorize_url
32
+ client.auth_code.authorize_url(
33
+ :redirect_uri => "urn:ietf:wg:oauth:2.0:oob",
34
+ :scope =>
35
+ "https://docs.google.com/feeds/ " +
36
+ "https://docs.googleusercontent.com/ " +
37
+ "https://spreadsheets.google.com/feeds/")
38
+ end
39
+
40
+ def api_console_url
41
+ "https://code.google.com/apis/console"
42
+ end
43
+
44
+ private
45
+
46
+ def client
47
+ @client ||= OAuth2::Client.new(google_client_id, google_client_secret,
48
+ :site => "https://accounts.google.com",
49
+ :token_url => "/o/oauth2/token",
50
+ :authorize_url => "/o/oauth2/auth")
51
+ end
52
+
53
+ def refresh_token
54
+ @refresh_token || configuration.google_refresh_token
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,48 @@
1
+ module Lionel
2
+ class ProxyAction
3
+ attr_reader :action
4
+ delegate :data, :type, :date, to: :action
5
+
6
+ def initialize(action)
7
+ @action = action
8
+ end
9
+
10
+ def data_attributes(key)
11
+ data[key] || {}
12
+ end
13
+
14
+ def create?
15
+ type == "createCard"
16
+ end
17
+
18
+ def update?
19
+ type == "updateCard"
20
+ end
21
+
22
+ def board_id
23
+ data_attributes("board")["id"]
24
+ end
25
+
26
+ def list_after
27
+ data_attributes("listAfter")
28
+ end
29
+
30
+ def list_before
31
+ data_attributes("listBefore")
32
+ end
33
+
34
+ def list_after?
35
+ list_after.any?
36
+ end
37
+
38
+ def list_before?
39
+ list_before.any?
40
+ end
41
+
42
+ def moved_to?(list_name)
43
+ return false unless list_after?
44
+ !!(list_after["name"] =~ %r{^#{Regexp.escape(list_name.downcase)}}i)
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,62 @@
1
+ module Lionel
2
+ class ProxyCard
3
+ attr_reader :card
4
+ delegate :id, :url, :name, :due, to: :card
5
+
6
+ def initialize(card)
7
+ @card = card
8
+ end
9
+
10
+ def link
11
+ %Q[=HYPERLINK("#{card.url}", "#{card.name.gsub(/"/, "")}")]
12
+ end
13
+
14
+ def actions
15
+ @actions ||= card.actions.map { |a| Lionel::ProxyAction.new(a) }
16
+ end
17
+
18
+ def action_date(&block)
19
+ filtered = actions.select(&block)
20
+ return "" if filtered.empty?
21
+ action = filtered.sort { |a, b| a.date <=> b.date }.first
22
+ format_date action.date
23
+ end
24
+
25
+ def date_moved_to(list_name)
26
+ action = first_action { |a| a.moved_to?(list_name) }
27
+ return "" unless action
28
+ format_date(action.date)
29
+ end
30
+
31
+ def format_date(date, format = "%m/%d/%Y")
32
+ date.strftime(format)
33
+ end
34
+
35
+ def first_action(&block)
36
+ actions.select(&block).sort { |a, b| a.date <=> b.date }.first
37
+ end
38
+
39
+ def type
40
+ labels.detect { |l| l =~ %r{bug|chore|task}i } || 'story'
41
+ end
42
+
43
+ def project
44
+ labels.detect { |l| l !~ %r{bug|chore|task}i }
45
+ end
46
+
47
+ def labels
48
+ @labels ||= card.labels.map(&:name).map(&:downcase)
49
+ end
50
+
51
+ def estimate
52
+ match = card.name.match(/\[(?<estimate>\w)\]/)
53
+ return "" unless match
54
+ match[:estimate]
55
+ end
56
+
57
+ def due_date
58
+ format_date(due) if due
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,25 @@
1
+ module Lionel
2
+ class ProxyWorksheet
3
+ delegate :rows, to: :worksheet
4
+ delegate :size, to: :rows
5
+
6
+ attr_reader :worksheet
7
+ def initialize(worksheet)
8
+ @worksheet = worksheet
9
+ end
10
+
11
+ def []=(col, row, value)
12
+ worksheet["#{col}#{row}"] = value
13
+ end
14
+
15
+ def [](col, row)
16
+ worksheet["#{col}#{row}"]
17
+ end
18
+
19
+ HEADER_ROW = 1
20
+ def content_rows
21
+ rows(HEADER_ROW)
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ module Lionel
2
+ class TrelloAuthentication
3
+ include Configurable
4
+
5
+ config_accessor :trello_key, :trello_token
6
+
7
+ def data
8
+ {
9
+ trello_key: trello_key,
10
+ trello_token: trello_token
11
+ }
12
+ end
13
+
14
+ def configure
15
+ Trello.configure do |c|
16
+ c.developer_public_key = trello_key
17
+ c.member_token = trello_token
18
+ end
19
+ end
20
+
21
+ def trello_key_url
22
+ "https://trello.com/1/appKey/generate"
23
+ end
24
+
25
+ def trello_token_url(key = trello_key)
26
+ "https://trello.com/1/authorize?key=#{key}&name=#{app_name}&response_type=token&scope=read,write,account&expiration=never"
27
+ end
28
+
29
+ def app_name
30
+ "LionelRichie"
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Lionel
2
+ VERSION = "0.1.0"
3
+ end
data/lib/lionel_richie.rb CHANGED
@@ -1,8 +1 @@
1
- require 'yajl'
2
- require 'trello'
3
- require 'google_drive'
4
- require "lionel_richie/version"
5
-
6
- module LionelRichie
7
- # Your code goes here...
8
- end
1
+ require 'lionel'
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'lionel_richie/version'
4
+ require 'lionel/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "lionel_richie"
8
- spec.version = LionelRichie::VERSION
8
+ spec.version = Lionel::VERSION
9
9
  spec.authors = ["Ross Kaffenberger"]
10
10
  spec.email = ["rosskaff@gmail.com"]
11
11
  spec.description = %q{Export Trello to Google Docs}
@@ -18,11 +18,14 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.bindir = 'bin'
22
+ spec.executables = %w(lionel)
23
+
21
24
  spec.add_dependency "ruby-trello"
22
25
  spec.add_dependency "google_drive"
23
26
  spec.add_dependency "yajl-ruby"
27
+ spec.add_dependency "thor"
24
28
 
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
29
  spec.add_development_dependency "bundler", "~> 1.3"
27
30
  spec.add_development_dependency "launchy"
28
31
  end
data/script/console ADDED
@@ -0,0 +1,13 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+
5
+ # Trap interrupts to quit cleanly. See
6
+ # https://twitter.com/mitchellh/status/283014103189053442
7
+ Signal.trap("INT") { exit 1 }
8
+
9
+ require 'irb'
10
+ require 'lionel_richie'
11
+
12
+ ARGV.clear # otherwise all script parameters get passed to IRB
13
+ IRB.start
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lionel_richie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-09 00:00:00.000000000 Z
12
+ date: 2013-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-trello
@@ -60,21 +60,21 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: bundler
63
+ name: thor
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
- - - ~>
67
+ - - ! '>='
68
68
  - !ruby/object:Gem::Version
69
- version: '1.3'
70
- type: :development
69
+ version: '0'
70
+ type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
- - - ~>
75
+ - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
- version: '1.3'
77
+ version: '0'
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: bundler
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -111,7 +111,6 @@ description: Export Trello to Google Docs
111
111
  email:
112
112
  - rosskaff@gmail.com
113
113
  executables:
114
- - authorize_lionel
115
114
  - lionel
116
115
  extensions: []
117
116
  extra_rdoc_files: []
@@ -121,11 +120,21 @@ files:
121
120
  - LICENSE.txt
122
121
  - README.md
123
122
  - Rakefile
124
- - bin/authorize_lionel
125
123
  - bin/lionel
124
+ - lib/lionel.rb
125
+ - lib/lionel/cli.rb
126
+ - lib/lionel/configurable.rb
127
+ - lib/lionel/configuration.rb
128
+ - lib/lionel/export.rb
129
+ - lib/lionel/google_authentication.rb
130
+ - lib/lionel/proxy_action.rb
131
+ - lib/lionel/proxy_card.rb
132
+ - lib/lionel/proxy_worksheet.rb
133
+ - lib/lionel/trello_authentication.rb
134
+ - lib/lionel/version.rb
126
135
  - lib/lionel_richie.rb
127
- - lib/lionel_richie/version.rb
128
136
  - lionel_richie.gemspec
137
+ - script/console
129
138
  homepage: ''
130
139
  licenses:
131
140
  - MIT
data/bin/authorize_lionel DELETED
@@ -1,61 +0,0 @@
1
- #! /usr/bin/env ruby
2
-
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
-
5
- require 'bundler'
6
- require 'lionel_richie'
7
- Bundler.require(:development)
8
-
9
- commands = []
10
-
11
- puts "Authorize for Trello?"
12
- if gets.strip =~ /\Ay/i
13
- Launchy.open "https://trello.com/1/appKey/generate"
14
- puts "Enter your trello key:"
15
- trello_key = gets.strip
16
- commands << "export TRELLO_KEY=#{trello_key}"
17
-
18
- Launchy.open "https://trello.com/1/authorize?key=#{trello_key.strip}&name=LionelRichie&response_type=token&scope=read,write,account&expiration=never"
19
- puts "Enter your trello token"
20
- trello_token = gets.strip
21
- commands << "export TRELLO_TOKEN=#{trello_token}"
22
- end
23
-
24
- # Google Auth
25
- puts "Authorize for Google?"
26
- if gets.strip =~ /\Ay/i
27
- client = OAuth2::Client.new(
28
- ENV['GOOGLE_CLIENT_ID'],
29
- ENV['GOOGLE_CLIENT_SECRET'],
30
- :site => "https://accounts.google.com",
31
- :token_url => "/o/oauth2/token",
32
- :authorize_url => "/o/oauth2/auth")
33
-
34
- if !(refresh_token = ENV['GOOGLE_REFRESH_TOKEN'])
35
- google_auth_token = OAuth2::AccessToken.from_hash(client,
36
- {:refresh_token => refresh_token, :expires_at => 7200})
37
- google_auth_token = google_auth_token.refresh!
38
- else
39
- auth_url = client.auth_code.authorize_url(
40
- :redirect_uri => "urn:ietf:wg:oauth:2.0:oob",
41
- :scope =>
42
- "https://docs.google.com/feeds/ " +
43
- "https://docs.googleusercontent.com/ " +
44
- "https://spreadsheets.google.com/feeds/")
45
-
46
- # Redirect the user to auth_url and get authorization code from redirect URL.
47
- Launchy.open auth_url
48
-
49
- puts "Enter your google key:"
50
- authorization_code = gets.strip
51
- google_auth_token = client.auth_code.get_token(
52
- authorization_code,
53
- :redirect_uri => "urn:ietf:wg:oauth:2.0:oob")
54
- end
55
-
56
- commands << "export GOOGLE_TOKEN=#{google_auth_token.token}"
57
- commands << "export GOOGLE_REFRESH_TOKEN=#{google_auth_token.refresh_token}"
58
- end
59
-
60
- puts "Run the following:\n"
61
- puts commands
@@ -1,3 +0,0 @@
1
- module LionelRichie
2
- VERSION = "0.0.1"
3
- end