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.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +237 -48
  3. data/img/chat_gpt.png +0 -0
  4. data/img/chat_gpt_session.png +0 -0
  5. data/img/chat_gpt_share.png +0 -0
  6. data/img/command_add_sc.png +0 -0
  7. data/img/command_bot_help_echo.png +0 -0
  8. data/img/command_loop.png +0 -0
  9. data/img/command_my_timeoff.png +0 -0
  10. data/img/command_recap.png +0 -0
  11. data/img/command_repl1.png +0 -0
  12. data/img/command_repl2.png +0 -0
  13. data/img/command_ruby.png +0 -0
  14. data/img/command_run_repl.png +0 -0
  15. data/img/command_see_announcements.png +0 -0
  16. data/img/command_see_statuses.png +0 -0
  17. data/img/command_see_team.png +0 -0
  18. data/img/command_summarize.png +0 -0
  19. data/img/commands_inline.png +0 -0
  20. data/img/commands_on_demand.png +0 -0
  21. data/img/commands_on_external_call.png +0 -0
  22. data/img/image_editing.png +0 -0
  23. data/img/image_generation.png +0 -0
  24. data/img/image_variations.png +0 -0
  25. data/img/openai-300.png +0 -0
  26. data/img/openai.png +0 -0
  27. data/img/slack-300.png +0 -0
  28. data/img/slack.png +0 -0
  29. data/img/smart-bot-150.png +0 -0
  30. data/img/smart-bot-profile-pic-2.png +0 -0
  31. data/img/smart-bot-profile-pic.png +0 -0
  32. data/img/smart-bot.png +0 -0
  33. data/img/whisper.png +0 -0
  34. data/lib/slack/smart-bot/ai/open_ai/connect.rb +165 -43
  35. data/lib/slack/smart-bot/ai/open_ai/models.rb +61 -9
  36. data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +67 -11
  37. data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +4 -3
  38. data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +4 -4
  39. data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +4 -3
  40. data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +4 -3
  41. data/lib/slack/smart-bot/comm/ask.rb +20 -8
  42. data/lib/slack/smart-bot/comm/dont_understand.rb +2 -2
  43. data/lib/slack/smart-bot/comm/event_hello.rb +30 -1
  44. data/lib/slack/smart-bot/comm/get_channel_members.rb +2 -1
  45. data/lib/slack/smart-bot/comm/get_presence.rb +1 -0
  46. data/lib/slack/smart-bot/comm/get_smartbot_team_info.rb +10 -0
  47. data/lib/slack/smart-bot/comm/get_user_info.rb +45 -6
  48. data/lib/slack/smart-bot/comm/get_users.rb +8 -1
  49. data/lib/slack/smart-bot/comm/respond.rb +225 -196
  50. data/lib/slack/smart-bot/comm/send_msg_channel.rb +2 -2
  51. data/lib/slack/smart-bot/comm/send_msg_user.rb +10 -9
  52. data/lib/slack/smart-bot/comm/unreact.rb +2 -2
  53. data/lib/slack/smart-bot/comm.rb +1 -0
  54. data/lib/slack/smart-bot/commands/general/add_admin.rb +16 -6
  55. data/lib/slack/smart-bot/commands/general/add_announcement.rb +3 -3
  56. data/lib/slack/smart-bot/commands/general/add_vacation.rb +28 -12
  57. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +272 -23
  58. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +42 -0
  59. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +89 -0
  60. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +45 -0
  61. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +41 -0
  62. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +81 -0
  63. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +52 -0
  64. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +52 -0
  65. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +14 -11
  66. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +15 -11
  67. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +29 -17
  68. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +16 -13
  69. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +13 -7
  70. data/lib/slack/smart-bot/commands/general/allow_access.rb +8 -4
  71. data/lib/slack/smart-bot/commands/general/bot_help.rb +24 -9
  72. data/lib/slack/smart-bot/commands/general/bye_bot.rb +9 -5
  73. data/lib/slack/smart-bot/commands/general/delete_announcement.rb +2 -1
  74. data/lib/slack/smart-bot/commands/general/delete_share.rb +2 -1
  75. data/lib/slack/smart-bot/commands/general/deny_access.rb +1 -1
  76. data/lib/slack/smart-bot/commands/general/get_smartbot_readme.rb +15 -0
  77. data/lib/slack/smart-bot/commands/general/hi_bot.rb +10 -4
  78. data/lib/slack/smart-bot/commands/general/personal_settings.rb +26 -8
  79. data/lib/slack/smart-bot/commands/general/poster.rb +26 -2
  80. data/lib/slack/smart-bot/commands/general/public_holidays.rb +14 -24
  81. data/lib/slack/smart-bot/commands/general/recap.rb +399 -0
  82. data/lib/slack/smart-bot/commands/general/remove_admin.rb +19 -9
  83. data/lib/slack/smart-bot/commands/general/remove_vacation.rb +23 -6
  84. data/lib/slack/smart-bot/commands/general/see_access.rb +2 -1
  85. data/lib/slack/smart-bot/commands/general/see_admins.rb +8 -4
  86. data/lib/slack/smart-bot/commands/general/see_announcements.rb +5 -5
  87. data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +4 -4
  88. data/lib/slack/smart-bot/commands/general/see_shares.rb +1 -1
  89. data/lib/slack/smart-bot/commands/general/see_vacations.rb +34 -17
  90. data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +4 -2
  91. data/lib/slack/smart-bot/commands/general/share_messages.rb +3 -3
  92. data/lib/slack/smart-bot/commands/general/summarize.rb +191 -0
  93. data/lib/slack/smart-bot/commands/general/teams/add_team.rb +4 -8
  94. data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +3 -3
  95. data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +34 -29
  96. data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +1 -1
  97. data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +6 -4
  98. data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +26 -15
  99. data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +33 -24
  100. data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +4 -4
  101. data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +10 -8
  102. data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +73 -61
  103. data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +28 -13
  104. data/lib/slack/smart-bot/commands/general/teams/update_team.rb +9 -9
  105. data/lib/slack/smart-bot/commands/general_bot_commands.rb +1153 -835
  106. data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +19 -17
  107. data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +12 -9
  108. data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +2 -0
  109. data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +1 -0
  110. data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +5 -3
  111. data/lib/slack/smart-bot/commands/on_bot/admin_master/delete_message.rb +2 -3
  112. data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +2 -3
  113. data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +2 -3
  114. data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +7 -6
  115. data/lib/slack/smart-bot/commands/on_bot/admin_master/update_message.rb +2 -3
  116. data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +1 -1
  117. data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +21 -20
  118. data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +40 -7
  119. data/lib/slack/smart-bot/commands/on_bot/general/bot_status.rb +6 -2
  120. data/lib/slack/smart-bot/commands/on_bot/general/stop_using_rules.rb +7 -6
  121. data/lib/slack/smart-bot/commands/on_bot/general/suggest_command.rb +5 -4
  122. data/lib/slack/smart-bot/commands/on_bot/general/use_rules.rb +4 -3
  123. data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +4 -4
  124. data/lib/slack/smart-bot/commands/on_bot/kill_repl.rb +1 -1
  125. data/lib/slack/smart-bot/commands/on_bot/repl.rb +110 -53
  126. data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +35 -29
  127. data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +5 -5
  128. data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +1 -2
  129. data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +5 -4
  130. data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +22 -11
  131. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +12 -7
  132. data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +2 -2
  133. data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +1 -1
  134. data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +5 -5
  135. data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +5 -5
  136. data/lib/slack/smart-bot/commands/on_master/create_bot.rb +3 -3
  137. data/lib/slack/smart-bot/commands.rb +10 -0
  138. data/lib/slack/smart-bot/config.rb +126 -0
  139. data/lib/slack/smart-bot/listen.rb +12 -11
  140. data/lib/slack/smart-bot/process.rb +62 -55
  141. data/lib/slack/smart-bot/process_first.rb +106 -65
  142. data/lib/slack/smart-bot/treat_message.rb +79 -47
  143. data/lib/slack/smart-bot/utils/answer.rb +11 -3
  144. data/lib/slack/smart-bot/utils/answer_delete.rb +11 -3
  145. data/lib/slack/smart-bot/utils/check_vacations.rb +21 -3
  146. data/lib/slack/smart-bot/utils/create_routine_thread.rb +13 -13
  147. data/lib/slack/smart-bot/utils/display_calendar.rb +42 -8
  148. data/lib/slack/smart-bot/utils/encryption/decrypt.rb +16 -9
  149. data/lib/slack/smart-bot/utils/encryption/encrypt.rb +14 -11
  150. data/lib/slack/smart-bot/utils/find_user.rb +71 -0
  151. data/lib/slack/smart-bot/utils/get_access_channels.rb +22 -3
  152. data/lib/slack/smart-bot/utils/get_channels_name_and_id.rb +3 -4
  153. data/lib/slack/smart-bot/utils/get_command_ids.rb +5 -5
  154. data/lib/slack/smart-bot/utils/get_countries_candelarific.rb +18 -0
  155. data/lib/slack/smart-bot/utils/get_help.rb +21 -19
  156. data/lib/slack/smart-bot/utils/get_openai_sessions.rb +47 -0
  157. data/lib/slack/smart-bot/utils/get_personal_settings.rb +29 -3
  158. data/lib/slack/smart-bot/utils/get_rules_imported.rb +27 -6
  159. data/lib/slack/smart-bot/utils/get_shares.rb +1 -1
  160. data/lib/slack/smart-bot/utils/get_team_members.rb +4 -4
  161. data/lib/slack/smart-bot/utils/get_vacations.rb +15 -7
  162. data/lib/slack/smart-bot/utils/has_access.rb +10 -4
  163. data/lib/slack/smart-bot/utils/is_admin.rb +25 -17
  164. data/lib/slack/smart-bot/utils/local_time.rb +29 -0
  165. data/lib/slack/smart-bot/utils/save_stats.rb +5 -3
  166. data/lib/slack/smart-bot/utils/update_access_channels.rb +19 -3
  167. data/lib/slack/smart-bot/utils/update_openai_sessions.rb +42 -0
  168. data/lib/slack/smart-bot/utils/update_personal_settings.rb +11 -3
  169. data/lib/slack/smart-bot/utils/update_rules_imported.rb +18 -3
  170. data/lib/slack/smart-bot/utils/update_vacations.rb +5 -2
  171. data/lib/slack/smart-bot/utils/upgrade_to_use_team_ids.rb +276 -0
  172. data/lib/slack/smart-bot/utils.rb +6 -1
  173. data/lib/slack-smart-bot.rb +182 -76
  174. data/lib/slack-smart-bot_general_commands.rb +10 -9
  175. data/whats_new.txt +30 -13
  176. metadata +152 -18
