slack-smart-bot 1.5.1 → 1.6.0
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/README.md +89 -2
- data/lib/slack-smart-bot.rb +6 -1
- data/lib/slack/smart-bot/commands.rb +5 -0
- data/lib/slack/smart-bot/commands/general/bot_help.rb +44 -40
- data/lib/slack/smart-bot/commands/general/bot_status.rb +32 -28
- data/lib/slack/smart-bot/commands/general/bye_bot.rb +9 -1
- data/lib/slack/smart-bot/commands/general/hi_bot.rb +6 -1
- data/lib/slack/smart-bot/commands/general/use_rules.rb +33 -29
- data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +40 -35
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +32 -0
- data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +30 -25
- data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +43 -0
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +202 -0
- data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +33 -29
- data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +73 -0
- data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +24 -0
- data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +23 -18
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +32 -27
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +79 -74
- data/lib/slack/smart-bot/listen.rb +2 -0
- data/lib/slack/smart-bot/process.rb +61 -9
- data/lib/slack/smart-bot/process_first.rb +17 -3
- data/lib/slack/smart-bot/treat_message.rb +24 -3
- data/lib/slack/smart-bot/utils.rb +3 -0
- data/lib/slack/smart-bot/utils/get_help.rb +1 -1
- data/lib/slack/smart-bot/utils/get_repls.rb +11 -0
- data/lib/slack/smart-bot/utils/update_repls.rb +8 -0
- metadata +28 -19
@@ -17,46 +17,51 @@ class SlackSmartBot
|
|
17
17
|
# help: _shortcut Spanish Account_
|
18
18
|
# help: _Spanish Account_
|
19
19
|
# help:
|
20
|
-
def add_shortcut(dest,
|
20
|
+
def add_shortcut(dest, user, typem, for_all, shortcut_name, command, command_to_run)
|
21
21
|
save_stats(__method__)
|
22
22
|
unless typem == :on_extended
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if for_all.to_s != ""
|
27
|
-
@shortcuts.each { |sck, scv|
|
28
|
-
if sck != :all and sck != from and scv.key?(shortcut_name)
|
29
|
-
found_other = true
|
30
|
-
end
|
31
|
-
}
|
32
|
-
end
|
33
|
-
if !config.admins.include?(from) and @shortcuts[:all].include?(shortcut_name) and !@shortcuts[from].include?(shortcut_name)
|
34
|
-
respond "Only the creator of the shortcut can modify it", dest
|
35
|
-
elsif found_other
|
36
|
-
respond "You cannot create a shortcut for all with the same name than other user is using", dest
|
37
|
-
elsif !@shortcuts[from].include?(shortcut_name)
|
38
|
-
#new shortcut
|
39
|
-
@shortcuts[from][shortcut_name] = command_to_run
|
40
|
-
@shortcuts[:all][shortcut_name] = command_to_run if for_all.to_s != ""
|
41
|
-
update_shortcuts_file()
|
42
|
-
respond "shortcut added", dest
|
23
|
+
from = user.name
|
24
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
25
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
43
26
|
else
|
44
|
-
|
45
|
-
|
46
|
-
|
27
|
+
@shortcuts[from] = Hash.new() unless @shortcuts.keys.include?(from)
|
28
|
+
|
29
|
+
found_other = false
|
30
|
+
if for_all.to_s != ""
|
31
|
+
@shortcuts.each { |sck, scv|
|
32
|
+
if sck != :all and sck != from and scv.key?(shortcut_name)
|
33
|
+
found_other = true
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
if !config.admins.include?(from) and @shortcuts[:all].include?(shortcut_name) and !@shortcuts[from].include?(shortcut_name)
|
38
|
+
respond "Only the creator of the shortcut can modify it", dest
|
39
|
+
elsif found_other
|
40
|
+
respond "You cannot create a shortcut for all with the same name than other user is using", dest
|
41
|
+
elsif !@shortcuts[from].include?(shortcut_name)
|
42
|
+
#new shortcut
|
43
|
+
@shortcuts[from][shortcut_name] = command_to_run
|
44
|
+
@shortcuts[:all][shortcut_name] = command_to_run if for_all.to_s != ""
|
45
|
+
update_shortcuts_file()
|
46
|
+
respond "shortcut added", dest
|
47
47
|
else
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@shortcuts[:all][shortcut_name] = command_to_run if for_all.to_s != ""
|
52
|
-
update_shortcuts_file()
|
53
|
-
respond "shortcut added", dest
|
54
|
-
@questions.delete(from)
|
55
|
-
when /^no/i
|
56
|
-
respond "ok, I won't add it", dest
|
57
|
-
@questions.delete(from)
|
48
|
+
#are you sure? to avoid overwriting existing
|
49
|
+
unless @questions.keys.include?(from)
|
50
|
+
ask("The shortcut already exists, are you sure you want to overwrite it?", command, from, dest)
|
58
51
|
else
|
59
|
-
|
52
|
+
case @questions[from]
|
53
|
+
when /^(yes|yep)/i
|
54
|
+
@shortcuts[from][shortcut_name] = command_to_run
|
55
|
+
@shortcuts[:all][shortcut_name] = command_to_run if for_all.to_s != ""
|
56
|
+
update_shortcuts_file()
|
57
|
+
respond "shortcut added", dest
|
58
|
+
@questions.delete(from)
|
59
|
+
when /^no/i
|
60
|
+
respond "ok, I won't add it", dest
|
61
|
+
@questions.delete(from)
|
62
|
+
else
|
63
|
+
ask "I don't understand, yes or no?", command, from, dest
|
64
|
+
end
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# help: ----------------------------------------------
|
3
|
+
# help: `delete repl SESSION_NAME`
|
4
|
+
# help: `delete irb SESSION_NAME`
|
5
|
+
# help: `remove repl SESSION_NAME`
|
6
|
+
# help:
|
7
|
+
# help: Will delete the specified REPL
|
8
|
+
# help: Only the creator of the REPL or an admin can delete REPLs
|
9
|
+
# help:
|
10
|
+
def delete_repl(dest, user, session_name)
|
11
|
+
#todo: add tests
|
12
|
+
save_stats(__method__)
|
13
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
14
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
15
|
+
else
|
16
|
+
if @repls.key?(session_name)
|
17
|
+
Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
|
18
|
+
if config.admins.include?(user.name) or @repls[session_name].creator_name == user.name
|
19
|
+
@repls.delete(session_name)
|
20
|
+
update_repls()
|
21
|
+
File.rename("#{config.path}/repl/#{@channel_id}/#{session_name}.input", "#{config.path}/repl/#{@channel_id}/#{session_name}_#{Time.now.strftime("%Y%m%d%H%M%S%N")}.deleted")
|
22
|
+
respond "REPL #{session_name} deleted"
|
23
|
+
else
|
24
|
+
respond "Only admins or the creator of this REPL can delete it", dest
|
25
|
+
end
|
26
|
+
|
27
|
+
else
|
28
|
+
respond "The REPL with session name: #{session_name} doesn't exist on this Smart Bot Channel", dest
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -5,37 +5,42 @@ class SlackSmartBot
|
|
5
5
|
# help: It will delete the shortcut with the supplied name
|
6
6
|
# help:
|
7
7
|
|
8
|
-
def delete_shortcut(dest,
|
8
|
+
def delete_shortcut(dest, user, shortcut, typem, command)
|
9
9
|
save_stats(__method__)
|
10
10
|
unless typem == :on_extended
|
11
|
-
|
11
|
+
from = user.name
|
12
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
13
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
14
|
+
else
|
15
|
+
deleted = false
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
else
|
21
|
-
case @questions[from]
|
22
|
-
when /^(yes|yep)/i
|
23
|
-
@questions.delete(from)
|
24
|
-
respond "shortcut deleted!", dest
|
25
|
-
respond("#{shortcut}: #{@shortcuts[from][shortcut]}", dest) if @shortcuts.key?(from) and @shortcuts[from].key?(shortcut)
|
26
|
-
respond("#{shortcut}: #{@shortcuts[:all][shortcut]}", dest) if @shortcuts.key?(:all) and @shortcuts[:all].key?(shortcut)
|
27
|
-
@shortcuts[from].delete(shortcut) if @shortcuts.key?(from) and @shortcuts[from].key?(shortcut)
|
28
|
-
@shortcuts[:all].delete(shortcut) if @shortcuts.key?(:all) and @shortcuts[:all].key?(shortcut)
|
29
|
-
update_shortcuts_file()
|
30
|
-
when /^no/i
|
31
|
-
@questions.delete(from)
|
32
|
-
respond "ok, I won't delete it", dest
|
17
|
+
if !config.admins.include?(from) and @shortcuts[:all].include?(shortcut) and !@shortcuts[from].include?(shortcut)
|
18
|
+
respond "Only the creator of the shortcut or an admin user can delete it", dest
|
19
|
+
elsif (@shortcuts.keys.include?(from) and @shortcuts[from].keys.include?(shortcut)) or
|
20
|
+
(config.admins.include?(from) and @shortcuts[:all].include?(shortcut))
|
21
|
+
#are you sure? to avoid deleting by mistake
|
22
|
+
unless @questions.keys.include?(from)
|
23
|
+
ask("are you sure you want to delete it?", command, from, dest)
|
33
24
|
else
|
34
|
-
|
25
|
+
case @questions[from]
|
26
|
+
when /^(yes|yep)/i
|
27
|
+
@questions.delete(from)
|
28
|
+
respond "shortcut deleted!", dest
|
29
|
+
respond("#{shortcut}: #{@shortcuts[from][shortcut]}", dest) if @shortcuts.key?(from) and @shortcuts[from].key?(shortcut)
|
30
|
+
respond("#{shortcut}: #{@shortcuts[:all][shortcut]}", dest) if @shortcuts.key?(:all) and @shortcuts[:all].key?(shortcut)
|
31
|
+
@shortcuts[from].delete(shortcut) if @shortcuts.key?(from) and @shortcuts[from].key?(shortcut)
|
32
|
+
@shortcuts[:all].delete(shortcut) if @shortcuts.key?(:all) and @shortcuts[:all].key?(shortcut)
|
33
|
+
update_shortcuts_file()
|
34
|
+
when /^no/i
|
35
|
+
@questions.delete(from)
|
36
|
+
respond "ok, I won't delete it", dest
|
37
|
+
else
|
38
|
+
ask("I don't understand, are you sure you want to delete it? (yes or no)", command, from, dest)
|
39
|
+
end
|
35
40
|
end
|
41
|
+
else
|
42
|
+
respond "shortcut not found", dest
|
36
43
|
end
|
37
|
-
else
|
38
|
-
respond "shortcut not found", dest
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# help: ----------------------------------------------
|
3
|
+
# help: `get repl SESSION_NAME`
|
4
|
+
# help: `get irb SESSION_NAME`
|
5
|
+
# help: `get live SESSION_NAME`
|
6
|
+
# help:
|
7
|
+
# help: Will get the Ruby commands sent on that SESSION_NAME.
|
8
|
+
# help:
|
9
|
+
def get_repl(dest, user, session_name)
|
10
|
+
#todo: add tests
|
11
|
+
save_stats(__method__)
|
12
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
13
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
14
|
+
else
|
15
|
+
Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
|
16
|
+
Dir.mkdir("#{config.path}/repl/#{@channel_id}") unless Dir.exist?("#{config.path}/repl/#{@channel_id}")
|
17
|
+
if File.exist?("#{config.path}/repl/#{@channel_id}/#{session_name}.input")
|
18
|
+
if @repls.key?(session_name) and @repls[session_name][:type] == :private and
|
19
|
+
@repls[session_name][:creator_name]!=user.name and
|
20
|
+
!config.admins.include?(user.name)
|
21
|
+
respond "The REPL with session name: #{session_name} is private", dest
|
22
|
+
else
|
23
|
+
if @repls.key?(session_name)
|
24
|
+
@repls[session_name][:accessed] = Time.now.to_s
|
25
|
+
@repls[session_name][:gets] += 1
|
26
|
+
update_repls()
|
27
|
+
end
|
28
|
+
|
29
|
+
content = "require 'nice_http'\n"
|
30
|
+
if File.exist?("#{project_folder}/.smart-bot-repl")
|
31
|
+
content += File.read("#{project_folder}/.smart-bot-repl")
|
32
|
+
content += "\n"
|
33
|
+
end
|
34
|
+
content += File.read("#{config.path}/repl/#{@channel_id}/#{session_name}.input").gsub(/^(quit|exit|bye)$/i,'')
|
35
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{session_name}.rb", content, mode: "w+")
|
36
|
+
send_file(dest, "REPL #{session_name} on #{config.channel}", "#{config.path}/repl/#{@channel_id}/#{session_name}.rb", " REPL #{session_name} on #{config.channel}", 'text/plain', "ruby")
|
37
|
+
end
|
38
|
+
else
|
39
|
+
respond "The REPL with session name: #{session_name} doesn't exist on this Smart Bot Channel", dest
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# help: ----------------------------------------------
|
3
|
+
# help: `repl`
|
4
|
+
# help: `live`
|
5
|
+
# help: `irb`
|
6
|
+
# help: `repl SESSION_NAME`
|
7
|
+
# help: `private repl SESSION_NAME`
|
8
|
+
# help: `repl ENV_VAR=VALUE`
|
9
|
+
# help: `repl SESSION_NAME ENV_VAR=VALUE ENV_VAR='VALUE'`
|
10
|
+
# help: `repl SESSION_NAME: "DESCRIPTION"`
|
11
|
+
# help: `repl SESSION_NAME: "DESCRIPTION" ENV_VAR=VALUE ENV_VAR='VALUE'`
|
12
|
+
# help:
|
13
|
+
# help: Will run all we write as a ruby command and will keep the session values.
|
14
|
+
# help: SESSION_NAME only admits from a to Z, numbers, - and _
|
15
|
+
# help: If no SESSION_NAME supplied it will be treated as a temporary REPL
|
16
|
+
# help: If 'private' specified the repl will be accessible only by you and it will be displayed only to you when `see repls`
|
17
|
+
# help: To avoid a message to be treated, start the message with '-'.
|
18
|
+
# help: Send _quit_, _bye_ or _exit_ to finish the session.
|
19
|
+
# help: Send puts, print, p or pp if you want to print out something when using `run repl` later.
|
20
|
+
# help: After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
21
|
+
# 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: By default it will be automatically loaded the gems: string_pattern, nice_hash and nice_http
|
23
|
+
# 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
|
24
|
+
# help: If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
25
|
+
# help: You can supply the Environmental Variables you need for the Session
|
26
|
+
# help: Examples:
|
27
|
+
# help: _repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
28
|
+
# help: _repl CreateCustomer: "It creates a random customer for testing" LOCATION=spain HOST='https://10.30.40.50:8887'_
|
29
|
+
# help: _repl delete_logs_
|
30
|
+
# help: _private repl random-ssn_
|
31
|
+
# help:
|
32
|
+
def repl(dest, user, session_name, env_vars, rules_file, command, description, type)
|
33
|
+
#todo: add more tests
|
34
|
+
from = user.name
|
35
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
36
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
37
|
+
else
|
38
|
+
if !@repl_sessions.key?(from)
|
39
|
+
save_stats(__method__)
|
40
|
+
Dir.mkdir("#{config.path}/repl") unless Dir.exist?("#{config.path}/repl")
|
41
|
+
Dir.mkdir("#{config.path}/repl/#{@channel_id}") unless Dir.exist?("#{config.path}/repl/#{@channel_id}")
|
42
|
+
|
43
|
+
serialt = Time.now.strftime("%Y%m%d%H%M%S%N")
|
44
|
+
if session_name.to_s==''
|
45
|
+
session_name = "#{from}_#{serialt}"
|
46
|
+
temp_repl = true
|
47
|
+
else
|
48
|
+
temp_repl = false
|
49
|
+
i = 0
|
50
|
+
name = session_name
|
51
|
+
while File.exist?("#{config.path}/repl/#{@channel_id}/#{session_name}.input")
|
52
|
+
i+=1
|
53
|
+
session_name = "#{name}#{i}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@repl_sessions[from] = {
|
57
|
+
name: session_name,
|
58
|
+
dest: dest,
|
59
|
+
started: Time.now,
|
60
|
+
finished: Time.now,
|
61
|
+
input: [],
|
62
|
+
on_thread: Thread.current[:on_thread],
|
63
|
+
thread_ts: Thread.current[:thread_ts]
|
64
|
+
}
|
65
|
+
|
66
|
+
unless temp_repl
|
67
|
+
@repls[session_name] = {
|
68
|
+
created: @repl_sessions[from][:started].to_s,
|
69
|
+
accessed: @repl_sessions[from][:started].to_s,
|
70
|
+
creator_name: user.name,
|
71
|
+
creator_id: user.id,
|
72
|
+
description: description,
|
73
|
+
type: type,
|
74
|
+
runs_by_creator: 0,
|
75
|
+
runs_by_others: 0,
|
76
|
+
gets: 0
|
77
|
+
}
|
78
|
+
update_repls()
|
79
|
+
end
|
80
|
+
|
81
|
+
message = "Session name: *#{session_name}*
|
82
|
+
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`.
|
83
|
+
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`.
|
84
|
+
If you want to avoid a message to be treated by me, start the message with '-'.
|
85
|
+
After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
86
|
+
If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
87
|
+
You can supply the Environmental Variables you need for the Session
|
88
|
+
Example:
|
89
|
+
_repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
90
|
+
"
|
91
|
+
respond message, dest
|
92
|
+
|
93
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", "", mode: "a+")
|
94
|
+
File.write("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.output", "", mode: "a+")
|
95
|
+
|
96
|
+
process_to_run = '
|
97
|
+
ruby -e "' + env_vars.join("\n") + '
|
98
|
+
require \"awesome_print\"
|
99
|
+
bindme' + serialt + ' = binding
|
100
|
+
eval(\"require \'nice_http\'\" , bindme' + serialt + ')
|
101
|
+
|
102
|
+
file_input_repl = File.open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.input\", \"r\")
|
103
|
+
while true do
|
104
|
+
sleep 0.2
|
105
|
+
if File.exist?(\"./.smart-bot-repl\")
|
106
|
+
begin
|
107
|
+
eval(File.read(\"./.smart-bot-repl\"), bindme' + serialt + ')
|
108
|
+
rescue Exception => resp_repl
|
109
|
+
end
|
110
|
+
end
|
111
|
+
code_to_run_repl = file_input_repl.read
|
112
|
+
if code_to_run_repl.to_s!=''
|
113
|
+
if code_to_run_repl.to_s.match?(/^quit$/i) or
|
114
|
+
code_to_run_repl.to_s.match?(/^exit$/i) or
|
115
|
+
code_to_run_repl.to_s.match?(/^bye bot$/i) or
|
116
|
+
code_to_run_repl.to_s.match?(/^bye$/i)
|
117
|
+
exit
|
118
|
+
else
|
119
|
+
if code_to_run_repl.match?(/^\s*ls\s+(.+)/)
|
120
|
+
code_to_run_repl = \"#{code_to_run_repl.scan(/^\s*ls\s+(.+)/).join}.methods - Object.methods\"
|
121
|
+
end
|
122
|
+
begin
|
123
|
+
code_to_run_repl.gsub!(/^\s*(puts|print|p|pp)\s/, \"\")
|
124
|
+
resp_repl = eval(code_to_run_repl.to_s, bindme' + serialt + ')
|
125
|
+
rescue Exception => resp_repl
|
126
|
+
end
|
127
|
+
if resp_repl.to_s != \"\"
|
128
|
+
open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.output\", \"a+\") {|f|
|
129
|
+
f.puts \"\`\`\`#{resp_repl.awesome_inspect}\`\`\`\"
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end"
|
135
|
+
'
|
136
|
+
|
137
|
+
unless rules_file.empty? # to get the project_folder
|
138
|
+
begin
|
139
|
+
eval(File.new(config.path+rules_file).read) if File.exist?(config.path+rules_file)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
started = Time.now
|
143
|
+
process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
|
144
|
+
|
145
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3(process_to_run)
|
146
|
+
timeout = 30 * 60 # 30 minutes
|
147
|
+
|
148
|
+
file_output_repl = File.open("#{config.path}/repl/#{@channel_id}/#{session_name}.output", "r")
|
149
|
+
|
150
|
+
while (wait_thr.status == 'run' or wait_thr.status == 'sleep') and @repl_sessions.key?(from)
|
151
|
+
begin
|
152
|
+
if (Time.now-@repl_sessions[from][:finished]) > timeout
|
153
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", 'a+') {|f|
|
154
|
+
f.puts 'quit'
|
155
|
+
}
|
156
|
+
respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
|
157
|
+
@repl_sessions.delete(from)
|
158
|
+
break
|
159
|
+
end
|
160
|
+
sleep 0.2
|
161
|
+
resp_repl = file_output_repl.read
|
162
|
+
if resp_repl.to_s!=''
|
163
|
+
respond resp_repl, dest
|
164
|
+
end
|
165
|
+
rescue Exception => excp
|
166
|
+
@logger.fatal excp
|
167
|
+
end
|
168
|
+
end
|
169
|
+
else
|
170
|
+
@repl_sessions[from][:finished] = Time.now
|
171
|
+
code = @repl_sessions[from][:command]
|
172
|
+
@repl_sessions[from][:command] = ''
|
173
|
+
code.gsub!("\\n", "\n")
|
174
|
+
code.gsub!("\\r", "\r")
|
175
|
+
# Disabled for the moment sinde it is deleting lines with '}'
|
176
|
+
#code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting.
|
177
|
+
if code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
178
|
+
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
|
179
|
+
code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
|
180
|
+
code.include?("ENV") or code.match?(/=\s*IO/)
|
181
|
+
respond "Sorry I cannot run this due security reasons", dest
|
182
|
+
else
|
183
|
+
@repl_sessions[from][:input]<<code
|
184
|
+
case code
|
185
|
+
when /^\s*(quit|exit|bye|bye bot)\s*$/i
|
186
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", 'a+') {|f|
|
187
|
+
f.puts code
|
188
|
+
}
|
189
|
+
respond "REPL session finished: #{@repl_sessions[from][:name]}", dest
|
190
|
+
@repl_sessions.delete(from)
|
191
|
+
when /^\s*-/i
|
192
|
+
#ommit
|
193
|
+
else
|
194
|
+
open("#{config.path}/repl/#{@channel_id}/#{@repl_sessions[from][:name]}.input", 'a+') {|f|
|
195
|
+
f.puts code
|
196
|
+
}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -7,43 +7,47 @@ class SlackSmartBot
|
|
7
7
|
# help: _ruby require 'json'; res=[]; 20.times {res<<rand(100)}; my_json={result: res}; puts my_json.to_json_
|
8
8
|
# help:
|
9
9
|
|
10
|
-
def ruby_code(dest, code, rules_file)
|
10
|
+
def ruby_code(dest, user, code, rules_file)
|
11
11
|
save_stats(__method__)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
if config[:allow_access].key?(__method__) and !config[:allow_access][__method__].include?(user.name) and !config[:allow_access][__method__].include?(user.id)
|
13
|
+
respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
|
14
|
+
else
|
15
|
+
unless code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
16
|
+
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
|
17
|
+
code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
|
18
|
+
code.include?("ENV") or code.match?(/=\s*IO/)
|
19
|
+
unless rules_file.empty?
|
20
|
+
begin
|
21
|
+
eval(File.new(config.path+rules_file).read) if File.exist?(config.path+rules_file)
|
22
|
+
end
|
19
23
|
end
|
20
|
-
end
|
21
24
|
|
22
|
-
|
25
|
+
respond "Running", dest if code.size > 100
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
begin
|
28
|
+
code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting
|
29
|
+
ruby = "ruby -e \"#{code.gsub('"', '\"')}\""
|
30
|
+
if defined?(project_folder) and project_folder.to_s != "" and Dir.exist?(project_folder)
|
31
|
+
ruby = ("cd #{project_folder} &&" + ruby)
|
32
|
+
else
|
33
|
+
def project_folder() "" end
|
34
|
+
end
|
35
|
+
stdout, stderr, status = Open3.capture3(ruby)
|
36
|
+
if stderr == ""
|
37
|
+
if stdout == ""
|
38
|
+
respond "Nothing returned. Remember you need to use p or puts to print", dest
|
39
|
+
else
|
40
|
+
respond stdout, dest
|
41
|
+
end
|
36
42
|
else
|
37
|
-
respond stdout, dest
|
43
|
+
respond "#{stderr}\n#{stdout}", dest
|
38
44
|
end
|
39
|
-
|
40
|
-
respond
|
45
|
+
rescue Exception => exc
|
46
|
+
respond exc, dest
|
41
47
|
end
|
42
|
-
|
43
|
-
respond
|
48
|
+
else
|
49
|
+
respond "Sorry I cannot run this due security reasons", dest
|
44
50
|
end
|
45
|
-
else
|
46
|
-
respond "Sorry I cannot run this due security reasons", dest
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|