slack-smart-bot 1.13.2 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +100 -4
- data/lib/slack/smart-bot/ai/open_ai/connect.rb +61 -0
- data/lib/slack/smart-bot/ai/open_ai/models.rb +21 -0
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +24 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +23 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +18 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +22 -0
- data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +21 -0
- data/lib/slack/smart-bot/ai.rb +8 -0
- data/lib/slack/smart-bot/comm/get_channel_members.rb +15 -13
- data/lib/slack/smart-bot/comm/get_channels.rb +31 -29
- data/lib/slack/smart-bot/comm/respond_thread.rb +2 -2
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +40 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +66 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +65 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +37 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +84 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +51 -0
- data/lib/slack/smart-bot/commands/general/bot_help.rb +1 -0
- data/lib/slack/smart-bot/commands/general/personal_settings.rb +38 -0
- data/lib/slack/smart-bot/commands/general/poster.rb +107 -104
- data/lib/slack/smart-bot/commands/general/public_holidays.rb +116 -114
- data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +6 -2
- data/lib/slack/smart-bot/commands/general/teams/add_team.rb +87 -0
- data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +69 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +136 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +37 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +83 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +97 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +304 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +66 -0
- data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +104 -0
- data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +236 -0
- data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +183 -0
- data/lib/slack/smart-bot/commands/general/teams/update_team.rb +137 -0
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +905 -741
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +379 -353
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +6 -107
- data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +233 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +17 -4
- data/lib/slack/smart-bot/commands.rb +26 -10
- data/lib/slack/smart-bot/process.rb +14 -3
- data/lib/slack/smart-bot/process_first.rb +36 -2
- data/lib/slack/smart-bot/treat_message.rb +28 -0
- data/lib/slack/smart-bot/utils/check_vacations.rb +1 -0
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +1 -1
- data/lib/slack/smart-bot/utils/display_calendar.rb +17 -10
- data/lib/slack/smart-bot/utils/encryption/decrypt.rb +23 -0
- data/lib/slack/smart-bot/utils/encryption/encrypt.rb +27 -0
- data/lib/slack/smart-bot/utils/{encryption_get_key_iv.rb → encryption/encryption_get_key_iv.rb} +12 -8
- data/lib/slack/smart-bot/utils/get_help.rb +3 -1
- data/lib/slack/smart-bot/utils/get_personal_settings.rb +14 -0
- data/lib/slack/smart-bot/utils/get_teams.rb +2 -2
- data/lib/slack/smart-bot/utils/get_vacations.rb +2 -2
- data/lib/slack/smart-bot/utils/save_stats.rb +3 -1
- data/lib/slack/smart-bot/utils/update_personal_settings.rb +18 -0
- data/lib/slack/smart-bot/utils/update_teams.rb +1 -1
- data/lib/slack/smart-bot/utils/update_vacations.rb +1 -1
- data/lib/slack/smart-bot/utils.rb +5 -3
- data/lib/slack-smart-bot.rb +12 -0
- data/whats_new.txt +13 -14
- metadata +63 -15
- data/lib/slack/smart-bot/commands/general/add_memo_team.rb +0 -117
- data/lib/slack/smart-bot/commands/general/add_team.rb +0 -81
- data/lib/slack/smart-bot/commands/general/delete_memo_team.rb +0 -69
- data/lib/slack/smart-bot/commands/general/delete_team.rb +0 -55
- data/lib/slack/smart-bot/commands/general/ping_team.rb +0 -100
- data/lib/slack/smart-bot/commands/general/see_memos_team.rb +0 -202
- data/lib/slack/smart-bot/commands/general/see_teams.rb +0 -230
- data/lib/slack/smart-bot/commands/general/see_vacations_team.rb +0 -136
- data/lib/slack/smart-bot/commands/general/set_memo_status.rb +0 -58
- data/lib/slack/smart-bot/commands/general/update_team.rb +0 -131
- data/lib/slack/smart-bot/utils/decrypt.rb +0 -15
- data/lib/slack/smart-bot/utils/encrypt.rb +0 -15
@@ -23,6 +23,8 @@ class SlackSmartBot
|
|
23
23
|
# help: By default it will be automatically loaded the gems: string_pattern, nice_hash and nice_http
|
24
24
|
# help: To pre-execute some ruby when starting the session add the code to .smart-bot-repl file on the project root folder defined on project_folder
|
25
25
|
# help: If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
26
|
+
# help: To see the code of a method: _code TheModuleOrClass.my_method_
|
27
|
+
# help: To see the documentation of a method: _doc TheModuleOrClass.my_method_
|
26
28
|
# help: You can supply the Environmental Variables you need for the Session
|
27
29
|
# help: You can add collaborators by sending _add collaborator @USER_ to the session.
|
28
30
|
# help: Examples:
|
@@ -91,118 +93,14 @@ class SlackSmartBot
|
|
91
93
|
end
|
92
94
|
@ts_repl ||= {}
|
93
95
|
@ts_repl[session_name] = ""
|
96
|
+
process_to_run = repl_client(from, session_name, type, serialt, env_vars)
|
94
97
|
|
95
|
-
message = "Session name: *#{session_name}*
|
96
|
-
From now on I will execute all you write as a Ruby command and I will keep the session open until you send `quit` or `bye` or `exit`.
|
97
|
-
In case you need someone to help you with the session you can add collaborators by sending `add collaborator @USER` to the session.
|
98
|
-
I will respond with the result so it is not necessary you send `print`, `puts`, `p` or `pp` unless you want it as the output when calling `run repl`.
|
99
|
-
Use `p` to print a message raw, exacly like it is returned.
|
100
|
-
If you want to avoid a message to be treated by me, start the message with '-'.
|
101
|
-
After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
102
|
-
If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
103
|
-
You can supply the Environmental Variables you need for the Session
|
104
|
-
Example:
|
105
|
-
_repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
106
|
-
"
|
107
|
-
respond message, dest
|
108
|
-
|
109
|
-
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "", mode: "a+")
|
110
|
-
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.output", "", mode: "a+")
|
111
|
-
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.run", "", mode: "a+")
|
112
|
-
|
113
|
-
if type != :private_clean and type != :public_clean
|
114
|
-
pre_execute = '
|
115
|
-
if File.exist?(\"./.smart-bot-repl\")
|
116
|
-
begin
|
117
|
-
eval(File.read(\"./.smart-bot-repl\"), bindme' + serialt + ")
|
118
|
-
rescue Exception => resp_repl
|
119
|
-
end
|
120
|
-
end
|
121
|
-
"
|
122
|
-
else
|
123
|
-
pre_execute = ""
|
124
|
-
end
|
125
|
-
|
126
|
-
process_to_run = "
|
127
|
-
" + env_vars.join("\n") + '
|
128
|
-
require \"amazing_print\"
|
129
|
-
require \"stringio\"
|
130
|
-
bindme' + serialt + ' = binding
|
131
|
-
eval(\"require \'nice_http\'\" , bindme' + serialt + ')
|
132
|
-
def ls(obj)
|
133
|
-
(obj.methods - Object.methods)
|
134
|
-
end
|
135
|
-
file_run_path = \"' + +File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.rb\"
|
136
|
-
file_input_repl = File.open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.input\", \"r\")
|
137
|
-
' + pre_execute + '
|
138
|
-
while true do
|
139
|
-
sleep 0.2
|
140
|
-
code_to_run_repl = file_input_repl.read
|
141
|
-
if code_to_run_repl.to_s!=\"\"
|
142
|
-
add_to_run_repl = true
|
143
|
-
if code_to_run_repl.to_s.match?(/^quit$/i) or
|
144
|
-
code_to_run_repl.to_s.match?(/^exit$/i) or
|
145
|
-
code_to_run_repl.to_s.match?(/^bye bot$/i) or
|
146
|
-
code_to_run_repl.to_s.match?(/^bye$/i)
|
147
|
-
exit
|
148
|
-
else
|
149
|
-
if code_to_run_repl.match?(/^\s*ls\s+(.+)/)
|
150
|
-
add_to_run_repl = false
|
151
|
-
end
|
152
|
-
error = false
|
153
|
-
begin
|
154
|
-
begin
|
155
|
-
original_stdout = $stdout
|
156
|
-
$stdout = StringIO.new
|
157
|
-
resp_repl = eval(code_to_run_repl, bindme' + serialt + ')
|
158
|
-
stdout_repl = $stdout.string
|
159
|
-
ensure
|
160
|
-
$stdout = original_stdout
|
161
|
-
end
|
162
|
-
rescue Exception => resp_repl
|
163
|
-
error = true
|
164
|
-
end
|
165
|
-
if error
|
166
|
-
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
167
|
-
f.puts \"\`\`\`\n#{resp_repl.to_s.gsub(/^.+' + session_name + '\.rb:\d+:/,\"\")}\`\`\`\"
|
168
|
-
}
|
169
|
-
else
|
170
|
-
if code_to_run_repl.match?(/^\s*p\s+/i)
|
171
|
-
resp_repl = stdout_repl unless stdout_repl.to_s == \'\'
|
172
|
-
if stdout_repl.to_s == \'\'
|
173
|
-
resp_repl = resp_repl.inspect
|
174
|
-
else
|
175
|
-
resp_repl = stdout_repl
|
176
|
-
end
|
177
|
-
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
178
|
-
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
179
|
-
}
|
180
|
-
else
|
181
|
-
if stdout_repl.to_s == \'\'
|
182
|
-
resp_repl = resp_repl.ai
|
183
|
-
else
|
184
|
-
resp_repl = stdout_repl
|
185
|
-
end
|
186
|
-
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
187
|
-
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
188
|
-
}
|
189
|
-
end
|
190
|
-
unless !add_to_run_repl
|
191
|
-
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.run\", \"a+\") {|f|
|
192
|
-
f.puts code_to_run_repl
|
193
|
-
}
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
'
|
200
98
|
unless rules_file.empty? # to get the project_folder
|
201
99
|
begin
|
202
100
|
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file)
|
203
101
|
end
|
204
102
|
end
|
205
|
-
|
103
|
+
|
206
104
|
file_run_path = "./tmp/repl/#{@channel_id}/#{session_name}.rb"
|
207
105
|
if defined?(project_folder)
|
208
106
|
Dir.mkdir("#{project_folder}/tmp/") unless Dir.exist?("#{project_folder}/tmp/")
|
@@ -257,7 +155,8 @@ class SlackSmartBot
|
|
257
155
|
unreact(:running, @ts_repl[@repl_sessions[from].name])
|
258
156
|
@ts_repl[@repl_sessions[from].name] = ""
|
259
157
|
end
|
260
|
-
if resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500
|
158
|
+
if (resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500) or
|
159
|
+
resp_repl.match?(/^\s*[_\*]*`\w+`/im)
|
261
160
|
respond resp_repl, dest
|
262
161
|
else
|
263
162
|
resp_repl.gsub!(/^\s*```/, "")
|
@@ -0,0 +1,233 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
def repl_client(from, session_name, type, serialt, env_vars)
|
3
|
+
message = "Session name: *#{session_name}*
|
4
|
+
From now on I will execute all you write as a Ruby command and I will keep the session open until you send `quit` or `bye` or `exit`.
|
5
|
+
In case you need someone to help you with the session you can add collaborators by sending `add collaborator @USER` to the session.
|
6
|
+
I will respond with the result so it is not necessary you send `print`, `puts`, `p` or `pp` unless you want it as the output when calling `run repl`.
|
7
|
+
Use `p` to print a message raw, exacly like it is returned.
|
8
|
+
If you want to avoid a message to be treated by me, start the message with '-'.
|
9
|
+
After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
10
|
+
If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
11
|
+
To see the code of a method: _code TheModuleOrClass.my_method_. To see the documentation of a method: _doc TheModuleOrClass.my_method_
|
12
|
+
You can supply the Environmental Variables you need for the Session
|
13
|
+
Example:
|
14
|
+
_repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
15
|
+
"
|
16
|
+
respond message
|
17
|
+
|
18
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "", mode: "a+")
|
19
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.output", "", mode: "a+")
|
20
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.run", "", mode: "a+")
|
21
|
+
|
22
|
+
if type != :private_clean and type != :public_clean
|
23
|
+
pre_execute = '
|
24
|
+
if File.exist?(\"./.smart-bot-repl\")
|
25
|
+
begin
|
26
|
+
eval(File.read(\"./.smart-bot-repl\"), bindme' + serialt + ")
|
27
|
+
rescue Exception => resp_repl
|
28
|
+
end
|
29
|
+
end
|
30
|
+
"
|
31
|
+
else
|
32
|
+
pre_execute = ""
|
33
|
+
end
|
34
|
+
|
35
|
+
process_to_run = "
|
36
|
+
" + env_vars.join("\n") + '
|
37
|
+
require \"amazing_print\"
|
38
|
+
require \"stringio\"
|
39
|
+
require \"method_source\"
|
40
|
+
bindme' + serialt + ' = binding
|
41
|
+
eval(\"require \'nice_http\'\" , bindme' + serialt + ')
|
42
|
+
def get_met_params(obj, m=nil)
|
43
|
+
result = ""
|
44
|
+
if m.nil?
|
45
|
+
met = obj
|
46
|
+
else
|
47
|
+
met = obj.method(m)
|
48
|
+
end
|
49
|
+
met.source.split("\n").each { |line|
|
50
|
+
line.gsub!("def", "")
|
51
|
+
line.gsub!("self.", "")
|
52
|
+
line.strip!
|
53
|
+
line.gsub!(/\A(\w+)\(/, \'*`\1`* (\')
|
54
|
+
line.gsub!(/\A(\w+)$/, \'*`\1`*\')
|
55
|
+
if line.strip[-1] == ")" or (result.empty? and !line.include?("("))
|
56
|
+
line.gsub!(/\A(\w+)\s/, \'*`\1`* \') if !line.include?("(")
|
57
|
+
result << "#{line}"
|
58
|
+
result << " ..." if !line.include?("(") and !line.include?(")")
|
59
|
+
result << "\n"
|
60
|
+
break
|
61
|
+
else
|
62
|
+
result << "#{line}\n"
|
63
|
+
end
|
64
|
+
}
|
65
|
+
result
|
66
|
+
end
|
67
|
+
def ls(obj)
|
68
|
+
result = ""
|
69
|
+
(obj.methods - Object.methods).sort.each do |m|
|
70
|
+
result << get_met_params(obj, m)
|
71
|
+
result << "\n"
|
72
|
+
end
|
73
|
+
puts result
|
74
|
+
end
|
75
|
+
def get_object(obj_txt)
|
76
|
+
met = obj_txt.scan(/\.(\w+)/).flatten.last
|
77
|
+
|
78
|
+
if met.nil? and obj_txt[0].match(/[A-Z]/)
|
79
|
+
obj = Object
|
80
|
+
obj_txt.split("::").each do |cl|
|
81
|
+
if obj.const_defined?(cl.to_sym)
|
82
|
+
obj = obj.const_get(cl)
|
83
|
+
else
|
84
|
+
obj = nil
|
85
|
+
break
|
86
|
+
end
|
87
|
+
end
|
88
|
+
elsif met.nil? and obj_txt[0].match(/[a-z]/)
|
89
|
+
begin
|
90
|
+
obj = self.method(obj_txt)
|
91
|
+
rescue
|
92
|
+
obj = nil
|
93
|
+
end
|
94
|
+
else
|
95
|
+
cl = obj_txt.scan(/([\w\:]+)\./).flatten.first
|
96
|
+
obj = Object
|
97
|
+
cl.split("::").each do |cl|
|
98
|
+
if obj.const_defined?(cl.to_sym)
|
99
|
+
obj = obj.const_get(cl)
|
100
|
+
else
|
101
|
+
obj = nil
|
102
|
+
break
|
103
|
+
end
|
104
|
+
end
|
105
|
+
unless obj.nil?
|
106
|
+
if obj.respond_to?(met)
|
107
|
+
obj = obj.method(met)
|
108
|
+
elsif obj.instance_method(met)
|
109
|
+
obj = obj.instance_method(met)
|
110
|
+
else
|
111
|
+
obj = nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def doc(obj_txt)
|
119
|
+
obj = get_object(obj_txt)
|
120
|
+
if !obj.nil? and obj.respond_to?(:source_location) and obj.respond_to?(:comment) and
|
121
|
+
!obj.source_location.nil? and !obj.comment.nil?
|
122
|
+
result = "_*#{obj.source_location.join(":").gsub(Dir.pwd,"").gsub(Dir.home,"")}*_\n\n"
|
123
|
+
comment = obj.comment.gsub(/^\s*\#/, "")
|
124
|
+
comment.gsub!(/^\s*#+\s*(\R|$)/, "")
|
125
|
+
comment.gsub!(/^\s(\w)([\w\s\-]*):/i, \'*\1\2*:\')
|
126
|
+
comment.gsub!(/^(\s+)(\w[\w\s\-]*):/i, \'\1*`\2`*:\')
|
127
|
+
result << "#{comment}"
|
128
|
+
result << "\n\n"
|
129
|
+
result << get_met_params(obj)
|
130
|
+
else
|
131
|
+
result = "No documentation found for #{obj_txt}. The object doesn\'t exist or it is not accessible."
|
132
|
+
end
|
133
|
+
puts result
|
134
|
+
end
|
135
|
+
|
136
|
+
def source(obj_txt)
|
137
|
+
obj = get_object(obj_txt)
|
138
|
+
if !obj.nil? and obj.respond_to?(:source_location) and obj.respond_to?(:comment) and
|
139
|
+
!obj.source_location.nil? and !obj.comment.nil?
|
140
|
+
result = "# #{obj.source_location.join(":").gsub(Dir.pwd,"").gsub(Dir.home,"")}\n\n"
|
141
|
+
result << "#{obj.source}"
|
142
|
+
else
|
143
|
+
result = "No source code found for #{obj_txt}. The object doesn\'t exist or it is not accessible."
|
144
|
+
end
|
145
|
+
puts result
|
146
|
+
end
|
147
|
+
|
148
|
+
def code(obj_txt)
|
149
|
+
source(obj_txt)
|
150
|
+
end
|
151
|
+
|
152
|
+
file_run_path = \"' + +File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.rb\"
|
153
|
+
file_input_repl = File.open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.input\", \"r\")
|
154
|
+
' + pre_execute + '
|
155
|
+
while true do
|
156
|
+
sleep 0.2
|
157
|
+
code_to_run_repl = file_input_repl.read
|
158
|
+
if code_to_run_repl.to_s!=\"\"
|
159
|
+
add_to_run_repl = true
|
160
|
+
if code_to_run_repl.to_s.match?(/^quit$/i) or
|
161
|
+
code_to_run_repl.to_s.match?(/^exit$/i) or
|
162
|
+
code_to_run_repl.to_s.match?(/^bye bot$/i) or
|
163
|
+
code_to_run_repl.to_s.match?(/^bye$/i)
|
164
|
+
exit
|
165
|
+
else
|
166
|
+
error = false
|
167
|
+
as_it_is = false
|
168
|
+
begin
|
169
|
+
if code_to_run_repl.match?(/^\s*ls\s+(.+)/)
|
170
|
+
add_to_run_repl = false
|
171
|
+
as_it_is = true
|
172
|
+
elsif code_to_run_repl.match(/^\s*doc\s+(.+)/)
|
173
|
+
add_to_run_repl = false
|
174
|
+
code_to_run_repl = \"doc \\\"#{$1}\\\"\"
|
175
|
+
as_it_is = true
|
176
|
+
elsif code_to_run_repl.match(/^\s*(code|source|src)\s+(.+)/)
|
177
|
+
add_to_run_repl = false
|
178
|
+
code_to_run_repl = \"source \\\"#{$2}\\\"\"
|
179
|
+
end
|
180
|
+
begin
|
181
|
+
original_stdout = $stdout
|
182
|
+
$stdout = StringIO.new
|
183
|
+
resp_repl = eval(code_to_run_repl, bindme' + serialt + ')
|
184
|
+
stdout_repl = $stdout.string
|
185
|
+
ensure
|
186
|
+
$stdout = original_stdout
|
187
|
+
end
|
188
|
+
rescue Exception => resp_repl
|
189
|
+
error = true
|
190
|
+
end
|
191
|
+
if error
|
192
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
193
|
+
f.puts \"\`\`\`\n#{resp_repl.to_s.gsub(/^.+' + session_name + '\.rb:\d+:/,\"\")}\`\`\`\"
|
194
|
+
}
|
195
|
+
else
|
196
|
+
if code_to_run_repl.match?(/^\s*p\s+/i)
|
197
|
+
resp_repl = stdout_repl unless stdout_repl.to_s == \'\'
|
198
|
+
if stdout_repl.to_s == \'\'
|
199
|
+
resp_repl = resp_repl.inspect
|
200
|
+
else
|
201
|
+
resp_repl = stdout_repl
|
202
|
+
end
|
203
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
204
|
+
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
205
|
+
}
|
206
|
+
else
|
207
|
+
if stdout_repl.to_s == \'\'
|
208
|
+
resp_repl = resp_repl.ai
|
209
|
+
else
|
210
|
+
resp_repl = stdout_repl
|
211
|
+
end
|
212
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
213
|
+
if as_it_is
|
214
|
+
f.puts resp_repl
|
215
|
+
else
|
216
|
+
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
217
|
+
end
|
218
|
+
}
|
219
|
+
end
|
220
|
+
unless !add_to_run_repl
|
221
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.run\", \"a+\") {|f|
|
222
|
+
f.puts code_to_run_repl
|
223
|
+
}
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
'
|
230
|
+
process_to_run.gsub!('\"', '"')
|
231
|
+
return process_to_run
|
232
|
+
end
|
233
|
+
end
|
@@ -4,12 +4,13 @@ class SlackSmartBot
|
|
4
4
|
# helpadmin: `exit bot`
|
5
5
|
# helpadmin: `quit bot`
|
6
6
|
# helpadmin: `close bot`
|
7
|
+
# helpadmin: `exit bot silent`
|
7
8
|
# helpadmin: The bot stops running and also stops all the bots created from this master channel
|
8
9
|
# helpadmin: You can use this command only if you are an admin user and you are on the master channel
|
9
10
|
# helpadmin: <https://github.com/MarioRuiz/slack-smart-bot#bot-management|more info>
|
10
11
|
# helpadmin: command_id: :exit_bot
|
11
12
|
# helpadmin:
|
12
|
-
def exit_bot(command, from, dest, display_name)
|
13
|
+
def exit_bot(command, from, dest, display_name, silent: false)
|
13
14
|
save_stats(__method__)
|
14
15
|
if config.on_master_bot
|
15
16
|
if config.masters.include?(from) #admin user
|
@@ -18,21 +19,33 @@ class SlackSmartBot
|
|
18
19
|
else
|
19
20
|
case answer
|
20
21
|
when /yes/i, /yep/i, /sure/i
|
21
|
-
|
22
|
-
respond "Ciao #{display_name}!", dest
|
22
|
+
react :runner
|
23
23
|
@bots_created.each { |key, value|
|
24
24
|
value[:thread] = ""
|
25
|
-
send_msg_channel(key, "Bot has been closed by #{from}")
|
25
|
+
send_msg_channel(key, "Bot has been closed by #{from}") unless silent
|
26
26
|
save_status :off, :exited, "The admin closed SmartBot on *##{value.channel_name}*"
|
27
27
|
sleep 0.5
|
28
28
|
}
|
29
29
|
update_bots_file()
|
30
30
|
sleep 0.5
|
31
|
+
file = File.open("#{config.path}/config_tmp.status", "w")
|
32
|
+
config.exit_bot = true
|
33
|
+
file.write config.inspect
|
34
|
+
file.close
|
35
|
+
@status = :exit
|
36
|
+
respond "Game over!", dest
|
31
37
|
if config.simulate
|
38
|
+
sleep 2
|
32
39
|
@status = :off
|
33
40
|
config.simulate = false
|
34
41
|
Thread.exit
|
35
42
|
else
|
43
|
+
respond 'Ok, It will take around 40s to close all the bots, all routines and the master bot.'
|
44
|
+
sleep 35
|
45
|
+
respond "Ciao #{display_name}!", dest
|
46
|
+
unreact :runner
|
47
|
+
react :beach_with_umbrella
|
48
|
+
sleep 1
|
36
49
|
exit!
|
37
50
|
end
|
38
51
|
when /no/i, /nope/i, /cancel/i
|
@@ -4,6 +4,7 @@ require_relative "commands/general/bot_help"
|
|
4
4
|
require_relative "commands/on_bot/general/suggest_command"
|
5
5
|
require_relative "commands/on_bot/ruby_code"
|
6
6
|
require_relative "commands/on_bot/repl"
|
7
|
+
require_relative "commands/on_bot/repl_client"
|
7
8
|
require_relative "commands/on_bot/get_repl"
|
8
9
|
require_relative "commands/on_bot/run_repl"
|
9
10
|
require_relative "commands/on_bot/kill_repl"
|
@@ -60,18 +61,33 @@ require_relative "commands/general/poster"
|
|
60
61
|
require_relative "commands/general/see_access"
|
61
62
|
require_relative "commands/general/allow_access"
|
62
63
|
require_relative "commands/general/deny_access"
|
63
|
-
require_relative "commands/general/add_team"
|
64
|
-
require_relative "commands/general/add_memo_team"
|
65
|
-
require_relative "commands/general/set_memo_status"
|
66
|
-
require_relative "commands/general/delete_memo_team"
|
67
|
-
require_relative "commands/general/see_memos_team"
|
68
|
-
require_relative "commands/general/see_teams"
|
69
|
-
require_relative "commands/general/update_team"
|
70
|
-
require_relative "commands/general/ping_team"
|
71
|
-
require_relative "commands/general/delete_team"
|
64
|
+
require_relative "commands/general/teams/add_team"
|
65
|
+
require_relative "commands/general/teams/memos/add_memo_team"
|
66
|
+
require_relative "commands/general/teams/memos/set_memo_status"
|
67
|
+
require_relative "commands/general/teams/memos/delete_memo_team"
|
68
|
+
require_relative "commands/general/teams/memos/see_memos_team"
|
69
|
+
require_relative "commands/general/teams/see_teams"
|
70
|
+
require_relative "commands/general/teams/update_team"
|
71
|
+
require_relative "commands/general/teams/ping_team"
|
72
|
+
require_relative "commands/general/teams/delete_team"
|
72
73
|
require_relative "commands/general/add_vacation"
|
73
74
|
require_relative "commands/general/remove_vacation"
|
74
75
|
require_relative "commands/general/see_vacations"
|
75
|
-
require_relative "commands/general/see_vacations_team"
|
76
|
+
require_relative "commands/general/teams/see_vacations_team"
|
76
77
|
require_relative "commands/general/public_holidays"
|
77
78
|
require_relative "commands/general/set_public_holidays"
|
79
|
+
require_relative "commands/general/personal_settings"
|
80
|
+
require_relative "commands/general/teams/memos/add_memo_team_comment"
|
81
|
+
require_relative "commands/general/teams/memos/see_memo_team"
|
82
|
+
require_relative 'commands/general/ai/open_ai/open_ai_chat'
|
83
|
+
require_relative 'commands/general/ai/open_ai/open_ai_generate_image'
|
84
|
+
require_relative 'commands/general/ai/open_ai/open_ai_variations_image'
|
85
|
+
require_relative 'commands/general/ai/open_ai/open_ai_edit_image'
|
86
|
+
require_relative 'commands/general/ai/open_ai/open_ai_models'
|
87
|
+
require_relative 'commands/general/ai/open_ai/open_ai_whisper'
|
88
|
+
|
89
|
+
class SlackSmartBot
|
90
|
+
include SlackSmartBot::Commands::General::AI::OpenAI
|
91
|
+
include SlackSmartBot::Commands::General::Teams
|
92
|
+
include SlackSmartBot::Commands::General::Teams::Memos
|
93
|
+
end
|
@@ -74,8 +74,9 @@ class SlackSmartBot
|
|
74
74
|
/\A\s*use\s+rules\s+(on\s+)(.+)/i
|
75
75
|
channel = $2
|
76
76
|
extend_rules(dest, user, from, channel, typem)
|
77
|
-
when /\A\s*exit\s+bot\s*$/i, /\A\s*quit\s+bot\s*$/i, /\A\s*close\s+bot\s*$/i
|
78
|
-
|
77
|
+
when /\A\s*exit\s+bot(\s+silent)?\s*$/i, /\A\s*quit\s+bot(\s+silent)?\s*$/i, /\A\s*close\s+bot(\s+silent)?\s*$/i
|
78
|
+
silent = $1.to_s != ''
|
79
|
+
exit_bot(command, from, dest, display_name, silent: silent)
|
79
80
|
when /\A\s*start\s+(this\s+)?bot$/i
|
80
81
|
start_bot(dest, from)
|
81
82
|
when /\A\s*pause\s+(this\s+)?bot$/i
|
@@ -327,13 +328,23 @@ class SlackSmartBot
|
|
327
328
|
opts.gsub!(/\s+routines$/,'')
|
328
329
|
opts.gsub!(/\s+routines\s+/,'')
|
329
330
|
end
|
331
|
+
only_graph = all_opts.include?('graph')
|
332
|
+
|
330
333
|
monthly = false
|
334
|
+
type_group = ''
|
331
335
|
if all_opts.include?('today')
|
332
336
|
st_from = st_to = "#{Time.now.strftime("%Y-%m-%d")}"
|
333
337
|
elsif all_opts.include?('yesterday')
|
334
338
|
st_from = st_to = "#{(Time.now-86400).strftime("%Y-%m-%d")}"
|
335
339
|
elsif all_opts.include?('monthly')
|
336
340
|
monthly = true
|
341
|
+
type_group = :monthly
|
342
|
+
elsif all_opts.include?('weekly')
|
343
|
+
type_group = :weekly
|
344
|
+
elsif all_opts.include?('daily')
|
345
|
+
type_group = :daily
|
346
|
+
elsif all_opts.include?('yearly')
|
347
|
+
type_group = :yearly
|
337
348
|
end
|
338
349
|
if this_month
|
339
350
|
st_from = "#{Date.today.strftime("%Y-%m-01")}"
|
@@ -379,7 +390,7 @@ class SlackSmartBot
|
|
379
390
|
header << r[0]
|
380
391
|
regexp << r[1]
|
381
392
|
end
|
382
|
-
bot_stats(dest, user, typem, st_channel, st_from, st_to, st_user, st_command, exclude_masters, exclude_routines, exclude_command, monthly, all_data, members_channel, exclude_members_channel, header, regexp)
|
393
|
+
bot_stats(dest, user, typem, st_channel, st_from, st_to, st_user, st_command, exclude_masters, exclude_routines, exclude_command, monthly, all_data, members_channel, exclude_members_channel, header, regexp, type_group: type_group, only_graph: only_graph)
|
383
394
|
when /\A(set|turn)\s+maintenance\s+(on|off)\s*()\z/im, /\A(set|turn)\s+maintenance\s+(on)\s*(.+)\s*\z/im
|
384
395
|
status = $2.downcase
|
385
396
|
message = $3.to_s
|
@@ -26,6 +26,15 @@ class SlackSmartBot
|
|
26
26
|
else
|
27
27
|
respond "Only the creator of the loop or an admin can stop the loop.", dest, thread_ts: thread_ts
|
28
28
|
end
|
29
|
+
if Thread.current.key?(:encrypted) and Thread.current[:encrypted].size > 0
|
30
|
+
found = false
|
31
|
+
Thread.current[:encrypted].each do |encdata|
|
32
|
+
found = true if !found and text.include?(encdata)
|
33
|
+
text.gsub!(encdata, "********")
|
34
|
+
end
|
35
|
+
text = "********" if !found
|
36
|
+
text+= " (encrypted #{Thread.current[:command_id]})"
|
37
|
+
end
|
29
38
|
@logger.info "command: #{nick}> #{text}"
|
30
39
|
return :next #jal
|
31
40
|
end
|
@@ -306,7 +315,20 @@ class SlackSmartBot
|
|
306
315
|
end
|
307
316
|
processed = (processed || general_bot_commands(user, command_thread, dest, files))
|
308
317
|
processed = (processed || general_commands(user, command_thread, dest, files)) if defined?(general_commands)
|
309
|
-
|
318
|
+
if processed
|
319
|
+
text_to_log = command_thread.dup
|
320
|
+
|
321
|
+
if Thread.current.key?(:encrypted) and Thread.current[:encrypted].size > 0
|
322
|
+
found = false
|
323
|
+
Thread.current[:encrypted].each do |encdata|
|
324
|
+
found = true if !found and text_to_log.include?(encdata)
|
325
|
+
text_to_log.gsub!(encdata, "********")
|
326
|
+
end
|
327
|
+
text_to_log = "********" if !found
|
328
|
+
text_to_log+= " (encrypted #{Thread.current[:command_id]})"
|
329
|
+
end
|
330
|
+
@logger.info "command: #{nick}> #{text_to_log}"
|
331
|
+
end
|
310
332
|
end
|
311
333
|
|
312
334
|
if !config.on_maintenance and !processed and typem != :on_pub and typem != :on_pg
|
@@ -319,7 +341,19 @@ class SlackSmartBot
|
|
319
341
|
((@listening[nick].key?(dest) and !Thread.current[:on_thread]) or
|
320
342
|
(@listening[nick].key?(thread_ts) and Thread.current[:on_thread]))) or
|
321
343
|
dest[0] == "D" or on_demand)
|
322
|
-
|
344
|
+
unless processed
|
345
|
+
text_to_log = command_thread.dup
|
346
|
+
found = false
|
347
|
+
if Thread.current.key?(:encrypted) and Thread.current[:encrypted].size > 0
|
348
|
+
Thread.current[:encrypted].each do |encdata|
|
349
|
+
found = true if !found and text_to_log.include?(encdata)
|
350
|
+
text_to_log.gsub!(encdata, "********")
|
351
|
+
end
|
352
|
+
text_to_log = "********" if !found
|
353
|
+
text_to_log+= " (encrypted #{Thread.current[:command_id]})"
|
354
|
+
end
|
355
|
+
@logger.info "command: #{nick}> #{text_to_log}"
|
356
|
+
end
|
323
357
|
#todo: verify this
|
324
358
|
|
325
359
|
if dest[0] == "C" or dest[0] == "G" or (dest[0] == "D" and typem == :on_call)
|
@@ -71,6 +71,16 @@ class SlackSmartBot
|
|
71
71
|
if !data.files.nil? and data.files.size == 1 and data.text.to_s == "" and data.files[0].filetype == "ruby"
|
72
72
|
data.text = "ruby"
|
73
73
|
end
|
74
|
+
|
75
|
+
#open ai chat gpt and shared messages as an input
|
76
|
+
if data.text.match?(/\A\s*(^|!!|!)?\s*(\?|\?\?)\s*/im) and !data.attachments.nil? and data.attachments.size > 0 and !data.attachments[0].text.nil? and data.attachments[0].text != ''
|
77
|
+
data.attachments.each_with_index do |att, i|
|
78
|
+
if !att.text.nil? and att.text != ''
|
79
|
+
data.text += "\n#{att.text}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
74
84
|
if !dest.nil? and config.on_master_bot and !data.text.nil? and data.text.match(/^ping from (.+)\s*$/) and data.user == config[:nick_id]
|
75
85
|
@pings << $1
|
76
86
|
end
|
@@ -355,6 +365,24 @@ class SlackSmartBot
|
|
355
365
|
if File.exist?("#{config.path}/shortcuts/shortcuts_global.yaml")
|
356
366
|
@shortcuts_global = YAML.load(File.read("#{config.path}/shortcuts/shortcuts_global.yaml"))
|
357
367
|
end
|
368
|
+
when /\AGame\s+over!\z/i
|
369
|
+
sleep 2
|
370
|
+
get_bots_created()
|
371
|
+
if File.exist?("#{config.path}/config_tmp.status")
|
372
|
+
file_cts = IO.readlines("#{config.path}/config_tmp.status").join
|
373
|
+
unless file_cts.to_s() == ""
|
374
|
+
file_cts = eval(file_cts)
|
375
|
+
if file_cts.is_a?(Hash) and file_cts.key?(:exit_bot)
|
376
|
+
config.exit_bot = file_cts.exit_bot
|
377
|
+
end
|
378
|
+
@status = :exit if config.exit_bot
|
379
|
+
end
|
380
|
+
end
|
381
|
+
if @status == :exit
|
382
|
+
@logger.info 'Game over!'
|
383
|
+
sleep 3
|
384
|
+
exit!
|
385
|
+
end
|
358
386
|
end
|
359
387
|
end
|
360
388
|
end
|
@@ -2,7 +2,7 @@ class SlackSmartBot
|
|
2
2
|
|
3
3
|
def create_routine_thread(name, hroutine)
|
4
4
|
t = Thread.new do
|
5
|
-
while @routines.key?(@channel_id) and @routines[@channel_id].key?(name)
|
5
|
+
while @routines.key?(@channel_id) and @routines[@channel_id].key?(name) and @status != :exit
|
6
6
|
@routines[@channel_id][name][:thread] = Thread.current
|
7
7
|
started = Time.now
|
8
8
|
if @status == :on and @routines[@channel_id][name][:status] == :on
|