@@ -1,16 +1,55 @@
1
1
  class SlackSmartBot
2
2
 
3
- def get_user_info(user)
3
+ def get_user_info(user, is_bot: false)
4
4
  begin
5
5
  if user.to_s.length>0
6
- if config.simulate and config.key?(:client)
7
- if user[0]=='@' #name
8
- client.web_client.users_info.select{|k, v| v[:user][:name] == user[1..-1]}.values[-1]
9
- else #id
6
+ if user[0]=='@' #name
7
+ user = user[1..-1]
8
+ is_name = true
9
+ else
10
+ is_name = false
11
+ end
12
+ if user.match?(/^[A-Z0-9]{7,11}_/) #team_id_user_name
13
+ team_id = user.split('_')[0]
14
+ user = user.split('_')[1..-1].join('_')
15
+ else
16
+ team_id = config.team_id
17
+ end
18
+ if config.simulate and config.key?(:client) #todo: add support for bots
19
+ if client.web_client.users_info.key?(user.to_sym) #id
10
20
  client.web_client.users_info[user.to_sym]
21
+ else #name
22
+ client.web_client.users_info.select{|k, v| v[:user][:name] == user and v[:user][:team_id] == team_id}.values[-1]
11
23
  end
12
24
  else
13
- client.web_client.users_info(user: user)
25
+ if is_bot
26
+ @logger.info "Getting bot info for <#{user}>"
27
+ begin
28
+ result = client.web_client.bots_info(bot: user)
29
+ rescue Exception => stack
30
+ @logger.warn stack
31
+ return nil
32
+ end
33
+ if !result.nil? and result.key?(:bot) and result[:bot].key?(:user_id)
34
+ user = result[:bot][:user_id]
35
+ is_name = false
36
+ else
37
+ return nil
38
+ end
39
+ end
40
+ #todo: see how to get user info using also the team_id
41
+ if is_name
42
+ result = client.web_client.users_info(user: "@#{user}")
43
+ else
44
+ result = client.web_client.users_info(user: user)
45
+ end
46
+ # in case of Enterprise Grid we use the enterprise_id as team_id and the enterprise_user id as user_id
47
+ if !result.nil? and result.key?(:user) and result[:user].key?(:enterprise_user) and result[:user][:enterprise_user].key?(:enterprise_id)
48
+ result[:user][:team_id] = result[:user][:enterprise_user][:enterprise_id]
49
+ result[:user][:id] = result[:user][:enterprise_user][:id]
50
+ end
51
+
52
+ return result
14
53
  end
