slack-smart-bot 1.14.1 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -12,10 +12,10 @@ class SlackSmartBot
12
12
  # help: if used 'command' it will show any kind of command or rule.
13
13
  # help: command_id: :suggest_command
14
14
  # help:
15
- def suggest_command(from, dest, dchannel, specific, rules_file)
15
+ def suggest_command(user, dest, dchannel, specific, rules_file)
16
16
  save_stats(__method__)
17
17
  dont_suggest = []
18
- help_message = get_help(rules_file, dest, from, specific, true, descriptions: false, only_normal_user: true)
18
+ help_message = get_help(rules_file, dest, user, specific, true, descriptions: false, only_normal_user: true)
19
19
  commands = help_message.gsub(/====+/,'-'*30).split(/^\s*-------*$/).flatten
20
20
  commands.reject!{|c| c.match?(/These are specific commands for this bot on this/i) || c.match?(/\A\s*\z/)}
21
21
  dont_suggest.each do |ds|
@@ -24,13 +24,14 @@ class SlackSmartBot
24
24
  @last_suggested_commands ||= []
25
25
  @last_suggested_commands.shift if @last_suggested_commands.size >=5
26
26
  command = ''
27
- begin
27
+ begin
28
28
  command = commands.sample
29
29
  end until !@last_suggested_commands.include?(command) or commands.size <= 5
30
30
  @last_suggested_commands << command
31
31
  command.gsub!(/^\s*command_id:\s+:\w+\s*$/,'')
32
+ command.gsub!(/^\s*>.+$/,'')
32
33
  message = "*Command suggestion*:\n#{command}"
33
34
  respond message, dest, unfurl_links: false, unfurl_media: false
34
35
  end
35
36
 
36
- end
37
+ end
@@ -31,11 +31,12 @@ class SlackSmartBot
31
31
  respond "The bot in that channel is not :on", dest
32
32
  else
33
33
  if user.id == channel_found.creator or members.include?(user.id)
34
- @rules_imported[user.name] = {} unless @rules_imported.key?(user.name)
34
+ team_id_user = "#{user.team_id}_#{user.name}"
35
+ @rules_imported[team_id_user] = {} unless @rules_imported.key?(team_id_user)
35
36
  if dest[0] == "C" or dest[0] == "G" #todo: take in consideration bots that are not master
36
- @rules_imported[user.name][dchannel] = channel_found.id
37
+ @rules_imported[team_id_user][dchannel] = channel_found.id
37
38
  else
38
- @rules_imported[user.name][user.name] = channel_found.id
39
+ @rules_imported[team_id_user][user.name] = channel_found.id
39
40
  end
40
41
  sleep 0.5
41
42
  update_rules_imported()
@@ -14,9 +14,9 @@ class SlackSmartBot
14
14
  Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
15
15
  Dir.mkdir("#{config.path}/repl/#{@channel_id}") unless Dir.exist?("#{config.path}/repl/#{@channel_id}")
16
16
  if File.exist?("#{config.path}/repl/#{@channel_id}/#{session_name}.run")
17
- if @repls.key?(session_name) and (@repls[session_name][:type] == :private or @repls[session_name][:type] == :private_clean) and
18
- @repls[session_name][:creator_name]!=user.name and
19
- !is_admin?(user.name)
17
+ if @repls.key?(session_name) and (@repls[session_name][:type] == :private or @repls[session_name][:type] == :private_clean) and
18
+ (@repls[session_name][:creator_name]!=user.name or @repls[session_name][:creator_team_id]!= user.team_id) and
19
+ !is_admin?(user)
20
20
  respond "The REPL with session name: #{session_name} is private", dest
21
21
  else
22
22
  content = "require 'nice_http'\n"
@@ -25,7 +25,7 @@ class SlackSmartBot
25
25
  @repls[session_name][:gets] += 1
26
26
  update_repls()
27
27
  end
28
- if !@repls.key?(session_name) or
28
+ if !@repls.key?(session_name) or
29
29
  (File.exist?("#{project_folder}/.smart-bot-repl") and @repls[session_name][:type] != :private_clean and @repls[session_name][:type] != :public_clean)
30
30
  content += File.read("#{project_folder}/.smart-bot-repl")
31
31
  content += "\n"
