slack-smart-bot 1.15.1 → 1.15.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -1
  3. data/img/chat_gpt_attach_image.png +0 -0
  4. data/lib/slack/smart-bot/ai/open_ai/models.rb +19 -10
  5. data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +14 -10
  6. data/lib/slack/smart-bot/comm/dont_understand.rb +23 -6
  7. data/lib/slack/smart-bot/comm/get_user_info.rb +9 -10
  8. data/lib/slack/smart-bot/comm/respond.rb +56 -28
  9. data/lib/slack/smart-bot/comm/send_file.rb +17 -6
  10. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +885 -129
  11. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +3 -3
  12. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +132 -15
  13. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +1 -1
  14. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +50 -12
  15. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +99 -34
  16. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +12 -2
  17. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +36 -25
  18. data/lib/slack/smart-bot/commands/general/bot_help.rb +29 -24
  19. data/lib/slack/smart-bot/commands/general/poster.rb +0 -1
  20. data/lib/slack/smart-bot/commands/general/see_announcements.rb +1 -1
  21. data/lib/slack/smart-bot/commands/general/summarize.rb +22 -8
  22. data/lib/slack/smart-bot/commands/general_bot_commands.rb +156 -55
  23. data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +13 -11
  24. data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +21 -17
  25. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +2 -2
  26. data/lib/slack/smart-bot/commands.rb +19 -19
  27. data/lib/slack/smart-bot/process_first.rb +38 -35
  28. data/lib/slack/smart-bot/treat_message.rb +57 -56
  29. data/lib/slack/smart-bot/utils/download_http_content.rb +91 -0
  30. data/lib/slack/smart-bot/utils/get_authorizations.rb +41 -0
  31. data/lib/slack/smart-bot/utils/get_keywords.rb +33 -0
  32. data/lib/slack/smart-bot/utils/get_openai_sessions.rb +46 -6
  33. data/lib/slack/smart-bot/utils/get_teams.rb +9 -1
  34. data/lib/slack/smart-bot/utils/save_stats.rb +13 -5
  35. data/lib/slack/smart-bot/utils/transform_to_slack_markdown.rb +36 -0
  36. data/lib/slack/smart-bot/utils/update_openai_sessions.rb +9 -4
  37. data/lib/slack/smart-bot/utils.rb +48 -44
  38. data/lib/slack-smart-bot.rb +10 -9
  39. data/whats_new.txt +27 -1
  40. metadata +63 -2
@@ -3,41 +3,74 @@ class SlackSmartBot
3
3
  module General
4
4
  module AI
5
5
  module OpenAI
6
- def open_ai_chat(message, delete_history, type, model: '', tag: '', description: '', files: [])
6
+ def open_ai_chat(message, delete_history, type, model: "", tag: "", description: "", files: [])
7
+ message.strip!
7
8
  get_personal_settings()
8
9
  user = Thread.current[:user].dup
9
10
  user_name = user.name
10
11
  team_id = user.team_id
11
12
  team_id_user = Thread.current[:team_id_user]
12
- if model != '' and !@open_ai_models.include?(model)
13
- open_ai_models('', just_models: true) if @open_ai_models.empty?
14
- model_selected = @open_ai_models.select{|m| m.include?(model)}
13
+ success = true
14
+ if !defined?(@chat_gpt_default_model)
15
+ #config.ai.open_ai.chat_gpt.model
16
+ if config.key?(:ai) and config[:ai].key?(:open_ai) and config[:ai][:open_ai].key?(:chat_gpt) and
17
+ config[:ai][:open_ai][:chat_gpt].key?(:model)
18
+ @chat_gpt_default_model = config[:ai][:open_ai][:chat_gpt][:model]
19
+ else
20
+ @chat_gpt_default_model = ""
21
+ end
22
+ end
23
+
24
+ if model != "" and !@open_ai_models.include?(model)
25
+ open_ai_models("", just_models: true) if @open_ai_models.empty?
26
+ model_selected = @open_ai_models.select { |m| m.include?(model) }
15
27
  model = model_selected[0] if model_selected.size == 1
16
28
  end
17
29
 
18
30
  @active_chat_gpt_sessions[team_id_user] ||= {}
19
31
  if delete_history
20
- @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = ''
21
- session_name = ''
32
+ @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = ""
33
+ session_name = ""
22
34
  end
23
-
24
- if @active_chat_gpt_sessions[team_id_user].key?(Thread.current[:thread_ts]) and Thread.current[:thread_ts]!='' #added and Thread.current[:thread_ts]!='' for testing when SIMULATE==true and not in a thread
35
+ if @active_chat_gpt_sessions[team_id_user].key?(Thread.current[:thread_ts]) and Thread.current[:thread_ts] != "" #added and Thread.current[:thread_ts]!='' for testing when SIMULATE==true and not in a thread
25
36
  session_name = @active_chat_gpt_sessions[team_id_user][Thread.current[:thread_ts]]
26
37
  elsif @active_chat_gpt_sessions[team_id_user].key?(Thread.current[:dest])
27
- session_name = @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]]
38
+ if type == :temporary
39
+ session_name = ""
40
+ @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = ""
41
+ else
42
+ #:continue_session
43
+ session_name = @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]]
44
+ end
28
45
  else
29
- session_name = ''
30
- @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = ''
46
+ session_name = ""
47
+ @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = ""
31
48
  end
32
- if type == :start or type == :continue
49
+ if @open_ai.key?(team_id_user) and @open_ai[team_id_user].key?(:chat_gpt) and @open_ai[team_id_user][:chat_gpt].key?(:sessions) and
50
+ @open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name) and @open_ai[team_id_user][:chat_gpt][:sessions][session_name].key?(:collaborators)
51
+ collaborators_saved = @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:collaborators]
52
+ else
53
+ collaborators_saved = []
54
+ end
55
+
56
+ if type == :start or type == :continue or type == :clean
33
57
  session_name = message
58
+
34
59
  @active_chat_gpt_sessions[team_id_user] ||= {}
35
60
  @active_chat_gpt_sessions[team_id_user][Thread.current[:thread_ts]] = session_name
36
- message = ''
61
+ @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = session_name
62
+ message = ""
37
63
  get_openai_sessions(session_name)
38
64
  @open_ai[team_id_user] ||= {}
39
65
  @open_ai[team_id_user][:chat_gpt] ||= {}
40
66
  @open_ai[team_id_user][:chat_gpt][:sessions] ||= {}
67
+
68
+ if !@open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name) and
69
+ (type == :continue or type == :clean)
70
+ respond "*ChatGPT*: I'm sorry, but I couldn't find a session named *#{session_name}*."
71
+ return
72
+ end
73
+
41
74
  if !@open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name)
42
75
  @open_ai[team_id_user][:chat_gpt][:sessions][session_name] = {
43
76
  team_creator: team_id,
@@ -47,33 +80,111 @@ class SlackSmartBot
47
80
  collaborators: [],
48
81
  num_prompts: 0,
49
82
  model: model,
50
- copy_of_session: '',
51
- copy_of_team: '',
52
- copy_of_user: '',
83
+ copy_of_session: "",
84
+ copy_of_team: "",
85
+ copy_of_user: "",
53
86
  users_copying: [],
87
+ temp_copies: 0,
88
+ own_temp_copies: 0,
54
89
  public: false,
55
90
  shared: [],
56
91
  description: description,
57
- tag: tag.downcase
92
+ tag: tag.downcase,
93
+ live_content: [],
94
+ static_content: [],
95
+ authorizations: {},
58
96
  }
59
- else # type == :continue or loading
60
- @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:model] = model if model != ''
97
+ else # type == :continue or loading or clean
98
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:model] = model if model != ""
61
99
  num_prompts = @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:num_prompts]
