slack-smart-bot 1.9.2 → 1.10.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 +109 -11
- data/lib/slack/smart-bot/comm/ask.rb +55 -49
- data/lib/slack/smart-bot/comm/dont_understand.rb +1 -1
- data/lib/slack/smart-bot/comm/event_hello.rb +7 -3
- data/lib/slack/smart-bot/comm/get_channel_members.rb +9 -4
- data/lib/slack/smart-bot/comm/get_channels.rb +31 -16
- data/lib/slack/smart-bot/comm/get_user_info.rb +12 -8
- data/lib/slack/smart-bot/comm/get_users.rb +24 -0
- data/lib/slack/smart-bot/comm/react.rb +19 -2
- data/lib/slack/smart-bot/comm/respond.rb +217 -72
- data/lib/slack/smart-bot/comm/respond_direct.rb +2 -3
- data/lib/slack/smart-bot/comm/respond_thread.rb +5 -0
- data/lib/slack/smart-bot/comm/send_file.rb +38 -34
- data/lib/slack/smart-bot/comm/send_msg_channel.rb +27 -22
- data/lib/slack/smart-bot/comm/send_msg_user.rb +58 -33
- data/lib/slack/smart-bot/comm/unreact.rb +22 -18
- data/lib/slack/smart-bot/comm.rb +2 -0
- data/lib/slack/smart-bot/commands/general/add_announcement.rb +32 -0
- data/lib/slack/smart-bot/commands/general/bot_help.rb +59 -32
- data/lib/slack/smart-bot/commands/general/bot_stats.rb +10 -9
- data/lib/slack/smart-bot/commands/general/bot_status.rb +2 -4
- data/lib/slack/smart-bot/commands/general/bye_bot.rb +0 -7
- data/lib/slack/smart-bot/commands/general/delete_announcement.rb +34 -0
- data/lib/slack/smart-bot/commands/general/delete_share.rb +34 -0
- data/lib/slack/smart-bot/commands/general/hi_bot.rb +16 -11
- data/lib/slack/smart-bot/commands/general/leaderboard.rb +200 -0
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +113 -0
- data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +54 -0
- data/lib/slack/smart-bot/commands/general/see_shares.rb +41 -0
- data/lib/slack/smart-bot/commands/general/see_statuses.rb +78 -0
- data/lib/slack/smart-bot/commands/general/share_messages.rb +58 -0
- data/lib/slack/smart-bot/commands/general/stop_using_rules.rb +11 -6
- data/lib/slack/smart-bot/commands/general/suggest_command.rb +30 -0
- data/lib/slack/smart-bot/commands/general/use_rules.rb +7 -7
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +243 -0
- data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +2 -5
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +32 -11
- data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +2 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/pause_bot.rb +4 -2
- data/lib/slack/smart-bot/commands/on_bot/admin/pause_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +6 -1
- data/lib/slack/smart-bot/commands/on_bot/admin/see_result_routine.rb +32 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +4 -2
- data/lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb +4 -2
- data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb +2 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +32 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +24 -0
- data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +2 -4
- data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +2 -4
- data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +2 -4
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +5 -7
- data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +2 -4
- data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +4 -5
- data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +3 -5
- data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +2 -4
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +45 -12
- data/lib/slack/smart-bot/commands/on_master/admin/kill_bot_on_channel.rb +4 -1
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +2 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +1 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +32 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +38 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +8 -0
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +27 -14
- data/lib/slack/smart-bot/commands.rb +16 -0
- data/lib/slack/smart-bot/listen.rb +1 -3
- data/lib/slack/smart-bot/process.rb +212 -74
- data/lib/slack/smart-bot/process_first.rb +118 -37
- data/lib/slack/smart-bot/treat_message.rb +313 -248
- data/lib/slack/smart-bot/utils/build_help.rb +3 -3
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +81 -46
- data/lib/slack/smart-bot/utils/get_bots_created.rb +4 -1
- data/lib/slack/smart-bot/utils/get_help.rb +58 -68
- data/lib/slack/smart-bot/utils/get_shares.rb +12 -0
- data/lib/slack/smart-bot/utils/has_access.rb +12 -0
- data/lib/slack/smart-bot/utils/save_stats.rb +2 -0
- data/lib/slack/smart-bot/utils/save_status.rb +52 -0
- data/lib/slack/smart-bot/utils.rb +3 -0
- data/lib/slack-smart-bot.rb +45 -4
- data/lib/slack-smart-bot_general_commands.rb +46 -0
- data/lib/slack-smart-bot_general_rules.rb +5 -2
- data/lib/slack-smart-bot_rules.rb +43 -17
- data/whats_new.txt +32 -20
- metadata +24 -2
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
             | 
| 3 | 
            +
                def save_status(status, status_id, message)
         | 
| 4 | 
            +
                  require 'csv'
         | 
| 5 | 
            +
                  Dir.mkdir("#{config.path}/status") unless Dir.exist?("#{config.path}/status")
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  CSV.open("#{config.path}/status/#{config.channel}_status.csv", "a+") do |csv|
         | 