@@ -14,7 +14,7 @@ class SlackSmartBot
14
14
  save_stats(__method__)
15
15
  if !@run_repls.key?(repl_id)
16
16
  respond "The run repl with id #{repl_id} doesn't exist"
17
- elsif @run_repls[repl_id].user != user.name and !config.masters.include?(user.name)
17
+ elsif (@run_repls[repl_id].user != user.name or @run_repls[repl_id].team_id != user.team_id) and !config.team_id_masters.include?("#{user.team_id}_#{user.name}")
18
18
  respond "Only #{@run_repls[repl_id].user} or a master admin can kill this repl."
19
19
  else
20
20
  pids = `pgrep -P #{@run_repls[repl_id].pid}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
@@ -1,5 +1,6 @@
1
1
  class SlackSmartBot
2
2
  # help: ----------------------------------------------
3
+ # help: >*<https://github.com/MarioRuiz/slack-smart-bot#repl|REPLs>*
3
4
  # help: `repl`
4
5
  # help: `live`
5
6
  # help: `irb`
@@ -25,6 +26,8 @@ class SlackSmartBot
25
26
  # help: If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
26
27
  # help: To see the code of a method: _code TheModuleOrClass.my_method_
27
28
  # help: To see the documentation of a method: _doc TheModuleOrClass.my_method_
29
+ # help: You can ask *ChatGPT* to help you or suggest any code by sending the message: `? PROMPT`
30
+ # help: If you send just `?` it will suggest some code to be added.
28
31
  # help: You can supply the Environmental Variables you need for the Session
29
32
  # help: You can add collaborators by sending _add collaborator @USER_ to the session.
30
33
  # help: Examples:
@@ -38,8 +41,9 @@ class SlackSmartBot
38
41
  def repl(dest, user, session_name, env_vars, rules_file, command, description, type)
39
42
  #todo: add more tests
40
43
  from = user.name
44
+ team_id_user = "#{user.team_id}_#{user.name}"
41
45
  if has_access?(__method__, user)
42
- if !@repl_sessions.key?(from)
46
+ if !@repl_sessions.key?(team_id_user)
43
47
  save_stats(__method__)
44
48
  Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
45
49
  Dir.mkdir("#{config.path}/repl/#{@channel_id}") unless Dir.exist?("#{config.path}/repl/#{@channel_id}")
@@ -57,7 +61,7 @@ class SlackSmartBot
57
61
  session_name = "#{name}#{i}"
58
62
  end
59
63
  end
60
- @repl_sessions[from] = {
64
+ @repl_sessions[team_id_user] = {
61
65
  name: session_name,
62
66
  dest: dest,
63
67
  started: Time.now,
@@ -67,14 +71,15 @@ class SlackSmartBot
67
71
  thread_ts: Thread.current[:thread_ts],
68
72
  collaborators: [],
69
73
  user_type: :creator,
70
- user_creator: from,
74
+ user_creator: team_id_user,
71
75
  }
72
76
 
73
77
  unless temp_repl
74
78
  @repls[session_name] = {
75
- created: @repl_sessions[from][:started].to_s,
76
- accessed: @repl_sessions[from][:started].to_s,
79
+ created: @repl_sessions[team_id_user][:started].to_s,
80
+ accessed: @repl_sessions[team_id_user][:started].to_s,
77
81
  creator_name: user.name,
82
+ creator_team_id: user.team_id,
78
83
  creator_id: user.id,
79
84
  description: description,
80
85
  type: type,
@@ -93,7 +98,7 @@ class SlackSmartBot
93
98
  end
94
99
  @ts_repl ||= {}
95
100
  @ts_repl[session_name] = ""
96
- process_to_run = repl_client(from, session_name, type, serialt, env_vars)
101
+ process_to_run = repl_client(team_id_user, session_name, type, serialt, env_vars)
97
102
 
98
103
  unless rules_file.empty? # to get the project_folder
99
104
  begin
@@ -123,83 +128,128 @@ class SlackSmartBot
123
128
  started = Time.now
124
129
  process_to_run = ("cd #{project_folder} && " + process_to_run) if defined?(project_folder)
125
130
  stdin, stdout, stderr, wait_thr = Open3.popen3(process_to_run)
126
- timeout = 30 * 60 # 30 minutes
131
+ timeout = TIMEOUT_LISTENING # 30 minutes
127
132
 
128
133
  file_output_repl = File.open("#{config.path}/repl/#{@channel_id}/#{session_name}.output", "r")
129
- @repl_sessions[from][:pid] = wait_thr.pid
130
- while (wait_thr.status == "run" or wait_thr.status == "sleep") and @repl_sessions.key?(from)
134
+ @repl_sessions[team_id_user][:pid] = wait_thr.pid
135
+ @repl_sessions[team_id_user][:output] ||= []
136
+ @repl_sessions[team_id_user][:input_output] ||= []
137
+ @repl_sessions[team_id_user][:input_output] << "Please chatgpt return code in Ruby language."
138
+ if File.exist?("#{project_folder}/.smart-bot-repl") and type != :private_clean and type != :public_clean
139
+ pre_input = File.read("#{project_folder}/.smart-bot-repl")
140
+ @repl_sessions[team_id_user][:input_output] << "```\n#{pre_input}\n```"
141
+ respond "*Preloaded source code:*\n```\n#{pre_input}\n```"
142
+ end
143
+
144
+ while (wait_thr.status == "run" or wait_thr.status == "sleep") and @repl_sessions.key?(team_id_user)
131
145
  begin