62
- respond "*ChatGPT*: I just loaded *#{session_name}*.\nThere are *#{num_prompts} prompts* in this session.\nThis was the *last prompt* from the session:\n"
63
- content = @ai_gpt[team_id_user][session_name].join("\n")
64
- index_last_prompt = content.rindex(/^(Me>\s.*)$/)
65
- if index_last_prompt.nil?
66
- respond "No prompts found"
67
- else
68
- last_prompt = content[index_last_prompt..-1].gsub(/^Me>/, '*Me>*').gsub(/^chatGPT>/i, "\n*ChatGPT>*")
69
- respond last_prompt
100
+ unless type == :clean
101
+ collaborators_txt = ""
102
+ if @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:collaborators].size > 0
103
+ collaborators = @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:collaborators].map do |team_user|
104
+ team_user.split("_")[1..-1].join("_")
105
+ end
106
+ collaborators_txt = ":busts_in_silhouette: Collaborators: `#{collaborators.join("`, `")}`\n"
107
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:collaborators].each do |team_id_user_collaborator|
108
+ @chat_gpt_collaborating[team_id_user_collaborator] ||= {}
109
+ @chat_gpt_collaborating[team_id_user_collaborator][Thread.current[:thread_ts]] ||= { team_creator: team_id, user_creator: user.name, session_name: session_name }
110
+ @listening[team_id_user_collaborator] ||= {}
111
+ @listening[team_id_user_collaborator][Thread.current[:thread_ts]] = Time.now
112
+ end
113
+ end
114
+ if num_prompts > 0
115
+ respond "*ChatGPT*: I just loaded *#{session_name}*.\n#{collaborators_txt}There are *#{num_prompts} prompts* in this session.\nThis was the *last prompt* from the session:\n"
116
+ else
117
+ respond "*ChatGPT*: I just loaded *#{session_name}*.\n#{collaborators_txt}There are *no prompts* in this session."
118
+ end
119
+ content = @ai_gpt[team_id_user][session_name]
120
+ index_last_prompt = content.rindex { |c| c[:role] == "user" and c[:content].size == 1 and c[:content][0][:type] == "text" }
121
+ index_last_context = content.rindex { |c| c[:role] == "system" and c[:content].size == 1 and c[:content][0][:type] == "text" }
122
+ if index_last_context
123
+ last_context = "\n:robot_face: *User>* #{content[index_last_context][:content][0][:text]}\n"
124
+ else
125
+ last_context = ""
126
+ end
127
+ if !@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:live_content].nil? and
128
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:live_content].size > 0
129
+ live_content = "\n:globe_with_meridians: *Live content*:\n\t\t - `#{@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:live_content].join("`\n\t\t - `")}`"
130
+ else
131
+ live_content = ""
132
+ end
133
+ if !@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].nil? and
134
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].size > 0
135
+ static_content = "\n:pushpin: *Static content*:\n\t\t - `#{@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].join("`\n\t\t - `")}`"
136
+ if Thread.current[:dest][0] != "D"
137
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].each do |cont|
138
+ channel_hist = cont.scan(/\AHistory of <#(\w+)>\Z/im).flatten[0]
139
+ if channel_hist != Thread.current[:dest]
140
+ respond ":information_source: I'm sorry this session is trying to load the history of <##{channel_hist}>, but you can only load the history of the channel where you are currently talking or in a DM with me."
141
+ return
142
+ end
143
+ end
144
+ end
145
+ else
146
+ static_content = ""
147
+ end
148
+
149
+ #authorizations
150
+ if !@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:authorizations].nil? and
151
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:authorizations].size > 0
152
+ auth = "\n:lock: *Authorizations:*\n"
153
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:authorizations].each do |host, header|
154
+ auth += "\t\t - `#{host}`: `#{header.keys.join("`, `")}`\n"
155
+ end
156
+ else
157
+ auth = ""
158
+ end
159
+ if index_last_prompt.nil?
160
+ respond "#{last_context}No prompts found.\n#{live_content}#{static_content}#{auth}" unless delete_history
161
+ else
162
+ last_prompt = ""
163
+ content[index_last_prompt..-1].each do |c|
164
+ if c[:role] == "user" and c[:content].size == 1 and c[:content][0][:type] == "text"
165
+ if c[:content][0].key?(:clean_text)
166
+ if @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].nil? or
167
+ !@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content].include?(c[:content][0][:clean_text])
168
+ last_prompt += ":runner: *User>* #{transform_to_slack_markdown(c[:content][0][:clean_text])}\n"
169
+ end
170
+ else
171
+ last_prompt += ":runner: *User>* #{transform_to_slack_markdown(c[:content][0][:text])}\n"
172
+ end
173
+ elsif c[:role] == "user" and c[:content].size == 1 and c[:content][0][:type] != "text"
174
+ last_prompt += ":runner: *User>* Attached file type #{c[:content][0][:type]}\n"
175
+ elsif c[:role] == "assistant" and c[:content].size == 1 and c[:content][0][:type] == "text"
176
+ last_prompt += ":speech_balloon: *ChatGPT>* #{transform_to_slack_markdown(c[:content][0][:text])}\n"
177
+ end
178
+ end
179
+ respond last_prompt + last_context + live_content + static_content + auth
180
+ end
70
181
  end
71
182
  end
72
183
  if Thread.current[:on_thread] and
73
- (Thread.current[:thread_ts] == Thread.current[:ts] or
74
- ( @open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name) and
75
- @open_ai[team_id_user][:chat_gpt][:sessions][session_name].key?(:thread_ts) and
76
- @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:thread_ts].include?(Thread.current[:thread_ts]) ) )
184
+ (Thread.current[:thread_ts] == Thread.current[:ts] or
185
+ (@open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name) and
186
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name].key?(:thread_ts) and
187
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:thread_ts].include?(Thread.current[:thread_ts])))
77
188
  react :running, Thread.current[:thread_ts]
78
189
  @listening[team_id_user] ||= {}
79
190
  @listening[team_id_user][Thread.current[:thread_ts]] = Time.now
@@ -84,20 +195,19 @@ class SlackSmartBot
84
195
  else
85
196
  @active_chat_gpt_sessions[team_id_user][Thread.current[:dest]] = session_name
86
197
  end
87
- @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:description] = description if description != ''
88
- @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:tag] = tag.downcase if tag != ''
89
- open_ai_chat_use_model(model, dont_save_stats: true) if model != ''
198
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:description] = description if description != ""
199
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:tag] = tag.downcase if tag != ""
200
+ open_ai_chat_use_model(model, dont_save_stats: true) if model != ""
90
201
  elsif type == :temporary and
91
- (!@chat_gpt_collaborating.key?(team_id_user) or !@chat_gpt_collaborating[team_id_user].key?(Thread.current[:thread_ts]))
92
-
202
+ (!@chat_gpt_collaborating.key?(team_id_user) or !@chat_gpt_collaborating[team_id_user].key?(Thread.current[:thread_ts]))
93
203
  @open_ai[team_id_user] ||= {}
94
204
  @open_ai[team_id_user][:chat_gpt] ||= {}
95
205
  @open_ai[team_id_user][:chat_gpt][:sessions] ||= {}
96
206
 
97
207
  if Thread.current[:on_thread] and
98
- (Thread.current[:thread_ts] == Thread.current[:ts] or
208
+ (Thread.current[:thread_ts] == Thread.current[:ts] or
99
209
  (@open_ai[team_id_user][:chat_gpt][:sessions].key?("") and @open_ai[team_id_user][:chat_gpt][:sessions][""].key?(:thread_ts) and
100
- @open_ai[team_id_user][:chat_gpt][:sessions][""][:thread_ts].include?(Thread.current[:thread_ts]) ))
210
+ @open_ai[team_id_user][:chat_gpt][:sessions][""][:thread_ts].include?(Thread.current[:thread_ts])))
101
211
  @listening[team_id_user] ||= {}
102
212
  @listening[team_id_user][Thread.current[:thread_ts]] = Time.now
103
213
  @listening[:threads][Thread.current[:thread_ts]] = Thread.current[:dest]
@@ -109,6 +219,19 @@ class SlackSmartBot
109
219
  @active_chat_gpt_sessions[team_id_user][Thread.current[:thread_ts]] ||= ""
110
220
  end
111
221
  end
222
+ if delete_history and type != :clean and @open_ai.key?(team_id_user) and @open_ai[team_id_user].key?(:chat_gpt) and @open_ai[team_id_user][:chat_gpt].key?(:sessions) and
223
+ @open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name)
224
+ if session_name == "" and type == :temporary
225
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:collaborators] = []
226
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:num_prompts] = 0
227
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:copy_of_session] = ""
228
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:copy_of_team] = ""
229
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:copy_of_user] = ""
230
+ end
231
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:live_content] = []
232
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:static_content] = []
233
+ @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:authorizations] = {}
234
+ end
112
235
 
