slack-smart-bot 1.13.1 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|