slack-smart-bot 1.13.1 → 1.13.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +95 -96
- data/whats_new.txt +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d49cea86f54f8c7486c39dfbdb0c9e871a5b2d740c06e80242f120e9f3c8b38
|
4
|
+
data.tar.gz: fb3d52d42693d1dba820685d7ef0bada290298de9db2cd00212e1196c2baaae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 261ac1f20a7bdec84c5e5b24278584656def3ab09dc0bf2f4fc17080a812952a18474bff74f845fcc83e8783b121e00be555086ea7159bd362b955236c4b1dc6
|
7
|
+
data.tar.gz: ea5fe6b71b79f696727a1a54585e6a2b450c381fa7daadc6e351e9513e3a0b878c7869683b2df4db35997071af06d17a1d55d03f465421aa701e9bd727adef88
|
@@ -10,7 +10,7 @@ class SlackSmartBot
|
|
10
10
|
# help: `repl SESSION_NAME ENV_VAR=VALUE ENV_VAR='VALUE'`
|
11
11
|
# help: `repl SESSION_NAME: "DESCRIPTION"`
|
12
12
|
# help: `repl SESSION_NAME: "DESCRIPTION" ENV_VAR=VALUE ENV_VAR='VALUE'`
|
13
|
-
# help: Will run all we write as a ruby command and will keep the session values.
|
13
|
+
# help: Will run all we write as a ruby command and will keep the session values.
|
14
14
|
# help: SESSION_NAME only admits from a to Z, numbers, - and _
|
15
15
|
# help: If no SESSION_NAME supplied it will be treated as a temporary REPL
|
16
16
|
# help: If 'private' specified the repl will be accessible only by you and it will be displayed only to you when `see repls`
|
@@ -19,7 +19,7 @@ class SlackSmartBot
|
|
19
19
|
# help: Send _quit_, _bye_ or _exit_ to finish the session.
|
20
20
|
# help: Send puts, print, p or pp if you want to print out something when using _run repl_ later.
|
21
21
|
# help: After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
22
|
-
# help: If you declare on your rules file a method called 'project_folder' returning the path for the project folder, the code will be executed from that folder.
|
22
|
+
# help: If you declare on your rules file a method called 'project_folder' returning the path for the project folder, the code will be executed from that folder.
|
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_
|
@@ -41,9 +41,9 @@ class SlackSmartBot
|
|
41
41
|
save_stats(__method__)
|
42
42
|
Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
|
43
43
|
Dir.mkdir("#{config.path}/repl/#{@channel_id}") unless Dir.exist?("#{config.path}/repl/#{@channel_id}")
|
44
|
-
|
44
|
+
|
45
45
|
serialt = Time.now.strftime("%Y%m%d%H%M%S%N")
|
46
|
-
if session_name.to_s==
|
46
|
+
if session_name.to_s == ""
|
47
47
|
session_name = "#{from}_#{serialt}"
|
48
48
|
temp_repl = true
|
49
49
|
else
|
@@ -51,7 +51,7 @@ class SlackSmartBot
|
|
51
51
|
i = 0
|
52
52
|
name = session_name
|
53
53
|
while File.exist?("#{config.path}/repl/#{@channel_id}/#{session_name}.input")
|
54
|
-
i+=1
|
54
|
+
i += 1
|
55
55
|
session_name = "#{name}#{i}"
|
56
56
|
end
|
57
57
|
end
|
@@ -65,32 +65,32 @@ class SlackSmartBot
|
|
65
65
|
thread_ts: Thread.current[:thread_ts],
|
66
66
|
collaborators: [],
|
67
67
|
user_type: :creator,
|
68
|
-
user_creator: from
|
68
|
+
user_creator: from,
|
69
69
|
}
|
70
70
|
|
71
71
|
unless temp_repl
|
72
72
|
@repls[session_name] = {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
73
|
+
created: @repl_sessions[from][:started].to_s,
|
74
|
+
accessed: @repl_sessions[from][:started].to_s,
|
75
|
+
creator_name: user.name,
|
76
|
+
creator_id: user.id,
|
77
|
+
description: description,
|
78
|
+
type: type,
|
79
|
+
runs_by_creator: 0,
|
80
|
+
runs_by_others: 0,
|
81
|
+
gets: 0,
|
82
82
|
}
|
83
|
-
update_repls()
|
83
|
+
update_repls()
|
84
84
|
end
|
85
85
|
react :running
|
86
86
|
@ts_react ||= {}
|
87
|
-
if Thread.current[:ts].to_s ==
|
87
|
+
if Thread.current[:ts].to_s == ""
|
88
88
|
@ts_react[session_name] = Thread.current[:thread_ts]
|
89
89
|
else
|
90
90
|
@ts_react[session_name] = Thread.current[:ts]
|
91
|
-
end
|
91
|
+
end
|
92
92
|
@ts_repl ||= {}
|
93
|
-
@ts_repl[session_name] =
|
93
|
+
@ts_repl[session_name] = ""
|
94
94
|
|
95
95
|
message = "Session name: *#{session_name}*
|
96
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`.
|
@@ -105,26 +105,26 @@ class SlackSmartBot
|
|
105
105
|
_repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
106
106
|
"
|
107
107
|
respond message, dest
|
108
|
-
|
108
|
+
|
109
109
|
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "", mode: "a+")
|
110
110
|
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.output", "", mode: "a+")
|
111
111
|
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.run", "", mode: "a+")
|
112
|
-
|
112
|
+
|
113
113
|
if type != :private_clean and type != :public_clean
|
114
114
|
pre_execute = '
|
115
115
|
if File.exist?(\"./.smart-bot-repl\")
|
116
116
|
begin
|
117
|
-
eval(File.read(\"./.smart-bot-repl\"), bindme' + serialt +
|
117
|
+
eval(File.read(\"./.smart-bot-repl\"), bindme' + serialt + ")
|
118
118
|
rescue Exception => resp_repl
|
119
119
|
end
|
120
120
|
end
|
121
|
-
|
121
|
+
"
|
122
122
|
else
|
123
|
-
pre_execute =
|
123
|
+
pre_execute = ""
|
124
124
|
end
|
125
125
|
|
126
|
-
process_to_run =
|
127
|
-
|
126
|
+
process_to_run = "
|
127
|
+
" + env_vars.join("\n") + '
|
128
128
|
require \"amazing_print\"
|
129
129
|
require \"stringio\"
|
130
130
|
bindme' + serialt + ' = binding
|
@@ -132,8 +132,8 @@ class SlackSmartBot
|
|
132
132
|
def ls(obj)
|
133
133
|
(obj.methods - Object.methods)
|
134
134
|
end
|
135
|
-
file_run_path = \"' +
|
136
|
-
file_input_repl = File.open(\"' + File.expand_path(config.path) +
|
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
137
|
' + pre_execute + '
|
138
138
|
while true do
|
139
139
|
sleep 0.2
|
@@ -163,7 +163,7 @@ class SlackSmartBot
|
|
163
163
|
error = true
|
164
164
|
end
|
165
165
|
if error
|
166
|
-
open(\"' + File.expand_path(config.path) +
|
166
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
167
167
|
f.puts \"\`\`\`\n#{resp_repl.to_s.gsub(/^.+' + session_name + '\.rb:\d+:/,\"\")}\`\`\`\"
|
168
168
|
}
|
169
169
|
else
|
@@ -174,7 +174,7 @@ class SlackSmartBot
|
|
174
174
|
else
|
175
175
|
resp_repl = stdout_repl
|
176
176
|
end
|
177
|
-
open(\"' + File.expand_path(config.path) +
|
177
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
178
178
|
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
179
179
|
}
|
180
180
|
else
|
@@ -183,12 +183,12 @@ class SlackSmartBot
|
|
183
183
|
else
|
184
184
|
resp_repl = stdout_repl
|
185
185
|
end
|
186
|
-
open(\"' + File.expand_path(config.path) +
|
186
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.output\", \"a+\") {|f|
|
187
187
|
f.puts \"\`\`\`\n#{resp_repl}\`\`\`\"
|
188
188
|
}
|
189
189
|
end
|
190
190
|
unless !add_to_run_repl
|
191
|
-
open(\"' + File.expand_path(config.path) +
|
191
|
+
open(\"' + File.expand_path(config.path) + "/repl/" + @channel_id + "/" + session_name + '.run\", \"a+\") {|f|
|
192
192
|
f.puts code_to_run_repl
|
193
193
|
}
|
194
194
|
end
|
@@ -199,16 +199,16 @@ class SlackSmartBot
|
|
199
199
|
'
|
200
200
|
unless rules_file.empty? # to get the project_folder
|
201
201
|
begin
|
202
|
-
eval(File.new(config.path+rules_file).read) if File.exist?(config.path+rules_file)
|
202
|
+
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file)
|
203
203
|
end
|
204
204
|
end
|
205
|
-
process_to_run.gsub!('\"','"')
|
205
|
+
process_to_run.gsub!('\"', '"')
|
206
206
|
file_run_path = "./tmp/repl/#{@channel_id}/#{session_name}.rb"
|
207
207
|
if defined?(project_folder)
|
208
208
|
Dir.mkdir("#{project_folder}/tmp/") unless Dir.exist?("#{project_folder}/tmp/")
|
209
209
|
Dir.mkdir("#{project_folder}/tmp/repl") unless Dir.exist?("#{project_folder}/tmp/repl")
|
210
210
|
Dir.mkdir("#{project_folder}/tmp/repl/#{@channel_id}/") unless Dir.exist?("#{project_folder}/tmp/repl/#{@channel_id}/")
|
211
|
-
file_run = File.open(file_run_path.gsub(
|
211
|
+
file_run = File.open(file_run_path.gsub("./", "#{project_folder}/"), "w")
|
212
212
|
file_run.write process_to_run
|
213
213
|
file_run.close
|
214
214
|
else
|
@@ -226,87 +226,88 @@ class SlackSmartBot
|
|
226
226
|
process_to_run = ("cd #{project_folder} && " + process_to_run) if defined?(project_folder)
|
227
227
|
stdin, stdout, stderr, wait_thr = Open3.popen3(process_to_run)
|
228
228
|
timeout = 30 * 60 # 30 minutes
|
229
|
-
|
229
|
+
|
230
230
|
file_output_repl = File.open("#{config.path}/repl/#{@channel_id}/#{session_name}.output", "r")
|
231
231
|
@repl_sessions[from][:pid] = wait_thr.pid
|
232
|
-
while (wait_thr.status ==
|
232
|
+
while (wait_thr.status == "run" or wait_thr.status == "sleep") and @repl_sessions.key?(from)
|
233
233
|
begin
|
234
|
-
if (Time.now
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end
|
234
|
+
if (Time.now - @repl_sessions[from][:finished]) > timeout
|
235
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
|
236
|
+
f.puts "quit"
|
237
|
+
}
|
238
|
+
respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
|
239
|
+
unreact :running, @ts_react[@repl_sessions[from].name]
|
240
|
+
pids = `pgrep -P #{@repl_sessions[from][:pid]}`.split("\n").map(&:to_i) #todo: it needs to be adapted for Windows
|
241
|
+
pids.each do |pid|
|
242
|
+
begin
|
243
|
+
Process.kill("KILL", pid)
|
244
|
+
rescue
|
246
245
|
end
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
246
|
+
end
|
247
|
+
@repl_sessions[from][:collaborators].each do |collaborator|
|
248
|
+
@repl_sessions.delete(collaborator)
|
249
|
+
end
|
250
|
+
@repl_sessions.delete(from)
|
251
|
+
break
|
252
252
|
end
|
253
253
|
sleep 0.2
|
254
254
|
resp_repl = file_output_repl.read
|
255
|
-
if resp_repl.to_s!=
|
256
|
-
if @ts_repl[@repl_sessions[from].name].to_s !=
|
257
|
-
unreact(:running, @ts_repl[@repl_sessions[from].name])
|
258
|
-
@ts_repl[@repl_sessions[from].name] =
|
255
|
+
if resp_repl.to_s != ""
|
256
|
+
if @ts_repl[@repl_sessions[from].name].to_s != ""
|
257
|
+
unreact(:running, @ts_repl[@repl_sessions[from].name])
|
258
|
+
@ts_repl[@repl_sessions[from].name] = ""
|
259
259
|
end
|
260
260
|
if resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500
|
261
261
|
respond resp_repl, dest
|
262
262
|
else
|
263
|
-
resp_repl.gsub!(/^\s*```/,
|
264
|
-
resp_repl.gsub!(/```\s*$/,
|
265
|
-
send_file(dest, "",
|
263
|
+
resp_repl.gsub!(/^\s*```/, "")
|
264
|
+
resp_repl.gsub!(/```\s*$/, "")
|
265
|
+
send_file(dest, "", "response.rb", "", "text/plain", "ruby", content: resp_repl)
|
266
266
|
end
|
267
267
|
end
|
268
268
|
rescue Exception => excp
|
269
269
|
@logger.fatal excp
|
270
270
|
end
|
271
271
|
end
|
272
|
-
elsif @repl_sessions.key?(from) and @repl_sessions[from][:command].to_s ==
|
273
|
-
respond
|
272
|
+
elsif @repl_sessions.key?(from) and @repl_sessions[from][:command].to_s == ""
|
273
|
+
respond "You are already in a repl on this SmartBot. You need to quit that one before starting a new one."
|
274
274
|
else
|
275
275
|
@repl_sessions[from][:finished] = Time.now
|
276
276
|
code = @repl_sessions[from][:command]
|
277
|
-
@repl_sessions[from][:command] =
|
277
|
+
@repl_sessions[from][:command] = ""
|
278
278
|
code.gsub!("\\n", "\n")
|
279
279
|
code.gsub!("\\r", "\r")
|
280
280
|
# Disabled for the moment since it is deleting lines with '}'
|
281
281
|
#code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting.
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
282
|
+
if code.match?(/\A\s*-/i)
|
283
|
+
# don't treat
|
284
|
+
elsif code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File.") or
|
285
|
+
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
|
286
|
+
code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
|
287
|
+
code.include?("ENV") or code.match?(/=\s*IO/) or code.include?("Dir.") or
|
288
|
+
code.match?(/=\s*File/) or code.match?(/=\s*Dir/) or code.match?(/<\s*File/) or code.match?(/<\s*Dir/) or
|
289
|
+
code.match?(/\w+:\s*File/) or code.match?(/\w+:\s*Dir/) or
|
290
|
+
code.match?(/=?\s*(require|load)(\(|\s)/i)
|
290
291
|
respond "Sorry I cannot run this due security reasons", dest
|
291
292
|
elsif code.match(/\A\s*add\s+collaborator\s+<@(\w+)>\s*\z/i)
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
293
|
+
collaborator = $1
|
294
|
+
user_info = @users.select { |u| u.id == collaborator or (u.key?(:enterprise_user) and u.enterprise_user.id == collaborator) }[-1]
|
295
|
+
collaborator_name = user_info.name
|
296
|
+
if @repl_sessions.key?(collaborator_name)
|
297
|
+
respond "Sorry, <@#{collaborator}> is already in a repl. Please ask her/him to quit it first.", dest
|
298
|
+
else
|
299
|
+
respond "Collaborator added. Now <@#{collaborator}> can interact with this repl.", dest
|
300
|
+
creator = @repl_sessions[from][:user_creator]
|
301
|
+
@repl_sessions[creator][:collaborators] << collaborator_name
|
302
|
+
@repl_sessions[collaborator_name] = {
|
303
|
+
name: @repl_sessions[from][:name],
|
304
|
+
dest: dest,
|
305
|
+
on_thread: Thread.current[:on_thread],
|
306
|
+
thread_ts: Thread.current[:thread_ts],
|
307
|
+
user_type: :collaborator,
|
308
|
+
user_creator: creator,
|
309
|
+
}
|
310
|
+
end
|
310
311
|
else
|
311
312
|
if @repl_sessions[from][:user_type] == :collaborator
|
312
313
|
@repl_sessions[@repl_sessions[from][:user_creator]][:input] << code
|
@@ -320,7 +321,7 @@ class SlackSmartBot
|
|
320
321
|
@repl_sessions[@repl_sessions[from][:user_creator]][:collaborators].delete(from)
|
321
322
|
@repl_sessions.delete(from)
|
322
323
|
else
|
323
|
-
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input",
|
324
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
|
324
325
|
f.puts code
|
325
326
|
}
|
326
327
|
respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
|
@@ -337,14 +338,12 @@ class SlackSmartBot
|
|
337
338
|
end
|
338
339
|
@repl_sessions.delete(from)
|
339
340
|
end
|
340
|
-
when /\A\s*-/i
|
341
|
-
#ommit
|
342
341
|
else
|
343
|
-
if @ts_repl[@repl_sessions[from].name].to_s ==
|
342
|
+
if @ts_repl[@repl_sessions[from].name].to_s == ""
|
344
343
|
@ts_repl[@repl_sessions[from].name] = Thread.current[:ts]
|
345
|
-
react :running
|
344
|
+
react :running
|
346
345
|
end
|
347
|
-
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input",
|
346
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "a+") { |f|
|
348
347
|
f.puts code
|
349
348
|
}
|
350
349
|
end
|
data/whats_new.txt
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slack-smart-bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.13.
|
4
|
+
version: 1.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slack-ruby-client
|