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
@@ -0,0 +1,202 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
def see_memos_team(user, type: "all", name: nil, topic: "", add_stats: true, team: nil)
|
3
|
+
save_stats(__method__) if add_stats
|
4
|
+
|
5
|
+
get_teams()
|
6
|
+
type = "all" if type.match?(/all\s+memo/i)
|
7
|
+
message = []
|
8
|
+
if @teams.size > 0
|
9
|
+
if team.nil?
|
10
|
+
@teams.each do |team_name, teamv|
|
11
|
+
if (team_name.to_s == name.to_s) or (name.to_s.gsub("-", "").gsub("_", "") == team_name.to_s)
|
12
|
+
if teamv.key?(:memos) and teamv[:memos].size > 0
|
13
|
+
team = teamv.deep_copy
|
14
|
+
else
|
15
|
+
respond "There are no memos for the team #{name}." unless !add_stats
|
16
|
+
end
|
17
|
+
break
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
if team
|
22
|
+
all_memos = {}
|
23
|
+
assigned_members, unassigned_members, not_on_team_channel, channels_members, all_team_members = get_team_members(team)
|
24
|
+
users_link = (Thread.current[:dest][0] == "D")
|
25
|
+
memos_filtered = []
|
26
|
+
all_topics = []
|
27
|
+
team[:memos].each do |memo|
|
28
|
+
if (type == "all" or type.to_s == memo[:type].to_s or type == "") and (topic == "" or memo[:topic].to_s.downcase == topic.to_s.downcase)
|
29
|
+
memos_filtered << memo
|
30
|
+
all_topics << memo.topic
|
31
|
+
end
|
32
|
+
end
|
33
|
+
all_topics.uniq!
|
34
|
+
all_topics.delete(:no_topic)
|
35
|
+
if memos_filtered.size >= 10 and !add_stats
|
36
|
+
message << " > *_memos_*"
|
37
|
+
message << " There are too many memos to show. "
|
38
|
+
message << " Please use the `see MEMO_TYPE team #{team.name} TOPIC` command."
|
39
|
+
message << " Available topics: #{all_topics.join(", ")}" if all_topics.size > 0
|
40
|
+
message << " Examples: `see bugs #{team.name} team`, `see all memos #{team.name} team #{all_topics.sample}`, `see tasks #{team.name} team #{all_topics.sample}`"
|
41
|
+
elsif memos_filtered.size > 0
|
42
|
+
memos_filtered.each do |memo|
|
43
|
+
if memo.privacy.empty? or
|
44
|
+
(memo.privacy == "private" and (all_team_members.include?(user.name) and (users_link or channels_members.include?(Thread.current[:dest])))) or
|
45
|
+
(memo.privacy == "personal" and memo.user == user.name and users_link)
|
46
|
+
if memo.type == "jira" and config.jira.host != ""
|
47
|
+
http = NiceHttp.new(config.jira.host)
|
48
|
+
http.headers.authorization = NiceHttpUtils.basic_authentication(user: config.jira.user, password: config.jira.password)
|
49
|
+
if memo.message.match?(/^\w+\-\d+$/)
|
50
|
+
resp = http.get("/rest/api/latest/issue/#{memo.message}")
|
51
|
+
issues = [resp.data.json] if resp.code == 200
|
52
|
+
else
|
53
|
+
resp = http.get("/rest/api/latest/search/?jql=#{memo.message}")
|
54
|
+
issues = resp.data.json().issues if resp.code == 200
|
55
|
+
end
|
56
|
+
if resp.code == 200
|
57
|
+
unless issues.empty?
|
58
|
+
issues.each do |issue|
|
59
|
+
jira_memo = { jira: true, github: false, status: "", memo_id: memo.memo_id, topic: memo.topic, privacy: memo.privacy, user: memo.user, date: memo.date, message: "", type: memo.type }
|
60
|
+
jira_memo.message = issue.fields.summary
|
61
|
+
jira_memo.user = issue.fields.reporter.name
|
62
|
+
jira_memo.date = issue.fields.created
|
63
|
+
if memo.topic == :no_topic and !issue.fields.labels.empty?
|
64
|
+
jira_memo.topic = issue.fields.labels.sort.join("_").split(" ").join("_")
|
65
|
+
end
|
66
|
+
case issue.fields.issuetype.name
|
67
|
+
when "Story"; jira_memo.type = ":abc:"
|
68
|
+
when "Bug"; jira_memo.type = ":bug:"
|
69
|
+
when "Task"; jira_memo.type = ":clock1:"
|
70
|
+
when "New Feature", "Improvement"; jira_memo.type = ":sunny:"
|
71
|
+
else jira_memo.type = ":memo:"
|
72
|
+
end
|
73
|
+
case issue.fields.status.statusCategory.name
|
74
|
+
when "Done"; jira_memo.status = ":heavy_check_mark:"
|
75
|
+
when "To Do"; jira_memo.status = ":new:"
|
76
|
+
when "In Progress"; jira_memo.status = ":runner:"
|
77
|
+
else jira_memo.status = ":heavy_minus_sign:"
|
78
|
+
end
|
79
|
+
#todo: check if possible to add link to status instead of jira issue
|
80
|
+
#jira_memo.status = " <#{config.jira.host}/browse/#{issue[:key]}|#{jira_memo.status}> "
|
81
|
+
jira_memo.status += " <#{config.jira.host}/browse/#{issue[:key]}|#{issue[:key]}>"
|
82
|
+
|
83
|
+
all_memos[jira_memo.topic] ||= []
|
84
|
+
all_memos[jira_memo.topic] << jira_memo
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
http.close
|
89
|
+
elsif memo.type == "github" and config.github.host != ""
|
90
|
+
http = NiceHttp.new(config.github.host)
|
91
|
+
http.headers.authorization = "token #{config.github.token}"
|
92
|
+
memo.message += "?" unless memo.message.include?("?")
|
93
|
+
memo.message += "&per_page=50"
|
94
|
+
|
95
|
+
resp = http.get("/repos/#{memo.message}")
|
96
|
+
issues = resp.data.json()
|
97
|
+
issues = [issues] unless issues.is_a?(Array)
|
98
|
+
if resp.code == 200
|
99
|
+
unless issues.empty?
|
100
|
+
issues.each do |issue|
|
101
|
+
github_memo = { jira: false, github: true, status: "", memo_id: memo.memo_id, topic: memo.topic, privacy: memo.privacy, user: memo.user, date: memo.date, message: "", type: memo.type }
|
102
|
+
github_memo.message = issue.title
|
103
|
+
github_memo.user = issue.user.login
|
104
|
+
github_memo.date = issue.created_at
|
105
|
+
if issue.labels.empty?
|
106
|
+
labels = ""
|
107
|
+
else
|
108
|
+
labels = issue.labels.name.sort.join("_").split(" ").join("_")
|
109
|
+
end
|
110
|
+
if memo.topic == :no_topic and !issue.labels.empty?
|
111
|
+
github_memo.topic = labels
|
112
|
+
end
|
113
|
+
case labels
|
114
|
+
when /bug/i; github_memo.type = ":bug:"
|
115
|
+
when /docum/i; github_memo.type = ":abc:"
|
116
|
+
when /task/i; github_memo.type = ":clock1:"
|
117
|
+
when /enhancem/i, /improvement/i; github_memo.type = ":sunny:"
|
118
|
+
else github_memo.type = ":memo:"
|
119
|
+
end
|
120
|
+
if issue.key?(:events_url)
|
121
|
+
resp_events = http.get(issue.events_url)
|
122
|
+
events = resp_events.data.json(:event)
|
123
|
+
issue.state = "in progress" if events.include?("referenced")
|
124
|
+
end
|
125
|
+
case issue.state
|
126
|
+
when "closed"; github_memo.status = ":heavy_check_mark:"
|
127
|
+
when "open"; github_memo.status = ":new:"
|
128
|
+
when "in progress"; github_memo.status = ":runner:"
|
129
|
+
else github_memo.status = ":heavy_minus_sign:"
|
130
|
+
end
|
131
|
+
#todo: check if possible to add link to status instead of github issue
|
132
|
+
github_memo.status += " <#{issue.html_url}|##{issue.number}>"
|
133
|
+
|
134
|
+
all_memos[github_memo.topic] ||= []
|
135
|
+
all_memos[github_memo.topic] << github_memo
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
http.close
|
140
|
+
else
|
141
|
+
memo.jira = false
|
142
|
+
memo.github = false
|
143
|
+
all_memos[memo.topic] ||= []
|
144
|
+
case memo.type
|
145
|
+
when "memo"; memo.type = ":memo:"
|
146
|
+
when "note"; memo.type = ":abc:"
|
147
|
+
when "bug"; memo.type = ":bug:"
|
148
|
+
when "task"; memo.type = ":clock1:"
|
149
|
+
when "feature"; memo.type = ":sunny:"
|
150
|
+
when "issue"; memo.type = ":hammer:"
|
151
|
+
else memo.type = ":heavy_minus_sign:"
|
152
|
+
end
|
153
|
+
all_memos[memo.topic] << memo
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
if !add_stats
|
158
|
+
message << " > *_memos_*" unless all_memos.empty?
|
159
|
+
else
|
160
|
+
message << " > *_#{team.name} team #{type}_*"
|
161
|
+
end
|
162
|
+
|
163
|
+
if all_memos.key?(:no_topic)
|
164
|
+
all_memos[:no_topic].sort_by { |memo| memo[:date] }.each do |memo|
|
165
|
+
case memo.privacy
|
166
|
+
when "private"; priv = " `private`"
|
167
|
+
when "personal"; priv = " `personal`"
|
168
|
+
else priv = ""
|
169
|
+
end
|
170
|
+
message << " #{memo.type} #{memo.date.gsub("-", "/")[0..9]}: #{memo.status} #{memo.message} (#{memo.user} #{memo.memo_id})#{priv}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
all_memos[:no_topic] = []
|
174
|
+
all_memos.each do |topic, mems|
|
175
|
+
unless mems.empty?
|
176
|
+
message << " _`#{topic}`_:"
|
177
|
+
mems.sort_by { |m| m[:date] }.each do |memo|
|
178
|
+
case memo.privacy
|
179
|
+
when "private"; priv = " `private`"
|
180
|
+
when "personal"; priv = " `personal`"
|
181
|
+
else priv = ""
|
182
|
+
end
|
183
|
+
message << " #{memo.type} #{memo.date.gsub("-", "/")[0..9]}: #{memo.status} #{memo.message} (#{memo.user} #{memo.memo_id})#{priv}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
else
|
188
|
+
message << "There are no memos #{type} #{topic}." unless !add_stats
|
189
|
+
end
|
190
|
+
else
|
191
|
+
respond "There is no team named #{name}." unless !add_stats
|
192
|
+
end
|
193
|
+
if add_stats
|
194
|
+
respond message.join("\n")
|
195
|
+
else
|
196
|
+
return message
|
197
|
+
end
|
198
|
+
else
|
199
|
+
respond "There are no teams added yet\. Use `add team` command to add a team" unless !add_stats
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -62,39 +62,8 @@ class SlackSmartBot
|
|
62
62
|
|
63
63
|
message << " > *_members_*"
|
64
64
|
|
65
|
-
assigned_members = team
|
66
|
-
|
67
|
-
assigned_members.dup.each do |m|
|
68
|
-
user_info = @users.select { |u| u.id == m or (u.key?(:enterprise_user) and u.enterprise_user.id == m) or u.name == m or (u.key?(:enterprise_user) and u.enterprise_user.name == m) }[-1]
|
69
|
-
assigned_members.delete(m) if user_info.nil? or user_info.deleted
|
70
|
-
end
|
71
|
-
channels_members = []
|
72
|
-
all_team_members = assigned_members.dup
|
73
|
-
if team.channels.key?("members")
|
74
|
-
team_members = []
|
75
|
-
team.channels["members"].each do |ch|
|
76
|
-
get_channels_name_and_id() unless @channels_id.key?(ch)
|
77
|
-
tm = get_channel_members(@channels_id[ch])
|
78
|
-
if tm.nil?
|
79
|
-
respond ":exclamation: Add the Smart Bot to *##{ch}* channel to be able to get the list of members.", dest
|
80
|
-
else
|
81
|
-
channels_members << @channels_id[ch]
|
82
|
-
tm.each do |m|
|
83
|
-
user_info = @users.select { |u| u.id == m or (u.key?(:enterprise_user) and u.enterprise_user.id == m) }[-1]
|
84
|
-
team_members << user_info.name unless user_info.is_app_user or user_info.is_bot
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
team_members.flatten!
|
89
|
-
team_members.uniq!
|
90
|
-
unassigned_members = team_members - assigned_members
|
91
|
-
unassigned_members.delete(config.nick)
|
92
|
-
not_on_team_channel = assigned_members - team_members
|
93
|
-
all_team_members += team_members
|
94
|
-
else
|
95
|
-
unassigned_members = []
|
96
|
-
not_on_team_channel = []
|
97
|
-
end
|
65
|
+
assigned_members, unassigned_members, not_on_team_channel, channels_members, all_team_members = get_team_members(team)
|
66
|
+
|
98
67
|
unless unassigned_members.empty?
|
99
68
|
um = unassigned_members.dup
|
100
69
|
um.each do |m|
|
@@ -217,148 +186,7 @@ class SlackSmartBot
|
|
217
186
|
end
|
218
187
|
|
219
188
|
unless !team.key?(:memos) or team.memos.empty? or (team_name.to_s == "" and search.to_s == "")
|
220
|
-
|
221
|
-
team.memos.each do |memo|
|
222
|
-
if memo.privacy.empty? or
|
223
|
-
(memo.privacy == "private" and (all_team_members.include?(user.name) and (users_link or channels_members.include?(Thread.current[:dest])))) or
|
224
|
-
(memo.privacy == "personal" and memo.user == user.name and users_link)
|
225
|
-
if memo.type == "jira" and config.jira.host != ""
|
226
|
-
http = NiceHttp.new(config.jira.host)
|
227
|
-
http.headers.authorization = NiceHttpUtils.basic_authentication(user: config.jira.user, password: config.jira.password)
|
228
|
-
if memo.message.match?(/^\w+\-\d+$/)
|
229
|
-
resp = http.get("/rest/api/latest/issue/#{memo.message}")
|
230
|
-
issues = [resp.data.json] if resp.code == 200
|
231
|
-
else
|
232
|
-
resp = http.get("/rest/api/latest/search/?jql=#{memo.message}")
|
233
|
-
issues = resp.data.json().issues if resp.code == 200
|
234
|
-
end
|
235
|
-
if resp.code == 200
|
236
|
-
unless issues.empty?
|
237
|
-
issues.each do |issue|
|
238
|
-
jira_memo = { jira: true, github: false, status: "", memo_id: memo.memo_id, topic: memo.topic, privacy: memo.privacy, user: memo.user, date: memo.date, message: "", type: memo.type }
|
239
|
-
jira_memo.message = issue.fields.summary
|
240
|
-
jira_memo.user = issue.fields.reporter.name
|
241
|
-
jira_memo.date = issue.fields.created
|
242
|
-
if memo.topic == :no_topic and !issue.fields.labels.empty?
|
243
|
-
jira_memo.topic = issue.fields.labels.sort.join("_").split(" ").join("_")
|
244
|
-
end
|
245
|
-
case issue.fields.issuetype.name
|
246
|
-
when "Story"; jira_memo.type = ":abc:"
|
247
|
-
when "Bug"; jira_memo.type = ":bug:"
|
248
|
-
when "Task"; jira_memo.type = ":clock1:"
|
249
|
-
when "New Feature", "Improvement"; jira_memo.type = ":sunny:"
|
250
|
-
else jira_memo.type = ":memo:"
|
251
|
-
end
|
252
|
-
case issue.fields.status.statusCategory.name
|
253
|
-
when "Done"; jira_memo.status = ":heavy_check_mark:"
|
254
|
-
when "To Do"; jira_memo.status = ":new:"
|
255
|
-
when "In Progress"; jira_memo.status = ":runner:"
|
256
|
-
else jira_memo.status = ":heavy_minus_sign:"
|
257
|
-
end
|
258
|
-
#todo: check if possible to add link to status instead of jira issue
|
259
|
-
#jira_memo.status = " <#{config.jira.host}/browse/#{issue[:key]}|#{jira_memo.status}> "
|
260
|
-
jira_memo.status += " <#{config.jira.host}/browse/#{issue[:key]}|#{issue[:key]}>"
|
261
|
-
|
262
|
-
all_memos[jira_memo.topic] ||= []
|
263
|
-
all_memos[jira_memo.topic] << jira_memo
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
http.close
|
268
|
-
elsif memo.type == "github" and config.github.host != ""
|
269
|
-
http = NiceHttp.new(config.github.host)
|
270
|
-
http.headers.authorization = "token #{config.github.token}"
|
271
|
-
memo.message+="?" unless memo.message.include?('?')
|
272
|
-
memo.message+="&per_page=50"
|
273
|
-
|
274
|
-
resp = http.get("/repos/#{memo.message}")
|
275
|
-
issues = resp.data.json()
|
276
|
-
issues = [issues] unless issues.is_a?(Array)
|
277
|
-
if resp.code == 200
|
278
|
-
unless issues.empty?
|
279
|
-
issues.each do |issue|
|
280
|
-
github_memo = { jira: false, github: true, status: "", memo_id: memo.memo_id, topic: memo.topic, privacy: memo.privacy, user: memo.user, date: memo.date, message: "", type: memo.type }
|
281
|
-
github_memo.message = issue.title
|
282
|
-
github_memo.user = issue.user.login
|
283
|
-
github_memo.date = issue.created_at
|
284
|
-
if issue.labels.empty?
|
285
|
-
labels = ''
|
286
|
-
else
|
287
|
-
labels = issue.labels.name.sort.join("_").split(" ").join("_")
|
288
|
-
end
|
289
|
-
if memo.topic == :no_topic and !issue.labels.empty?
|
290
|
-
github_memo.topic = labels
|
291
|
-
end
|
292
|
-
case labels
|
293
|
-
when /bug/i; github_memo.type = ":bug:"
|
294
|
-
when /docum/i; github_memo.type = ":abc:"
|
295
|
-
when /task/i; github_memo.type = ":clock1:"
|
296
|
-
when /enhancem/i, /improvement/i; github_memo.type = ":sunny:"
|
297
|
-
else github_memo.type = ":memo:"
|
298
|
-
end
|
299
|
-
if issue.key?(:events_url)
|
300
|
-
resp_events = http.get(issue.events_url)
|
301
|
-
events = resp_events.data.json(:event)
|
302
|
-
issue.state = "in progress" if events.include?('referenced')
|
303
|
-
end
|
304
|
-
case issue.state
|
305
|
-
when "closed"; github_memo.status = ":heavy_check_mark:"
|
306
|
-
when "open"; github_memo.status = ":new:"
|
307
|
-
when "in progress"; github_memo.status = ":runner:"
|
308
|
-
else github_memo.status = ":heavy_minus_sign:"
|
309
|
-
end
|
310
|
-
#todo: check if possible to add link to status instead of github issue
|
311
|
-
github_memo.status += " <#{issue.html_url}|##{issue.number}>"
|
312
|
-
|
313
|
-
all_memos[github_memo.topic] ||= []
|
314
|
-
all_memos[github_memo.topic] << github_memo
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
318
|
-
http.close
|
319
|
-
else
|
320
|
-
memo.jira = false
|
321
|
-
memo.github = false
|
322
|
-
all_memos[memo.topic] ||= []
|
323
|
-
case memo.type
|
324
|
-
when "memo"; memo.type = ":memo:"
|
325
|
-
when "note"; memo.type = ":abc:"
|
326
|
-
when "bug"; memo.type = ":bug:"
|
327
|
-
when "task"; memo.type = ":clock1:"
|
328
|
-
when "feature"; memo.type = ":sunny:"
|
329
|
-
when "issue"; memo.type = ":hammer:"
|
330
|
-
else memo.type = ":heavy_minus_sign:"
|
331
|
-
end
|
332
|
-
all_memos[memo.topic] << memo
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
message << " > *_memos_*" unless all_memos.empty?
|
337
|
-
|
338
|
-
if all_memos.key?(:no_topic)
|
339
|
-
all_memos[:no_topic].sort_by { |memo| memo[:date] }.each do |memo|
|
340
|
-
case memo.privacy
|
341
|
-
when "private"; priv = " `private`"
|
342
|
-
when "personal"; priv = " `personal`"
|
343
|
-
else priv = ""
|
344
|
-
end
|
345
|
-
message << " #{memo.type} #{memo.date.gsub("-", "/")[0..9]}: #{memo.status} #{memo.message} (#{memo.user} #{memo.memo_id})#{priv}"
|
346
|
-
end
|
347
|
-
end
|
348
|
-
all_memos[:no_topic] = []
|
349
|
-
all_memos.each do |topic, mems|
|
350
|
-
unless mems.empty?
|
351
|
-
message << " _`#{topic}`_:"
|
352
|
-
mems.sort_by { |m| m[:date] }.each do |memo|
|
353
|
-
case memo.privacy
|
354
|
-
when "private"; priv = " `private`"
|
355
|
-
when "personal"; priv = " `personal`"
|
356
|
-
else priv = ""
|
357
|
-
end
|
358
|
-
message << " #{memo.type} #{memo.date.gsub("-", "/")[0..9]}: #{memo.status} #{memo.message} (#{memo.user} #{memo.memo_id})#{priv}"
|
359
|
-
end
|
360
|
-
end
|
361
|
-
end
|
189
|
+
message += see_memos_team(user, type: "all", add_stats: false, team: team)
|
362
190
|
end
|
363
191
|
|
364
192
|
unless team.info.empty?
|
@@ -1,10 +1,11 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
def see_vacations(user, from_user: '', add_stats: true)
|
2
|
+
def see_vacations(user, dest, from_user: '', add_stats: true, year: '')
|
3
3
|
save_stats(__method__) if add_stats
|
4
4
|
|
5
5
|
get_vacations()
|
6
6
|
|
7
7
|
from_user_name = ''
|
8
|
+
year = Date.today.year if year.to_s == ''
|
8
9
|
|
9
10
|
if from_user.empty?
|
10
11
|
from_user_name = user.name
|
@@ -13,8 +14,8 @@ class SlackSmartBot
|
|
13
14
|
user_info = @users.select{|u| u.id == from_user or (u.key?(:enterprise_user) and u.enterprise_user.id == from_user)}[-1]
|
14
15
|
from_user_name = user_info.name
|
15
16
|
end
|
16
|
-
|
17
|
-
if !@vacations.key?(from_user_name) or @vacations[from_user_name].periods.empty?
|
17
|
+
from_user = '' if from_user_name == user.name
|
18
|
+
if !@vacations.key?(from_user_name) or !@vacations[from_user_name].key?(:periods) or @vacations[from_user_name].periods.empty?
|
18
19
|
if from_user.empty?
|
19
20
|
respond "You didn't add any time off yet. Use `add vacation from YYYY/MM/DD to YYYY/MM/DD`"
|
20
21
|
else
|
@@ -22,36 +23,55 @@ class SlackSmartBot
|
|
22
23
|
end
|
23
24
|
else
|
24
25
|
messages = []
|
25
|
-
messages << "*Time off <@#{from_user}
|
26
|
+
messages << "*Time off <@#{from_user}> #{year}*" if !from_user.empty?
|
27
|
+
|
28
|
+
display_calendar(from_user_name, year) if from_user_name == user.name and dest[0] == 'D'
|
29
|
+
|
26
30
|
today = Date.today.strftime("%Y/%m/%d")
|
27
31
|
current_added = false
|
28
32
|
past_added = false
|
29
33
|
@vacations[from_user_name].periods.sort_by { |v| v[:from]}.reverse.each do |vac|
|
30
|
-
if !current_added and vac.to >= today
|
34
|
+
if !current_added and vac.to >= today
|
31
35
|
messages << "*Current and future periods*"
|
32
36
|
current_added = true
|
33
37
|
end
|
34
|
-
if !past_added and vac.to < today and from_user.empty?
|
35
|
-
|
36
|
-
|
38
|
+
if !past_added and vac.to < today and from_user.empty? and vac.to[0..3] == year
|
39
|
+
if dest[0]=='D'
|
40
|
+
messages << "\n*Past periods #{year}*"
|
41
|
+
past_added = true
|
42
|
+
else
|
43
|
+
messages << "To see past periods call me from a DM"
|
44
|
+
break
|
45
|
+
end
|
37
46
|
end
|
38
47
|
unless !from_user.empty? and vac.to < today
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
if vac.to[0..3] == year
|
49
|
+
if !from_user.empty?
|
50
|
+
icon = ":beach_with_umbrella:"
|
51
|
+
elsif vac.type == 'vacation'
|
52
|
+
icon = ':palm_tree:'
|
53
|
+
elsif vac.type == 'sick'
|
54
|
+
icon = ':face_with_thermometer:'
|
55
|
+
elsif vac.type == 'sick child'
|
56
|
+
icon = ':baby:'
|
57
|
+
end
|
58
|
+
if vac.from == vac.to
|
59
|
+
messages << " #{icon} #{vac.from} ##{vac.vacation_id}"
|
60
|
+
else
|
61
|
+
messages << " #{icon} #{vac.from} -> #{vac.to} ##{vac.vacation_id}"
|
62
|
+
end
|
52
63
|
end
|
53
64
|
end
|
54
65
|
end
|
66
|
+
if !past_added and !current_added and dest[0]=='D'
|
67
|
+
if from_user.empty?
|
68
|
+
messages << "No time off added yet for #{year}"
|
69
|
+
else
|
70
|
+
messages << "Not possible to see past periods for another user"
|
71
|
+
end
|
72
|
+
elsif !past_added and dest[0]=='D' and !from_user.empty? and from_user_name != user.name
|
73
|
+
messages << "Not possible to see past periods for another user"
|
74
|
+
end
|
55
75
|
respond messages.join("\n")
|
56
76
|
end
|
57
77
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
def set_public_holidays(country, state, user)
|
3
|
+
save_stats(__method__)
|
4
|
+
|
5
|
+
result = public_holidays(country, state, Date.today.year.to_s, '', '', add_stats: false, publish_results: false)
|
6
|
+
if result == true
|
7
|
+
if state == ""
|
8
|
+
country_region = country
|
9
|
+
else
|
10
|
+
country_region = "#{country}/#{state}"
|
11
|
+
end
|
12
|
+
respond "Public holidays for *#{country_region}* set."
|
13
|
+
get_vacations()
|
14
|
+
@vacations[user.name] ||= {}
|
15
|
+
@vacations[user.name][:public_holidays] = country_region
|
16
|
+
update_vacations()
|
17
|
+
else
|
18
|
+
respond "Be sure the country and state are correct."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -32,6 +32,7 @@ class SlackSmartBot
|
|
32
32
|
team = @teams[team_name.to_sym].deep_copy
|
33
33
|
@teams[new_name.to_sym] = team
|
34
34
|
@teams.delete(team_name.to_sym)
|
35
|
+
File.delete(File.join(config.path, "teams", "t_#{team_name}.yaml"))
|
35
36
|
message = "The *#{team_name}* team has been renamed #{new_name}."
|
36
37
|
team_name = new_name
|
37
38
|
elsif new_info != ""
|