113
236
  #for collaborators
114
237
  if @chat_gpt_collaborating.key?(team_id_user) and @chat_gpt_collaborating[team_id_user].key?(Thread.current[:thread_ts])
@@ -123,33 +246,72 @@ class SlackSmartBot
123
246
  end
124
247
  team_id_user_creator = team_creator + "_" + user_creator
125
248
  unless type != :temporary and
126
- (!@open_ai.key?(team_id_user_creator) or !@open_ai[team_id_user_creator].key?(:chat_gpt) or !@open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) or
127
- !@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) or
128
- (@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) and !collaborator and user_creator!=user.name))
129
- save_stats(__method__)
130
- @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:last_activity] = Time.now.strftime("%Y-%m-%d %H:%M:%S") unless session_name == ''
249
+ (!@open_ai.key?(team_id_user_creator) or !@open_ai[team_id_user_creator].key?(:chat_gpt) or !@open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) or
250
+ !@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) or
251
+ (@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) and !collaborator and user_creator != user.name))
252
+ subtype = ""
253
+ if type == :clean
254
+ save_stats(:open_ai_chat_clean_session)
255
+ elsif message.match?(/\A\s*set\s+context\s+(.+)\s*\Z/i)
256
+ subtype = :set_context
257
+ save_stats(:open_ai_chat_set_context)
258
+ elsif message.match(/\A\s*add\s+live\s+(resource|content|feed|doc)s?\s+(.+)\s*\Z/im)
259
+ subtype = :add_live_content
260
+ save_stats(:open_ai_chat_add_live_content)
261
+ elsif message.match(/\A\s*add\s+(static\s+)?(resource|content|doc)s?\s+(.+)\s*\Z/im)
262
+ subtype = :add_static_content
263
+ save_stats(:open_ai_chat_add_static_content)
264
+ elsif message.match(/\A\s*add\s+history\s+(channel\s+)?<#(\w+)\|.*>\s*\Z/im)
265
+ subtype = :add_history_channel
266
+ save_stats(:open_ai_chat_add_history_channel)
267
+ elsif message.match(/\A\s*delete\s+live\s+(resource|content|feed|doc)s?\s+(.+)\s*\Z/im)
268
+ subtype = :delete_live_content
269
+ save_stats(:open_ai_chat_delete_live_content)
270
+ elsif message.match(/\A\s*delete\s+(static\s+)?(resource|content|doc)s?\s+(.+)\s*\Z/im)
271
+ subtype = :delete_static_content
272
+ save_stats(:open_ai_chat_delete_static_content)
273
+ elsif message.match(/\A\s*delete\s+history\s+(channel\s+)?<#(\w+)\|.*>\s*\Z/im)
274
+ subtype = :delete_history_channel
275
+ save_stats(:open_ai_chat_delete_history_channel)
276
+ elsif message.match(/\A\s*add\s+authorization\s+([^\s]+)\s+([^\s]+)\s+(.+)\s*\Z/im)
277
+ subtype = :add_authorization
278
+ save_stats(:open_ai_chat_add_authorization)
279
+ elsif message.match(/\A\s*delete\s+authorization\s+([^\s]+)\s+([^\s]+)\s*\Z/im)
280
+ subtype = :delete_authorization
281
+ save_stats(:open_ai_chat_delete_authorization)
282
+ else
283
+ save_stats(__method__)
284
+ end
285
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:last_activity] = Time.now.strftime("%Y-%m-%d %H:%M:%S") unless session_name == ""
131
286
  @ai_open_ai, message_connect = SlackSmartBot::AI::OpenAI.connect(@ai_open_ai, config, @personal_settings, reconnect: delete_history, service: :chat_gpt)
132
287
 
133
288
  respond message_connect if message_connect
134
289
  if !@ai_open_ai[team_id_user_creator].nil? and !@ai_open_ai[team_id_user_creator][:chat_gpt][:client].nil?
135
290
  @ai_gpt[team_id_user_creator] ||= {}
136
291
  @ai_gpt[team_id_user_creator][session_name] ||= []
137
-
138
- if delete_history or !@open_ai.key?(team_id_user_creator) or !@open_ai[team_id_user_creator].key?(:chat_gpt) or !@open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) or
139
- !@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) or !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:model) or
140
- !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:num_prompts)
141
-
142
- if delete_history and session_name == '' && @open_ai.key?(team_id_user_creator) && @open_ai[team_id_user_creator].key?(:chat_gpt) &&
143
- @open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) && @open_ai[team_id_user_creator][:chat_gpt][:sessions].key?("") &&
144
- @open_ai[team_id_user_creator][:chat_gpt][:sessions][""].key?(:thread_ts)
145
-
292
+ if delete_history or !@open_ai.key?(team_id_user_creator) or !@open_ai[team_id_user_creator].key?(:chat_gpt) or
293
+ !@open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) or
294
+ !@open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) or
295
+ !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:model) or
296
+ !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:num_prompts)
297
+ if delete_history and session_name == "" && @open_ai.key?(team_id_user_creator) && @open_ai[team_id_user_creator].key?(:chat_gpt) &&
298
+ @open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) && @open_ai[team_id_user_creator][:chat_gpt][:sessions].key?("") &&
299
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][""].key?(:thread_ts)
146
300
  @open_ai[team_id_user_creator][:chat_gpt][:sessions][""][:thread_ts].each do |thread_ts|
147
301
  if thread_ts != Thread.current[:thread_ts] && @listening[:threads].key?(thread_ts)
148
302
  unreact :running, thread_ts, channel: @listening[:threads][thread_ts]
149
- message_chatgpt = "I'm sorry, but I'm no longer listening to this thread since you started a new temporary session."
303
+ message_chatgpt = ":information_source: I'm sorry, but I'm no longer listening to this thread since you started a new temporary session."
150
304
  respond message_chatgpt, @listening[:threads][thread_ts], thread_ts: thread_ts
151
305
  @listening[team_id_user_creator].delete(thread_ts)
152
306
  @listening[:threads].delete(thread_ts)
307
+ collaborators_saved.each do |team_id_user_collaborator|
308
+ if @listening.key?(team_id_user_collaborator)
309
+ @listening[team_id_user_collaborator].delete(thread_ts)
310
+ end
311
+ if @chat_gpt_collaborating.key?(team_id_user_collaborator) && @chat_gpt_collaborating[team_id_user_collaborator].key?(thread_ts)
312
+ @chat_gpt_collaborating[team_id_user_collaborator].delete(thread_ts)
313
+ end
314
+ end
153
315
  end
154
316
  end
155
317
  end
@@ -162,117 +324,711 @@ class SlackSmartBot
162
324
  @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:num_prompts] = 0
163
325
  end
164
326
 
165
- if message == "" and session_name == '' # ?? is called
327
+ if message == "" and session_name == "" # ?? is called
166
328
  @ai_gpt[team_id_user_creator][session_name] = []
167
329
  respond "*ChatGPT*: Let's start a new temporary conversation. Ask me anything."
168
- open_ai_chat_use_model(model, dont_save_stats: true) if model != ''
330
+ open_ai_chat_use_model(model, dont_save_stats: true) if model != ""
331
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content] = []
332
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] = []
333
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations] = {}
169
334
  else
335
+ treated = false
170
336
  react :speech_balloon
171
337
  begin
172
338
  urls_messages = []
173
339
  get_openai_sessions(session_name, team_id: team_creator, user_name: user_creator)
174
- @ai_gpt[team_id_user_creator][session_name] = [] if delete_history
340
+ if delete_history
341
+ prompts = []
342
+ if type == :temporary
343
+ @ai_gpt[team_id_user_creator][session_name] = []
344
+ else
345
+ #remove all prompts that are not static content or context
346
+ @ai_gpt[team_id_user_creator][session_name].each do |c|
347
+ if (c[:role] == "user" and c[:content].size == 1 and c[:content][0][:type] == "text" and c[:content][0].key?(:clean_text) and
348
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].include?(c[:content][0][:clean_text])) or
349
+ c[:role] == "system"
350
+ prompts << c
351
+ end
352
+ end
353
+ end
354
+ @ai_gpt[team_id_user_creator][session_name] = prompts
355
+ end
356
+
175
357
  if @open_ai.key?(team_id_user_creator) and @open_ai[team_id_user_creator].key?(:chat_gpt) and @open_ai[team_id_user_creator][:chat_gpt].key?(:sessions) and