15
54
  end
16
55
  rescue Exception => stack
@@ -4,7 +4,7 @@ class SlackSmartBot
4
4
  begin
5
5
  users = []
6
6
  cursor = nil
7
- if config.simulate
7
+ if config.simulate
8
8
  users = client.web_client.users_list
9
9
  else
10
10
  begin
@@ -16,6 +16,13 @@ class SlackSmartBot
16
16
  end until cursor.empty?
17
17
  users.flatten!
18
18
  end
19
+ users.each do |user|
20
+ # in case of Enterprise Grid we use the enterprise_id as team_id and the enterprise_user id as user_id
21
+ if user.key?(:enterprise_user) and user[:enterprise_user].key?(:enterprise_id)
22
+ user[:team_id] = user[:enterprise_user][:enterprise_id]
23
+ user[:id] = user[:enterprise_user][:id]
24
+ end
25
+ end
19
26
  return users
20
27
  rescue Exception => stack
21
28
  @logger.warn stack
@@ -2,241 +2,270 @@ class SlackSmartBot
2
2
  def respond(msg = "", dest = nil, unfurl_links: true, unfurl_media: true, thread_ts: "", web_client: true, blocks: [], dont_share: false, return_message: false, max_chars_per_message: 4000)
3
3
  result = true
4
4
  resp = nil