| 8 | 
            +
                    csv << [Time.now.strftime("%Y/%m/%d"), Time.now.strftime("%H:%M:%S"), status, status_id, message]
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  if status_id == :disconnected
         | 
| 11 | 
            +
                    Thread.new do
         | 
| 12 | 
            +
                      sleep 50
         | 
| 13 | 
            +
                      @logger.info "check disconnection 50 scs later #{@last_notified_status_id}"
         | 
| 14 | 
            +
                      unless @last_notified_status_id == :connected
         | 
| 15 | 
            +
                        respond ":red_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* is down. An admin will take a look. <@#{config.admins.join(">, <@")}>", config.status_channel
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                  if @channels_id.is_a?(Hash) and @channels_id.keys.include?(config.status_channel)
         | 
| 20 | 
            +
                    is_back = false
         | 
| 21 | 
            +
                    m = ''
         | 
| 22 | 
            +
                    if (Time.now-@last_status_change) > 20 or !defined?(@last_notified_status_id)
         | 
| 23 | 
            +
                      if status_id == :connected
         | 
| 24 | 
            +
                        if defined?(@last_notified_status_id)
         | 
| 25 | 
            +
                          m = ":exclamation: :large_green_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* was not available for #{(Time.now-@last_status_change).round(0)} secs. *Now it is up and running again.*" 
         | 
| 26 | 
            +
                        else
         | 
| 27 | 
            +
                          m = ":large_green_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* is up and running again." 
         | 
| 28 | 
            +
                        end
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                    if status_id == :paused
         | 
| 32 | 
            +
                      m = ":red_circle: #{message} *<##{@channel_id}|#{config.channel}>*"
         | 
| 33 | 
            +
                    elsif status_id == :started
         | 
| 34 | 
            +
                      m = ":large_green_circle: #{message} *<##{@channel_id}|#{config.channel}>*"            
         | 
| 35 | 
            +
                    elsif status_id == :killed or status_id == :exited
         | 
| 36 | 
            +
                      m = ":red_circle: #{message}"
         | 
| 37 | 
            +
                    elsif config.on_master_bot and status_id == :maintenance_on
         | 
| 38 | 
            +
                      m = ":red_circle: The *SmartBot* is on maintenance so not possible to attend any request."
         | 
| 39 | 
            +
                    elsif config.on_master_bot and status_id == :maintenance_off
         | 
| 40 | 
            +
                      m = ":large_green_circle: The *SmartBot* is up and running again."
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                    @last_status_change = Time.now
         | 
| 43 | 
            +
                    @last_notified_status_id = status_id
         | 
| 44 | 
            +
                    unless m == ''
         | 
| 45 | 
            +
                      respond m, config.status_channel
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
             | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            end  
         | 
| @@ -4,6 +4,7 @@ require_relative 'utils/get_bots_created' | |
| 4 4 | 
             
            require_relative 'utils/get_channels_name_and_id'
         | 
| 5 5 | 
             
            require_relative 'utils/get_help'
         | 
| 6 6 | 
             
            require_relative 'utils/get_routines'
         | 
| 7 | 
            +
            require_relative 'utils/get_shares'
         | 
| 7 8 | 
             
            require_relative 'utils/get_rules_imported'
         | 
| 8 9 | 
             
            require_relative 'utils/remove_hash_keys'
         | 
| 9 10 | 
             
            require_relative 'utils/update_bots_file'
         | 
| @@ -15,4 +16,6 @@ require_relative 'utils/get_repls' | |
| 15 16 | 
             
            require_relative 'utils/update_repls'
         | 
| 16 17 | 
             
            require_relative 'utils/answer'
         | 
| 17 18 | 
             
            require_relative 'utils/answer_delete'
         | 
| 19 | 
            +
            require_relative 'utils/has_access'
         | 
| 20 | 
            +
            require_relative 'utils/save_status'
         | 
| 18 21 |  | 
    
        data/lib/slack-smart-bot.rb
    CHANGED
    
    | @@ -43,6 +43,9 @@ class SlackSmartBot | |
| 43 43 | 
             
                config[:allow_access] = Hash.new unless config.key?(:allow_access)
         | 
| 44 44 | 
             
                config[:on_maintenance] = false unless config.key?(:on_maintenance)
         | 
| 45 45 | 
             
                config[:on_maintenance_message] = "Sorry I'm on maintenance so I cannot attend your request." unless config.key?(:on_maintenance_message)
         | 
| 46 | 
            +
                config[:general_message] = "" unless config.key?(:general_message)
         | 
| 47 | 
            +
                config[:logrtm] = false unless config.key?(:logrtm)
         | 
| 48 | 
            +
                config[:status_channel] = 'smartbot-status' unless config.key?(:status_channel)
         | 
| 46 49 |  | 
| 47 50 | 
             
                if config.path.to_s!='' and config.file.to_s==''
         | 
| 48 51 | 
             
                  config.file = File.basename($0)
         | 
