slack-smart-bot 1.12.8 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +85 -12
- data/lib/slack/smart-bot/comm/respond.rb +1 -0
- data/lib/slack/smart-bot/comm/update.rb +13 -0
- data/lib/slack/smart-bot/comm.rb +1 -0
- data/lib/slack/smart-bot/commands/general/add_team.rb +1 -0
- data/lib/slack/smart-bot/commands/general/add_vacation.rb +5 -0
- data/lib/slack/smart-bot/commands/general/allow_access.rb +1 -1
- data/lib/slack/smart-bot/commands/general/delete_team.rb +1 -0
- data/lib/slack/smart-bot/commands/general/deny_access.rb +1 -1
- data/lib/slack/smart-bot/commands/general/public_holidays.rb +144 -0
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +2 -2
- data/lib/slack/smart-bot/commands/general/see_memos_team.rb +202 -0
- data/lib/slack/smart-bot/commands/general/see_teams.rb +3 -175
- data/lib/slack/smart-bot/commands/general/see_vacations.rb +41 -21
- data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +21 -0
- data/lib/slack/smart-bot/commands/general/update_team.rb +1 -0
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +100 -8
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +27 -3
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +12 -8
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +33 -4
- data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +22 -1
- data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +50 -4
- data/lib/slack/smart-bot/commands/on_bot/admin_master/update_message.rb +25 -0
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +8 -6
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +55 -15
- data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +2 -1
- data/lib/slack/smart-bot/commands.rb +4 -0
- data/lib/slack/smart-bot/listen.rb +1 -1
- data/lib/slack/smart-bot/process.rb +36 -6
- data/lib/slack/smart-bot/process_first.rb +250 -188
- data/lib/slack/smart-bot/treat_message.rb +1 -1
- data/lib/slack/smart-bot/utils/build_help.rb +1 -1
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +40 -4
- data/lib/slack/smart-bot/utils/decrypt.rb +15 -0
- data/lib/slack/smart-bot/utils/display_calendar.rb +86 -0
- data/lib/slack/smart-bot/utils/encrypt.rb +15 -0
- data/lib/slack/smart-bot/utils/encryption_get_key_iv.rb +29 -0
- data/lib/slack/smart-bot/utils/get_help.rb +1 -1
- data/lib/slack/smart-bot/utils/get_team_members.rb +39 -0
- data/lib/slack/smart-bot/utils/get_teams.rb +22 -16
- data/lib/slack/smart-bot/utils/get_vacations.rb +20 -15
- data/lib/slack/smart-bot/utils/save_stats.rb +2 -2
- data/lib/slack/smart-bot/utils/update_teams.rb +15 -9
- data/lib/slack/smart-bot/utils/update_vacations.rb +5 -3
- data/lib/slack/smart-bot/utils.rb +5 -0
- data/lib/slack-smart-bot.rb +9 -0
- data/lib/slack-smart-bot_general_commands.rb +33 -0
- data/lib/slack-smart-bot_general_rules.rb +2 -2
- data/whats_new.txt +15 -17
- metadata +27 -11
@@ -61,10 +61,12 @@ class SlackSmartBot
|
|
61
61
|
/\A\s*stop\s+using\s+rules\s+(on\s+)(.+)\s*$/i
|
62
62
|
channel = $2
|
63
63
|
stop_using_rules_on(dest, user, from, channel, typem)
|
64
|
-
when /\A\s*stop\s+using\s+
|
64
|
+
when /\A\s*stop\s+using\s+rules\s*$()()/i,
|
65
|
+
/\A\s*stop\s+using\s+(rules\s+from\s+)?<#\w+\|(.+)>/i,
|
65
66
|
/\A\s*stop\s+using\s+(rules\s+from\s+)?<#(\w+)\|>/i,
|
66
67
|
/\A\s*stop\s+using\s+(rules\s+from\s+)?(.+)\s*$/i
|
67
68
|
channel = $2
|
69
|
+
channel = @channel_id if channel.to_s == ''
|
68
70
|
stop_using_rules(dest, channel, user, dchannel)
|
69
71
|
when /\A\s*extend\s+rules\s+(to\s+)<#C\w+\|(.+)>/i, /\A\s*extend\s+rules\s+(to\s+)<#(\w+)\|>/i,
|
70
72
|
/\A\s*extend\s+rules\s+(to\s+)(.+)/i,
|
@@ -106,6 +108,8 @@ class SlackSmartBot
|
|
106
108
|
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+(every)\s+(\d+)\s*(days|hours|minutes|seconds|mins|min|secs|sec|d|h|m|s)\s*(\s<#(C\w+)\|.*>\s*)?(\s.+)?\s*\z/im,
|
107
109
|
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+on\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday|weekend|weekday)s?\s+at\s+(\d+:\d+:?\d+?)\s*()(\s#(\w+)\s*)(\s.+)?\s*\z/im,
|
108
110
|
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+on\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday|weekend|weekday)s?\s+at\s+(\d+:\d+:?\d+?)\s*()(\s<#(C\w+)\|.*>\s*)?(\s.+)?\s*\z/im,
|
111
|
+
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+on\s+the\s+(\d+)[^\s]*\s+at\s+(\d+:\d+:?\d+?)\s*()(\s#(\w+)\s*)(\s.+)?\s*\z/im,
|
112
|
+
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+on\s+the\s+(\d+)[^\s]*\s+at\s+(\d+:\d+:?\d+?)\s*()(\s<#(C\w+)\|.*>\s*)?(\s.+)?\s*\z/im,
|
109
113
|
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s#(\w+)\s*)(\s.+)?\s*\z/im,
|
110
114
|
/\A\s*(add|create)\s+(silent\s+)?(bgroutine|routine)\s+([\w\.]+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s<#(C\w+)\|.*>\s*)?(\s.+)?\s*\z/im
|
111
115
|
silent = $2.to_s!=''
|
@@ -145,9 +149,11 @@ class SlackSmartBot
|
|
145
149
|
when /\A\s*start\s+routine\s+([\w\.]+)\s*$/i
|
146
150
|
name = $1.downcase
|
147
151
|
start_routine(dest, from, name)
|
148
|
-
when /\A\s*see\s+(all\s+)?routines\s*$/i
|
152
|
+
when /\A\s*see\s+(all\s+)?routines\s*()$/i, /\A\s*see\s+(all\s+)?routines\s+(name|creator|status|next_run|last_run|command)\s+\/(.+)\/\s*$/i
|
149
153
|
all = $1.to_s != ""
|
150
|
-
|
154
|
+
header = $2.to_s.downcase
|
155
|
+
regexp = $3.to_s
|
156
|
+
see_routines(dest, from, user, all, header, regexp)
|
151
157
|
when /\A\s*get\s+bot\s+logs?\s*$/i
|
152
158
|
get_bot_logs(dest, from, typem)
|
153
159
|
when /\A\s*send\s+message\s+(on|to|in)\s+<(https?:[^:]+)>\s*:\s*(.+)\s*$/im,
|
@@ -158,25 +164,49 @@ class SlackSmartBot
|
|
158
164
|
thread_ts = ''
|
159
165
|
to_channel = ''
|
160
166
|
to = []
|
167
|
+
stats_from = ''
|
168
|
+
stats_to = ''
|
169
|
+
stats_channel_filter = ''
|
170
|
+
stats_command_filter = ''
|
161
171
|
|
162
172
|
opts.split(' ').each do |opt|
|
163
173
|
if opt.match?(/\Ahttps:/i)
|
164
174
|
to_channel, thread_ts = opt.scan(/\/archives\/(\w+)\/(\w\d+)/)[0]
|
165
175
|
to << to_channel
|
166
176
|
elsif opt.match(/<#([^>]+)\|.*>/) #channel
|
167
|
-
|
177
|
+
if stats_from == ''
|
178
|
+
to << $1
|
179
|
+
else
|
180
|
+
stats_channel_filter = $1
|
181
|
+
end
|
168
182
|
elsif opt.match(/#([^\s]+)/) #channel
|
169
|
-
|
183
|
+
if stats_from == ''
|
184
|
+
to << $1
|
185
|
+
else
|
186
|
+
stats_channel_filter = $1
|
187
|
+
end
|
170
188
|
elsif opt.match(/<@(\w+)>/)
|
171
189
|
to << $1
|
190
|
+
elsif opt.match(/\d{4}[\/\-]\d\d[\/\-]\d\d/)
|
191
|
+
if stats_from == ''
|
192
|
+
stats_from = opt
|
193
|
+
else
|
194
|
+
stats_to = opt
|
195
|
+
end
|
196
|
+
elsif stats_to!=''
|
197
|
+
stats_command_filter = opt
|
172
198
|
end
|
173
199
|
end
|
174
200
|
|
175
201
|
thread_ts.gsub!('.','')
|
176
|
-
send_message(dest, from, typem, to, thread_ts, message)
|
202
|
+
send_message(dest, from, typem, to, thread_ts, stats_from, stats_to, stats_channel_filter, stats_command_filter, message)
|
177
203
|
when /\A\s*delete\s+message\s+(http.+)\s*$/i
|
178
204
|
url = $1
|
179
205
|
delete_message(from, typem, url)
|
206
|
+
when /\A\s*update\s+message\s+(http[^\s]+)\s+(.+)\s*\z/mi
|
207
|
+
url = $1
|
208
|
+
text = Thread.current[:command_orig].scan(/\A\s*update\s+message\s+<?http[^\s]+\s+(.+)\s*\z/mi).join
|
209
|
+
update_message(from, typem, url, text)
|
180
210
|
when /\A\s*react\s+(on|to|in)\s*([^\s]+)\s+([p\d\.]+)\s+(.+)\s*$/i,
|
181
211
|
/\A\s*react\s+(on|to|in)\s*([^\s]+)\s+()(.+)\s*$/i
|
182
212
|
to = $2
|
@@ -2,12 +2,66 @@ class SlackSmartBot
|
|
2
2
|
def process_first(user, text, dest, dchannel, typem, files, ts, thread_ts, routine, routine_name, routine_type, command_orig)
|
3
3
|
nick = user.name
|
4
4
|
rules_file = ""
|
5
|
-
text.
|
5
|
+
if text.match(/\A\s*(stop|quit|exit|kill)\s+(iterator|iteration|loop)\s+(\d+)\s*\z/i)
|
6
|
+
save_stats :quit_loop, forced: true, data: {dest: dest, typem: typem, user: user, files: false, command: text, routine: routine}
|
7
|
+
num_iteration = $3.to_i
|
8
|
+
if config.admins.include?(user.name) or @loops.key?(user.name)
|
9
|
+
if config.admins.include?(user.name)
|
10
|
+
name_loop = ''
|
11
|
+
@loops.each do |k,v|
|
12
|
+
if v.include?(num_iteration)
|
13
|
+
name_loop = k
|
14
|
+
break
|
15
|
+
end
|
16
|
+
end
|
17
|
+
else
|
18
|
+
name_loop = user.name
|
19
|
+
end
|
20
|
+
if @loops.key?(name_loop) and @loops[name_loop].include?(num_iteration)
|
21
|
+
@loops[name_loop].delete(num_iteration)
|
22
|
+
respond "Loop #{num_iteration} stopped", dest, thread_ts: thread_ts
|
23
|
+
else
|
24
|
+
respond "You don't have any loop with id #{num_iteration}. Only the creator of the loop or an admin can stop the loop.", dest, thread_ts: thread_ts
|
25
|
+
end
|
26
|
+
else
|
27
|
+
respond "Only the creator of the loop or an admin can stop the loop.", dest, thread_ts: thread_ts
|
28
|
+
end
|
29
|
+
@logger.info "command: #{nick}> #{text}"
|
30
|
+
return :next #jal
|
31
|
+
end
|
32
|
+
if text.match(/\A\s*!*^?\s*(for\s*)?(\d+)\s+times\s+every\s+(\d+)\s*(m|minute|minutes|s|sc|second|seconds)\s+(.+)\s*\z/i)
|
33
|
+
save_stats :create_loop, forced: true, data: {dest: dest, typem: typem, user: user, files: false, command: text, routine: routine}
|
34
|
+
# min every 10s, max every 60m, max times 24
|
35
|
+
command_every = text.dup
|
36
|
+
text = $5
|
37
|
+
num_times = $2.to_i
|
38
|
+
type_every = $4.downcase
|
39
|
+
every_seconds = $3.to_i
|
40
|
+
command_every.gsub!(/^\s*!*^?\s*/, '')
|
41
|
+
every_seconds = (every_seconds * 60) if type_every[0] == "m"
|
42
|
+
if num_times > 24 or every_seconds < 10 or every_seconds > 3600
|
43
|
+
respond "You can't do that. Maximum times is 24, minimum every is 10 seconds, maximum every is 60 minutes.", dest, thread_ts: thread_ts
|
44
|
+
return :next #jal
|
45
|
+
end
|
46
|
+
@loops[user.name] ||= []
|
47
|
+
@num_loops ||= 0
|
48
|
+
@num_loops += 1
|
49
|
+
loop_id = @num_loops
|
50
|
+
@loops[user.name] << loop_id
|
51
|
+
respond "Loop #{loop_id} started. To stop the loop use: `#{['stop','quit','exit', 'kill'].sample} #{['iteration','iterator','loop'].sample} #{loop_id}`", dest, thread_ts: thread_ts
|
52
|
+
#todo: command_orig should be reasigned maybe to remove for N times every X seconds. Check.
|
53
|
+
else
|
54
|
+
command_every = ''
|
55
|
+
num_times = 1
|
56
|
+
every_seconds = 0
|
57
|
+
end
|
58
|
+
|
59
|
+
text.gsub!(/^!!/, "^") # to treat it just as ^
|
6
60
|
shared = []
|
7
|
-
if @shares.key?(@channels_name[dest]) and (ts.to_s!=
|
61
|
+
if @shares.key?(@channels_name[dest]) and (ts.to_s != "" or config.simulate) and (user.id != config.nick_id or (user.id == config.nick_id and !text.match?(/\A\*?Shares from channel/)))
|
8
62
|
@shares[@channels_name[dest]].each do |row|
|
9
|
-
if row[:user_deleted]==
|
10
|
-
if ((row[:type] ==
|
63
|
+
if row[:user_deleted] == ""
|
64
|
+
if ((row[:type] == "text" and text.include?(row[:condition][1..-2])) or (row[:type] == "regexp" and text.match?(/#{row[:condition][1..-2]}/im))) and !shared.include?(row[:to_channel])
|
11
65
|
if config.simulate
|
12
66
|
link = text
|
13
67
|
else
|
@@ -41,7 +95,7 @@ class SlackSmartBot
|
|
41
95
|
if @bots_created.key?(@rules_imported[user.name][user.name])
|
42
96
|
rules_file = @bots_created[@rules_imported[user.name][user.name]][:rules_file]
|
43
97
|
end
|
44
|
-
elsif dest[0] ==
|
98
|
+
elsif dest[0] == "D" and (!@rules_imported.key?(user.name) or (@rules_imported.key?(user.name) and !@rules_imported[user.name].key?(user.name)))
|
45
99
|
if File.exist?("#{config.path}/rules/general_rules.rb")
|
46
100
|
rules_file = "/rules/general_rules.rb"
|
47
101
|
end
|
@@ -98,18 +152,18 @@ class SlackSmartBot
|
|
98
152
|
|
99
153
|
#only for shortcuts
|
100
154
|
if text.match(/^@?(#{config[:nick]}):*\s+(.+)\s*/im) or
|
101
|
-
|
102
|
-
|
103
|
-
|
155
|
+
text.match(/^()\^\s*(.+)\s*/im) or
|
156
|
+
text.match(/^()!\s*(.+)\s*/im) or
|
157
|
+
text.match(/^()<@#{config[:nick_id]}>\s+(.+)\s*/im)
|
104
158
|
command2 = $2
|
105
159
|
if text.match?(/^()\^\s*(.+)/im)
|
106
160
|
add_double_excl = true
|
107
161
|
addexcl = false
|
108
162
|
if command2.match?(/^![^!]/) or command2.match?(/^\^/)
|
109
|
-
command2[0]=
|
163
|
+
command2[0] = ""
|
110
164
|
elsif command2.match?(/^!!/)
|
111
|
-
command2[0]=
|
112
|
-
command2[1]=
|
165
|
+
command2[0] = ""
|
166
|
+
command2[1] = ""
|
113
167
|
end
|
114
168
|
else
|
115
169
|
add_double_excl = false
|
@@ -118,14 +172,14 @@ class SlackSmartBot
|
|
118
172
|
command = command2
|
119
173
|
else
|
120
174
|
addexcl = false
|
121
|
-
if text.include?(
|
175
|
+
if text.include?("$") #for shortcuts inside commands
|
122
176
|
command = text.lstrip.rstrip
|
123
177
|
else
|
124
178
|
command = text.downcase.lstrip.rstrip
|
125
179
|
end
|
126
180
|
end
|
127
181
|
|
128
|
-
if command.include?(
|
182
|
+
if command.include?("$") #for adding shortcuts inside commands
|
129
183
|
command.scan(/\$([^\$]+)/i).flatten.each do |sc|
|
130
184
|
sc.strip!
|
131
185
|
if @shortcuts.key?(nick) and @shortcuts[nick].keys.include?(sc)
|
@@ -155,10 +209,10 @@ class SlackSmartBot
|
|
155
209
|
text = "^" + text if add_double_excl
|
156
210
|
end
|
157
211
|
if command.scan(/^(shortcut|sc)\s+([^:]+)\s*$/i).any? or
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
212
|
+
(@shortcuts.keys.include?(:all) and @shortcuts[:all].keys.include?(command)) or
|
213
|
+
(@shortcuts.keys.include?(nick) and @shortcuts[nick].keys.include?(command)) or
|
214
|
+
(@shortcuts_global.keys.include?(:all) and @shortcuts_global[:all].keys.include?(command)) or
|
215
|
+
(@shortcuts_global.keys.include?(nick) and @shortcuts_global[nick].keys.include?(command))
|
162
216
|
command = $2.downcase unless $2.nil?
|
163
217
|
if @shortcuts.keys.include?(nick) and @shortcuts[nick].keys.include?(command)
|
164
218
|
text = @shortcuts[nick][command].dup
|
@@ -178,209 +232,217 @@ class SlackSmartBot
|
|
178
232
|
|
179
233
|
command = text
|
180
234
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
235
|
+
num_times.times do |i|
|
236
|
+
command_thread = command.dup
|
237
|
+
begin
|
238
|
+
t = Thread.new do
|
239
|
+
begin
|
240
|
+
sleep every_seconds * i if every_seconds > 0
|
241
|
+
Thread.exit if command_every!='' and @loops.key?(user.name) and !@loops[user.name].include?(loop_id)
|
242
|
+
@logger.info "i: #{i}, num_times: #{num_times}, every_seconds: #{every_seconds}, command: #{command_thread}" if command_every!=''
|
243
|
+
processed = false
|
244
|
+
processed_rules = false
|
186
245
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
246
|
+
Thread.current[:dest] = dest
|
247
|
+
Thread.current[:user] = user
|
248
|
+
Thread.current[:command] = command_thread.dup
|
249
|
+
Thread.current[:rules_file] = rules_file
|
250
|
+
Thread.current[:typem] = typem
|
251
|
+
Thread.current[:files?] = !files.nil? && files.size > 0
|
252
|
+
Thread.current[:ts] = ts
|
253
|
+
Thread.current[:thread_ts] = thread_ts
|
254
|
+
Thread.current[:routine] = routine
|
255
|
+
Thread.current[:routine_name] = routine_name
|
256
|
+
Thread.current[:routine_type] = routine_type
|
257
|
+
Thread.current[:dchannel] = dchannel
|
258
|
+
Thread.current[:command_orig] = command_orig.dup
|
259
|
+
if thread_ts.to_s == ""
|
260
|
+
Thread.current[:on_thread] = false
|
261
|
+
Thread.current[:thread_ts] = Thread.current[:ts] # to create the thread if necessary
|
262
|
+
else
|
263
|
+
Thread.current[:on_thread] = true
|
264
|
+
end
|
265
|
+
if (dest[0] == "C") || (dest[0] == "G") and @rules_imported.key?(user.name) &&
|
266
|
+
@rules_imported[user.name].key?(dchannel) && @bots_created.key?(@rules_imported[user.name][dchannel])
|
208
267
|
Thread.current[:using_channel] = @rules_imported[user.name][dchannel]
|
209
|
-
|
210
|
-
|
268
|
+
elsif dest[0] == "D" && @rules_imported.key?(user.name) && @rules_imported[user.name].key?(user.name) and
|
269
|
+
@bots_created.key?(@rules_imported[user.name][user.name])
|
211
270
|
Thread.current[:using_channel] = @rules_imported[user.name][user.name]
|
212
|
-
|
213
|
-
Thread.current[:using_channel] =
|
214
|
-
end
|
215
|
-
if (typem == :on_pub or typem == :on_pg) and (!command.match?(/\s*bot\s+stats\s*(.*)\s*$/i) or dest!=@channels_id[config.stats_channel])
|
216
|
-
processed = false
|
217
|
-
else
|
218
|
-
processed = process(user, command, dest, dchannel, rules_file, typem, files, Thread.current[:thread_ts])
|
219
|
-
end
|
220
|
-
on_demand = false
|
221
|
-
if command.match(/\A@?(#{config[:nick]}):*\s+(.+)/im) or
|
222
|
-
command.match(/\A()!!(.+)/im) or
|
223
|
-
command.match(/\A()\^(.+)/im) or
|
224
|
-
command.match(/\A()!(.+)/im) or
|
225
|
-
command.match(/\A()<@#{config[:nick_id]}>\s+(.+)/im)
|
226
|
-
command2 = $2
|
227
|
-
Thread.current[:command] = command2
|
228
|
-
if command2.match?(/^()!!(.+)/im) or
|
229
|
-
command.match?(/^()\^(.+)/im)
|
230
|
-
Thread.current[:on_thread] = true
|
271
|
+
else
|
272
|
+
Thread.current[:using_channel] = ""
|
231
273
|
end
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
274
|
+
if (typem == :on_pub or typem == :on_pg) and (!command_thread.match?(/\s*bot\s+stats\s*(.*)\s*$/i) or dest != @channels_id[config.stats_channel])
|
275
|
+
processed = false
|
276
|
+
else
|
277
|
+
processed = process(user, command_thread, dest, dchannel, rules_file, typem, files, Thread.current[:thread_ts])
|
278
|
+
end
|
279
|
+
on_demand = false
|
280
|
+
if command_thread.match(/\A@?(#{config[:nick]}):*\s+(.+)/im) or
|
281
|
+
command_thread.match(/\A()!!(.+)/im) or
|
282
|
+
command_thread.match(/\A()\^(.+)/im) or
|
283
|
+
command_thread.match(/\A()!(.+)/im) or
|
284
|
+
command_thread.match(/\A()<@#{config[:nick_id]}>\s+(.+)/im)
|
285
|
+
command2 = $2
|
286
|
+
Thread.current[:command] = command2
|
287
|
+
if command2.match?(/^()!!(.+)/im) or
|
288
|
+
command_thread.match?(/^()\^(.+)/im)
|
289
|
+
Thread.current[:on_thread] = true
|
290
|
+
end
|
291
|
+
command_thread = command2
|
292
|
+
on_demand = true
|
293
|
+
end
|
294
|
+
unless config.on_maintenance or @status != :on
|
295
|
+
if typem == :on_pub or typem == :on_pg or typem == :on_extended
|
296
|
+
if command_thread.match(/\A\s*(#{@salutations.join("|")})\s+(rules|help)\s*(.+)?$/i) or command_thread.match(/\A(#{@salutations.join("|")}),? what can I do/i)
|
297
|
+
$2.to_s.match?(/rules/i) ? specific = true : specific = false
|
298
|
+
help_command = $3
|
299
|
+
if typem == :on_extended and specific
|
300
|
+
bot_rules(dest, help_command, typem, rules_file, user)
|
301
|
+
else
|
302
|
+
bot_help(user, user.name, dest, dchannel, specific, help_command, rules_file)
|
303
|
+
end
|
304
|
+
processed = true
|
244
305
|
end
|
245
|
-
|
246
|
-
|
306
|
+
end
|
307
|
+
processed = (processed || general_bot_commands(user, command_thread, dest, files))
|
308
|
+
processed = (processed || general_commands(user, command_thread, dest, files)) if defined?(general_commands)
|
309
|
+
@logger.info "command: #{nick}> #{command_thread}" if processed
|
247
310
|
end
|
248
|
-
processed = (processed || general_bot_commands(user, command, dest, files) )
|
249
|
-
processed = (processed || general_commands(user, command, dest, files) ) if defined?(general_commands)
|
250
|
-
@logger.info "command: #{nick}> #{command}" if processed
|
251
|
-
end
|
252
311
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
312
|
+
if !config.on_maintenance and !processed and typem != :on_pub and typem != :on_pg
|
313
|
+
if @status == :on and
|
314
|
+
(!answer.empty? or
|
315
|
+
(@repl_sessions.key?(nick) and dest == @repl_sessions[nick][:dest] and
|
316
|
+
((@repl_sessions[nick][:on_thread] and thread_ts == @repl_sessions[nick][:thread_ts]) or
|
317
|
+
(!@repl_sessions[nick][:on_thread] and !Thread.current[:on_thread]))) or
|
318
|
+
(@listening.key?(nick) and typem != :on_extended and
|
319
|
+
((@listening[nick].key?(dest) and !Thread.current[:on_thread]) or
|
320
|
+
(@listening[nick].key?(thread_ts) and Thread.current[:on_thread]))) or
|
321
|
+
dest[0] == "D" or on_demand)
|
322
|
+
@logger.info "command: #{nick}> #{command_thread}" unless processed
|
323
|
+
#todo: verify this
|
265
324
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
end
|
274
|
-
end
|
275
|
-
unless rules_file.empty?
|
276
|
-
begin
|
277
|
-
eval(File.new(config.path+rules_file).read) if File.exist?(config.path+rules_file)
|
278
|
-
rescue Exception => stack
|
279
|
-
@logger.fatal "ERROR ON RULES FILE: #{rules_file}"
|
280
|
-
@logger.fatal stack
|
281
|
-
end
|
282
|
-
if defined?(rules)
|
283
|
-
command[0] = "" if command[0] == "!"
|
284
|
-
command.gsub!(/^@\w+:*\s*/, "")
|
285
|
-
if method(:rules).parameters.size == 4
|
286
|
-
processed_rules = rules(user, command, processed, dest)
|
287
|
-
elsif method(:rules).parameters.size == 5
|
288
|
-
processed_rules = rules(user, command, processed, dest, files)
|
289
|
-
else
|
290
|
-
processed_rules = rules(user, command, processed, dest, files, rules_file)
|
325
|
+
if dest[0] == "C" or dest[0] == "G" or (dest[0] == "D" and typem == :on_call)
|
326
|
+
if typem != :on_call and @rules_imported.key?(user.name) and @rules_imported[user.name].key?(dchannel)
|
327
|
+
if @bots_created.key?(@rules_imported[user.name][dchannel])
|
328
|
+
if @bots_created[@rules_imported[user.name][dchannel]][:status] != :on
|
329
|
+
respond "The bot on that channel is not :on", dest
|
330
|
+
rules_file = ""
|
331
|
+
end
|
291
332
|
end
|
292
|
-
else
|
293
|
-
@logger.warn "It seems like rules method is not defined"
|
294
333
|
end
|
295
|
-
|
296
|
-
elsif @rules_imported.key?(user.name) and @rules_imported[user.name].key?(user.name)
|
297
|
-
if @bots_created.key?(@rules_imported[user.name][user.name])
|
298
|
-
if @bots_created[@rules_imported[user.name][user.name]][:status] == :on
|
334
|
+
unless rules_file.empty?
|
299
335
|
begin
|
300
|
-
eval(File.new(config.path+rules_file).read) if File.exist?(config.path
|
336
|
+
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file)
|
301
337
|
rescue Exception => stack
|
302
|
-
@logger.fatal "ERROR ON
|
338
|
+
@logger.fatal "ERROR ON RULES FILE: #{rules_file}"
|
303
339
|
@logger.fatal stack
|
304
340
|
end
|
305
|
-
|
306
|
-
|
307
|
-
|
341
|
+
if defined?(rules)
|
342
|
+
command_thread[0] = "" if command_thread[0] == "!"
|
343
|
+
command_thread.gsub!(/^@\w+:*\s*/, "")
|
344
|
+
if method(:rules).parameters.size == 4
|
345
|
+
processed_rules = rules(user, command_thread, processed, dest)
|
346
|
+
elsif method(:rules).parameters.size == 5
|
347
|
+
processed_rules = rules(user, command_thread, processed, dest, files)
|
348
|
+
else
|
349
|
+
processed_rules = rules(user, command_thread, processed, dest, files, rules_file)
|
350
|
+
end
|
351
|
+
else
|
352
|
+
@logger.warn "It seems like rules method is not defined"
|
353
|
+
end
|
354
|
+
end
|
355
|
+
elsif @rules_imported.key?(user.name) and @rules_imported[user.name].key?(user.name)
|
356
|
+
if @bots_created.key?(@rules_imported[user.name][user.name])
|
357
|
+
if @bots_created[@rules_imported[user.name][user.name]][:status] == :on
|
358
|
+
begin
|
359
|
+
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file) and ![".", ".."].include?(config.path + rules_file)
|
360
|
+
rescue Exception => stack
|
361
|
+
@logger.fatal "ERROR ON imported RULES FILE: #{rules_file}"
|
362
|
+
@logger.fatal stack
|
363
|
+
end
|
364
|
+
else
|
365
|
+
respond "The bot on <##{@rules_imported[user.name][user.name]}|#{@bots_created[@rules_imported[user.name][user.name]][:channel_name]}> is not :on", dest
|
366
|
+
rules_file = ""
|
367
|
+
end
|
308
368
|
end
|
309
|
-
end
|
310
369
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
370
|
+
unless rules_file.empty?
|
371
|
+
if defined?(rules)
|
372
|
+
command_thread[0] = "" if command_thread[0] == "!"
|
373
|
+
command_thread.gsub!(/^@\w+:*\s*/, "")
|
374
|
+
if method(:rules).parameters.size == 4
|
375
|
+
processed_rules = rules(user, command_thread, processed, dest)
|
376
|
+
elsif method(:rules).parameters.size == 5
|
377
|
+
processed_rules = rules(user, command_thread, processed, dest, files)
|
378
|
+
else
|
379
|
+
processed_rules = rules(user, command_thread, processed, dest, files, rules_file)
|
380
|
+
end
|
319
381
|
else
|
320
|
-
|
382
|
+
@logger.warn "It seems like rules method is not defined"
|
321
383
|
end
|
322
|
-
else
|
323
|
-
@logger.warn "It seems like rules method is not defined"
|
324
384
|
end
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
end
|
385
|
+
elsif dest[0] == "D" and
|
386
|
+
(!@rules_imported.key?(user.name) or (@rules_imported.key?(user.name) and !@rules_imported[user.name].key?(user.name))) and
|
387
|
+
rules_file.include?("general_rules.rb")
|
388
|
+
begin
|
389
|
+
eval(File.new(config.path + rules_file).read) if File.exist?(config.path + rules_file) and ![".", ".."].include?(config.path + rules_file)
|
390
|
+
rescue Exception => stack
|
391
|
+
@logger.fatal "ERROR ON imported RULES FILE: #{rules_file}"
|
392
|
+
@logger.fatal stack
|
393
|
+
end
|
335
394
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
395
|
+
if defined?(general_rules)
|
396
|
+
command_thread[0] = "" if command_thread[0] == "!"
|
397
|
+
command_thread.gsub!(/^@\w+:*\s*/, "")
|
398
|
+
#todo: check to change processed > processed_rules
|
399
|
+
if method(:general_rules).parameters.size == 4
|
400
|
+
processed = general_rules(user, command_thread, processed, dest)
|
401
|
+
elsif method(:general_rules).parameters.size == 5
|
402
|
+
processed = general_rules(user, command_thread, processed, dest, files)
|
403
|
+
else
|
404
|
+
processed = general_rules(user, command_thread, processed, dest, files, rules_file)
|
405
|
+
end
|
344
406
|
else
|
345
|
-
|
407
|
+
@logger.warn "It seems like general_rules method is not defined"
|
408
|
+
end
|
409
|
+
unless processed
|
410
|
+
dont_understand("")
|
346
411
|
end
|
347
412
|
else
|
348
|
-
@logger.
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
if command.match?(/^\s*bot\s+rules\s*(.*)$/i)
|
356
|
-
respond "No rules running. You can use the command `use rules from CHANNEL` to specify the rules you want to use on this private conversation.\n`bot help` to see available commands.", dest
|
357
|
-
end
|
358
|
-
unless processed
|
359
|
-
dont_understand('')
|
413
|
+
@logger.info "it is a direct message with no rules file selected so no rules file executed."
|
414
|
+
if command_thread.match?(/^\s*bot\s+rules\s*(.*)$/i)
|
415
|
+
respond "No rules running. You can use the command `use rules from CHANNEL` to specify the rules you want to use on this private conversation.\n`bot help` to see available commands.", dest
|
416
|
+
end
|
417
|
+
unless processed
|
418
|
+
dont_understand("")
|
419
|
+
end
|
360
420
|
end
|
361
|
-
end
|
362
421
|
|
363
|
-
|
422
|
+
processed = (processed_rules || processed)
|
364
423
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
424
|
+
if processed and @listening.key?(nick)
|
425
|
+
if Thread.current[:on_thread] and @listening[nick].key?(Thread.current[:thread_ts])
|
426
|
+
@listening[nick][Thread.current[:thread_ts]] = Time.now
|
427
|
+
elsif !Thread.current[:on_thread] and @listening[nick].key?(dest)
|
428
|
+
@listening[nick][dest] = Time.now
|
429
|
+
end
|
370
430
|
end
|
371
431
|
end
|
372
432
|
end
|
433
|
+
|
434
|
+
if processed and config.general_message != "" and !routine
|
435
|
+
respond eval("\"" + config.general_message + "\"")
|
436
|
+
end
|
437
|
+
respond "_*Loop #{loop_id}* (#{i+1}/#{num_times}) <@#{user.name}>: #{command_every}_" if command_every!='' and processed
|
438
|
+
@loops[user.name].delete(loop_id) if command_every!='' and !processed and @loops.key?(user.name) and @loops[user.name].include?(loop_id)
|
439
|
+
rescue Exception => stack
|
440
|
+
@logger.fatal stack
|
373
441
|
end
|
374
|
-
|
375
|
-
if processed and config.general_message != '' and !routine
|
376
|
-
respond eval("\"" + config.general_message + "\"")
|
377
|
-
end
|
378
|
-
rescue Exception => stack
|
379
|
-
@logger.fatal stack
|
380
442
|
end
|
443
|
+
rescue => e
|
444
|
+
@logger.error "exception: #{e.inspect}"
|
381
445
|
end
|
382
|
-
rescue => e
|
383
|
-
@logger.error "exception: #{e.inspect}"
|
384
446
|
end
|
385
447
|
end
|
386
448
|
end
|
@@ -290,7 +290,7 @@ class SlackSmartBot
|
|
290
290
|
end
|
291
291
|
|
292
292
|
else
|
293
|
-
@logger.warn "Pay attention there is no user on users with id #{data.user}" if user_info.nil?
|
293
|
+
@logger.warn "Pay attention there is no user on users with id #{data.user}" if user_info.nil? and data.user.to_s!=''
|
294
294
|
if !config.on_master_bot and !dest.nil? and (data.channel == @master_bot_id or dest[0] == "D") and
|
295
295
|
data.text.match?(/^\s*(!|!!|\^)?\s*bot\s+status\s*$/i) and @admin_users_id.include?(data.user)
|
296
296
|
respond "ping from #{config.channel}", dest
|
@@ -17,7 +17,7 @@ class SlackSmartBot
|
|
17
17
|
help_message[:admin][t.scan(/\/(\w+)$/).join.to_sym] = res[:admin]
|
18
18
|
help_message[:normal][t.scan(/\/(\w+)$/).join.to_sym] = res[:normal]
|
19
19
|
else
|
20
|
-
lines = IO.readlines(t)
|
20
|
+
lines = IO.readlines(t, encoding: 'UTF-8')
|
21
21
|
data = {master:{}, admin:{}, normal:{}}
|
22
22
|
data.master = lines.join #normal user help
|
23
23
|
data.admin = lines.reject {|l| l.match?(/^\s*#\s*help\s*master\s*:.+$/i)}.join #not master help
|