132
- if (Time.now - @repl_sessions[from][:finished]) > timeout
133
- open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
146
+ if (Time.now - @repl_sessions[team_id_user][:finished]) > timeout
147
+ open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[team_id_user][:name]}.input", "a+") { |f|
134
148
  f.puts "quit"
135
149
  }
136
- respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
137
- unreact :running, @ts_react[@repl_sessions[from].name]
138
- pids = `pgrep -P #{@repl_sessions[from][:pid]}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
150
+ respond "REPL session finished: #{@repl_sessions[team_id_user][:name]}", dest
151
+ unreact :running, @ts_react[@repl_sessions[team_id_user].name]
152
+ pids = `pgrep -P #{@repl_sessions[team_id_user][:pid]}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
139
153
  pids.each do |pid|
140
154
  begin
141
155
  Process.kill("KILL", pid)
142
156
  rescue
143
157
  end
144
158
  end
145
- @repl_sessions[from][:collaborators].each do |collaborator|
159
+ @repl_sessions[team_id_user][:collaborators].each do |collaborator|
146
160
  @repl_sessions.delete(collaborator)
147
161
  end
148
- @repl_sessions.delete(from)
162
+ @repl_sessions.delete(team_id_user)
149
163
  break
150
164
  end
151
165
  sleep 0.2
152
166
  resp_repl = file_output_repl.read
153
167
  if resp_repl.to_s != ""
154
- if @ts_repl[@repl_sessions[from].name].to_s != ""
155
- unreact(:running, @ts_repl[@repl_sessions[from].name])
156
- @ts_repl[@repl_sessions[from].name] = ""
168
+ if @ts_repl[@repl_sessions[team_id_user].name].to_s != ""
169
+ unreact(:running, @ts_repl[@repl_sessions[team_id_user].name])
170
+ @ts_repl[@repl_sessions[team_id_user].name] = ""
157
171
  end
158
- if (resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500) or
159
- resp_repl.match?(/^\s*[_\*]*`\w+`/im)
172
+ if (resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500) or
173
+ resp_repl.match?(/^\s*[_\*]*`\w+`/im)
160
174
  respond resp_repl, dest
161
175
  else
162
176
  resp_repl.gsub!(/^\s*```/, "")
163
177
  resp_repl.gsub!(/```\s*$/, "")
164
178
  send_file(dest, "", "response.rb", "", "text/plain", "ruby", content: resp_repl)
165
179
  end
180
+ @repl_sessions[team_id_user][:output] << resp_repl
181
+ @repl_sessions[team_id_user][:input_output] << resp_repl
166
182
  end
167
183
  rescue Exception => excp
168
184
  @logger.fatal excp
169
185
  end
170
186
  end
171
- elsif @repl_sessions.key?(from) and @repl_sessions[from][:command].to_s == ""
187
+ elsif @repl_sessions.key?(team_id_user) and @repl_sessions[team_id_user][:command].to_s == ""
172
188
  respond "You are already in a repl on this SmartBot. You need to quit that one before starting a new one."
