slack-smart-bot 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/slack-smart-bot_general_rules.rb +7 -4
- data/lib/slack-smart-bot_rules.rb +2 -0
- data/lib/slack/smart-bot/comm.rb +2 -1
- data/lib/slack/smart-bot/comm/respond.rb +1 -1
- data/lib/slack/smart-bot/comm/send_file.rb +1 -1
- data/lib/slack/smart-bot/comm/unreact.rb +16 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +24 -5
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/bot_stats.rb +25 -6
- data/lib/slack/smart-bot/process.rb +2 -1
- data/lib/slack/smart-bot/treat_message.rb +1 -0
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +25 -3
- metadata +13 -12
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b15c46b5b101a0a31487508457982e8f5d6b81ad41f54338407ecdb2aa9974f3
         | 
| 4 | 
            +
              data.tar.gz: d32bfceda9068f5f11d1002f255b77a280f3a7b7068f40a632c03b7cb6378127
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 61c6e4060d928a1562176a0596ac968c7d007998c268816af489a0d36624a768ba1eadd3b6d27be7d19d37984b335d70215f718189165c1a9ac0a3a18130c5a0
         | 
| 7 | 
            +
              data.tar.gz: 48995f9d416dd8906353508ac9bf86219cd92b2ede2f0043c3752dcc4db95564161ad64f41d86fd9f821fa1dc6d9d5bba3ef5519be037214e0003c3423b595c9
         | 
    
        data/README.md
    CHANGED
    
    | @@ -124,6 +124,7 @@ def rules(user, command, processed, dest) | |
| 124 124 | 
             
                        respond "zZzzzzzZZZZZZzzzzzzz!"
         | 
| 125 125 | 
             
                        react :sleeping
         | 
| 126 126 | 
             
                        sleep 10
         | 
| 127 | 
            +
                        unreact :sleeping
         | 
| 127 128 | 
             
                        react :sunny
         | 
| 128 129 | 
             
                      when /no/i, /nope/i, /cancel/i
         | 
| 129 130 | 
             
                        @questions.delete(from)
         | 
| @@ -152,6 +153,8 @@ def rules(user, command, processed, dest) | |
| 152 153 | 
             
                  else
         | 
| 153 154 | 
             
                    respond "#{user.name}: #{stdout} #{stderr}"
         | 
| 154 155 | 
             
                  end
         | 
| 156 | 
            +
                  
         | 
| 157 | 
            +
                  unreact :runner
         | 
| 155 158 |  | 
| 156 159 | 
             
                else
         | 
| 157 160 | 
             
                  unless processed
         | 
| @@ -391,6 +394,7 @@ Examples: | |
| 391 394 | 
             
            >**_`add routine run_tests every 3h !run tests on customers`_**  
         | 
| 392 395 | 
             
            >**_`add routine clean_db at 17:05 !clean customers temp db`_**  
         | 
| 393 396 | 
             
            >**_`add silent routine clean_db at 17:05 !clean customers temp db`_**  
         | 
| 397 | 
            +
            >**_`add routine clean_custdb on Mondays at 05:00 !clean customers db`_**  
         | 
| 394 398 |  | 
| 395 399 | 
             
            Also instead of adding a Command to be executed, you can attach a file, then the routine will be created and the attached file will be executed on the criteria specified. Only Master Admins are allowed to use it this way.
         | 
| 396 400 |  | 
| @@ -8,12 +8,15 @@ def general_rules(user, command, processed, dest, files = [], rules_file = "") | |
| 8 8 |  | 
| 9 9 | 
             
                    # help: ----------------------------------------------
         | 
| 10 10 | 
             
                    # help: `echo SOMETHING`
         | 
| 11 | 
            -
                    # help: | 
| 11 | 
            +
                    # help: `INTEGER echo SOMETHING`
         | 
| 12 | 
            +
                    # help:     repeats SOMETHING. If INTEGER supplied then that number of times.
         | 
| 12 13 | 
             
                    # help:  Examples:
         | 
| 13 14 | 
             
                    # help:     _echo I am the Smart Bot_
         | 
| 14 | 
            -
                     | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 15 | 
            +
                    # help:     _100 echo :heart:_
         | 
| 16 | 
            +
                  when /^(\d*)\s*echo\s(.+)/i
         | 
| 17 | 
            +
                    save_stats :echo
         | 
| 18 | 
            +
                    $1.to_s == '' ? times = 1 : times = $1.to_i
         | 