176
- @open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) and @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:model)
177
- if model == ''
358
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions].key?(session_name) and @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name].key?(:model)
359
+ if model == ""
178
360
  model = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:model].to_s
179
361
  else
180
362
  @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:model] = model
181
363
  end
182
364
  else
183
- model = ''
365
+ model = ""
184
366
  end
185
367
  model = @ai_open_ai[team_id_user_creator].chat_gpt.model if model.empty?
186
- if message == ''
187
- res = ''
188
- else
189
- if !files.nil? and files.size == 1
190
- http = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config.token}" })
191
- res = http.get(files[0].url_private_download)
192
- message = "#{message}\n\n#{res.data}"
368
+ max_num_tokens = 8000 #default in case no model is found
369
+ @open_ai_model_info ||= {}
370
+ if !@open_ai_model_info.key?(model)
371
+ ai_models_conn, message_conn = SlackSmartBot::AI::OpenAI.connect({}, config, {}, service: :models)
372
+ models = ai_models_conn[team_id_user_creator].models
373
+ unless models.nil? or models.client.nil? or message_conn.to_s != ""
374
+ @open_ai_model_info[model] ||= SlackSmartBot::AI::OpenAI.models(models.client, models, model, return_response: true)
193
375
  end
376
+ end
377
+ if @open_ai_model_info.key?(model) and @open_ai_model_info[model].key?(:max_input_tokens)
378
+ max_num_tokens = @open_ai_model_info[model][:max_input_tokens].to_i
379
+ elsif @open_ai_model_info.key?(model) and @open_ai_model_info[model].key?(:max_tokens)
380
+ max_num_tokens = @open_ai_model_info[model][:max_tokens].to_i
381
+ end
194
382
 
195
- @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:num_prompts] += 1
196
- urls = message.scan(/!(https?:\/\/[\S]+)/).flatten
197
- urls.uniq.each do |url|
198
- begin
199
- parsed_url = URI.parse(url)
200
-
201
- headers = {}
202
- authorizations = {}
383
+ if message.match?(/\A\s*resend\s+prompt\s*\z/i) and !@ai_gpt[team_id_user_creator][session_name].empty?
384
+ files_attached = []
385
+ system_prompt = @ai_gpt[team_id_user_creator][session_name].pop if @ai_gpt[team_id_user_creator][session_name].last[:role] == "system"
386
+ @ai_gpt[team_id_user_creator][session_name].pop if @ai_gpt[team_id_user_creator][session_name].last[:role] == "assistant"
387
+ while @ai_gpt[team_id_user_creator][session_name].last[:role] == "user" and
388
+ @ai_gpt[team_id_user_creator][session_name].last[:content].first[:type] == "image_url"
389
+ files_attached << @ai_gpt[team_id_user_creator][session_name].last[:content].first
390
+ @ai_gpt[team_id_user_creator][session_name].pop
391
+ end
392
+ if @ai_gpt[team_id_user_creator][session_name].last[:role] == "user" and
393
+ @ai_gpt[team_id_user_creator][session_name].last[:content].first[:type] == "text"
394
+ last_prompt = @ai_gpt[team_id_user_creator][session_name].pop
395
+ if last_prompt[:content].first.key?(:clean_text) and
396
+ (@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].nil? or
397
+ !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].include?(last_prompt[:content].first[:clean_text]))
398
+ message = last_prompt[:content].first[:clean_text]
399
+ else
400
+ message = last_prompt[:content].first[:text]
401
+ end
402
+ respond ":information_source: Last ChatGPT response was removed from history.\nPrompt resent: `#{message}`"
403
+ end
404
+ elsif subtype == :set_context
405
+ context = message.match(/\A\s*set\s+context\s+(.+)\s*\Z/i)[1]
406
+ @ai_gpt[team_id_user_creator][session_name] << { role: "system", content: [{ type: "text", text: context }] }
407
+ respond ":information_source: Context set to: `#{context}`"
408
+ treated = true
409
+ elsif message.match(/\A\s*add\s+live\s+(resource|content|feed|doc)s?\s+(.+)\s*\Z/im)
410
+ opts = $2.to_s
411
+ opts.gsub!("!http", "http")
412
+ urls = opts.scan(/https?:\/\/[^\s\/$.?#].[^\s]*/)
413
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content] ||= []
414
+ copy_of_user = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
415
+ if copy_of_user.to_s != "" and copy_of_user != user_name
416
+ #check if host of url is in authorizations of the user orig of the session
417
+ team_id_user_orig = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_team] + "_" +
418
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
419
+ copy_of_session = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session]
420
+ auth_user_orig = @open_ai[team_id_user_orig][:chat_gpt][:sessions][copy_of_session][:authorizations]
421
+ not_allowed = []
422
+ #if the host is on auth of the user orig, then it is not allwed for other users to add it
423
+ urls.each do |url|
424
+ host = URI.parse(url).host
425
+ if auth_user_orig.key?(host)
426
+ not_allowed << url
427
+ end
428
+ end
429
+ if not_allowed.size > 0
430
+ respond ":warning: You are not allowed to add the following URLs because they are part of the authorizations of the user that created the session:\n\t\t - `#{not_allowed.join("`\n\t\t - `")}`"
431
+ urls -= not_allowed
432
+ end
433
+ end
434
+ if urls.size > 0
435
+ urls.each do |url|
436
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content] << url
437
+ end
438
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content].uniq!
439
+ respond ":globe_with_meridians: Live content added:\n\t\t - `#{urls.join("`\n\t\t - `")}`\nEvery time you send a new prompt, it will use the latest version of the resource.\nCall `delete live content URL1 URL99` to remove them."
440
+ end
441
+ treated = true
442
+ elsif message.match(/\A\s*add\s+(static\s+)?(resource|content|doc)s?\s+(.+)\s*\Z/im)
443
+ opts = $3.to_s
444
+ opts.gsub!("!http", "http")
445
+ urls = opts.scan(/https?:\/\/[^\s\/$.?#].[^\s]*/)
446
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] ||= []
447
+ copy_of_user = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
448
+ if copy_of_user.to_s != "" and copy_of_user != user_name
449
+ #check if host of url is in authorizations of the user orig of the session
450
+ team_id_user_orig = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_team] + "_" +
451
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
452
+ copy_of_session = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session]
453
+ auth_user_orig = @open_ai[team_id_user_orig][:chat_gpt][:sessions][copy_of_session][:authorizations]
454
+ not_allowed = []
455
+ #if the host is on auth of the user orig, then it is not allwed for other users to add it
456
+ urls.each do |url|
457
+ host = URI.parse(url).host
458
+ if auth_user_orig.key?(host)
459
+ not_allowed << url
460
+ end
461
+ end
462
+ if not_allowed.size > 0
463
+ respond ":warning: You are not allowed to add the following URLs because they are part of the authorizations of the user that created the session:\n\t\t - `#{not_allowed.join("`\n\t\t - `")}`"
464
+ urls -= not_allowed
465
+ end
466
+ end
467
+ if urls.size > 0
468
+ authorizations = get_authorizations(session_name, team_id_user_creator)
469
+ threads = []
470
+ urls.uniq.each do |url|
471
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] << url
472
+ threads << Thread.new do
473
+ text, url_message = download_http_content(url, authorizations, team_id_user_creator, session_name)
474
+ @ai_gpt[team_id_user_creator][session_name] << { role: "user", content: [{ type: "text", text: text, clean_text: url }] }
475
+ end
476
+ end
477
+ threads.each(&:join)
203
478
 