173
189
  else
174
- @repl_sessions[from][:finished] = Time.now
175
- code = @repl_sessions[from][:command]
176
- @repl_sessions[from][:command] = ""
190
+ @repl_sessions[team_id_user][:finished] = Time.now
191
+ code = @repl_sessions[team_id_user][:command]
192
+ @repl_sessions[team_id_user][:command] = ""
177
193
  code.gsub!("\\n", "\n")
178
194
  code.gsub!("\\r", "\r")
179
195
  # Disabled for the moment since it is deleting lines with '}'
180
196
  #code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting.
181
- if code.match?(/\A\s*-/i)
182
- # don't treat
183
- elsif code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File.") or
184
- code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
185
- code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
186
- code.include?("ENV") or code.match?(/=\s*IO/) or code.include?("Dir.") or
187
- code.match?(/=\s*File/) or code.match?(/=\s*Dir/) or code.match?(/<\s*File/) or code.match?(/<\s*Dir/) or
188
- code.match?(/\w+:\s*File/) or code.match?(/\w+:\s*Dir/) or
189
- code.match?(/=?\s*(require|load)(\(|\s)/i)
197
+ if code.match?(/\A\s*-/i)
198
+ # don't treat
199
+ elsif code.match(/\A\s*\?\s*(.*)\s*\z/im)
200
+ save_stats :open_ai_chat
201
+ #call chatgpt when: ? prompt
202
+ #if no prompt then suggest next code line
203
+ prompt = $1
204
+ prompt = "suggest next code line" if prompt.to_s == ""
205
+ tid = "#{user.team_id}_#{user.name}"
206
+ @repl_sessions[tid][:chat_gpt] ||= {}
207
+ react :speech_balloon
208
+ if !@repl_sessions[tid][:chat_gpt].key?(:client) or @repl_sessions[tid][:chat_gpt][:client].nil?
209
+ get_personal_settings()
210
+ tmp_repl_sessions, message_connect = SlackSmartBot::AI::OpenAI.connect(@repl_sessions, config, @personal_settings, reconnect: true, service: :chat_gpt)
211
+ @repl_sessions[tid][:chat_gpt] = tmp_repl_sessions[tid][:chat_gpt]
212
+ respond message_connect if message_connect
213
+ end
214
+ @repl_sessions[tid][:chat_gpt][:prompts] ||= []
215
+ unless @repl_sessions[tid][:chat_gpt][:client].nil?
216
+ model ||= @repl_sessions[tid][:chat_gpt][:smartbot_model]
217
+ #todo: add source code to the prompt
218
+ @repl_sessions[tid][:chat_gpt][:prompts] << prompt
219
+ @repl_sessions[team_id_user][:input_output] << prompt
220
+ prompts = @repl_sessions[tid][:input_output].join("\n")
221
+ success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(@repl_sessions[tid][:chat_gpt][:client], model, prompts, @repl_sessions[tid].chat_gpt)
222
+ if success
223
+ @repl_sessions[tid][:chat_gpt][:prompts] << res
224
+ respond "*ChatGPT>* _#{model}_\n#{res}"
225
+ @repl_sessions[team_id_user][:input_output] << res
226
+ elsif res.to_s.strip!=''
227
+ respond "*ChatGPT>* _#{model}_\n#{res}"
228
+ else
229
+ respond "ChatGPT: Sorry, I cannot chat right now. Please try again later."
230
+ end
231
+ end
232
+ unreact :speech_balloon
233
+ elsif code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File.") or
234
+ code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
235
+ code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
236
+ code.include?("ENV") or code.match?(/=\s*IO/) or code.include?("Dir.") or
237
+ code.match?(/=\s*File/) or code.match?(/=\s*Dir/) or code.match?(/<\s*File/) or code.match?(/<\s*Dir/) or
238
+ code.match?(/\w+:\s*File/) or code.match?(/\w+:\s*Dir/) or
239
+ code.match?(/=?\s*(require|load)(\(|\s)/i)
190
240
  respond "Sorry I cannot run this due security reasons", dest
191
241
  elsif code.match(/\A\s*add\s+collaborator\s+<@(\w+)>\s*\z/i)
192
242
  collaborator = $1
193
- user_info = @users.select { |u| u.id == collaborator or (u.key?(:enterprise_user) and u.enterprise_user.id == collaborator) }[-1]
194
- collaborator_name = user_info.name
243
+ user_info = find_user(collaborator)
244
+ collaborator_name = "#{user_info.team_id}_#{user_info.name}"
195
245
  if @repl_sessions.key?(collaborator_name)
196
246
  respond "Sorry, <@#{collaborator}> is already in a repl. Please ask her/him to quit it first.", dest
197
247
  else
198
248
  respond "Collaborator added. Now <@#{collaborator}> can interact with this repl.", dest
199
- creator = @repl_sessions[from][:user_creator]
249
+ creator = @repl_sessions[team_id_user][:user_creator]
200
250
  @repl_sessions[creator][:collaborators] << collaborator_name
201
251
  @repl_sessions[collaborator_name] = {
202
- name: @repl_sessions[from][:name],
252
+ name: @repl_sessions[team_id_user][:name],
203
253
  dest: dest,
204
254
  on_thread: Thread.current[:on_thread],
205
255
  thread_ts: Thread.current[:thread_ts],
@@ -208,41 +258,48 @@ class SlackSmartBot
208
258
  }
209
259
  end
210
260
  else
211
- if @repl_sessions[from][:user_type] == :collaborator
212
- @repl_sessions[@repl_sessions[from][:user_creator]][:input] << code
261
+ if @repl_sessions[team_id_user][:user_type] == :collaborator
262
+ creator = @repl_sessions[team_id_user][:user_creator]
263
+ @repl_sessions[@repl_sessions[team_id_user][:user_creator]][:input] << code
264
+ else
265
+ creator = team_id_user
266
+ @repl_sessions[team_id_user][:input] << code
267
+ end
268
+ if code.include?("```")
269
+ @repl_sessions[creator][:input_output] << code
213
270
  else
214
- @repl_sessions[from][:input] << code
271
+ @repl_sessions[creator][:input_output] << "```\n#{code}\n```"
215
272
  end
216
273
  case code
217
274
  when /^\s*(quit|exit|bye|bye\s+bot)\s*$/i
218
- if @repl_sessions[from][:user_type] == :collaborator
275
+ if @repl_sessions[team_id_user][:user_type] == :collaborator
219
276
  respond "Collaborator <@#{user.id}> removed.", dest
220
- @repl_sessions[@repl_sessions[from][:user_creator]][:collaborators].delete(from)
221
- @repl_sessions.delete(from)
277
+ @repl_sessions[creator][:collaborators].delete(team_id_user)
278
+ @repl_sessions.delete(team_id_user)
222
279
  else
223
- open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
280
+ open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[team_id_user][:name]}.input", "a+") { |f|
224
281
  f.puts code
225
282
  }