| 19 | 
            +
                    respond ($2*times).to_s
         | 
| 17 20 |  | 
| 18 21 | 
             
                  else
         | 
| 19 22 | 
             
                    return false
         | 
| @@ -60,6 +60,7 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 60 60 | 
             
                        respond "zZzzzzzZZZZZZzzzzzzz!"
         | 
| 61 61 | 
             
                        react :sleeping
         | 
| 62 62 | 
             
                        sleep 5
         | 
| 63 | 
            +
                        unreact :sleeping
         | 
| 63 64 | 
             
                        react :sunny
         | 
| 64 65 | 
             
                      when /no/i, /nope/i, /cancel/i
         | 
| 65 66 | 
             
                        @questions.delete(from)
         | 
| @@ -81,6 +82,7 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 81 82 | 
             
                    process_to_run = "ruby -v"
         | 
| 82 83 | 
             
                    process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
         | 
| 83 84 | 
             
                    stdout, stderr, status = Open3.capture3(process_to_run)
         | 
| 85 | 
            +
                    unreact :runner
         | 
| 84 86 | 
             
                    if stderr == ""
         | 
| 85 87 | 
             
                      if stdout == ""
         | 
| 86 88 | 
             
                        respond "#{display_name}: Nothing returned."
         | 
    
        data/lib/slack/smart-bot/comm.rb
    CHANGED
    
    
| @@ -38,7 +38,7 @@ class SlackSmartBot | |
| 38 38 | 
             
                      f.puts "|#{dest}|#{config[:nick_id]}|#{msg}"
         | 
| 39 39 | 
             
                    }
         | 
| 40 40 | 
             
                  end
         | 
| 41 | 
            -
                elsif dest[0] == "D" or dest[0] == "U" # Direct message
         | 
| 41 | 
            +
                elsif dest[0] == "D" or dest[0] == "U"  or dest[0] == "W" # Direct message
         | 
| 42 42 | 
             
                  send_msg_user(dest, msg)
         | 
| 43 43 | 
             
                elsif dest[0] == "@"
         | 
| 44 44 | 
             
                  begin
         | 
| @@ -8,7 +8,7 @@ class SlackSmartBot | |
| 8 8 | 
             
              def send_file(to, msg, file, title, format, type = "text", content: '')
         | 
| 9 9 | 
             
                unless config[:simulate]
         | 
| 10 10 | 
             
                  file = 'myfile' if file.to_s == '' and content!=''
         | 
| 11 | 
            -
                  if to[0] == "U" #user
         | 
| 11 | 
            +
                  if to[0] == "U" or to[0] == "W" #user
         | 
| 12 12 | 
             
                    im = client.web_client.im_open(user: to)
         | 
| 13 13 | 
             
                    channel = im["channel"]["id"]
         | 
| 14 14 | 
             
                  else
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
              # list of available emojis: https://www.webfx.com/tools/emoji-cheat-sheet/
         | 
| 3 | 
            +
              # unreact(:thumbsup)
         | 
| 4 | 
            +
              def unreact(emoji, parent=false)
         | 
| 5 | 
            +
                if parent
         | 
| 6 | 
            +
                  ts = Thread.current[:thread_ts]
         | 
| 7 | 
            +
                else
         | 
| 8 | 
            +
                  ts = Thread.current[:ts]
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
                begin
         | 
| 11 | 
            +
                  client.web_client.reactions_remove(channel: Thread.current[:dest], name: emoji, timestamp: ts)
         | 
| 12 | 
            +
                rescue Exception => stack
         | 
| 13 | 
            +
                  @logger.warn stack
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -5,6 +5,7 @@ class SlackSmartBot | |
| 5 5 | 
             
              # helpadmin: `add silent routine NAME every NUMBER PERIOD`
         | 
| 6 6 | 
             
              # helpadmin: `create routine NAME every NUMBER PERIOD`
         | 
| 7 7 | 
             
              # helpadmin: `add routine NAME at TIME COMMAND`
         | 
| 8 | 
            +
              # helpadmin: `add routine NAME on DAYWEEK at TIME COMMAND`
         | 
| 8 9 | 
             
              # helpadmin: `add routine NAME at TIME`
         | 
| 9 10 | 
             
              # helpadmin: `add silent routine NAME at TIME`
         | 
| 10 11 | 
             
              # helpadmin: `create routine NAME at TIME`
         | 