204
- if config.key?(:authorizations)
205
- config[:authorizations].each do |key, value|
206
- if value.key?(:host)
207
- authorizations[value[:host]] = value
479
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].uniq!
480
+ update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == ""
481
+ respond ":pushpin: Static content added:\n\t\t - `#{urls.join("`\n\t\t - `")}`\nCall `delete static content URL1 URL99` to remove them."
482
+ end
483
+ treated = true
484
+ elsif message.match(/\A\s*add\s+history\s+(channel\s+)?<#(\w+)\|.*>\s*\Z/im)
485
+ channel_history = $2.to_s
486
+ #check if the user is on the channel or on a DM with the bot
487
+ if Thread.current[:dest][0] == "D" or Thread.current[:dest] == channel_history
488
+ members_channel_history = get_channel_members(channel_history)
489
+ #check if SmartBot and The granular smartbot are members of the channel
490
+ if members_channel_history.include?(config.nick_id) and members_channel_history.include?(config.nick_id_granular)
491
+ if Thread.current[:dest][0] == "D"
492
+ #Check if the user is a member of the Channel
493
+ if !members_channel_history.include?(user.id)
494
+ respond ":warning: You are not a member of the channel <##{channel_history}>."
495
+ end
496
+ end
497
+ #get the history of the channel
498
+ @history_still_running ||= false
499
+ if @history_still_running
500
+ respond "Due to Slack API rate limit, when getting history of a channel this command is limited. Waiting for other command to finish."
501
+ num_times = 0
502
+ while @history_still_running and num_times < 30
503
+ num_times += 1
504
+ sleep 1
505
+ end
506
+ if @history_still_running
507
+ respond "Sorry, Another command is still running after 30 seconds. Please try again later."
508
+ end
509
+ end
510
+ unless @history_still_running
511
+ @history_still_running = true
512
+ #from 6 months ago
513
+ from = Time.now - 60 * 60 * 24 * 180
514
+ to = Time.now
515
+ respond "Adding the history of the channel from #{from.strftime("%Y-%m-%d")}. Take in consideration that this could take a while."
516
+ hist = []
517
+ num_times = 0
518
+ while hist.empty? and num_times < 6
519
+ client_granular.conversations_history(channel: channel_history, limit: 1000, oldest: from.to_f, latest: to.to_f) do |response|
520
+ hist << response.messages
521
+ end
522
+ hist.flatten!
523
+ num_times += 1
524
+ if hist.empty?
525
+ if num_times == 1
526
+ respond "It seems like the history of the channel is empty. It could be the Slack API rate limit. I'll try again for one minute."
208
527
  end
528
+ sleep 10
209
529
  end
210
530
  end
211
-
212
- if @personal_settings_hash.key?(team_id_user) and @personal_settings_hash[team_id_user].key?(:authorizations)
213
- @personal_settings_hash[team_id_user][:authorizations].each do |key, value|
214
- if value.key?(:host)
215
- authorizations[value[:host]] = value
531
+ messages = {} # store the messages by year/month
532
+ act_users = {}
533
+ act_threads = {}
534
+ #from the past 6 months
535
+ hist.each do |hist_message|
536
+ if Time.at(hist_message.ts.to_f) >= from
537
+ year_month = Time.at(hist_message.ts.to_f).strftime("%Y-%m")
538
+ messages[year_month] ||= []
539
+ if hist_message.key?("thread_ts")
540
+ thread_ts_message = hist_message.thread_ts
541
+ replies = client_granular.conversations_replies(channel: channel_history, ts: thread_ts_message) #jal, latest: last_msg.ts)
542
+ sleep 0.5 #to avoid rate limit Tier 3 (50 requests per minute)
543
+ messages_replies = ["Thread Started about last message:"]
544
+ act_threads[hist_message.ts] = replies.messages.size
545
+ replies.messages.each_with_index do |msgrepl, i|
546
+ act_users[msgrepl.user] ||= 0
547
+ act_users[msgrepl.user] += 1
548
+ messages_replies << "<@#{msgrepl.user}> (#{Time.at(msgrepl.ts.to_f)}) wrote:> #{msgrepl.text}" if i > 0
549
+ end
550
+ messages_replies << "Thread ended."
551
+ messages[year_month] += messages_replies.reverse # the order on repls is from older to newer
216
552
  end
553
+ act_users[hist_message.user] ||= 0
554
+ act_users[hist_message.user] += 1
555
+ url_to_message = "https://#{client.team.domain}.slack.com/archives/#{channel_history}/#{hist_message.ts}"
556
+ messages[year_month] << "<@#{hist_message.user}> (#{Time.at(hist_message.ts.to_f)}) (link to the message: #{url_to_message}) wrote:> #{hist_message.text}"
217
557
  end
218
558
  end
219
-
220
- authorizations.each do |key, value|
221
- if key.match?(/^(https:\/\/|http:\/\/)?#{parsed_url.host.gsub('.','\.')}/)
222
- value.each do |k, v|
223
- headers[k.to_sym] = v unless k == :host
559
+ @history_still_running = false
560
+ messages.each do |year_month, msgs|
561
+ messages[year_month] = msgs.reverse # the order on history is from newer to older
562
+ end
563
+ if messages.empty?
564
+ #last 6 months
565
+ message_history = ":warning: No messages found on the channel <##{channel_history}> from the past 6 months."
566
+ message_history += "\n\nIt could be the Slack API rate limit. Please try again in a while."
567
+ respond message_history
568
+ else
569
+ #sort by year/month from older to newer
570
+ messages = messages.sort_by { |k, v| k }.to_h
571
+ #check num_tokens don't exceed max_num_tokens
572
+ #remove messages if it exceeds from the oldest to the newest
573
+ num_tokens = 0
574
+ prompts_check = @ai_gpt[team_id_user_creator][session_name].deep_copy
575
+ prompts_check_text = prompts_check.map { |c| c[:content].map { |cont| cont[:text] }.join("\n") }.join("\n")
576
+ enc = Tiktoken.encoding_for_model("gpt-4") #jal todo: fixed value since version 0.0.8 and 0.0.9 failed to install on SmartBot VM. Revert when fixed.
577
+ text_to_check = nil
578
+ num_tokens = 0
579
+ removed_months = []
580
+ while text_to_check.nil? or num_tokens > (max_num_tokens - 1000)
581
+ if num_tokens > (max_num_tokens - 1000)
582
+ removed_months << messages.keys.first
583
+ messages.shift
584
+ end
585
+ text_to_check = messages.values.flatten.join("\n") + prompts_check_text
586
+ num_tokens = enc.encode(text_to_check.to_s).length
587
+ end
588
+ if messages.empty?
589
+ message_history = ":warning: The history of the channel exceeds the limit of tokens allowed."
590
+ if removed_months.size > 0
591
+ message_history += "\n\n:The following months were removed because the total number of ChatGPT tokens exceeded the limit of the model:\n\t\t - `#{removed_months.join("`\n\t\t - `")}`"
592
+ end
593
+ else
594
+ history_text = "This is the history of conversations on the Slack channel <##{channel_history}>:\n\n#{messages.values.flatten.join("\n")}"
595
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] ||= []
596
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] << "History of <##{channel_history}>"
597
+ @ai_gpt[team_id_user_creator][session_name] << { role: "user", content: [{ type: "text", text: history_text, clean_text: "History of <##{channel_history}>" }] }
598
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].uniq!
599
+ update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == ""
600
+ message_history = ":scroll: History of the channel <##{channel_history}> from the past 6 months added to the session.\nCall `delete history <##{channel_history}>` to delete it."
601
+ if removed_months.size > 0
602
+ message_history += "\n\n:warning: The following months were removed because the total number of tokens exceeded the limit:\n\t\t - `#{removed_months.join("`\n\t\t - `")}`"
224
603
  end
604
+ message_history += "\n\nThe history of that channel will be used as part of the prompts for the next responses."
605
+ # specify month and year
606
+ message_history += "\n\nThe first message added is from #{messages.keys.first}."
607
+ message_history += "\n\t\tTotal number of messages added: #{messages.values.flatten.size - act_threads.size}."
608
+ message_history += "\n\t\tNumber of threads added: #{act_threads.size}."
609
+ message_history += "\n\t\tNumber of messages on threads added: #{act_threads.values.sum}." unless removed_months.size > 0
610
+ respond message_history
225
611
  end
226
612
  end