| @@ -61,6 +64,8 @@ class SlackSmartBot | |
| 61 64 | 
             
                Dir.mkdir("#{config.path}/logs") unless Dir.exist?("#{config.path}/logs")
         | 
| 62 65 | 
             
                Dir.mkdir("#{config.path}/shortcuts") unless Dir.exist?("#{config.path}/shortcuts")
         | 
| 63 66 | 
             
                Dir.mkdir("#{config.path}/routines") unless Dir.exist?("#{config.path}/routines")
         | 
| 67 | 
            +
                Dir.mkdir("#{config.path}/announcements") unless Dir.exist?("#{config.path}/announcements")
         | 
| 68 | 
            +
                Dir.mkdir("#{config.path}/shares") unless Dir.exist?("#{config.path}/shares")
         | 
| 64 69 | 
             
                File.delete("#{config.path}/config_tmp.status") if File.exist?("#{config.path}/config_tmp.status")
         | 
| 65 70 |  | 
| 66 71 | 
             
                config.masters = MASTER_USERS if config.masters.to_s=='' and defined?(MASTER_USERS)
         | 
| @@ -117,6 +122,7 @@ class SlackSmartBot | |
| 117 122 | 
             
                File.new("#{config.path}/buffer_complete.log", "w") if config[:simulate] and config.on_master_bot
         | 
| 118 123 |  | 
| 119 124 | 
             
                self.config = config
         | 
| 125 | 
            +
                save_status :off, :initializing, "Initializing bot: #{config_log.inspect}"
         | 
| 120 126 |  | 
| 121 127 | 
             
                unless config.simulate and config.key?(:client)
         | 
| 122 128 | 
             
                  Slack.configure do |conf|
         | 
| @@ -128,10 +134,18 @@ class SlackSmartBot | |
| 128 134 | 
             
                while restarts < 200 and !created
         | 
| 129 135 | 
             
                  begin
         | 
| 130 136 | 
             
                    @logger.info "Connecting #{config_log.inspect}"
         | 
| 137 | 
            +
                    save_status :off, :connecting, "Connecting #{config_log.inspect}"
         | 
| 131 138 | 
             
                    if config.simulate and config.key?(:client)
         | 
| 132 139 | 
             
                      self.client = config.client
         | 
| 133 140 | 
             
                    else
         | 
| 134 | 
            -
                       | 
| 141 | 
            +
                      if config.logrtm
         | 
| 142 | 
            +
                        logrtmname = "#{config.path}/logs/rtm_#{config.channel}.log"
         | 
| 143 | 
            +
                        File.delete(logrtmname) if File.exists?(logrtmname)
         | 
| 144 | 
            +
                        @logrtm = Logger.new(logrtmname)
         | 
| 145 | 
            +
                        self.client = Slack::RealTime::Client.new(start_method: :rtm_connect, logger: @logrtm)
         | 
| 146 | 
            +
                      else
         | 
| 147 | 
            +
                        self.client = Slack::RealTime::Client.new(start_method: :rtm_connect)
         | 
| 148 | 
            +
                      end
         | 
| 135 149 | 
             
                    end
         | 
| 136 150 | 
             
                    created = true
         | 
| 137 151 | 
             
                  rescue Exception => e
         | 
| @@ -141,6 +155,8 @@ class SlackSmartBot | |
| 141 155 | 
             
                      @logger.fatal "Rescued on creation: #{e.inspect}"
         | 
| 142 156 | 
             
                      @logger.info "Waiting 60 seconds to retry. restarts: #{restarts}"
         | 
| 143 157 | 
             
                      puts "#{Time.now}: Not able to create client. Waiting 60 seconds to retry: #{config_log.inspect}"
         | 
| 158 | 
            +
                      save_status :off, :waiting, "Not able to create client. Waiting 60 seconds to retry: #{config_log.inspect}"
         | 
| 159 | 
            +
             | 
| 144 160 | 
             
                      sleep 60
         | 
| 145 161 | 
             
                    else
         | 
| 146 162 | 
             
                      exit!
         | 
| @@ -158,6 +174,11 @@ class SlackSmartBot | |
| 158 174 | 
             
                @rules_imported = Hash.new()
         | 
| 159 175 | 
             
                @routines = Hash.new()
         | 
| 160 176 | 
             
                @repls = Hash.new()
         | 
| 177 | 
            +
                @users = Hash.new()
         | 
| 178 | 
            +
                @announcements = Hash.new()
         | 
| 179 | 
            +
                @shares = Hash.new()
         | 
| 180 | 
            +
                @last_status_change = Time.now
         | 
| 181 | 
            +
             | 
| 161 182 |  | 
| 162 183 | 
             
                if File.exist?("#{config.path}/shortcuts/#{config.shortcuts_file}")
         | 
| 163 184 | 
             
                  file_sc = IO.readlines("#{config.path}/shortcuts/#{config.shortcuts_file}").join
         | 
| @@ -180,10 +201,17 @@ class SlackSmartBot | |
| 180 201 | 
             
                  if @bots_created.kind_of?(Hash) and config.start_bots
         | 
