slack-smart-bot 1.6.4 → 1.7.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 +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
|