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.
- checksums.yaml +4 -4
- data/README.md +34 -1
- data/img/chat_gpt_attach_image.png +0 -0
- data/lib/slack/smart-bot/ai/open_ai/models.rb +19 -10
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +14 -10
- data/lib/slack/smart-bot/comm/dont_understand.rb +23 -6
- data/lib/slack/smart-bot/comm/get_user_info.rb +9 -10
- data/lib/slack/smart-bot/comm/respond.rb +56 -28
- data/lib/slack/smart-bot/comm/send_file.rb +17 -6
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +885 -129
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +3 -3
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +132 -15
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +1 -1
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +50 -12
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +99 -34
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +12 -2
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +36 -25
- data/lib/slack/smart-bot/commands/general/bot_help.rb +29 -24
- data/lib/slack/smart-bot/commands/general/poster.rb +0 -1
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +1 -1
- data/lib/slack/smart-bot/commands/general/summarize.rb +22 -8
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +156 -55
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +13 -11
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +21 -17
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +2 -2
- data/lib/slack/smart-bot/commands.rb +19 -19
- data/lib/slack/smart-bot/process_first.rb +38 -35
- data/lib/slack/smart-bot/treat_message.rb +57 -56
- data/lib/slack/smart-bot/utils/download_http_content.rb +91 -0
- data/lib/slack/smart-bot/utils/get_authorizations.rb +41 -0
- data/lib/slack/smart-bot/utils/get_keywords.rb +33 -0
- data/lib/slack/smart-bot/utils/get_openai_sessions.rb +46 -6
- data/lib/slack/smart-bot/utils/get_teams.rb +9 -1
- data/lib/slack/smart-bot/utils/save_stats.rb +13 -5
- data/lib/slack/smart-bot/utils/transform_to_slack_markdown.rb +36 -0
- data/lib/slack/smart-bot/utils/update_openai_sessions.rb +9 -4
- data/lib/slack/smart-bot/utils.rb +48 -44
- data/lib/slack-smart-bot.rb +10 -9
- data/whats_new.txt +27 -1
- metadata +63 -2
@@ -1,46 +1,45 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
|
3
|
-
def bot_help(user, from, dest, dchannel, specific, help_command, rules_file, savestats: true, strict: false, send_to_file: false)
|
2
|
+
def bot_help(user, from, dest, dchannel, specific, help_command, rules_file, savestats: true, strict: false, send_to_file: false, return_output: false)
|
4
3
|
save_stats(__method__) if savestats
|
5
4
|
output = []
|
6
5
|
if has_access?(__method__, user)
|
7
6
|
help_found = false
|
8
7
|
message = ""
|
9
|
-
if help_command.to_s !=
|
10
|
-
help_command =
|
8
|
+
if help_command.to_s != ""
|
9
|
+
help_command = "" if help_command.to_s.match?(/^\s*expanded\s*$/i) or help_command.to_s.match?(/^\s*extended\s*$/i)
|
11
10
|
expanded = true
|
12
|
-
message_not_expanded =
|
11
|
+
message_not_expanded = ""
|
13
12
|
else
|
14
13
|
expanded = false
|
15
14
|
message_not_expanded = "If you want to see the *expanded* version of *`bot help`* or *`bot rules`*, please call *`bot help expanded`* or *`bot rules expanded`*\n"
|
16
15
|
message_not_expanded += "Also to get specific *expanded* help for a specific command or rule call *`bot help COMMAND`*\n"
|
17
16
|
end
|
18
|
-
expanded = true if Thread.current[:prompt].to_s !=
|
17
|
+
expanded = true if Thread.current[:prompt].to_s != ""
|
19
18
|
if send_to_file
|
20
|
-
|
21
|
-
|
19
|
+
expanded = true
|
20
|
+
message_not_expanded = ""
|
22
21
|
end
|
23
22
|
help_message = get_help(rules_file, dest, user, specific, expanded)
|
24
23
|
commands = []
|
25
24
|
commands_search = []
|
26
25
|
if help_command.to_s != ""
|
27
26
|
help_command.gsub!("?", "\\?") # for open ai commands
|
28
|
-
help_message.gsub(/====+/,
|
27
|
+
help_message.gsub(/====+/, "-" * 30).split(/^\s*-------*$/).each do |h|
|
29
28
|
if strict
|
30
|
-
if h.match?(/`#{help_command}`/i) or h.match?(/^\s*command_id:\s+:#{help_command.gsub(
|
29
|
+
if h.match?(/`#{help_command}`/i) or h.match?(/^\s*command_id:\s+:#{help_command.gsub(" ", "_")}\s*$/)
|
31
30
|
output << h
|
32
31
|
help_found = true
|
33
32
|
commands << h
|
34
33
|
break
|
35
34
|
end
|
36
35
|
else
|
37
|
-
if h.match?(/[`_]#{help_command}/i) or h.match?(/^\s*command_id:\s+:#{help_command.gsub(
|
36
|
+
if h.match?(/[`_]#{help_command}/i) or h.match?(/^\s*command_id:\s+:#{help_command.gsub(" ", "_")}\s*$/)
|
38
37
|
output << h
|
39
38
|
help_found = true
|
40
39
|
commands << h
|
41
40
|
elsif !h.match?(/\A\s*\*/) and !h.match?(/\A\s*=+/) #to avoid general messages for bot help *General commands...*
|
42
41
|
all_found = true
|
43
|
-
help_command.to_s.split(
|
42
|
+
help_command.to_s.split(" ") do |hc|
|
44
43
|
unless hc.match?(/^\s*\z/)
|
45
44
|
if !h.match?(/#{hc}/i)
|
46
45
|
all_found = false
|
@@ -52,7 +51,7 @@ class SlackSmartBot
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
else
|
55
|
-
if Thread.current[:using_channel]!=
|
54
|
+
if Thread.current[:using_channel] != ""
|
56
55
|
message += "*You are using rules from another channel: <##{Thread.current[:using_channel]}>. These are the specific commands for that channel:*"
|
57
56
|
end
|
58
57
|
output << message
|
@@ -65,16 +64,16 @@ class SlackSmartBot
|
|
65
64
|
end
|
66
65
|
end
|
67
66
|
if Thread.current[:typem] == :on_pg or Thread.current[:typem] == :on_pub
|
68
|
-
if @bots_created.size>0
|
69
|
-
txt = "\nThese are the *SmartBots* running on this Slack workspace: *<##{@master_bot_id}>, <##{@bots_created.keys.join(
|
67
|
+
if @bots_created.size > 0
|
68
|
+
txt = "\nThese are the *SmartBots* running on this Slack workspace: *<##{@master_bot_id}>, <##{@bots_created.keys.join(">, <#")}>*\n"
|
70
69
|
txt += "Join one channel and call *`bot rules`* to see specific commands for that channel or *`bot help`* to see all commands for that channel.\n"
|
71
70
|
output << txt
|
72
71
|
end
|
73
72
|
end
|
74
73
|
else
|
75
|
-
if commands.size < 10 and help_command.to_s!=
|
74
|
+
if commands.size < 10 and help_command.to_s != "" and commands_search.size > 0
|
76
75
|
commands_search.shuffle!
|
77
|
-
(10-commands.size).times do |n|
|
76
|
+
(10 - commands.size).times do |n|
|
78
77
|
unless commands_search[n].nil?
|
79
78
|
output << commands_search[n]
|
80
79
|
help_found = true
|
@@ -114,22 +113,28 @@ class SlackSmartBot
|
|
114
113
|
output << message_not_expanded
|
115
114
|
end
|
116
115
|
end
|
117
|
-
if output.join("\n").lines.count > 50 and dest[0]!=
|
116
|
+
if output.join("\n").lines.count > 50 and dest[0] != "D" and !send_to_file
|
118
117
|
dest = :on_thread
|
119
|
-
output.unshift(
|
118
|
+
output.unshift("Since there are many lines returned the results are returned on a thread by default.")
|
120
119
|
end
|
121
120
|
if send_to_file
|
122
121
|
content = output.join("\n\n")
|
123
122
|
content.gsub!(/\*<([^>]*)\|([^>]*)>\*/, '## [\2](\1)')
|
124
123
|
content.gsub!(/^\s*(\*.+\*)\s*$/, '# \1')
|
125
|
-
content.gsub!(/command_id:\s+:/,
|
126
|
-
content = content.gsub("\n", " \n").gsub(/\|[\w\s]*>/i,">").gsub(/^\s*\-\-\-\-\-\-/, "\n------")
|
124
|
+
content.gsub!(/command_id:\s+:/, "### :")
|
125
|
+
content = content.gsub("\n", " \n").gsub(/\|[\w\s]*>/i, ">").gsub(/^\s*\-\-\-\-\-\-/, "\n------")
|
127
126
|
dest == :on_thread ? dest_file = dchannel : dest_file = dest
|
128
|
-
send_file(dest_file, "SmartBot Help", "",
|
127
|
+
send_file(dest_file, "SmartBot Help", "", "smartbot_help.md", "text/markdown", "markdown", content: content)
|
128
|
+
elsif return_output
|
129
|
+
output.each do |h|
|
130
|
+
h.gsub!(/^\s*command_id:\s+:\w+\s*$/, "")
|
131
|
+
h.gsub!(/^\s*>.+$/, "") if help_command.to_s != ""
|
132
|
+
end
|
133
|
+
return output
|
129
134
|
else
|
130
135
|
output.each do |h|
|
131
|
-
msg = h.gsub(/^\s*command_id:\s+:\w+\s*$/,
|
132
|
-
msg.gsub!(/^\s*>.+$/,
|
136
|
+
msg = h.gsub(/^\s*command_id:\s+:\w+\s*$/, "")
|
137
|
+
msg.gsub!(/^\s*>.+$/, "") if help_command.to_s != ""
|
133
138
|
unless msg.match?(/\A\s*\z/)
|
134
139
|
respond msg, dest, unfurl_links: false, unfurl_media: false
|
135
140
|
end
|
@@ -100,7 +100,7 @@ class SlackSmartBot
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
else
|
103
|
-
if typem == :on_dm and channel_id[0]=='D'
|
103
|
+
if typem == :on_dm and !channel_id.nil? and channel_id[0]=='D'
|
104
104
|
respond("There are no announcements#{general_message}", dest) unless type == 'all'
|
105
105
|
else
|
106
106
|
respond("There are no announcements for <##{channel_id}>#{general_message}", dest) unless publish or type == 'all' or (typem==:on_dm and channel_id[0]!='D' and !see_announcements_on_demand)
|
@@ -41,7 +41,7 @@ class SlackSmartBot
|
|
41
41
|
if @vacations.key?(user.team_id_user) and @vacations[user.team_id_user].key?(:periods)
|
42
42
|
@vacations[user.team_id_user].periods.each do |p|
|
43
43
|
#get the last from date
|
44
|
-
if p.from > from[0..9].gsub("-", "/")
|
44
|
+
if p.from > from[0..9].gsub("-", "/") and p.from < Time.now.to_s[0..9].gsub("-", "/")
|
45
45
|
from = p.from
|
46
46
|
from_time_off = true
|
47
47
|
end
|
@@ -127,12 +127,16 @@ class SlackSmartBot
|
|
127
127
|
chatgpt = ai_conn[user.team_id_user].chat_gpt
|
128
128
|
models = ai_models_conn[user.team_id_user].models
|
129
129
|
|
130
|
-
prompt_orig = "Could you please provide a summary of the given conversation, including all key points and supporting details
|
130
|
+
prompt_orig = "Could you please provide a summary of the given conversation, including all key points and supporting details?\n"
|
131
|
+
prompt_orig += "The summary should be comprehensive and accurately reflect the main message and arguments presented in the original text, while also being concise and easy to understand.\n"
|
132
|
+
prompt_orig += "To ensure accuracy, please read the text carefully and pay attention to any nuances or complexities in the language.\n"
|
133
|
+
prompt_orig += "Please also add the most important conversations in the summary.\n"
|
134
|
+
prompt_orig += "Additionally, the summary should avoid any personal biases or interpretations and remain objective and factual throughout.\n"
|
131
135
|
prompt_orig += "If you name an user remember to name it as <@user_id> so it is not replaced by the user name.\n"
|
132
|
-
prompt_orig += "Add the link to the message so it is easy to find it
|
133
|
-
prompt_orig += "For example <https://#{client.team.domain}.slack.com/archives/C111JG4V4DZ/1610231016.950299|message>\n"
|
136
|
+
prompt_orig += "Add the link to the message so it is easy to find it.\n"
|
134
137
|
prompt_orig += "Add also the date of the message for relevant conversations.\n"
|
135
138
|
prompt_orig += "This is the conversation:\n"
|
139
|
+
|
136
140
|
#sort by year/month from older to newer
|
137
141
|
messages = messages.sort_by { |k, v| k }.to_h
|
138
142
|
|
@@ -145,26 +149,36 @@ class SlackSmartBot
|
|
145
149
|
else
|
146
150
|
max_num_tokens = 8000
|
147
151
|
end
|
148
|
-
num_tokens = OpenAI.rough_token_count(prompt_orig + messages.values.flatten.join)
|
152
|
+
#num_tokens = OpenAI.rough_token_count(prompt_orig + messages.values.flatten.join) #jal
|
153
|
+
#enc = Tiktoken.encoding_for_model(chatgpt.smartbot_model)
|
154
|
+
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.
|
155
|
+
num_tokens = enc.encode(prompt_orig + messages.values.flatten.join).length
|
156
|
+
|
149
157
|
respond ":information_source: ChatGPT model: *#{chatgpt.smartbot_model}*. Max tokens: *#{max_num_tokens}*. Characters: #{messages.values.flatten.join.size}. Messages: #{messages.values.flatten.size}. Threads: #{act_threads.size}. Users: #{act_users.size}. Chatgpt tokens: *#{num_tokens}*"
|
150
158
|
|
151
159
|
prompts = []
|
152
160
|
i = 0
|
153
161
|
messages.each do |year_month, msgs|
|
154
162
|
msgs.each do |msg|
|
155
|
-
num_tokens = OpenAI.rough_token_count(prompts[i].to_s + msg)
|
163
|
+
#num_tokens = OpenAI.rough_token_count(prompts[i].to_s + msg) #jal
|
164
|
+
#enc = Tiktoken.encoding_for_model(chatgpt.smartbot_model)
|
165
|
+
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.
|
166
|
+
num_tokens = enc.encode(prompts[i].to_s + msg).length
|
156
167
|
i += 1 if num_tokens > max_num_tokens
|
157
168
|
prompts[i] ||= prompt_orig
|
158
169
|
prompts[i] += "#{msg}\n"
|
159
170
|
end
|
160
171
|
end
|
161
172
|
prompts.each_with_index do |prompt, i|
|
162
|
-
num_tokens = OpenAI.rough_token_count(prompt)
|
173
|
+
#num_tokens = OpenAI.rough_token_count(prompt)
|
174
|
+
#enc = Tiktoken.encoding_for_model(chatgpt.smartbot_model)
|
175
|
+
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.
|
176
|
+
num_tokens = enc.encode(prompt).length
|
163
177
|
respond ":information_source: The total number of chatgpt tokens is more than the max allowed for this chatgpt model. *Part #{i + 1} of #{prompts.size}*.\n" if prompts.size > 1
|
164
178
|
success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(chatgpt.client, chatgpt.smartbot_model, prompt, chatgpt)
|
165
179
|
result_messages = []
|
166
180
|
if success
|
167
|
-
result_messages << "*ChatGPT:*\n#{res}"
|
181
|
+
result_messages << "*ChatGPT:*\n#{transform_to_slack_markdown(res.to_s.strip)}"
|
168
182
|
else
|
169
183
|
result_messages << "*ChatGPT:*\nI'm sorry, I couldn't summarize the conversation. This is the issue: #{res}"
|
170
184
|
end
|
@@ -45,48 +45,48 @@ class SlackSmartBot
|
|
45
45
|
when /^\A*(get\s+)?smartbot\s+readme\s*\z/i, /^\A*readme\s+smartbot\s*\z/i
|
46
46
|
get_smartbot_readme(dest)
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
48
|
+
# help: ----------------------------------------------
|
49
|
+
# help: `for NUMBER times every NUMBER minutes COMMAND`
|
50
|
+
# help: `for NUMBER times every NUMBER seconds COMMAND`
|
51
|
+
# help: `NUMBER times every NUMBER minutes COMMAND`
|
52
|
+
# help: `NUMBER times every NUMBER seconds COMMAND`
|
53
|
+
# help: It will run the command every NUMBER minutes or seconds for NUMBER times.
|
54
|
+
# help: max 24 times. min every 10 seconds. max every 60 minutes.
|
55
|
+
# help: Call `quit loop LOOP_ID` to stop the loop.
|
56
|
+
# help: aliases for minutes: m, minute, minutes
|
57
|
+
# help: aliases for seconds: s, sc, second, seconds
|
58
|
+
# help: Examples:
|
59
|
+
# help: _for 5 times every 1 minute ^ruby puts Time.now_
|
60
|
+
# help: _10 times every 30s !ruby puts Time.now_
|
61
|
+
# help: _24 times every 60m !get sales today_
|
62
|
+
# help: <https://github.com/MarioRuiz/slack-smart-bot#loops|more info>
|
63
|
+
# help: command_id: :create_loop
|
64
|
+
# help:
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
66
|
+
# help: ----------------------------------------------
|
67
|
+
# help: `quit loop LOOP_ID`
|
68
|
+
# help: It will stop the loop with the id LOOP_ID.
|
69
|
+
# help: Only the user who created the loop or an admin can stop it.
|
70
|
+
# help: aliases for loop: iterator, iteration
|
71
|
+
# help: aliases for quit: stop, exit, kill
|
72
|
+
# help: Examples:
|
73
|
+
# help: _quit loop 1_
|
74
|
+
# help: _stop iterator 12_
|
75
|
+
# help: <https://github.com/MarioRuiz/slack-smart-bot#loops|more info>
|
76
|
+
# help: command_id: :quit_loop
|
77
|
+
# help:
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
79
|
+
# help: ----------------------------------------------
|
80
|
+
# help: `Hi Bot`
|
81
|
+
# help: `Hi Smart`
|
82
|
+
# help: `Hello Bot` `Hola Bot` `Hallo Bot` `What's up Bot` `Hey Bot` `Hæ Bot`
|
83
|
+
# help: `Hello THE_NAME_OF_THE_BOT`
|
84
|
+
# help: Bot starts listening to you if you are on a Bot channel
|
85
|
+
# help: After that if you want to avoid a single message to be treated by the smart bot, start the message by -
|
86
|
+
# help: Also apart of Hello you can use _Hallo, Hi, Hola, What's up, Hey, Hæ_
|
87
|
+
# help: <https://github.com/MarioRuiz/slack-smart-bot#how-to-access-the-smart-bot|more info>
|
88
|
+
# help: command_id: :hi_bot
|
89
|
+
# help:
|
90
90
|
when /\A\s*(Hello|Hallo|Hi|Hola|What's\sup|Hey|Hæ)\s+(#{@salutations.join("|")})\s*$/i
|
91
91
|
hi_bot(user, dest, user.name, display_name)
|
92
92
|
|
@@ -122,7 +122,7 @@ class SlackSmartBot
|
|
122
122
|
# help: command_id: :poster
|
123
123
|
# help:
|
124
124
|
when /\A()poster\s+(\d+m\s+)?(:[^:]+:)\s+(:[^:]+:)(.+)\s*\z/i, /\A()poster\s+(\d+m\s+)?(:.+:)\s+()(.+)\s*\z/i, /\A()poster\s+(\d+m\s+)?()()(.+)\s*\z/i,
|
125
|
-
|
125
|
+
/\A(p)poster\s+()(:[^:]+:)\s+(:[^:]+:)(.+)\s*\z/i, /\A(p)poster\s+()(:.+:)\s+()(.+)\s*\z/i, /\A(p)poster\s+()()()(.+)\s*\z/i
|
126
126
|
permanent = $1.to_s != ""
|
127
127
|
minutes = $2.to_s
|
128
128
|
emoticon_text = $3
|
@@ -957,6 +957,15 @@ class SlackSmartBot
|
|
957
957
|
# help: If ?? is used, it will start from zero the temporary session. If not all the previous prompts from the session will be used to generate the response.
|
958
958
|
# help: You can share a message and use it as input for the supplied PROMPT.
|
959
959
|
# help: If you include in the prompt !URL then it will download and use the content of the URL as input for the prompt.
|
960
|
+
# help: If the URL is a Google Drive link, it will download the content of the file.
|
961
|
+
# help: If the URL is a PDF, DOCX or text file (txt, json, yaml...) SmartBot will extract the content of the file and use it as input for the prompt.
|
962
|
+
# help: Add static content to your session by using `add static content URL1 URL99`. The content will be downloaded and added to your session only once.
|
963
|
+
# help: Add live content to your session by using `add live content URL1 URL99`. The content will be downloaded and added to your session every time you send a new prompt.
|
964
|
+
# help: Add messages from a channel to your session by using `add history #CHANNEL_NAME`.
|
965
|
+
# help: You can add authorizations on a specific ChatGPT session: `add authorization HOST HEADER VALUE`, for example: `add authorization api.example.com Authorization Bearer 123456`.
|
966
|
+
# help: You can attach any image to the message and it will be used as input for the prompt.
|
967
|
+
# help: If you want to delete the last ChatGPT response and send again last prompt, you can use `resend prompt`.
|
968
|
+
# help: You can set the context of your ChatGPT session: `set context CONTEXT`. Example: `set context You are a funny comedian who tells dad jokes. The output should be in JSON format.`
|
960
969
|
# help: MODEL_NAME can be a substring of the model name, SmartBot will search the model name that contains the substring supplied.
|
961
970
|
# help: When "DESCRIPTION" is used it will be used as a description for the session.
|
962
971
|
# help: If a previous DESCRIPTION for the session exists it will be replaced.
|
@@ -975,6 +984,14 @@ class SlackSmartBot
|
|
975
984
|
# help: command_id: :open_ai_chat
|
976
985
|
# help: command_id: :open_ai_chat_add_collaborator
|
977
986
|
# help: command_id: :open_ai_chat_use_model
|
987
|
+
# help: command_id: :open_ai_chat_add_live_content
|
988
|
+
# help: command_id: :open_ai_chat_add_static_content
|
989
|
+
# help: command_id: :open_ai_chat_add_authorization
|
990
|
+
# help: command_id: :open_ai_chat_resend_prompt
|
991
|
+
# help: command_id: :open_ai_chat_set_context
|
992
|
+
# help: command_id: :open_ai_chat_delete_live_content
|
993
|
+
# help: command_id: :open_ai_chat_delete_static_content
|
994
|
+
# help: command_id: :open_ai_chat_delete_authorization
|
978
995
|
# help:
|
979
996
|
|
980
997
|
# help: ----------------------------------------------
|
@@ -997,6 +1014,14 @@ class SlackSmartBot
|
|
997
1014
|
# help: command_id: :open_ai_chat_delete_session
|
998
1015
|
# help:
|
999
1016
|
|
1017
|
+
# help: ----------------------------------------------
|
1018
|
+
# help: `chatGPT clean SESSION_NAME`
|
1019
|
+
# help: OpenAI: SmartBot will delete all the prompts from the ChatGPT session indicated.
|
1020
|
+
# help: Examples:
|
1021
|
+
# help: _chatgpt clean SpanishTeacher_
|
1022
|
+
# help: command_id: :open_ai_chat_clean_session
|
1023
|
+
# help:
|
1024
|
+
|
1000
1025
|
# help: ----------------------------------------------
|
1001
1026
|
# help: `chatGPT share SESSION_NAME`
|
1002
1027
|
# help: `chatGPT share SESSION_NAME #CHANNEL`
|
@@ -1040,15 +1065,23 @@ class SlackSmartBot
|
|
1040
1065
|
# help: `chatGPT copy temporary session NEW_SESSION_NAME`
|
1041
1066
|
# help: `chatGPT use USER_NAME SESSION_NAME`
|
1042
1067
|
# help: `chatGPT use USER_NAME SESSION_NAME NEW_SESSION_NAME`
|
1068
|
+
# help: `?? use SESSION_NAME`
|
1069
|
+
# help: `?? use SESSION_NAME NEW_PROMPT`
|
1070
|
+
# help: `?? use USER_NAME SESSION_NAME`
|
1071
|
+
# help: `?? use USER_NAME SESSION_NAME NEW_PROMPT`
|
1043
1072
|
# help: OpenAI: SmartBot will copy the ChatGPT session indicated.
|
1044
1073
|
# help: If NEW_SESSION_NAME is supplied it will be used as the name for the new session.
|
1045
1074
|
# help: If USER_NAME is supplied it will copy the session from that user on shared sessions.
|
1046
1075
|
# help: In case no NEW_SESSION_NAME is supplied it will use the same name as the original session plus a number.
|
1076
|
+
# help: If ?? is used it will start a new temporary session with the prompts from the session indicated.
|
1047
1077
|
# help: Examples:
|
1048
1078
|
# help: _chatgpt copy SpanishTeacher_
|
1049
1079
|
# help: _chatgpt copy SpanishTeacher spanish_lessons_
|
1050
1080
|
# help: _chatgpt use peterw SpanishTeacher_
|
1051
1081
|
# help: _chatgpt use susanssd dataAnalysis DataSales_
|
1082
|
+
# help: _?? use peterw SpanishTeacher_
|
1083
|
+
# help: _?? use stats_sales can you project the sales for next month?_
|
1084
|
+
# help: _?? use susanssd dataAnalysis How much is the total?_
|
1052
1085
|
# help: command_id: :open_ai_chat_copy_session
|
1053
1086
|
# help: command_id: :open_ai_chat_copy_session_from_user
|
1054
1087
|
# help:
|
@@ -1115,22 +1148,85 @@ class SlackSmartBot
|
|
1115
1148
|
end
|
1116
1149
|
open_ai_chat_copy_session(user_team_id, user_name, session_name, new_session_name)
|
1117
1150
|
|
1151
|
+
#?? use model
|
1152
|
+
when /\A\s*(\?\?)()\s+use\s+model\s+([\w\-0-9\.]+)()()\s*\z/im,
|
1153
|
+
/\A\s*\?\s+(use)\s+model\s+()([\w\-0-9\.]+)()()\s*\z/im
|
1154
|
+
model = $3.to_s
|
1155
|
+
if $1.to_s == "??"
|
1156
|
+
open_ai_chat("", true, :temporary, model: model)
|
1157
|
+
else
|
1158
|
+
open_ai_chat_use_model(model)
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
#chatgpt use session for temporary session
|
1162
|
+
when /\A\s*\?\?\s*use\s+(session\s+)?([\w\-0-9]+)()()\s*\z/im, #use SESSION_NAME
|
1163
|
+
/\A\s*\?\?\s*use\s+(session\s+)?([\w\-0-9]+)\s+([\w\-0-9]+)()\s*\z/im, #use USER_NAME SESSION_NAME
|
1164
|
+
/\A\s*\?\?\s*use\s+(session\s+)?([\w\-0-9]+)\s+([\w\-0-9]+)\s+(.+)\s*\z/im, #use USER_NAME SESSION_NAME NEW_PROMPT
|
1165
|
+
/\A\s*\?\?\s*use\s+(session\s+)?([\w\-0-9]+)\s+(.+)()\s*\z/im #use SESSION_NAME NEW_PROMPT
|
1166
|
+
user_name = $2.to_s
|
1167
|
+
session_name = $3.to_s
|
1168
|
+
new_prompt = $4.to_s
|
1169
|
+
session_found = false
|
1170
|
+
more_than_one = false
|
1171
|
+
|
1172
|
+
if !@open_ai.keys.any? { |team_id_user| team_id_user.match?(/\A[A-Z0-9]{7,11}_#{user_name}$/) }
|
1173
|
+
session_name += " " + new_prompt
|
1174
|
+
new_prompt = ""
|
1175
|
+
end
|
1176
|
+
short_command = false
|
1177
|
+
if new_prompt == "" #use SESSION_NAME or use SESSION_NAME PROMPT
|
1178
|
+
short_command = true
|
1179
|
+
get_openai_sessions()
|
1180
|
+
new_prompt = session_name
|
1181
|
+
session_name = user_name
|
1182
|
+
@open_ai.keys.each do |team_id_user|
|
1183
|
+
if @open_ai[team_id_user][:chat_gpt].key?(:sessions) and
|
1184
|
+
@open_ai[team_id_user][:chat_gpt][:sessions].key?(session_name)
|
1185
|
+
if @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:shared].size > 0
|
1186
|
+
members_shared = []
|
1187
|
+
@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:shared].each do |shared|
|
1188
|
+
members_shared += get_channel_members(shared)
|
1189
|
+
end
|
1190
|
+
members_shared.uniq!
|
1191
|
+
else
|
1192
|
+
members_shared = []
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
if team_id_user == user.team_id_user or
|
1196
|
+
@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:public] or
|
1197
|
+
@open_ai[team_id_user][:chat_gpt][:sessions][session_name][:shared].include?(dest) or
|
1198
|
+
members_shared.include?(user.id)
|
1199
|
+
user_name = @open_ai[team_id_user][:chat_gpt][:sessions][session_name][:user_creator]
|
1200
|
+
more_than_one = true if session_found
|
1201
|
+
session_found = true
|
1202
|
+
end
|
1203
|
+
break if more_than_one
|
1204
|
+
end
|
1205
|
+
end
|
1206
|
+
end
|
1207
|
+
if more_than_one
|
1208
|
+
respond "There is more than one session with that name. Please specify the user name."
|
1209
|
+
save_stats(:open_ai_chat_copy_session_from_user)
|
1210
|
+
elsif !session_found and short_command
|
1211
|
+
respond ":exclamation: Session not found.\nCall `chatGPT sessions` to see the list of your sessions\n`chatGPT public sessions` to see the public sessions.\n`chatGPT shared sessions` to see the shared sessions."
|
1212
|
+
else
|
1213
|
+
success = open_ai_chat_copy_session("", user_name, session_name, "", temporary_session: true)
|
1214
|
+
open_ai_chat(new_prompt, false, :temporary) if new_prompt != "" and success
|
1215
|
+
end
|
1216
|
+
|
1118
1217
|
# chatgpt chat
|
1119
1218
|
when /\A\s*\?\s+(add\s+collaborator)\s+<@(\w+)>()()()\s*\z/im,
|
1120
|
-
/\A\s*\?\s+(use)\s+model\s+()([\w\-0-9\.]+)()()\s*\z/im,
|
1121
|
-
/\A\s*(\?\?)()\s+use\s+model\s+([\w\-0-9\.]+)()()\s*\z/im,
|
1122
1219
|
/\A\s*\?\?(s|c)\s+([\w\-0-9]+)()()()\s*\z/im,
|
1123
|
-
/\A\s*chatgpt\s+(start|continue|load)\s+([\w\-0-9]+)()()()\s*\z/im,
|
1220
|
+
/\A\s*chatgpt\s+(start|continue|load|clean)\s+([\w\-0-9]+)()()()\s*\z/im,
|
1124
1221
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)()()()\s*\z/im, #chatgpt session_name
|
1125
1222
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)()\s+>([\w\-0-9]+)()\s*\z/im, #chatgpt session_name >tag_name
|
1126
1223
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)\s+([\w\-0-9\.]+)()()\s*\z/im, #chatgpt session_name model_name
|
1127
1224
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)\s+([\w\-0-9\.]+)\s+>([\w\-0-9\.]+)()\s*\z/im, #chatgpt session_name model_name >tag_name
|
1128
1225
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)()\s+>([\w\-0-9]+)\s+(".+")\s*\z/im, #chatgpt session_name >tag_name "description"
|
1129
1226
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)()()\s+(".+")\s*\z/im, #chatgpt session_name "description"
|
1130
|
-
/\A\s*(chatgpt)\s+([\w\-0-9]+)()\s+>([\w\-0-9]+)\s+(".+")\s*\z/im, #chatgpt session_name >tag_name "description"
|
1131
1227
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)\s+([\w\-0-9\.]+)()\s+(".+")\s*\z/im, #chatgpt session_name model_name "description"
|
1132
1228
|
/\A\s*(chatgpt)\s+([\w\-0-9]+)\s+([\w\-0-9\.]+)\s+>([\w\-0-9]+)\s+(".+")\s*\z/im, #chatgpt session_name model_name >tag_name "description"
|
1133
|
-
/\A\s*(\?\?)\s*()()()()\z/im, /\A\s*(\?\?)\s*(.+)()\s*()()\z/im, /\A\s*()\?\s
|
1229
|
+
/\A\s*(\?\?)\s*()()()()\z/im, /\A\s*(\?\?)\s*(.+)()\s*()()\z/im, /\A\s*()(\?\s*.+)()\s*()()\z/im
|
1134
1230
|
type = $1.to_s.downcase
|
1135
1231
|
text = $2.to_s
|
1136
1232
|
model = $3.to_s
|
@@ -1142,21 +1238,26 @@ class SlackSmartBot
|
|
1142
1238
|
type = :start
|
1143
1239
|
elsif type == "c" or type == "continue" or type == "load"
|
1144
1240
|
type = :continue
|
1241
|
+
elsif type == "clean"
|
1242
|
+
type = :clean
|
1243
|
+
delete_history = true
|
1145
1244
|
elsif type.match?(/add\s+collaborator/)
|
1146
1245
|
type = :add_collaborator
|
1147
|
-
elsif type == "use"
|
1148
|
-
type = :use_model
|
1149
1246
|
else
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
text =
|
1247
|
+
if text.match?(/\A\?[^\?]/im) and !text.match?(/\A\?\s+\?\?/im)
|
1248
|
+
type = :continue_session
|
1249
|
+
#remove first ? from the prompt
|
1250
|
+
text = text[1..-1]
|
1251
|
+
else
|
1252
|
+
type = :temporary
|
1253
|
+
if text == "??" or text.match?(/\A\?\s+\?\?/)
|
1254
|
+
delete_history = true
|
1255
|
+
text = ""
|
1256
|
+
end
|
1154
1257
|
end
|
1155
1258
|
end
|
1156
1259
|
if type == :add_collaborator
|
1157
1260
|
open_ai_chat_add_collaborator(text)
|
1158
|
-
elsif type == :use_model
|
1159
|
-
open_ai_chat_use_model(model)
|
1160
1261
|
else
|
1161
1262
|
open_ai_chat(text, delete_history, type, model: model, tag: tag, description: description, files: files)
|
1162
1263
|
end
|
@@ -1231,7 +1332,7 @@ class SlackSmartBot
|
|
1231
1332
|
channel = dest if channel == ""
|
1232
1333
|
summarize(user, dest, channel, from, thread_ts)
|
1233
1334
|
|
1234
|
-
|
1335
|
+
# help: >*<|OTHER GENERAL COMMANDS>*
|
1235
1336
|
|
1236
1337
|
else
|
1237
1338
|
return false
|
@@ -83,7 +83,7 @@ class SlackSmartBot
|
|
83
83
|
get_channels_name_and_id() unless @channels_id.keys.include?(channel_members)
|
84
84
|
|
85
85
|
tm = get_channel_members(channel_members)
|
86
|
-
if tm.nil?
|
86
|
+
if tm.nil? or tm.size == 0
|
87
87
|
message << ":exclamation: Add the Smart Bot to *<##{channel_members}>* channel first."
|
88
88
|
wrong = true
|
89
89
|
else
|
@@ -93,7 +93,6 @@ class SlackSmartBot
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
97
96
|
if header.size > 0
|
98
97
|
headers = ["date", "bot_channel", "bot_channel_id", "dest_channel", "dest_channel_id", "type_message", "user_name", "user_id", "text", "command", "files", "time_zone", "job_title", "team_id"]
|
99
98
|
header.each do |h|
|
@@ -195,8 +194,9 @@ class SlackSmartBot
|
|
195
194
|
Dir["#{config.stats_path}.*.log"].sort.each do |file|
|
196
195
|
if file >= "#{config.stats_path}.#{from_file}.log" and file <= "#{config.stats_path}.#{to_file}.log"
|
197
196
|
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
|
198
|
-
|
199
|
-
|
197
|
+
clean_user_name = row[:user_name].gsub('routine/','')
|
198
|
+
if (include_channel_members and members_list.include?(clean_user_name)) or
|
199
|
+
(exclude_channel_members and !members_list.include?(clean_user_name)) or
|
200
200
|
(!include_channel_members and !exclude_channel_members)
|
201
201
|
row[:date] = row[:date].to_s
|
202
202
|
row[:team_id] = config.team_id if row[:team_id].to_s == ''
|
@@ -385,9 +385,10 @@ class SlackSmartBot
|
|
385
385
|
|
386
386
|
#print users by team
|
387
387
|
if users_by_team.size > 0
|
388
|
+
total_users = rows.user_id.uniq.size
|
388
389
|
message << "*Users by Space*"
|
389
390
|
users_by_team.each do |team_name, users|
|
390
|
-
message << "\t#{team_name}: #{users.size} (#{(users.size.to_f * 100 /
|
391
|
+
message << "\t#{team_name}: #{users.size} (#{(users.size.to_f * 100 / total_users).round(2)}%)"
|
391
392
|
end
|
392
393
|
end
|
393
394
|
|
@@ -404,8 +405,8 @@ class SlackSmartBot
|
|
404
405
|
if user == ""
|
405
406
|
users = rows.user_id.uniq.sort
|
406
407
|
if rows[0].key?(:time_zone) #then save_stats is saving the time zone already
|
407
|
-
rows.time_zone.
|
408
|
-
unless time_zone == ""
|
408
|
+
rows.time_zone.each_with_index do |time_zone, idx|
|
409
|
+
unless time_zone == "" or rows.user_name[idx].match?(/^routine\//)
|
409
410
|
tzone_users[time_zone] ||= 0
|
410
411
|
tzone_users[time_zone] += 1
|
411
412
|
end
|
@@ -413,13 +414,13 @@ class SlackSmartBot
|
|
413
414
|
else
|
414
415
|
rows.user_id.each_with_index do |usr, i|
|
415
416
|
if rows[i].values.size >= 12 #then save_stats is saving the time zone already but not all the data
|
416
|
-
unless rows[i].values[11] == ""
|
417
|
+
unless rows[i].values[11] == "" or rows[i].values[11].match?(/^routine\//)
|
417
418
|
tzone_users[rows[i].values[11]] ||= 0
|
418
419
|
tzone_users[rows[i].values[11]] += 1
|
419
420
|
end
|
420
421
|
else
|
421
422
|
user_info = find_user(usr)
|
422
|
-
unless user_info.nil? or user_info.is_app_user or user_info.is_bot
|
423
|
+
unless user_info.nil? or user_info.is_app_user or user_info.is_bot or user_info.tz_label.to_s == "" or rows.user_name[i].match?(/^routine\//)
|
423
424
|
tzone_users[user_info.tz_label] ||= 0
|
424
425
|
tzone_users[user_info.tz_label] += 1
|
425
426
|
end
|
@@ -428,7 +429,7 @@ class SlackSmartBot
|
|
428
429
|
end
|
429
430
|
if rows[0].key?(:job_title) #then save_stats is saving the job title already
|
430
431
|
rows.job_title.each_with_index do |job_title, idx|
|
431
|
-
unless job_title.to_s == ""
|
432
|
+
unless job_title.to_s == "" or rows.user_name[idx].match?(/^routine\//)
|
432
433
|
unless job_title_users.key?(job_title)
|
433
434
|
job_title = job_title.to_s.split.map { |x| x[0].upcase + x[1..-1] }.join(" ")
|
434
435
|
job_title_users[job_title] ||= 0
|
@@ -543,10 +544,11 @@ class SlackSmartBot
|
|
543
544
|
message << "*Num Users by Job Title*"
|
544
545
|
end
|
545
546
|
i = 0
|
547
|
+
users_size_without_routines = users.delete_if { |u| u.include?("routine/") }.size
|
546
548
|
users_by_job_title.sort_by { |k, v| -v.size }.each do |jtitle, usersj|
|
547
549
|
i += 1
|
548
550
|
if i <= 10
|
549
|
-
message << "\t#{jtitle}: #{usersj.size} (#{(usersj.size.to_f * 100 /
|
551
|
+
message << "\t#{jtitle}: #{usersj.size} (#{(usersj.size.to_f * 100 / users_size_without_routines).round(2)}%)"
|
550
552
|
end
|
551
553
|
end
|
552
554
|
end
|