class SlackSmartBot
def leaderboard(from, to, period)
exclude_masters = true
exclude_routines = true
require 'csv'
if config.stats
message = []
else
message = ["You need to set stats to true to generate the stats when running the bot instance."]
end
save_stats(__method__)
if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
message<<'No stats'
else
if period == ''
message << "*Leaderboard SmartBot <##@channel_id> from #{from} to #{to}*\n"
else
message << "*Leaderboard SmartBot <##@channel_id> #{period}* (#{from} -> #{to})\n"
end
from_short = from
to_short = to
from_file = from[0..3] + '-' + from[5..6]
to_file = to[0..3] + '-' + to[5..6]
from+= " 00:00:00 +0000"
to+= " 23:59:59 +0000"
rows = []
users_id_name = {}
users_name_id = {}
count_users = {}
count_channels_dest = {}
count_commands_uniq_user = {}
if from[0..3]=='2020' Dir["#{config.stats_path}.*.log"].sort.each do |file|
if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
unless users_id_name.key?(row[:user_id])
users_id_name[row[:user_id]] = row[:user_name]
end
unless users_name_id.key?(row[:user_name])
users_name_id[row[:user_name]] = row[:user_id]
end
end
end
end
end
master_admins = config.masters.dup
if users_id_name.size > 0
config.masters.each do |u|
if users_id_name.key?(u)
master_admins << users_id_name[u]
elsif users_name_id.key?(u)
master_admins << users_name_id[u]
end
end
end
Dir["#{config.stats_path}.*.log"].sort.each do |file|
if file >= "#{config.stats_path}.#{from_file}.log" and file <= "#{config.stats_path}.#{to_file}.log"
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
row[:date] = row[:date].to_s
if row[:dest_channel_id].to_s[0]=='D'
row[:dest_channel] = 'DM'
elsif row[:dest_channel].to_s == ''
row[:dest_channel] = row[:dest_channel_id]
end
if users_name_id.size > 0
row[:user_name] = users_id_name[row[:user_id]]
row[:user_id] = users_name_id[row[:user_name]]
else
users_id_name[row[:user_id]] ||= row[:user_name]
end
if !exclude_masters or (exclude_masters and !master_admins.include?(row[:user_name]) and
!master_admins.include?(row[:user_id]) and
!@master_admin_users_id.include?(row[:user_id]))
if !exclude_routines or (exclude_routines and !row[:user_name].match?(/^routine\//) )
if row[:bot_channel_id] == @channel_id
if row[:date] >= from and row[:date] <= to
count_users[row[:user_id]] ||= 0
count_users[row[:user_id]] += 1
rows << row.to_h
count_channels_dest[row[:dest_channel]] ||= 0
count_channels_dest[row[:dest_channel]] += 1
count_commands_uniq_user[row[:user_id]] ||= []
count_commands_uniq_user[row[:user_id]] << row[:command] unless count_commands_uniq_user[row[:user_id]].include?(row[:command])
end
end
end
end
end
end
end
total = rows.size
if total > 0
users = rows.user_id.uniq.sort
count_user = {}
users.each do |user|
count = rows.count {|h| h.user_id==user}
count_user[user] = count
end
mtc = nil
mtu = []
i = 0
count_user.sort_by {|k,v| -v}.each do |user, count|
if i >= 3
break
elsif mtc.nil? or mtc == count or i < 3
mtu << "*<@#{users_id_name[user]}>* (#{count})"
mtc = count
else
break
end
i+=1
end
message << "\t :boom: Users that called more commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
mtc = nil
mtu = []
i = 0
count_commands_uniq_user.sort_by {|k,v| -v.size}.each do |user, cmds|
if i >= 3
break
elsif mtc.nil? or mtc == cmds.size or i < 3
mtu << "*<@#{users_id_name[user]}>* (#{cmds.size})"
mtc = cmds.size
else
break
end
i+=1
end
message << "\t :stethoscope: Users that called more different commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
commands_attachment = []
commands = rows.command.uniq.sort
count_command = {}
commands.each do |command|
count = rows.count {|h| h.command==command}
count_command[command] = count
end
mtu = []
count_command.sort_by {|k,v| -v}[0..2].each do |command, count|
mtu << "*`#{command.gsub('_',' ')}`* (#{count})"
end
message << "\t :four_leaf_clover: Most used commands: \n\t\t\t\t#{mtu.join("\n\t\t\t\t")}"
count_channels_dest = count_channels_dest.sort_by(&:last).reverse.to_h
count_channels_dest.keys[0..0].each do |ch|
if ch=='DM'
message << "\t :star: Most used channel: *DM* (#{(count_channels_dest[ch].to_f*100/total).round(2)}%)"
else
message << "\t :star: Most used channel: *<##{@channels_id[ch]}>* (#{(count_channels_dest[ch].to_f*100/total).round(2)}%)"
end
end
types = rows.type_message.uniq.sort
count_type = {}
types.each do |type|
count = rows.count {|h| h.type_message==type}
count_type[type] = count
end
count_type.sort_by {|k,v| -v}[0..0].each do |type, count|
message << "\t :house_with_garden: Most calls came from *#{type}* (#{(count.to_f*100/total).round(2)}%)"
end
else
message << 'No data yet'
end
end
respond "#{message.join("\n")}"
end
end