226
- respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
227
- unreact :running, @ts_react[@repl_sessions[from].name]
228
- pids = `pgrep -P #{@repl_sessions[from][:pid]}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
283
+ respond "REPL session finished: #{@repl_sessions[team_id_user][:name]}", dest
284
+ unreact :running, @ts_react[@repl_sessions[team_id_user].name]
285
+ pids = `pgrep -P #{@repl_sessions[team_id_user][:pid]}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
229
286
  pids.each do |pid|
230
287
  begin
231
288
  Process.kill("KILL", pid)
232
289
  rescue
233
290
  end
234
291
  end
235
- @repl_sessions[from][:collaborators].each do |collaborator|
292
+ @repl_sessions[team_id_user][:collaborators].each do |collaborator|
236
293
  @repl_sessions.delete(collaborator)
237
294
  end
238
- @repl_sessions.delete(from)
295
+ @repl_sessions.delete(team_id_user)
239
296
  end
240
297
  else
241
- if @ts_repl[@repl_sessions[from].name].to_s == ""
242
- @ts_repl[@repl_sessions[from].name] = Thread.current[:ts]
298
+ if @ts_repl[@repl_sessions[creator].name].to_s == ""
299
+ @ts_repl[@repl_sessions[creator].name] = Thread.current[:ts]
243
300
  react :running
244
301
  end
245
- open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
302
+ open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[creator][:name]}.input", "a+") { |f|
246
303
  f.puts code
247
304
  }
248
305
  end
@@ -1,23 +1,24 @@
1
1
  class SlackSmartBot
