sd-ruby-libs 0.0.1

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.
@@ -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: []