slack-smart-bot 1.7.0 → 1.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd95efb0ac282a17d1b463fe28293643c0b38b91b3261e0d3899e879950e4655
4
- data.tar.gz: 1d332d2651286f4bef95c1172d95bc6ce422166b50bf788773563747ebbf1c30
3
+ metadata.gz: b15c46b5b101a0a31487508457982e8f5d6b81ad41f54338407ecdb2aa9974f3
4
+ data.tar.gz: d32bfceda9068f5f11d1002f255b77a280f3a7b7068f40a632c03b7cb6378127
5
5
  SHA512:
6
- metadata.gz: f48dc2999a22da392d297cb789dfcc7552ce1ef7aad607283f705d39af5eac58ce2ca002b844178184e6bacdc13fe641ddbe762f8a999b17da7532a5cad234b8
7
- data.tar.gz: f4ac49668234f24295e79afd842218e40a1a918c1107392af84d3b31c6d8908fadb8319f2e4596ef896c44e7c36665714523fc554f4c8b70a3a5a1f02cc2c872
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
@@ -391,6 +394,7 @@ Examples:
391
394
  >**_`add routine run_tests every 3h !run tests on customers`_**
392
395
  >**_`add routine clean_db at 17:05 !clean customers temp db`_**
393
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`_**
394
398
 
395
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.
396
400
 
@@ -8,12 +8,15 @@ def general_rules(user, command, processed, dest, files = [], rules_file = "")
8
8
 
9
9
  # help: ----------------------------------------------
10
10
  # help: `echo SOMETHING`
11
- # help: repeats SOMETHING
11
+ # help: `INTEGER echo SOMETHING`
12
+ # help: repeats SOMETHING. If INTEGER supplied then that number of times.
12
13
  # help: Examples:
13
14
  # help: _echo I am the Smart Bot_
14
- when /^echo\s(.+)/i
15
- save_stats :echo
16
- respond $1
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
17
20
 
18
21
  else
19
22
  return false
@@ -60,6 +60,7 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
60
60
  respond "zZzzzzzZZZZZZzzzzzzz!"
61
61
  react :sleeping
62
62
  sleep 5
63
+ unreact :sleeping
63
64
  react :sunny
64
65
  when /no/i, /nope/i, /cancel/i
65
66
  @questions.delete(from)
@@ -81,6 +82,7 @@ def rules(user, command, processed, dest, files = [], rules_file = "")
81
82
  process_to_run = "ruby -v"
82
83
  process_to_run = ("cd #{project_folder} &&" + process_to_run) if defined?(project_folder)
83
84
  stdout, stderr, status = Open3.capture3(process_to_run)
85
+ unreact :runner
84
86
  if stderr == ""
85
87
  if stdout == ""
86
88
  respond "#{display_name}: Nothing returned."
@@ -5,4 +5,5 @@ require_relative 'comm/respond'
5
5
  require_relative 'comm/send_file'
6
6
  require_relative 'comm/send_msg_channel'
7
7
  require_relative 'comm/send_msg_user'
8
- require_relative 'comm/react'
8
+ require_relative 'comm/react'
9
+ require_relative 'comm/unreact'
@@ -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
@@ -8,7 +8,7 @@ class SlackSmartBot
8
8
  def send_file(to, msg, file, title, format, type = "text", content: '')
9
9
  unless config[:simulate]
10
10
  file = 'myfile' if file.to_s == '' and content!=''
11
- if to[0] == "U" #user
11
+ if to[0] == "U" or to[0] == "W" #user
12
12
  im = client.web_client.im_open(user: to)
13
13
  channel = im["channel"]["id"]
14
14
  else
@@ -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 == "at") && !number_time.match?(/^[01][0-9]:[0-5][0-9]:[0-5][0-9]$/) &&
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 day
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 }
@@ -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] !=''
@@ -22,7 +22,7 @@ class SlackSmartBot
22
22
  # helpadmin: _bot stats @peter.wind_
23
23
  # helpadmin: _bot stats #sales from 2019/12/15 to 2019/12/31_
24
24
  # helpadmin: _bot stats #sales today_
25
- # helpadmin: _bot stats #sales monthly_
25
+ # helpadmin: _bot stats #sales from 2020-01-01 monthly_
26
26
  # helpadmin:
27
27
  def bot_stats(dest, from_user, typem, channel_id, from, to, user, exclude_masters, exclude_command, monthly)
28
28
  require 'csv'
@@ -36,6 +36,10 @@ class SlackSmartBot
36
36
  if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
37
37
  message<<'No stats'
38
38
  else
39
+ if user!=''
40
+ user_info = client.web_client.users_info(user: user)
41
+ user_name = user_info.user.name
42
+ end
39
43
  from = "#{Time.now.strftime("%Y-%m")}-01" if from == ''
40
44
  to = "#{Time.now.strftime("%Y-%m-%d")}" if to == ''
41
45
  from_short = from
@@ -46,20 +50,26 @@ class SlackSmartBot
46
50
  to+= " 23:59:59 +0000"
47
51
  rows = []
48
52
  rows_month = {}
53
+ users_month = {}
54
+ commands_month = {}
49
55
 
50
56
  Dir["#{config.stats_path}.*.log"].sort.each do |file|
51
57
  if file >= "#{config.stats_path}.#{from_file}.log" or file <= "#{config.stats_path}.#{to_file}.log"
52
58
  CSV.foreach(file, headers: true, header_converters: :symbol, converters: :numeric) do |row|
53
59
  row[:date] = row[:date].to_s
54
60
  if !exclude_masters or (exclude_masters and !config.masters.include?(row[:user_name]))
55
- if user=='' or (user!='' and row[:user_id] == user)
61
+ if user=='' or (user!='' and row[:user_name] == user_name)
56
62
  if exclude_command == '' or (exclude_command!='' and row[:command]!=exclude_command)
57
63
  if row[:bot_channel_id] == channel_id or channel_id == ''
58
64
  if row[:date] >= from and row[:date] <= to
59
65
  rows << row.to_h
60
66
  if monthly
61
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])
62
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]
63
73
  end
64
74
  end
65
75
  end
@@ -87,9 +97,18 @@ class SlackSmartBot
87
97
  end
88
98
  if total > 0
89
99
  if monthly
90
- message << '*Totals by month*'
100
+ message << '*Totals by month / commands / users (%new)*'
101
+ all_users = []
102
+ new_users = []
91
103
  rows_month.each do |k,v|
92
- message << "\t#{k}: #{v} (#{(v.to_f*100/total).round(2)}%)"
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}"
93
112
  end
94
113
  end
95
114
 
@@ -102,16 +121,16 @@ class SlackSmartBot
102
121
  end
103
122
  end
104
123
  if user==''
105
- message << "*Users*"
106
124
  users = rows.user_name.uniq.sort
125
+ message << "*Users* - #{users.size}"
107
126
  users.each do |user|
108
127
  count = rows.count {|h| h.user_name==user}
109
128
  message << "\t#{user}: #{count} (#{(count.to_f*100/total).round(2)}%)"
110
129
  end
111
130
  end
112
131
 
113
- message << "*Commands*"
114
132
  commands = rows.command.uniq.sort
133
+ message << "*Commands* - #{commands.size}"
115
134
  commands.each do |command|
116
135
  count = rows.count {|h| h.command==command}
117
136
  message << "\t#{command}: #{count} (#{(count.to_f*100/total).round(2)}%)"
@@ -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
- /^\s*(add|create)\s+(silent\s+)?routine\s+(\w+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i
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
@@ -117,6 +117,7 @@ class SlackSmartBot
117
117
  begin
118
118
  #todo: when changed @questions user_id then move user_info inside the ifs to avoid calling it when not necessary
119
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
120
121
  if @questions.key?(user_info.user.name)
121
122
  if data.text.match?(/^\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i)
122
123
  @questions.delete(user_info.user.name)
@@ -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 started.strftime("%H:%M:%S") < @routines[@channel_id][name][:at]
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
- next_run = started + (24 * 60 * 60) # one more day
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
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.7.0
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-05-27 00:00:00.000000000 Z
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.14.6
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.14.6
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
@@ -81,7 +81,7 @@ dependencies:
81
81
  version: '1'
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
- version: 1.1.0
84
+ version: 1.2.1
85
85
  type: :runtime
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
@@ -91,7 +91,7 @@ dependencies:
91
91
  version: '1'
92
92
  - - ">="
93
93
  - !ruby/object:Gem::Version
94
- version: 1.1.0
94
+ version: 1.2.1
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: rspec
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,7 @@ files:
136
136
  - lib/slack/smart-bot/comm/send_file.rb
137
137
  - lib/slack/smart-bot/comm/send_msg_channel.rb
138
138
  - lib/slack/smart-bot/comm/send_msg_user.rb
139
+ - lib/slack/smart-bot/comm/unreact.rb
139
140
  - lib/slack/smart-bot/commands.rb
140
141
  - lib/slack/smart-bot/commands/general/bot_help.rb
141
142
  - lib/slack/smart-bot/commands/general/bot_status.rb