613
+ end
614
+ else
615
+ respond ":warning: <@#{config.nick_id}> and <@#{config.nick_id_granular}> need to be members of the channel <##{channel_history}> to be able to add its history. Please add them to the channel and try again."
616
+ end
617
+ else
618
+ respond ":warning: You can only add the history of a Slack channel where you are or on a DM with me."
619
+ end
227
620
 
228
- domain = "#{parsed_url.scheme}://#{parsed_url.host}"
229
- http = NiceHttp.new(host: domain, headers: headers, log: :no)
230
- response = http.get(parsed_url.path)
231
- html_doc = Nokogiri::HTML(response.body)
232
- html_doc.search('script, style').remove
233
- text = html_doc.text.strip
234
- text.gsub!(/^\s*$/m, "")
235
- urls_messages << "> #{url}: content extracted and added to prompt\n"
236
- http.close
237
- rescue Exception => e
238
- text = "Error: #{e.message}"
239
- urls_messages << "> #{url}: #{text}\n"
240
- end
241
- message.gsub!("!#{url}", '')
242
- message += "\n #{text}\n"
621
+ treated = true
622
+ elsif message.match(/\A\s*delete\s+live\s+(resource|content|feed|doc)s?\s+(.+)\s*\Z/im)
623
+ opts = $2.to_s
624
+ opts.gsub!("!http", "http")
625
+ urls = opts.scan(/https?:\/\/[^\s\/$.?#].[^\s]*/)
626
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content] ||= []
627
+ not_found = []
628
+ urls.each do |url|
629
+ unless @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content].delete(url)
630
+ not_found << url
631
+ end
632
+ end
633
+ message_live_content = []
634
+ message_live_content << "Live content removed: `#{(urls - not_found).join("`, `")}`." if (urls - not_found).size > 0
635
+ message_live_content << "Not found: `#{not_found.join("`, `")}`." if not_found.size > 0
636
+ respond ":globe_with_meridians: #{message_live_content.join("\n")}"
637
+ treated = true
638
+ elsif message.match(/\A\s*delete\s+(static\s+)?(resource|content|doc)s?\s+(.+)\s*\Z/im)
639
+ opts = $3.to_s
640
+ opts.gsub!("!http", "http")
641
+ urls = opts.scan(/https?:\/\/[^\s\/$.?#].[^\s]*/)
642
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] ||= []
643
+ not_found = []
644
+ urls.each do |url|
645
+ unless @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].delete(url)
646
+ not_found << url
647
+ end
648
+ @ai_gpt[team_id_user_creator][session_name].each do |prompt|
649
+ prompt[:content].each do |content|
650
+ if content[:type] == "text" and content[:clean_text] == url
651
+ @ai_gpt[team_id_user_creator][session_name].delete(prompt)
652
+ end
653
+ end
654
+ end
655
+ end
656
+ update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == ""
657
+ message_static_content = []
658
+ message_static_content << "Static content removed: `#{(urls - not_found).join("`, `")}`." if (urls - not_found).size > 0
659
+ message_static_content << "Not found: `#{not_found.join("`, `")}`." if not_found.size > 0
660
+ respond ":pushpin: #{message_static_content.join("\n")}"
661
+ treated = true
662
+ elsif message.match(/\A\s*delete\s+history\s+(channel\s+)?<#(\w+)\|.*>\s*\Z/im)
663
+ channel_history = $2.to_s
664
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content] ||= []
665
+ @ai_gpt[team_id_user_creator][session_name].each do |prompt|
666
+ prompt[:content].each do |content|
667
+ if content[:type] == "text" and content[:clean_text] == "History of <##{channel_history}>"
668
+ @ai_gpt[team_id_user_creator][session_name].delete(prompt)
669
+ end
670
+ end
243
671
  end
672
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:static_content].delete_if { |url| url == "History of <##{channel_history}>" }
673
+ update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == ""
674
+ respond ":scroll: History of the channel <##{channel_history}> removed from the session."
675
+ treated = true
244
676
 
245
- @ai_gpt[team_id_user_creator][session_name] << "Me> #{message}"
246
- prompts = @ai_gpt[team_id_user_creator][session_name].join("\n\n")
247
- prompts.gsub!(/^Me>\s*/,'')
248
- prompts.gsub!(/^chatGPT>\s*/,'')
249
- success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(@ai_open_ai[team_id_user_creator][:chat_gpt][:client], model, prompts, @ai_open_ai[team_id_user_creator].chat_gpt)
250
- if success
251
- @ai_gpt[team_id_user_creator][session_name] << "chatGPT> #{res}"
677
+ #add authorization HOST HEADER VALUE
678
+ #for example: add authorization api.example.com Authorization Bearer 123456
679
+ elsif message.match(/\A\s*add\s+authorization\s+([^\s]+)\s+([^\s]+)\s+(.+)\s*\Z/im)
680
+ host = $1.to_s
681
+ header = $2.to_s
682
+ value = $3.to_s
683
+ #remove http:// or https:// from host
684
+ host.gsub!(/\Ahttps?:\/\//, "")
685
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations] ||= {}
686
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host] ||= {}
687
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host][header] = value
688
+ message_sec = [":key: Authorization header added: `#{header}` for host `#{host}`."]
689
+ message_sec << "Call `delete authorization HOST HEADER` to remove it."
690
+ message_sec << "This authorization will be used only for this session."
691
+ unless type == :temporary
692
+ message_sec << "If you share this session, they will be able to use the authorization but will not be able to see the authorization value."
693
+ end
694
+ respond message_sec.join("\n")
695
+ treated = true
696
+ #delete authorization HOST HEADER
697
+ #for example: delete authorization api.example.com Authorization
698
+ elsif message.match(/\A\s*delete\s+authorization\s+([^\s]+)\s+([^\s]+)\s*\Z/im)
699
+ host = $1.to_s
700
+ header = $2.to_s
701
+ host.gsub!(/\Ahttps?:\/\//, "")
702
+ if @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations].nil? or
703
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host].nil? or
704
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host][header].nil?
705
+ respond ":key: Authorization header not found: `#{header}` for host `#{host}`."
706
+ else
707
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations] ||= {}
708
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host] ||= {}
709
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:authorizations][host].delete(header)
710
+ respond ":key: Authorization header deleted: `#{header}` for host `#{host}`."
252
711
  end
712
+ treated = true
253
713
  end
