slack-smart-bot 1.6.4 → 1.7.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 +4 -1
- data/lib/slack-smart-bot.rb +3 -8
- data/lib/slack-smart-bot_general_rules.rb +30 -0
- data/lib/slack-smart-bot_rules.rb +78 -84
- data/lib/slack/smart-bot/comm/send_file.rb +27 -11
- data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/admin_master/bot_stats.rb +14 -1
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +25 -8
- data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +12 -3
- data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +1 -1
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +5 -0
- data/lib/slack/smart-bot/process.rb +8 -5
- data/lib/slack/smart-bot/treat_message.rb +6 -12
- data/lib/slack/smart-bot/utils/get_help.rb +5 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd95efb0ac282a17d1b463fe28293643c0b38b91b3261e0d3899e879950e4655
|
4
|
+
data.tar.gz: 1d332d2651286f4bef95c1172d95bc6ce422166b50bf788773563747ebbf1c30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f48dc2999a22da392d297cb789dfcc7552ce1ef7aad607283f705d39af5eac58ce2ca002b844178184e6bacdc13fe641ddbe762f8a999b17da7532a5cad234b8
|
7
|
+
data.tar.gz: f4ac49668234f24295e79afd842218e40a1a918c1107392af84d3b31c6d8908fadb8319f2e4596ef896c44e7c36665714523fc554f4c8b70a3a5a1f02cc2c872
|
data/README.md
CHANGED
@@ -159,8 +159,11 @@ def rules(user, command, processed, dest)
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
end
|
162
|
-
|
163
162
|
```
|
163
|
+
|
164
|
+
Also you can add general rules that will be available on all Smart Bot channels to `./rules/general_rules.rb`
|
165
|
+
|
166
|
+
|
164
167
|
### How to access the Smart Bot
|
165
168
|
You can access the bot directly on the MASTER CHANNEL, on a secondary channel where the bot is running and directly by opening a private chat with the bot, in this case the conversation will be just between you and the bot.
|
166
169
|
|
data/lib/slack-smart-bot.rb
CHANGED
@@ -36,13 +36,7 @@ class SlackSmartBot
|
|
36
36
|
else
|
37
37
|
config[:path] = '.'
|
38
38
|
end
|
39
|
-
|
40
|
-
config[:silent] = true
|
41
|
-
elsif ENV['BOT_SILENT'].to_s == 'false'
|
42
|
-
config[:silent] = false
|
43
|
-
else
|
44
|
-
config[:silent] = false unless config.key?(:silent)
|
45
|
-
end
|
39
|
+
config[:silent] = false unless config.key?(:silent)
|
46
40
|
config[:testing] = false unless config.key?(:testing)
|
47
41
|
config[:simulate] = false unless config.key?(:simulate)
|
48
42
|
config[:stats] = false unless config.key?(:stats)
|
@@ -210,7 +204,8 @@ class SlackSmartBot
|
|
210
204
|
if version_remote != VERSION
|
211
205
|
version_message = ". There is a new available version: #{version_remote}."
|
212
206
|
end
|
213
|
-
|
207
|
+
if !config[:silent] or ENV['BOT_SILENT'].to_s == 'false'
|
208
|
+
ENV['BOT_SILENT'] = 'true' if config[:silent] == 'true' and ENV['BOT_SILENT'].to_s != 'true'
|
214
209
|
respond "Smart Bot started v#{VERSION}#{version_message}\nIf you want to know what I can do for you: `bot help`.\n`bot rules` if you want to display just the specific rules of this channel.\nYou can talk to me privately if you prefer it."
|
215
210
|
end
|
216
211
|
@routines.each do |ch, rout|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# add here the general rules you will be using in all Smart Bots
|
2
|
+
def general_rules(user, command, processed, dest, files = [], rules_file = "")
|
3
|
+
from = user.name
|
4
|
+
display_name = user.profile.display_name
|
5
|
+
|
6
|
+
begin
|
7
|
+
case command
|
8
|
+
|
9
|
+
# help: ----------------------------------------------
|
10
|
+
# help: `echo SOMETHING`
|
11
|
+
# help: repeats SOMETHING
|
12
|
+
# help: Examples:
|
13
|
+
# help: _echo I am the Smart Bot_
|
14
|
+
when /^echo\s(.+)/i
|
15
|
+
save_stats :echo
|
16
|
+
respond $1
|
17
|
+
|
18
|
+
else
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
return true
|
22
|
+
rescue => exception
|
23
|
+
if defined?(@logger)
|
24
|
+
@logger.fatal exception
|
25
|
+
respond "Unexpected error!! Please contact an admin to solve it: <@#{ADMIN_USERS.join(">, <@")}>"
|
26
|
+
else
|
27
|
+
puts exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -38,102 +38,96 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
|
|
38
38
|
from = user.name
|
39
39
|
display_name = user.profile.display_name
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
load "#{config.path}/rules/general_rules.rb"
|
42
|
+
|
43
|
+
unless general_rules(user, command, processed, dest, files, rules_file)
|
44
|
+
begin
|
45
|
+
case command
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
react :monkey_face
|
53
|
-
|
54
|
-
# help: ----------------------------------------------
|
55
|
-
# help: `go to sleep`
|
56
|
-
# help: it will sleep the bot for 5 seconds
|
57
|
-
# help:
|
58
|
-
when /^go\sto\ssleep/i
|
59
|
-
save_stats :to_to_sleep
|
60
|
-
unless @questions.keys.include?(from)
|
61
|
-
ask "do you want me to take a siesta?"
|
62
|
-
else
|
63
|
-
case @questions[from]
|
64
|
-
when /yes/i, /yep/i, /sure/i
|
65
|
-
@questions.delete(from)
|
66
|
-
respond "I'll be sleeping for 5 secs... just for you"
|
67
|
-
respond "zZzzzzzZZZZZZzzzzzzz!"
|
68
|
-
react :sleeping
|
69
|
-
sleep 5
|
70
|
-
react :sunny
|
71
|
-
when /no/i, /nope/i, /cancel/i
|
72
|
-
@questions.delete(from)
|
73
|
-
respond "Thanks, I'm happy to be awake"
|
47
|
+
# help: ----------------------------------------------
|
48
|
+
# help: `go to sleep`
|
49
|
+
# help: it will sleep the bot for 5 seconds
|
50
|
+
# help:
|
51
|
+
when /^go\sto\ssleep/i
|
52
|
+
save_stats :go_to_sleep
|
53
|
+
unless @questions.keys.include?(from)
|
54
|
+
ask "do you want me to take a siesta?"
|
74
55
|
else
|
75
|
-
|
76
|
-
|
56
|
+
case @questions[from]
|
57
|
+
when /yes/i, /yep/i, /sure/i
|
58
|
+
@questions.delete(from)
|
59
|
+
respond "I'll be sleeping for 5 secs... just for you"
|
60
|
+
respond "zZzzzzzZZZZZZzzzzzzz!"
|
61
|
+
react :sleeping
|
62
|
+
sleep 5
|
63
|
+
react :sunny
|
64
|
+
when /no/i, /nope/i, /cancel/i
|
65
|
+
@questions.delete(from)
|
66
|
+
respond "Thanks, I'm happy to be awake"
|
67
|
+
else
|
68
|
+
respond "I don't understand"
|
69
|
+
ask "are you sure do you want me to sleep? (yes or no)"
|
70
|
+
end
|
77
71
|
end
|
78
|
-
end
|
79
72
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
73
|
+
# help: ----------------------------------------------
|
74
|
+
# help: `run something`
|
75
|
+
# help: It will run the process and report the results when done
|
76
|
+
# help:
|
77
|
+
when /^run something/i
|
78
|
+
save_stats :run_something
|
79
|
+
react :runner
|
87
80
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
81
|
+
process_to_run = "ruby -v"
|
82
|
+
process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
|
83
|
+
stdout, stderr, status = Open3.capture3(process_to_run)
|
84
|
+
if stderr == ""
|
85
|
+
if stdout == ""
|
86
|
+
respond "#{display_name}: Nothing returned."
|
87
|
+
else
|
88
|
+
respond "#{display_name}: #{stdout}"
|
89
|
+
end
|
94
90
|
else
|
95
|
-
respond "#{display_name}: #{stdout}"
|
91
|
+
respond "#{display_name}: #{stdout} #{stderr}"
|
96
92
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
# respond "the message", '@theuser'
|
114
|
-
# # send 'the message' to a specific user id as direct message
|
115
|
-
# respond "the message", 'US3344D3'
|
93
|
+
|
94
|
+
# Emoticons you can use with `react` command https://www.webfx.com/tools/emoji-cheat-sheet/
|
95
|
+
|
96
|
+
# Examples for respond and respond_direct
|
97
|
+
# # send 'the message' to the channel or direct message where the command was written
|
98
|
+
# respond "the message"
|
99
|
+
# # send 'the message' privately as a direct message to the user that sent the command
|
100
|
+
# respond_direct "the message"
|
101
|
+
# # send 'the message' to a specific channel name
|
102
|
+
# respond "the message", 'my_channel'
|
103
|
+
# # send 'the message' to a specific channel id
|
104
|
+
# respond "the message", 'CSU34D33'
|
105
|
+
# # send 'the message' to a specific user as direct message
|
106
|
+
# respond "the message", '@theuser'
|
107
|
+
# # send 'the message' to a specific user id as direct message
|
108
|
+
# respond "the message", 'US3344D3'
|
116
109
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
110
|
+
# Example downloading a file from slack
|
111
|
+
# if !files.nil? and files.size == 1 and files[0].filetype == 'yaml'
|
112
|
+
# require 'nice_http'
|
113
|
+
# http = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config[:token]}" })
|
114
|
+
# http.get(files[0].url_private_download, save_data: './tmp/')
|
115
|
+
# end
|
123
116
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
117
|
+
# Examples sending a file to slack:
|
118
|
+
# send_file(to, msg, filepath, title, format, type = "text")
|
119
|
+
# send_file(dest, 'the message', "#{project_folder}/temp/logs_ptBI.log", 'title', 'text/plain', "text")
|
120
|
+
# send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'title', 'image/jpeg', "jpg")
|
128
121
|
|
129
122
|
|
130
|
-
|
131
|
-
|
132
|
-
|
123
|
+
else
|
124
|
+
unless processed
|
125
|
+
dont_understand()
|
126
|
+
end
|
133
127
|
end
|
128
|
+
rescue => exception
|
129
|
+
@logger.fatal exception
|
130
|
+
respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
|
134
131
|
end
|
135
|
-
rescue => exception
|
136
|
-
@logger.fatal exception
|
137
|
-
respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
|
138
132
|
end
|
139
133
|
end
|
@@ -3,8 +3,11 @@ class SlackSmartBot
|
|
3
3
|
#to send a file to an user or channel
|
4
4
|
#send_file(dest, 'the message', "#{project_folder}/temp/logs_ptBI.log", 'message to be sent', 'text/plain', "text")
|
5
5
|
#send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'message to be sent', 'image/jpeg', "jpg")
|
6
|
-
|
6
|
+
#send_file(dest, 'the message', "", 'message to be sent', 'text/plain', "ruby", content: "the content to be sent when no file supplied")
|
7
|
+
#send_file(dest, 'the message', "myfile.rb", 'message to be sent', 'text/plain', "ruby", content: "the content to be sent when no file supplied")
|
8
|
+
def send_file(to, msg, file, title, format, type = "text", content: '')
|
7
9
|
unless config[:simulate]
|
10
|
+
file = 'myfile' if file.to_s == '' and content!=''
|
8
11
|
if to[0] == "U" #user
|
9
12
|
im = client.web_client.im_open(user: to)
|
10
13
|
channel = im["channel"]["id"]
|
@@ -18,16 +21,29 @@ class SlackSmartBot
|
|
18
21
|
ts = nil
|
19
22
|
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
if content.to_s == ''
|
25
|
+
client.web_client.files_upload(
|
26
|
+
channels: channel,
|
27
|
+
as_user: true,
|
28
|
+
file: Faraday::UploadIO.new(file, format),
|
29
|
+
title: title,
|
30
|
+
filename: file,
|
31
|
+
filetype: type,
|
32
|
+
initial_comment: msg,
|
33
|
+
thread_ts: ts
|
34
|
+
)
|
35
|
+
else
|
36
|
+
client.web_client.files_upload(
|
37
|
+
channels: channel,
|
38
|
+
as_user: true,
|
39
|
+
content: content,
|
40
|
+
title: title,
|
41
|
+
filename: file,
|
42
|
+
filetype: type,
|
43
|
+
initial_comment: msg,
|
44
|
+
thread_ts: ts
|
45
|
+
)
|
46
|
+
end
|
31
47
|
end
|
32
48
|
end
|
33
49
|
|
@@ -54,7 +54,7 @@ class SlackSmartBot
|
|
54
54
|
respond "Now the rules from <##{@channel_id}> are available on *<##{@channels_id[channel]}>*", dest
|
55
55
|
end
|
56
56
|
respond "<@#{user.id}> extended the rules from <##{@channel_id}> to this channel so now you can talk to the Smart Bot on demand using those rules.", @channels_id[channel]
|
57
|
-
respond "Use `!` before the command you want to run", @channels_id[channel]
|
57
|
+
respond "Use `!` or `^` or `!!` before the command you want to run", @channels_id[channel]
|
58
58
|
respond "To see the specific rules for this bot on this channel: `!bot rules` or `!bot rules COMMAND`", @channels_id[channel]
|
59
59
|
end
|
60
60
|
end
|
@@ -13,6 +13,7 @@ class SlackSmartBot
|
|
13
13
|
# helpadmin: `bot stats CHANNEL exclude masters from YYYY/MM/DD to YYYY/MM/DD`
|
14
14
|
# helpadmin: `bot stats today`
|
15
15
|
# helpadmin: `bot stats exclude COMMAND_ID`
|
16
|
+
# helpadmin: `bot stats monthly`
|
16
17
|
# helpadmin: To see the bot stats
|
17
18
|
# helpadmin: You can use this command only if you are a Master admin user and if you are in a private conversation with the bot
|
18
19
|
# helpadmin: You need to set stats to true to generate the stats when running the bot instance.
|
@@ -21,8 +22,9 @@ class SlackSmartBot
|
|
21
22
|
# helpadmin: _bot stats @peter.wind_
|
22
23
|
# helpadmin: _bot stats #sales from 2019/12/15 to 2019/12/31_
|
23
24
|
# helpadmin: _bot stats #sales today_
|
25
|
+
# helpadmin: _bot stats #sales monthly_
|
24
26
|
# helpadmin:
|
25
|
-
def bot_stats(dest, from_user, typem, channel_id, from, to, user, exclude_masters, exclude_command)
|
27
|
+
def bot_stats(dest, from_user, typem, channel_id, from, to, user, exclude_masters, exclude_command, monthly)
|
26
28
|
require 'csv'
|
27
29
|
if config.stats
|
28
30
|
message = []
|
@@ -43,6 +45,7 @@ class SlackSmartBot
|
|
43
45
|
from+= " 00:00:00 +0000"
|
44
46
|
to+= " 23:59:59 +0000"
|
45
47
|
rows = []
|
48
|
+
rows_month = {}
|
46
49
|
|
47
50
|
Dir["#{config.stats_path}.*.log"].sort.each do |file|
|
48
51
|
if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
|
@@ -54,6 +57,10 @@ class SlackSmartBot
|
|
54
57
|
if row[:bot_channel_id] == channel_id or channel_id == ''
|
55
58
|
if row[:date] >= from and row[:date] <= to
|
56
59
|
rows << row.to_h
|
60
|
+
if monthly
|
61
|
+
rows_month[row[:date][0..6]] = 0 unless rows_month.key?(row[:date][0..6])
|
62
|
+
rows_month[row[:date][0..6]] += 1
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
@@ -79,6 +86,12 @@ class SlackSmartBot
|
|
79
86
|
message << "*Total calls <##{channel_id}>*: #{total} from #{from_short} to #{to_short}"
|
80
87
|
end
|
81
88
|
if total > 0
|
89
|
+
if monthly
|
90
|
+
message << '*Totals by month*'
|
91
|
+
rows_month.each do |k,v|
|
92
|
+
message << "\t#{k}: #{v} (#{(v.to_f*100/total).round(2)}%)"
|
93
|
+
end
|
94
|
+
end
|
82
95
|
|
83
96
|
if channel_id == ''
|
84
97
|
message << "*Channels*"
|
@@ -82,6 +82,7 @@ class SlackSmartBot
|
|
82
82
|
message = "Session name: *#{session_name}*
|
83
83
|
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`.
|
84
84
|
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`.
|
85
|
+
Use `p` to print a message raw, exacly like it is returned.
|
85
86
|
If you want to avoid a message to be treated by me, start the message with '-'.
|
86
87
|
After 30 minutes of no communication with the Smart Bot the session will be dismissed.
|
87
88
|
If you want to see the methods of a class or module you created use _ls TheModuleOrClass_
|
@@ -100,7 +101,10 @@ class SlackSmartBot
|
|
100
101
|
require \"amazing_print\"
|
101
102
|
bindme' + serialt + ' = binding
|
102
103
|
eval(\"require \'nice_http\'\" , bindme' + serialt + ')
|
103
|
-
|
104
|
+
def ls(obj)
|
105
|
+
(obj.methods - Object.methods)
|
106
|
+
end
|
107
|
+
|
104
108
|
file_input_repl = File.open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.input\", \"r\")
|
105
109
|
if File.exist?(\"./.smart-bot-repl\")
|
106
110
|
begin
|
@@ -112,6 +116,7 @@ class SlackSmartBot
|
|
112
116
|
sleep 0.2
|
113
117
|
code_to_run_repl = file_input_repl.read
|
114
118
|
if code_to_run_repl.to_s!=''
|
119
|
+
add_to_run_repl = true
|
115
120
|
if code_to_run_repl.to_s.match?(/^quit$/i) or
|
116
121
|
code_to_run_repl.to_s.match?(/^exit$/i) or
|
117
122
|
code_to_run_repl.to_s.match?(/^bye bot$/i) or
|
@@ -119,7 +124,7 @@ class SlackSmartBot
|
|
119
124
|
exit
|
120
125
|
else
|
121
126
|
if code_to_run_repl.match?(/^\s*ls\s+(.+)/)
|
122
|
-
|
127
|
+
add_to_run_repl = false
|
123
128
|
end
|
124
129
|
error = false
|
125
130
|
begin
|
@@ -128,10 +133,16 @@ class SlackSmartBot
|
|
128
133
|
error = true
|
129
134
|
end
|
130
135
|
if resp_repl.to_s != \"\"
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
136
|
+
if code_to_run_repl.match?(/^\s*p\s+/i)
|
137
|
+
open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.output\", \"a+\") {|f|
|
138
|
+
f.puts \"\`\`\`\n#{resp_repl.inspect}\n\`\`\`\"
|
139
|
+
}
|
140
|
+
else
|
141
|
+
open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.output\", \"a+\") {|f|
|
142
|
+
f.puts \"\`\`\`\n#{resp_repl.ai}\n\`\`\`\"
|
143
|
+
}
|
144
|
+
end
|
145
|
+
unless error or !add_to_run_repl
|
135
146
|
open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.run\", \"a+\") {|f|
|
136
147
|
f.puts code_to_run_repl
|
137
148
|
}
|
@@ -168,7 +179,13 @@ class SlackSmartBot
|
|
168
179
|
sleep 0.2
|
169
180
|
resp_repl = file_output_repl.read
|
170
181
|
if resp_repl.to_s!=''
|
171
|
-
|
182
|
+
if resp_repl.to_s.lines.count < 60 and resp_repl.to_s.size < 3500
|
183
|
+
respond resp_repl, dest
|
184
|
+
else
|
185
|
+
resp_repl.gsub!(/^\s*```/,'')
|
186
|
+
resp_repl.gsub!(/```\s*$/,'')
|
187
|
+
send_file(dest, "", 'response.rb', "", 'text/plain', "ruby", content: resp_repl)
|
188
|
+
end
|
172
189
|
end
|
173
190
|
rescue Exception => excp
|
174
191
|
@logger.fatal excp
|
@@ -180,7 +197,7 @@ class SlackSmartBot
|
|
180
197
|
@repl_sessions[from][:command] = ''
|
181
198
|
code.gsub!("\\n", "\n")
|
182
199
|
code.gsub!("\\r", "\r")
|
183
|
-
# Disabled for the moment
|
200
|
+
# Disabled for the moment since it is deleting lines with '}'
|
184
201
|
#code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting.
|
185
202
|
if code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
186
203
|
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
|
@@ -52,7 +52,7 @@ class SlackSmartBot
|
|
52
52
|
Dir.mkdir("#{project_folder}/tmp") unless Dir.exist?("#{project_folder}/tmp")
|
53
53
|
Dir.mkdir("#{project_folder}/tmp/repl") unless Dir.exist?("#{project_folder}/tmp/repl")
|
54
54
|
File.write("#{project_folder}/tmp/repl/#{session_name}.rb", content, mode: "w+")
|
55
|
-
process_to_run = "ruby
|
55
|
+
process_to_run = "ruby ./tmp/repl/#{session_name}.rb"
|
56
56
|
process_to_run = ("cd #{project_folder} && #{process_to_run}") if defined?(project_folder)
|
57
57
|
respond "Running REPL #{session_name}"
|
58
58
|
stdout, stderr, status = Open3.capture3(process_to_run)
|
@@ -60,10 +60,19 @@ class SlackSmartBot
|
|
60
60
|
if stdout == ""
|
61
61
|
respond "*#{session_name}*: Nothing returned."
|
62
62
|
else
|
63
|
-
|
63
|
+
if stdout.to_s.lines.count < 60 and stdout.to_s.size < 3500
|
64
|
+
respond "*#{session_name}*: #{stdout}"
|
65
|
+
else
|
66
|
+
send_file(dest, "", 'response.rb', "", 'text/plain', "ruby", content: stdout)
|
67
|
+
end
|
64
68
|
end
|
65
69
|
else
|
66
|
-
|
70
|
+
if (stdout.to_s+stderr.to_s).lines.count < 60
|
71
|
+
respond "*#{session_name}*: #{stdout} #{stderr}"
|
72
|
+
else
|
73
|
+
send_file(dest, "", 'response.rb', "", 'text/plain', "ruby", content: (stdout.to_s+stderr.to_s))
|
74
|
+
end
|
75
|
+
|
67
76
|
end
|
68
77
|
end
|
69
78
|
else
|
@@ -15,7 +15,7 @@ class SlackSmartBot
|
|
15
15
|
message = ""
|
16
16
|
@repls.sort.to_h.each do |session_name, repl|
|
17
17
|
if (repl.creator_name == user.name or repl.type == :public) or (config.admins.include?(user.name) and typem == :on_dm)
|
18
|
-
message += "(#{repl.type}) *#{session_name}*: #{repl.description} / created: #{repl.created} / accessed: #{repl.accessed} / creator: #{repl.
|
18
|
+
message += "(#{repl.type}) *#{session_name}*: #{repl.description} / created: #{repl.created} / accessed: #{repl.accessed} / creator: #{repl.creator_name} / runs: #{repl.runs_by_creator+repl.runs_by_others} / gets: #{repl.gets} \n"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
message = "No repls created" if message == ''
|
@@ -46,14 +46,19 @@ class SlackSmartBot
|
|
46
46
|
rules_file = "slack-smart-bot_rules_#{channel_id}_#{from.gsub(" ", "_")}.rb"
|
47
47
|
if defined?(RULES_FOLDER)
|
48
48
|
rules_file = RULES_FOLDER + rules_file
|
49
|
+
general_rules_file = RULES_FOLDER + 'general_rules.rb'
|
49
50
|
else
|
50
51
|
Dir.mkdir("#{config.path}/rules") unless Dir.exist?("#{config.path}/rules")
|
51
52
|
Dir.mkdir("#{config.path}/rules/#{channel_id}") unless Dir.exist?("#{config.path}/rules/#{channel_id}")
|
52
53
|
rules_file = "/rules/#{channel_id}/" + rules_file
|
54
|
+
general_rules_file = "/rules/general_rules.rb"
|
53
55
|
end
|
54
56
|
default_rules = (__FILE__).gsub(/slack\/smart-bot\/commands\/on_master\/create_bot\.rb$/, "slack-smart-bot_rules.rb")
|
57
|
+
default_general_rules = (__FILE__).gsub(/slack\/smart-bot\/commands\/on_master\/create_bot\.rb$/, "slack-smart-bot_general_rules.rb")
|
58
|
+
|
55
59
|
File.delete(config.path + rules_file) if File.exist?(config.path + rules_file)
|
56
60
|
FileUtils.copy_file(default_rules, config.path + rules_file) unless File.exist?(config.path + rules_file)
|
61
|
+
FileUtils.copy_file(default_general_rules, config.path + general_rules_file) unless File.exist?(config.path + general_rules_file)
|
57
62
|
admin_users = Array.new()
|
58
63
|
creator_info = client.web_client.users_info(user: channel_found.creator)
|
59
64
|
admin_users = [from, creator_info.user.name] + config.masters
|
@@ -105,12 +105,15 @@ class SlackSmartBot
|
|
105
105
|
st_to = st_to.gsub('.','-').gsub('/','-')
|
106
106
|
st_user = opts.scan(/<@([^>]+)>/).join
|
107
107
|
exclude_masters = opts.match?(/exclude\s+masters?/i)
|
108
|
+
monthly = false
|
108
109
|
if all_opts.include?('today')
|
109
110
|
st_from = st_to = "#{Time.now.strftime("%Y-%m-%d")}"
|
111
|
+
elsif all_opts.include?('monthly')
|
112
|
+
monthly = true
|
110
113
|
end
|
111
114
|
exclude_command = opts.scan(/exclude\s+([^\s]+)/i).join
|
112
115
|
exclude_command = '' if exclude_command == 'masters'
|
113
|
-
bot_stats(dest, from, typem, st_channel, st_from, st_to, st_user, exclude_masters, exclude_command)
|
116
|
+
bot_stats(dest, from, typem, st_channel, st_from, st_to, st_user, exclude_masters, exclude_command, monthly)
|
114
117
|
else
|
115
118
|
processed = false
|
116
119
|
end
|
@@ -166,11 +169,11 @@ class SlackSmartBot
|
|
166
169
|
ruby_code(dest, user, code, rules_file)
|
167
170
|
when /^\s*(private\s+)?(repl|irb|live)\s*()()()$/i,
|
168
171
|
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)()()\s*$/i,
|
169
|
-
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s
|
170
|
-
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s
|
172
|
+
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s+"([^"]+)"()\s*$/i,
|
173
|
+
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s+"([^"]+)"\s+(.+)\s*$/i,
|
171
174
|
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)()\s+(.+)\s*$/i,
|
172
175
|
/^\s*(private\s+)?(repl|irb|live)()\s+()(.+)\s*$/i
|
173
|
-
|
176
|
+
if $1.to_s!=''
|
174
177
|
type = :private
|
175
178
|
else
|
176
179
|
type = :public
|
@@ -206,7 +209,7 @@ class SlackSmartBot
|
|
206
209
|
end
|
207
210
|
run_repl(dest, user, session_name, env_vars.flatten, rules_file)
|
208
211
|
when /^\s*(delete|remove)\s+(repl|irb|live)\s+([\w\-]+)\s*$/i
|
209
|
-
repl_name = $3
|
212
|
+
repl_name = $3
|
210
213
|
delete_repl(dest, user, repl_name)
|
211
214
|
when /^\s*see\s+(repls|repl|irb|irbs)\s*$/i
|
212
215
|
see_repls(dest, user, typem)
|
@@ -32,6 +32,8 @@ class SlackSmartBot
|
|
32
32
|
data.text = CGI.unescapeHTML(data.text)
|
33
33
|
data.text.gsub!("\u00A0", " ") #to change (asc char 160) into blank space
|
34
34
|
end
|
35
|
+
data.text.gsub!('’', "'")
|
36
|
+
data.text.gsub!('“', '"')
|
35
37
|
rescue
|
36
38
|
@logger.warn "Impossible to unescape or clean format for data.text:#{data.text}"
|
37
39
|
end
|
@@ -127,12 +129,8 @@ class SlackSmartBot
|
|
127
129
|
((@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts == @repl_sessions[user_info.user.name][:thread_ts]) or
|
128
130
|
(!@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts.to_s == '' ))
|
129
131
|
|
130
|
-
if data.text.
|
131
|
-
|
132
|
-
@repl_sessions[user_info.user.name][:command] = ""
|
133
|
-
else
|
134
|
-
@repl_sessions[user_info.user.name][:command] = data.text[3..-4]
|
135
|
-
end
|
132
|
+
if data.text.match(/^\s*```(.*)```\s*$/im)
|
133
|
+
@repl_sessions[user_info.user.name][:command] = $1
|
136
134
|
else
|
137
135
|
@repl_sessions[user_info.user.name][:command] = data.text
|
138
136
|
end
|
@@ -142,12 +140,8 @@ class SlackSmartBot
|
|
142
140
|
end
|
143
141
|
|
144
142
|
#when added special characters on the message
|
145
|
-
if command.
|
146
|
-
|
147
|
-
command = ''
|
148
|
-
else
|
149
|
-
command = command[3..-4]
|
150
|
-
end
|
143
|
+
if command.match(/^\s*```(.*)```\s*$/im)
|
144
|
+
command = $1
|
151
145
|
elsif command.size >= 2 and
|
152
146
|
((command[0] == "`" and command[-1] == "`") or (command[0] == "*" and command[-1] == "*") or (command[0] == "_" and command[-1] == "_"))
|
153
147
|
command = command[1..-2]
|
@@ -32,7 +32,11 @@ class SlackSmartBot
|
|
32
32
|
help = @help_messages.deep_copy
|
33
33
|
end
|
34
34
|
if rules_file != ""
|
35
|
-
help[:rules_file] =
|
35
|
+
help[:rules_file] = ''
|
36
|
+
help[:rules_file] += IO.readlines(config.path+rules_file).join.scan(/#\s*help\s*\w*:(.*)/i).join("\n") + "\n"
|
37
|
+
if File.exist?(config.path+'/rules/general_rules.rb')
|
38
|
+
help[:rules_file] += IO.readlines(config.path+'/rules/general_rules.rb').join.scan(/#\s*help\s*\w*:(.*)/i).join("\n")
|
39
|
+
end
|
36
40
|
end
|
37
41
|
help = remove_hash_keys(help, :admin_master) unless user_type == :admin_master
|
38
42
|
help = remove_hash_keys(help, :admin) unless user_type == :admin or user_type == :admin_master
|
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.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slack-ruby-client
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '0.14'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.14.
|
22
|
+
version: 0.14.6
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '0.14'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.14.
|
32
|
+
version: 0.14.6
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: nice_http
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,6 +79,9 @@ dependencies:
|
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '1'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 1.1.0
|
82
85
|
type: :runtime
|
83
86
|
prerelease: false
|
84
87
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -86,6 +89,9 @@ dependencies:
|
|
86
89
|
- - "~>"
|
87
90
|
- !ruby/object:Gem::Version
|
88
91
|
version: '1'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.1.0
|
89
95
|
- !ruby/object:Gem::Dependency
|
90
96
|
name: rspec
|
91
97
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,6 +125,7 @@ files:
|
|
119
125
|
- LICENSE
|
120
126
|
- README.md
|
121
127
|
- lib/slack-smart-bot.rb
|
128
|
+
- lib/slack-smart-bot_general_rules.rb
|
122
129
|
- lib/slack-smart-bot_rules.rb
|
123
130
|
- lib/slack/smart-bot/comm.rb
|
124
131
|
- lib/slack/smart-bot/comm/ask.rb
|