slack-smart-bot 1.6.5 → 1.8.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 +8 -1
- data/lib/slack-smart-bot.rb +3 -8
- data/lib/slack-smart-bot_general_rules.rb +33 -0
- data/lib/slack-smart-bot_rules.rb +80 -84
- data/lib/slack/smart-bot/comm.rb +2 -1
- data/lib/slack/smart-bot/comm/respond.rb +1 -1
- data/lib/slack/smart-bot/comm/send_file.rb +28 -12
- data/lib/slack/smart-bot/comm/unreact.rb +16 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +24 -5
- data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/bot_stats.rb +36 -4
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +19 -32
- 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 +10 -6
- data/lib/slack/smart-bot/treat_message.rb +7 -12
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +25 -3
- data/lib/slack/smart-bot/utils/get_help.rb +5 -1
- metadata +18 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b15c46b5b101a0a31487508457982e8f5d6b81ad41f54338407ecdb2aa9974f3
|
4
|
+
data.tar.gz: d32bfceda9068f5f11d1002f255b77a280f3a7b7068f40a632c03b7cb6378127
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61c6e4060d928a1562176a0596ac968c7d007998c268816af489a0d36624a768ba1eadd3b6d27be7d19d37984b335d70215f718189165c1a9ac0a3a18130c5a0
|
7
|
+
data.tar.gz: 48995f9d416dd8906353508ac9bf86219cd92b2ede2f0043c3752dcc4db95564161ad64f41d86fd9f821fa1dc6d9d5bba3ef5519be037214e0003c3423b595c9
|
data/README.md
CHANGED
@@ -124,6 +124,7 @@ def rules(user, command, processed, dest)
|
|
124
124
|
respond "zZzzzzzZZZZZZzzzzzzz!"
|
125
125
|
react :sleeping
|
126
126
|
sleep 10
|
127
|
+
unreact :sleeping
|
127
128
|
react :sunny
|
128
129
|
when /no/i, /nope/i, /cancel/i
|
129
130
|
@questions.delete(from)
|
@@ -152,6 +153,8 @@ def rules(user, command, processed, dest)
|
|
152
153
|
else
|
153
154
|
respond "#{user.name}: #{stdout} #{stderr}"
|
154
155
|
end
|
156
|
+
|
157
|
+
unreact :runner
|
155
158
|
|
156
159
|
else
|
157
160
|
unless processed
|
@@ -159,8 +162,11 @@ def rules(user, command, processed, dest)
|
|
159
162
|
end
|
160
163
|
end
|
161
164
|
end
|
162
|
-
|
163
165
|
```
|
166
|
+
|
167
|
+
Also you can add general rules that will be available on all Smart Bot channels to `./rules/general_rules.rb`
|
168
|
+
|
169
|
+
|
164
170
|
### How to access the Smart Bot
|
165
171
|
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
172
|
|
@@ -388,6 +394,7 @@ Examples:
|
|
388
394
|
>**_`add routine run_tests every 3h !run tests on customers`_**
|
389
395
|
>**_`add routine clean_db at 17:05 !clean customers temp db`_**
|
390
396
|
>**_`add silent routine clean_db at 17:05 !clean customers temp db`_**
|
397
|
+
>**_`add routine clean_custdb on Mondays at 05:00 !clean customers db`_**
|
391
398
|
|
392
399
|
Also instead of adding a Command to be executed, you can attach a file, then the routine will be created and the attached file will be executed on the criteria specified. Only Master Admins are allowed to use it this way.
|
393
400
|
|
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,33 @@
|
|
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: `INTEGER echo SOMETHING`
|
12
|
+
# help: repeats SOMETHING. If INTEGER supplied then that number of times.
|
13
|
+
# help: Examples:
|
14
|
+
# help: _echo I am the Smart Bot_
|
15
|
+
# help: _100 echo :heart:_
|
16
|
+
when /^(\d*)\s*echo\s(.+)/i
|
17
|
+
save_stats :echo
|
18
|
+
$1.to_s == '' ? times = 1 : times = $1.to_i
|
19
|
+
respond ($2*times).to_s
|
20
|
+
|
21
|
+
else
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
return true
|
25
|
+
rescue => exception
|
26
|
+
if defined?(@logger)
|
27
|
+
@logger.fatal exception
|
28
|
+
respond "Unexpected error!! Please contact an admin to solve it: <@#{ADMIN_USERS.join(">, <@")}>"
|
29
|
+
else
|
30
|
+
puts exception
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -38,102 +38,98 @@ 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
|
+
unreact :sleeping
|
64
|
+
react :sunny
|
65
|
+
when /no/i, /nope/i, /cancel/i
|
66
|
+
@questions.delete(from)
|
67
|
+
respond "Thanks, I'm happy to be awake"
|
68
|
+
else
|
69
|
+
respond "I don't understand"
|
70
|
+
ask "are you sure do you want me to sleep? (yes or no)"
|
71
|
+
end
|
77
72
|
end
|
78
|
-
end
|
79
73
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
74
|
+
# help: ----------------------------------------------
|
75
|
+
# help: `run something`
|
76
|
+
# help: It will run the process and report the results when done
|
77
|
+
# help:
|
78
|
+
when /^run something/i
|
79
|
+
save_stats :run_something
|
80
|
+
react :runner
|
87
81
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
if
|
93
|
-
|
82
|
+
process_to_run = "ruby -v"
|
83
|
+
process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
|
84
|
+
stdout, stderr, status = Open3.capture3(process_to_run)
|
85
|
+
unreact :runner
|
86
|
+
if stderr == ""
|
87
|
+
if stdout == ""
|
88
|
+
respond "#{display_name}: Nothing returned."
|
89
|
+
else
|
90
|
+
respond "#{display_name}: #{stdout}"
|
91
|
+
end
|
94
92
|
else
|
95
|
-
respond "#{display_name}: #{stdout}"
|
93
|
+
respond "#{display_name}: #{stdout} #{stderr}"
|
96
94
|
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'
|
95
|
+
|
96
|
+
# Emoticons you can use with `react` command https://www.webfx.com/tools/emoji-cheat-sheet/
|
97
|
+
|
98
|
+
# Examples for respond and respond_direct
|
99
|
+
# # send 'the message' to the channel or direct message where the command was written
|
100
|
+
# respond "the message"
|
101
|
+
# # send 'the message' privately as a direct message to the user that sent the command
|
102
|
+
# respond_direct "the message"
|
103
|
+
# # send 'the message' to a specific channel name
|
104
|
+
# respond "the message", 'my_channel'
|
105
|
+
# # send 'the message' to a specific channel id
|
106
|
+
# respond "the message", 'CSU34D33'
|
107
|
+
# # send 'the message' to a specific user as direct message
|
108
|
+
# respond "the message", '@theuser'
|
109
|
+
# # send 'the message' to a specific user id as direct message
|
110
|
+
# respond "the message", 'US3344D3'
|
116
111
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
112
|
+
# Example downloading a file from slack
|
113
|
+
# if !files.nil? and files.size == 1 and files[0].filetype == 'yaml'
|
114
|
+
# require 'nice_http'
|
115
|
+
# http = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config[:token]}" })
|
116
|
+
# http.get(files[0].url_private_download, save_data: './tmp/')
|
117
|
+
# end
|
123
118
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
# Examples sending a file to slack:
|
120
|
+
# send_file(to, msg, filepath, title, format, type = "text")
|
121
|
+
# send_file(dest, 'the message', "#{project_folder}/temp/logs_ptBI.log", 'title', 'text/plain', "text")
|
122
|
+
# send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'title', 'image/jpeg', "jpg")
|
128
123
|
|
129
124
|
|
130
|
-
|
131
|
-
|
132
|
-
|
125
|
+
else
|
126
|
+
unless processed
|
127
|
+
dont_understand()
|
128
|
+
end
|
133
129
|
end
|
130
|
+
rescue => exception
|
131
|
+
@logger.fatal exception
|
132
|
+
respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
|
134
133
|
end
|
135
|
-
rescue => exception
|
136
|
-
@logger.fatal exception
|
137
|
-
respond "Unexpected error!! Please contact an admin to solve it: <@#{config.admins.join(">, <@")}>"
|
138
134
|
end
|
139
135
|
end
|
data/lib/slack/smart-bot/comm.rb
CHANGED
@@ -38,7 +38,7 @@ class SlackSmartBot
|
|
38
38
|
f.puts "|#{dest}|#{config[:nick_id]}|#{msg}"
|
39
39
|
}
|
40
40
|
end
|
41
|
-
elsif dest[0] == "D" or dest[0] == "U" # Direct message
|
41
|
+
elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
|
42
42
|
send_msg_user(dest, msg)
|
43
43
|
elsif dest[0] == "@"
|
44
44
|
begin
|
@@ -3,9 +3,12 @@ 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]
|
8
|
-
if
|
10
|
+
file = 'myfile' if file.to_s == '' and content!=''
|
11
|
+
if to[0] == "U" or to[0] == "W" #user
|
9
12
|
im = client.web_client.im_open(user: to)
|
10
13
|
channel = im["channel"]["id"]
|
11
14
|
else
|
@@ -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
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# list of available emojis: https://www.webfx.com/tools/emoji-cheat-sheet/
|
3
|
+
# unreact(:thumbsup)
|
4
|
+
def unreact(emoji, parent=false)
|
5
|
+
if parent
|
6
|
+
ts = Thread.current[:thread_ts]
|
7
|
+
else
|
8
|
+
ts = Thread.current[:ts]
|
9
|
+
end
|
10
|
+
begin
|
11
|
+
client.web_client.reactions_remove(channel: Thread.current[:dest], name: emoji, timestamp: ts)
|
12
|
+
rescue Exception => stack
|
13
|
+
@logger.warn stack
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,6 +5,7 @@ class SlackSmartBot
|
|
5
5
|
# helpadmin: `add silent routine NAME every NUMBER PERIOD`
|
6
6
|
# helpadmin: `create routine NAME every NUMBER PERIOD`
|
7
7
|
# helpadmin: `add routine NAME at TIME COMMAND`
|
8
|
+
# helpadmin: `add routine NAME on DAYWEEK at TIME COMMAND`
|
8
9
|
# helpadmin: `add routine NAME at TIME`
|
9
10
|
# helpadmin: `add silent routine NAME at TIME`
|
10
11
|
# helpadmin: `create routine NAME at TIME`
|
@@ -15,12 +16,14 @@ class SlackSmartBot
|
|
15
16
|
# helpadmin: NUMBER: Integer
|
16
17
|
# helpadmin: PERIOD: days, d, hours, h, minutes, mins, min, m, seconds, secs, sec, s
|
17
18
|
# helpadmin: TIME: time at format HH:MM:SS
|
19
|
+
# helpadmin: DAYWEEK: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. And their plurals.
|
18
20
|
# helpadmin: COMMAND: any valid smart bot command or rule
|
19
21
|
# helpadmin: Examples:
|
20
22
|
# helpadmin: _add routine example every 30s ruby puts 'a'_
|
21
23
|
# helpadmin: _add routine example every 3 days ruby puts 'a'_
|
22
24
|
# helpadmin: _add routine example at 17:05 ruby puts 'a'_
|
23
25
|
# helpadmin: _create silent routine every 12 hours !Run customer tests_
|
26
|
+
# helpadmin: _add routine example on Mondays at 05:00 !run customer tests_
|
24
27
|
# helpadmin:
|
25
28
|
def add_routine(dest, from, user, name, type, number_time, period, command_to_run, files, silent)
|
26
29
|
save_stats(__method__)
|
@@ -30,13 +33,14 @@ class SlackSmartBot
|
|
30
33
|
respond "I'm sorry but there is already a routine with that name.\nCall `see routines` to see added routines", dest
|
31
34
|
else
|
32
35
|
number_time += ":00" if number_time.split(":").size == 2
|
33
|
-
if (type
|
36
|
+
if (type != "every") && !number_time.match?(/^[01][0-9]:[0-5][0-9]:[0-5][0-9]$/) &&
|
34
37
|
!number_time.match?(/^2[0-3]:[0-5][0-9]:[0-5][0-9]$/)
|
35
38
|
respond "Wrong time specified: *#{number_time}*"
|
36
39
|
else
|
37
40
|
file_path = ""
|
38
41
|
every = ""
|
39
42
|
at = ""
|
43
|
+
dayweek = ''
|
40
44
|
next_run = Time.now
|
41
45
|
case period.downcase
|
42
46
|
when "days", "d"
|
@@ -52,16 +56,31 @@ class SlackSmartBot
|
|
52
56
|
every = "#{number_time} seconds"
|
53
57
|
every_in_seconds = number_time.to_i
|
54
58
|
else # time
|
59
|
+
if type != 'at'
|
60
|
+
dayweek = type.downcase
|
61
|
+
days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday']
|
62
|
+
incr = days.index(dayweek) - Time.now.wday
|
63
|
+
if incr < 0
|
64
|
+
incr = (7+incr)*24*60*60
|
65
|
+
else
|
66
|
+
incr = incr * 24 * 60 * 60
|
67
|
+
end
|
68
|
+
days = incr/(24*60*60)
|
69
|
+
every_in_seconds = 7 * 24 * 60 * 60 # one week
|
70
|
+
else
|
71
|
+
days = 0
|
72
|
+
every_in_seconds = 24 * 60 * 60 # one day
|
73
|
+
end
|
74
|
+
|
55
75
|
at = number_time
|
56
|
-
if next_run.strftime("%H:%M:%S") < number_time
|
76
|
+
if next_run.strftime("%H:%M:%S") < number_time and days == 0
|
57
77
|
nt = number_time.split(":")
|
58
78
|
next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
|
59
79
|
else
|
60
|
-
next_run += (24 * 60 * 60) # one more
|
80
|
+
next_run += ((24 * 60 * 60) * days) # one or more days
|
61
81
|
nt = number_time.split(":")
|
62
82
|
next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
|
63
83
|
end
|
64
|
-
every_in_seconds = 24 * 60 * 60
|
65
84
|
end
|
66
85
|
Dir.mkdir("#{config.path}/routines/#{@channel_id}") unless Dir.exist?("#{config.path}/routines/#{@channel_id}")
|
67
86
|
|
@@ -78,7 +97,7 @@ class SlackSmartBot
|
|
78
97
|
|
79
98
|
@routines[@channel_id] = {} unless @routines.key?(@channel_id)
|
80
99
|
@routines[@channel_id][name] = { channel_name: config.channel, creator: from, creator_id: user.id, status: :on,
|
81
|
-
every: every, every_in_seconds: every_in_seconds, at: at, file_path: file_path,
|
100
|
+
every: every, every_in_seconds: every_in_seconds, at: at, dayweek: dayweek, file_path: file_path,
|
82
101
|
command: command_to_run.to_s.strip, silent: silent,
|
83
102
|
next_run: next_run.to_s, dest: dest, last_run: "", last_elapsed: "",
|
84
103
|
running: false }
|
@@ -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
|
@@ -44,6 +44,7 @@ class SlackSmartBot
|
|
44
44
|
msg << "\tStatus: #{v[:status]}"
|
45
45
|
msg << "\tEvery: #{v[:every]}" unless v[:every] == ""
|
46
46
|
msg << "\tAt: #{v[:at]}" unless v[:at] == ""
|
47
|
+
msg << "\tOn: #{v[:dayweek]}" unless !v.key?(:dayweek) or v[:dayweek].to_s == ""
|
47
48
|
msg << "\tNext Run: #{v[:next_run]}"
|
48
49
|
msg << "\tLast Run: #{v[:last_run]}"
|
49
50
|
msg << "\tTime consumed on last run: #{v[:last_elapsed]}" unless v[:command] !=''
|
@@ -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 from 2020-01-01 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 = []
|
@@ -34,6 +36,10 @@ class SlackSmartBot
|
|
34
36
|
if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
|
35
37
|
message<<'No stats'
|
36
38
|
else
|
39
|
+
if user!=''
|
40
|
+
user_info = client.web_client.users_info(user: user)
|
41
|
+
user_name = user_info.user.name
|
42
|
+
end
|
37
43
|
from = "#{Time.now.strftime("%Y-%m")}-01" if from == ''
|
38
44
|
to = "#{Time.now.strftime("%Y-%m-%d")}" if to == ''
|
39
45
|
from_short = from
|
@@ -43,17 +49,28 @@ class SlackSmartBot
|
|
43
49
|
from+= " 00:00:00 +0000"
|
44
50
|
to+= " 23:59:59 +0000"
|
45
51
|
rows = []
|
52
|
+
rows_month = {}
|
53
|
+
users_month = {}
|
54
|
+
commands_month = {}
|
46
55
|
|
47
56
|
Dir["#{config.stats_path}.*.log"].sort.each do |file|
|
48
57
|
if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
|
49
58
|
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
|
50
59
|
row[:date] = row[:date].to_s
|
51
60
|
if !exclude_masters or (exclude_masters and !config.masters.include?(row[:user_name]))
|
52
|
-
if user=='' or (user!='' and row[:
|
61
|
+
if user=='' or (user!='' and row[:user_name] == user_name)
|
53
62
|
if exclude_command == '' or (exclude_command!='' and row[:command]!=exclude_command)
|
54
63
|
if row[:bot_channel_id] == channel_id or channel_id == ''
|
55
64
|
if row[:date] >= from and row[:date] <= to
|
56
65
|
rows << row.to_h
|
66
|
+
if monthly
|
67
|
+
rows_month[row[:date][0..6]] = 0 unless rows_month.key?(row[:date][0..6])
|
68
|
+
users_month[row[:date][0..6]] = [] unless users_month.key?(row[:date][0..6])
|
69
|
+
commands_month[row[:date][0..6]] = [] unless commands_month.key?(row[:date][0..6])
|
70
|
+
rows_month[row[:date][0..6]] += 1
|
71
|
+
users_month[row[:date][0..6]] << row[:user_name]
|
72
|
+
commands_month[row[:date][0..6]] << row[:command]
|
73
|
+
end
|
57
74
|
end
|
58
75
|
end
|
59
76
|
end
|
@@ -79,6 +96,21 @@ class SlackSmartBot
|
|
79
96
|
message << "*Total calls <##{channel_id}>*: #{total} from #{from_short} to #{to_short}"
|
80
97
|
end
|
81
98
|
if total > 0
|
99
|
+
if monthly
|
100
|
+
message << '*Totals by month / commands / users (%new)*'
|
101
|
+
all_users = []
|
102
|
+
new_users = []
|
103
|
+
rows_month.each do |k,v|
|
104
|
+
if all_users.empty?
|
105
|
+
message_new_users = ''
|
106
|
+
else
|
107
|
+
new_users = (users_month[k]-all_users).uniq
|
108
|
+
message_new_users = "(#{new_users.size*100/users_month[k].uniq.size}%)"
|
109
|
+
end
|
110
|
+
all_users += users_month[k]
|
111
|
+
message << "\t#{k}: #{v} (#{(v.to_f*100/total).round(2)}%) / #{commands_month[k].uniq.size} / #{users_month[k].uniq.size} #{message_new_users}"
|
112
|
+
end
|
113
|
+
end
|
82
114
|
|
83
115
|
if channel_id == ''
|
84
116
|
message << "*Channels*"
|
@@ -89,16 +121,16 @@ class SlackSmartBot
|
|
89
121
|
end
|
90
122
|
end
|
91
123
|
if user==''
|
92
|
-
message << "*Users*"
|
93
124
|
users = rows.user_name.uniq.sort
|
125
|
+
message << "*Users* - #{users.size}"
|
94
126
|
users.each do |user|
|
95
127
|
count = rows.count {|h| h.user_name==user}
|
96
128
|
message << "\t#{user}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
97
129
|
end
|
98
130
|
end
|
99
131
|
|
100
|
-
message << "*Commands*"
|
101
132
|
commands = rows.command.uniq.sort
|
133
|
+
message << "*Commands* - #{commands.size}"
|
102
134
|
commands.each do |command|
|
103
135
|
count = rows.count {|h| h.command==command}
|
104
136
|
message << "\t#{command}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
@@ -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,34 +101,8 @@ class SlackSmartBot
|
|
100
101
|
require \"amazing_print\"
|
101
102
|
bindme' + serialt + ' = binding
|
102
103
|
eval(\"require \'nice_http\'\" , bindme' + serialt + ')
|
103
|
-
def repl_params(met)
|
104
|
-
res = []
|
105
|
-
met.parameters.each do |par|
|
106
|
-
if par[0]==:req
|
107
|
-
res << par[1].to_s
|
108
|
-
elsif par[0]==:keyreq
|
109
|
-
res << par[1].to_s + \":\"
|
110
|
-
elsif par[0]==:key
|
111
|
-
res << \"?\"+par[1].to_s + \":\"
|
112
|
-
elsif par[0]==:opt
|
113
|
-
res << \"?\"+par[1].to_s
|
114
|
-
elsif par[0]==:rest
|
115
|
-
res << \"*\"+par[1].to_s
|
116
|
-
elsif par[0]==:keyrest
|
117
|
-
res << \"**\"+par[1].to_s
|
118
|
-
else
|
119
|
-
res << par[1].to_s
|
120
|
-
end
|
121
|
-
end
|
122
|
-
\"(#{res.join(\", \")})\"
|
123
|
-
end
|
124
104
|
def ls(obj)
|
125
|
-
|
126
|
-
res = []
|
127
|
-
mets.each do |met|
|
128
|
-
res << \"#{met}#{repl_params(obj.method(met))}\"
|
129
|
-
end
|
130
|
-
res
|
105
|
+
(obj.methods - Object.methods)
|
131
106
|
end
|
132
107
|
|
133
108
|
file_input_repl = File.open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.input\", \"r\")
|
@@ -158,9 +133,15 @@ class SlackSmartBot
|
|
158
133
|
error = true
|
159
134
|
end
|
160
135
|
if resp_repl.to_s != \"\"
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
164
145
|
unless error or !add_to_run_repl
|
165
146
|
open(\"' + Dir.pwd + '/repl/' + @channel_id + '/' + session_name + '.run\", \"a+\") {|f|
|
166
147
|
f.puts code_to_run_repl
|
@@ -198,7 +179,13 @@ class SlackSmartBot
|
|
198
179
|
sleep 0.2
|
199
180
|
resp_repl = file_output_repl.read
|
200
181
|
if resp_repl.to_s!=''
|
201
|
-
|
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
|
202
189
|
end
|
203
190
|
rescue Exception => excp
|
204
191
|
@logger.fatal excp
|
@@ -210,7 +197,7 @@ class SlackSmartBot
|
|
210
197
|
@repl_sessions[from][:command] = ''
|
211
198
|
code.gsub!("\\n", "\n")
|
212
199
|
code.gsub!("\\r", "\r")
|
213
|
-
# Disabled for the moment
|
200
|
+
# Disabled for the moment since it is deleting lines with '}'
|
214
201
|
#code.gsub!(/^\W*$/, "") #to remove special chars from slack when copy/pasting.
|
215
202
|
if code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
216
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
|
@@ -70,7 +70,8 @@ class SlackSmartBot
|
|
70
70
|
channel = $1
|
71
71
|
kill_bot_on_channel(dest, from, channel)
|
72
72
|
when /^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+(every)\s+(\d+)\s*(days|hours|minutes|seconds|mins|min|secs|sec|d|h|m|s)\s*(\s.+)?\s*$/i,
|
73
|
-
|
73
|
+
/^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+on\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)s?\s+at\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i,
|
74
|
+
/^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i
|
74
75
|
silent = $2.to_s!=''
|
75
76
|
name = $3.downcase
|
76
77
|
type = $4
|
@@ -105,12 +106,15 @@ class SlackSmartBot
|
|
105
106
|
st_to = st_to.gsub('.','-').gsub('/','-')
|
106
107
|
st_user = opts.scan(/<@([^>]+)>/).join
|
107
108
|
exclude_masters = opts.match?(/exclude\s+masters?/i)
|
109
|
+
monthly = false
|
108
110
|
if all_opts.include?('today')
|
109
111
|
st_from = st_to = "#{Time.now.strftime("%Y-%m-%d")}"
|
112
|
+
elsif all_opts.include?('monthly')
|
113
|
+
monthly = true
|
110
114
|
end
|
111
115
|
exclude_command = opts.scan(/exclude\s+([^\s]+)/i).join
|
112
116
|
exclude_command = '' if exclude_command == 'masters'
|
113
|
-
bot_stats(dest, from, typem, st_channel, st_from, st_to, st_user, exclude_masters, exclude_command)
|
117
|
+
bot_stats(dest, from, typem, st_channel, st_from, st_to, st_user, exclude_masters, exclude_command, monthly)
|
114
118
|
else
|
115
119
|
processed = false
|
116
120
|
end
|
@@ -166,11 +170,11 @@ class SlackSmartBot
|
|
166
170
|
ruby_code(dest, user, code, rules_file)
|
167
171
|
when /^\s*(private\s+)?(repl|irb|live)\s*()()()$/i,
|
168
172
|
/^\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
|
173
|
+
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s+"([^"]+)"()\s*$/i,
|
174
|
+
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)\s*:\s+"([^"]+)"\s+(.+)\s*$/i,
|
171
175
|
/^\s*(private\s+)?(repl|irb|live)\s+([\w\-]+)()\s+(.+)\s*$/i,
|
172
176
|
/^\s*(private\s+)?(repl|irb|live)()\s+()(.+)\s*$/i
|
173
|
-
|
177
|
+
if $1.to_s!=''
|
174
178
|
type = :private
|
175
179
|
else
|
176
180
|
type = :public
|
@@ -206,7 +210,7 @@ class SlackSmartBot
|
|
206
210
|
end
|
207
211
|
run_repl(dest, user, session_name, env_vars.flatten, rules_file)
|
208
212
|
when /^\s*(delete|remove)\s+(repl|irb|live)\s+([\w\-]+)\s*$/i
|
209
|
-
repl_name = $3
|
213
|
+
repl_name = $3
|
210
214
|
delete_repl(dest, user, repl_name)
|
211
215
|
when /^\s*see\s+(repls|repl|irb|irbs)\s*$/i
|
212
216
|
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
|
@@ -115,6 +117,7 @@ class SlackSmartBot
|
|
115
117
|
begin
|
116
118
|
#todo: when changed @questions user_id then move user_info inside the ifs to avoid calling it when not necessary
|
117
119
|
user_info = client.web_client.users_info(user: data.user)
|
120
|
+
user_info.user.id = data.user #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
|
118
121
|
if @questions.key?(user_info.user.name)
|
119
122
|
if data.text.match?(/^\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i)
|
120
123
|
@questions.delete(user_info.user.name)
|
@@ -127,12 +130,8 @@ class SlackSmartBot
|
|
127
130
|
((@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts == @repl_sessions[user_info.user.name][:thread_ts]) or
|
128
131
|
(!@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts.to_s == '' ))
|
129
132
|
|
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
|
133
|
+
if data.text.match(/^\s*```(.*)```\s*$/im)
|
134
|
+
@repl_sessions[user_info.user.name][:command] = $1
|
136
135
|
else
|
137
136
|
@repl_sessions[user_info.user.name][:command] = data.text
|
138
137
|
end
|
@@ -142,12 +141,8 @@ class SlackSmartBot
|
|
142
141
|
end
|
143
142
|
|
144
143
|
#when added special characters on the message
|
145
|
-
if command.
|
146
|
-
|
147
|
-
command = ''
|
148
|
-
else
|
149
|
-
command = command[3..-4]
|
150
|
-
end
|
144
|
+
if command.match(/^\s*```(.*)```\s*$/im)
|
145
|
+
command = $1
|
151
146
|
elsif command.size >= 2 and
|
152
147
|
((command[0] == "`" and command[-1] == "`") or (command[0] == "*" and command[-1] == "*") or (command[0] == "_" and command[-1] == "_"))
|
153
148
|
command = command[1..-2]
|
@@ -13,7 +13,6 @@ class SlackSmartBot
|
|
13
13
|
ruby = ""
|
14
14
|
end
|
15
15
|
@routines[@channel_id][name][:silent] = false if !@routines[@channel_id][name].key?(:silent)
|
16
|
-
|
17
16
|
if @routines[@channel_id][name][:at] == "" or
|
18
17
|
(@routines[@channel_id][name][:at] != "" and @routines[@channel_id][name][:running] and
|
19
18
|
@routines[@channel_id][name][:next_run] != "" and Time.now.to_s >= @routines[@channel_id][name][:next_run])
|
@@ -55,11 +54,34 @@ class SlackSmartBot
|
|
55
54
|
require "time"
|
56
55
|
every_in_seconds = Time.parse(@routines[@channel_id][name][:next_run]) - Time.now
|
57
56
|
elsif @routines[@channel_id][name][:at] != "" #coming from start after pause for 'at'
|
58
|
-
if
|
57
|
+
if @routines[@channel_id][name].key?(:dayweek) and @routines[@channel_id][name][:dayweek].to_s!=''
|
58
|
+
day = @routines[@channel_id][name][:dayweek]
|
59
|
+
days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday']
|
60
|
+
incr = days.index(day) - Time.now.wday
|
61
|
+
if incr < 0
|
62
|
+
incr = (7+incr)*24*60*60
|
63
|
+
else
|
64
|
+
incr = incr * 24 * 60 * 60
|
65
|
+
end
|
66
|
+
days = incr/(24*60*60)
|
67
|
+
weekly = true
|
68
|
+
else
|
69
|
+
days = 0
|
70
|
+
weekly = false
|
71
|
+
end
|
72
|
+
|
73
|
+
if started.strftime("%H:%M:%S") < @routines[@channel_id][name][:at] and days == 0
|
59
74
|
nt = @routines[@channel_id][name][:at].split(":")
|
60
75
|
next_run = Time.new(started.year, started.month, started.day, nt[0], nt[1], nt[2])
|
61
76
|
else
|
62
|
-
|
77
|
+
if days == 0 and started.strftime("%H:%M:%S") >= @routines[@channel_id][name][:at]
|
78
|
+
if weekly
|
79
|
+
days = 7
|
80
|
+
else
|
81
|
+
days = 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
next_run = started + (days * 24 * 60 * 60) # one more day/week
|
63
85
|
nt = @routines[@channel_id][name][:at].split(":")
|
64
86
|
next_run = Time.new(next_run.year, next_run.month, next_run.day, nt[0], nt[1], nt[2])
|
65
87
|
end
|
@@ -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,35 +1,35 @@
|
|
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.8.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-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slack-ruby-client
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.14'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
19
|
+
version: 0.15.0
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0.15'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0.14'
|
30
27
|
- - ">="
|
31
28
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
29
|
+
version: 0.15.0
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.15'
|
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.2.1
|
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.2.1
|
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
|
@@ -129,6 +136,7 @@ files:
|
|
129
136
|
- lib/slack/smart-bot/comm/send_file.rb
|
130
137
|
- lib/slack/smart-bot/comm/send_msg_channel.rb
|
131
138
|
- lib/slack/smart-bot/comm/send_msg_user.rb
|
139
|
+
- lib/slack/smart-bot/comm/unreact.rb
|
132
140
|
- lib/slack/smart-bot/commands.rb
|
133
141
|
- lib/slack/smart-bot/commands/general/bot_help.rb
|
134
142
|
- lib/slack/smart-bot/commands/general/bot_status.rb
|