5
- if (msg.to_s != "" or !msg.to_s.match?(/^A\s*\z/) or !blocks.empty?) and Thread.current[:routine_type].to_s != "bgroutine"
6
- if !web_client.is_a?(TrueClass) and !web_client.is_a?(FalseClass)
7
- (!unfurl_links or !unfurl_media) ? web_client = true : web_client = false
8
- end
9
- begin
10
- msg = msg.to_s
11
- web_client = true if !blocks.empty?
12
5
 
13
- on_thread = Thread.current[:on_thread]
14
- if dest.nil? and Thread.current.key?(:dest)
15
- dest = Thread.current[:dest]
16
- elsif dest.is_a?(Symbol) and dest == :on_thread
17
- on_thread = true
18
- dest = Thread.current[:dest]
19
- elsif dest.is_a?(Symbol) and dest == :direct
20
- dest = Thread.current[:user].id
21
- end
22
- if thread_ts.to_s.match?(/^\d+\.\d+$/)
23
- on_thread = true
24
- #thread id
25
- elsif thread_ts.to_s.match?(/^p\d\d\d\d\d+$/)
26
- on_thread = true
27
- #a thread id taken from url fex: p1622549264010700
28
- thread_ts = thread_ts.scan(/(\d+)/).join
29
- thread_ts = "#{thread_ts[0..9]}.#{thread_ts[10..-1]}"
30
- else
31
- thread_ts = Thread.current[:thread_ts] if thread_ts == ""
32
- end
33
-
34
- dest = @channels_id[dest] if @channels_id.key?(dest) #it is a name of channel
6
+ if Thread.current.key?(:prompt) and !Thread.current[:prompt].empty? #don't send response to slack since chatgpt will get the response from stdout
7
+ Thread.current[:stdout] += "#{msg}\n"
8
+ return true
9
+ else
10
+ if (msg.to_s != "" or !msg.to_s.match?(/^A\s*\z/) or !blocks.empty?) and Thread.current[:routine_type].to_s != "bgroutine"
11
+ if !web_client.is_a?(TrueClass) and !web_client.is_a?(FalseClass)
12
+ (!unfurl_links or !unfurl_media) ? web_client = true : web_client = false
13
+ end
14
+ begin
15
+ msg = msg.to_s
16
+ web_client = true if !blocks.empty?
35
17
 
36
- on_thread ? txt_on_thread=':on_thread:' : txt_on_thread=''
37
-
38
- if blocks.empty?
39
- if !config.simulate #https://api.slack.com/docs/rate-limits
40
- msg.size > 500 ? wait = 0.5 : wait = 0.1
41
- sleep wait if Time.now <= (@last_respond + wait)
42
- else
43
- wait = 0
18
+ on_thread = Thread.current[:on_thread]
19
+ if dest.nil? and Thread.current.key?(:dest)
20
+ dest = Thread.current[:dest]
21
+ elsif dest.is_a?(Symbol) and dest == :on_thread
22
+ on_thread = true
23
+ dest = Thread.current[:dest]
24
+ elsif dest.is_a?(Symbol) and dest == :direct
25
+ dest = Thread.current[:user].id
44
26
  end
