Top Level Namespace

Defined Under Namespace

Classes: SlackSmartBot

Constant Summary collapse

ADMIN_USERS =

for bg compatibility

MASTER_USERS

Instance Method Summary collapse

Instance Method Details

#general_bot_commands(user, command, dest, files = []) ⇒ Object

add here the general commands you will be using in any channel where The SmartBot is part of. Not necessary to use ! or ^, it will answer directly.



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
# File 'lib/slack/smart-bot/commands/general_bot_commands.rb', line 2

def general_bot_commands(user, command, dest, files = [])
    
  begin
    if config.simulate
      display_name = user.profile.display_name
    else
      if user.profile.display_name.to_s.match?(/\A\s*\z/)
        user.profile.display_name = user.profile.real_name
      end
      display_name = user.profile.display_name
    end
    case command
      # help: ----------------------------------------------
      # help: `bot help`
      # help: `bot help COMMAND`
      # help: `bot rules`
      # help: `bot rules COMMAND`
      # help: `bot help expanded`
      # help: `bot rules expanded`
      # help: `bot what can I do?`
      # help:    it will display this help. For a more detailed help call `bot help expanded` or `bot rules expanded`.
      # help:    if COMMAND supplied just help for that command
      # help:    you can use the option 'expanded' or the alias 'extended'
      # help:    `bot rules` will show only the specific rules for this channel.
      # help:    <https://github.com/MarioRuiz/slack-smart-bot#bot-help|more info>
      # help: command_id: :bot_help
      # help:

      # help: ----------------------------------------------
      # help: `for NUMBER times every NUMBER minutes COMMAND`
      # help: `for NUMBER times every NUMBER seconds COMMAND`
      # help: `NUMBER times every NUMBER minutes COMMAND`
      # help: `NUMBER times every NUMBER seconds COMMAND`
      # help:    It will run the command every NUMBER minutes or seconds for NUMBER times.
      # help:    max 24 times. min every 10 seconds. max every 60 minutes.
      # help:    Call `quit loop LOOP_ID` to stop the loop.
      # help:       aliases for minutes: m, minute, minutes
      # help:       aliases for seconds: s, sc, second, seconds
      # help:  Examples:
      # help:       _for 5 times every 1 minute ^ruby puts Time.now_
      # help:       _10 times every 30s !ruby puts Time.now_
      # help:       _24 times every 60m !get sales today_
      # help:    <https://github.com/MarioRuiz/slack-smart-bot#loops|more info>
      # help: command_id: :create_loop
      # help:

      # help: ----------------------------------------------
      # help: `quit loop LOOP_ID`
      # help:    It will stop the loop with the id LOOP_ID.
      # help:    Only the user who created the loop or an admin can stop it.
      # help:       aliases for loop: iterator, iteration
      # help:       aliases for quit: stop, exit, kill
      # help:  Examples:
      # help:       _quit loop 1_
      # help:       _stop iterator 12_
      # help:    <https://github.com/MarioRuiz/slack-smart-bot#loops|more info>
      # help: command_id: :quit_loop

      # help: ----------------------------------------------
      # help: `Hi Bot`
      # help: `Hi Smart`
      # help: `Hello Bot` `Hola Bot` `Hallo Bot` `What's up Bot` `Hey Bot` `Hæ Bot`
      # help: `Hello THE_NAME_OF_THE_BOT`
      # help:    Bot starts listening to you if you are on a Bot channel
      # help:    After that if you want to avoid a single message to be treated by the smart bot, start the message by -
      # help:    Also apart of Hello you can use _Hallo, Hi, Hola, What's up, Hey, Hæ_
      # help:    <https://github.com/MarioRuiz/slack-smart-bot#how-to-access-the-smart-bot|more info>
      # help: command_id: :hi_bot
      # help:
      when /\A\s*(Hello|Hallo|Hi|Hola|What's\sup|Hey|Hæ)\s+(#{@salutations.join("|")})\s*$/i
          hi_bot(user, dest, user.name, display_name)

      # help: ----------------------------------------------
      # help: `Bye Bot`
      # help: `Bye Smart`
      # help: `Bye NAME_OF_THE_BOT`
      # help:    Bot stops listening to you if you are on a Bot channel
      # help:    Also apart of Bye you can use _Bæ, Good Bye, Adiós, Ciao, Bless, Bless Bless, Adeu_
      # help:    <https://github.com/MarioRuiz/slack-smart-bot#how-to-access-the-smart-bot|more info>
      # help: command_id: :bye_bot
      # help:
      when /\A\s*(Bye|Bæ|Good\s+Bye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s+(#{@salutations.join("|")})\s*$/i
          bye_bot(dest, user.name, display_name)

        # help: ----------------------------------------------
        # help: `add announcement MESSAGE`
        # help: `add red announcement MESSAGE`
        # help: `add green announcement MESSAGE`
        # help: `add yellow announcement MESSAGE`
        # help: `add white announcement MESSAGE`
        # help: `add EMOJI announcement MESSAGE`
        # help:     It will store the message on the announcement list labeled with the color or emoji specified, white by default.
        # help:        aliases for announcement: statement, declaration, message
        # help:  Examples:
        # help:     _add green announcement :heavy_check_mark: All customer services are up and running_
        # help:     _add red declaration Customers db is down :x:_
        # help:     _add yellow statement Don't access the linux server without VPN_
        # help:     _add message `*Party* will start at *20:00* :tada:`_
        # help:     _add :heavy_exclamation_mark: message Pay attention all DB are on maintenance until 20:00 GMT_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#announcements|more info>
        # help: command_id: :add_announcement
        # help: 
      when /\A\s*(add|create)\s+(red\s+|green\s+|white\s+|yellow\s+)?(announcement|statement|declaration|message)\s+(.+)\s*\z/i,
        /\A\s*(add|create)\s+(:[\w\-]+:)\s+(announcement|statement|declaration|message)\s+(.+)\s*\z/i
        type = $2.to_s.downcase.strip
        type = 'white' if type == ''
        message = $4
        add_announcement(user, type, message)
        

        # help: ----------------------------------------------
        # help: `delete announcement ID`
        # help:     It will delete the message on the announcement list.
        # help:        aliases for announcement: statement, declaration, message
        # help:  Examples:
        # help:     _delete announcement 24_
        # help:     _delete message 645_
        # help:     _delete statement 77_
        # help:     _delete declaration 334_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#announcements|more info>
        # help: command_id: :delete_announcement
        # help: 
      when /\A\s*(delete|remove)\s+(announcement|statement|declaration|message)\s+(\d+)\s*\z/i
        message_id = $3
        delete_announcement(user, message_id)

        # help: ----------------------------------------------
        # help: `see announcements`
        # help: `see red announcements`
        # help: `see green announcements`
        # help: `see yellow announcements`
        # help: `see white announcements`
        # help: `see EMOJI announcements`
        # helpmaster: `see announcements #CHANNEL`
        # helpmaster: `see all announcements`
        # help:     It will display the announcements for the channel.
        # help:        aliases for announcements: statements, declarations, messages
        # helpmaster:        In case #CHANNEL it will display the announcements for that channel. Only master admins can use it from a DM with the Smartbot.
        # helpmaster:        In case 'all' it will display all the announcements for all channels. Only master admins can use it from a DM with the Smartbot.
        # help:  Examples:
        # help:     _see announcements_
        # help:     _see white messages_
        # help:     _see red statements_
        # help:     _see yellow declarations_
        # help:     _see messages_
        # help:     _see :heavy_exclamation_mark: messages_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#announcements|more info>
        # help: command_id: :see_announcements
        # help: 
      when /\A\s*see\s+(red\s+|green\s+|white\s+|yellow\s+|:[\w\-]+:\s+)?(announcements|statements|declarations|messages)()\s*\z/i,
        /\A\s*see\s+(all\s+)?(announcements|statements|declarations|messages)()\s*\z/i,
        /\A\s*see\s+(red\s+|green\s+|white\s+|yellow\s+|:[\w\-]+:\s+)?(announcements|statements|declarations|messages)\s+#([\w\-]+)\s*\z/i,
        /\A\s*see\s+(red\s+|green\s+|white\s+|yellow\s+|:[\w\-]+:\s+)?(announcements|statements|declarations|messages)\s+<#(\w+)\|.*>\s*\z/i

        type = $1.to_s.downcase.strip
        channel = $3.to_s

        see_announcements(user, type, channel)


        # help: ----------------------------------------------
        # help: `share messages /REGEXP/ on #CHANNEL`
        # help: `share messages "TEXT" on #CHANNEL`
        # xhelp: `share messages :EMOJI: on #CHANNEL`
        # help:     It will automatically share new messages published that meet the specified criteria.
        # xhelp:     In case :EMOJI: it will share the messages with the indicated reaction.
        # help:     SmartBot user and user adding the share need to be members on both channels.
        # help:     The Regexp will automatically add the parameters /im
        # help:     Only available on public channels.
        # help:  Examples:
        # help:     _share messages /(last\s+|previous\s+)sales\s+results\s+/ on #sales_
        # help:     _share messages "share post" on #announcements_
        # xhelp:     _share messages :tada: on #announcements_
        # xhelp:     _share messages :moneybag: from #sales_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#share-messages|more info>
        # help: command_id: :share_messages
        # help: 
      when /\A\s*share\s+messages\s+(\/.+\/|".+"|'.+')\s+on\s+<#\w+\|(.+)>\s*\z/i,
        /\A\s*share\s+messages\s+(\/.+\/|".+"|'.+')\s+on\s+<#(\w+)\|>\s*\z/,
        /\A\s*share\s+messages\s+(\/.+\/|".+"|'.+')\s+on\s+(.+)\s*\z/i
        condition = $1
        channel = $2
        channel.gsub!('#','') # for the case the channel name is in plain text including #
        channel = @channels_name[channel] if @channels_name.key?(channel)
        channel_from = @channels_name[dest]
        channel_to = channel
        share_messages(user, channel_from, channel_to, condition)

        # help: ----------------------------------------------
        # help: `see shares`
        # help:     It will display the active shares from this channel.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#share-messages|more info>
        # help: command_id: :see_shares
        # help: 
      when /\A\s*see\s+shares\s*\z/i
        see_shares()

        # help: ----------------------------------------------
        # help: `delete share ID`
        # help:     It will delete the share id specified.
        # help:  Examples:
        # help:     _delete share 24_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#share-messages|more info>
        # help: command_id: :delete_share
        # help: 
      when /\A\s*(delete|remove)\s+share\s+(\d+)\s*\z/i
        share_id = $2
        delete_share(user, share_id)

        # help: ----------------------------------------------
        # help: `see statuses`
        # help: `see statuses #CHANNEL`
        # help: `see status EMOJI`
        # help: `see status EMOJI #CHANNEL`
        # help: `see status EMOJI1 EMOJI99`
        # help: `who is on vacation?`
        # help: `who is on EMOJI`
        # help: `who is on EMOJI #CHANNEL`
        # help: `who is on EMOJI1 EMOJI99`
        # help: `who is not on vacation?`
        # help: `who is not on EMOJI`
        # help: `who is available?`
        # help:     It will display the current statuses of the members of the channel where you are calling the command or on the channel you supply.
        # help:     In case of `who is available?` will show members of the channel that are on line and not on a meeting or vacation or sick.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#see-statuses|more info>
        # help: command_id: :see_statuses
        # help: 
      when /\A\s*(see|get)\s+(statuses)()\s*\z/i,
        /\A\s*(see\s+status|get\s+status|who\s+is\s+on|who\s+are\s+on|who\s+is\s+not\s+on|who\s+are\s+not\s+on)\s+(:[\w\-\:\s]+:)\s*\??()\s*\z/i,
        /\A\s*(who\s+is\s+on|who\s+are\s+on|who\s+is\s+not\s+on|who\s+are\s+not\s+on)\s+(vacation|holiday)\s*\??()\s*\z/i,
        /\A\s*(who\s+is|who\s+are)\s+(available|active)\s*\??()\s*\z/i,
        /\A\s*(see|get)\s+(statuses)\s+#([\w\-]+)\s*\z/i,
        /\A\s*(see\s+status|get\s+status|who\s+is\s+on|who\s+are\s+on|who\s+is\s+not\s+on|who\s+are\s+not\s+on)\s+(:[\w\-\:\s]+:)\s*\??\s+#([\w\-]+)\s*\z/i,
        /\A\s*(who\s+is|who\s+are)\s+(available|active)\s*\??\s+#([\w\-]+)\s*\z/i,
        /\A\s*(who\s+is|who\s+are)\s+(available|active)\s*\??\s+<#(\w+)\|.*>\s*\z/i,
        /\A\s*(who\s+is\s+on|who\s+are\s+on|who\s+is\s+not\s+on|who\s+are\s+not\s+on)\s+(vacation|holiday)\s*\??\s+#([\w\-]+)\s*\z/i,
        /\A\s*(see|get)\s+(statuses)\s+<#(\w+)\|.*>\s*\z/i,
        /\A\s*(see\s+status|get\s+status|who\s+is\s+on|who\s+is\s+not\s+on|who\s+are\s+on|who\s+are\s+not\s+on)\s+(:[\w\-\:\s]+:)\s*\??\s+<#(\w+)\|.*>\s*\z/i,
        /\A\s*(who\s+is\s+on|who\s+is\s+not\s+on|who\s+are\s+on|who\s+are\s+not\s+on)\s+(vacation|holiday)\s*\??\s+<#(\w+)\|.*>\s*\z/i

        not_on = $1.match?(/who\s+(is|are)\s+not\s+on/i)
        type = $2.downcase
        channel = $3.to_s
        if type == 'statuses'
          types = []
        elsif type =='vacation' or type == 'holiday'
          types = [':palm_tree:']
        elsif type == 'available' or type == 'active'
          types = ['available']
        else
          type.gsub!(' ', '')
          type.gsub!('::',': :')
          types = type.split(' ')
        end
        see_statuses(user, channel, types, dest, not_on)


        # help: ----------------------------------------------
        # help: `see favorite commands`
        # help: `see my favorite commands`
        # help: `favorite commands`
        # help: `my favorite commands`
        # help:     It will display the favorite commands.
        # help:     aliases for favorite: favourite, most used, fav
        # helpmaster:    You need to set stats to true to generate the stats when running the bot instance and get this info.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#see-favorite-commands|more info>
        # help: command_id: :see_favorite_commands
        # help: 
      when /\A\s*(see\s+)?(my\s+)?(fav|favorite|favourite|most\s+used)\s+commands\s*\z/i
        only_mine = $2.to_s!=''
        see_favorite_commands(user, only_mine)

        # helpadmin: ----------------------------------------------
        # helpadmin: `add admin @user`
        # helpadmin:     It will add @user as an admin of the channel.
        # helpadmin:     Only creator of the channel, admins and master admins can use this command.
        # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
        # helpadmin: command_id: :add_admin
        # helpadmin: 
      when /\A\s*add\s+admin\s+<@(\w+)>\s*\z/i
        admin_user = $1
        add_admin(user, admin_user)

        # help: ----------------------------------------------
        # help: `see admins`
        # help: `show admins`
        # help: `who are admins?`
        # help:     It will show who are the admins of the channel.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
        # help: command_id: :see_admins
        # help: 
      when /\A\s*(see|show)\s+admins\s*\z/i, /\A\s*who\s+are\s+(the\s+)?admins\??\s*\z/i
        see_admins()

        # helpadmin: ----------------------------------------------
        # helpadmin: `remove admin @user`
        # helpadmin:     It will remove the admin privileges for @user on the channel.
        # helpadmin:     Only creator of the channel, admins and master admins can use this command.
        # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
        # helpadmin: command_id: :remove_admin
        # helpadmin: 
      when /\A\s*(remove|delete)\s+admin\s+<@(\w+)>\s*\z/i
        admin_user = $2
        remove_admin(user, admin_user)

        # helpadmin: ----------------------------------------------
        # helpadmin: `see command ids`
        # helpadmin:     It will display all available command ids.
        # helpadmin:     The command id can be used on `bot stats command COMMAND_ID`, `allow access COMMAND_ID` and `deny access COMMAND_ID`
        # helpadmin:     Only creator of the channel, admins and master admins can use this command.
        # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
        # helpadmin: command_id: :see_command_ids
        # helpadmin: 
      when /\A\s*(see|display|get)\s+command(\s+|_)ids?\s*\z/i
        see_command_ids()

        # helpadmin: ----------------------------------------------
        # helpadmin: `allow access COMMAND_ID`
        # helpadmin: `allow access COMMAND_ID @user1 @user99`
        # helpadmin:     It will allow the specified command to be used on the channel.
        # helpadmin:     If @user specified, only those users will have access to the command.
        # helpadmin:     Only admins of the channel can use this command
        # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#control-who-has-access-to-a-command|more info>
        # helpadmin: command_id: :allow_access
        # helpadmin: 
      when /\A\s*(allow|give)\s+access\s+(\w+)\s+(.+)\s*\z/i, /\A\s*(allow|give)\s+access\s+(\w+)()\s*\z/i
        command_id = $2.downcase
        opt = $3.to_s.split(' ')
        allow_access(user, command_id, opt)

        # helpadmin: ----------------------------------------------
        # helpadmin: `deny access COMMAND_ID`
        # helpadmin:     It won't allow the specified command to be used on the channel.
        # helpadmin:     Only admins of the channel can use this command
        # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#control-who-has-access-to-a-command|more info>
        # helpadmin: command_id: :deny_access
        # helpadmin: 
      when /\A\s*deny\s+access(\s+rights)?\s+(\w+)\s*\z/i
        command_id = $2.downcase
        deny_access(user, command_id)


        # help: ----------------------------------------------
        # help: `see access COMMAND_ID`
        # help:     It will show the access rights for the specified command.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#control-who-has-access-to-a-command|more info>
        # help: command_id: :see_access
        # help: 
      when /\A\s*(see|show)\s+access(\s+rights)?\s+(.+)\s*\z/i
        command_id = $3.downcase
        see_access(command_id)

        # help: ----------------------------------------------
        # help: `poster MESSAGE`
        # help: `poster :EMOTICON_TEXT: MESSAGE`
        # help: `poster :EMOTICON_TEXT: :EMOTICON_BACKGROUND: MESSAGE`
        # help: `poster MINUTESm MESSAGE`
        # help:     It will create a poster with the message supplied. By default will be autodeleted 1 minute later.
        # help:     If you want the poster to be permanent then use the command `pposter`
        # help:     If minutes supplied then it will be deleted after the minutes specified. Maximum value 60.
        # help:     To see the messages on a mobile phone put the phone on landscape mode
        # help:     Max 15 characters. If the message is longer than that won't be treat it.
        # help:     Only letters from a to z, 0 to 9 and the chars: ? ! - + =
        # help:     To be displayed correctly use words with no more than 6 characters
        # help:     Examples:
        # help:            _poster nice work!_
        # help:            _poster :heart: nice work!_
        # help:            _poster :mac-spinning-wheel: :look: love!_
        # help:            _poster 25m :heart: woah!_
        # help: command_id: :poster
        # help: 
      when /\A()poster\s+(\d+m\s+)?(:[^:]+:)\s+(:[^:]+:)(.+)\s*\z/i, /\A()poster\s+(\d+m\s+)?(:.+:)\s+()(.+)\s*\z/i, /\A()poster\s+(\d+m\s+)?()()(.+)\s*\z/i,
        /\A(p)poster\s+()(:[^:]+:)\s+(:[^:]+:)(.+)\s*\z/i, /\A(p)poster\s+()(:.+:)\s+()(.+)\s*\z/i, /\A(p)poster\s+()()()(.+)\s*\z/i
        permanent = $1.to_s != ''
        minutes = $2.to_s
        emoticon_text = $3
        emoticon_bg = $4
        text = $5
        minutes = minutes.scan(/(\d+)/).join
        
        if minutes == ''
          minutes = 1
        elsif minutes.to_i > 60
          minutes = 60
        end
        
        save_stats :poster
        if text.to_s.gsub(/\s+/, '').length > 15
          respond "Too long. Max 15 chars", :on_thread
        else
          poster(permanent, emoticon_text, emoticon_bg, text, minutes)
        end

        # help: ----------------------------------------------
        # help: `add team TEAM_NAME members #TEAM_CHANNEL CHANNEL_TYPE #CHANNEL1 #CHANNEL99 : INFO`
        # help: `add team TEAM_NAME MEMBER_TYPE @USER1 @USER99 CHANNEL_TYPE #CHANNEL1 #CHANNEL99 : INFO`
        # help: `add team TEAM_NAME MEMBER_TYPE1 @USER1 @USER99 MEMBER_TYPE99 @USER1 @USER99 CHANNEL_TYPE1 #CHANNEL1 #CHANNEL99 CHANNEL_TYPE99 #CHANNEL1 #CHANNEL99 : INFO`
        # help:     It will add a team with the info supplied.
        # help:     TEAM_NAME, TYPE: one word, a-z, A-Z, 0-9, - and _
        # help:     In case it is supplied a channel with type 'members' the members of that channel would be considered members of the team. The SmartBot needs to be a member of the channel.
        # help:  Examples:
        # help:     _add team sales members #sales support #sales-support public #sales-ff : Contact us if you need anything related to Sales. You can also send us an email at [email protected]_
        # help:     _add team Sales manager @ann qa @peter @berglind dev @john @sam @marta members #sales support #sales-support public #sales-ff : Contact us if you need anything related to Sales. You can also send us an email at [email protected]_
        # help:     _add team devweb qa @jim dev @johnja @cooke @luisa members #devweb support #devweb-support : We take care of the website_
        # help:     _add team sandex manager @sarah members #sandex : We take care of the sand_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :add_team
        # help: 
      when /\A\s*add\s+team\s+([\w\-]+)\s+([^:]+)\s*:\s+(.+)\s*\z/im, /\A\s*add\s+([\w\-]+)\s+team\s+([^:]+)\s*:\s+(.+)\s*\z/im
        name = $1.downcase
        options = $2
        info = Thread.current[:command_orig].to_s.gsub("\u00A0", " ").scan(/^[^:]+:\s*(.+)\s*$/im).join
        add_team(user, name, options, info)

        # help: ----------------------------------------------
        # help: `add TYPE to TEAM_NAME team : MESSAGE`
        # help: `add private TYPE to TEAM_NAME team : MESSAGE`
        # help: `add personal TYPE to TEAM_NAME team : MESSAGE`
        # help: `add TYPE to TEAM_NAME team TOPIC : MESSAGE`
        # help: `add private TYPE to TEAM_NAME team TOPIC : MESSAGE`
        # help: `add personal TYPE to TEAM_NAME team TOPIC : MESSAGE`
        # help:     It will add a memo to the team. The memos will be displayed with the team info.
        # help:     Only team members can add a memo.
        # help:     TYPE: memo, note, issue, task, feature, bug, jira, github
        # help:     TOPIC: one word, a-z, A-Z, 0-9, - and _
        # help:     If private then the memo will be only displayed to team members on a DM or the members channel.
        # help:     If personal then the memo will be only displayed to the creator on a DM.
        # help:     In case jira type supplied:
        # help:       The message should be an JQL URL, JQL string or an issue URL.
        # help:       To be able to use it you need to specify on the SmartBot settings the credentials.
        # help:       In case no TOPIC is supplied then it will create automatically the topics from the labels specified on every JIRA issue
        # help:     In case github type supplied:
        # help:       The message should be a github URL. You can filter by state (open/closed/all) and labels
        # help:       To be able to use it you need to specify on the SmartBot settings the github token.
        # help:       In case no TOPIC is supplied then it will create automatically the topics from the labels specified on every Github issue
        # help:  Examples:
        # help:     _add memo to sales team : Add tests for Michigan feature_
        # help:     _add private note to sales team : Bills will need to be deployed before Friday_
        # help:     _add memo to dev team web : Check last version_
        # help:     _add private bug to dev team SRE : Logs should not be accessible from outside VPN_
        # help:     _add memo sales team : Add tests for Michigan feature_
        # help:     _add memo team sales: Add tests for Michigan feature_
        # help:     _add personal memo team sales: Check my vacations_
        # help:     _add jira to sales team : labels = SalesT AND status != Done_
        # help:     _add github to sales team : PeterBale/SalesBoom/issues?state=open&labels=bug_
        # help:     _add github to sales team dev: PeterBale/DevProject/issues/71_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :add_memo_team
        # help: 
      when /\A\s*add\s+(private\s+|personal\s+)?(memo|note|issue|task|feature|bug|jira|github)\s+(to\s+)?team\s+([\w\-]+)\s*([^:]+)?\s*:\s+(.+)\s*\z/im,
           /\A\s*add\s+(private\s+|personal\s+)?(memo|note|issue|task|feature|bug|jira|github)\s+(to\s+)?([\w\-]+)\s+team\s*([^:]+)?\s*:\s+(.+)\s*\z/im 
        privacy = $1.to_s.strip.downcase
        type = $2.downcase
        team_name = $4.downcase
        topic = $5.to_s.strip
        message = Thread.current[:command_orig].to_s.gsub("\u00A0", " ").scan(/^[^:]+:\s*(.+)\s*$/im).join
        add_memo_team(user, privacy, team_name, topic, type, message)

        # help: ----------------------------------------------
        # help: `delete memo ID from TEAM_NAME team`
        # help:     It will delete the supplied memo ID on the team specified.
        # help:     aliases for memo: note, issue, task, feature, bug, jira, github
        # help:     You have to be a member of the team, the creator or a Master admin to be able to delete a memo.
        # help:  Examples:
        # help:     _delete memo 32 from sales team_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :delete_memo_team
        # help: 
      when /\A\s*(delete|remove)\s+(memo|note|issue|task|feature|bug|jira|github)\s+(\d+)\s+(from|on)\s+team\s+([\w\-]+)\s*\z/i, 
        /\A\s*(delete|remove)\s+(memo|note|issue|task|feature|bug|jira|github)\s+(\d+)\s+(from|on)\s+([\w\-]+)\s+team\s*\z/i
        memo_id = $3
        team_name = $5.downcase
        delete_memo_team(user, team_name, memo_id)

        # help: ----------------------------------------------
        # help: `set memo ID on TEAM_NAME team STATUS`
        # help: `set STATUS on memo ID TEAM_NAME team`
        # help:     It will assign to the ID specified the emoticon status indicated.
        # help:     aliases for memo: note, issue, task, feature, bug
        # help:     This command will be only for memo, note, issue, task, feature, bug. Not for jira or github.
        # help:     You have to be a member of the team, the creator or a Master admin to be able to set a status.
        # help:  Examples:
        # help:     _set memo 32 on sales team :runner:_
        # help:     _set bug 7 on team sales :heavy_check_mark:_
        # help:     _set :runner: on memo 6 sales team_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :set_memo_status
        # help: 
      when /\A\s*(set)\s+(memo|note|issue|task|feature|bug)\s+(\d+)\s+on\s+team\s+([\w\-]+)\s+(:[\w\-]+:)\s*\z/i, 
        /\A\s*(set)\s+(memo|note|issue|task|feature|bug)\s+(\d+)\s+on\s+([\w\-]+)\s+team\s+(:[\w\-]+:)\s*\z/i
        memo_id = $3
        team_name = $4.downcase
        status = $5
        set_memo_status(user, team_name, memo_id, status)

      when /\A\s*(set)\s+(:[\w\-]+:)\s+on\s+(memo|note|issue|task|feature|bug)\s+(\d+)\s+team\s+([\w\-]+)\s*\z/i,
        /\A\s*(set)\s+(:[\w\-]+:)\s+on\s+(memo|note|issue|task|feature|bug)\s+(\d+)\s+([\w\-]+)\s+team\s*\z/i 
        memo_id = $4
        team_name = $5.downcase
        status = $2
        set_memo_status(user, team_name, memo_id, status)

        # help: ----------------------------------------------
        # help: `see teams`
        # help: `see team TEAM_NAME`
        # help: `team TEAM_NAME`
        # help: `TEAM_NAME team`
        # help: `which team @USER`
        # help: `which team #CHANNEL`
        # help: `which team TEXT_TO_SEARCH_ON_INFO`
        # help: `which team does @USER belongs to?`
        # help:     It will display all teams or the team specified.
        # help:     In case a specific team it will show also the availability of the members.
        # help:  Examples:
        # help:     _see teams_
        # help:     _see team Sales_
        # help:     _Dev team_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :see_teams
        # help: 
      when /\A\s*see\s+teams?\s*([\w\-]+)?\s*\z/i, /\A\s*team\s+([\w\-]+)\s*\z/i, /\A\s*([\w\-]+)\s+team\s*\z/i, /\A\s*see\s+all\s+teams\s*()\z/i
        name = $1.to_s.downcase
        see_teams(user, name)
      when /\A\s*(which|search)\s+teams?\s+(is\s+)?(.+)\??\s*\z/i, /\A\s*which\s+team\s+does\s+()()(.+)\s+belongs\s+to\??\s*\z/i
        search = $3.to_s.downcase
        see_teams(user, '', search)

        # help: ----------------------------------------------
        # help: `update team TEAM_NAME NEW_TEAM_NAME`
        # help: `update team TEAM_NAME : NEW_INFO`
        # help: `update team TEAM_NAME add MEMBER_TYPE @USER`
        # help: `update team TEAM_NAME add CHANNEL_TYPE #CHANNEL`
        # help: `update team TEAM_NAME delete MEMBER_TYPE @USER`
        # help: `update team TEAM_NAME delete CHANNEL_TYPE #CHANNEL`
        # help: `update team TEAM_NAME delete @USER`
        # help: `update team TEAM_NAME delete #CHANNEL`
        # help:     It will update a team with the info supplied.
        # help:     You have to be a member of the team, the creator or a Master admin to be able to update a team.
        # help:  Examples:
        # help:     _update team sales salesff_
        # help:     _update team salesff : Support for customers_        
        # help:     _update sales team delete @sarah @peter_
        # help:     _update team sales delete public #sales_
        # help:     _update team sales delete #sales_support_
        # help:     _update sales team add public #salesff_
        # help:     _update sales team add qa @john @ben @ana_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :update_team
        # help: 
      when /\A\s*update\s+team\s+([\w\-]+)\s+([\w\-]+)\s*\z/i, /\A\s*update\s+([\w\-]+)\s+team\s+([\w\-]+)\s*\z/i
        name = $1.downcase
        new_name = $2.downcase
        update_team(user, name, new_name: new_name)
      when /\A\s*update\s+team\s+([\w\-]+)\s*:\s+(.+)\s*\z/im, /\A\s*update\s+([\w\-]+)\s+team\s*:\s+(.+)\s*\z/im
        name = $1.downcase
        new_info = Thread.current[:command_orig].to_s.gsub("\u00A0", " ").scan(/^[^:]+:\s*(.+)\s*$/im).join
        update_team(user, name, new_info: new_info)
      when /\A\s*update\s+team\s+([\w\-]+)\s+(delete|remove)\s+(.+)\s*\z/i, /\A\s*update\s+([\w\-]+)\s+team\s+(delete|remove)\s+(.+)\s*\z/i
        name = $1.downcase
        delete_opts = $3
        update_team(user, name, delete_opts: delete_opts)
      when /\A\s*update\s+team\s+([\w\-]+)\s+add\s+(.+)\s*\z/i, /\A\s*update\s+([\w\-]+)\s+team\s+add\s+(.+)\s*\z/i
        name = $1.downcase
        add_opts = $2
        update_team(user, name, add_opts: add_opts)

        # help: ----------------------------------------------
        # help: `ping team TEAM_NAME MEMBER_TYPE MESSAGE`
        # help: `contact team TEAM_NAME MEMBER_TYPE MESSAGE`
        # help:     ping: It will send the MESSAGE naming all available members of the MEMBER_TYPE supplied.
        # help:     contact: It will send the MESSAGE naming all members of the MEMBER_TYPE supplied.
        # help:     In case MEMBER_TYPE is 'all' it will name 10 random members of the team
        # help:  Examples:
        # help:     _ping team sales development How is the status on the last feature_
        # help:     _contact team sales qa Please finish testing of dev02 feature before noon_
        # help:     _contact team qa all Check the test failures please_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :ping_team
        # help: command_id: :contact_team
        # help: 
      when /\A\s*(contact|ping)\s+team\s+([\w\-]+)\s+([\w\-]+)\s+(.+)\s*\z/im, /\A\s*(contact|ping)\s+([\w\-]+)\s+team\s+([\w\-]+)\s+(.+)\s*\z/im
        type = $1.downcase.to_sym
        name = $2.downcase
        member_type = $3.downcase
        message = Thread.current[:command_orig].to_s.gsub("\u00A0", " ").scan(/\A\s*[\w]+\s+\w+\s+team\s+[\w\-]+\s+(.+)\s*\z/im).join
        if message == ''
          message = Thread.current[:command_orig].to_s.gsub("\u00A0", " ").scan(/\A\s*[\w]+\s+team\s+\w+\s+[\w\-]+\s+(.+)\s*\z/im).join
        end
        ping_team(user, type, name, member_type, message)

        # help: ----------------------------------------------
        # help: `delete team TEAM_NAME`
        # help:     It will delete the supplied team.
        # help:     You have to be a member of the team, the creator or a Master admin to be able to delete a team.
        # help:  Examples:
        # help:     _delete team sales_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :delete_team
        # help: 
      when /\A\s*(delete|remove)\s+team\s+([\w\-]+)\s*\z/i, /\A\s*(delete|remove)\s+([\w\-]+)\s+team\s*\z/i
        name = $2.downcase
        delete_team(user, name)

        # help: ----------------------------------------------
        # help: `see MEMO_TYPE from TEAM_NAME team`
        # help: `see MEMO_TYPE from TEAM_NAME team TOPIC`
        # help: `see all memos from TEAM_NAME team`
        # help: `see all memos from TEAM_NAME team TOPIC`
        # help:     It will show the memos of the team.
        # help:     If TOPIC is supplied it will show the memos of the topic.
        # help:     MEMO_TYPE: memos, notes, issues, tasks, features, bugs, jira, github. In case of 'all memos' will display all of any type.
        # help:  Examples:
        # help:     _see memos from sales team_
        # help:     _see bugs from sales team_
        # help:     _see all memos from sales team webdev_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#teams|more info>
        # help: command_id: :see_memos_team
        # help:
      when /\A\s*see\s+(memo|note|issue|task|feature|bug|jira|github|all\s+memo)s?\s+(from\s+)?([\w\-]+)\s+team(.*)\s*\z/i,
        /\A\s*see\s+(memo|note|issue|task|feature|bug|jira|github|all\s+memo)s?\s+(from\s+)?team\s+([\w\-]+)(.*)\s*\z/i
        type = $1.downcase.to_sym
        name = $3.downcase
        topic = $4.strip
        see_memos_team(user, type: type, name: name, topic: topic)

        # help: ----------------------------------------------
        # help: `add vacation from YYYY/MM/DD to YYYY/MM/DD`
        # help: `add vacation YYYY/MM/DD`
        # help: `add sick from YYYY/MM/DD to YYYY/MM/DD`
        # help: `add sick YYYY/MM/DD`
        # help: `add sick child YYYY/MM/DD`
        # help: `I'm sick today`
        # help: `I'm on vacation today`
        # help:     It will add the supplied period to your plan.
        # help:     Instead of YYYY/MM/DD you can use 'today' or 'tomorrow' or 'next week'
        # help:     To see your plan call `see my time off`
        # help:     If you want to see the vacation plan for the team `see team NAME`
        # help:     Also you can see the vacation plan for the team for a specific period: `vacations team NAME YYYY/MM/DD`
        # help:     The SmartBot will automatically set the users status to :palm_tree:, :baby: or :face_with_thermometer: and the expiration date.
        # help:  Examples:
        # help:     _add vacation from 2022/10/01 to 2022/10/22_
        # help:     _add sick 2022/08/22_
        # help:     _add vacation tomorrow_
        # help:     _I'll be on vacation next week_
        # help:     _add sick baby today_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#time-off-management|more info>
        # help: command_id: :add_vacation
        # help: 
      when /\A\s*(add)\s+(sick|vacation|sick\s+baby|sick\s+child)\s+from\s+(\d\d\d\d\/\d\d\/\d\d)\s+to\s+(\d\d\d\d\/\d\d\/\d\d)\s*\z/i,
        /\A\s*(add)\s+(sick|vacation|sick\s+baby|sick\s+child)\s+from\s+(\d\d\d\d-\d\d-\d\d)\s+to\s+(\d\d\d\d-\d\d-\d\d)\s*\z/i,
        /\A\s*(add)\s+(sick|vacation|sick\s+baby|sick\s+child)\s+(\d\d\d\d-\d\d-\d\d)()\s*\z/i,
        /\A\s*(add)\s+(sick|vacation|sick\s+baby|sick\s+child)\s+(\d\d\d\d\/\d\d\/\d\d)()\s*\z/i,
        /\A\s*(add)\s+(sick|vacation|sick\s+baby|sick\s+child)\s+(today|tomorrow|next\sweek)()\s*\z/i,
        /\A\s*(I'm|I\s+am|I'll\s+be|I\s+will\s+be)\s+(sick|on\s+vacation)\s+(today|tomorrow|next\sweek)()\s*\z/i
        type = $2
        from = $3.downcase
        to = $4
        type = 'vacation' if type.match?(/vacation/)
        add_vacation(user, type, from, to)

        # help: ----------------------------------------------
        # help: `remove vacation ID`
        # help: `remove vacation period ID`
        # help: `remove sick period ID`
        # help: `remove time off period ID`
        # help: `delete vacation ID`
        # help:     It will remove the specified period from your vacations/sick periods.
        # help:  Examples:
        # help:     _remove vacation 20_
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#time-off-management|more info>
        # help: command_id: :remove_vacation
        # help: 
      when /\A\s*(delete|remove)\s+(vacation|sick|time\s+off)(\s+period)?\s+(\d+)\s*\z/i
        vacation_id = $4
        remove_vacation(user, vacation_id)

        # help: ----------------------------------------------
        # help: `see my vacations`
        # help: `see my time off`
        # help: `see vacations @USER`
        # help: `see my vacations YEAR`
        # help:     It will display current and past time off.
        # help:     If you call this command on a DM, it will show your vacations for the year on a calendar.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#time-off-management|more info>
        # help: command_id: :see_vacations
        # help: 
      when /\A\s*see\s+my\s+vacations\s*()\s*(\d{4})?\s*\z/i,
        /\A\s*see\s+my\s+time\s+off\s*()\s*(\d{4})?\s*\z/i,
        /\A\s*see\s+time\s+off\s+<@(\w+)>\s*\s*(\d{4})?\s*\z/i,
        /\A\s*see\s+vacations\s+<@(\w+)>\s*(\d{4})?\s*\z/i
        from_user = $1
        year = $2
        see_vacations(user, dest, from_user: from_user, year: year)

        # help: ----------------------------------------------
        # help: `vacations team NAME`
        # help: `time off team NAME`
        # help: `vacations team NAME YYYY/MM/DD`
        # help: `time off team NAME YYYY/MM/DD`
        # help:     It will display the time off plan for the team specified.
        # help:    <https://github.com/MarioRuiz/slack-smart-bot#time-off-management|more info>
        # help: command_id: :see_vacations_team
        # help: 
      when /\A\s*(see\s+)?(vacations|time\s+off)\s+team\s+([\w\-]+)\s*(\d\d\d\d\/\d\d\/\d\d)?\s*\z/i,
        /\A\s*(see\s+)?(vacations|time\s+off)\s+([\w\-]+)\s+team\s*(\d\d\d\d\/\d\d\/\d\d)?\s*\z/i,
        /\A\s*(see\s+)?(vacations|time\s+off)\s+team\s+([\w\-]+)\s*(\d\d\d\d-\d\d-\d\d)?\s*\z/i,
        /\A\s*(see\s+)?(vacations|time\s+off)\s+([\w\-]+)\s+team\s*(\d\d\d\d-\d\d-\d\d)?\s*\z/i        
        team_name = $3.downcase
        date = $4.to_s
        date = Date.today.strftime("%Y/%m/%d") if date.empty?
        see_vacations_team(user, team_name, date)


        # help: ----------------------------------------------
        # help: `public holidays COUNTRY`
        # help: `public holidays COUNTRY/STATE DATE`
        # help:     STATE: optional. If not specified, it will return all the holidays for the country.
        # help:     DATE: optional. It can be supplied as YYYY or YYYY-MM or YYYY-MM-DD. If not specified, it will return all the holidays for current year.
        # help: Examples:
        # help:     _public holidays United States_
        # help:     _public holidays United States/California_
        # help:     _public holidays United States/California 2023_
        # help:     _public holidays Iceland 2023-12_
        # help:     _public holidays India 2023-12-25_
        # help: command_id: :public_holidays
        # help: 
      when /\A\s*public\s+(holiday?|vacation)s?\s+(in\s+|on\s+)?([a-zA-Z\s]+)()()()()\s*\z/i,
        /\A\s*public\s+(holiday?|vacation)s?\s+(in\s+|on\s+)?([a-zA-Z\s]+)\/([a-zA-Z\s]+)()()()\s*\z/i,
        /\A\s*public\s+(holiday?|vacation)s?\s+(in\s+|on\s+)?([a-zA-Z\s]+)\/([a-zA-Z\s]+)\s+(\d{4})[\/\-]?(\d\d)?[\/\-]?(\d\d)?\s*\z/i,
        /\A\s*public\s+(holiday?|vacation)s?\s+(in\s+|on\s+)?([a-zA-Z\s]+)()\s+(\d{4})[\/\-]?(\d\d)?[\/\-]?(\d\d)?\s*\z/i
        country = $3
        state = $4.to_s
        year = $5.to_s
        month = $6.to_s
        day = $7.to_s
        year = Date.today.year if year.to_s == ''
        public_holidays(country, state, year, month, day)

        # help: ----------------------------------------------
        # help: `set public holidays to COUNTRY/STATE`
        # help:     It will set the public holidays for the country and state specified.
        # help:     If STATE is not specified, it will set the public holidays for the country.
        # help: Examples:
        # help:     _set public holidays to Iceland_
        # help:     _set public holidays to United States/California_
        # help: command_id: :set_public_holidays
        # help:
      when /\A\s*set\s+public\s+(holiday?|vacation)s?\s+to\s+([^\/]+)\/([^\/]+)\s*\z/i,
        /\A\s*set\s+public\s+(holiday?|vacation)s?\s+to\s+([^\/]+)\s*\z/i
        country = $2
        state = $3.to_s
        set_public_holidays(country, state, user)

    else
      return false
    end
    return true
  rescue => exception
    if defined?(@logger)
      @logger.fatal exception
      respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
    else
      puts exception
    end
    return false
  end
end

#general_commands(user, command, dest, files = []) ⇒ Object

add here the general commands you will be using in any channel where The SmartBot is part of. Not necessary to use ! or ^, it will answer directly.



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/slack-smart-bot_general_commands.rb', line 2

def general_commands(user, command, dest, files = [])
    
  begin
    case command

        # help: ----------------------------------------------
        # help: `cls`
        # help: `clear`
        # help: `clear screen`
        # help: `NUMBER cls`
        # help:     It will send a big empty message.
        # help:        NUMBER (optional): number of lines. Default 100. Max 200.
        # help: command_id: :cls
        # help: 
    when /\A\s*(\d*)\s*(clear|cls|clear\s+screen)\s*\z/i
      save_stats :cls
      $1.to_s == '' ? lines = 100 : lines = $1.to_i
      lines = 200 if lines > 200
      respond (">#{"\n"*lines}<")

        # help: ----------------------------------------------
        # help: `blink TEXT`
        # help: `INTEGER blink TEXT`
        # help:     It will blink the text supplied. One or more lines of text. Emoticons or text format are allowed.
        # help:        INTEGER (optional): number of times. Default 50. Max 200.
        # help:  Examples: 
        # help:    blink Hello World!
        # help:    blink :moneybag: Pay attention! *Sales* are published!
        # help:    100 blink :new: *Party is about to start* :i_love_you_hand_sign:
        # help: command_id: :blink
        # help: 
      when /\A\s*(\d+)?\s*blink\s+(.+)\s*\z/im
        save_stats :blink
        num_times = $1.to_s == '' ? 50 : $1.to_i
        text = $2
        @blinking ||= []
        if num_times > 200 or num_times < 1
          respond "The number of times must be between 1 and 200"
        elsif @blinking.include?(user.name)
          respond "I'm already blinking something for you. Please wait until I finish"
        elsif @blinking.size >= 3 # rate limit in theory update can be done only once per second
          respond "I'm already blinking something for too many people. Please wait until I finish at least one of them."
        else
          @blinking << user.name
          msg = respond(text, return_message: true)
          num_times.times do
            sleep 2
            update(dest, msg.ts, ' ')
            sleep 0.5
            update(dest, msg.ts, text)
          end
          @blinking.delete(user.name)
        end

      # this is a hidden command that it is not listed when calling bot help
    when /\s*(that's\s+)?(thanks|thank\s+you|I\s+love\s+you|nice|cool)\s+(#{@salutations.join("|")})\s*!*\s*$/i
      save_stats :thanks
      reactions = [:heart, :heart_eyes, :blush, :relaxed, :simple_smile, :smiley, :two_hearts, :heartbeat, :green_heart ]
      reactions.sample(rand(3)+1).each {|rt| react rt }
      responses = ['Thank YOU', "You're welcome", "You're very welcome", 'No problem', 'No worries', "Don't mention it", 'My pleasure', 
        'Anytime', 'It was the least I could do', 'Glad to help', 'Sure', 'Pleasure', 'The pleasure is mine', 'It was nothing', 'Much obliged', "I'm happy to help",
        'Það var ekkert', 'De nada', 'No hay de qué', 'De rien',  'Bitte', 'Prego', 'मेरा सौभाग्य है', '不客氣', 'Παρακαλώ']
      respond "#{responses.sample}#{'!'*rand(4)}"

      # this is a hidden command that it is not listed when calling bot help
    when /\s*.*happy\s+birthday.*(<@\w+>)\s*.*$/i, /\s*.*(<@\w+>).*happy\s+birthday\s*.*$/i
      unless Thread.current[:on_thread]
        save_stats :happy_birthday
        happy_user = $1
        reactions = [:tada, :cake, :birthday]
        sleep 30
        reactions.sample(rand(3)+1).each {|rt| react rt }
        sleep (rand(10)+5)*60 # so SmartBot is not the first one
        responses = ['Happy birthday', "Very happy birthday", "Happy happy happy birthday", "Have a fabulous birthday", 'May all your wishes come true',
          'Many happy returns of the day', 'I wish you a wonderful birthday', 'Have a great one', 'I hope you have a fantastic day and a fantastic year to come',
          'To your happiness', "Don't count the candles. Enjoy the party", 'May your day be as awesome as you are', 'The best things in life are yet to come']
        respond "#{happy_user} #{responses.sample}#{'!'*rand(4)}", :on_thread
      end

    else
      return false
    end
    return true
  rescue => exception
    if defined?(@logger)
      @logger.fatal exception
      respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
    else
      puts exception
    end
    return false
  end
end

#general_rules(user, command, processed, dest, files = [], rules_file = "") ⇒ Object

add here the general rules you will be using in all Smart Bots



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/slack-smart-bot_general_rules.rb', line 2

def general_rules(user, command, processed, dest, files = [], rules_file = "")
    from = user.name
    display_name = user.profile.display_name
  
    begin
      case command

        # help: ----------------------------------------------
        # help: `echo SOMETHING`
        # help: `NUMBER echo SOMETHING`
        # help:     repeats SOMETHING. If NUMBER supplied then that number of times.
        # help:  Examples:
        # help:     _echo I am the Smart Bot_
        # help:     _100 echo :heart:_
        # help: command_id: :echo
        # help:        
      when /\A\s*(\d*)\s*echo\s(.+)/i
        save_stats :echo
        $1.to_s == '' ? times = 1 : times = $1.to_i
        respond ($2*times).to_s

      else
        return false
      end
      return true
    rescue => exception
      if defined?(@logger)
        @logger.fatal exception
        respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
      else
        puts exception
      end
      return false
    end
end

#get_channel_members(channel_id) ⇒ Object

todo: add pagination for case more than 1000 members in the channel



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/slack/smart-bot/comm/get_channel_members.rb', line 2

def get_channel_members(channel_id)
    begin
        if channel_id.nil?
            return nil
        else
            if config.simulate and config.key?(:client)
                client.web_client.conversations_members[channel_id.to_sym].members
            else
                client.web_client.conversations_members(channel: channel_id, limit: 1000).members
            end
        end
    rescue Exception => stack
        @logger.warn stack
    end

end

#get_channels(bot_is_in: false, types: 'private_channel,public_channel') ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/slack/smart-bot/comm/get_channels.rb', line 1

def get_channels(bot_is_in: false, types: 'private_channel,public_channel')
  begin
    if config.simulate and config.key?(:client)
      if bot_is_in
        client.web_client.conversations_members.reject { |r, v| !v.members.include?(config.nick_id) }.values
      else
        client.web_client.conversations_members.values
      end
    else
      if bot_is_in
        client.web_client.users_conversations(exclude_archived: true, limit: 1000, types: "im, public_channel,private_channel").channels
      else
        resp = client.web_client.conversations_list(types: types, limit: "600", exclude_archived: "true")
        channels = resp.channels
        begin
          while resp..next_cursor.to_s != ""
            resp = client.web_client.conversations_list(
              cursor: resp..next_cursor.to_s,
              types: types,
              limit: "600",
              exclude_archived: "true",
            )
            channels += resp.channels
          end
        rescue Exception => stack
          @logger.warn stack
        end
        return channels
      end
    end
  rescue Exception => stack
    @logger.warn stack
    return []
  end
end

#git_projectObject

link to the project



9
10
11
# File 'lib/slack-smart-bot_rules.rb', line 9

def git_project()
  ""
end

#poster(permanent, emoticon_text, emoticon_bg, string, minutes) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/slack/smart-bot/commands/general/poster.rb', line 1

def poster(permanent, emoticon_text, emoticon_bg, string, minutes)
  chars = { a: ["0000", "1111", "1001", "1111", "1001", "1001", "0000"],
            b: ["0000", "1111", "1001", "1110", "1001", "1111", "0000"],
            c: ["0000", "0111", "1000", "1000", "1000", "0111", "0000"],
            d: ["0000", "1110", "1001", "1001", "1001", "1110", "0000"],
            e: ["0000", "1111", "1000", "1110", "1000", "1111", "0000"],
            f: ["0000", "1111", "1000", "1110", "1000", "1000", "0000"],
            g: ["0000", "1111", "1000", "1011", "1001", "1111", "0000"],
            h: ["0000", "1001", "1001", "1111", "1001", "1001", "0000"],
            i: ["000", "111", "010", "010", "010", "111", "000"],
            j: ["0000", "0111", "0010", "0010", "1010", "0110", "0000"],
            k: ["0000", "1001", "1010", "1100", "1010", "1001", "0000"],
            l: ["000", "100", "100", "100", "100", "111", "000"],
            m: ["00000", "10001", "11011", "10101", "10001", "10001", "00000"],
            n: ["00000", "10001", "11001", "10101", "10011", "10001", "00000"],
            o: ["0000", "0110", "1001", "1001", "1001", "0110", "0000"],
            p: ["0000", "1110", "1001", "1110", "1000", "1000", "0000"],
            q: ["00000", "01100", "10010", "10010", "10010", "01111", "00000"],
            r: ["0000", "1110", "1001", "1110", "1010", "1001", "0000"],
            s: ["0000", "0111", "1000", "0110", "0001", "1110", "0000"],
            t: ["00000", "11111", "00100", "00100", "00100", "00100", "00000"],
            u: ["00000", "10001", "10001", "10001", "10001", "01110", "00000"],
            v: ["00000", "10001", "10001", "10001", "01010", "00100", "00000"],
            w: ["0000000", "1000001", "1000001", "1001001", "1010101", "0100010", "0000000"],
            x: ["00000", "10001", "01010", "00100", "01010", "10001", "00000"],
            y: ["00000", "10001", "01010", "00100", "00100", "00100", "00000"],
            z: ["00000", "11111", "00010", "00100", "01000", "11111", "00000"],
            '!': ["0", "1", "1", "1", "0", "1", "0"],
            '+': ["000", "000", "010", "111", "010", "000", "000"],
            '-': ["000", "000", "000", "111", "000", "000", "000"],
            '=': ["000", "000", "111", "000", "111", "000", "000"],
            '?': ["000", "111", "001", "010", "000", "010", "000"],
            '0': ["000", "111", "101", "101", "101", "111", "000"],
            '1': ["00", "01", "11", "01", "01", "01", "00"],
            '2': ["000", "111", "001", "010", "100", "111", "000"],
            '3': ["000", "111", "001", "111", "001", "111", "000"],
            '4': ["000", "101", "101", "111", "001", "001", "000"],
            '5': ["000", "111", "100", "111", "001", "111", "000"],
            '6': ["000", "111", "100", "111", "101", "111", "000"],
            '7': ["000", "111", "001", "010", "100", "100", "000"],
            '8': ["000", "111", "101", "111", "101", "111", "000"],
            '9': ["000", "111", "101", "111", "001", "111", "000"],
            ' ': ["0", "0", "0", "0", "0", "0", "0"] }

  emoticon_bg = ":white_square:" if emoticon_bg.to_s == ""
  emoticon_text = ":black_square:" if emoticon_text.to_s == ""
  string.downcase!
  messages = []

  string = string.strip.split(" ").join(" ")
  lines = [""]
  string.split(" ").each do |t|
    if ("#{lines[-1]}#{t}").size <= 6
      lines[-1] = "#{lines[-1]}#{t} "
    else
      lines[-1].strip!
      lines.pop if lines[-1] == ""
      if t.size > 6
        t.chars.each_slice(6).map(&:join).each do |tt|
          lines << tt.strip
        end
        lines[-1] += " " if lines[-1].size < 6
      else
        lines << t.strip + " "
      end
    end
  end
  lines[-1].strip!
  messages = []
  lines.each do |line|
    results = []
    all_spaces = true
    line.each_char do |char|
      if chars.key?(char.to_sym)
        results << chars[char.to_sym]
        all_spaces = false
      else
        results << chars[:' ']
      end
    end
    unless all_spaces
      rtxt = ""
      7.times do |n|
        results.size.times do |i|
          rtxt += "0#{results[i][n]}0"
        end
        rtxt += "\n"
      end
      rtxt.gsub!("1", emoticon_text)
      rtxt.gsub!("0", emoticon_bg)
      txt = ""
      msgs = []
      rtxt.split("\n").each do |m|
        if (m + txt).size > 4000
          msgs << txt unless txt == ""
          txt = ""
        end
        txt += (m + "\n")
      end
      msgs << txt
      msgs.flatten!
      msgs.each do |msg|
        messages << respond(msg, return_message: true)
      end
    end
  end
  unless permanent
    react :heavy_check_mark
    sleep (minutes.to_i * 60)
    messages.delete(nil)
    messages.each do |message|
      delete(message.channel, message.ts)
    end
    react :heavy_minus_sign
  end
end

#project_folderObject

path to the project folder for example "#echo ~$USER.chop/projects/the_project"



4
5
6
# File 'lib/slack-smart-bot_rules.rb', line 4

def project_folder()
  "#{Dir.pwd}/"
end

#public_holidays(country_name, location, year, month, day, add_stats: true, publish_results: true) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/slack/smart-bot/commands/general/public_holidays.rb', line 1

def public_holidays(country_name, location, year, month, day, add_stats: true, publish_results: true)
  save_stats(__method__) if add_stats
  if config[:public_holidays][:api_key].to_s == ""
    respond "Sorry, I don't have the API key for the public holidays #{config[:public_holidays][:host]}. Set it up on your SmartBot config file."
  else
    begin
      found_location = true
      http = NiceHttp.new("#{config[:public_holidays][:host]}/api/v2")
      if !defined?(@countries_candelarific)
        if File.exist?("#{config.path}/vacations/countries_candelarific.json")
          @countries_candelarific = JSON.parse(File.read("#{config.path}/vacations/countries_candelarific.json"))
        else
          response = http.get "/countries?api_key=#{config[:public_holidays][:api_key]}"
          countries_candelarific = response.data.json(:countries)
          if countries_candelarific.is_a?(Array)
            File.write("#{config.path}/vacations/countries_candelarific.json", countries_candelarific.to_json)
            @countries_candelarific = JSON.parse(countries_candelarific.to_json)
          else
            @countries_candelarific = []
          end
        end
      end
      country = @countries_candelarific.find { |c| c.country_name.match?(/^\s*#{country_name}\s*$/i) }
      if country.nil?
        respond "Country #{country_name} not found"
      else
        country_original_name = country_name.downcase
        country_region_id = country_name.downcase
        country_region_id += "/#{location.downcase}" unless location.empty?
        country_name = country["country_name"]
        country_iso = country["iso-3166"]
        states = []
        if @public_holidays.key?(country_region_id) and @public_holidays[country_region_id].key?(year.to_s)
          holidays = @public_holidays[country_region_id][year.to_s]
        elsif File.exist?(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))
          holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))).json()
        elsif !location.empty? and File.exist?(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))
          holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))).json()
          holidays.each do |holiday|
            if holiday.states.is_a?(Array)
              states << holiday.states.name
            else
              states << holiday.states
            end
          end
          holidays = holidays.select { |h| h.states.is_a?(String) and h.states == "All" or (h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0) }
          holidays_specific = holidays.select { |h| h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0 }
          found_location = false if holidays_specific.length == 0
        else
          response = http.get "/holidays?country=#{country_iso}&year=#{year}&day=#{day}&month=#{month}&api_key=#{config[:public_holidays][:api_key]}"
          holidays = response.data.json(:holidays)
          if location != ""
            holidays.each do |holiday|
              if holiday.states.is_a?(Array)
                states << holiday.states.name
              else
                states << holiday.states
              end
            end
            holidays = holidays.select { |h| h.states.is_a?(String) and h.states == "All" or (h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0) }
            holidays_specific = holidays.select { |h| h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0 }
            found_location = false if holidays_specific.length == 0
          end
          if day == "" and month == "" and holidays.is_a?(Array) and holidays.length > 0 and found_location
            File.write(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"), holidays.to_json) if holidays.is_a?(Array)
          end
        end
        if day == "" and month == ""
          date = year
        elsif day == ""
          date = "#{year}-#{"%02d" % month}"
        else
          date = "#{year}-#{"%02d" % month}-#{"%02d" % day}"
        end

        if holidays.is_a?(Array) and holidays.length > 0 and found_location
          date_holiday = ""
          messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
          num_holidays_to_show = 0
          all_holidays = []
          states = []
          holidays_to_add = []
          holidays.each do |holiday|
            if holiday.type.join.match?(/holiday/i)
              if location == "" or (location != "" and (holiday.states.is_a?(String) and holiday.states == "All") or (holiday.states.is_a?(Array) and holiday.states.name.grep(/#{location}/i).length > 0))
                holiday_id = "#{holiday[:date][:datetime][:year]}-#{"%02d" % holiday[:date][:datetime][:month]}-#{"%02d" % holiday[:date][:datetime][:day]} #{holiday[:name]}"
                unless all_holidays.include?(holiday_id) or
                       (day != "" and holiday[:date][:datetime][:day] != day.to_i) or
                       (month != "" and holiday[:date][:datetime][:month] != month.to_i)
                  all_holidays << holiday_id
                  if day == ""
                    m = holiday[:date][:datetime][:month]
                    d = holiday[:date][:datetime][:day]
                    date_holiday = " #{holiday[:date][:datetime][:year]}-#{"%02d" % m}-#{"%02d" % d} "
                  end
                  num_holidays_to_show += 1
                  break if num_holidays_to_show > 30 and publish_results
                  week_day = Date.new(holiday[:date][:datetime][:year], holiday[:date][:datetime][:month], holiday[:date][:datetime][:day]).strftime("%A")
                  messages << "\t:spiral_calendar_pad:#{date_holiday}*#{holiday[:name]}* _(#{holiday[:type].join(", ")}) (#{week_day})_"
                  messages << "\t#{holiday[:description]}"
                  if location == ""
                    if holiday.states.is_a?(Array)
                      messages << "\tLocations: #{holiday.states.name.sort.join(", ")}"
                    else
                      messages << "\tLocations: #{holiday.states}"
                    end
                  end
                  if holiday.states.is_a?(Array)
                    states << holiday.states.name
                  else
                    states << holiday.states
                  end
                  messages << "\n"
                  holidays_to_add << holiday
                end
              end
            end
          end
          @public_holidays[country_region_id] = {} if !@public_holidays.key?(country_region_id)
          @public_holidays[country_region_id][year.to_s] = holidays_to_add if !@public_holidays[country_region_id].key?(year.to_s)

          if num_holidays_to_show > 30
            messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
            messages << "Too many holidays to show, please refine your search"
          end
        else
          messages = ["*No holidays found in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}. Be sure the Country and State are written correctly. Try using just the Country, not all countries are supporting States.*"]
        end
        states.flatten!
        states.uniq!
        states.delete("All")
        if states.length > 1 and (location == "" or !found_location)
          messages << "*All States found in #{date} #{country_name}*: #{states.sort.join(", ")}"
          respond messages[-1] if !publish_results
        end
        respond messages.join("\n") unless !publish_results
      end
    rescue Exception => stack
      respond "Sorry, I can't get the public holidays for #{country_name} #{location} in #{date}. Error: #{stack.message}"
      @logger.fatal stack
    end
    return (found_location==true and !country.nil?) if !publish_results
  end
end

#rules(user, command, processed, dest, files = [], rules_file = "") ⇒ Object

user: user slack object command: command to run processed: in case the command has been already processed on Bot class, by default false dest: channel_id files: files attached rules_file: rules_file name

About the Help: Add as a comment starting by "help:" the help you need to add to the bot help and bot rules commands. The command logic needs to be added with `, and the parameters to supply need to be in capital for example:echo SOMETHING`

help: =================================== help: help: These are specific commands for this bot on this Channel. help: They will be accessible only when the bot is listening to you just writing the command help: or the bot is not listening to you but requested on demand, or in a private conversation with the Smart Bot. help: To run a command on demand: help: !THE_COMMAND help: @NAME_OF_BOT THE_COMMAND help: NAME_OF_BOT THE_COMMAND help: To run a command on demand and add the respond on a thread: help: ^THE_COMMAND help: !!THE_COMMAND help:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/slack-smart-bot_rules.rb', line 37

def rules(user, command, processed, dest, files = [], rules_file = "")
  from = user.name
  display_name = user.profile.display_name

  load "#{config.path}/rules/general_rules.rb"
  
  if general_rules(user, command, processed, dest, files, rules_file)
    return true
  else
    begin
      case command

        # help: ----------------------------------------------
        # help: `go to sleep`
        # help:   it will sleep the bot for 5 seconds
        # help: command_id: :go_to_sleep
        # help:
      when /\A\s*go\sto\ssleep/i
        save_stats :go_to_sleep
        if answer.empty?
          ask "do you want me to take a siesta?"
        else
          case answer
          when /yes/i, /yep/i, /sure/i
            answer_delete
            respond "I'll be sleeping for 5 secs... just for you"
            respond "zZzzzzzZZZZZZzzzzzzz!"
            react :sleeping
            sleep 5
            unreact :sleeping
            react :sunny
          when /no/i, /nope/i, /cancel/i
            answer_delete
            respond "Thanks, I'm happy to be awake"
          else
            respond "I don't understand"
            ask "are you sure you want me to sleep? (yes or no)"
          end
        end

        # help: ----------------------------------------------
        # help: `run something`
        # help:   It will run the process and report the results when done
        # help: command_id: :run_something
        # help:
      when /\Arun something/i
        save_stats :run_something
        if has_access?(:run_something, user)
          react :runner

          process_to_run = "ruby -v"
          process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
          stdout, stderr, status = Open3.capture3(process_to_run)
          unreact :runner
          if stderr == ""
            if stdout == ""
              respond "#{display_name}: Nothing returned."
            else
              respond "#{display_name}: #{stdout}"
            end
          else
            respond "#{display_name}: #{stdout} #{stderr}"
          end
        end
        
        # Emoticons you can use with `react` command https://www.webfx.com/tools/emoji-cheat-sheet/
        
        # Examples for respond, respond_thread and respond_direct
        #   # send 'the message' to the channel or direct message where the command was written
        #   respond "the message"
        #   # send 'the message' privately as a direct message to the user that sent the command
        #   respond_direct "the message"
        #   # same thing can be done:
        #   respond "the message", :direct
        #   # send 'the message' opening a thread
        #   respond_thread "the message"
        #   # same thing can be done:
        #   respond 'the message', :on_thread
        #   # send 'the message' to a specific channel name
        #   respond "the message", 'my_channel'
        #   # send 'the message' to a specific channel id
        #   respond "the message", 'CSU34D33'
        #   # send 'the message' to a specific user as direct message
        #   respond "the message", '@theuser'
        #   # send 'the message' to a specific user id as direct message
        #   respond "the message", 'US3344D3'

        # Example sending blocks https://api.slack.com/block-kit
        # my_blocks = [
        #   { type: "context",
        #     elements:
        #       [
        #         { type: "plain_text", :text=>"\tInfo: " },
        #         { type: "image", image_url: "https://avatars.slack-edge.com/2021-03-23/182815_e54abb1dd_24.jpg", alt_text: "mario" },
        #         { type: "mrkdwn", text: " *Mario Ruiz* (marior)  " }
        #       ]
        #   }
        # ]
        # respond blocks: my_blocks

        # Example downloading a file from slack
        #  if !files.nil? and files.size == 1 and files[0].filetype == 'yaml'
        #    require 'nice_http'
        #    http = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config[:token]}" })
        #    http.get(files[0].url_private_download, save_data: './tmp/')
        #  end

        # Examples sending a file to slack:
        #   send_file(to, msg, filepath, title, format, type = "text")
        #   send_file(dest, 'the message', "#{project_folder}/temp/logs_ptBI.log", 'title', 'text/plain', "text")
        #   send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'title', 'image/jpeg', "jpg")
      else
        unless processed
          dont_understand()
        end
        return false
      end
      return true
    rescue => exception
      @logger.fatal exception
      respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
      return false
    end
  end
end