slack-smart-bot 1.14.1 → 1.15.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 +237 -48
- data/img/chat_gpt.png +0 -0
- data/img/chat_gpt_session.png +0 -0
- data/img/chat_gpt_share.png +0 -0
- data/img/command_add_sc.png +0 -0
- data/img/command_bot_help_echo.png +0 -0
- data/img/command_loop.png +0 -0
- data/img/command_my_timeoff.png +0 -0
- data/img/command_recap.png +0 -0
- data/img/command_repl1.png +0 -0
- data/img/command_repl2.png +0 -0
- data/img/command_ruby.png +0 -0
- data/img/command_run_repl.png +0 -0
- data/img/command_see_announcements.png +0 -0
- data/img/command_see_statuses.png +0 -0
- data/img/command_see_team.png +0 -0
- data/img/command_summarize.png +0 -0
- data/img/commands_inline.png +0 -0
- data/img/commands_on_demand.png +0 -0
- data/img/commands_on_external_call.png +0 -0
- data/img/image_editing.png +0 -0
- data/img/image_generation.png +0 -0
- data/img/image_variations.png +0 -0
- data/img/openai-300.png +0 -0
- data/img/openai.png +0 -0
- data/img/slack-300.png +0 -0
- data/img/slack.png +0 -0
- data/img/smart-bot-150.png +0 -0
- data/img/smart-bot-profile-pic-2.png +0 -0
- data/img/smart-bot-profile-pic.png +0 -0
- data/img/smart-bot.png +0 -0
- data/img/whisper.png +0 -0
- data/lib/slack/smart-bot/ai/open_ai/connect.rb +165 -43
- data/lib/slack/smart-bot/ai/open_ai/models.rb +61 -9
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +67 -11
- data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +4 -3
- data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +4 -4
- data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +4 -3
- data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +4 -3
- data/lib/slack/smart-bot/comm/ask.rb +20 -8
- data/lib/slack/smart-bot/comm/dont_understand.rb +2 -2
- data/lib/slack/smart-bot/comm/event_hello.rb +30 -1
- data/lib/slack/smart-bot/comm/get_channel_members.rb +2 -1
- data/lib/slack/smart-bot/comm/get_presence.rb +1 -0
- data/lib/slack/smart-bot/comm/get_smartbot_team_info.rb +10 -0
- data/lib/slack/smart-bot/comm/get_user_info.rb +45 -6
- data/lib/slack/smart-bot/comm/get_users.rb +8 -1
- data/lib/slack/smart-bot/comm/respond.rb +225 -196
- data/lib/slack/smart-bot/comm/send_msg_channel.rb +2 -2
- data/lib/slack/smart-bot/comm/send_msg_user.rb +10 -9
- data/lib/slack/smart-bot/comm/unreact.rb +2 -2
- data/lib/slack/smart-bot/comm.rb +1 -0
- data/lib/slack/smart-bot/commands/general/add_admin.rb +16 -6
- data/lib/slack/smart-bot/commands/general/add_announcement.rb +3 -3
- data/lib/slack/smart-bot/commands/general/add_vacation.rb +28 -12
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +272 -23
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +42 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +89 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +45 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +41 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +81 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +52 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +52 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +14 -11
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +15 -11
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +29 -17
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +16 -13
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +13 -7
- data/lib/slack/smart-bot/commands/general/allow_access.rb +8 -4
- data/lib/slack/smart-bot/commands/general/bot_help.rb +24 -9
- data/lib/slack/smart-bot/commands/general/bye_bot.rb +9 -5
- data/lib/slack/smart-bot/commands/general/delete_announcement.rb +2 -1
- data/lib/slack/smart-bot/commands/general/delete_share.rb +2 -1
- data/lib/slack/smart-bot/commands/general/deny_access.rb +1 -1
- data/lib/slack/smart-bot/commands/general/get_smartbot_readme.rb +15 -0
- data/lib/slack/smart-bot/commands/general/hi_bot.rb +10 -4
- data/lib/slack/smart-bot/commands/general/personal_settings.rb +26 -8
- data/lib/slack/smart-bot/commands/general/poster.rb +26 -2
- data/lib/slack/smart-bot/commands/general/public_holidays.rb +14 -24
- data/lib/slack/smart-bot/commands/general/recap.rb +399 -0
- data/lib/slack/smart-bot/commands/general/remove_admin.rb +19 -9
- data/lib/slack/smart-bot/commands/general/remove_vacation.rb +23 -6
- data/lib/slack/smart-bot/commands/general/see_access.rb +2 -1
- data/lib/slack/smart-bot/commands/general/see_admins.rb +8 -4
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +5 -5
- data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +4 -4
- data/lib/slack/smart-bot/commands/general/see_shares.rb +1 -1
- data/lib/slack/smart-bot/commands/general/see_vacations.rb +34 -17
- data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +4 -2
- data/lib/slack/smart-bot/commands/general/share_messages.rb +3 -3
- data/lib/slack/smart-bot/commands/general/summarize.rb +191 -0
- data/lib/slack/smart-bot/commands/general/teams/add_team.rb +4 -8
- data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +3 -3
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +34 -29
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +1 -1
- data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +6 -4
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +26 -15
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +33 -24
- data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +4 -4
- data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +10 -8
- data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +73 -61
- data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +28 -13
- data/lib/slack/smart-bot/commands/general/teams/update_team.rb +9 -9
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +1153 -835
- data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +19 -17
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +12 -9
- data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +2 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +5 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/delete_message.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +7 -6
- data/lib/slack/smart-bot/commands/on_bot/admin_master/update_message.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +21 -20
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +40 -7
- data/lib/slack/smart-bot/commands/on_bot/general/bot_status.rb +6 -2
- data/lib/slack/smart-bot/commands/on_bot/general/stop_using_rules.rb +7 -6
- data/lib/slack/smart-bot/commands/on_bot/general/suggest_command.rb +5 -4
- data/lib/slack/smart-bot/commands/on_bot/general/use_rules.rb +4 -3
- data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +4 -4
- data/lib/slack/smart-bot/commands/on_bot/kill_repl.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +110 -53
- data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +35 -29
- data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +5 -5
- data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +1 -2
- data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +5 -4
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +22 -11
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +12 -7
- data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +2 -2
- data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +1 -1
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +5 -5
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +5 -5
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +3 -3
- data/lib/slack/smart-bot/commands.rb +10 -0
- data/lib/slack/smart-bot/config.rb +126 -0
- data/lib/slack/smart-bot/listen.rb +12 -11
- data/lib/slack/smart-bot/process.rb +62 -55
- data/lib/slack/smart-bot/process_first.rb +106 -65
- data/lib/slack/smart-bot/treat_message.rb +79 -47
- data/lib/slack/smart-bot/utils/answer.rb +11 -3
- data/lib/slack/smart-bot/utils/answer_delete.rb +11 -3
- data/lib/slack/smart-bot/utils/check_vacations.rb +21 -3
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +13 -13
- data/lib/slack/smart-bot/utils/display_calendar.rb +42 -8
- data/lib/slack/smart-bot/utils/encryption/decrypt.rb +16 -9
- data/lib/slack/smart-bot/utils/encryption/encrypt.rb +14 -11
- data/lib/slack/smart-bot/utils/find_user.rb +71 -0
- data/lib/slack/smart-bot/utils/get_access_channels.rb +22 -3
- data/lib/slack/smart-bot/utils/get_channels_name_and_id.rb +3 -4
- data/lib/slack/smart-bot/utils/get_command_ids.rb +5 -5
- data/lib/slack/smart-bot/utils/get_countries_candelarific.rb +18 -0
- data/lib/slack/smart-bot/utils/get_help.rb +21 -19
- data/lib/slack/smart-bot/utils/get_openai_sessions.rb +47 -0
- data/lib/slack/smart-bot/utils/get_personal_settings.rb +29 -3
- data/lib/slack/smart-bot/utils/get_rules_imported.rb +27 -6
- data/lib/slack/smart-bot/utils/get_shares.rb +1 -1
- data/lib/slack/smart-bot/utils/get_team_members.rb +4 -4
- data/lib/slack/smart-bot/utils/get_vacations.rb +15 -7
- data/lib/slack/smart-bot/utils/has_access.rb +10 -4
- data/lib/slack/smart-bot/utils/is_admin.rb +25 -17
- data/lib/slack/smart-bot/utils/local_time.rb +29 -0
- data/lib/slack/smart-bot/utils/save_stats.rb +5 -3
- data/lib/slack/smart-bot/utils/update_access_channels.rb +19 -3
- data/lib/slack/smart-bot/utils/update_openai_sessions.rb +42 -0
- data/lib/slack/smart-bot/utils/update_personal_settings.rb +11 -3
- data/lib/slack/smart-bot/utils/update_rules_imported.rb +18 -3
- data/lib/slack/smart-bot/utils/update_vacations.rb +5 -2
- data/lib/slack/smart-bot/utils/upgrade_to_use_team_ids.rb +276 -0
- data/lib/slack/smart-bot/utils.rb +6 -1
- data/lib/slack-smart-bot.rb +182 -76
- data/lib/slack-smart-bot_general_commands.rb +10 -9
- data/whats_new.txt +30 -13
- metadata +152 -18
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
class SlackSmartBot
|
|
2
|
+
|
|
3
|
+
#todo: add tests
|
|
4
|
+
def recap(user, dest, channel, date_start, date_end, my_recap)
|
|
5
|
+
save_stats(__method__)
|
|
6
|
+
|
|
7
|
+
require "date"
|
|
8
|
+
require "time"
|
|
9
|
+
react :runner
|
|
10
|
+
@history_still_running ||= false
|
|
11
|
+
|
|
12
|
+
if channel[0] == "D"
|
|
13
|
+
messages = []
|
|
14
|
+
messages << "Sorry, `recap` command is not available in direct messages."
|
|
15
|
+
messages << "Specify a channel instead or call it from a channel."
|
|
16
|
+
messages << "For example: `my recap 2023 #channel`"
|
|
17
|
+
messages << ""
|
|
18
|
+
messages << "You can also call from a DM:"
|
|
19
|
+
messages << "\t\t`bot stats last year`"
|
|
20
|
+
messages << "\t\t`bot stats last year monthly graph`"
|
|
21
|
+
messages << "\t\t`bot stats`"
|
|
22
|
+
messages << ""
|
|
23
|
+
messages << "Call `bot help bot stats` for more information."
|
|
24
|
+
respond messages.join("\n")
|
|
25
|
+
elsif @history_still_running
|
|
26
|
+
respond "Due to Slack API rate limit, `recap` command is limited. Waiting for other `recap` command to finish."
|
|
27
|
+
num_times = 0
|
|
28
|
+
while @history_still_running and num_times < 30
|
|
29
|
+
num_times += 1
|
|
30
|
+
sleep 1
|
|
31
|
+
end
|
|
32
|
+
if @history_still_running
|
|
33
|
+
respond "Sorry, Another `recap` command is still running after 30 seconds. Please try again later."
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if !@history_still_running and channel[0] != "D"
|
|
38
|
+
@history_still_running = true
|
|
39
|
+
begin
|
|
40
|
+
date_start = date_start.gsub(".", "/").gsub("-", "/")
|
|
41
|
+
date_end = date_end.gsub(".", "/").gsub("-", "/")
|
|
42
|
+
if date_start.to_s == ""
|
|
43
|
+
date_start = Date.today.strftime("%Y/01/01")
|
|
44
|
+
elsif date_start.match(/^\d\d\d\d$/)
|
|
45
|
+
date_start = "#{date_start}/01/01"
|
|
46
|
+
end
|
|
47
|
+
if date_end.to_s == ""
|
|
48
|
+
date_end = Date.parse(date_start).strftime("%Y/12/31")
|
|
49
|
+
end
|
|
50
|
+
if date_end < date_start
|
|
51
|
+
respond "Sorry, `recap` command requires `date_start` to be before `date_end`."
|
|
52
|
+
else
|
|
53
|
+
# if more than one year respond max one year
|
|
54
|
+
num_days = (Date.parse(date_end) - Date.parse(date_start)).to_i
|
|
55
|
+
if num_days > 365
|
|
56
|
+
respond "Sorry, `recap` command is limited to one year."
|
|
57
|
+
else
|
|
58
|
+
messages = []
|
|
59
|
+
#if date_start is 1st of January and date_end is 31st of December, then use the year only
|
|
60
|
+
if Date.parse(date_start).strftime("%m/%d") == "01/01" and Date.parse(date_end).strftime("%m/%d") == "12/31"
|
|
61
|
+
messages << "*#{Date.parse(date_start).strftime("%Y")} Recap <##{channel}>*"
|
|
62
|
+
else
|
|
63
|
+
messages << "*Recap for <##{channel}> from #{date_start} to #{date_end}*"
|
|
64
|
+
end
|
|
65
|
+
date_start = date_start + " 00:00:00"
|
|
66
|
+
date_start = Time.strptime(date_start, "%Y/%m/%d %H:%M:%S")
|
|
67
|
+
date_end = date_end + " 23:59:59"
|
|
68
|
+
date_end = Time.strptime(date_end, "%Y/%m/%d %H:%M:%S")
|
|
69
|
+
|
|
70
|
+
# get all messages from the channel
|
|
71
|
+
hist = []
|
|
72
|
+
|
|
73
|
+
begin
|
|
74
|
+
members = get_channel_members(channel)
|
|
75
|
+
rescue
|
|
76
|
+
members = []
|
|
77
|
+
end
|
|
78
|
+
if !members.include?(config.nick_id_granular) or !members.include?(config.nick_id) #monitor-smartbot #smartbot
|
|
79
|
+
respond "Sorry, `recap` command requires <@#{config.nick_id_granular}> and <@#{config.nick_id}> to be in the channel. Please add them and try again."
|
|
80
|
+
elsif !members.include?(user.id)
|
|
81
|
+
respond "Sorry, `recap` command requires you to be in the channel. Please join the channel and try again."
|
|
82
|
+
else
|
|
83
|
+
|
|
84
|
+
client_granular.conversations_history(channel: channel, limit: 200, oldest: date_start.to_f, latest: date_end.to_f) do |response|
|
|
85
|
+
hist << response.messages
|
|
86
|
+
end
|
|
87
|
+
hist_replies = hist.deep_copy()
|
|
88
|
+
hist.flatten!
|
|
89
|
+
|
|
90
|
+
# sort hist by reply_count from highest to lowest, reply_count is not always, return a hash
|
|
91
|
+
hist.each do |message|
|
|
92
|
+
if !message.key?("reply_count")
|
|
93
|
+
message[:reply_count] = 0
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
num_posts = hist.length
|
|
97
|
+
num_threads = hist.select { |msg| msg.key?("thread_ts") }.length
|
|
98
|
+
|
|
99
|
+
hist_replies_count = hist.sort_by { |k| k[:reply_count] }
|
|
100
|
+
# get the top 3 threads
|
|
101
|
+
top_three_threads = []
|
|
102
|
+
#hist_replies_count is not always 3, so we need to check if the index exists
|
|
103
|
+
top_three_threads << hist_replies_count[-1] if hist_replies_count[-1] and hist_replies_count[-1].key?("thread_ts")
|
|
104
|
+
top_three_threads << hist_replies_count[-2] if hist_replies_count[-2] and hist_replies_count[-2].key?("thread_ts")
|
|
105
|
+
top_three_threads << hist_replies_count[-3] if hist_replies_count[-3] and hist_replies_count[-3].key?("thread_ts")
|
|
106
|
+
|
|
107
|
+
num_messages_skipped = 0
|
|
108
|
+
num_messages_not_skipped = 0
|
|
109
|
+
hist.each do |message|
|
|
110
|
+
if Time.at(message[:ts].to_f) >= date_start and Time.at(message[:ts].to_f) <= date_end
|
|
111
|
+
if message.key?("thread_ts")
|
|
112
|
+
if message.reply_users_count == 1 and message.reply_users[0] == config.nick_id
|
|
113
|
+
#if the thread has only one replier and it is from smartbot, then we don't need to get the replies from the thread
|
|
114
|
+
num_messages_skipped += 1
|
|
115
|
+
message[:reply_count].times do
|
|
116
|
+
hist_replies << { user: config.nick_id, ts: message.thread_ts, text: "" }
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
num_messages_not_skipped += 1
|
|
120
|
+
thread_ts = message.thread_ts
|
|
121
|
+
passed = false
|
|
122
|
+
num_tries = 0
|
|
123
|
+
while !passed and num_tries < 30
|
|
124
|
+
begin
|
|
125
|
+
num_tries += 1
|
|
126
|
+
replies = client_granular.conversations_replies(channel: channel, ts: thread_ts)
|
|
127
|
+
passed = true
|
|
128
|
+
rescue => e
|
|
129
|
+
@logger.info "recap command: threads num_tries: #{num_tries}"
|
|
130
|
+
@logger.fatal "recap command: threads error: #{e.message}"
|
|
131
|
+
sleep 1
|
|
132
|
+
passed = false
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
if !passed
|
|
136
|
+
respond "Sorry, `recap` command failed. <@#{config.admins.join(">,<@")}> please check the logs."
|
|
137
|
+
@history_still_running = false
|
|
138
|
+
unreact :runner
|
|
139
|
+
return
|
|
140
|
+
end
|
|
141
|
+
hist_replies << replies.messages
|
|
142
|
+
sleep 0.5 #to avoid rate limit Tier 3 (50 requests per minute)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
hist_replies.flatten!
|
|
148
|
+
|
|
149
|
+
hist_user = {}
|
|
150
|
+
hist_replies.each do |msg|
|
|
151
|
+
hist_user[msg.user] ||= 0
|
|
152
|
+
hist_user[msg.user] += 1
|
|
153
|
+
end
|
|
154
|
+
#sort hist_user by value from highest to lowest, return a hash
|
|
155
|
+
hist_user = hist_user.sort_by { |k, v| v }.reverse.to_h
|
|
156
|
+
#top_three_users excluding smartbot
|
|
157
|
+
hist_user_wo_smartbot = hist_user.reject { |k, v| k == config.nick_id }
|
|
158
|
+
|
|
159
|
+
top_three_users = hist_user_wo_smartbot.first(3).to_h
|
|
160
|
+
messages << "\t :bar_chart: Totals:"
|
|
161
|
+
messages << "\t\t\t messages: *#{hist_replies.length}*"
|
|
162
|
+
messages << "\t\t\t SmartBot messages: *#{hist_user[config.nick_id]}* (#{hist_user[config.nick_id] * 100 / hist_replies.length} %)" if hist_user.key?(config.nick_id)
|
|
163
|
+
messages << "\t\t\t posts: *#{num_posts}*"
|
|
164
|
+
messages << "\t\t\t threads: *#{num_threads}*"
|
|
165
|
+
|
|
166
|
+
num_replies = hist_replies.length - num_posts
|
|
167
|
+
messages << "\t\t\t replies: *#{num_replies}*"
|
|
168
|
+
|
|
169
|
+
messages << "\t\t\t users: *#{hist_user.length}*"
|
|
170
|
+
if top_three_users.length > 0
|
|
171
|
+
messages << "\n\t :boom: Top 3 users:"
|
|
172
|
+
top_three_users.each do |user, num|
|
|
173
|
+
messages << "\t\t\t<@#{user}>: *#{num}*"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#top 3 users posting excluding smartbot
|
|
178
|
+
hist_user_posts = {}
|
|
179
|
+
hist.each do |msg|
|
|
180
|
+
hist_user_posts[msg.user] ||= 0
|
|
181
|
+
hist_user_posts[msg.user] += 1
|
|
182
|
+
end
|
|
183
|
+
hist_user_posts = hist_user_posts.reject { |k, v| k == config.nick_id }
|
|
184
|
+
hist_user_posts = hist_user_posts.sort_by { |k, v| v }.reverse.to_h
|
|
185
|
+
top_three_users_posts = hist_user_posts.first(3).to_h
|
|
186
|
+
if top_three_users_posts.length > 0
|
|
187
|
+
messages << "\n\t :bust_in_silhouette: Top 3 users posting:"
|
|
188
|
+
top_three_users_posts.each do |user, num|
|
|
189
|
+
messages << "\t\t\t<@#{user}>: *#{num}*"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
if top_three_threads.length > 0
|
|
194
|
+
messages << "\n\t :star: Top 3 threads:"
|
|
195
|
+
top_three_threads.each do |thread|
|
|
196
|
+
messages << "\t\t\t<@#{thread.user}>: *#{thread.reply_count}* replies. *<https://greenqloud.slack.com/archives/#{channel}/p#{thread.ts.gsub(".", "")}|#{thread.text[0..50].gsub(/[^a-zA-Z0-9\s]/, "").gsub("\n", "").strip}>*"
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
#get the stats from the files, they are like smart-bot.stats.2020-01.log, smart-bot.stats.2020-02.log, etc.
|
|
201
|
+
smartbot_stats = []
|
|
202
|
+
Dir["#{config.stats_path}.*.log"].sort.each do |file|
|
|
203
|
+
#read only the files that are in the range of date_start and date_end
|
|
204
|
+
if file.match(/#{config.stats_path}\.(\d\d\d\d-\d\d)\.log/)
|
|
205
|
+
if $1 >= date_start.strftime("%Y-%m") and $1 <= date_end.strftime("%Y-%m")
|
|
206
|
+
smartbot_stats_file = CSV.read(file, headers: true, converters: :numeric)
|
|
207
|
+
#convert smartbot_stats_file to array of hashes
|
|
208
|
+
smartbot_stats_file = smartbot_stats_file.map(&:to_hash)
|
|
209
|
+
smartbot_stats << smartbot_stats_file
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
smartbot_stats.flatten!
|
|
214
|
+
|
|
215
|
+
#filter by bot_channel_id==channel and dest_channel_id!=channel and type_message==on_dm
|
|
216
|
+
smartbot_stats_on_dm = smartbot_stats.deep_copy
|
|
217
|
+
smartbot_stats_on_dm = smartbot_stats_on_dm.select { |msg| msg["bot_channel_id"] == channel and msg["dest_channel_id"] != channel and msg["type_message"] == "on_dm" }
|
|
218
|
+
#filter by date_start and date_end. We store the date on "date" field like this: 2020-01-14 16:34:16
|
|
219
|
+
smartbot_stats_on_dm = smartbot_stats_on_dm.select { |msg| Date.parse(msg["date"]) >= Date.parse(date_start.strftime("%Y-%m-%d")) and Date.parse(msg["date"]) <= Date.parse(date_end.strftime("%Y-%m-%d")) }
|
|
220
|
+
|
|
221
|
+
#filter by bot_channel_id==channel and dest_channel_id!=channel and type_message!=on_dm
|
|
222
|
+
smartbot_stats_external = smartbot_stats.deep_copy
|
|
223
|
+
smartbot_stats_external = smartbot_stats_external.select { |msg| msg["bot_channel_id"] == channel and msg["dest_channel_id"] != channel and msg["type_message"] != "on_dm" }
|
|
224
|
+
#filter by date_start and date_end. We store the date on "date" field like this: 2020-01-14 16:34:16
|
|
225
|
+
smartbot_stats_external = smartbot_stats_external.select { |msg| Date.parse(msg["date"]) >= Date.parse(date_start.strftime("%Y-%m-%d")) and Date.parse(msg["date"]) <= Date.parse(date_end.strftime("%Y-%m-%d")) }
|
|
226
|
+
|
|
227
|
+
# filter by dest_channel_id
|
|
228
|
+
smartbot_stats = smartbot_stats.select { |msg| msg["dest_channel_id"] == channel }
|
|
229
|
+
# filter by date_start and date_end. We store the date on "date" field like this: 2020-01-14 16:34:16
|
|
230
|
+
smartbot_stats = smartbot_stats.select { |msg| Date.parse(msg["date"]) >= Date.parse(date_start.strftime("%Y-%m-%d")) and Date.parse(msg["date"]) <= Date.parse(date_end.strftime("%Y-%m-%d")) }
|
|
231
|
+
|
|
232
|
+
#get the number of times SmartBot was called by a user, if field 'user_name' is not including 'routine/'
|
|
233
|
+
smartbot_stats_user = {}
|
|
234
|
+
smartbot_stats.each do |msg|
|
|
235
|
+
if !msg["user_name"].include?("routine/")
|
|
236
|
+
smartbot_stats_user[msg["user_name"]] ||= 0
|
|
237
|
+
smartbot_stats_user[msg["user_name"]] += 1
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
smartbot_stats_total = smartbot_stats_user.values.sum
|
|
242
|
+
if smartbot_stats_total > 0
|
|
243
|
+
messages << "\t :robot_face: *SmartBot* Stats:"
|
|
244
|
+
#total of times SmartBot was called
|
|
245
|
+
messages << "\t\t\t called by a user: *#{smartbot_stats_total}*"
|
|
246
|
+
#total of times SmartBot was called by any user including routines
|
|
247
|
+
smartbot_stats_total_all = smartbot_stats.length
|
|
248
|
+
messages << "\t\t\t called on this channel: *#{smartbot_stats_total_all}*" if smartbot_stats_total != smartbot_stats_total_all
|
|
249
|
+
#total of times SmartBot was called using this channel on a DM
|
|
250
|
+
messages << "\t\t\t called on a DM using this channel: *#{smartbot_stats_on_dm.length}*" if smartbot_stats_on_dm.length > 0
|
|
251
|
+
#total of times SmartBot was called using this channel from another channel
|
|
252
|
+
messages << "\t\t\t called from another channel using this channel: *#{smartbot_stats_external.length}*" if smartbot_stats_external.length > 0
|
|
253
|
+
|
|
254
|
+
#total of times SmartBot was used
|
|
255
|
+
total_sb_calls = smartbot_stats_total_all + smartbot_stats_on_dm.length + smartbot_stats_external.length
|
|
256
|
+
messages << "\t\t\t Total times SmartBot was used: *#{total_sb_calls}*" if total_sb_calls != smartbot_stats_total_all
|
|
257
|
+
|
|
258
|
+
#get the three most used commands. The command is stored on "command" field
|
|
259
|
+
smartbot_stats_commands = {}
|
|
260
|
+
smartbot_stats.each do |msg|
|
|
261
|
+
smartbot_stats_commands[msg["command"]] ||= 0
|
|
262
|
+
smartbot_stats_commands[msg["command"]] += 1
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
#total number of different commands
|
|
266
|
+
smartbot_stats_total_commands = smartbot_stats_commands.keys.length
|
|
267
|
+
messages << "\t\t\t Total different commands used: *#{smartbot_stats_total_commands}*"
|
|
268
|
+
|
|
269
|
+
#top three commands
|
|
270
|
+
smartbot_stats_commands = smartbot_stats_commands.sort_by { |k, v| v }.reverse.to_h
|
|
271
|
+
smartbot_stats_commands = smartbot_stats_commands.first(3).to_h
|
|
272
|
+
messages << "\t\t\t :speech_balloon: Top 3 commands:"
|
|
273
|
+
smartbot_stats_commands.each do |command, num|
|
|
274
|
+
messages << "\t\t\t\t*#{command}*: *#{num}*"
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
#top three commands excluding routines only if the top 3 is different from including routines
|
|
278
|
+
smartbot_stats_commands_include_routines = smartbot_stats_commands.deep_copy
|
|
279
|
+
|
|
280
|
+
smartbot_stats_commands = {}
|
|
281
|
+
smartbot_stats.each do |msg|
|
|
282
|
+
if !msg["user_name"].include?("routine/")
|
|
283
|
+
smartbot_stats_commands[msg["command"]] ||= 0
|
|
284
|
+
smartbot_stats_commands[msg["command"]] += 1
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
smartbot_stats_commands = smartbot_stats_commands.sort_by { |k, v| v }.reverse.to_h
|
|
288
|
+
smartbot_stats_commands = smartbot_stats_commands.first(3).to_h
|
|
289
|
+
if smartbot_stats_commands != smartbot_stats_commands_include_routines
|
|
290
|
+
messages << "\t\t\t :speech_balloon: Top 3 commands excluding routines:"
|
|
291
|
+
smartbot_stats_commands.each do |command, num|
|
|
292
|
+
messages << "\t\t\t\t*#{command}*: *#{num}*"
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
#get the three most used users. The user is stored on "user_name" field
|
|
297
|
+
smartbot_stats_user = smartbot_stats_user.sort_by { |k, v| v }.reverse.to_h
|
|
298
|
+
smartbot_stats_user = smartbot_stats_user.first(3).to_h
|
|
299
|
+
messages << "\t\t\t :bust_in_silhouette: Top 3 users calling SmartBot:"
|
|
300
|
+
smartbot_stats_user.each do |user, num|
|
|
301
|
+
messages << "\t\t\t\t<@#{user}>: *#{num}*"
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
#number of messages by month
|
|
306
|
+
hist_month = {}
|
|
307
|
+
hist_replies.each do |msg|
|
|
308
|
+
if Time.at(msg[:ts].to_f) >= date_start and Time.at(msg[:ts].to_f) <= date_end
|
|
309
|
+
date = Time.at(msg[:ts].to_f).strftime("%Y/%m")
|
|
310
|
+
hist_month[date] ||= 0
|
|
311
|
+
hist_month[date] += 1
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
hist_month = hist_month.sort_by { |k, v| k }.to_h
|
|
315
|
+
respond messages.join("\n")
|
|
316
|
+
messages = []
|
|
317
|
+
messages << "\t :memo: Number of messages by month:" if hist_month.size > 0
|
|
318
|
+
hist_month.each do |date, num|
|
|
319
|
+
graph = ":large_yellow_square: " * (num.to_f * (10 * hist_month.size) / hist_replies.size).round(2)
|
|
320
|
+
messages << "\t\t\t#{date}: #{graph} #{num} (#{num * 100 / hist_replies.size}%)"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
#number of users by month
|
|
324
|
+
hist_month_user = {}
|
|
325
|
+
hist_replies.each do |msg|
|
|
326
|
+
if Time.at(msg[:ts].to_f) >= date_start and Time.at(msg[:ts].to_f) <= date_end
|
|
327
|
+
date = Time.at(msg[:ts].to_f).strftime("%Y/%m")
|
|
328
|
+
hist_month_user[date] ||= []
|
|
329
|
+
hist_month_user[date] << msg.user
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
hist_month_user = hist_month_user.sort_by { |k, v| k }.to_h
|
|
333
|
+
respond messages.join("\n")
|
|
334
|
+
messages = []
|
|
335
|
+
messages << "\t :person_with_crown: Number of users by month:" if hist_month_user.size > 0
|
|
336
|
+
total_users_by_month = 0
|
|
337
|
+
hist_month_user.each do |date, users|
|
|
338
|
+
total_users_by_month += users.uniq.length
|
|
339
|
+
end
|
|
340
|
+
hist_month_user.each do |date, users|
|
|
341
|
+
graph = ":large_orange_square: " * (users.uniq.length.to_f * (10 * hist_month_user.size) / total_users_by_month).round(2)
|
|
342
|
+
messages << "\t\t\t#{date}: #{graph} #{users.uniq.length} "
|
|
343
|
+
end
|
|
344
|
+
if my_recap
|
|
345
|
+
respond messages.join("\n")
|
|
346
|
+
messages = []
|
|
347
|
+
messages << "\t :medal: *Recap for <@#{user[:id]}>*:"
|
|
348
|
+
messages << "\t\t\tTotal messages: *#{hist_user[user[:id]]}*"
|
|
349
|
+
# top three posts of user.name
|
|
350
|
+
hist_user_posts = hist.select { |msg| msg.user == user[:id] }
|
|
351
|
+
hist_user_posts = hist_user_posts.sort_by { |k| k[:reply_count] }
|
|
352
|
+
top_three_posts = [hist_user_posts[-1], hist_user_posts[-2], hist_user_posts[-3]]
|
|
353
|
+
messages << "\t\t\tTop 3 threads:"
|
|
354
|
+
top_three_posts.each do |post|
|
|
355
|
+
if !post.nil?
|
|
356
|
+
messages << "\t\t\t\t *#{post.reply_count}* replies: *<https://greenqloud.slack.com/archives/#{channel}/p#{post.ts.gsub(".", "")}|#{post.text[0..50].gsub(/[^a-zA-Z0-9\s]/, "").gsub("\n", "").strip}>*"
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
#Add also stats from SmartBot commands for this user
|
|
361
|
+
#filter stats by user
|
|
362
|
+
smartbot_stats_user = smartbot_stats.select { |msg| msg["user_id"] == user[:id] }
|
|
363
|
+
#get the number of times SmartBot was called by this user
|
|
364
|
+
smartbot_stats_user_total = smartbot_stats_user.length
|
|
365
|
+
messages << "\t\t\t SmartBot calls: *#{smartbot_stats_user_total}*"
|
|
366
|
+
#get the three most used commands by this user
|
|
367
|
+
smartbot_stats_user_commands = {}
|
|
368
|
+
smartbot_stats_user.each do |msg|
|
|
369
|
+
smartbot_stats_user_commands[msg["command"]] ||= 0
|
|
370
|
+
smartbot_stats_user_commands[msg["command"]] += 1
|
|
371
|
+
end
|
|
372
|
+
if smartbot_stats_user_total > 0
|
|
373
|
+
#total number of different commands
|
|
374
|
+
smartbot_stats_user_total_commands = smartbot_stats_user_commands.keys.length
|
|
375
|
+
messages << "\t\t\t Different commands: *#{smartbot_stats_user_total_commands}*"
|
|
376
|
+
#top three commands
|
|
377
|
+
smartbot_stats_user_commands = smartbot_stats_user_commands.sort_by { |k, v| v }.reverse.to_h
|
|
378
|
+
smartbot_stats_user_commands = smartbot_stats_user_commands.first(3).to_h
|
|
379
|
+
messages << "\t\t\t :speech_balloon: Top 3 commands:"
|
|
380
|
+
smartbot_stats_user_commands.each do |command, num|
|
|
381
|
+
messages << "\t\t\t\t\t*#{command}*: *#{num}*"
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
respond messages.join("\n")
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
rescue => e
|
|
391
|
+
@logger.fatal "recap command failed: #{e.message}"
|
|
392
|
+
@logger.fatal e.backtrace.inspect
|
|
393
|
+
respond "Sorry, `recap` command failed. <@#{config.admins.join(">,<@")}> please check the logs."
|
|
394
|
+
end
|
|
395
|
+
@history_still_running = false
|
|
396
|
+
end
|
|
397
|
+
unreact :runner
|
|
398
|
+
end
|
|
399
|
+
end
|
|
@@ -14,37 +14,47 @@ class SlackSmartBot
|
|
|
14
14
|
end
|
|
15
15
|
messages = []
|
|
16
16
|
admins = config.masters.dup
|
|
17
|
+
team_id_admins = config.team_id_masters.dup
|
|
17
18
|
channels = get_channels()
|
|
18
19
|
channel_found = channels.detect { |c| c.id == channel }
|
|
19
20
|
if !channel_found.nil? and channel_found.creator.to_s != ''
|
|
20
|
-
creator_info =
|
|
21
|
+
creator_info = find_user(channel_found.creator)
|
|
21
22
|
admins << creator_info.name
|
|
23
|
+
team_id_admins << "#{creator_info.team_id}_#{creator_info.name}"
|
|
22
24
|
end
|
|
23
25
|
if Thread.current[:typem] == :on_bot or Thread.current[:typem] == :on_master
|
|
24
26
|
admins << config.admins.dup
|
|
27
|
+
team_id_admins << config.team_id_admins.dup
|
|
25
28
|
end
|
|
26
29
|
if @admins_channels.key?(channel) and @admins_channels[channel].size > 0
|
|
27
|
-
|
|
30
|
+
team_id_admins << @admins_channels[channel]
|
|
31
|
+
#remove the team_id from the names on @admins_channels
|
|
32
|
+
admins << @admins_channels[channel].map { |a| a.split('_')[1..-1].join('_') }
|
|
28
33
|
end
|
|
29
34
|
admins.flatten!
|
|
30
35
|
admins.uniq!
|
|
31
36
|
admins.delete(nil)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
team_id_admins.flatten!
|
|
38
|
+
team_id_admins.uniq!
|
|
39
|
+
team_id_admins.delete(nil)
|
|
40
|
+
|
|
41
|
+
if team_id_admins.include?("#{user.team_id}_#{user.name}")
|
|
42
|
+
admin_info = find_user(admin_user)
|
|
43
|
+
if creator_info.name == admin_info.name and creator_info.team_id == admin_info.team_id
|
|
35
44
|
messages << "This user created the channel and cannot be removed as an admin."
|
|
36
|
-
elsif config.
|
|
45
|
+
elsif config.team_id_masters.include?("#{admin_info.team_id}_#{admin_info.name}") or config.team_id_masters.include?(admin_user)
|
|
37
46
|
messages << "Master admins cannot be removed as admins of this channel."
|
|
38
|
-
elsif config.
|
|
47
|
+
elsif config.team_id_admins.include?("#{admin_info.team_id}_#{admin_info.name}") or config.team_id_admins.include?(admin_user)
|
|
39
48
|
messages << "This user is a defaulted admin for this channel and cannot be removed using this command."
|
|
40
|
-
elsif !
|
|
49
|
+
elsif !team_id_admins.include?("#{admin_info.team_id}_#{admin_info.name}")
|
|
41
50
|
messages << "This user is not an admin of this channel."
|
|
42
51
|
else
|
|
43
52
|
@admins_channels[channel] ||= []
|
|
44
|
-
@admins_channels[channel].delete(admin_info.name)
|
|
53
|
+
@admins_channels[channel].delete("#{admin_info.team_id}_#{admin_info.name}")
|
|
45
54
|
update_admins_channels()
|
|
46
55
|
messages << "The user is not an admin of this channel from now on."
|
|
47
56
|
admins.delete(admin_info.name)
|
|
57
|
+
team_id_admins.delete("#{admin_info.team_id}_#{admin_info.name}")
|
|
48
58
|
end
|
|
49
59
|
messages << "*Admins*: <@#{admins.join('>, <@')}>"
|
|
50
60
|
else
|
|
@@ -3,24 +3,41 @@ class SlackSmartBot
|
|
|
3
3
|
save_stats(__method__)
|
|
4
4
|
|
|
5
5
|
get_vacations()
|
|
6
|
-
|
|
6
|
+
team_id_user = "#{user.team_id}_#{user.name}"
|
|
7
|
+
|
|
8
|
+
if !@vacations.key?(team_id_user)
|
|
7
9
|
respond "It seems like you don't have any time off added."
|
|
8
|
-
elsif @vacations[
|
|
10
|
+
elsif @vacations[team_id_user].periods.empty? or !@vacations[team_id_user].periods.vacation_id.include?(vacation_id)
|
|
9
11
|
respond "It seems like the ID supplied doesn't exist. Please call `see my time off` and check the ID."
|
|
10
12
|
else
|
|
11
|
-
vacations
|
|
13
|
+
if @vacations.key?(team_id_user) and @vacations[team_id_user][:public_holidays].to_s != ""
|
|
14
|
+
country_region = @vacations[team_id_user][:public_holidays].downcase
|
|
15
|
+
elsif config[:public_holidays].key?(:default_calendar)
|
|
16
|
+
country_region = config[:public_holidays][:default_calendar].downcase
|
|
17
|
+
else
|
|
18
|
+
country_region = ''
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
local_day_time = local_time(country_region)
|
|
22
|
+
if local_day_time.nil?
|
|
23
|
+
today = Date.today
|
|
24
|
+
else
|
|
25
|
+
today = local_day_time.to_date
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
vacations = @vacations[team_id_user].deep_copy
|
|
12
29
|
vacation = vacations.periods.select {|v| v.vacation_id == vacation_id }[-1]
|
|
13
30
|
vacations.periods.delete_if {|v| v.vacation_id == vacation_id }
|
|
14
|
-
update_vacations({
|
|
31
|
+
update_vacations({team_id_user => vacations})
|
|
15
32
|
respond "Your time off has been removed."
|
|
16
|
-
if vacation.from <=
|
|
33
|
+
if vacation.from <= today.strftime("%Y/%m/%d") and vacation.to >= today.strftime("%Y/%m/%d")
|
|
17
34
|
info = get_user_info(vacations.user_id)
|
|
18
35
|
emoji = info.user.profile.status_emoji
|
|
19
36
|
if (vacation.type == 'vacation' and emoji == ':palm_tree:') or (vacation.type == 'sick' and emoji == ':face_with_thermometer:') or
|
|
20
37
|
(vacation.type == 'sick child' and emoji == ':baby:')
|
|
21
38
|
set_status(vacations.user_id, status: '', expiration: '', message: '')
|
|
22
39
|
end
|
|
23
|
-
check_vacations(date:
|
|
40
|
+
check_vacations(date: today, team_id: user.team_id, user: user.name, set_status: true, only_first_day: false)
|
|
24
41
|
end
|
|
25
42
|
end
|
|
26
43
|
end
|
|
@@ -11,7 +11,8 @@ class SlackSmartBot
|
|
|
11
11
|
command_ids = get_command_ids()
|
|
12
12
|
if command_ids.values.flatten.include?(command_id)
|
|
13
13
|
if @access_channels.key?(channel) and @access_channels[channel].key?(command_id) and @access_channels[channel][command_id].size > 0
|
|
14
|
-
|
|
14
|
+
names = @access_channels[channel][command_id].map { |a| a.split('_')[1..-1].join('_') }
|
|
15
|
+
respond "Only these users have access to `#{command_id}` in this channel: <@#{names.join(">, <@")}>"
|
|
15
16
|
elsif @access_channels.key?(channel) and @access_channels[channel].key?(command_id) and @access_channels[channel][command_id].empty?
|
|
16
17
|
respond "`#{command_id}` is not possible to be used in this channel. Please contact an admin if you want to use it."
|
|
17
18
|
else
|
|
@@ -11,22 +11,26 @@ class SlackSmartBot
|
|
|
11
11
|
|
|
12
12
|
messages = []
|
|
13
13
|
admins = []
|
|
14
|
+
team_id_admins = []
|
|
14
15
|
channels = get_channels()
|
|
15
16
|
channel_found = channels.detect { |c| c.id == channel }
|
|
16
17
|
if !channel_found.nil? and channel_found.creator.to_s != ''
|
|
17
|
-
messages << "*Channel creator*: <@#{channel_found.creator}>"
|
|
18
|
-
creator_info =
|
|
18
|
+
messages << "*Channel creator*: <@#{channel_found.creator}>"
|
|
19
|
+
creator_info = find_user(channel_found.creator)
|
|
19
20
|
else
|
|
20
|
-
creator_info = {name: []}
|
|
21
|
+
creator_info = {name: [], team_id: []}
|
|
21
22
|
end
|
|
22
23
|
messages << "*Master admins*: <@#{config.masters.join('>, <@')}>"
|
|
23
24
|
if Thread.current[:typem] == :on_bot or Thread.current[:typem] == :on_master
|
|
24
25
|
admins = config.admins.dup
|
|
26
|
+
team_id_admins = config.team_id_admins.dup
|
|
25
27
|
end
|
|
26
28
|
if @admins_channels.key?(channel) and @admins_channels[channel].size > 0
|
|
27
|
-
|
|
29
|
+
team_id_admins = (@admins_channels[channel] + team_id_admins).uniq
|
|
30
|
+
admins = (@admins_channels[channel].map { |a| a.split('_')[1..-1].join('_') } + admins).uniq
|
|
28
31
|
end
|
|
29
32
|
admins = admins - config.masters - [creator_info.name]
|
|
33
|
+
team_id_admins = team_id_admins - config.team_id_masters - ["#{creator_info.team_id}_#{creator_info.name}"]
|
|
30
34
|
messages << "*Admins*: <@#{admins.join('>, <@')}>" unless admins.empty?
|
|
31
35
|
respond messages.join("\n")
|
|
32
36
|
end
|
|
@@ -16,9 +16,9 @@ class SlackSmartBot
|
|
|
16
16
|
else
|
|
17
17
|
dest = Thread.current[:dest]
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
if type == 'all'
|
|
21
|
-
if config.
|
|
21
|
+
if config.team_id_masters.include?("#{user.team_id}_#{user.name}") and typem==:on_dm
|
|
22
22
|
channels = Dir.entries("#{config.path}/announcements/")
|
|
23
23
|
channels.select! {|i| i[/\.csv$/]}
|
|
24
24
|
else
|
|
@@ -45,14 +45,14 @@ class SlackSmartBot
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
if has_access?(__method__, user)
|
|
48
|
-
if (channel_id!=Thread.current[:dest] and config.
|
|
48
|
+
if (channel_id!=Thread.current[:dest] and config.team_id_masters.include?("#{user.team_id}_#{user.name}") and typem==:on_dm) or publish
|
|
49
49
|
see_announcements_on_demand = true
|
|
50
50
|
else
|
|
51
51
|
see_announcements_on_demand = false
|
|
52
52
|
end
|
|
53
53
|
if channel_id == Thread.current[:dest] or see_announcements_on_demand or publish #master admin user or publish_announcements
|
|
54
54
|
if File.exist?("#{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'])
|
|
55
|
+
t = CSV.table("#{config.path}/announcements/#{channel_id}.csv", headers: ['message_id', 'user_team_id_deleted', 'user_deleted', 'user_team_id_created', 'user_created', 'date', 'time', 'type', 'message'])
|
|
56
56
|
@announcements[channel_id] = t
|
|
57
57
|
end
|
|
58
58
|
if @announcements.key?(channel_id)
|
|
@@ -70,7 +70,7 @@ class SlackSmartBot
|
|
|
70
70
|
user_created = "<@#{m[:user_created]}>"
|
|
71
71
|
else
|
|
72
72
|
user_created = m[:user_created]
|
|
73
|
-
user_info =
|
|
73
|
+
user_info = find_user(user_created)
|
|
74
74
|
user_created = user_info.profile.display_name unless user_info.nil?
|
|
75
75
|
end
|
|
76
76
|
if type == 'all' and channel_id[0]=='D'
|
|
@@ -9,18 +9,18 @@ class SlackSmartBot
|
|
|
9
9
|
else
|
|
10
10
|
channel = Thread.current[:using_channel]
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
files = Dir["#{config.stats_path}.*.log"].sort.reverse[0..1]
|
|
14
14
|
if files.empty?
|
|
15
15
|
respond "There is no data stored."
|
|
16
16
|
else
|
|
17
17
|
count_commands = {}
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
files.each do |file|
|
|
20
20
|
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
|
|
21
21
|
row[:dest_channel_id] = row[:bot_channel_id] if row[:dest_channel_id].to_s[0] == "D"
|
|
22
|
-
if ((only_mine and row[:user_name]==user.name) or (!only_mine and !config.
|
|
23
|
-
row[:dest_channel_id] == channel and !row[:user_name].include?('routine/') and
|
|
22
|
+
if ((only_mine and row[:user_name]==user.name) or (!only_mine and !config.team_id_masters.include?("#{row[:team_id]}_#{row[:user_name]}"))) and
|
|
23
|
+
row[:dest_channel_id] == channel and !row[:user_name].include?('routine/') and
|
|
24
24
|
row[:command] != 'dont_understand'
|
|
25
25
|
row[:command] = 'bot_help' if row[:command] == 'bot_rules'
|
|
26
26
|
count_commands[row[:command]] ||= 0
|
|
@@ -12,7 +12,7 @@ class SlackSmartBot
|
|
|
12
12
|
|
|
13
13
|
general_message = "\nRelated commands `share messages /RegExp/ on #CHANNEL`, `share messages \"TEXT\" on #CHANNEL`, `delete share ID`"
|
|
14
14
|
if File.exist?("#{config.path}/shares/#{@channels_name[channel]}.csv")
|
|
15
|
-
t = CSV.table("#{config.path}/shares/#{@channels_name[channel]}.csv", headers: ['share_id', 'user_deleted', 'user_created', 'date', 'time', 'type', 'to_channel', 'condition'])
|
|
15
|
+
t = CSV.table("#{config.path}/shares/#{@channels_name[channel]}.csv", headers: ['share_id', 'user_team_id_deleted', 'user_deleted', 'user_team_id_created', 'user_created', 'date', 'time', 'type', 'to_channel', 'condition'])
|
|
16
16
|
message =[]
|
|
17
17
|
t.each do |m|
|
|
18
18
|
if m[:user_deleted] == ''
|