sd-ruby-libs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5585ce25566d5dfdf7447411490f187c5e1292e0
4
+ data.tar.gz: 499df0a567a0afc06d66c40bfac727acc584a41a
5
+ SHA512:
6
+ metadata.gz: a73fce6fbdc1496e6752b1cd312eff00056e5b323476897ba79c004e0bf4032acb430b092a981f2c7987f2792a3ba05df45b7a1fd77ab69389e0205048e8fa41
7
+ data.tar.gz: d55c92da3739ffa84900a4b80846fd94329bd495b461bc27b742e2dd97d791ded9e7ac96a0bdf3a17502de3c53f51c8256ef2c89693a4bf045d1ea07c870d41b
@@ -0,0 +1,3 @@
1
+ ---
2
+ Metrics/LineLength:
3
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,57 @@
1
+ require 'writeexcel'
2
+ require 'write_xlsx'
3
+
4
+ # `Generic` 2d Data set to excel file generator
5
+ module ExcelReports
6
+ Youtube_time_link = Struct.new(:video, :time) do
7
+ def time_in_seconds
8
+ return 0 unless time
9
+ segments = time.split(':')
10
+ (segments[0].to_i * 3600) + (segments[1].to_i * 60) + segments[2].to_i
11
+ rescue
12
+ return 0
13
+ end
14
+
15
+ def excel_hyperlink
16
+ return '' unless time
17
+ "=hyperlink(\"https://youtu.be/#{video}?t=#{time_in_seconds}\", \"#{time}\")"
18
+ end
19
+
20
+ def to_s
21
+ time
22
+ end
23
+ end
24
+
25
+ def multi_array_to_xlsx(column_info, data, filename, freeze_panes: nil)
26
+ workbook ||= WriteXLSX.new("#{filename}.xlsx")
27
+
28
+ format_heading = workbook.add_format # Add a format
29
+ format_heading.set_bold
30
+ format_heading.set_align('center')
31
+
32
+ data.each do |sheet|
33
+ worksheet = workbook.add_worksheet sheet.first
34
+
35
+ worksheet.freeze_panes(freeze_panes[:y], freeze_panes[:x]) if freeze_panes
36
+
37
+ row = 0
38
+
39
+ column_info.each_with_index do |column, index|
40
+ worksheet.set_column(index, index, column[1])
41
+ worksheet.write(row, index, column.first, format_heading)
42
+ end
43
+ row = row.next
44
+
45
+ next unless sheet.last
46
+ sheet.last.each do |record|
47
+ record.each_with_index do |cell, index|
48
+ worksheet.write(row, index, cell) unless cell.last
49
+ worksheet.write(row, index, cell.last) if cell.last
50
+ end
51
+ row = row.next
52
+ end
53
+ end
54
+
55
+ workbook.close
56
+ end
57
+ end
@@ -0,0 +1,73 @@
1
+ require 'google/apis/drive_v3'
2
+ require 'googleauth'
3
+ require 'googleauth/stores/file_token_store'
4
+ require 'pry'
5
+ require 'fileutils'
6
+
7
+ class GoogleDriveHelper
8
+ def initialize
9
+ @GDRIVE_OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
10
+ @GDRIVE_APPLICATION_NAME = 'Drive API Ruby Quickstart'
11
+ @GDRIVE_CLIENT_SECRETS_PATH = 'drive_client_secret.json'
12
+ @GDRIVE_CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
13
+ "drive-ruby-permissions.yaml")
14
+ @GDRIVE_SCOPE = Google::Apis::DriveV3::AUTH_DRIVE
15
+ end
16
+
17
+ ##
18
+ # Ensure valid credentials, either by restoring from the saved credentials
19
+ # files or intitiating an OAuth2 authorization. If authorization is required,
20
+ # the user's default browser will be launched to approve the request.
21
+ #
22
+ # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
23
+ def authorize
24
+ FileUtils.mkdir_p(File.dirname(@GDRIVE_CREDENTIALS_PATH))
25
+
26
+ client_id = Google::Auth::ClientId.from_file(@GDRIVE_CLIENT_SECRETS_PATH)
27
+ token_store = Google::Auth::Stores::FileTokenStore.new(file: @GDRIVE_CREDENTIALS_PATH)
28
+ authorizer = Google::Auth::UserAuthorizer.new(
29
+ client_id, @GDRIVE_SCOPE, token_store)
30
+ user_id = 'default'
31
+ credentials = authorizer.get_credentials(user_id)
32
+ if credentials.nil?
33
+ url = authorizer.get_authorization_url(
34
+ base_url: @GDRIVE_OOB_URI)
35
+ puts "Open the following URL in the browser and enter the " +
36
+ "resulting code after authorization"
37
+ puts url
38
+ code = gets
39
+ credentials = authorizer.get_and_store_credentials_from_code(
40
+ user_id: user_id, code: code, base_url: @GDRIVE_OOB_URI)
41
+ end
42
+ credentials
43
+ end
44
+
45
+ def share_document(document, email_address)
46
+ # Initialize the API
47
+ service = Google::Apis::DriveV3::DriveService.new
48
+ service.client_options.application_name = @GDRIVE_APPLICATION_NAME
49
+ service.authorization = authorize
50
+
51
+ file_id = document
52
+ callback = lambda do |res, err|
53
+ if err
54
+ # Handle error...
55
+ puts errb.psqlody
56
+ else
57
+ # puts "Permission ID: #{res.id}"
58
+ end
59
+ end
60
+
61
+ service.batch do |drive|
62
+ user_permission = {
63
+ type: 'user',
64
+ role: 'writer',
65
+ email_address: email_address
66
+ }
67
+ drive.create_permission(file_id,
68
+ user_permission,
69
+ fields: 'id',
70
+ &callback)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,398 @@
1
+ require 'google/apis/sheets_v4'
2
+ require 'googleauth'
3
+ require 'googleauth/stores/file_token_store'
4
+ require '../rubyLibs/google_drive.rb'
5
+ require 'pry'
6
+ require 'fileutils'
7
+
8
+ OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'.freeze
9
+ APPLICATION_NAME = 'Google Sheets API Export Tool'.freeze
10
+ CLIENT_SECRETS_PATH = 'client_secret.json'.freeze
11
+
12
+ begin
13
+ CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
14
+ 'sheets.googleapis.com-ruby-quickstart.yaml')
15
+ rescue StandardError
16
+ # @todo had to catch for error when home isn't 'set'. need to find better place for creds to go
17
+ CREDENTIALS_PATH = File.join('/root/.credentials',
18
+ 'sheets.googleapis.com-ruby-quickstart.yaml')
19
+ end
20
+ # SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY
21
+ SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS
22
+
23
+ ##
24
+ # Ensure valid credentials, either by restoring from the saved credentials
25
+ # files or intitiating an OAuth2 authorization. If authorization is required,
26
+ # the user's default browser will be launched to approve the request.
27
+ #
28
+ # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
29
+ def authorize
30
+ FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
31
+
32
+ client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH)
33
+ token_store = Google::Auth::Stores::FileTokenStore.new(file: CREDENTIALS_PATH)
34
+ authorizer = Google::Auth::UserAuthorizer.new(
35
+ client_id, SCOPE, token_store
36
+ )
37
+ user_id = 'default'
38
+ credentials = authorizer.get_credentials(user_id)
39
+ if credentials.nil?
40
+ url = authorizer.get_authorization_url(
41
+ base_url: OOB_URI
42
+ )
43
+ puts 'Open the following URL in the browser and enter the ' \
44
+ 'resulting code after authorization'
45
+ puts url
46
+ code = gets
47
+ credentials = authorizer.get_and_store_credentials_from_code(
48
+ user_id: user_id, code: code, base_url: OOB_URI
49
+ )
50
+ end
51
+ credentials
52
+ end
53
+
54
+ # Utility class to export data into specified sheet id, overwrites existing sheets completely
55
+ class GoogleSheetsExporter
56
+ attr_accessor :headers, :spreadsheet_id, :data, :sheets, :service, :email_address, :document_name
57
+
58
+ def initialize(headers, spreadsheet_id, data, email_address = nil, document_name = nil)
59
+ @headers = headers
60
+
61
+ @email_address = email_address
62
+ @document_name = document_name
63
+
64
+ @data = data
65
+
66
+ # initialize api
67
+ @sheets = Google::Apis::SheetsV4
68
+ @service = Google::Apis::SheetsV4::SheetsService.new
69
+ @service.client_options.application_name = APPLICATION_NAME
70
+ @service.authorization = authorize
71
+
72
+ return unless spreadsheet_id
73
+ @spreadsheet_id = spreadsheet_id unless spreadsheet_id && spreadsheet_id['https://']
74
+ begin
75
+ @spreadsheet_id = spreadsheet_id.match(%r{/([^/]{44})[/]?})[1] if spreadsheet_id['https://']
76
+ rescue
77
+ puts "Provided spreadsheet address does not work."
78
+ end
79
+ end
80
+
81
+ def spreadsheet_url
82
+ "https://docs.google.com/spreadsheets/d/#{spreadsheet_id}/"
83
+ end
84
+
85
+ def sheet_id_from_name(sheet_name)
86
+ retries ||= 0
87
+ service
88
+ .get_spreadsheet(spreadsheet_id)
89
+ .to_h[:sheets]
90
+ .select { |sheet| sheet[:properties][:title] == sheet_name }
91
+ .first[:properties][:sheet_id]
92
+ rescue StandardError => e
93
+ puts "Sheet name #{sheet_name} not found. Retry #{retries}"
94
+ sleep 5 ** (retries + 1) / 10.to_f
95
+ retry if (retries += 1) < 6
96
+ return 0
97
+ end
98
+
99
+ def batch_update(request)
100
+ batch = sheets::BatchUpdateSpreadsheetRequest.new(request)
101
+
102
+ begin
103
+ retries ||= 0
104
+ service.batch_update_spreadsheet spreadsheet_id, batch, {}
105
+ rescue StandardError => e
106
+ binding.pry if ENV['HACKING']
107
+ return true if e.to_s['already exists']
108
+ return false if e.to_s['Requested entity was not found.']
109
+ puts "Error with google API calling #{request} on retry #{retries}"
110
+ puts e
111
+ sleep 5 ** (retries + 1) / 10.to_f
112
+ retry if (retries += 1) < 6 and not e.to_s['Invalid request']
113
+ end
114
+ end
115
+
116
+ def auto_resize_sheet(sheet)
117
+ batch_update(requests: [
118
+ {
119
+ auto_resize_dimensions: {
120
+ dimensions: {
121
+ sheet_id: sheet_id_from_name(sheet.first),
122
+ dimension: 'COLUMNS'
123
+ }
124
+ }
125
+ }
126
+ ])
127
+ end
128
+
129
+ def sheet_default_font(sheet)
130
+ batch_update(requests: [
131
+ {
132
+ repeat_cell: {
133
+ range: {
134
+ sheet_id: sheet_id_from_name(sheet.first)
135
+ },
136
+ cell: {
137
+ user_entered_format: {
138
+ text_format: {
139
+ font_size: 11,
140
+ font_family: 'Arial'
141
+ }
142
+ }
143
+ },
144
+ fields: 'user_entered_format(text_format, horizontal_alignment)'
145
+ }
146
+ }
147
+ ])
148
+ end
149
+
150
+ def bold_row(sheet, start_row_index, end_row_index)
151
+ batch_update(requests: [
152
+ {
153
+ repeat_cell: {
154
+ range: {
155
+ sheet_id: sheet_id_from_name(sheet.first),
156
+ start_row_index: start_row_index,
157
+ end_row_index: end_row_index + 1
158
+ },
159
+ cell: {
160
+ user_entered_format: {
161
+ horizontal_alignment: 'CENTER',
162
+ text_format: {
163
+ foreground_color: {
164
+ red: 20.0 / 255,
165
+ green: 108.0 / 255,
166
+ blue: 124.0 / 255
167
+ },
168
+ font_size: 11,
169
+ bold: true
170
+ }
171
+ }
172
+ },
173
+ fields: 'user_entered_format(text_format, horizontal_alignment)'
174
+ }
175
+ },
176
+ {
177
+ update_sheet_properties: {
178
+ properties: {
179
+ sheet_id: sheet_id_from_name(sheet.first),
180
+ grid_properties: {
181
+ frozen_row_count: 1
182
+ }
183
+ },
184
+ fields: 'grid_properties.frozen_row_count'
185
+ }
186
+ }
187
+ ])
188
+ end
189
+
190
+ def format_column(sheet, start_column_index, end_column_index, horizontal_alignment = 'left', bold = false, font_size = 11)
191
+ horizontal_alignment = 'left' unless horizontal_alignment
192
+ batch_update(requests: [
193
+ {
194
+ repeat_cell: {
195
+ range: {
196
+ sheet_id: sheet_id_from_name(sheet.first),
197
+ start_column_index: start_column_index,
198
+ end_column_index: end_column_index + 1
199
+ },
200
+ cell: {
201
+ user_entered_format: {
202
+ horizontal_alignment: horizontal_alignment.upcase,
203
+ text_format: {
204
+ font_size: font_size,
205
+ bold: bold
206
+ }
207
+ }
208
+ },
209
+ fields: 'user_entered_format(text_format, horizontal_alignment)'
210
+ }
211
+ }
212
+ ])
213
+ end
214
+
215
+ def number_format_column(sheet, start_column_index, end_column_index, pattern = '#,##0.00')
216
+ batch_update(requests: [
217
+ {
218
+ repeat_cell: {
219
+ range: {
220
+ sheet_id: sheet_id_from_name(sheet.first),
221
+ start_column_index: start_column_index,
222
+ end_column_index: end_column_index + 1
223
+ },
224
+ cell: {
225
+ user_entered_format: {
226
+ number_format: {
227
+ type: 'NUMBER',
228
+ pattern: pattern
229
+ }
230
+ }
231
+ },
232
+ fields: 'user_entered_format(number_format)'
233
+ }
234
+ }
235
+ ])
236
+ end
237
+
238
+ def create_temp_sheet
239
+ batch_update(requests: [{
240
+ add_sheet: {
241
+ properties: {
242
+ title: 'temp-sheet',
243
+ grid_properties: {
244
+ column_count: 1
245
+ }
246
+ }
247
+ }
248
+ }])
249
+ end
250
+
251
+ def delete_all_sheets
252
+ service
253
+ .get_spreadsheet(spreadsheet_id)
254
+ .to_h[:sheets]
255
+ .select { |sheet| sheet[:properties][:title] != 'temp-sheet' }
256
+ .each do |sheet|
257
+ batch_update(requests: [{
258
+ delete_sheet: {
259
+ sheet_id: sheet[:properties][:sheet_id]
260
+ }
261
+ }])
262
+ end
263
+ end
264
+
265
+ def column_from_index(index)
266
+ %w(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)[index - 1]
267
+ end
268
+
269
+ def populate_new_sheets
270
+ threads = []
271
+ data.each do |sheet|
272
+ # threads.push Thread.new {
273
+
274
+ begin
275
+ batch_update(requests: [{
276
+ add_sheet: {
277
+ properties: {
278
+ title: sheet.first,
279
+ grid_properties: {
280
+ column_count: sheet.last.first.count
281
+ }
282
+ }
283
+ }
284
+ }])
285
+
286
+ rescue
287
+ binding.pry if ENV['HACKING']
288
+ puts sheet
289
+ puts "invalid or no data, skipping"
290
+ next
291
+ end
292
+ sheet_default_font(sheet)
293
+
294
+ headers.each_with_index do |header, index|
295
+ format_column sheet, index, index, header[1]
296
+ number_format_column sheet, index, index, header[2] if header[2]
297
+ end
298
+
299
+ value_range_object = {
300
+ major_dimension: 'ROWS',
301
+ values: [headers.map(&:first)]
302
+ }
303
+
304
+ range = sheet.first
305
+
306
+ begin
307
+ retries ||= 0
308
+ service.update_spreadsheet_value(spreadsheet_id, range, value_range_object, value_input_option: 'USER_ENTERED')
309
+ rescue StandardError => e
310
+ puts "Failed to save data, retry #{retries}"
311
+ puts e
312
+ sleep 5 ** (retries + 1) / 10.to_f
313
+ retry if (retries += 1) < 6
314
+ end
315
+
316
+ bold_row(sheet, 0, 0)
317
+
318
+ if sheet.last.first.respond_to?('values')
319
+ value_range_object = {
320
+ major_dimension: 'ROWS',
321
+ values: sheet.last.map(&:values)
322
+ }
323
+ else
324
+ value_range_object = {
325
+ major_dimension: 'ROWS',
326
+ values: sheet.last.map(&:itself)
327
+ }
328
+ end
329
+
330
+ range = "#{sheet.first}!A2:#{column_from_index headers.count}#{sheet.last.count + 1}"
331
+
332
+ begin
333
+ retries ||= 0
334
+
335
+ service.update_spreadsheet_value(spreadsheet_id, range, value_range_object, value_input_option: 'USER_ENTERED')
336
+ rescue StandardError => e
337
+ puts "Failed to save data, retry #{retries}"
338
+ puts e
339
+ sleep 5 ** (retries + 1) / 10.to_f
340
+ retry if (retries += 1) < 6
341
+ end
342
+
343
+ auto_resize_sheet(sheet)
344
+ # }
345
+ end
346
+
347
+ threads.each(&:join)
348
+ end
349
+
350
+ def delete_temp_sheet
351
+ service
352
+ .get_spreadsheet(spreadsheet_id)
353
+ .to_h[:sheets]
354
+ .select { |sheet| sheet[:properties][:title] == 'temp-sheet' }
355
+ .each do |sheet|
356
+ batch_update(requests: [{
357
+ delete_sheet: {
358
+ sheet_id: sheet[:properties][:sheet_id]
359
+ }
360
+ }])
361
+ end
362
+ end
363
+
364
+ def update_google_sheet
365
+ return puts "Invalid Google Sheet. Please make sure it is shared with sdegabriele@bbtv.com" unless create_temp_sheet
366
+ delete_all_sheets
367
+ populate_new_sheets
368
+ delete_temp_sheet
369
+ end
370
+
371
+ def create_sheet
372
+ request_body = Google::Apis::SheetsV4::Spreadsheet.new
373
+ response = service.create_spreadsheet(request_body)
374
+ @spreadsheet_id = response.spreadsheet_id
375
+
376
+ requests = []
377
+ requests.push(
378
+ update_spreadsheet_properties: {
379
+ properties: { title: document_name },
380
+ fields: 'title'
381
+ }
382
+ )
383
+ batch_update(requests: requests)
384
+ end
385
+
386
+ def share_sheet
387
+ GoogleDriveHelper.new.share_document(spreadsheet_id, email_address)
388
+ end
389
+
390
+ def create_google_sheet
391
+ create_sheet
392
+ share_sheet
393
+ create_temp_sheet
394
+ delete_all_sheets
395
+ populate_new_sheets
396
+ delete_temp_sheet
397
+ end
398
+ end
@@ -0,0 +1,3 @@
1
+ def number_format(number)
2
+ number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, '\\1,')
3
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'sd-ruby-libs'
3
+ gem.version = `git describe --tags --abbrev=0`.chomp
4
+ gem.summary = "various tools"
5
+ gem.description = "basic slack and google sheets functionality"
6
+ gem.authors = ["Stephen DeGabriele"]
7
+ gem.email = 'someguy@degabriele.com'
8
+
9
+ gem.files = `git ls-files`.split("\n")
10
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
12
+ gem.require_paths = ['lib']
13
+
14
+ gem.add_runtime_dependency 'google-api-client', '~> 0.13.4', '>= 0.13.4'
15
+ gem.add_runtime_dependency 'googleauth', '~> 0.5.3', '>= 0.5.3'
16
+ gem.add_runtime_dependency 'slack-api', '~> 1.6.0', '>= 1.6.0'
17
+ gem.add_runtime_dependency 'write_xlsx', '~> 0.85.1', '>= 0.85.1'
18
+ gem.add_runtime_dependency 'writeexcel', '~> 1.0.5', '>= 1.0.5'
19
+ gem.add_runtime_dependency 'pry'
20
+ end
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env ruby
2
+ require 'slack'
3
+ require 'kanban'
4
+ require 'yaml'
5
+ require 'redis'
6
+ require 'json'
7
+ require 'pry'
8
+
9
+ # Simple wrapper for the slack ruby interface
10
+ module SlackNotification
11
+ def initialize
12
+ @restarts = 0
13
+ @config = YAML.load_file(ENV['SLACKCONFIG'] || 'slackConfig.yaml')
14
+
15
+ Slack.configure do |config|
16
+ config.token = @config['slack_token']
17
+ end
18
+ end
19
+
20
+ def redis
21
+ @redis ||= Redis.new
22
+ end
23
+
24
+ def worker_backlog
25
+ @worker_backlog ||= Kanban::Backlog.new backend: Redis.new(db: 3), namespace: "#{name}-worker"
26
+ end
27
+
28
+ def dispatch_backlog
29
+ @dispatch_backlog ||= Kanban::Backlog.new backend: Redis.new(db: 3), namespace: "#{name}-dispatch"
30
+ end
31
+
32
+ def client
33
+ @client ||= Slack::Client.new
34
+ end
35
+
36
+ def create_channel
37
+ @config['slack_channels'].each do |channel|
38
+ client.groups_create(name: channel)
39
+ end
40
+ end
41
+
42
+ def invite(who)
43
+ @config['slack_channels'].each do |channel|
44
+ client.groups_invite(channel: channel, user: who)
45
+ end
46
+ end
47
+
48
+ def create_interface(*message)
49
+ create_channel
50
+ invite message.first['user']
51
+ help
52
+ end
53
+
54
+ def name
55
+ @config['slack_name']
56
+ end
57
+
58
+ def help(message)
59
+ send_notification(known_commands.to_s, message['channel'])
60
+ end
61
+
62
+ def parse_command(message)
63
+ unsure = [
64
+ "I heard my name.... instructions unclear. `#{name} help` might be what you need. :dog:",
65
+ ":dog: Sometimes when you say my name I think you are going to give me a treat. `#{name} help` :dog:",
66
+ ":dog: wag :dog: `#{name} help` might be what you want.",
67
+ "woof. Not sure what you mean. Please try \"#{name} help\"",
68
+ ":dog: feeling confused? Me too. Might be a good time for a sandwich! then try \"#{name} help\"",
69
+ "http://puppyloveblog.com/scaled/600x450/taro-the-black-labrador-puppy-and-his-sad-puppy-dog-eyes-451.jpg Try `#{name} help` for assistance.",
70
+ "http://puppyloveblog.com/scaled/600x450/taro-the-black-labrador-puppy-being-cute-519.jpg `#{name} help` to see what i can do.",
71
+ "http://puppyloveblog.com/scaled/600x337/kratos-and-his-rope-what-a-handsome-black-labrador-retriever-puppy-471.jpg `#{name} help` will pull up the list of commands i know"
72
+ ]
73
+ send_notification(unsure.sample, message['channel'])
74
+ end
75
+
76
+ def bot_message?(m)
77
+ m['subtype'] && m['subtype'] == 'bot_message'
78
+ end
79
+
80
+ def magic_phrase?(m)
81
+ return unless m['text'] && m['text'].start_with?("#{name} juice #{name} juice #{name} juice")
82
+ send_notification "It's showtime #{m}", m['channel']
83
+ # need to have auth users before using this
84
+ # create_interface m
85
+ true
86
+ end
87
+
88
+ def configured_channel?(m)
89
+ return false if @config['slack_blacklist_channels'] && @config['slack_blacklist_channels'].include?(m['channel'])
90
+ @config['slack_channels'].include? m['channel'] or @config['any_channel']
91
+ end
92
+
93
+ def message_for_bot?(m)
94
+ m['text'] && m['text'].start_with?(name)
95
+ end
96
+
97
+ def valid_command(command_matrix, m)
98
+ commands = command_matrix.select do |keyword|
99
+ m['text'].start_with? "#{name} #{keyword.first}"
100
+ end
101
+
102
+ [commands.sort_by { |command| command.first.length }.reverse.first]
103
+ end
104
+
105
+ def skip_message?(m)
106
+ return true if bot_message? m
107
+ return true if magic_phrase? m
108
+ return true unless configured_channel? m
109
+ return true unless message_for_bot? m
110
+ end
111
+
112
+ def queue_command(command, message)
113
+ message['command'] = command
114
+ job = { 'task' => JSON.dump(message) }
115
+ worker_backlog.add job
116
+ end
117
+
118
+ def perform_command(matrix, m)
119
+ action = valid_command(matrix, m) - [nil]
120
+ return send_notification("Command not known. Please try help.", m['channel']) unless action
121
+ return send('parse_command', m) if action.count.zero?
122
+ return send_notification("It is not clear what you want. Valid matching actions are: #{action}", m['channel']) if action.count > 1
123
+ queue_command(action.first.last, m)
124
+ end
125
+
126
+ def worker
127
+ loop do
128
+ task_id = worker_backlog.claim(duration: 999999)
129
+ message = JSON.parse(worker_backlog.get(task_id)['task'])
130
+ command = message['command']
131
+ puts "Debug info: command = #{command} message = #{message}"
132
+ send(command, message)
133
+ worker_backlog.complete task_id
134
+ end
135
+ end
136
+
137
+ def real_time(matrix, restarted = false)
138
+ rtm = client.realtime
139
+ message_count = 0
140
+ rtm.on :message do |m|
141
+ puts m if ENV['DEBUGGING']
142
+ message_count += 1
143
+ next if restarted && message_count == 1
144
+ next if skip_message? m
145
+ perform_command matrix, m
146
+ end
147
+ rtm.start
148
+ end
149
+
150
+ def send_binary_file(file, override_filename = nil)
151
+ puts "Sending binary file: #{file}"
152
+ override_filename = file.split('/').last unless override_filename
153
+ `curl -F file=@#{file} -F channels=#{@config['slack_channels'].first} -F token=#{@config['slack_token']} -F filename=#{override_filename} https://slack.com/api/files.upload 2>&1`
154
+ end
155
+
156
+ def queue_notification(message, channel = nil)
157
+ task = {
158
+ message: message,
159
+ channel: channel ? channel : @config['slack_channels'].first
160
+ }
161
+ job = { 'task' => JSON.dump(task) }
162
+ dispatch_backlog.add job
163
+ end
164
+
165
+ def transmission
166
+ loop do
167
+ task_id = dispatch_backlog.claim(duration: 999999)
168
+ job = JSON.parse(dispatch_backlog.get(task_id)['task'])
169
+ next unless job['message']
170
+ puts "Debug info: channel = #{job['channel']} message = #{job['message']}"
171
+ send_notification job['message'], job['channel']
172
+ end
173
+ end
174
+
175
+ def send_notification(message, channel = nil)
176
+ return queue_notification message, channel unless ENV['TRANSMISSION']
177
+ puts "Sending notification: #{message}"
178
+ channel ||= @config['slack_channels'].first
179
+ client.chat_postMessage(channel: channel, text: message, as_user: false, username: @config['slack_name'])
180
+ end
181
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sd-ruby-libs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stephen DeGabriele
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google-api-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.13.4
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.13.4
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 0.13.4
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.13.4
33
+ - !ruby/object:Gem::Dependency
34
+ name: googleauth
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.5.3
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.5.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.5.3
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.5.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: slack-api
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: 1.6.0
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.6.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.6.0
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.6.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: write_xlsx
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 0.85.1
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.85.1
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.85.1
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.85.1
93
+ - !ruby/object:Gem::Dependency
94
+ name: writeexcel
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: 1.0.5
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 1.0.5
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 1.0.5
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.0.5
113
+ - !ruby/object:Gem::Dependency
114
+ name: pry
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :runtime
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ description: basic slack and google sheets functionality
128
+ email: someguy@degabriele.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".rubocop.yml"
134
+ - Gemfile
135
+ - excel_reports.rb
136
+ - google_drive.rb
137
+ - google_sheets.rb
138
+ - number_format.rb
139
+ - sd-ruby-libs.gemspec
140
+ - slack-bot.rb
141
+ homepage:
142
+ licenses: []
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 2.5.2.1
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: various tools
164
+ test_files: []