slack-smart-bot 1.4.3 → 1.5.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 +17 -1
- data/lib/slack-smart-bot.rb +7 -0
- data/lib/slack-smart-bot_rules.rb +13 -2
- data/lib/slack/smart-bot/comm.rb +2 -1
- data/lib/slack/smart-bot/comm/ask.rb +10 -2
- data/lib/slack/smart-bot/comm/dont_understand.rb +1 -0
- data/lib/slack/smart-bot/comm/react.rb +16 -0
- data/lib/slack/smart-bot/comm/respond.rb +10 -2
- data/lib/slack/smart-bot/comm/send_file.rb +6 -0
- data/lib/slack/smart-bot/comm/send_msg_channel.rb +5 -1
- data/lib/slack/smart-bot/comm/send_msg_user.rb +10 -2
- data/lib/slack/smart-bot/commands.rb +2 -0
- data/lib/slack/smart-bot/commands/general/bot_help.rb +3 -3
- data/lib/slack/smart-bot/commands/general/bot_status.rb +1 -0
- data/lib/slack/smart-bot/commands/general/bye_bot.rb +1 -0
- data/lib/slack/smart-bot/commands/general/hi_bot.rb +1 -0
- data/lib/slack/smart-bot/commands/general/stop_using_rules.rb +1 -0
- data/lib/slack/smart-bot/commands/general/use_rules.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/pause_bot.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/pause_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/bot_stats.rb +122 -0
- data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +18 -0
- data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +2 -1
- data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +1 -0
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +3 -2
- data/lib/slack/smart-bot/commands/on_master/admin/kill_bot_on_channel.rb +1 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +2 -1
- data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +1 -0
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +1 -0
- data/lib/slack/smart-bot/process.rb +29 -3
- data/lib/slack/smart-bot/process_first.rb +49 -12
- data/lib/slack/smart-bot/treat_message.rb +32 -9
- data/lib/slack/smart-bot/utils.rb +1 -0
- data/lib/slack/smart-bot/utils/get_help.rb +12 -6
- data/lib/slack/smart-bot/utils/save_stats.rb +32 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7276a93ba8921b2fc6fe95b31d883210acdf5668959f997f4605f4069f4d1050
|
4
|
+
data.tar.gz: '0389132b491c8c7e0d7ee58057b8499a0b5210ccb0b940bb3426aa2a5e2e56b3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df45b098eb49a96e57d7c5fb64aca50f28bfc663b6c6f1122d98ef01f3064705b4fbd136273cd53db167bd8fa735b253354a3f1b310525eacf86cd78b59c4dbb
|
7
|
+
data.tar.gz: 2fe9fceb4f7bce3423371abd2185d91e1debe2a37155390838de5d4d0d900d96ffc5264fc613a6d7f75dc6e1bfebd160e422897ec301c93d3b1972aa8507e3c3
|
data/README.md
CHANGED
@@ -106,6 +106,7 @@ def rules(user, command, processed, dest)
|
|
106
106
|
# help:
|
107
107
|
when /^echo\s(.+)/i
|
108
108
|
respond $1
|
109
|
+
react :monkey_face
|
109
110
|
|
110
111
|
# help: `go to sleep`
|
111
112
|
# help: it will sleep the bot for 10 seconds
|
@@ -119,7 +120,9 @@ def rules(user, command, processed, dest)
|
|
119
120
|
@questions.delete(from)
|
120
121
|
respond "I'll be sleeping for 10 secs... just for you"
|
121
122
|
respond "zZzzzzzZZZZZZzzzzzzz!"
|
123
|
+
react :sleeping
|
122
124
|
sleep 10
|
125
|
+
react :sunny
|
123
126
|
when /no/i, /nope/i, /cancel/i
|
124
127
|
@questions.delete(from)
|
125
128
|
respond "Thanks, I'm happy to be awake"
|
@@ -134,7 +137,7 @@ def rules(user, command, processed, dest)
|
|
134
137
|
# help: It will run the process and report the results when done
|
135
138
|
# help:
|
136
139
|
when /^run something/i
|
137
|
-
|
140
|
+
react :runner
|
138
141
|
|
139
142
|
process_to_run = "ruby -v"
|
140
143
|
stdout, stderr, status = Open3.capture3(process_to_run)
|
@@ -171,6 +174,9 @@ To run a command on demand:
|
|
171
174
|
**_`!THE_COMMAND`_**
|
172
175
|
**_`@NAME_OF_BOT THE_COMMAND`_**
|
173
176
|
**_`NAME_OF_BOT THE_COMMAND`_**
|
177
|
+
To run a command on demand and add the respond on a thread:
|
178
|
+
**_`^THE_COMMAND`_**
|
179
|
+
**_`!!THE_COMMAND`_**
|
174
180
|
|
175
181
|
Examples run a command on demand:
|
176
182
|
>**_Peter>_** `!ruby puts Time.now`
|
@@ -182,12 +188,18 @@ Examples run a command on demand:
|
|
182
188
|
>**_Peter>_** `smart-bot see shortcuts`
|
183
189
|
>**_Smart-Bot>_** `Available shortcuts for Peter:`
|
184
190
|
>`Spanish account: ruby require 'iso/iban'; 10.times {puts ISO::IBAN.random('ES')}`
|
191
|
+
>**_Peter>_** `!!echo Example`
|
192
|
+
> **_Smart-Bot>_** `Example`
|
193
|
+
>**_Peter>_** `^echo Example`
|
194
|
+
> **_Smart-Bot>_** `Example`
|
185
195
|
|
186
196
|
Also you can always call the Smart Bot from any channel, even from channels without a running Smart Bot. You can use the External Call on Demand: **_`@NAME_OF_BOT on #CHANNEL_NAME COMMAND`_**. In this case you will call the bot on #CHANNEL_NAME.
|
187
197
|
|
188
198
|
Example:
|
189
199
|
>**_Peter>_** `@smart-bot on #the_channel ruby puts Time.now`
|
190
200
|
>**_Smart-Bot>_** `2019-10-23 12:43:42 +0000`
|
201
|
+
>**_Peter>_** `@smart-bot on #the_channel ^ruby puts Time.now`
|
202
|
+
>**_Smart-Bot>_** `2019-10-23 12:43:42 +0000`
|
191
203
|
|
192
204
|
|
193
205
|
|
@@ -232,6 +244,10 @@ To see the status of the bots, on the MASTER CHANNEL: **_`bot status`_**
|
|
232
244
|
|
233
245
|
To close the Master Bot, run on MASTER CHANNEL: **_`exit bot`_**
|
234
246
|
|
247
|
+
If you are a Master Admin on a Direct Message with the Smart Bot you can call the **_`bot stats`_** and get use stats of the users. You need to set to <true> the `stats` settings when initializing the Smart Bot. Take a look at `bot help bot stats` for more info.
|
248
|
+
|
249
|
+
You can also get the bot logs of the bot channel you are using by calling `get bot logs`. You need to be a Master Admin user on a DM with the Smart Bot.
|
250
|
+
|
235
251
|
#### Cloud Bots
|
236
252
|
If you want to create a bot that will be running on a different machine: **_`create cloud bot on CHANNEL`_**. Even though the cloud bots are running on different machines, the management can be done through the MASTER CHANNEL. The new cloud bot will be managed by your Master Bot like the others, closing, pausing...
|
237
253
|
|
data/lib/slack-smart-bot.rb
CHANGED
@@ -45,6 +45,8 @@ class SlackSmartBot
|
|
45
45
|
end
|
46
46
|
config[:testing] = false unless config.key?(:testing)
|
47
47
|
config[:simulate] = false unless config.key?(:simulate)
|
48
|
+
config[:stats] = false unless config.key?(:stats)
|
49
|
+
|
48
50
|
if config.path.to_s!='' and config.file.to_s==''
|
49
51
|
config.file = File.basename($0)
|
50
52
|
end
|
@@ -55,6 +57,10 @@ class SlackSmartBot
|
|
55
57
|
config.file = File.basename(config.file_path)
|
56
58
|
config.path = File.dirname(config.file_path)
|
57
59
|
end
|
60
|
+
if config.stats
|
61
|
+
Dir.mkdir("#{config.path}/stats") unless Dir.exist?("#{config.path}/stats")
|
62
|
+
config.stats_path = "#{config.path}/stats/#{config.file.gsub(".rb", ".stats")}"
|
63
|
+
end
|
58
64
|
Dir.mkdir("#{config.path}/logs") unless Dir.exist?("#{config.path}/logs")
|
59
65
|
Dir.mkdir("#{config.path}/shortcuts") unless Dir.exist?("#{config.path}/shortcuts")
|
60
66
|
Dir.mkdir("#{config.path}/routines") unless Dir.exist?("#{config.path}/routines")
|
@@ -101,6 +107,7 @@ class SlackSmartBot
|
|
101
107
|
|
102
108
|
|
103
109
|
logfile = File.basename(config.rules_file.gsub("_rules_", "_logs_"), ".rb") + ".log"
|
110
|
+
config.log_file = logfile
|
104
111
|
@logger = Logger.new("#{config.path}/logs/#{logfile}")
|
105
112
|
|
106
113
|
config_log = config.dup
|
@@ -30,6 +30,9 @@ end
|
|
30
30
|
# help: `!THE_COMMAND`
|
31
31
|
# help: `@NAME_OF_BOT THE_COMMAND`
|
32
32
|
# help: `NAME_OF_BOT THE_COMMAND`
|
33
|
+
# help: To run a command on demand and add the respond on a thread:
|
34
|
+
# help: `^THE_COMMAND`
|
35
|
+
# help: `!!THE_COMMAND`
|
33
36
|
# help:
|
34
37
|
def rules(user, command, processed, dest, files = [], rules_file = "")
|
35
38
|
from = user.name
|
@@ -44,13 +47,16 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
|
|
44
47
|
# help: Examples:
|
45
48
|
# help: _echo I am the Smart Bot_
|
46
49
|
when /^echo\s(.+)/i
|
50
|
+
save_stats :echo
|
47
51
|
respond $1
|
52
|
+
react :monkey_face
|
48
53
|
|
49
54
|
# help: ----------------------------------------------
|
50
55
|
# help: `go to sleep`
|
51
56
|
# help: it will sleep the bot for 5 seconds
|
52
57
|
# help:
|
53
58
|
when /^go\sto\ssleep/i
|
59
|
+
save_stats :to_to_sleep
|
54
60
|
unless @questions.keys.include?(from)
|
55
61
|
ask "do you want me to take a siesta?"
|
56
62
|
else
|
@@ -59,7 +65,9 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
|
|
59
65
|
@questions.delete(from)
|
60
66
|
respond "I'll be sleeping for 5 secs... just for you"
|
61
67
|
respond "zZzzzzzZZZZZZzzzzzzz!"
|
68
|
+
react :sleeping
|
62
69
|
sleep 5
|
70
|
+
react :sunny
|
63
71
|
when /no/i, /nope/i, /cancel/i
|
64
72
|
@questions.delete(from)
|
65
73
|
respond "Thanks, I'm happy to be awake"
|
@@ -74,7 +82,8 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
|
|
74
82
|
# help: It will run the process and report the results when done
|
75
83
|
# help:
|
76
84
|
when /^run something/i
|
77
|
-
|
85
|
+
save_stats :run_something
|
86
|
+
react :runner
|
78
87
|
|
79
88
|
process_to_run = "ruby -v"
|
80
89
|
process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
|
@@ -88,7 +97,9 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
|
|
88
97
|
else
|
89
98
|
respond "#{display_name}: #{stdout} #{stderr}"
|
90
99
|
end
|
91
|
-
|
100
|
+
|
101
|
+
# Emoticons you can use with `react` command https://www.webfx.com/tools/emoji-cheat-sheet/
|
102
|
+
|
92
103
|
# Examples for respond and respond_direct
|
93
104
|
# # send 'the message' to the channel or direct message where the command was written
|
94
105
|
# respond "the message"
|
data/lib/slack/smart-bot/comm.rb
CHANGED
@@ -19,7 +19,11 @@ class SlackSmartBot
|
|
19
19
|
f.puts "|#{@channel_id}|#{config[:nick_id]}|#{message}~~~"
|
20
20
|
}
|
21
21
|
else
|
22
|
-
|
22
|
+
if Thread.current[:on_thread]
|
23
|
+
client.message(channel: @channel_id, text: message, as_user: true, thread_ts: Thread.current[:thread_ts])
|
24
|
+
else
|
25
|
+
client.message(channel: @channel_id, text: message, as_user: true)
|
26
|
+
end
|
23
27
|
end
|
24
28
|
if config[:testing] and config.on_master_bot
|
25
29
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -32,7 +36,11 @@ class SlackSmartBot
|
|
32
36
|
f.puts "|#{dest}|#{config[:nick_id]}|#{message}~~~"
|
33
37
|
}
|
34
38
|
else
|
35
|
-
|
39
|
+
if Thread.current[:on_thread]
|
40
|
+
client.message(channel: dest, text: message, as_user: true, thread_ts: Thread.current[:thread_ts])
|
41
|
+
else
|
42
|
+
client.message(channel: dest, text: message, as_user: true)
|
43
|
+
end
|
36
44
|
end
|
37
45
|
if config[:testing] and config.on_master_bot
|
38
46
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class SlackSmartBot
|
2
2
|
|
3
3
|
def dont_understand(rules_file = nil, command = nil, user = nil, dest = nil, answer = ["what?", "huh?", "sorry?", "what do you mean?", "I don't understand"], channel_rules: config.channel, typem: nil)
|
4
|
+
save_stats(:dont_understand)
|
4
5
|
command = Thread.current[:command] if command.nil?
|
5
6
|
user = Thread.current[:user] if user.nil?
|
6
7
|
dest = Thread.current[:dest] if dest.nil?
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# list of available emojis: https://www.webfx.com/tools/emoji-cheat-sheet/
|
3
|
+
# react(:thumbsup)
|
4
|
+
def react(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_add(channel: Thread.current[:dest], name: emoji, timestamp: ts)
|
12
|
+
rescue Exception => stack
|
13
|
+
@logger.warn stack
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -10,7 +10,11 @@ class SlackSmartBot
|
|
10
10
|
f.puts "|#{@channel_id}|#{config[:nick_id]}|#{msg}~~~"
|
11
11
|
}
|
12
12
|
else
|
13
|
-
|
13
|
+
if Thread.current[:on_thread]
|
14
|
+
client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: Thread.current[:thread_ts])
|
15
|
+
else
|
16
|
+
client.message(channel: @channel_id, text: msg, as_user: true)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
if config[:testing] and config.on_master_bot
|
16
20
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -23,7 +27,11 @@ class SlackSmartBot
|
|
23
27
|
f.puts "|#{dest}|#{config[:nick_id]}|#{msg}~~~"
|
24
28
|
}
|
25
29
|
else
|
26
|
-
|
30
|
+
if Thread.current[:on_thread]
|
31
|
+
client.message(channel: dest, text: msg, as_user: true, thread_ts: Thread.current[:thread_ts])
|
32
|
+
else
|
33
|
+
client.message(channel: dest, text: msg, as_user: true)
|
34
|
+
end
|
27
35
|
end
|
28
36
|
if config[:testing] and config.on_master_bot
|
29
37
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -10,6 +10,11 @@ class SlackSmartBot
|
|
10
10
|
else
|
11
11
|
channel = to
|
12
12
|
end
|
13
|
+
if Thread.current[:on_thread]
|
14
|
+
ts = Thread.current[:thread_ts]
|
15
|
+
else
|
16
|
+
ts = nil
|
17
|
+
end
|
13
18
|
|
14
19
|
client.web_client.files_upload(
|
15
20
|
channels: channel,
|
@@ -19,6 +24,7 @@ class SlackSmartBot
|
|
19
24
|
filename: file,
|
20
25
|
filetype: type,
|
21
26
|
initial_comment: msg,
|
27
|
+
thread_ts: ts
|
22
28
|
)
|
23
29
|
end
|
24
30
|
|
@@ -17,7 +17,11 @@ class SlackSmartBot
|
|
17
17
|
f.puts "|#{channel_id}|#{config[:nick_id]}|#{msg}~~~"
|
18
18
|
}
|
19
19
|
else
|
20
|
-
|
20
|
+
if Thread.current[:on_thread]
|
21
|
+
client.message(channel: channel_id, text: msg, as_user: true, thread_ts: Thread.current[:thread_ts])
|
22
|
+
else
|
23
|
+
client.message(channel: channel_id, text: msg, as_user: true)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
if config[:testing] and config.on_master_bot
|
23
27
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -9,7 +9,11 @@ class SlackSmartBot
|
|
9
9
|
f.puts "|#{id_user}|#{config[:nick_id]}|#{msg}~~~"
|
10
10
|
}
|
11
11
|
else
|
12
|
-
|
12
|
+
if Thread.current[:on_thread]
|
13
|
+
client.message(channel: id_user, as_user: true, text: msg, thread_ts: Thread.current[:thread_ts])
|
14
|
+
else
|
15
|
+
client.message(channel: id_user, as_user: true, text: msg)
|
16
|
+
end
|
13
17
|
end
|
14
18
|
if config[:testing] and config.on_master_bot
|
15
19
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -23,7 +27,11 @@ class SlackSmartBot
|
|
23
27
|
f.puts "|#{im["channel"]["id"]}|#{config[:nick_id]}|#{msg}~~~"
|
24
28
|
}
|
25
29
|
else
|
26
|
-
|
30
|
+
if Thread.current[:on_thread]
|
31
|
+
client.message(channel: im["channel"]["id"], as_user: true, text: msg, thread_ts: Thread.current[:thread_ts])
|
32
|
+
else
|
33
|
+
client.message(channel: im["channel"]["id"], as_user: true, text: msg)
|
34
|
+
end
|
27
35
|
end
|
28
36
|
if config[:testing] and config.on_master_bot
|
29
37
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -23,3 +23,5 @@ require_relative "commands/on_bot/add_shortcut"
|
|
23
23
|
require_relative "commands/on_bot/delete_shortcut"
|
24
24
|
require_relative "commands/on_bot/see_shortcuts"
|
25
25
|
require_relative "commands/on_extended/bot_rules"
|
26
|
+
require_relative "commands/on_bot/admin_master/get_bot_logs"
|
27
|
+
require_relative "commands/on_bot/admin_master/bot_stats"
|
@@ -11,7 +11,7 @@ class SlackSmartBot
|
|
11
11
|
# help: `bot rules` will show only the specific rules for this channel.
|
12
12
|
# help:
|
13
13
|
def bot_help(user, from, dest, dchannel, specific, help_command, rules_file)
|
14
|
-
|
14
|
+
save_stats(__method__)
|
15
15
|
help_found = false
|
16
16
|
|
17
17
|
message = ""
|
@@ -19,7 +19,7 @@ class SlackSmartBot
|
|
19
19
|
help_message = get_help(rules_file, dest, from, specific)
|
20
20
|
|
21
21
|
if help_command.to_s != ""
|
22
|
-
help_message.split(/^\s*-------*$/).each do |h|
|
22
|
+
help_message.gsub(/====+/,'-'*30).split(/^\s*-------*$/).each do |h|
|
23
23
|
if h.match?(/[`_]#{help_command}/i)
|
24
24
|
respond h, dest
|
25
25
|
help_found = true
|
@@ -52,7 +52,7 @@ class SlackSmartBot
|
|
52
52
|
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file)
|
53
53
|
end
|
54
54
|
end
|
55
|
-
if defined?(git_project) && (git_project.to_s != "") && (
|
55
|
+
if defined?(git_project) && (git_project.to_s != "") && (help_command.to_s == "")
|
56
56
|
respond "Git project: #{git_project}", dest
|
57
57
|
else
|
58
58
|
def git_project
|
@@ -5,6 +5,7 @@ class SlackSmartBot
|
|
5
5
|
# helpadmin: If on master channel and admin user also it will display info about bots created
|
6
6
|
# helpadmin:
|
7
7
|
def bot_status(dest, from)
|
8
|
+
save_stats(__method__)
|
8
9
|
get_bots_created()
|
9
10
|
gems_remote = `gem list slack-smart-bot --remote`
|
10
11
|
version_remote = gems_remote.to_s().scan(/slack-smart-bot \((\d+\.\d+\.\d+)/).join
|
@@ -9,6 +9,7 @@ class SlackSmartBot
|
|
9
9
|
# help:
|
10
10
|
def bye_bot(dest, from, display_name)
|
11
11
|
if @status == :on
|
12
|
+
save_stats(__method__)
|
12
13
|
bye = ["Bye", "Bæ", "Good Bye", "Adiós", "Ciao", "Bless", "Bless bless", "Adeu"].sample
|
13
14
|
respond "#{bye} #{display_name}", dest
|
14
15
|
@listening.delete(from)
|
@@ -11,6 +11,7 @@ class SlackSmartBot
|
|
11
11
|
# help:
|
12
12
|
def hi_bot(user, dest, dchannel, from, display_name)
|
13
13
|
if @status == :on
|
14
|
+
save_stats(__method__)
|
14
15
|
greetings = ["Hello", "Hallo", "Hi", "Hola", "What's up", "Hey", "Hæ"].sample
|
15
16
|
respond "#{greetings} #{display_name}", dest
|
16
17
|
if Thread.current[:using_channel]!=''
|
@@ -8,6 +8,7 @@ class SlackSmartBot
|
|
8
8
|
# help: you need to be part of that channel to be able to use the rules.
|
9
9
|
# help:
|
10
10
|
def use_rules(dest, channel, user, dchannel)
|
11
|
+
save_stats(__method__)
|
11
12
|
get_bots_created()
|
12
13
|
#todo: add pagination for case more than 1000 channels on the workspace
|
13
14
|
channels = client.web_client.conversations_list(
|
@@ -18,6 +18,7 @@ class SlackSmartBot
|
|
18
18
|
# help: _Spanish Account_
|
19
19
|
# help:
|
20
20
|
def add_shortcut(dest, from, typem, for_all, shortcut_name, command, command_to_run)
|
21
|
+
save_stats(__method__)
|
21
22
|
unless typem == :on_extended
|
22
23
|
@shortcuts[from] = Hash.new() unless @shortcuts.keys.include?(from)
|
23
24
|
|
@@ -23,6 +23,7 @@ class SlackSmartBot
|
|
23
23
|
# helpadmin: _create silent routine every 12 hours !Run customer tests_
|
24
24
|
# helpadmin:
|
25
25
|
def add_routine(dest, from, user, name, type, number_time, period, command_to_run, files, silent)
|
26
|
+
save_stats(__method__)
|
26
27
|
if files.nil? or files.size == 0 or (files.size > 0 and config.masters.include?(from))
|
27
28
|
if config.admins.include?(from)
|
28
29
|
if @routines.key?(@channel_id) && @routines[@channel_id].key?(name)
|
@@ -6,6 +6,7 @@ class SlackSmartBot
|
|
6
6
|
# helpadmin: It will allow to use the specific rules from this channel on the CHANNEL_NAME
|
7
7
|
# helpadmin:
|
8
8
|
def extend_rules(dest, user, from, channel, typem)
|
9
|
+
save_stats(__method__)
|
9
10
|
unless typem == :on_extended
|
10
11
|
if config.on_master_bot
|
11
12
|
respond "You cannot use the rules from Master Channel on any other channel.", dest
|
@@ -7,6 +7,7 @@ class SlackSmartBot
|
|
7
7
|
# helpadmin: You can use this command only if you are an admin user
|
8
8
|
# helpadmin:
|
9
9
|
def pause_bot(dest, from)
|
10
|
+
save_stats(__method__)
|
10
11
|
if config.admins.include?(from) #admin user
|
11
12
|
respond "This bot is paused from now on. You can start it again: start this bot", dest
|
12
13
|
respond "zZzzzzZzzzzZZZZZZzzzzzzzz", dest
|
@@ -8,6 +8,7 @@ class SlackSmartBot
|
|
8
8
|
# helpadmin: _pause routine example_
|
9
9
|
# helpadmin:
|
10
10
|
def pause_routine(dest, from, name)
|
11
|
+
save_stats(__method__)
|
11
12
|
if config.admins.include?(from) #admin user
|
12
13
|
if !config.on_master_bot and dest[0] == "D"
|
13
14
|
respond "It's only possible to pause routines from MASTER channel from a direct message with the bot.", dest
|
@@ -11,6 +11,7 @@ class SlackSmartBot
|
|
11
11
|
# helpadmin: _kill routine example_
|
12
12
|
# helpadmin:
|
13
13
|
def remove_routine(dest, from, name)
|
14
|
+
save_stats(__method__)
|
14
15
|
if config.admins.include?(from) #admin user
|
15
16
|
if !config.on_master_bot and dest[0] == "D"
|
16
17
|
respond "It's only possible to remove routines from MASTER channel from a direct message with the bot.", dest
|
@@ -11,6 +11,7 @@ class SlackSmartBot
|
|
11
11
|
# helpadmin:
|
12
12
|
|
13
13
|
def run_routine(dest, from, name)
|
14
|
+
save_stats(__method__)
|
14
15
|
if config.admins.include?(from) #admin user
|
15
16
|
if !config.on_master_bot and dest[0] == "D"
|
16
17
|
respond "It's only possible to run routines from MASTER channel from a direct message with the bot.", dest
|
@@ -7,6 +7,7 @@ class SlackSmartBot
|
|
7
7
|
# helpadmin: You can use this command only if you are an admin user
|
8
8
|
# helpadmin:
|
9
9
|
def start_bot(dest, from)
|
10
|
+
save_stats(__method__)
|
10
11
|
if config.admins.include?(from) #admin user
|
11
12
|
respond "This bot is running and listening from now on. You can pause again: pause this bot", dest
|
12
13
|
@status = :on
|
@@ -10,6 +10,7 @@ class SlackSmartBot
|
|
10
10
|
# helpadmin:
|
11
11
|
|
12
12
|
def start_routine(dest, from, name)
|
13
|
+
save_stats(__method__)
|
13
14
|
if config.admins.include?(from) #admin user
|
14
15
|
if !config.on_master_bot and dest[0] == "D"
|
15
16
|
respond "It's only possible to start routines from MASTER channel from a direct message with the bot.", dest
|
@@ -6,6 +6,7 @@ class SlackSmartBot
|
|
6
6
|
# helpadmin:
|
7
7
|
|
8
8
|
def stop_using_rules_on(dest, user, from, channel, typem)
|
9
|
+
save_stats(__method__)
|
9
10
|
unless typem == :on_extended
|
10
11
|
if !config.admins.include?(from) #not admin
|
11
12
|
respond "Only admins can extend or stop using the rules. Admins on this channel: #{config.admins}", dest
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
# helpadmin: ----------------------------------------------
|
3
|
+
# helpadmin: `bot stats`
|
4
|
+
# helpadmin: `bot stats USER_NAME`
|
5
|
+
# helpadmin: `bot stats exclude masters`
|
6
|
+
# helpadmin: `bot stats from YYYY/MM/DD`
|
7
|
+
# helpadmin: `bot stats from YYYY/MM/DD to YYYY/MM/DD`
|
8
|
+
# helpadmin: `bot stats CHANNEL`
|
9
|
+
# helpadmin: `bot stats CHANNEL from YYYY/MM/DD`
|
10
|
+
# helpadmin: `bot stats CHANNEL from YYYY/MM/DD to YYYY/MM/DD`
|
11
|
+
# helpadmin: `bot stats USER_NAME from YYYY/MM/DD to YYYY/MM/DD`
|
12
|
+
# helpadmin: `bot stats CHANNEL USER_NAME from YYYY/MM/DD to YYYY/MM/DD`
|
13
|
+
# helpadmin: `bot stats CHANNEL exclude masters from YYYY/MM/DD to YYYY/MM/DD`
|
14
|
+
# helpadmin: `bot stats today`
|
15
|
+
# helpadmin: `bot stats exclude COMMAND_ID`
|
16
|
+
# helpadmin: To see the bot stats
|
17
|
+
# 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
|
+
# helpadmin: You need to set stats to true to generate the stats when running the bot instance.
|
19
|
+
# helpadmin: Examples:
|
20
|
+
# helpadmin: _bot stats #sales_
|
21
|
+
# helpadmin: _bot stats @peter.wind_
|
22
|
+
# helpadmin: _bot stats #sales from 2019/12/15 to 2019/12/31_
|
23
|
+
# helpadmin: _bot stats #sales today_
|
24
|
+
# helpadmin:
|
25
|
+
def bot_stats(dest, from_user, typem, channel_id, from, to, user, exclude_masters, exclude_command)
|
26
|
+
require 'csv'
|
27
|
+
if config.stats
|
28
|
+
message = []
|
29
|
+
else
|
30
|
+
message = ["You need to set stats to true to generate the stats when running the bot instance."]
|
31
|
+
end
|
32
|
+
save_stats(__method__)
|
33
|
+
if config.masters.include?(from_user) and typem==:on_dm #master admin user
|
34
|
+
if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
|
35
|
+
message<<'No stats'
|
36
|
+
else
|
37
|
+
from = "#{Time.now.strftime("%Y-%m")}-01" if from == ''
|
38
|
+
to = "#{Time.now.strftime("%Y-%m-%d")}" if to == ''
|
39
|
+
from_short = from
|
40
|
+
to_short = to
|
41
|
+
from_file = from[0..3] + '-' + from[5..6]
|
42
|
+
to_file = to[0..3] + '-' + to[5..6]
|
43
|
+
from+= " 00:00:00 +0000"
|
44
|
+
to+= " 23:59:59 +0000"
|
45
|
+
rows = []
|
46
|
+
|
47
|
+
Dir["#{config.stats_path}.*.log"].each do |file|
|
48
|
+
if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
|
49
|
+
CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
|
50
|
+
row[:date] = row[:date].to_s
|
51
|
+
if !exclude_masters or (exclude_masters and !config.masters.include?(row[:user_name]))
|
52
|
+
if user=='' or (user!='' and row[:user_id] == user)
|
53
|
+
if exclude_command == '' or (exclude_command!='' and row[:command]!=exclude_command)
|
54
|
+
if row[:bot_channel_id] == channel_id or channel_id == ''
|
55
|
+
if row[:date] >= from and row[:date] <= to
|
56
|
+
rows << row.to_h
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
total = rows.size
|
67
|
+
if exclude_masters
|
68
|
+
message << 'Excluding master admins'
|
69
|
+
end
|
70
|
+
if exclude_command != ''
|
71
|
+
message << "Excluding command #{exclude_command}"
|
72
|
+
end
|
73
|
+
if user!=''
|
74
|
+
message << "Showing only user <@#{user}>"
|
75
|
+
end
|
76
|
+
if channel_id == ''
|
77
|
+
message << "*Total calls*: #{total} from #{from_short} to #{to_short}"
|
78
|
+
else
|
79
|
+
message << "*Total calls <##{channel_id}>*: #{total} from #{from_short} to #{to_short}"
|
80
|
+
end
|
81
|
+
if total > 0
|
82
|
+
|
83
|
+
if channel_id == ''
|
84
|
+
message << "*Channels*"
|
85
|
+
channels = rows.bot_channel.uniq.sort
|
86
|
+
channels.each do |channel|
|
87
|
+
count = rows.count {|h| h.bot_channel==channel}
|
88
|
+
message << "\t#{channel}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
if user==''
|
92
|
+
message << "*Users*"
|
93
|
+
users = rows.user_name.uniq.sort
|
94
|
+
users.each do |user|
|
95
|
+
count = rows.count {|h| h.user_name==user}
|
96
|
+
message << "\t#{user}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
message << "*Commands*"
|
101
|
+
commands = rows.command.uniq.sort
|
102
|
+
commands.each do |command|
|
103
|
+
count = rows.count {|h| h.command==command}
|
104
|
+
message << "\t#{command}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
105
|
+
end
|
106
|
+
|
107
|
+
message << "*Message type*"
|
108
|
+
types = rows.type_message.uniq.sort
|
109
|
+
types.each do |type|
|
110
|
+
count = rows.count {|h| h.type_message==type}
|
111
|
+
message << "\t#{type}: #{count} (#{(count.to_f*100/total).round(2)}%)"
|
112
|
+
end
|
113
|
+
message << "*Last activity*: #{rows[-1].date} #{rows[-1].bot_channel} #{rows[-1].type_message} #{rows[-1].user_name} #{rows[-1].command}"
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
else
|
118
|
+
message<<"Only Master admin users on a private conversation with the bot can see the bot stats."
|
119
|
+
end
|
120
|
+
respond "#{message.join("\n")}", dest
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
|
3
|
+
# helpadmin: ----------------------------------------------
|
4
|
+
# helpadmin: `get bot logs`
|
5
|
+
# helpadmin: To see the bot logs
|
6
|
+
# 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
|
7
|
+
# helpadmin:
|
8
|
+
def get_bot_logs(dest, from, typem)
|
9
|
+
save_stats(__method__)
|
10
|
+
if config.masters.include?(from) and typem==:on_dm #master admin user
|
11
|
+
respond 'Remember this data is private'
|
12
|
+
send_file(dest, "Logs for #{config.channel}", "#{config.path}/logs/#{config.log_file}", 'Remember this data is private', 'text/plain', "text")
|
13
|
+
else
|
14
|
+
respond "Only master admin users on a private conversation with the bot can get the bot logs.", dest
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -8,6 +8,7 @@ class SlackSmartBot
|
|
8
8
|
# help:
|
9
9
|
|
10
10
|
def ruby_code(dest, code, rules_file)
|
11
|
+
save_stats(__method__)
|
11
12
|
unless code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
12
13
|
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO.") or
|
13
14
|
code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
|
@@ -36,7 +37,7 @@ class SlackSmartBot
|
|
36
37
|
respond stdout, dest
|
37
38
|
end
|
38
39
|
else
|
39
|
-
respond stderr, dest
|
40
|
+
respond "#{stderr}\n#{stdout}", dest
|
40
41
|
end
|
41
42
|
rescue Exception => exc
|
42
43
|
respond exc, dest
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class SlackSmartBot
|
2
2
|
def bot_rules(dest, help_command, typem, rules_file, from)
|
3
|
+
save_stats(__method__)
|
3
4
|
if typem == :on_extended or typem == :on_call #for the other cases above.
|
4
5
|
help_filtered = get_help(rules_file, dest, from, true)
|
5
6
|
|
@@ -15,7 +16,7 @@ class SlackSmartBot
|
|
15
16
|
else
|
16
17
|
message = "-\n\n\n===================================\n*Rules from channel #{config.channel}*\n"
|
17
18
|
if typem == :on_extended
|
18
|
-
message += "To run the commands on this extended channel, add
|
19
|
+
message += "To run the commands on this extended channel, add `!`, `!!` or `^` before the command.\n"
|
19
20
|
end
|
20
21
|
message += help_filtered
|
21
22
|
respond message, dest
|
@@ -26,7 +27,7 @@ class SlackSmartBot
|
|
26
27
|
eval(File.new(config.path+rules_file).read) if File.exist?(config.path+rules_file)
|
27
28
|
end
|
28
29
|
end
|
29
|
-
if defined?(git_project) and git_project.to_s != "" and
|
30
|
+
if defined?(git_project) and git_project.to_s != "" and help_command.to_s == ""
|
30
31
|
respond "Git project: #{git_project}", dest
|
31
32
|
else
|
32
33
|
def git_project() "" end
|
@@ -5,6 +5,7 @@ class SlackSmartBot
|
|
5
5
|
# helpmaster: Only works if you are on Master channel and you created that bot or you are an admin user
|
6
6
|
# helpmaster:
|
7
7
|
def kill_bot_on_channel(dest, from, channel)
|
8
|
+
save_stats(__method__)
|
8
9
|
if config.on_master_bot
|
9
10
|
get_channels_name_and_id() unless @channels_name.keys.include?(channel) or @channels_id.keys.include?(channel)
|
10
11
|
channel_id = nil
|
@@ -8,6 +8,7 @@ class SlackSmartBot
|
|
8
8
|
# helpadmin: You can use this command only if you are an admin user and you are on the master channel
|
9
9
|
# helpadmin:
|
10
10
|
def exit_bot(command, from, dest, display_name)
|
11
|
+
save_stats(__method__)
|
11
12
|
if config.on_master_bot
|
12
13
|
if config.admins.include?(from) #admin user
|
13
14
|
unless @questions.keys.include?(from)
|
@@ -24,7 +25,7 @@ class SlackSmartBot
|
|
24
25
|
}
|
25
26
|
update_bots_file()
|
26
27
|
sleep 0.5
|
27
|
-
if config.simulate
|
28
|
+
if config.simulate
|
28
29
|
@status = :off
|
29
30
|
config.simulate = false
|
30
31
|
Thread.exit
|
@@ -9,6 +9,7 @@ class SlackSmartBot
|
|
9
9
|
# helpmaster: Only works if you are on Master channel and you are a master admin user
|
10
10
|
# helpmaster:
|
11
11
|
def notify_message(dest, from, where, message)
|
12
|
+
save_stats(__method__)
|
12
13
|
if config.on_master_bot
|
13
14
|
if config.admins.include?(from) #admin user
|
14
15
|
if where.nil? #not all and not channel
|
@@ -8,6 +8,7 @@ class SlackSmartBot
|
|
8
8
|
# helpmaster: follow the instructions in case creating cloud bots
|
9
9
|
# helpmaster:
|
10
10
|
def create_bot(dest, from, cloud, channel)
|
11
|
+
save_stats(__method__)
|
11
12
|
if config.on_master_bot
|
12
13
|
get_channels_name_and_id() unless @channels_name.keys.include?(channel) or @channels_id.keys.include?(channel)
|
13
14
|
channel_id = nil
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
def process(user, command, dest, dchannel, rules_file, typem, files)
|
2
|
+
def process(user, command, dest, dchannel, rules_file, typem, files, ts)
|
3
3
|
from = user.name
|
4
4
|
if user.profile.display_name.to_s.match?(/\A\s*\z/)
|
5
5
|
user.profile.display_name = user.profile.real_name
|
@@ -9,10 +9,18 @@ class SlackSmartBot
|
|
9
9
|
|
10
10
|
on_demand = false
|
11
11
|
if command.match(/^@?(#{config[:nick]}):*\s+(.+)/im) or
|
12
|
+
command.match(/^()!!(.+)/im) or
|
13
|
+
command.match(/^()\^(.+)/im) or
|
12
14
|
command.match(/^()!(.+)/im) or
|
13
15
|
command.match(/^()<@#{config[:nick_id]}>\s+(.+)/im)
|
14
|
-
|
15
|
-
|
16
|
+
command2 = $2
|
17
|
+
Thread.current[:command] = command2
|
18
|
+
if command2.match?(/^()!!(.+)/im) or
|
19
|
+
command.match?(/^()\^(.+)/im)
|
20
|
+
Thread.current[:on_thread] = true
|
21
|
+
end
|
22
|
+
command = command2
|
23
|
+
on_demand = true
|
16
24
|
end
|
17
25
|
|
18
26
|
#todo: check :on_pg in this case
|
@@ -84,6 +92,24 @@ class SlackSmartBot
|
|
84
92
|
when /^\s*see\s+(all\s+)?routines\s*$/i
|
85
93
|
all = $1.to_s != ""
|
86
94
|
see_routines(dest, from, user, all)
|
95
|
+
when /^\s*get\s+bot\s+logs?\s*$/i
|
96
|
+
get_bot_logs(dest, from, typem)
|
97
|
+
when /^\s*bot\s+stats\s*(.*)\s*$/i
|
98
|
+
opts = $1.to_s
|
99
|
+
all_opts = opts.downcase.split(' ')
|
100
|
+
st_channel = opts.scan(/<#(\w+)\|.+>/).join
|
101
|
+
st_from = opts.scan(/from\s+(\d\d\d\d[\/\-\.]\d\d[\/\-\.]\d\d)/).join
|
102
|
+
st_from = st_from.gsub('.','-').gsub('/','-')
|
103
|
+
st_to = opts.scan(/to\s+(\d\d\d\d[\/\-\.]\d\d[\/\-\.]\d\d)/).join
|
104
|
+
st_to = st_to.gsub('.','-').gsub('/','-')
|
105
|
+
st_user = opts.scan(/<@([^>]+)>/).join
|
106
|
+
exclude_masters = opts.match?(/exclude\s+masters?/i)
|
107
|
+
if all_opts.include?('today')
|
108
|
+
st_from = st_to = "#{Time.now.strftime("%Y-%m-%d")}"
|
109
|
+
end
|
110
|
+
exclude_command = opts.scan(/exclude\s+([^\s]+)/i).join
|
111
|
+
exclude_command = '' if exclude_command == 'masters'
|
112
|
+
bot_stats(dest, from, typem, st_channel, st_from, st_to, st_user, exclude_masters, exclude_command)
|
87
113
|
else
|
88
114
|
processed = false
|
89
115
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
def process_first(user, text, dest, dchannel, typem, files)
|
2
|
+
def process_first(user, text, dest, dchannel, typem, files, ts, thread_ts)
|
3
3
|
nick = user.name
|
4
4
|
rules_file = ""
|
5
|
+
text.gsub!(/^!!/,'^') # to treat it just as ^
|
5
6
|
if typem == :on_call
|
6
7
|
rules_file = config.rules_file
|
7
8
|
elsif dest[0] == "C" or dest[0] == "G" # on a channel or private channel
|
@@ -30,7 +31,7 @@ class SlackSmartBot
|
|
30
31
|
when /^Bot has been (closed|killed) by/i
|
31
32
|
if config.channel == @channels_name[dchannel]
|
32
33
|
@logger.info "#{nick}: #{text}"
|
33
|
-
if config.simulate
|
34
|
+
if config.simulate
|
34
35
|
@status = :off
|
35
36
|
config.simulate = false
|
36
37
|
Thread.exit
|
@@ -76,13 +77,31 @@ class SlackSmartBot
|
|
76
77
|
|
77
78
|
#only for shortcuts
|
78
79
|
if text.match(/^@?(#{config[:nick]}):*\s+(.+)\s*/im) or
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
text.match(/^()\^\s*(.+)\s*/im) or
|
81
|
+
text.match(/^()!\s*(.+)\s*/im) or
|
82
|
+
text.match(/^()<@#{config[:nick_id]}>\s+(.+)\s*/im)
|
83
|
+
command2 = $2
|
84
|
+
if text.match?(/^()\^\s*(.+)/im)
|
85
|
+
add_double_excl = true
|
86
|
+
addexcl = false
|
87
|
+
if command2.match?(/^![^!]/) or command2.match?(/^\^/)
|
88
|
+
command2[0]=''
|
89
|
+
elsif command2.match?(/^!!/)
|
90
|
+
command2[0]=''
|
91
|
+
command2[1]=''
|
92
|
+
end
|
93
|
+
else
|
94
|
+
add_double_excl = false
|
95
|
+
addexcl = true
|
96
|
+
end
|
97
|
+
command = command2
|
83
98
|
else
|
84
99
|
addexcl = false
|
85
|
-
|
100
|
+
if text.include?('$') #for shortcuts inside commands
|
101
|
+
command = text.lstrip.rstrip
|
102
|
+
else
|
103
|
+
command = text.downcase.lstrip.rstrip
|
104
|
+
end
|
86
105
|
end
|
87
106
|
|
88
107
|
if command.include?('$') #for adding shortcuts inside commands
|
@@ -104,6 +123,7 @@ class SlackSmartBot
|
|
104
123
|
end
|
105
124
|
text = command
|
106
125
|
text = "!" + text if addexcl and text[0] != "!"
|
126
|
+
text = "^" + text if add_double_excl
|
107
127
|
end
|
108
128
|
if command.scan(/^(shortcut|sc)\s+([^:]+)\s*$/i).any? or
|
109
129
|
(@shortcuts.keys.include?(:all) and @shortcuts[:all].keys.include?(command)) or
|
@@ -118,6 +138,7 @@ class SlackSmartBot
|
|
118
138
|
return :next #jal
|
119
139
|
end
|
120
140
|
text = "!" + text if addexcl and text[0] != "!"
|
141
|
+
text = "^" + text if add_double_excl
|
121
142
|
end
|
122
143
|
|
123
144
|
command = text
|
@@ -130,6 +151,15 @@ class SlackSmartBot
|
|
130
151
|
Thread.current[:command] = command
|
131
152
|
Thread.current[:rules_file] = rules_file
|
132
153
|
Thread.current[:typem] = typem
|
154
|
+
Thread.current[:files?] = !files.nil? && files.size>0
|
155
|
+
Thread.current[:ts] = ts
|
156
|
+
Thread.current[:thread_ts] = thread_ts
|
157
|
+
if thread_ts.to_s == ''
|
158
|
+
Thread.current[:on_thread] = false
|
159
|
+
Thread.current[:thread_ts] = Thread.current[:ts] # to create the thread if necessary
|
160
|
+
else
|
161
|
+
Thread.current[:on_thread] = true
|
162
|
+
end
|
133
163
|
if (dest[0] == "C") || (dest[0] == "G") and @rules_imported.key?(user.id) &&
|
134
164
|
@rules_imported[user.id].key?(dchannel) && @bots_created.key?(@rules_imported[user.id][dchannel])
|
135
165
|
Thread.current[:using_channel] = @rules_imported[user.id][dchannel]
|
@@ -140,14 +170,21 @@ class SlackSmartBot
|
|
140
170
|
Thread.current[:using_channel] = ''
|
141
171
|
end
|
142
172
|
|
143
|
-
processed = process(user, command, dest, dchannel, rules_file, typem, files)
|
173
|
+
processed = process(user, command, dest, dchannel, rules_file, typem, files, Thread.current[:thread_ts])
|
144
174
|
@logger.info "command: #{nick}> #{command}" if processed
|
145
175
|
on_demand = false
|
146
176
|
if command.match(/^@?(#{config[:nick]}):*\s+(.+)/im) or
|
147
|
-
|
148
|
-
|
149
|
-
command
|
150
|
-
|
177
|
+
command.match(/^()!!(.+)/im) or
|
178
|
+
command.match(/^()\^(.+)/im) or
|
179
|
+
command.match(/^()!(.+)/im) or
|
180
|
+
command.match(/^()<@#{config[:nick_id]}>\s+(.+)/im)
|
181
|
+
command2 = $2
|
182
|
+
Thread.current[:command] = command2
|
183
|
+
if command2.match?(/^()!!(.+)/im) or
|
184
|
+
command.match?(/^()\^(.+)/im)
|
185
|
+
Thread.current[:on_thread] = true
|
186
|
+
end
|
187
|
+
command = command2
|
151
188
|
on_demand = true
|
152
189
|
end
|
153
190
|
if @status == :on and
|
@@ -1,9 +1,31 @@
|
|
1
1
|
class SlackSmartBot
|
2
2
|
def treat_message(data)
|
3
3
|
begin
|
4
|
-
|
4
|
+
unless data.text.to_s.match(/\A\s*\z/)
|
5
|
+
#to remove italic, bold... from data.text since there is no method on slack api
|
6
|
+
#only works when no @user or #channel mentioned
|
7
|
+
if !data.blocks.nil? and data.blocks.size > 0
|
8
|
+
data.blocks.each do |b|
|
9
|
+
if b.type == 'rich_text'
|
10
|
+
if b.elements.size > 0
|
11
|
+
b.elements.each do |e|
|
12
|
+
if e.type == 'rich_text_section'
|
13
|
+
if e.elements.size > 0 and e.elements.type.uniq == ['text']
|
14
|
+
data.text = e.elements.text.join
|
15
|
+
end
|
16
|
+
break
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
break
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
data.text = CGI.unescapeHTML(data.text)
|
25
|
+
data.text.gsub!("\u00A0", " ") #to change (asc char 160) into blank space
|
26
|
+
end
|
5
27
|
rescue
|
6
|
-
@logger.warn "Impossible to unescape
|
28
|
+
@logger.warn "Impossible to unescape or clean format for data.text:#{data.text}"
|
7
29
|
end
|
8
30
|
if config[:testing] and config.on_master_bot
|
9
31
|
open("#{config.path}/buffer.log", "a") { |f|
|
@@ -56,9 +78,10 @@ class SlackSmartBot
|
|
56
78
|
elsif dest[0] == "C" or dest[0] == "G"
|
57
79
|
#only to be treated on the channel of the bot. excluding running ruby
|
58
80
|
if !config.on_master_bot and @bots_created.key?(@channel_id) and @bots_created[@channel_id][:extended].include?(@channels_name[dest]) and
|
59
|
-
!data.text.match?(/^!?\s*(ruby|code)\s+/)
|
81
|
+
!data.text.match?(/^!?\s*(ruby|code)\s+/) and !data.text.match?(/^!?!?\s*(ruby|code)\s+/) and !data.text.match?(/^\^?\s*(ruby|code)\s+/)
|
60
82
|
typem = :on_extended
|
61
|
-
elsif config.on_master_bot and data.text.match?(/^!?\s*(ruby|code)\s+/)
|
83
|
+
elsif config.on_master_bot and (data.text.match?(/^!?\s*(ruby|code)\s+/) or data.text.match?(/^!?!?\s*(ruby|code)\s+/) or data.text.match?(/^\^?\s*(ruby|code)\s+/) )
|
84
|
+
#or in case of running ruby, the master bot
|
62
85
|
@bots_created.each do |k, v|
|
63
86
|
if v.key?(:extended) and v[:extended].include?(@channels_name[dest])
|
64
87
|
typem = :on_extended
|
@@ -104,7 +127,7 @@ class SlackSmartBot
|
|
104
127
|
end
|
105
128
|
|
106
129
|
if typem == :on_call
|
107
|
-
command = "!" + command unless command[0] == "!" or command.match?(/^\s*$/)
|
130
|
+
command = "!" + command unless command[0] == "!" or command.match?(/^\s*$/) or command[0] == "^"
|
108
131
|
|
109
132
|
#todo: add pagination for case more than 1000 channels on the workspace
|
110
133
|
channels = client.web_client.conversations_list(
|
@@ -121,21 +144,21 @@ class SlackSmartBot
|
|
121
144
|
elsif @status != :on
|
122
145
|
respond "The bot in that channel is not :on", dest
|
123
146
|
elsif data.user == channel_found.creator or members.include?(data.user)
|
124
|
-
process_first(user_info.user, command, dest, channel_rules, typem, data.files)
|
147
|
+
process_first(user_info.user, command, dest, channel_rules, typem, data.files, data.ts, data.thread_ts)
|
125
148
|
else
|
126
149
|
respond "You need to join the channel <##{channel_found.id}> to be able to use the rules.", dest
|
127
150
|
end
|
128
151
|
elsif config.on_master_bot and typem == :on_extended and
|
129
152
|
command.size > 0 and command[0] != "-"
|
130
153
|
# to run ruby only from the master bot for the case more than one extended
|
131
|
-
process_first(user_info.user, command, dest, @channel_id, typem, data.files)
|
154
|
+
process_first(user_info.user, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts)
|
132
155
|
elsif !config.on_master_bot and @bots_created[@channel_id].key?(:extended) and
|
133
156
|
@bots_created[@channel_id][:extended].include?(@channels_name[data.channel]) and
|
134
157
|
command.size > 0 and command[0] != "-"
|
135
|
-
process_first(user_info.user, command, dest, @channel_id, typem, data.files)
|
158
|
+
process_first(user_info.user, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts)
|
136
159
|
elsif (dest[0] == "D" or @channel_id == data.channel or data.user == config[:nick_id]) and
|
137
160
|
command.size > 0 and command[0] != "-"
|
138
|
-
process_first(user_info.user, command, dest, data.channel, typem, data.files)
|
161
|
+
process_first(user_info.user, command, dest, data.channel, typem, data.files, data.ts, data.thread_ts)
|
139
162
|
# if @botname on #channel_rules: do something
|
140
163
|
end
|
141
164
|
rescue Exception => stack
|
@@ -4,7 +4,7 @@ class SlackSmartBot
|
|
4
4
|
general: [:hi_bot, :bye_bot, :bot_help, :bot_status, :use_rules, :stop_using_rules],
|
5
5
|
on_bot: [:ruby_code, :add_shortcut, :delete_shortcut, :see_shortcuts],
|
6
6
|
on_bot_admin: [:extend_rules, :stop_using_rules_on, :start_bot, :pause_bot, :add_routine,
|
7
|
-
|
7
|
+
:see_routines, :start_routine, :pause_routine, :remove_routine, :run_routine]
|
8
8
|
}
|
9
9
|
# user_type: :admin, :user, :admin_master
|
10
10
|
if config.masters.include?(from)
|
@@ -34,20 +34,23 @@ class SlackSmartBot
|
|
34
34
|
if rules_file != ""
|
35
35
|
help[:rules_file] = IO.readlines(config.path+rules_file).join.scan(/#\s*help\s*\w*:(.*)/i).join("\n")
|
36
36
|
end
|
37
|
-
|
38
37
|
help = remove_hash_keys(help, :admin_master) unless user_type == :admin_master
|
39
38
|
help = remove_hash_keys(help, :admin) unless user_type == :admin or user_type == :admin_master
|
40
39
|
help = remove_hash_keys(help, :on_master) unless channel_type == :master_bot
|
41
40
|
help = remove_hash_keys(help, :on_extended) unless channel_type == :extended
|
42
41
|
help = remove_hash_keys(help, :on_dm) unless channel_type == :direct
|
43
42
|
txt = ""
|
43
|
+
|
44
44
|
if channel_type == :bot or channel_type == :master_bot
|
45
45
|
txt += "===================================
|
46
46
|
For the Smart Bot start listening to you say *hi bot*
|
47
47
|
To run a command on demand even when the Smart Bot is not listening to you:
|
48
48
|
*!THE_COMMAND*
|
49
49
|
*@NAME_OF_BOT THE_COMMAND*
|
50
|
-
*NAME_OF_BOT THE_COMMAND
|
50
|
+
*NAME_OF_BOT THE_COMMAND*
|
51
|
+
To run a command on demand and add the respond on a thread:
|
52
|
+
*^THE_COMMAND*
|
53
|
+
*!!THE_COMMAND*\n"
|
51
54
|
end
|
52
55
|
if channel_type == :direct
|
53
56
|
txt += "===================================
|
@@ -104,17 +107,20 @@ class SlackSmartBot
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
|
-
if help.key?(:
|
110
|
+
if help.key?(:on_bot) and help.on_bot.key?(:admin_master) and help.on_bot.admin_master.size > 0
|
108
111
|
txt += "===================================
|
109
112
|
*Master Admin commands:*\n"
|
110
|
-
help.
|
113
|
+
help.on_bot.admin_master.each do |k, v|
|
111
114
|
txt += v if v.is_a?(String)
|
112
115
|
end
|
113
116
|
end
|
114
117
|
|
115
|
-
if help.key?(:
|
118
|
+
if help.key?(:on_master) and help.on_master.key?(:admin_master) and help.on_master.admin_master.size > 0
|
116
119
|
txt += "===================================
|
117
120
|
*Master Admin commands:*\n"
|
121
|
+
help.on_master.admin_master.each do |k, v|
|
122
|
+
txt += v if v.is_a?(String)
|
123
|
+
end
|
118
124
|
end
|
119
125
|
|
120
126
|
if help.key?(:rules_file)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
|
3
|
+
def save_stats(method)
|
4
|
+
if config.stats
|
5
|
+
begin
|
6
|
+
require 'csv'
|
7
|
+
if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
|
8
|
+
CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", 'wb') do |csv|
|
9
|
+
csv << ['date','bot_channel', 'bot_channel_id', 'dest_channel', 'dest_channel_id', 'type_message', 'user_name', 'user_id', 'text', 'command', 'files']
|
10
|
+
end
|
11
|
+
end
|
12
|
+
dest = Thread.current[:dest]
|
13
|
+
typem = Thread.current[:typem]
|
14
|
+
user = Thread.current[:user]
|
15
|
+
files = Thread.current[:files?]
|
16
|
+
if method.to_s == 'ruby_code' and files
|
17
|
+
command_txt = 'ruby'
|
18
|
+
else
|
19
|
+
command_txt = Thread.current[:command]
|
20
|
+
end
|
21
|
+
|
22
|
+
CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", "a+") do |csv|
|
23
|
+
csv << [Time.now, config.channel, @channel_id, @channels_name[dest], dest, typem, user.name, user.id, command_txt, method, files]
|
24
|
+
end
|
25
|
+
rescue Exception => exception
|
26
|
+
@logger.fatal "There was a problem on the stats"
|
27
|
+
@logger.fatal exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
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.5.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:
|
11
|
+
date: 2020-02-07 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.5
|
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.5
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: nice_http
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- lib/slack/smart-bot/comm.rb
|
122
122
|
- lib/slack/smart-bot/comm/ask.rb
|
123
123
|
- lib/slack/smart-bot/comm/dont_understand.rb
|
124
|
+
- lib/slack/smart-bot/comm/react.rb
|
124
125
|
- lib/slack/smart-bot/comm/respond.rb
|
125
126
|
- lib/slack/smart-bot/comm/respond_direct.rb
|
126
127
|
- lib/slack/smart-bot/comm/send_file.rb
|
@@ -144,6 +145,8 @@ files:
|
|
144
145
|
- lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb
|
145
146
|
- lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb
|
146
147
|
- lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb
|
148
|
+
- lib/slack/smart-bot/commands/on_bot/admin_master/bot_stats.rb
|
149
|
+
- lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb
|
147
150
|
- lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb
|
148
151
|
- lib/slack/smart-bot/commands/on_bot/ruby_code.rb
|
149
152
|
- lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb
|
@@ -165,6 +168,7 @@ files:
|
|
165
168
|
- lib/slack/smart-bot/utils/get_routines.rb
|
166
169
|
- lib/slack/smart-bot/utils/get_rules_imported.rb
|
167
170
|
- lib/slack/smart-bot/utils/remove_hash_keys.rb
|
171
|
+
- lib/slack/smart-bot/utils/save_stats.rb
|
168
172
|
- lib/slack/smart-bot/utils/update_bots_file.rb
|
169
173
|
- lib/slack/smart-bot/utils/update_routines.rb
|
170
174
|
- lib/slack/smart-bot/utils/update_rules_imported.rb
|