| 181 202 | 
             
                    @bots_created.each { |key, value|
         | 
| 182 203 | 
             
                      if !value.key?(:cloud) or (value.key?(:cloud) and value[:cloud] == false)
         | 
| 183 | 
            -
                         | 
| 204 | 
            +
                        if value.key?(:silent) and value.silent!=config.silent
         | 
| 205 | 
            +
                          silent = value.silent
         | 
| 206 | 
            +
                        else
         | 
| 207 | 
            +
                          silent = config.silent
         | 
| 208 | 
            +
                        end
         | 
| 209 | 
            +
                        @logger.info "BOT_SILENT=#{silent} ruby #{config.file_path} \"#{value[:channel_name]}\" \"#{value[:admins]}\" \"#{value[:rules_file]}\" #{value[:status].to_sym}"
         | 
| 184 210 | 
             
                        puts "Starting #{value[:channel_name]} Smart Bot"
         | 
| 211 | 
            +
                        save_status :off, :starting, "Starting #{value[:channel_name]} Smart Bot"
         | 
| 212 | 
            +
             | 
| 185 213 | 
             
                        t = Thread.new do
         | 
| 186 | 
            -
                          `ruby #{config.file_path} \"#{value[:channel_name]}\" \"#{value[:admins]}\" \"#{value[:rules_file]}\" #{value[:status].to_sym}`
         | 
| 214 | 
            +
                          `BOT_SILENT=#{silent} ruby #{config.file_path} \"#{value[:channel_name]}\" \"#{value[:admins]}\" \"#{value[:rules_file]}\" #{value[:status].to_sym}`
         | 
| 187 215 | 
             
                        end
         | 
| 188 216 | 
             
                        value[:thread] = t
         | 
| 189 217 | 
             
                        sleep value[:admins].size
         | 
| @@ -191,6 +219,12 @@ class SlackSmartBot | |
| 191 219 | 
             
                    }
         | 
| 192 220 | 
             
                  end
         | 
| 193 221 | 
             
                end
         | 
| 222 | 
            +
                general_rules_file = "/rules/general_rules.rb"
         | 
| 223 | 
            +
                general_commands_file = "/rules/general_commands.rb"
         | 
| 224 | 
            +
                default_general_rules = (__FILE__).gsub(/\/slack-smart-bot\.rb$/, "/slack-smart-bot_general_rules.rb")
         | 
| 225 | 
            +
                default_general_commands = (__FILE__).gsub(/\/slack-smart-bot\.rb$/, "/slack-smart-bot_general_commands.rb")
         | 
| 226 | 
            +
                FileUtils.copy_file(default_general_rules, config.path + general_rules_file) unless File.exist?(config.path + general_rules_file)
         | 
| 227 | 
            +
                FileUtils.copy_file(default_general_commands, config.path + general_commands_file) unless File.exist?(config.path + general_commands_file)
         | 
| 194 228 |  | 
| 195 229 | 
             
                get_rules_imported()
         | 
| 196 230 |  | 
| @@ -213,9 +247,11 @@ class SlackSmartBot | |
| 213 247 | 
             
                  end
         | 
| 214 248 | 
             
                rescue Slack::Web::Api::Errors::TooManyRequestsError
         | 
| 215 249 | 
             
                  @logger.fatal "TooManyRequestsError"
         | 
| 250 | 
            +
                  save_status :off, :TooManyRequestsError, "TooManyRequestsError please re run the bot and be sure of executing first: killall ruby"
         | 
| 216 251 | 
             
                  abort("TooManyRequestsError please re run the bot and be sure of executing first: killall ruby")
         | 
| 217 252 | 
             
                rescue Exception => stack
         | 
| 218 253 | 
             
                  pp stack if config.testing
         | 
| 254 | 
            +
                  save_status :off, :wrong_admin_user, "The admin user specified on settings: #{config.admins.join(", ")}, doesn't exist on Slack. Execution aborted"
         | 
| 219 255 | 
             
                  abort("The admin user specified on settings: #{config.admins.join(", ")}, doesn't exist on Slack. Execution aborted")
         | 
| 220 256 | 
             
                end
         | 
| 221 257 |  | 
| @@ -231,6 +267,7 @@ class SlackSmartBot | |
| 231 267 | 
             
                @questions = Hash.new()
         | 
| 232 268 | 
             
                @answer = Hash.new()
         | 
| 233 269 | 
             
                @repl_sessions = Hash.new()
         | 
| 270 | 
            +
                @datetime_general_commands = 0
         | 
| 234 271 | 
             
                @channels_id = Hash.new()
         | 
| 235 272 | 
             
                @channels_name = Hash.new()
         | 
| 236 273 | 
             
                get_channels_name_and_id()
         | 
| @@ -239,6 +276,8 @@ class SlackSmartBot | |
| 239 276 |  | 
| 240 277 | 
             
                get_routines()
         | 
| 241 278 | 
             
                get_repls()
         | 
| 279 | 
            +
                get_shares()
         | 
| 280 | 
            +
             | 