254
- if session_name == ''
255
- temp_session_name = @ai_gpt[team_id_user_creator][''].first[0..35].gsub('Me> ','')
256
- respond "*ChatGPT* Temporary session: _<#{temp_session_name.gsub("\n",' ').gsub("`",' ')}...>_ model: #{model}\n#{res.to_s.strip}"
257
- if res.to_s.strip == ''
258
- respond "It seems like GPT is not responding. Please try again later or use another model, as it might be overloaded."
714
+ unless treated
715
+ num_folder_docs = 0
716
+ if message == ""
717
+ res = ""
718
+ prompts ||= []
719
+ else
720
+ restricted = false
721
+ files_attached ||= []
722
+ if !files.nil?
723
+ files.each do |file|
724
+ http2 = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config.token}" })
725
+ res = http2.get(file.url_private_download)
726
+ #identify the type of file. In case of image identify the type and encode it to base64
727
+ if res[:'content-type'].to_s.include?("image")
728
+ require "base64"
729
+ image_type = res[:'content-type'].split("/")[1]
730
+ data = "data:image/#{image_type};base64,#{Base64.strict_encode64(res.body)}"
731
+ files_attached << { type: "image_url", image_url: { url: data } }
732
+ else
733
+ message = "#{message}\n\n#{res.data}"
734
+ end
735
+ http2.close
736
+ end
737
+ end
738
+
739
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:num_prompts] += 1
740
+ urls = message.scan(/!(https?:\/\/[\S]+)/).flatten
741
+ if urls.size > 0 and @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user] != user_name
742
+ #check if host of url is in authorizations of the user orig of the session
743
+ team_id_user_orig = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_team] + "_" +
744
+ @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
745
+ copy_of_session = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session]
746
+ if @open_ai.key?(team_id_user_orig) and @open_ai[team_id_user_orig].key?(:chat_gpt) and
747
+ @open_ai[team_id_user_orig][:chat_gpt].key?(:sessions) and @open_ai[team_id_user_orig][:chat_gpt][:sessions].key?(copy_of_session) and
748
+ !@open_ai[team_id_user_orig][:chat_gpt][:sessions][copy_of_session].key?(:authorizations)
749
+ auth_user_orig = @open_ai[team_id_user_orig][:chat_gpt][:sessions][copy_of_session][:authorizations]
750
+ else
751
+ auth_user_orig = {}
752
+ end
753
+ not_allowed = []
754
+ #if the host is on auth of the user orig, then it is not allwed for other users to add it
755
+ urls.each do |url|
756
+ host = URI.parse(url).host
757
+ if auth_user_orig.key?(host)
758
+ not_allowed << url
759
+ end
760
+ end
761
+ if not_allowed.size > 0
762
+ respond ":warning: You are not allowed to add the following URLs because they are part of the authorizations of the user that created the session:\n\t\t - `#{not_allowed.join("`\n\t\t - `")}`"
763
+ urls -= not_allowed
764
+ end
765
+ end
766
+
767
+ if !@open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content].nil?
768
+ urls += @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:live_content]
769
+ end
770
+ #get a copy of message
771
+ clean_message = message.dup
772
+ authorizations = get_authorizations(session_name, team_id_user_creator)
773
+ #download the content of the urls simultaneously on threads
774
+ threads = []
775
+ texts = []
776
+ urls.uniq.each do |url|
777
+ threads << Thread.new do
778
+ text, url_message = download_http_content(url, authorizations, team_id_user_creator, session_name)
779
+ urls_messages << url_message if url_message != ""
780
+ texts << text
781
+ end
782
+ end
783
+ threads.each(&:join)
784
+ urls.uniq.each do |url|
785
+ message.gsub!("!#{url}", "")
786
+ end
787
+ texts.each do |text|
788
+ message += "\n #{text}\n"
789
+ end
790
+
791
+ if urls.empty?
792
+ @ai_gpt[team_id_user_creator][session_name] << { role: "user", content: [{ type: "text", text: message }] }
793
+ else
794
+ @ai_gpt[team_id_user_creator][session_name] << { role: "user", content: [{ type: "text", text: message, clean_text: clean_message }] }
795
+ end
796
+ files_attached.each do |file|
797
+ @ai_gpt[team_id_user_creator][session_name] << { role: "user", content: [file] }
798
+ end
799
+ prompts = @ai_gpt[team_id_user_creator][session_name].deep_copy
800
+ prompts.each do |prompt|
801
+ prompt[:content].each do |content|
802
+ content.delete(:clean_text)
803
+ end
804
+ end
805
+ if @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session] == ""
806
+ path_to_session_folder = "#{config.path}/openai/#{team_creator}/#{user_creator}/#{session_name}"
807
+ term_to_avoid = session_name
808
+ else
809
+ copy_of_team = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_team]
810
+ copy_of_user = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_user]
811
+ term_to_avoid = @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session]
812
+ path_to_session_folder = "#{config.path}/openai/#{copy_of_team}/#{copy_of_user}/"
813
+ path_to_session_folder += @open_ai[team_id_user_creator][:chat_gpt][:sessions][session_name][:copy_of_session].to_s
814
+ end
815
+
816
+ if Dir.exist?(path_to_session_folder)
817
+ #read the content of chatgpt_prompts.json and add it to the prompts at the beginning
818
+ if !File.exist?("#{path_to_session_folder}/chatgpt_prompts.json")
819
+ # Get the content of all files in all folders and subfolders and add it to the chatgpt_prompts.json file
820
+ docs_folder_prompts = []
821
+ #enc = Tiktoken.encoding_for_model(model)
822
+ enc = Tiktoken.encoding_for_model("gpt-4") #jal todo: fixed value since version 0.0.8 and 0.0.9 failed to install on SmartBot VM. Revert when fixed.
823
+ # all files in the docs_folder should be in text format
824
+ # first all files on 'include' folder then all files on 'filter' folder
825
+ ["#{path_to_session_folder}/docs_folder/include/**/*", "#{path_to_session_folder}/docs_folder/filter/**/*"].each do |folder|
826
+ Dir.glob(folder).each do |file|
827
+ next if File.directory?(file)
828
+ file_content = File.read(file)
829
+ num_tokens = enc.encode(file_content.to_s).length
830
+ docs_folder_prompts << {
831
+ role: "user",
832
+ content: [
833
+ { type: "text", text: file_content, include_file: file.include?("/docs_folder/include/"), num_tokens: num_tokens, clean_text: file },
834
+ ],
835
+ }
836
+ end
837
+ end
838
+ File.open("#{path_to_session_folder}/chatgpt_prompts.json", "w") do |f|
839
+ f.write(docs_folder_prompts.to_json)
840
+ end
841
+ end
842
+ if File.exist?("#{path_to_session_folder}/chatgpt_prompts.json")
843
+ # Extract all sentences from the prompts not including the system prompts or the user prompts that are images or responses from chatGPT
844
+ all_sentences = ""
845
+ prompts.each do |prompt|
846
+ if prompt[:role] == "user" and prompt[:content].size == 1 and prompt[:content][0][:type] == "text"
847
+ all_sentences += prompt[:content][0][:text] + " "
848
+ end
849
+ end
850
+ list_avoid = ["use", "set", "bash", term_to_avoid]
851
+ keywords = get_keywords(all_sentences, list_avoid: list_avoid)
852
+
853
+ # Read the JSON file
854
+ file_content = File.read("#{path_to_session_folder}/chatgpt_prompts.json")
855
+ json_data = JSON.parse(file_content, symbolize_names: true)
856
+
857
+ #remove keyword if keyword is in more than 50% of the documents
858
+ keywords_num_docs = {}
859
+ keywords.delete_if do |k|
860
+ num_found = 0
861
+ #check if the keyword is in the text field but not in the clean_text field (file name)
862
+ json_data.each do |entry|
863
+ num_found += 1 if entry[:content][0][:text].match?(/#{k}/i) and !entry[:content][0][:clean_text].to_s.match?(/#{k}/i)
864
+ end
865
+ keywords_num_docs[k] = num_found
866
+ num_found > (json_data.size / 2)
867
+ end
868
+
869
+ # Filter the JSON data to include only entries with keywords in the text field.
870
+ # Order the entries by the number of keywords found in the text field.
871
+ data_num_keywords = {}
872
+ json_data.each do |entry|
873
+ num_found = 0
874
+ total_occurrences = 0
875
+ keywords.each do |k|
876
+ num_found += 1 if entry[:content][0][:text].match?(/#{k}/i)
877
+ total_occurrences += entry[:content][0][:text].scan(/#{k}/i).size
878
+ end
879
+ entry[:content][0][:total_occurrences] = total_occurrences
880
+ data_num_keywords[num_found] ||= []
881
+ data_num_keywords[num_found] << entry
882
+ end
883
+ #delete all entries that have no keywords
884
+ data_num_keywords.delete(0)
885
+ #sort the data_num_keywords by the number of keywords found in the text field. From the highest to the lowest
886
+ data_num_keywords = data_num_keywords.sort_by { |k, v| k }.reverse.to_h
887
+ #sort by the total_occurrences descending
888
+ data_num_keywords.each do |k, v|
889
+ v.sort_by! { |entry| entry[:content][0][:total_occurrences] }.reverse!
890
+ end
891
+ #remove occurences of 1 keyword if 10 or more documents have been found with more than 1 keyword
892
+ if data_num_keywords.values.flatten.uniq.size > (json_data.size / 2) and data_num_keywords.keys.size > 1 and
893
+ data_num_keywords.key?(1) and (data_num_keywords.values.flatten.uniq.size - data_num_keywords[1].size) >= 10
894
+
895
+ #remove data_num_keywords for entries that have less than 2 keywords found
896
+ data_num_keywords.delete(1)
897
+ end
898
+
899
+ #flatten the data_num_keywords
900
+ filtered_data = data_num_keywords.values.flatten.uniq
901
+
902
+ #add all the entries that have the include_file set to true
903
+ json_data.each do |entry|
904
+ if entry[:content][0][:include_file]
905
+ filtered_data << entry
906
+ end
907
+ end
908
+
909
+ # put on top of the filtered_data the entries that have the include_file set to true
910
+ filtered_data.sort_by! { |entry| entry[:content][0][:include_file] ? 0 : 1 }
911
+
912
+ #remove key "include_file" and total_occurrences from filtered_data
913
+ filtered_data.each do |entry|
914
+ entry[:content].each do |content_block|
915
+ content_block.delete(:include_file)
916
+ content_block.delete(:total_occurrences)
917
+ end
918
+ end
919
+ filtered_data.uniq!
920
+
921
+ #enc = Tiktoken.encoding_for_model(model)
922
+ enc = Tiktoken.encoding_for_model("gpt-4") #jal todo: fixed value since version 0.0.8 and 0.0.9 failed to install on SmartBot VM. Revert when fixed.
923
+ prompts_orig = prompts.deep_copy
924
+ prompts = filtered_data + prompts
925
+ #content = (prompts || []).map do |entry|
926
+ # (entry[:content] || []).map { |content_block| content_block[:text] }
927
+ #end.flatten
928
+ content = ""
929
+ prompts.each do |prompt|
930
+ content += prompt[:content][0][:text] if prompt.key?(:content) and prompt[:content][0].key?(:text)
931
+ end
932
+
933
+ num_tokens = enc.encode(content.to_s).length
934
+
935
+ respond ":information_source: The number of tokens in the prompt including all filtered docs is *#{num_tokens}*.\n\tWe will remove docs to ensure we don't reach the max num of allowed tokens for this ChatGPT model." if num_tokens > max_num_tokens
936
+ if num_tokens > (max_num_tokens - 1000) #since the number of tokens is not exact, we allow 1000 tokens less
937
+ #remove filtered_data one by one from the end until the number of tokens is less than max_num_tokens
938
+ while num_tokens > (max_num_tokens - 1000) and filtered_data.size > 0
939
+ filtered_data.pop
940
+ prompts = filtered_data + prompts_orig
941
+ content = ""
942
+ num_tokens = 0
943
+ prompts.each do |prompt|
944
+ if prompt[:content][0].key?(:num_tokens) and prompt[:content][0][:num_tokens] > 0
945
+ num_tokens += prompt[:content][0][:num_tokens]
946
+ else
947
+ if prompt.key?(:content) and prompt[:content][0].key?(:text)
948
+ content += prompt[:content][0][:text]
949
+ end
950
+ end
951
+ end
952
+ num_tokens += enc.encode(content.to_s).length if content != ""
953
+ end
954
+ end
955
+ num_folder_docs = filtered_data.size
956
+ end
957
+ #delete num_tokens from content
958
+ prompts.each do |entry|
959
+ entry[:content].each do |content_block|
960
+ content_block.delete(:num_tokens)
961
+ end
962
+ end
963
+ end
964
+ if @chat_gpt_default_model != model and File.exist?("#{config.path}/openai/restricted_models.yaml")
965
+ restricted_models = YAML.load_file("#{config.path}/openai/restricted_models.yaml")
966
+ if restricted_models.key?(model) and !restricted_models[model].include?(team_id_user_creator) and !restricted_models[model].include?(user_creator)
967
+ respond "You don't have access to this model: #{model}. You can request access to an admin user."
968
+ restricted = true
969
+ end
970
+ end
971
+ if !restricted
972
+ success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(@ai_open_ai[team_id_user_creator][:chat_gpt][:client], model, prompts, @ai_open_ai[team_id_user_creator].chat_gpt)
973
+ if success
974
+ @ai_gpt[team_id_user_creator][session_name] << { role: "assistant", content: [{ type: "text", text: res }] }
975
+ @ai_gpt[team_id_user_creator][session_name] << system_prompt if system_prompt
976
+ end
977
+ end
259
978
  end
260
- #to avoid logging the prompt or the response
261
- if config.encrypt
262
- Thread.current[:encrypted] ||= []
263
- Thread.current[:encrypted] << message
979
+ unless restricted
980
+ #enc = Tiktoken.encoding_for_model(model)
981
+ enc = Tiktoken.encoding_for_model("gpt-4") #jal todo: fixed value since version 0.0.8 and 0.0.9 failed to install on SmartBot VM. Revert when fixed.
982
+ content = ""
983
+ prompts.each do |prompt|
984
+ content += prompt[:content][0][:text] if prompt.key?(:content) and prompt[:content][0].key?(:text)
985
+ end
986
+
987
+ num_tokens = enc.encode(content.to_s).length
988
+
989
+ if num_tokens > max_num_tokens and type != :clean
990
+ message_max_tokens = ":warning: The total number of tokens in the prompt is #{num_tokens}, which is greater than the maximum number of tokens allowed for the model (#{max_num_tokens})."
991
+ message_max_tokens += "\nTry to be more concrete writing your prompt. The number of docs attached according to your prompt was #{num_folder_docs}\n" if num_folder_docs > 0
992
+ respond message_max_tokens
993
+ end
994
+
995
+ if session_name == ""
996
+ temp_session_name = @ai_gpt[team_id_user_creator][""].first.content.first.text.to_s[0..35] #jal
997
+ res_slack_mkd = transform_to_slack_markdown(res.to_s.strip)
998
+ if num_folder_docs > 0
999
+ docs_message = "\n:notebook_with_decorative_cover: *#{num_folder_docs} documents* were added for this prompt (keywords: _#{keywords.sort[0..9].join(", ")}#{" ..." if keywords.size > 10}_)\n\n"
1000
+ else
1001
+ docs_message = ""
1002
+ end
1003
+ obj_id = @ai_gpt[team_id_user_creator][""].first.object_id
1004
+ respond "*ChatGPT* Temporary session: _<#{temp_session_name.gsub("\n", " ").gsub("`", " ")}...>_ (#{obj_id}) model: #{model} num_tokens: #{num_tokens}#{docs_message}\n#{res_slack_mkd}", split: false
1005
+ if res.to_s.strip == ""
1006
+ respond "It seems like GPT is not responding. Please try again later or use another model, as it might be overloaded."
1007
+ end
1008
+ #to avoid logging the prompt or the response
1009
+ if config.encrypt
1010
+ Thread.current[:encrypted] ||= []
1011
+ Thread.current[:encrypted] << message
1012
+ end
1013
+ elsif res.to_s.strip == ""
1014
+ res = "\nAll prompts were removed from session." if delete_history
1015
+ respond "*ChatGPT* Session _<#{session_name}>_ model: #{model}#{res}"
1016
+ respond "It seems like GPT is not responding. Please try again later or use another model, as it might be overloaded." if message != ""
1017
+ else
1018
+ res_slack_mkd = transform_to_slack_markdown(res.to_s.strip)
1019
+ if num_folder_docs > 0
1020
+ docs_message = "\n:open_file_folder: #{num_folder_docs} documents from the folder were added to the prompts."
1021
+ else
1022
+ docs_message = ""
1023
+ end
1024
+ respond "*ChatGPT* Session _<#{session_name}>_ model: #{model} num_tokens: #{num_tokens}#{docs_message}\n#{res_slack_mkd}", split: false
1025
+ end
1026
+ if urls_messages.size > 0
1027
+ respond urls_messages.join("\n")
1028
+ end
264
1029
  end
265
- elsif res.to_s.strip == ''
266
- res = "\nAll prompts were removed from session." if delete_history
267
- respond "*ChatGPT* Session _<#{session_name}>_ model: #{model}#{res}"
268
- respond "It seems like GPT is not responding. Please try again later or use another model, as it might be overloaded." if message != ''
269
- else
270
- respond "*ChatGPT* Session _<#{session_name}>_ model: #{model}\n#{res.to_s.strip}"
271
- end
272
- if urls_messages.size > 0
273
- respond urls_messages.join("\n")
274
1030
  end
275
- update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == ''
1031
+ update_openai_sessions(session_name, team_id: team_creator, user_name: user_creator) unless session_name == "" or !success or restricted
276
1032
  rescue => exception
277
1033
  respond "*ChatGPT*: Sorry, I'm having some problems. OpenAI probably is not available. Please try again later."
278
1034
  @logger.warn exception