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
| @@ -3,14 +3,12 @@ class SlackSmartBot | |
| 3 3 | 
             
              # helpadmin: `bot status`
         | 
| 4 4 | 
             
              # helpadmin:    Displays the status of the bot
         | 
| 5 5 | 
             
              # helpadmin:    If on master channel and admin user also it will display info about bots created
         | 
| 6 | 
            +
              # helpadmin:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
         | 
| 6 7 | 
             
              # helpadmin:
         | 
| 7 8 | 
             
              def bot_status(dest, user)
         | 
| 8 9 | 
             
                save_stats(__method__)
         | 
| 9 10 | 
             
                get_bots_created()
         | 
| 10 | 
            -
                if  | 
| 11 | 
            -
                  (!user.key?(:enterprise_user) or ( user.key?(:enterprise_user) and !config[:allow_access][__method__].include?(user[:enterprise_user].id)))
         | 
| 12 | 
            -
                  respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
         | 
| 13 | 
            -
                else
         | 
| 11 | 
            +
                if has_access?(__method__, user)
         | 
| 14 12 | 
             
                  gems_remote = `gem list slack-smart-bot --remote`
         | 
| 15 13 | 
             
                  version_remote = gems_remote.to_s().scan(/slack-smart-bot \((\d+\.\d+\.\d+)/).join
         | 
| 16 14 | 
             
                  version_message = ""
         | 
| @@ -1,12 +1,5 @@ | |
| 1 1 | 
             
            class SlackSmartBot
         | 
| 2 2 |  | 
| 3 | 
            -
              # help: ----------------------------------------------
         | 
| 4 | 
            -
              # help: `Bye Bot`
         | 
| 5 | 
            -
              # help: `Bye Smart`
         | 
| 6 | 
            -
              # help: `Bye NAME_OF_THE_BOT`
         | 
| 7 | 
            -
              # help:    Bot stops listening to you
         | 
| 8 | 
            -
              # help:    Also apart of Bye you can use _Bæ, Good Bye, Adiós, Ciao, Bless, Bless Bless, Adeu_
         | 
| 9 | 
            -
              # help:
         | 
| 10 3 | 
             
              def bye_bot(dest, from, display_name)
         | 
| 11 4 | 
             
                if @status == :on
         | 
| 12 5 | 
             
                  save_stats(__method__)
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def delete_announcement(user, message_id)
         | 
| 4 | 
            +
                save_stats(__method__)
         | 
| 5 | 
            +
                if has_access?(__method__, user)
         | 
| 6 | 
            +
                  if Thread.current[:typem] == :on_call
         | 
| 7 | 
            +
                    channel = Thread.current[:dchannel]
         | 
| 8 | 
            +
                  else
         | 
| 9 | 
            +
                    channel = Thread.current[:dest]
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                  if File.exists?("#{config.path}/announcements/#{channel}.csv") and !@announcements.key?(channel)
         | 
| 12 | 
            +
                    t = CSV.table("#{config.path}/announcements/#{channel}.csv", headers: ['message_id', 'user_deleted', 'user_created', 'date', 'time', 'type', 'message'])
         | 
| 13 | 
            +
                    @announcements[channel] = t
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  found = false
         | 
| 16 | 
            +
                  message = ''
         | 
| 17 | 
            +
                  if @announcements.key?(channel) and @announcements[channel][:message_id].include?(message_id.to_i)
         | 
| 18 | 
            +
                    CSV.open("#{config.path}/announcements/#{channel}.csv", "w") do |csv|
         | 
| 19 | 
            +
                      @announcements[channel].each do |row|
         | 
| 20 | 
            +
                        if row[:message_id].to_i == message_id.to_i
         | 
| 21 | 
            +
                          message = row[:message]
         | 
| 22 | 
            +
                          row[:user_deleted] = user.name
         | 
| 23 | 
            +
                        end    
         | 
| 24 | 
            +
                        csv << row
         | 
| 25 | 
            +
                      end
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                    respond "The announcement has been deleted: #{message}"
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    respond "Sorry but I didn't find the message id #{message_id}. Call `see announcements` to see the ids."
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def delete_share(user, share_id)
         | 
| 4 | 
            +
                save_stats(__method__)
         | 
| 5 | 
            +
                if has_access?(__method__, user)
         | 
| 6 | 
            +
                  if Thread.current[:typem] == :on_call
         | 
| 7 | 
            +
                    channel = Thread.current[:dchannel]
         | 
| 8 | 
            +
                  else
         | 
| 9 | 
            +
                    channel = Thread.current[:dest]
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                  if File.exists?("#{config.path}/shares/#{@channels_name[channel]}.csv") and !@shares.key?(@channels_name[channel])
         | 
| 12 | 
            +
                    t = CSV.table("#{config.path}/shares/#{@channels_name[channel]}.csv", headers: ['share_id', 'user_deleted', 'user_created', 'date', 'time', 'type', 'to_channel', 'condition'])
         | 
| 13 | 
            +
                    @shares[@channels_name[channel]] = t
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  found = false
         | 
| 16 | 
            +
                  message = ''
         | 
| 17 | 
            +
                  if @shares[@channels_name[channel]][:share_id].include?(share_id.to_i)
         | 
| 18 | 
            +
                    CSV.open("#{config.path}/shares/#{@channels_name[channel]}.csv", "w") do |csv|
         | 
| 19 | 
            +
                      @shares[@channels_name[channel]].each do |row|
         | 
| 20 | 
            +
                        if row[:share_id].to_i == share_id.to_i
         | 
| 21 | 
            +
                          message = row[:condition]
         | 
| 22 | 
            +
                          row[:user_deleted] = user.name
         | 
| 23 | 
            +
                        end    
         | 
| 24 | 
            +
                        csv << row
         | 
| 25 | 
            +
                      end
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                    respond "The share has been deleted: #{message}"
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    respond "Sorry but I didn't find the share id #{share_id}. Call `see shares` to see all the ids."
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -1,21 +1,26 @@ | |
| 1 1 | 
             
            class SlackSmartBot
         | 
| 2 2 |  | 
| 3 | 
            -
               | 
| 4 | 
            -
              # help: `Hi Bot`
         | 
| 5 | 
            -
              # help: `Hi Smart`
         | 
| 6 | 
            -
              # help: `Hello Bot` `Hola Bot` `Hallo Bot` `What's up Bot` `Hey Bot` `Hæ Bot`
         | 
| 7 | 
            -
              # help: `Hello THE_NAME_OF_THE_BOT`
         | 
| 8 | 
            -
              # help:    Bot starts listening to you
         | 
| 9 | 
            -
              # help:    After that if you want to avoid a single message to be treated by the smart bot, start the message by -
         | 
| 10 | 
            -
              # help:    Also apart of Hello you can use _Hallo, Hi, Hola, What's up, Hey, Hæ_
         | 
| 11 | 
            -
              # help:
         | 
| 12 | 
            -
              def hi_bot(user, dest, dchannel, from, display_name)
         | 
| 3 | 
            +
              def hi_bot(user, dest, from, display_name)
         | 
| 13 4 | 
             
                if @status == :on
         | 
| 14 5 | 
             
                  save_stats(__method__)
         | 
| 15 6 | 
             
                  greetings = ["Hello", "Hallo", "Hi", "Hola", "What's up", "Hey", "Hæ"].sample
         | 
| 16 7 | 
             
                  respond "#{greetings} #{display_name}", dest
         | 
| 8 | 
            +
                  if Thread.current[:typem] == :on_pub or Thread.current[:typem] == :on_pg
         | 
| 9 | 
            +
                    respond "You are on a channel where the SmartBot is just a member. You can only run general bot commands.\nCall `bot help` to see the commands you can use."
         | 
| 10 | 
            +
                  elsif Thread.current[:typem] == :on_extended
         | 
| 11 | 
            +
                    message = ["You are on an extended channel from <##{@channel_id}> so you can use all specific commands from that channel just adding !, !! or ^ before the command."]
         | 
| 12 | 
            +
                    message << "Call `bot help` to see the commands you can use."
         | 
| 13 | 
            +
                    respond message.join("\n")
         | 
| 14 | 
            +
                  elsif Thread.current[:typem] == :on_dm and Thread.current[:using_channel] == ''
         | 
| 15 | 
            +
                    respond "To start using the rules from a Bot channel call `use #CHANNEL`.\nAvailable SmartBots: <##{@bots_created.keys.join('>, <#')}>\nIf you want to call just one command from a specific channel: `#CHANNEL COMMAND`"
         | 
| 16 | 
            +
                  else
         | 
| 17 | 
            +
                    respond "You are on <##{@channel_id}> SmartBot channel. Call `bot help` to see all commands you can use or `bot rules` just to see the specific commands for this Bot channel."
         | 
| 18 | 
            +
                  end
         | 
| 17 19 | 
             
                  if Thread.current[:using_channel]!=''
         | 
| 18 | 
            -
                     | 
| 20 | 
            +
                    message = ["You are using rules from <##{Thread.current[:using_channel]}>"]
         | 
| 21 | 
            +
                    message << "If you want to change bot channel rules call `use #CHANNEL` or `stop using rules from <##{Thread.current[:using_channel]}>` to stop using rules from this channel."
         | 
| 22 | 
            +
                    message << "You can call a command from any other channel by calling `#CHANNEL COMMAND`" if Thread.current[:typem] == :on_dm
         | 
| 23 | 
            +
                    respond message.join("\n")
         | 
| 19 24 | 
             
                  end
         | 
| 20 25 | 
             
                  @listening[from] = {} unless @listening.key?(from)
         | 
| 21 26 | 
             
                  if Thread.current[:on_thread]
         | 
| @@ -0,0 +1,200 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
                # help: ----------------------------------------------
         | 
| 3 | 
            +
                # help: `leaderboard`
         | 
| 4 | 
            +
                # help: `ranking`
         | 
| 5 | 
            +
                # help: `podium`
         | 
| 6 | 
            +
                # help: `leaderboard from YYYY/MM/DD`
         | 
| 7 | 
            +
                # help: `leaderboard from YYYY/MM/DD to YYYY/MM/DD`
         | 
| 8 | 
            +
                # help: `leaderboard PERIOD`
         | 
| 9 | 
            +
                # help:    It will present some useful information about the use of the SmartBot in the period specified.
         | 
| 10 | 
            +
                # help:    If no 'from' and 'to' specified then it will be considered 'last week'
         | 
| 11 | 
            +
                # help:    PERIOD: today, yesterday, last week, this week, last month, this month, last year, this year
         | 
| 12 | 
            +
                # help:    The results will exclude master admins and routines.
         | 
| 13 | 
            +
                # help:    For a more detailed data use the command `bot stats`
         | 
| 14 | 
            +
                # help:    Examples:
         | 
| 15 | 
            +
                # help:      _leaderboard_
         | 
| 16 | 
            +
                # help:      _podium from 2021/05/01_
         | 
| 17 | 
            +
                # help:      _leaderboard from 2021/05/01 to 2021/05/31_
         | 
| 18 | 
            +
                # help:      _ranking today_
         | 
| 19 | 
            +
                # help:    <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
         | 
| 20 | 
            +
                # help: 
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                def leaderboard(from, to, period)
         | 
| 23 | 
            +
                    exclude_masters = true
         | 
| 24 | 
            +
                    exclude_routines = true
         | 
| 25 | 
            +
                    require 'csv'
         | 
| 26 | 
            +
                    if config.stats
         | 
| 27 | 
            +
                        message = []
         | 
| 28 | 
            +
                    else
         | 
| 29 | 
            +
                        message = ["You need to set stats to true to generate the stats when running the bot instance."]
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                    save_stats(__method__)
         | 
| 32 | 
            +
                    if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
         | 
| 33 | 
            +
                        message<<'No stats'
         | 
| 34 | 
            +
                    else
         | 
| 35 | 
            +
                        if period == ''
         | 
| 36 | 
            +
                            message << "*Leaderboard SmartBot <##@channel_id> from #{from} to #{to}*\n"
         | 
| 37 | 
            +
                        else
         | 
| 38 | 
            +
                            message << "*Leaderboard SmartBot <##@channel_id> #{period}* (#{from} -> #{to})\n"
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                        from_short = from
         | 
| 41 | 
            +
                        to_short = to
         | 
| 42 | 
            +
                        from_file = from[0..3] + '-' + from[5..6]
         | 
| 43 | 
            +
                        to_file = to[0..3] + '-' + to[5..6]
         | 
| 44 | 
            +
                        from+= " 00:00:00 +0000"
         | 
| 45 | 
            +
                        to+= " 23:59:59 +0000"
         | 
| 46 | 
            +
                        rows = []
         | 
| 47 | 
            +
                        users_id_name = {}
         | 
| 48 | 
            +
                        users_name_id = {}
         | 
| 49 | 
            +
                        count_users = {}
         | 
| 50 | 
            +
                        count_channels_dest = {}
         | 
| 51 | 
            +
                        count_commands_uniq_user = {}
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                        # to translate global and enterprise users since sometimes was returning different names/ids
         | 
| 54 | 
            +
                        if from[0..3]=='2020' # this was an issue only on that period
         | 
| 55 | 
            +
                            Dir["#{config.stats_path}.*.log"].sort.each do |file|
         | 
| 56 | 
            +
                                if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
         | 
| 57 | 
            +
                                    CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
         | 
| 58 | 
            +
                                        unless users_id_name.key?(row[:user_id])
         | 
| 59 | 
            +
                                            users_id_name[row[:user_id]] = row[:user_name]
         | 
| 60 | 
            +
                                        end
         | 
| 61 | 
            +
                                        unless users_name_id.key?(row[:user_name])
         | 
| 62 | 
            +
                                            users_name_id[row[:user_name]] = row[:user_id]
         | 
| 63 | 
            +
                                        end
         | 
| 64 | 
            +
                
         | 
| 65 | 
            +
                                    end
         | 
| 66 | 
            +
                                end
         | 
| 67 | 
            +
                            end
         | 
| 68 | 
            +
                        end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                        master_admins = config.masters.dup
         | 
| 71 | 
            +
                        if users_id_name.size > 0
         | 
| 72 | 
            +
                            config.masters.each do |u|
         | 
| 73 | 
            +
                                if users_id_name.key?(u)
         | 
| 74 | 
            +
                                    master_admins << users_id_name[u]
         | 
| 75 | 
            +
                                elsif users_name_id.key?(u)
         | 
| 76 | 
            +
                                    master_admins << users_name_id[u]
         | 
| 77 | 
            +
                                end
         | 
| 78 | 
            +
                            end
         | 
| 79 | 
            +
                        end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                        Dir["#{config.stats_path}.*.log"].sort.each do |file|
         | 
| 82 | 
            +
                            if file >= "#{config.stats_path}.#{from_file}.log" and file <= "#{config.stats_path}.#{to_file}.log"
         | 
| 83 | 
            +
                                CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
         | 
| 84 | 
            +
                                    row[:date] = row[:date].to_s
         | 
| 85 | 
            +
                                    if row[:dest_channel_id].to_s[0]=='D'
         | 
| 86 | 
            +
                                        row[:dest_channel] = 'DM'
         | 
| 87 | 
            +
                                    elsif row[:dest_channel].to_s == ''
         | 
| 88 | 
            +
                                        row[:dest_channel] = row[:dest_channel_id]
         | 
| 89 | 
            +
                                    end
         | 
| 90 | 
            +
                                    if users_name_id.size > 0
         | 
| 91 | 
            +
                                        row[:user_name] = users_id_name[row[:user_id]]
         | 
| 92 | 
            +
                                        row[:user_id] = users_name_id[row[:user_name]]
         | 
| 93 | 
            +
                                    else
         | 
| 94 | 
            +
                                        users_id_name[row[:user_id]] ||= row[:user_name]
         | 
| 95 | 
            +
                                    end
         | 
| 96 | 
            +
                                    if !exclude_masters or (exclude_masters and !master_admins.include?(row[:user_name]) and 
         | 
| 97 | 
            +
                                                            !master_admins.include?(row[:user_id]) and
         | 
| 98 | 
            +
                                                            !@master_admin_users_id.include?(row[:user_id]))
         | 
| 99 | 
            +
                                        if !exclude_routines or (exclude_routines and !row[:user_name].match?(/^routine\//) )
         | 
| 100 | 
            +
                                            if row[:bot_channel_id] == @channel_id
         | 
| 101 | 
            +
                                                if row[:date] >= from and row[:date] <= to
         | 
| 102 | 
            +
                                                    count_users[row[:user_id]] ||= 0
         | 
| 103 | 
            +
                                                    count_users[row[:user_id]] += 1
         | 
| 104 | 
            +
                                                    rows << row.to_h
         | 
| 105 | 
            +
                                                    count_channels_dest[row[:dest_channel]] ||= 0
         | 
| 106 | 
            +
                                                    count_channels_dest[row[:dest_channel]] += 1
         | 
| 107 | 
            +
                                                    count_commands_uniq_user[row[:user_id]] ||= []
         | 
| 108 | 
            +
                                                    count_commands_uniq_user[row[:user_id]] << row[:command] unless count_commands_uniq_user[row[:user_id]].include?(row[:command])
         | 
| 109 | 
            +
                                                end
         | 
| 110 | 
            +
                                            end
         | 
| 111 | 
            +
                                        end
         | 
| 112 | 
            +
                                    end
         | 
| 113 | 
            +
                                end
         | 
| 114 | 
            +
                            end
         | 
| 115 | 
            +
                        end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                        total = rows.size
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                        if total > 0
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                            users = rows.user_id.uniq.sort
         | 
| 122 | 
            +
                            count_user = {}
         | 
| 123 | 
            +
                            users.each do |user|
         | 
| 124 | 
            +
                                count = rows.count {|h| h.user_id==user}
         | 
| 125 | 
            +
                                count_user[user] = count
         | 
| 126 | 
            +
                            end
         | 
| 127 | 
            +
                            mtc = nil
         | 
| 128 | 
            +
                            mtu = []
         | 
| 129 | 
            +
                            i = 0
         | 
| 130 | 
            +
                            count_user.sort_by {|k,v| -v}.each do |user, count|
         | 
| 131 | 
            +
                                if i >= 3
         | 
| 132 | 
            +
                                    break
         | 
| 133 | 
            +
                                elsif mtc.nil? or mtc == count or i < 3
         | 
| 134 | 
            +
                                    mtu << "*<@#{users_id_name[user]}>* (#{count})"
         | 
| 135 | 
            +
                                    mtc = count
         | 
| 136 | 
            +
                                else 
         | 
| 137 | 
            +
                                    break
         | 
| 138 | 
            +
                                end
         | 
| 139 | 
            +
                                i+=1
         | 
| 140 | 
            +
                            end
         | 
| 141 | 
            +
                            message << "\t :boom: Users that called more commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                            mtc = nil
         | 
| 144 | 
            +
                            mtu = []
         | 
| 145 | 
            +
                            i = 0
         | 
| 146 | 
            +
                            count_commands_uniq_user.sort_by {|k,v| -v.size}.each do |user, cmds|
         | 
| 147 | 
            +
                                if i >= 3
         | 
| 148 | 
            +
                                    break
         | 
| 149 | 
            +
                                elsif mtc.nil? or mtc == cmds.size or i < 3
         | 
| 150 | 
            +
                                    mtu << "*<@#{users_id_name[user]}>* (#{cmds.size})"
         | 
| 151 | 
            +
                                    mtc = cmds.size
         | 
| 152 | 
            +
                                else 
         | 
| 153 | 
            +
                                    break
         | 
| 154 | 
            +
                                end
         | 
| 155 | 
            +
                                i+=1
         | 
| 156 | 
            +
                            end
         | 
| 157 | 
            +
                            message << "\t :stethoscope: Users that called more different commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
         | 
| 158 | 
            +
                            
         | 
| 159 | 
            +
                            commands_attachment = []
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                            commands = rows.command.uniq.sort
         | 
| 162 | 
            +
                            count_command = {}
         | 
| 163 | 
            +
                            commands.each do |command|
         | 
| 164 | 
            +
                                count = rows.count {|h| h.command==command}
         | 
| 165 | 
            +
                                count_command[command] = count
         | 
| 166 | 
            +
                            end
         | 
| 167 | 
            +
                            
         | 
| 168 | 
            +
                            mtu = []
         | 
| 169 | 
            +
                            count_command.sort_by {|k,v| -v}[0..2].each do |command, count|
         | 
| 170 | 
            +
                                mtu << "*`#{command.gsub('_',' ')}`* (#{count})"
         | 
| 171 | 
            +
                            end
         | 
| 172 | 
            +
                            message << "\t :four_leaf_clover: Most used commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                            count_channels_dest = count_channels_dest.sort_by(&:last).reverse.to_h
         | 
| 175 | 
            +
                            count_channels_dest.keys[0..0].each do |ch|
         | 
| 176 | 
            +
                                if ch=='DM'
         | 
| 177 | 
            +
                                    message << "\t :star: Most used channel: *DM* (#{(count_channels_dest[ch].to_f*100/total).round(2)}%)"
         | 
| 178 | 
            +
                                else
         | 
| 179 | 
            +
                                    message << "\t :star: Most used channel: *<##{@channels_id[ch]}>* (#{(count_channels_dest[ch].to_f*100/total).round(2)}%)"
         | 
| 180 | 
            +
                                end
         | 
| 181 | 
            +
                            end
         | 
| 182 | 
            +
                            
         | 
| 183 | 
            +
                            types = rows.type_message.uniq.sort
         | 
| 184 | 
            +
                            count_type = {}
         | 
| 185 | 
            +
                            types.each do |type|
         | 
| 186 | 
            +
                                count = rows.count {|h| h.type_message==type}
         | 
| 187 | 
            +
                                count_type[type] = count
         | 
| 188 | 
            +
                            end
         | 
| 189 | 
            +
                            
         | 
| 190 | 
            +
                            count_type.sort_by {|k,v| -v}[0..0].each do |type, count|
         | 
| 191 | 
            +
                                message << "\t :house_with_garden: Most calls came from *#{type}* (#{(count.to_f*100/total).round(2)}%)"
         | 
| 192 | 
            +
                            end
         | 
| 193 | 
            +
                        else
         | 
| 194 | 
            +
                            message << 'No data yet'
         | 
| 195 | 
            +
                        end
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
                    respond "#{message.join("\n")}"
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
            end
         | 
| @@ -0,0 +1,113 @@ | |
| 1 | 
            +
            class SlackSmartBot
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def see_announcements(user, type, channel, mention=false, publish=false)
         | 
| 4 | 
            +
                save_stats(__method__)
         | 
| 5 | 
            +
                typem = Thread.current[:typem]
         | 
| 6 | 
            +
                general_message = "\nRelated commands `add announcement MESSAGE`, `delete announcement ID`"
         | 
| 7 | 
            +
                if channel == ''
         | 
| 8 | 
            +
                  if typem == :on_call
         | 
| 9 | 
            +
                    channel = Thread.current[:dchannel]
         | 
| 10 | 
            +
                  else
         | 
| 11 | 
            +
                    channel = Thread.current[:dest]
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                if publish
         | 
| 15 | 
            +
                  dest = channel
         | 
| 16 | 
            +
                else
         | 
| 17 | 
            +
                  dest = Thread.current[:dest]
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                if type == 'all'
         | 
| 21 | 
            +
                  if config.masters.include?(user.name) and typem==:on_dm
         | 
| 22 | 
            +
                    channels = Dir.entries("#{config.path}/announcements/")
         | 
| 23 | 
            +
                    channels.select! {|i| i[/\.csv$/]}
         | 
| 24 | 
            +
                  else
         | 
| 25 | 
            +
                    channels = []
         | 
| 26 | 
            +
                    respond "Only master admins on a DM with the SmarBot can call this command.", dest
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                elsif typem == :on_dm and channel == Thread.current[:dest]
         | 
| 29 | 
            +
                  channels = [channel, @channel_id]
         | 
| 30 | 
            +
                else
         | 
| 31 | 
            +
                  channels = [channel]
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
                channels.each do |channel|
         | 
| 34 | 
            +
                  channel.gsub!('.csv','')
         | 
| 35 | 
            +
                  if channel[0]== 'D'
         | 
| 36 | 
            +
                    channel_id = channel
         | 
| 37 | 
            +
                  else
         | 
| 38 | 
            +
                    get_channels_name_and_id() unless @channels_name.keys.include?(channel) or @channels_id.keys.include?(channel)
         | 
| 39 | 
            +
                    channel_id = nil
         | 
| 40 | 
            +
                    if @channels_name.key?(channel) #it is an id
         | 
| 41 | 
            +
                      channel_id = channel
         | 
| 42 | 
            +
                      channel = @channels_name[channel_id]
         | 
| 43 | 
            +
                    elsif @channels_id.key?(channel) #it is a channel name
         | 
| 44 | 
            +
                      channel_id = @channels_id[channel]
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  if has_access?(__method__, user)
         | 
| 48 | 
            +
                    if (channel_id!=Thread.current[:dest] and config.masters.include?(user.name) and typem==:on_dm) or publish
         | 
| 49 | 
            +
                      see_announcements_on_demand = true
         | 
| 50 | 
            +
                    else
         | 
| 51 | 
            +
                      see_announcements_on_demand = false
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                    if channel_id == Thread.current[:dest] or see_announcements_on_demand or publish #master admin user or publish_announcements
         | 
| 54 | 
            +
                      if File.exists?("#{config.path}/announcements/#{channel_id}.csv") and (!@announcements.key?(channel_id) or see_announcements_on_demand) # to force to have the last version that maybe was updated by other SmartBot in case of demand
         | 
| 55 | 
            +
                        t = CSV.table("#{config.path}/announcements/#{channel_id}.csv", headers: ['message_id', 'user_deleted', 'user_created', 'date', 'time', 'type', 'message'])
         | 
| 56 | 
            +
                        @announcements[channel_id] = t
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                      if @announcements.key?(channel_id)
         | 
| 59 | 
            +
                        message = []
         | 
| 60 | 
            +
                        @announcements[channel_id].each do |m|
         | 
| 61 | 
            +
                          if m[:user_deleted] == '' and (type == 'all' or type == '' or type==m[:type])
         | 
| 62 | 
            +
                            if m[:type].match?(/:\w+:/)
         | 
| 63 | 
            +
                              emoji = m[:type]
         | 
| 64 | 
            +
                            elsif m[:type] == 'white'
         | 
| 65 | 
            +
                              emoji = ':white_square:'
         | 
| 66 | 
            +
                            else
         | 
| 67 | 
            +
                              emoji = ":large_#{m[:type]}_square:"
         | 
| 68 | 
            +
                            end
         | 
| 69 | 
            +
                            if mention
         | 
| 70 | 
            +
                              user_created = "<@#{m[:user_created]}>"
         | 
| 71 | 
            +
                            else
         | 
| 72 | 
            +
                              user_created = m[:user_created]
         | 
| 73 | 
            +
                            end
         | 
| 74 | 
            +
                            if type == 'all' and channel_id[0]=='D'
         | 
| 75 | 
            +
                              message << "\t#{m[:message_id]} #{emoji} *_#{m[:date]}_* #{m[:time]} *:* \t*private*"
         | 
| 76 | 
            +
                            else
         | 
| 77 | 
            +
                              message << "\t#{m[:message_id]} #{emoji} *_#{m[:date]}_* #{m[:time]} #{"#{user_created} " unless channel_id[0]=='D'}*:* \t#{m[:message]}"
         | 
| 78 | 
            +
                            end
         | 
| 79 | 
            +
                          end
         | 
| 80 | 
            +
                        end
         | 
| 81 | 
            +
                        if message.size > 0
         | 
| 82 | 
            +
                          if channel_id[0]=='D'
         | 
| 83 | 
            +
                            if type == 'all'
         | 
| 84 | 
            +
                              message.unshift("*Private messages stored on DM with the SmartBot and <@#{@announcements[channel_id][:user_created][0]}>*")
         | 
| 85 | 
            +
                            else
         | 
| 86 | 
            +
                              message.unshift("*Private messages stored on your DM with the SmartBot*")
         | 
| 87 | 
            +
                            end
         | 
| 88 | 
            +
                          else
         | 
| 89 | 
            +
                            message.unshift("*Announcements for channel <##{channel_id}>*")
         | 
| 90 | 
            +
                          end
         | 
| 91 | 
            +
                          message << general_message
         | 
| 92 | 
            +
                          respond message.join("\n"), dest
         | 
| 93 | 
            +
                        else
         | 
| 94 | 
            +
                          if typem == :on_dm and channel_id[0]=='D'
         | 
| 95 | 
            +
                            respond("There are no #{type} announcements#{general_message}", dest) unless type == 'all'
         | 
| 96 | 
            +
                          else
         | 
| 97 | 
            +
                            respond("There are no #{type} announcements for <##{channel_id}>#{general_message}", dest) unless publish or type == 'all' or (typem==:on_dm and channel_id[0]!='D' and !see_announcements_on_demand)
         | 
| 98 | 
            +
                          end
         | 
| 99 | 
            +
                        end
         | 
| 100 | 
            +
                      else
         | 
| 101 | 
            +
                        if typem == :on_dm and channel_id[0]=='D'
         | 
| 102 | 
            +
                          respond("There are no announcements#{general_message}", dest) unless type == 'all'
         | 
| 103 | 
            +
                        else
         | 
| 104 | 
            +
                          respond("There are no announcements for <##{channel_id}>#{general_message}", dest) unless publish or type == 'all' or (typem==:on_dm and channel_id[0]!='D' and !see_announcements_on_demand)
         | 
| 105 | 
            +
                        end
         | 
| 106 | 
            +
                      end
         | 
| 107 | 
            +
                    else
         | 
| 108 | 
            +
                      respond "Go to <##{channel_id}> and call the command from there.", dest
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
            end
         |