45
- msgs = [] # max of max_chars_per_message characters per message
46
- if max_chars_per_message.nil?
47
- txt = msg
27
+ if thread_ts.to_s.match?(/^\d+\.\d+$/)
28
+ on_thread = true
29
+ #thread id
30
+ elsif thread_ts.to_s.match?(/^p\d\d\d\d\d+$/)
31
+ on_thread = true
32
+ #a thread id taken from url fex: p1622549264010700
33
+ thread_ts = thread_ts.scan(/(\d+)/).join
34
+ thread_ts = "#{thread_ts[0..9]}.#{thread_ts[10..-1]}"
48
35
  else
49
- txt = ""
50
- msg.split("\n").each do |m|
51
- if (m + txt).size > max_chars_per_message
52
- unless txt == ""
53
- txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
54
- t = txt.chars.each_slice(max_chars_per_message).map(&:join)
55
- msgs << t
56
- txt = ""
57
- end
58
- end
59
- txt += (m + "\n")
60
- txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
61
- txt[0] = ". " if txt.match?(/\A\t/)
62
- end
36
+ thread_ts = Thread.current[:thread_ts] if thread_ts == ""
63
37
  end
64
- msgs << txt
65
- msgs.flatten!
66
- msgs.delete_if{|e| e.match?(/\A\s*\z/)}
67
- if dest.nil?
68
- if config[:simulate]
69
- open("#{config.path}/buffer_complete.log", "a") { |f|
70
- f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~"
71
- }
38
+
39
+ dest = @channels_id[dest] if @channels_id.key?(dest) #it is a name of channel
40
+
41
+ on_thread ? txt_on_thread=":on_thread:" : txt_on_thread=''
42
+
43
+ if blocks.empty?
44
+ if !config.simulate #https://api.slack.com/docs/rate-limits
45
+ msg.size > 500 ? wait = 0.5 : wait = 0.1
46
+ sleep wait if Time.now <= (@last_respond + wait)
72
47
  else
73
- if on_thread
74
- msgs.each do |msg|
75
- if web_client
76
- resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
77
- else
78
- resp = client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
48
+ wait = 0
49
+ end
50
+ msgs = [] # max of max_chars_per_message characters per message
51
+ if max_chars_per_message.nil?
52
+ txt = msg
53
+ else
54
+ txt = ""
55
+ in_a_code_block = false
56
+ print_previous = false
57
+ all_lines = msg.split("\n")
58
+
59
+ all_lines.each_with_index do |m, i|
60
+ if m.match?(/^\s*```/)
61
+ in_a_code_block = !in_a_code_block
62
+ num_chars_code = 0
63
+ print_previous = false
64
+ if in_a_code_block
65
+ all_lines[i+1..-1].each do |l|
66
+ num_chars_code += l.size
67
+ break if l.match?(/^\s*```/)
68
+ end
69
+ if num_chars_code + (m + txt).size > max_chars_per_message
70
+ print_previous = true
71
+ end
79
72
  end