| @@ -15,12 +16,14 @@ class SlackSmartBot | |
| 15 16 | 
             
              # helpadmin:    NUMBER: Integer
         | 
| 16 17 | 
             
              # helpadmin:    PERIOD: days, d, hours, h, minutes, mins, min, m, seconds, secs, sec, s
         | 
| 17 18 | 
             
              # helpadmin:    TIME: time at format HH:MM:SS
         | 
| 19 | 
            +
              # helpadmin:    DAYWEEK: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. And their plurals.
         | 
| 18 20 | 
             
              # helpadmin:    COMMAND: any valid smart bot command or rule
         | 
| 19 21 | 
             
              # helpadmin:    Examples:
         | 
| 20 22 | 
             
              # helpadmin:      _add routine example every 30s ruby puts 'a'_
         | 
| 21 23 | 
             
              # helpadmin:      _add routine example every 3 days ruby puts 'a'_
         | 
| 22 24 | 
             
              # helpadmin:      _add routine example at 17:05 ruby puts 'a'_
         | 
| 23 25 | 
             
              # helpadmin:      _create silent routine every 12 hours !Run customer tests_
         | 
| 26 | 
            +
              # helpadmin:      _add routine example on Mondays at 05:00 !run customer tests_
         | 
| 24 27 | 
             
              # helpadmin:
         | 
| 25 28 | 
             
              def add_routine(dest, from, user, name, type, number_time, period, command_to_run, files, silent)
         | 
| 26 29 | 
             
                save_stats(__method__)
         | 
| @@ -30,13 +33,14 @@ class SlackSmartBot | |
| 30 33 | 
             
                      respond "I'm sorry but there is already a routine with that name.\nCall `see routines` to see added routines", dest
         | 
| 31 34 | 
             
                    else
         | 
| 32 35 | 
             
                      number_time += ":00" if number_time.split(":").size == 2
         | 