2
- def repl_client(from, session_name, type, serialt, env_vars)
2
+ def repl_client(team_id_user, session_name, type, serialt, env_vars)
3
3
  message = "Session name: *#{session_name}*
4
- From now on I will execute all you write as a Ruby command and I will keep the session open until you send `quit` or `bye` or `exit`.
4
+ From now on I will execute all you write as a Ruby command and I will keep the session open until you send `quit` or `bye` or `exit`.
5
5
  In case you need someone to help you with the session you can add collaborators by sending `add collaborator @USER` to the session.
6
- I will respond with the result so it is not necessary you send `print`, `puts`, `p` or `pp` unless you want it as the output when calling `run repl`.
7
- Use `p` to print a message raw, exacly like it is returned.
8
- If you want to avoid a message to be treated by me, start the message with '-'.
6
+ I will respond with the result so it is not necessary you send `print`, `puts`, `p` or `pp` unless you want it as the output when calling `run repl`.
7
+ Use `p` to print a message raw, exacly like it is returned.
8
+ If you want to avoid a message to be treated by me, start the message with '-'.
9
9
  After 30 minutes of no communication with the Smart Bot the session will be dismissed.
10
10
  If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
11
11
  To see the code of a method: _code TheModuleOrClass.my_method_. To see the documentation of a method: _doc TheModuleOrClass.my_method_
12
+ You can ask *ChatGPT* to help you or suggest any code by sending the message: `? PROMPT`. If no prompt then it will suggest the next line of code.
12
13
  You can supply the Environmental Variables you need for the Session
13
14
  Example:
14
15
  _repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
15
16
  "
16
17
  respond message
17
18
 
18
- File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "", mode: "a+")
19
- File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.output", "", mode: "a+")
20
- File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.run", "", mode: "a+")
19
+ File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[team_id_user][:name]}.input", "", mode: "a+")
20
+ File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[team_id_user][:name]}.output", "", mode: "a+")
21
+ File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[team_id_user][:name]}.run", "", mode: "a+")
21
22
 
22
23
  if type != :private_clean and type != :public_clean
23
24
  pre_execute = '
@@ -44,7 +45,7 @@ class SlackSmartBot
44
45
  if m.nil?
45
46
  met = obj
46
47
  else
47
- met = obj.method(m)
48
+ met = obj.method(m)
48
49
  end