80
- sleep wait
81
- end
82
- else
83
- msgs.each do |msg|
84
- if web_client
85
- resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
86
- else
87
- resp = client.message(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
73
+ end
74
+ if ((m + txt).size > max_chars_per_message and !in_a_code_block) or print_previous
75
+ unless txt == ""
76
+ txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
77
+ if m.match?(/^\s*```\s*$/) and !in_a_code_block
78
+ txt += (m + "\n")
79
+ m = ""
80
+ end
81
+ t = txt.chars.each_slice(max_chars_per_message).map(&:join)
82
+ msgs << t
83
+ txt = ""
84
+ print_previous = false if print_previous
88
85
  end
89
- sleep wait
90
86
  end
87
+ txt += (m + "\n")
88
+ txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
89
+ txt[0] = ". " if txt.match?(/\A\t/)
91
90
  end
92
91
  end
93
- if config[:testing] and config.on_master_bot and !@buffered
94
- @buffered = true
95
- open("#{config.path}/buffer.log", "a") { |f|
96
- f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
97
- }
98
- end
99
- elsif dest[0] == "C" or dest[0] == "G" # channel
100
- if config[:simulate]
101
- open("#{config.path}/buffer_complete.log", "a") { |f|
102
- f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~"
103
- }
104
- else
105
- if on_thread
106
- msgs.each do |msg|
107
- if web_client
108
- resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
109
- else
110
- resp = client.message(channel: dest, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
92
+ msgs << txt
93
+ msgs.flatten!
94
+ msgs.delete_if{|e| e.match?(/\A\s*\z/)}
95
+ if dest.nil?
96
+ if config[:simulate]
97
+ open("#{config.path}/buffer_complete.log", "a") { |f|
98
+ f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~"
99
+ }
100
+ else
101
+ if on_thread
102
+ msgs.each do |msg|
103
+ if web_client
104
+ resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
105
+ else
106
+ resp = client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
107
+ end
108
+ sleep wait
109
+ end
110
+ else
111
+ msgs.each do |msg|
112
+ if web_client
113
+ resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
114
+ else
115
+ resp = client.message(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
116
+ end
117
+ sleep wait
111
118
  end
112
- sleep wait
113
119
  end
120
+ end
121
+ if config[:testing] and config.on_master_bot and !@buffered
122
+ @buffered = true
123
+ open("#{config.path}/buffer.log", "a") { |f|
124
+ f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
125
+ }
126
+ end
127
+ elsif dest[0] == "C" or dest[0] == "G" # channel
128
+ if config[:simulate]
129
+ open("#{config.path}/buffer_complete.log", "a") { |f|
130
+ f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~"
131
+ }
114
132
  else
115
- msgs.each do |msg|
116
- if web_client
117
- resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
118
- else
119
- resp = client.message(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
133
+ if on_thread
134
+ msgs.each do |msg|
135
+ if web_client
136
+ resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
137
+ else
138
+ resp = client.message(channel: dest, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
139
+ end
140
+ sleep wait
141
+ end
142
+ else
143
+ msgs.each do |msg|
144
+ if web_client
145
+ resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
146
+ else
147
+ resp = client.message(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
148
+ end
149
+ sleep wait
120
150
  end
121
- sleep wait
122
151
  end
123
152
  end
124
- end
125
- if config[:testing] and config.on_master_bot and !@buffered
126
- @buffered = true
127
- open("#{config.path}/buffer.log", "a") { |f|
128
- f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
129
- }
130
- end
131
- elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
132
- msgs.each do |msg|
133
- resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
134
- sleep wait
135
- end
136
- elsif dest[0] == "@"
137
- begin
138
- user_info = @users.select { |u| u.id == dest[1..-1] or u.name == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1]
153
+ if config[:testing] and config.on_master_bot and !@buffered
154
+ @buffered = true
155
+ open("#{config.path}/buffer.log", "a") { |f|
156
+ f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
157
+ }
158
+ end
159
+ elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
139
160
  msgs.each do |msg|
140
- resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
161
+ resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
141
162
  sleep wait
142
163
  end
143
- rescue Exception => stack
144
- @logger.warn("user #{dest} not found.")
145
- @logger.warn stack
146
- if Thread.current.key?(:dest)
147
- respond("User #{dest} not found.")
164
+ elsif dest[0] == "@"
165
+ begin
166
+ user_info = @users.select { |u| u.id == dest[1..-1] or u.name == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1]
167
+ msgs.each do |msg|
168
+ resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
169
+ sleep wait
170
+ end
171
+ rescue Exception => stack
172
+ @logger.warn("user #{dest} not found.")
173
+ @logger.warn stack
174
+ if Thread.current.key?(:dest)
175
+ respond("User #{dest} not found.")
176
+ end
177
+ result = false
148
178
  end
179
+ else
180
+ @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}")
149
181
  result = false
150
182
  end
151
183
  else
152
- @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}")
153
- result = false
154
- end
155
- else
156
- wait = 0.1
157
- if dest.nil?
158
- if config[:simulate]
159
- open("#{config.path}/buffer_complete.log", "a") { |f|
160
- f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~"
161
- }
162
- else
163
- if on_thread
164
- blocks.each_slice(40).to_a.each do |blockstmp|
165
- resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true, thread_ts: thread_ts)
166
- sleep wait
167
- end
184
+ wait = 0.1
185
+ if dest.nil?
186
+ if config[:simulate]
187
+ open("#{config.path}/buffer_complete.log", "a") { |f|
188
+ f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~"
189
+ }
168
190
  else
169
- blocks.each_slice(40).to_a.each do |blockstmp|
170
- resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true)
171
- sleep wait
191
+ if on_thread
192
+ blocks.each_slice(40).to_a.each do |blockstmp|
193
+ resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true, thread_ts: thread_ts)
194
+ sleep wait
195
+ end
196
+ else
197
+ blocks.each_slice(40).to_a.each do |blockstmp|
198
+ resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true)
199
+ sleep wait
200
+ end
172
201
  end
173
202
  end
174
- end
175
- if config[:testing] and config.on_master_bot and !@buffered
176
- @buffered = true
177
- open("#{config.path}/buffer.log", "a") { |f|
178
- f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}"
179
- }
180
- end
181
- elsif dest[0] == "C" or dest[0] == "G" # channel
182
- if config[:simulate]
183
- open("#{config.path}/buffer_complete.log", "a") { |f|
184
- f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~"
185
- }
186
- else
187
- if on_thread
188
- blocks.each_slice(40).to_a.each do |blockstmp|
189
- resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true, thread_ts: thread_ts)
190
- sleep wait
191
- end
203
+ if config[:testing] and config.on_master_bot and !@buffered
204
+ @buffered = true
205
+ open("#{config.path}/buffer.log", "a") { |f|
206
+ f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}"
207
+ }
208
+ end
209
+ elsif dest[0] == "C" or dest[0] == "G" # channel
210
+ if config[:simulate]
211
+ open("#{config.path}/buffer_complete.log", "a") { |f|
212
+ f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~"
213
+ }
192
214
  else
193
- blocks.each_slice(40).to_a.each do |blockstmp|
194
- resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true)
195
- sleep wait
215
+ if on_thread
216
+ blocks.each_slice(40).to_a.each do |blockstmp|
217
+ resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true, thread_ts: thread_ts)
218
+ sleep wait
219
+ end
220
+ else
221
+ blocks.each_slice(40).to_a.each do |blockstmp|
222
+ resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true)
223
+ sleep wait
224
+ end
196
225
  end
197
226
  end
198
- end
199
- if config[:testing] and config.on_master_bot and !@buffered
200
- @buffered = true
201
- open("#{config.path}/buffer.log", "a") { |f|
202
- f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}"
203
- }
204
- end
205
- elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
206
- blocks.each_slice(40).to_a.each do |blockstmp|
207
- resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp)
208
- sleep wait
209
- end
210
- elsif dest[0] == "@"
211
- begin
212
- user_info = @users.select { |u| u.id == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1]
227
+ if config[:testing] and config.on_master_bot and !@buffered
228
+ @buffered = true
229
+ open("#{config.path}/buffer.log", "a") { |f|
230
+ f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}"
231
+ }
232
+ end
233
+ elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
213
234
  blocks.each_slice(40).to_a.each do |blockstmp|
214
- resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp)
235
+ resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp, thread_ts: thread_ts)
215
236
  sleep wait
216
237
  end
217
- rescue Exception => stack
218
- @logger.warn("user #{dest} not found.")
219
- @logger.warn stack
220
- if Thread.current.key?(:dest)
221
- respond("User #{dest} not found.")
238
+ elsif dest[0] == "@"
239
+ begin
240
+ user_info = @users.select { |u| u.id == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1]
241
+ blocks.each_slice(40).to_a.each do |blockstmp|
242
+ resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp, thread_ts: thread_ts)
243
+ sleep wait
244
+ end
245
+ rescue Exception => stack
246
+ @logger.warn("user #{dest} not found.")
247
+ @logger.warn stack
248
+ if Thread.current.key?(:dest)
249
+ respond("User #{dest} not found.")
250
+ end
251
+ result = false
222
252
  end
253
+ else
254
+ @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}")
223
255
  result = false
224
256
  end
225
- else
226
- @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}")
227
- result = false
228
257
  end
258
+ @last_respond = Time.now
259
+ rescue Exception => stack
260
+ @logger.warn stack
261
+ result = false
229
262
  end
230
- @last_respond = Time.now
231
- rescue Exception => stack
232
- @logger.warn stack
233
- result = false
234
263
  end
264
+ if Thread.current.key?(:routine) and Thread.current[:routine]
265
+ File.write("#{config.path}/routines/#{@channel_id}/#{Thread.current[:routine_name]}_output.txt", msg, mode: "a+")
266
+ end
267
+ result = resp if return_message
268
+ return result
235
269
  end
236
- if Thread.current.key?(:routine) and Thread.current[:routine]
237
- File.write("#{config.path}/routines/#{@channel_id}/#{Thread.current[:routine_name]}_output.txt", msg, mode: "a+")
238
- end
239
- result = resp if return_message
240
- return result
241
270
  end
242
271
  end
@@ -15,7 +15,7 @@ class SlackSmartBot
15
15
  end
16
16
  if config[:simulate]
17
17
  open("#{config.path}/buffer_complete.log", "a") { |f|
18
- f.puts "|#{channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{msg}~~~"
18
+ f.puts "|#{channel_id}|#{Thread.current[:thread_ts]}|#{config[:nick_id]}|#{config[:nick]}|#{msg}~~~"
19
19
  }
20
20
  else
21
21
  if Thread.current[:on_thread]
@@ -27,7 +27,7 @@ class SlackSmartBot
27
27
  if config[:testing] and config.on_master_bot and !@buffered
28
28
  @buffered = true
29
29
  open("#{config.path}/buffer.log", "a") { |f|
30
- f.puts "|#{channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
30
+ f.puts "|#{channel_id}|#{Thread.current[:thread_ts]}|#{config[:nick_id]}|#{config[:nick]}|#{msg}"
31
31
  }
32
32
  end
33
33
  rescue Exception => stack
@@ -1,27 +1,28 @@
1
1
  class SlackSmartBot
2
2
 
3
3
  #to send messages without listening for a response to users
4
- def send_msg_user(id_user, msg='', on_thread=nil, unfurl_links: true, unfurl_media: true, blocks: [], web_client: true)
4
+ def send_msg_user(id_user, msg='', on_thread=nil, unfurl_links: true, unfurl_media: true, blocks: [], web_client: true, thread_ts: nil)
5
5
  resp = nil
6
6
  unless msg == "" and blocks.empty?
7
7
  begin
8
8
  on_thread = Thread.current[:on_thread] if on_thread.nil?
9
+ thread_ts = Thread.current[:thread_ts] if thread_ts.to_s == ""
9
10
  web_client = true if !blocks.empty? or !unfurl_links or !unfurl_media
10
11
  if id_user[0] == "D"
11
12
  if config[:simulate]
12
13
  open("#{config.path}/buffer_complete.log", "a") { |f|
13
- f.puts "|#{id_user}|#{config[:nick_id]}|#{config[:nick]}|#{msg}~~~"
14
+ f.puts "|#{id_user}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}~~~"
14
15
  }
15
16
  else
16
17
  if web_client
17
18
  if on_thread
18
- resp = client.web_client.chat_postMessage(channel: id_user, text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: Thread.current[:thread_ts])
19
+ resp = client.web_client.chat_postMessage(channel: id_user, text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
19
20
  else
20
21
  resp = client.web_client.chat_postMessage(channel: id_user, text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
21
22
  end
22
23
  else
23
24
  if on_thread
24
- resp = client.message(channel: id_user, as_user: true, text: msg, thread_ts: Thread.current[:thread_ts], unfurl_links: unfurl_links, unfurl_media: unfurl_media)
25
+ resp = client.message(channel: id_user, as_user: true, text: msg, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
25
26
  else
26
27
  resp = client.message(channel: id_user, as_user: true, text: msg, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
27
28
  end
@@ -30,25 +31,25 @@ class SlackSmartBot
30
31
  if config[:testing] and config.on_master_bot and !@buffered
31
32
  @buffered = true
32
33
  open("#{config.path}/buffer.log", "a") { |f|
33
- f.puts "|#{id_user}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}"
34
+ f.puts "|#{id_user}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}"
34
35
  }
35
36
  end
36
37
  else
37
38
  if config[:simulate]
38
39
  open("#{config.path}/buffer_complete.log", "a") { |f|
39
- f.puts "|#{DIRECT[id_user.to_sym].ubot}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}~~~"
40
+ f.puts "|#{DIRECT[id_user.to_sym].ubot}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}~~~"
40
41
  }
41
42
  else
42
43
  im = client.web_client.conversations_open(users: id_user)
43
44
  if web_client
44
45
  if on_thread
45
- resp = client.web_client.chat_postMessage(channel: im["channel"]["id"], text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: Thread.current[:thread_ts])
46
+ resp = client.web_client.chat_postMessage(channel: im["channel"]["id"], text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
46
47
  else
47
48
  resp = client.web_client.chat_postMessage(channel: im["channel"]["id"], text: msg, blocks: blocks, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
48
49
  end
49
50
  else
50
51
  if on_thread
51
- resp = client.message(channel: im["channel"]["id"], as_user: true, text: msg, thread_ts: Thread.current[:thread_ts], unfurl_links: unfurl_links, unfurl_media: unfurl_media)
52
+ resp = client.message(channel: im["channel"]["id"], as_user: true, text: msg, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
52
53
  else
53
54
  resp = client.message(channel: im["channel"]["id"], as_user: true, text: msg, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
54
55
  end
@@ -57,7 +58,7 @@ class SlackSmartBot
57
58
  if config[:testing] and config.on_master_bot and !@buffered
58
59
  @buffered = true
59
60
  open("#{config.path}/buffer.log", "a") { |f|
60
- f.puts "|#{im["channel"]["id"]}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}"
61
+ f.puts "|#{im["channel"]["id"]}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}#{blocks.join}"
61
62
  }
62
63
  end
63
64
  end