forked from hubot-archive/hubot-standup-alarm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstandup.coffee
236 lines (208 loc) · 9.09 KB
/
standup.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# Description:
# Have Hubot remind you to do standups.
# hh:mm must be in the same timezone as the server Hubot is on. Probably UTC.
#
# This is configured to work for Hipchat. You may need to change the 'create
# standup' command to match the adapter you're using.
#
# Configuration:
# HUBOT_STANDUP_PREPEND
#
# Commands:
# hubot standup help - See a help document explaining how to use.
# hubot create standup hh:mm - Creates a standup at hh:mm every weekday for this room
# hubot create standup hh:mm at location/url - Creates a standup at hh:mm (UTC) every weekday for this chat room with a reminder for a physical location or url
# hubot create standup Monday@hh:mm - Creates a standup at hh:mm every Monday for this room
# hubot create standup hh:mm UTC+2 - Creates a standup at hh:mm every weekday for this room (relative to UTC)
# hubot create standup Monday@hh:mm UTC+2 - Creates a standup at hh:mm every Monday for this room (relative to UTC)
# hubot list standups - See all standups for this room
# hubot list all standups - See all standups in every room
# hubot delete standup hh:mm - If you have a standup on weekdays at hh:mm, delete it. Can also supply a weekday and/or UTC offset
# hubot delete all standups - Deletes all standups for this room.
#
# Dependencies:
# underscore
# cron
###jslint node: true###
cronJob = require('cron').CronJob
_ = require('underscore')
module.exports = (robot) ->
# Compares current time to the time of the standup to see if it should be fired.
standupShouldFire = (standup) ->
standupTime = standup.time
standupDayOfWeek = getDayOfWeek(standup.dayOfWeek)
now = new Date()
standupDate = new Date()
utcOffset = -standup.utc or (now.getTimezoneOffset() / 60)
standupHours = parseInt(standupTime.split(":")[0], 10)
standupMinutes = parseInt(standupTime.split(":")[1], 10)
standupDate.setUTCMinutes(standupMinutes)
standupDate.setUTCHours(standupHours + utcOffset)
result = (standupDate.getUTCHours() == now.getUTCHours()) and
(standupDate.getUTCMinutes() == now.getUTCMinutes()) and
(standupDayOfWeek == -1 or (standupDayOfWeek == standupDate.getDay() == now.getUTCDay()))
if result then true else false
# Returns the number of a day of the week from a supplied string. Will only attempt to match the first 3 characters
# Sat/Sun currently aren't supported by the cron but are included to ensure indexes are correct
getDayOfWeek = (day) ->
if (!day)
return -1
['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'].indexOf(day.toLowerCase().substring(0,3))
# Returns all standups.
getStandups = ->
robot.brain.get('standups') or []
# Returns just standups for a given room.
getStandupsForRoom = (room) ->
_.where getStandups(), room: room
# Gets all standups, fires ones that should be.
checkStandups = ->
standups = getStandups()
_.chain(standups).filter(standupShouldFire).pluck('room').each doStandup
return
# Fires the standup message.
doStandup = (room) ->
standups = getStandupsForRoom(room)
if standups.length > 0
# Do some magic here to loop through the standups and find the one for right now
theStandup = standups.filter(standupShouldFire)
message = "#{PREPEND_MESSAGE} #{_.sample(STANDUP_MESSAGES)} #{theStandup[0].location}"
else
message = "#{PREPEND_MESSAGE} #{_.sample(STANDUP_MESSAGES)} #{standups[0].location}"
robot.messageRoom room, message
return
# Finds the room for most adaptors
findRoom = (msg) ->
room = msg.envelope.room
if _.isUndefined(room)
room = msg.envelope.user.reply_to
room
# Confirm a time is in the valid 00:00 format
timeIsValid = (time) ->
validateTimePattern = /([01]?[0-9]|2[0-4]):[0-5]?[0-9]/
return validateTimePattern.test time
# Stores a standup in the brain.
saveStandup = (room, dayOfWeek, time, utcOffset, location, msg) ->
if !timeIsValid time
msg.send "Sorry, but I couldn't find a time to create the standup at."
return
standups = getStandups()
newStandup =
room: room
dayOfWeek: dayOfWeek
time: time
utc: utcOffset
location: location.trim()
standups.push newStandup
updateBrain standups
displayDate = dayOfWeek or 'weekday'
msg.send 'Ok, from now on I\'ll remind this room to do a standup every ' + displayDate + ' at ' + time + (if location then location else '')
return
# Updates the brain's standup knowledge.
updateBrain = (standups) ->
robot.brain.set 'standups', standups
return
# Remove all standups for a room
clearAllStandupsForRoom = (room, msg) ->
standups = getStandups()
standupsToKeep = _.reject(standups, room: room)
updateBrain standupsToKeep
standupsCleared = standups.length - (standupsToKeep.length)
msg.send 'Deleted ' + standupsCleared + ' standups for ' + room
return
# Remove specific standups for a room
clearSpecificStandupForRoom = (room, time, msg) ->
if !timeIsValid time
msg.send "Sorry, but I couldn't spot a time in your command."
return
standups = getStandups()
standupsToKeep = _.reject(standups,
room: room
time: time)
updateBrain standupsToKeep
standupsCleared = standups.length - (standupsToKeep.length)
if standupsCleared == 0
msg.send 'Nice try. You don\'t even have a standup at ' + time
else
msg.send 'Deleted your ' + time + ' standup.'
return
# Responsd to the help command
sendHelp = (msg) ->
message = []
message.push 'I can remind you to do your standups!'
message.push 'Use me to create a standup, and then I\'ll post in this room at the times you specify. Here\'s how:'
message.push ''
message.push robot.name + ' create standup hh:mm - I\'ll remind you to standup in this room at hh:mm every weekday.'
message.push robot.name + ' create standup hh:mm UTC+2 - I\'ll remind you to standup in this room at hh:mm UTC+2 every weekday.'
message.push robot.name + ' create standup hh:mm at location/url - Creates a standup at hh:mm (UTC) every weekday for this chat room with a reminder for a physical location or url'
message.push robot.name + ' create standup Monday@hh:mm UTC+2 - I\'ll remind you to standup in this room at hh:mm UTC+2 every Monday.'
message.push robot.name + ' list standups - See all standups for this room.'
message.push robot.name + ' list all standups- Be nosey and see when other rooms have their standup.'
message.push robot.name + ' delete standup hh:mm - If you have a standup at hh:mm, I\'ll delete it.'
message.push robot.name + ' delete all standups - Deletes all standups for this room.'
msg.send message.join('\n')
return
# List the standups within a specific room
listStandupsForRoom = (room, msg) ->
standups = getStandupsForRoom(findRoom(msg))
if standups.length == 0
msg.send 'Well this is awkward. You haven\'t got any standups set :-/'
else
standupsText = [ 'Here\'s your standups:' ].concat(_.map(standups, (standup) ->
text = 'Time: ' + standup.time
if standup.utc
text += ' UTC' + standup.utc
if standup.location
text +=', Location: '+ standup.location
text
))
msg.send standupsText.join('\n')
return
listStandupsForAllRooms = (msg) ->
standups = getStandups()
if standups.length == 0
msg.send 'No, because there aren\'t any.'
else
standupsText = [ 'Here\'s the standups for every room:' ].concat(_.map(standups, (standup) ->
text = 'Room: ' + standup.room + ', Time: ' + standup.time
if standup.utc
text += ' UTC' + standup.utc
if standup.location
text +=', Location: '+ standup.location
text
))
msg.send standupsText.join('\n')
return
'use strict'
# Constants.
STANDUP_MESSAGES = [
'Standup time!'
'Time for standup, y\'all.'
'It\'s standup time once again!'
'Get up, stand up (it\'s time for our standup)'
'Standup time. Get up, humans'
'Standup time! Now! Go go go!'
]
PREPEND_MESSAGE = process.env.HUBOT_STANDUP_PREPEND or ''
if PREPEND_MESSAGE.length > 0 and PREPEND_MESSAGE.slice(-1) != ' '
PREPEND_MESSAGE += ' '
# Check for standups that need to be fired, once a minute
# Defaults to Monday to Friday.
WEEKDAYS_CRON = process.env.HUBOT_STANDUP_WEEKDAYS or '1-5'
new cronJob('1 * * * * '+ WEEKDAYS_CRON, checkStandups, null, true)
# Global regex should match all possible options
robot.respond /(.*?)standups? ?(?:([A-z]*)\s?\@\s?)?((?:[01]?[0-9]|2[0-4]):[0-5]?[0-9])?(?: UTC([- +]\d\d?))?(.*)/i, (msg) ->
action = msg.match[1].trim().toLowerCase()
dayOfWeek = msg.match[2]
time = msg.match[3]
utcOffset = msg.match[4]
location = msg.match[5]
room = findRoom msg
switch action
when 'create' then saveStandup room, dayOfWeek, time, utcOffset, location, msg
when 'list' then listStandupsForRoom room, msg
when 'list all' then listStandupsForAllRooms msg
when 'delete' then clearSpecificStandupForRoom room, time, msg
when 'delete all' then clearAllStandupsForRoom room, msg
else sendHelp msg
return
return