49
50
  met.source.split("\n").each { |line|
50
51
  line.gsub!("def", "")
@@ -57,7 +58,7 @@ class SlackSmartBot
57
58
  result << "#{line}"
58
59
  result << " ..." if !line.include?("(") and !line.include?(")")
59
60
  result << "\n"
60
- break
61
+ break
61
62
  else
62
63
  result << "#{line}\n"
63
64
  end
@@ -67,15 +68,20 @@ class SlackSmartBot
67
68
  def ls(obj)
68
69
  result = ""
69
70
  (obj.methods - Object.methods).sort.each do |m|
70
- result << get_met_params(obj, m)
71
+ if obj.respond_to?(m)
72
+ pre = "*`#{obj}`*."
73
+ else
74
+ pre = ""
75
+ end
76
+ result << "#{pre}#{get_met_params(obj, m)}"
71
77
  result << "\n"
72
78
  end
73
79
  puts result
74
80
  end
75
81
  def get_object(obj_txt)
76
82
  met = obj_txt.scan(/\.(\w+)/).flatten.last
77
-
78
- if met.nil? and obj_txt[0].match(/[A-Z]/)
83
+
84
+ if met.nil? and obj_txt[0].match(/[A-Z]/)
79
85
  obj = Object
80
86
  obj_txt.split("::").each do |cl|
81
87
  if obj.const_defined?(cl.to_sym)
@@ -90,7 +96,7 @@ class SlackSmartBot
90
96
  obj = self.method(obj_txt)
91
97
  rescue
92
98
  obj = nil
93
- end
99
+ end
94
100
  else
95
101
  cl = obj_txt.scan(/([\w\:]+)\./).flatten.first
96
102
  obj = Object
@@ -106,15 +112,15 @@ class SlackSmartBot
106
112
  if obj.respond_to?(met)
107
113
  obj = obj.method(met)
108
114
  elsif obj.instance_method(met)
109
- obj = obj.instance_method(met)
115
+ obj = obj.instance_method(met)
110
116
  else
111
117
  obj = nil
112
118
  end
113
119
  end
114
-
115
- end
120
+
121
+ end
116
122
  end
117
-
123
+
118
124
  def doc(obj_txt)
119
125
  obj = get_object(obj_txt)
120
126
  if !obj.nil? and obj.respond_to?(:source_location) and obj.respond_to?(:comment) and
@@ -132,7 +138,7 @@ class SlackSmartBot
132
138
  end
133
139
  puts result
134
140
  end
135
-
141
+
136
142
  def source(obj_txt)
137
143
  obj = get_object(obj_txt)
138
144
  if !obj.nil? and obj.respond_to?(:source_location) and obj.respond_to?(:comment) and
@@ -144,21 +150,21 @@ class SlackSmartBot
144
150
  end
145
151
  puts result
146
152
  end
147
-
153
+
148
154
  def code(obj_txt)
149
155
  source(obj_txt)
150
- end
156
+ end
151
157
 
152
158
  file_run_path = \"' + +File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.rb\"
153
159
  file_input_repl = File.open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.input\", \"r\")
154
160
  ' + pre_execute + '
155
- while true do
156
- sleep 0.2
161
+ while true do
162
+ sleep 0.2
157
163
  code_to_run_repl = file_input_repl.read
158
164
  if code_to_run_repl.to_s!=\"\"
159
165
  add_to_run_repl = true
160
- if code_to_run_repl.to_s.match?(/^quit$/i) or
161
- code_to_run_repl.to_s.match?(/^exit$/i) or
166
+ if code_to_run_repl.to_s.match?(/^quit$/i) or
167
+ code_to_run_repl.to_s.match?(/^exit$/i) or
162
168
  code_to_run_repl.to_s.match?(/^bye bot$/i) or
163
169
  code_to_run_repl.to_s.match?(/^bye$/i)
164
170
  exit
@@ -179,10 +185,10 @@ class SlackSmartBot
179
185
  end
180
186
  begin
181
187
  original_stdout = $stdout
182
- $stdout = StringIO.new
188
+ $stdout = StringIO.new
183
189
  resp_repl = eval(code_to_run_repl, bindme' + serialt + ')
184
190
  stdout_repl = $stdout.string
185
- ensure
191
+ ensure
186
192
  $stdout = original_stdout
187
193
  end
188
194
  rescue Exception => resp_repl
@@ -198,7 +204,7 @@ class SlackSmartBot
198
204
  if stdout_repl.to_s == \'\'
199
205
  resp_repl = resp_repl.inspect
200
206
  else
201
- resp_repl = stdout_repl
207
+ resp_repl = stdout_repl
202
208
  end
203
209
  open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
204
210
  f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
@@ -207,7 +213,7 @@ class SlackSmartBot
207
213
  if stdout_repl.to_s == \'\'
208
214
  resp_repl = resp_repl.ai
209
215
  else
210
- resp_repl = stdout_repl
216
+ resp_repl = stdout_repl
211
217
  end
212
218
  open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
213
219
  if as_it_is
@@ -24,8 +24,8 @@ class SlackSmartBot
24
24
  code = prerun.join("\n")
25
25
  if File.exist?("#{config.path}/repl/#{@channel_id}/#{session_name}.run")
26
26
  if @repls.key?(session_name) and (@repls[session_name][:type] == :private or @repls[session_name][:type] == :private_clean) and
27
- @repls[session_name][:creator_name] != user.name and
28
- !is_admin?(user.name)
27
+ (@repls[session_name][:creator_name] != user.name or @repls[session_name][:creator_team_id] != user.team_id) and
28
+ !is_admin?(user)
29
29
  respond "The REPL with session name: #{session_name} is private", dest
30
30
  elsif !prerun.empty? and (code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File.") or
31
31
  code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
@@ -38,7 +38,7 @@ class SlackSmartBot
38
38
  else
39
39
  if @repls.key?(session_name) #not temp
40
40
  @repls[session_name][:accessed] = Time.now.to_s
41
- if @repls[session_name].creator_name == user.name
41
+ if @repls[session_name].creator_name == user.name and @repls[session_name].creator_team_id == user.team_id
42
42
  @repls[session_name][:runs_by_creator] += 1
43
43
  else
44
44
  @repls[session_name][:runs_by_others] += 1
@@ -65,7 +65,7 @@ class SlackSmartBot
65
65
  content += File.read("#{config.path}/repl/#{@channel_id}/#{session_name}.run").gsub(/^(quit|exit|bye)$/i, "") #todo: remove this gsub, it will never contain it
66
66
  Dir.mkdir("#{project_folder}/tmp") unless Dir.exist?("#{project_folder}/tmp")
67
67
  Dir.mkdir("#{project_folder}/tmp/repl") unless Dir.exist?("#{project_folder}/tmp/repl")
68
- if Thread.current[:on_thread]
68
+ if Thread.current[:on_thread]
69
69
  # to force stdout.each to be performed every 3 seconds
70
70
  content = "Thread.new do
71
71
  while true do
@@ -81,7 +81,7 @@ class SlackSmartBot
81
81
  process_to_run = "ruby ./tmp/repl/#{session_name}_#{user.name}_#{random}.rb"
82
82
  process_to_run = ("cd #{project_folder} && #{process_to_run}") if defined?(project_folder)
83
83
  respond "Running REPL #{session_name} (id: #{random})"
84
- @run_repls[random] = { user: user.name, name: session_name, pid: '' }
84
+ @run_repls[random] = { team_id: user.team_id, user: user.name, name: session_name, pid: '' }
85
85
  react :running
86
86
 
87
87
  require "pty"
@@ -9,11 +9,10 @@ class SlackSmartBot
9
9
  def see_repls(dest, user, typem)
10
10
  #todo: add tests
11
11
  save_stats(__method__)
12
- from = user.name
13
12
  if has_access?(__method__, user)
14
13
  message = ""
15
14
  @repls.sort.to_h.each do |session_name, repl|
16
- if (repl.creator_name == user.name or repl.type == :public or repl.type == :public_clean) or (is_admin?(user.name) and typem == :on_dm)
15
+ if ((repl.creator_name == user.name and repl.creator_team_id == user.team_id) or repl.type == :public or repl.type == :public_clean) or (is_admin?(user) and typem == :on_dm)
17
16
  message += "(#{repl.type}) *#{session_name}*: #{repl.description} / created: #{repl.created} / accessed: #{repl.accessed} / creator: #{repl.creator_name} / runs: #{repl.runs_by_creator+repl.runs_by_others} / gets: #{repl.gets} \n"
18
17
  end
19
18
  end
@@ -9,6 +9,7 @@ class SlackSmartBot
9
9
  def see_shortcuts(dest, user, typem)
10
10
  save_stats(__method__)
11
11
  from = user.name
12
+ team_id_user = user.team_id + '_' + from
12
13
  if has_access?(__method__, user)
13
14
  unless typem == :on_extended
14
15
  msg = ""
@@ -28,8 +29,8 @@ class SlackSmartBot
28
29
  respond msg, dest
29
30
  end
30
31
  msg2 = ''
31
- if @shortcuts.keys.include?(from) and @shortcuts[from].keys.size > 0
32
- new_hash = @shortcuts[from].deep_copy
32
+ if @shortcuts.keys.include?(team_id_user) and @shortcuts[team_id_user].keys.size > 0
33
+ new_hash = @shortcuts[team_id_user].deep_copy
33
34
  @shortcuts[:all].keys.each { |k| new_hash.delete(k) }
34
35
  if new_hash.keys.size > 0
35
36
  msg2 = "*Available shortcuts for #{from}:*\n"
@@ -38,8 +39,8 @@ class SlackSmartBot
38
39
  }
39
40
  end
40
41
  end
41
- if @shortcuts_global.keys.include?(from) and @shortcuts_global[from].keys.size > 0
42
- new_hash = @shortcuts_global[from].deep_copy
42
+ if @shortcuts_global.keys.include?(team_id_user) and @shortcuts_global[team_id_user].keys.size > 0
43
+ new_hash = @shortcuts_global[team_id_user].deep_copy
43
44
  @shortcuts_global[:all].keys.each { |k| new_hash.delete(k) }
44
45
  if new_hash.keys.size > 0
45
46
  msg2 = "*Available shortcuts for #{from}:*\n" if msg2 == ''