| 33 | 
            -
                      if (type  | 
| 36 | 
            +
                      if (type != "every") && !number_time.match?(/^[01][0-9]:[0-5][0-9]:[0-5][0-9]$/) &&
         | 
| 34 37 | 
             
                         !number_time.match?(/^2[0-3]:[0-5][0-9]:[0-5][0-9]$/)
         | 
| 35 38 | 
             
                        respond "Wrong time specified: *#{number_time}*"
         | 
| 36 39 | 
             
                      else
         | 
| 37 40 | 
             
                        file_path = ""
         | 
| 38 41 | 
             
                        every = ""
         | 
| 39 42 | 
             
                        at = ""
         | 
| 43 | 
            +
                        dayweek = ''
         | 
| 40 44 | 
             
                        next_run = Time.now
         | 
| 41 45 | 
             
                        case period.downcase
         | 
| 42 46 | 
             
                        when "days", "d"
         | 
| @@ -52,16 +56,31 @@ class SlackSmartBot | |
| 52 56 | 
             
                          every = "#{number_time} seconds"
         | 
| 53 57 | 
             
                          every_in_seconds = number_time.to_i
         | 
| 54 58 | 
             
                        else # time
         | 
| 59 | 
            +
                          if type != 'at'
         | 
| 60 | 
            +
                            dayweek = type.downcase
         | 
| 61 | 
            +
                            days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday']
         | 
| 62 | 
            +
                            incr = days.index(dayweek) - Time.now.wday
         | 
| 63 | 
            +
                            if incr < 0 
         | 
| 64 | 
            +
                              incr = (7+incr)*24*60*60
         | 
| 65 | 
            +
                            else
         | 
| 66 | 
            +
                              incr = incr * 24 * 60 * 60
         | 
| 67 | 
            +
                            end
         | 
| 68 | 
            +
                            days = incr/(24*60*60)
         | 
| 69 | 
            +
                            every_in_seconds = 7 * 24 * 60 * 60 # one week
         | 
| 70 | 
            +
                          else
         | 
| 71 | 
            +
                            days = 0
         | 
| 72 | 
            +
                            every_in_seconds = 24 * 60 * 60 # one day
         | 
| 73 | 
            +
                          end
         | 
| 74 | 
            +
             | 
| 55 75 | 
             
                          at = number_time
         | 
| 56 | 
            -
                          if next_run.strftime("%H:%M:%S") < number_time
         | 
| 76 | 
            +
                          if next_run.strftime("%H:%M:%S") < number_time and days == 0
         | 
| 57 77 | 
             
                            nt = number_time.split(":")
         | 
| 58 78 | 
             
                            next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
         | 
| 59 79 | 
             
                          else
         | 
| 60 | 
            -
                            next_run += (24 * 60 * 60) # one more  | 
| 80 | 
            +
                            next_run += ((24 * 60 * 60) * days) # one or more days
         | 
| 61 81 | 
             
                            nt = number_time.split(":")
         | 
| 62 82 | 
             
                            next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
         | 
| 63 83 | 
             
                          end
         | 
| 64 | 
            -
                          every_in_seconds = 24 * 60 * 60
         | 
| 65 84 | 
             
                        end
         | 
| 66 85 | 
             
                        Dir.mkdir("#{config.path}/routines/#{@channel_id}") unless Dir.exist?("#{config.path}/routines/#{@channel_id}")
         | 
| 67 86 |  | 
| @@ -78,7 +97,7 @@ class SlackSmartBot | |
| 78 97 |  | 
| 79 98 | 
             
                        @routines[@channel_id] = {} unless @routines.key?(@channel_id)
         | 
| 80 99 | 
             
                        @routines[@channel_id][name] = { channel_name: config.channel, creator: from, creator_id: user.id, status: :on,
         | 
| 81 | 
            -
                                                         every: every, every_in_seconds: every_in_seconds, at: at, file_path: file_path, 
         | 
| 100 | 
            +
                                                         every: every, every_in_seconds: every_in_seconds, at: at, dayweek: dayweek, file_path: file_path, 
         | 
| 82 101 | 
             
                                                         command: command_to_run.to_s.strip, silent: silent,
         | 
| 83 102 | 
             
                                                         next_run: next_run.to_s, dest: dest, last_run: "", last_elapsed: "", 
         | 
| 84 103 | 
             
                                                         running: false }
         | 
| @@ -44,6 +44,7 @@ class SlackSmartBot | |
| 44 44 | 
             
                        msg << "\tStatus: #{v[:status]}"
         | 
| 45 45 | 
             
                        msg << "\tEvery: #{v[:every]}" unless v[:every] == ""
         | 
| 46 46 | 
             
                        msg << "\tAt: #{v[:at]}" unless v[:at] == ""
         | 
| 47 | 
            +
                        msg << "\tOn: #{v[:dayweek]}" unless !v.key?(:dayweek) or v[:dayweek].to_s == "" 
         | 
| 47 48 | 
             
                        msg << "\tNext Run: #{v[:next_run]}"
         | 
| 48 49 | 
             
                        msg << "\tLast Run: #{v[:last_run]}"
         | 
| 49 50 | 
             
                        msg << "\tTime consumed on last run: #{v[:last_elapsed]}" unless v[:command] !=''
         | 
| @@ -22,7 +22,7 @@ class SlackSmartBot | |
| 22 22 | 
             
                # helpadmin:      _bot stats @peter.wind_
         | 
| 23 23 | 
             
                # helpadmin:      _bot stats #sales from 2019/12/15 to 2019/12/31_
         | 
| 24 24 | 
             
                # helpadmin:      _bot stats #sales today_
         | 
| 25 | 
            -
                # helpadmin:      _bot stats #sales monthly_
         | 
| 25 | 
            +
                # helpadmin:      _bot stats #sales from 2020-01-01 monthly_
         | 
| 26 26 | 
             
                # helpadmin:
         | 
| 27 27 | 
             
                def bot_stats(dest, from_user, typem, channel_id, from, to, user, exclude_masters, exclude_command, monthly)
         | 
| 28 28 | 
             
                    require 'csv'
         | 
| @@ -36,6 +36,10 @@ class SlackSmartBot | |
| 36 36 | 
             
                        if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
         | 
| 37 37 | 
             
                            message<<'No stats'
         | 
| 38 38 | 
             
                        else
         | 
| 39 | 
            +
                            if user!=''
         | 
| 40 | 
            +
                                user_info = client.web_client.users_info(user: user)
         | 
| 41 | 
            +
                                user_name = user_info.user.name
         | 
| 42 | 
            +
                            end
         | 
| 39 43 | 
             
                            from = "#{Time.now.strftime("%Y-%m")}-01" if from == ''
         | 
| 40 44 | 
             
                            to = "#{Time.now.strftime("%Y-%m-%d")}" if to == ''
         | 
| 41 45 | 
             
                            from_short = from
         | 
| @@ -46,20 +50,26 @@ class SlackSmartBot | |
| 46 50 | 
             
                            to+= " 23:59:59 +0000"
         | 
| 47 51 | 
             
                            rows = []
         | 
| 48 52 | 
             
                            rows_month = {}
         | 
| 53 | 
            +
                            users_month = {}
         | 
| 54 | 
            +
                            commands_month = {}
         | 
| 49 55 |  | 
| 50 56 | 
             
                            Dir["#{config.stats_path}.*.log"].sort.each do |file|
         | 
| 51 57 | 
             
                                if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
         | 
| 52 58 | 
             
                                    CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
         | 
| 53 59 | 
             
                                        row[:date] = row[:date].to_s
         | 
| 54 60 | 
             
                                        if !exclude_masters or (exclude_masters and !config.masters.include?(row[:user_name]))
         | 
| 55 | 
            -
                                            if user=='' or (user!='' and row[: | 
| 61 | 
            +
                                            if user=='' or (user!='' and row[:user_name] == user_name)
         | 
| 56 62 | 
             
                                                if exclude_command == '' or (exclude_command!='' and row[:command]!=exclude_command)
         | 
| 57 63 | 
             
                                                    if row[:bot_channel_id] == channel_id or channel_id == ''
         | 
| 58 64 | 
             
                                                        if row[:date] >= from and row[:date] <= to
         | 
| 59 65 | 
             
                                                            rows << row.to_h
         | 
| 60 66 | 
             
                                                            if monthly
         | 
| 61 67 | 
             
                                                                rows_month[row[:date][0..6]] = 0 unless rows_month.key?(row[:date][0..6])
         | 
| 68 | 
            +
                                                                users_month[row[:date][0..6]] = [] unless users_month.key?(row[:date][0..6])
         | 
| 69 | 
            +
                                                                commands_month[row[:date][0..6]] = [] unless commands_month.key?(row[:date][0..6])
         | 
| 62 70 | 
             
                                                                rows_month[row[:date][0..6]] += 1
         | 
| 71 | 
            +
                                                                users_month[row[:date][0..6]] << row[:user_name]
         | 
| 72 | 
            +
                                                                commands_month[row[:date][0..6]] << row[:command]
         | 
| 63 73 | 
             
                                                            end
         | 
| 64 74 | 
             
                                                        end
         | 
| 65 75 | 
             
                                                    end
         | 
| @@ -87,9 +97,18 @@ class SlackSmartBot | |
| 87 97 | 
             
                            end
         | 
| 88 98 | 
             
                            if total > 0
         | 
| 89 99 | 
             
                                if monthly 
         | 
| 90 | 
            -
                                    message << '*Totals by month*'
         | 
| 100 | 
            +
                                    message << '*Totals by month / commands / users (%new)*'
         | 
| 101 | 
            +
                                    all_users = []
         | 
| 102 | 
            +
                                    new_users = []
         | 
| 91 103 | 
             
                                    rows_month.each do |k,v|
         | 
| 92 | 
            -
                                         | 
| 104 | 
            +
                                        if all_users.empty?
         | 
| 105 | 
            +
                                            message_new_users = ''
         | 
| 106 | 
            +
                                        else
         | 
| 107 | 
            +
                                            new_users = (users_month[k]-all_users).uniq
         | 
| 108 | 
            +
                                            message_new_users = "(#{new_users.size*100/users_month[k].uniq.size}%)"
         | 
| 109 | 
            +
                                        end
         | 
| 110 | 
            +
                                        all_users += users_month[k]
         | 
| 111 | 
            +
                                        message << "\t#{k}: #{v} (#{(v.to_f*100/total).round(2)}%) / #{commands_month[k].uniq.size} / #{users_month[k].uniq.size} #{message_new_users}"
         | 
| 93 112 | 
             
                                    end
         | 
| 94 113 | 
             
                                end
         | 
| 95 114 |  | 
| @@ -102,16 +121,16 @@ class SlackSmartBot | |
| 102 121 | 
             
                                    end
         | 
| 103 122 | 
             
                                end
         | 
| 104 123 | 
             
                                if user==''
         | 
| 105 | 
            -
                                    message << "*Users*"
         | 
| 106 124 | 
             
                                    users = rows.user_name.uniq.sort
         | 
| 125 | 
            +
                                    message << "*Users* - #{users.size}"
         | 
| 107 126 | 
             
                                    users.each do |user|
         | 
| 108 127 | 
             
                                        count = rows.count {|h| h.user_name==user}
         | 
| 109 128 | 
             
                                        message << "\t#{user}: #{count} (#{(count.to_f*100/total).round(2)}%)"
         | 
| 110 129 | 
             
                                    end
         | 
| 111 130 | 
             
                                end
         | 
| 112 131 |  | 
| 113 | 
            -
                                message << "*Commands*"
         | 
| 114 132 | 
             
                                commands = rows.command.uniq.sort
         | 
| 133 | 
            +
                                message << "*Commands* - #{commands.size}"
         | 
| 115 134 | 
             
                                commands.each do |command|
         | 
| 116 135 | 
             
                                    count = rows.count {|h| h.command==command}
         | 
| 117 136 | 
             
                                    message << "\t#{command}: #{count} (#{(count.to_f*100/total).round(2)}%)"
         | 
| @@ -70,7 +70,8 @@ class SlackSmartBot | |
| 70 70 | 
             
                    channel = $1
         | 
| 71 71 | 
             
                    kill_bot_on_channel(dest, from, channel)
         | 
| 72 72 | 
             
                  when /^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+(every)\s+(\d+)\s*(days|hours|minutes|seconds|mins|min|secs|sec|d|h|m|s)\s*(\s.+)?\s*$/i,
         | 
| 73 | 
            -
             | 
| 73 | 
            +
                    /^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+on\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)s?\s+at\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i,
         | 
| 74 | 
            +
                    /^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i
         | 
| 74 75 | 
             
                    silent = $2.to_s!=''
         | 
| 75 76 | 
             
                    name = $3.downcase
         | 
| 76 77 | 
             
                    type = $4
         | 
| @@ -117,6 +117,7 @@ class SlackSmartBot | |
| 117 117 | 
             
                  begin
         | 
| 118 118 | 
             
                    #todo: when changed @questions user_id then move user_info inside the ifs to avoid calling it when not necessary
         | 
| 119 119 | 
             
                    user_info = client.web_client.users_info(user: data.user)
         | 
| 120 | 
            +
                    user_info.user.id = data.user #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
         | 
| 120 121 | 
             
                    if @questions.key?(user_info.user.name)
         | 
| 121 122 | 
             
                      if data.text.match?(/^\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i)
         | 
| 122 123 | 
             
                        @questions.delete(user_info.user.name)
         | 
| @@ -13,7 +13,6 @@ class SlackSmartBot | |
| 13 13 | 
             
                        ruby = ""
         | 
| 14 14 | 
             
                      end
         | 
| 15 15 | 
             
                      @routines[@channel_id][name][:silent] = false if !@routines[@channel_id][name].key?(:silent)
         | 
| 16 | 
            -
             | 
| 17 16 | 
             
                      if @routines[@channel_id][name][:at] == "" or
         | 
| 18 17 | 
             
                         (@routines[@channel_id][name][:at] != "" and @routines[@channel_id][name][:running] and
         | 
| 19 18 | 
             
                          @routines[@channel_id][name][:next_run] != "" and Time.now.to_s >= @routines[@channel_id][name][:next_run])
         | 
| @@ -55,11 +54,34 @@ class SlackSmartBot | |
| 55 54 | 
             
                        require "time"
         | 
| 56 55 | 
             
                        every_in_seconds = Time.parse(@routines[@channel_id][name][:next_run]) - Time.now
         | 
| 57 56 | 
             
                      elsif @routines[@channel_id][name][:at] != "" #coming from start after pause for 'at'
         | 
| 58 | 
            -
                        if  | 
| 57 | 
            +
                        if @routines[@channel_id][name].key?(:dayweek) and @routines[@channel_id][name][:dayweek].to_s!=''
         | 
| 58 | 
            +
                          day = @routines[@channel_id][name][:dayweek]
         | 
| 59 | 
            +
                          days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday']
         | 
| 60 | 
            +
                          incr = days.index(day) - Time.now.wday
         | 
| 61 | 
            +
                          if incr < 0 
         | 
| 62 | 
            +
                            incr = (7+incr)*24*60*60
         | 
| 63 | 
            +
                          else
         | 
| 64 | 
            +
                            incr = incr * 24 * 60 * 60
         | 
| 65 | 
            +
                          end
         | 
| 66 | 
            +
                          days = incr/(24*60*60)
         | 
| 67 | 
            +
                          weekly = true
         | 
| 68 | 
            +
                        else
         | 
| 69 | 
            +
                          days = 0
         | 
| 70 | 
            +
                          weekly = false
         | 
| 71 | 
            +
                        end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                        if started.strftime("%H:%M:%S") < @routines[@channel_id][name][:at] and days == 0
         | 
| 59 74 | 
             
                          nt = @routines[@channel_id][name][:at].split(":")
         | 
| 60 75 | 
             
                          next_run = Time.new(started.year, started.month, started.day, nt[0], nt[1], nt[2])
         | 
| 61 76 | 
             
                        else
         | 
| 62 | 
            -
                           | 
| 77 | 
            +
                          if days == 0 and started.strftime("%H:%M:%S") >= @routines[@channel_id][name][:at]
         | 
| 78 | 
            +
                            if weekly
         | 
| 79 | 
            +
                                days = 7
         | 
| 80 | 
            +
                            else
         | 
| 81 | 
            +
                                days = 1
         | 
| 82 | 
            +
                            end
         | 
| 83 | 
            +
                          end
         | 
| 84 | 
            +
                          next_run = started + (days * 24 * 60 * 60) # one more day/week
         | 
| 63 85 | 
             
                          nt = @routines[@channel_id][name][:at].split(":")
         | 
| 64 86 | 
             
                          next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
         | 
| 65 87 | 
             
                        end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,35 +1,35 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: slack-smart-bot
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.8.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Mario Ruiz
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020- | 
| 11 | 
            +
            date: 2020-08-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: slack-ruby-client
         | 
| 15 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 16 | 
             
                requirements:
         | 
| 17 | 
            -
                - - "~>"
         | 
| 18 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: '0.14'
         | 
| 20 17 | 
             
                - - ">="
         | 
| 21 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            -
                    version: 0. | 
| 19 | 
            +
                    version: 0.15.0
         | 
| 20 | 
            +
                - - "~>"
         | 
| 21 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            +
                    version: '0.15'
         | 
| 23 23 | 
             
              type: :runtime
         | 
| 24 24 | 
             
              prerelease: false
         | 
| 25 25 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 26 26 | 
             
                requirements:
         | 
| 27 | 
            -
                - - "~>"
         | 
| 28 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            -
                    version: '0.14'
         | 
| 30 27 | 
             
                - - ">="
         | 
| 31 28 | 
             
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            -
                    version: 0. | 
| 29 | 
            +
                    version: 0.15.0
         | 
| 30 | 
            +
                - - "~>"
         | 
| 31 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            +
                    version: '0.15'
         | 
| 33 33 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 34 34 | 
             
              name: nice_http
         | 
| 35 35 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -81,7 +81,7 @@ dependencies: | |
| 81 81 | 
             
                    version: '1'
         | 
| 82 82 | 
             
                - - ">="
         | 
| 83 83 | 
             
                  - !ruby/object:Gem::Version
         | 
| 84 | 
            -
                    version: 1.1 | 
| 84 | 
            +
                    version: 1.2.1
         | 
| 85 85 | 
             
              type: :runtime
         | 
| 86 86 | 
             
              prerelease: false
         | 
| 87 87 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -91,7 +91,7 @@ dependencies: | |
| 91 91 | 
             
                    version: '1'
         | 
| 92 92 | 
             
                - - ">="
         | 
| 93 93 | 
             
                  - !ruby/object:Gem::Version
         | 
| 94 | 
            -
                    version: 1.1 | 
| 94 | 
            +
                    version: 1.2.1
         | 
| 95 95 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 96 96 | 
             
              name: rspec
         | 
| 97 97 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -136,6 +136,7 @@ files: | |
| 136 136 | 
             
            - lib/slack/smart-bot/comm/send_file.rb
         | 
| 137 137 | 
             
            - lib/slack/smart-bot/comm/send_msg_channel.rb
         | 
| 138 138 | 
             
            - lib/slack/smart-bot/comm/send_msg_user.rb
         | 
| 139 | 
            +
            - lib/slack/smart-bot/comm/unreact.rb
         | 
| 139 140 | 
             
            - lib/slack/smart-bot/commands.rb
         | 
| 140 141 | 
             
            - lib/slack/smart-bot/commands/general/bot_help.rb
         | 
| 141 142 | 
             
            - lib/slack/smart-bot/commands/general/bot_status.rb
         |