| 242 281 | 
             
                if @routines.key?(@channel_id)
         | 
| 243 282 | 
             
                  @routines[@channel_id].each do |k, v|
         | 
| 244 283 | 
             
                    @routines[@channel_id][k][:running] = false
         | 
| @@ -250,7 +289,7 @@ class SlackSmartBot | |
| 250 289 | 
             
                  @routines.each do |ch, rout|
         | 
| 251 290 | 
             
                    rout.each do |k, v|
         | 
| 252 291 | 
             
                      if !v[:running] and v[:channel_name] == config.channel
         | 
| 253 | 
            -
                        create_routine_thread(k)
         | 
| 292 | 
            +
                        create_routine_thread(k, v)
         | 
| 254 293 | 
             
                      end
         | 
| 255 294 | 
             
                    end
         | 
| 256 295 | 
             
                  end
         | 
| @@ -259,12 +298,14 @@ class SlackSmartBot | |
| 259 298 | 
             
                    m = "Connection closing, exiting. #{Time.now}"
         | 
| 260 299 | 
             
                    @logger.info m
         | 
| 261 300 | 
             
                    @logger.info _data
         | 
| 301 | 
            +
                    #save_status :off, :closing, "Connection closing, exiting." #todo: don't notify for the moment, remove when checked
         | 
| 262 302 | 
             
                  end
         | 
| 263 303 |  | 
| 264 304 | 
             
                  client.on :closed do |_data|
         | 
| 265 305 | 
             
                    m = "Connection has been disconnected. #{Time.now}"
         | 
| 266 306 | 
             
                    @logger.info m
         | 
| 267 307 | 
             
                    @logger.info _data
         | 
| 308 | 
            +
                    save_status :off, :disconnected, "Connection has been disconnected."
         | 
| 268 309 | 
             
                  end
         | 
| 269 310 | 
             
                end
         | 
| 270 311 | 
             
                self
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # 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 | 
            +
            def general_commands(user, command, dest, files = [])
         | 
| 3 | 
            +
                
         | 
| 4 | 
            +
              begin
         | 
| 5 | 
            +
                case command
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    # help: ----------------------------------------------
         | 
| 8 | 
            +
                    # help: `cls`
         | 
| 9 | 
            +
                    # help: `clear`
         | 
| 10 | 
            +
                    # help: `clear screen`
         | 
| 11 | 
            +
                    # help: `NUMBER cls`
         | 
| 12 | 
            +
                    # help:     It will send a big empty message.
         | 
| 13 | 
            +
                    # help:        NUMBER (optional): number of lines. Default 100. Max 200.
         | 
| 14 | 
            +
                    # help: command_id: :cls
         | 
| 15 | 
            +
                    # help: 
         | 
| 16 | 
            +
                when /\A\s*(\d*)\s*(clear|cls|clear\s+screen)\s*\z/i
         | 
| 17 | 
            +
                  save_stats :cls
         | 
| 18 | 
            +
                  $1.to_s == '' ? lines = 100 : lines = $1.to_i
         | 
| 19 | 
            +
                  lines = 200 if lines > 200
         | 
| 20 | 
            +
                  respond (">#{"\n"*lines}<")
         | 
| 21 | 
            +
             | 
| 22 | 
            +
             | 
| 23 | 
            +
                  # this is a hidden command that it is not listed when calling bot help
         | 
| 24 | 
            +
                when /\A\s*(that's\s+)?(thanks|thank\s+you|I\s+love\s+you|nice|cool)\s+(#{@salutations.join("|")})\s*!*\s*$/i
         | 
| 25 | 
            +
                  save_stats :thanks
         | 
| 26 | 
            +
                  reactions = [:heart, :heart_eyes, :blush, :relaxed, :simple_smile, :smiley, :two_hearts, :heartbeat, :green_heart ]
         | 
| 27 | 
            +
                  reactions.sample(rand(3)+1).each {|rt| react rt }
         | 
| 28 | 
            +
                  responses = ['Thank YOU', "You're welcome", "You're very welcome", 'No problem', 'No worries', "Don't mention it", 'My pleasure', 
         | 
| 29 | 
            +
                    '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",
         | 
| 30 | 
            +
                    'Það var ekkert', 'De nada', 'No hay de qué', 'De rien',  'Bitte', 'Prego', 'मेरा सौभाग्य है', '不客氣', 'Παρακαλώ']
         | 
| 31 | 
            +
                  respond "#{responses.sample}#{'!'*rand(4)}"
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                else
         | 
| 34 | 
            +
                  return false
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
                return true
         | 
| 37 | 
            +
              rescue => exception
         | 
| 38 | 
            +
                if defined?(@logger)
         | 
| 39 | 
            +
                  @logger.fatal exception
         | 
| 40 | 
            +
                  respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
         | 
| 41 | 
            +
                else
         | 
| 42 | 
            +
                  puts exception
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                return false
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -13,7 +13,9 @@ def general_rules(user, command, processed, dest, files = [], rules_file = "") | |
| 13 13 | 
             
                    # help:  Examples:
         | 
| 14 14 | 
             
                    # help:     _echo I am the Smart Bot_
         | 
| 15 15 | 
             
                    # help:     _100 echo :heart:_
         | 
| 16 | 
            -
             | 
| 16 | 
            +
                    # help: command_id: :echo
         | 
| 17 | 
            +
                    # help:        
         | 
| 18 | 
            +
                  when /\A\s*(\d*)\s*echo\s(.+)/i
         | 
| 17 19 | 
             
                    save_stats :echo
         | 
| 18 20 | 
             
                    $1.to_s == '' ? times = 1 : times = $1.to_i
         | 
| 19 21 | 
             
                    respond ($2*times).to_s
         | 
| @@ -25,9 +27,10 @@ def general_rules(user, command, processed, dest, files = [], rules_file = "") | |
| 25 27 | 
             
                rescue => exception
         | 
| 26 28 | 
             
                  if defined?(@logger)
         | 
| 27 29 | 
             
                    @logger.fatal exception
         | 
| 28 | 
            -
                    respond "Unexpected error!! Please contact an admin to solve it: <@#{ | 
| 30 | 
            +
                    respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
         | 
| 29 31 | 
             
                  else
         | 
| 30 32 | 
             
                    puts exception
         | 
| 31 33 | 
             
                  end
         | 
| 34 | 
            +
                  return false
         | 
| 32 35 | 
             
                end
         | 
| 33 36 | 
             
            end
         | 
| @@ -40,15 +40,18 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 40 40 |  | 
| 41 41 | 
             
              load "#{config.path}/rules/general_rules.rb"
         | 
| 42 42 |  | 
| 43 | 
            -
               | 
| 43 | 
            +
              if general_rules(user, command, processed, dest, files, rules_file)
         | 
| 44 | 
            +
                return true
         | 
| 45 | 
            +
              else
         | 
| 44 46 | 
             
                begin
         | 
| 45 47 | 
             
                  case command
         | 
| 46 48 |  | 
| 47 49 | 
             
                    # help: ----------------------------------------------
         | 
| 48 50 | 
             
                    # help: `go to sleep`
         | 
| 49 51 | 
             
                    # help:   it will sleep the bot for 5 seconds
         | 
| 52 | 
            +
                    # help: command_id: :go_to_sleep
         | 
| 50 53 | 
             
                    # help:
         | 
| 51 | 
            -
                  when  | 
| 54 | 
            +
                  when /\A\s*go\sto\ssleep/i
         | 
| 52 55 | 
             
                    save_stats :go_to_sleep
         | 
| 53 56 | 
             
                    if answer.empty?
         | 
| 54 57 | 
             
                      ask "do you want me to take a siesta?"
         | 
| @@ -74,32 +77,41 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 74 77 | 
             
                    # help: ----------------------------------------------
         | 
| 75 78 | 
             
                    # help: `run something`
         | 
| 76 79 | 
             
                    # help:   It will run the process and report the results when done
         | 
| 80 | 
            +
                    # help: command_id: :run_something
         | 
| 77 81 | 
             
                    # help:
         | 
| 78 | 
            -
                  when  | 
| 82 | 
            +
                  when /\Arun something/i
         | 
| 79 83 | 
             
                    save_stats :run_something
         | 
| 80 | 
            -
                     | 
| 84 | 
            +
                    if has_access?(:run_something, user)
         | 
| 85 | 
            +
                      react :runner
         | 
| 81 86 |  | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 87 | 
            +
                      process_to_run = "ruby -v"
         | 
| 88 | 
            +
                      process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
         | 
| 89 | 
            +
                      stdout, stderr, status = Open3.capture3(process_to_run)
         | 
| 90 | 
            +
                      unreact :runner
         | 
| 91 | 
            +
                      if stderr == ""
         | 
| 92 | 
            +
                        if stdout == ""
         | 
| 93 | 
            +
                          respond "#{display_name}: Nothing returned."
         | 
| 94 | 
            +
                        else
         | 
| 95 | 
            +
                          respond "#{display_name}: #{stdout}"
         | 
| 96 | 
            +
                        end
         | 
| 89 97 | 
             
                      else
         | 
| 90 | 
            -
                        respond "#{display_name}: #{stdout}"
         | 
| 98 | 
            +
                        respond "#{display_name}: #{stdout} #{stderr}"
         | 
| 91 99 | 
             
                      end
         | 
| 92 | 
            -
                    else
         | 
| 93 | 
            -
                      respond "#{display_name}: #{stdout} #{stderr}"
         | 
| 94 100 | 
             
                    end
         | 
| 95 101 |  | 
| 96 102 | 
             
                    # Emoticons you can use with `react` command https://www.webfx.com/tools/emoji-cheat-sheet/
         | 
| 97 103 |  | 
| 98 | 
            -
                    # Examples for respond and respond_direct
         | 
| 104 | 
            +
                    # Examples for respond, respond_thread and respond_direct
         | 
| 99 105 | 
             
                    #   # send 'the message' to the channel or direct message where the command was written
         | 
| 100 106 | 
             
                    #   respond "the message"
         | 
| 101 107 | 
             
                    #   # send 'the message' privately as a direct message to the user that sent the command
         | 
| 102 108 | 
             
                    #   respond_direct "the message"
         | 
| 109 | 
            +
                    #   # same thing can be done:
         | 
| 110 | 
            +
                    #   respond "the message", :direct
         | 
| 111 | 
            +
                    #   # send 'the message' opening a thread
         | 
| 112 | 
            +
                    #   respond_thread "the message"
         | 
| 113 | 
            +
                    #   # same thing can be done:
         | 
| 114 | 
            +
                    #   respond 'the message', :on_thread
         | 
| 103 115 | 
             
                    #   # send 'the message' to a specific channel name
         | 
| 104 116 | 
             
                    #   respond "the message", 'my_channel'
         | 
| 105 117 | 
             
                    #   # send 'the message' to a specific channel id
         | 
| @@ -109,6 +121,19 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 109 121 | 
             
                    #   # send 'the message' to a specific user id as direct message
         | 
| 110 122 | 
             
                    #   respond "the message", 'US3344D3'
         | 
| 111 123 |  | 
| 124 | 
            +
                    # Example sending blocks https://api.slack.com/block-kit
         | 
| 125 | 
            +
                    # my_blocks = [
         | 
| 126 | 
            +
                    #   { type: "context",
         | 
| 127 | 
            +
                    #     elements:
         | 
| 128 | 
            +
                    #       [
         | 
| 129 | 
            +
                    #         { type: "plain_text", :text=>"\tInfo: " },
         | 
| 130 | 
            +
                    #         { type: "image", image_url: "https://avatars.slack-edge.com/2021-03-23/182815_e54abb1dd_24.jpg", alt_text: "mario" },
         | 
| 131 | 
            +
                    #         { type: "mrkdwn", text: " *Mario Ruiz* (marior)  " }
         | 
| 132 | 
            +
                    #       ]
         | 
| 133 | 
            +
                    #   }
         | 
| 134 | 
            +
                    # ]
         | 
| 135 | 
            +
                    # respond blocks: my_blocks
         | 
| 136 | 
            +
             | 
| 112 137 | 
             
                    # Example downloading a file from slack
         | 
| 113 138 | 
             
                    #  if !files.nil? and files.size == 1 and files[0].filetype == 'yaml'
         | 
| 114 139 | 
             
                    #    require 'nice_http'
         | 
| @@ -120,16 +145,17 @@ def rules(user, command, processed, dest, files = [], rules_file = "") | |
| 120 145 | 
             
                    #   send_file(to, msg, filepath, title, format, type = "text")
         | 
| 121 146 | 
             
                    #   send_file(dest, 'the message', "#{project_folder}/temp/logs_ptBI.log", 'title', 'text/plain', "text")
         | 
| 122 147 | 
             
                    #   send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'title', 'image/jpeg', "jpg")
         | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 148 | 
             
                  else
         | 
| 126 149 | 
             
                    unless processed
         | 
| 127 150 | 
             
                      dont_understand()
         | 
| 128 151 | 
             
                    end
         | 
| 152 | 
            +
                    return false
         | 
| 129 153 | 
             
                  end
         | 
| 154 | 
            +
                  return true
         | 
| 130 155 | 
             
                rescue => exception
         | 
| 131 156 | 
             
                  @logger.fatal exception
         | 
| 132 157 | 
             
                  respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
         | 
| 158 | 
            +
                  return false
         | 
| 133 159 | 
             
                end
         | 
| 134 160 | 
             
              end
         | 
| 135 161 | 
             
            end
         | 
    
        data/whats_new.txt
    CHANGED
    
    | @@ -1,24 +1,36 @@ | |
| 1 | 
            -
            *Version 1. | 
| 1 | 
            +
            *Version 1.10.0* Released 2021-Sep-17
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 3 | 
            +
            *For General users*
         | 
| 4 | 
            +
            - When on a private conversation with the SmartBot (DM) and not using any channels rule on the conversation, the general_rules will be available.
         | 
| 5 | 
            +
            - On DM with the SmartBot if you want to use a rule from a specific channel you can use also: `#CHANNEL RULE` or `on #CHANNEL RULE`. For example: `#sales get report for India` 
         | 
| 6 | 
            +
            - Now when using general commands, the SmartBot will be responding on any channel where is a member, even though is not listening to you. For example: `clear screen`
         | 
| 7 | 
            +
            - Added command `suggest command` that will return the help content for a random command.
         | 
| 8 | 
            +
            - New command `leaderboard` returns useful information about the use of the SmartBot.
         | 
| 9 | 
            +
            - `add COLOR announcement MESSAGE`, `add EMOJI announcement MESSAGE` command stores the message on the announcement list labeled with the color/emoji specified, white by default. Aliases for announcement: statement, declaration, message. Related: `see announcements`, `delete announcement id`
         | 
| 10 | 
            +
            - `hi bot` and `bye bot` can be called from any channel where the SmartBot is a member.
         | 
| 11 | 
            +
            - Added general command `see statuses`, `who is on vacation?`, `who is not on vacation?`
         | 
| 12 | 
            +
            - New general command `see favorite commands`. It will display the favorite commands in that channel. 
         | 
| 13 | 
            +
            - Now when running the `ruby` command it can be supplied a code block.
         | 
| 14 | 
            +
            - New general command `share messages /REGEXP/ on #CHANNEL`, `share messages "TEXT" on #CHANNEL`, `see shares', `delete share ID`. It will automatically share new messages published that meet the specified criteria.
         | 
| 6 15 |  | 
| 7 | 
            -
            * | 
| 16 | 
            +
            *For Admin users*
         | 
| 17 | 
            +
            - respond_thread method will send the respond creating a thread if necessary. It can be used also `respond 'msg', :on_thread`
         | 
| 18 | 
            +
            - `respond 'msg', :direct` will send a direct message to the person that is executing the rule.
         | 
| 19 | 
            +
            - You can add general commands that will be responding on any channel where the Smart Bot is a member even though is not 'listening to you'. Add them to '/rules/general_commands.rb
         | 
| 20 | 
            +
            - when using `respond` you can supply two options: unfurl_links and unfurl_media. By default is a boolean: true
         | 
| 21 | 
            +
            - added option 'weekdays' and 'weekends' for `create routine` command, for example: `add silent routine suggestions on weekdays at 09:00 suggest command`
         | 
| 22 | 
            +
            - Added a new config for the SmartBot to log all RTM communication, admits `true` or `false`, by default `false`: `logrtm`
         | 
| 23 | 
            +
            - Use the command `send message to` and `react to` to impersonate the SmartBot. Only accessible for Master Admins on a DM with the SmartBot.
         | 
| 24 | 
            +
            - New command to see the result of the last run of a routine: `see result routine NAME`
         | 
| 25 | 
            +
            - Now it is possible to create *bgroutine* then the results of the routine run won't be published.
         | 
| 26 | 
            +
            - To display a general message after every command use: `set general message MESSAGE`. Use `set general message off` to stop displaying it.
         | 
| 27 | 
            +
            - When adding a general message is possible to use interpolation
         | 
| 28 | 
            +
            - If you are a master admin and you are on master channel then you can call `publish announcements` that will publish the announcements on all channels. The messages stored on a DM won't be published. This is very convenient to be called from a *Routine* for example every weekday at 09:00.
         | 
| 29 | 
            +
            - Now it is possible to send blocks `respond blocks: my_blocks`. More info about blocks: https://api.slack.com/block-kit
         | 
| 30 | 
            +
            - When using bgroutines if we want to avoid a file to be sent: 
         | 
| 31 | 
            +
                    send_file(dest, 'description', "file_path", 'desc', 'text/plain', "text") unless Thread.current[:routine_type] == 'bgroutine'
         | 
| 32 | 
            +
            - SmartBot will notify about SmartBot status changes if defined the status_channel in config file and the channel exists. By default: smartbot-status
         | 
| 8 33 |  | 
| 9 | 
            -
            *For General users*
         | 
| 10 | 
            -
            - Added command `what's new` that will show this.
         | 
| 11 | 
            -
            - `bot stats` will return detailed statistics using the SmartBot. If you call it from a DM with the SmartBot you will see all stats for all Bot channels.
         | 
| 12 | 
            -
            - Possible to create 'global' shortcuts that will be available on any SmartBot Channel.
         | 
| 13 | 
            -
            - Added option to start a `repl` without pre-executing '.smart-bot-repl' source code in case exists. Just add `clean` before the `repl` command. For example: `clean repl Example`
         | 
| 14 | 
            -
            - When using `Ruby` command in case the process doesn't finish in 20 seconds will be aborted.
         | 
| 15 | 
            -
            - When creating rules/commands and asking a question now you can use 'answer' instead of '@questions'. Take a look at README.md for an example.
         | 
| 16 | 
            -
            - Using external calls, it is possible to send to more than one bot channel the same rule: `@smart-bot on #channel1 #channel2 #channel3 echo Lala`
         | 
| 17 | 
            -
            - `bot help` and `bot rules` return by default a short version of the commands. Call `bot help expanded` or `bot rules expanded` to get a full desciption of the commands.
         | 
| 18 | 
            -
            - It is possible to exclude routines from results when using `bot stats`
         | 
| 19 34 | 
             
            ------------------------------
         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
            - Bot Stats. Now the routines are displayed as routine/USER
         | 
| 23 | 
            -
            - When creating routines now it is possible to publish in a different channel: `add routine run_tests at 17:05 #thechannel !run api tests`
         | 
| 24 | 
            -
            - `Turn maintenance on/off` command available
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            *Previous*: <https://github.com/MarioRuiz/slack-smart-bot/blob/dd23939f93ee95aca3c04d33cd1ce197d6efbd37/whats_new.txt|1.9.0>
         |