hubot-victorops-bot
Version:
A hubot script to quickly view or page the person on call in victorops
132 lines (116 loc) • 4.08 kB
text/coffeescript
# Description:
# Quickly view or page the person on call in victorops
#
# Dependencies:
# - coffee-script
# - node-fetch
# - moment
# - ical
# - fuzzy
# - underscore
#
# Configuration:
# HUBOT_VICTOROPS_POST_URL - REST Endpoint for Victorops
# HUBOT_VICTOROPS_TEAMS_MAP `\{\"ops\":\"devops\",\"data\":\"data\"\}`
# HUBOT_VICTOROPS_TEAMS_ICAL `\{\"devops\":\"URL_TO_ICS\",\"data\":\"URL_TO_ICS\"\}`
#
# Commands:
# hubot page oncall <optional message>
# hubot whois oncall
#
# Author:
# ndaversa
_ = require 'underscore'
fetch = require 'node-fetch'
moment = require 'moment'
ical = require 'ical'
fuzzy = require 'fuzzy'
module.exports = (robot) ->
users = robot.adapter?.client?.rtm?.dataStore?.users or robot.brain.users()
url = process.env.HUBOT_VICTOROPS_POST_URL
teams = JSON.parse process.env.HUBOT_VICTOROPS_TEAMS_MAP
calendars = JSON.parse process.env.HUBOT_VICTOROPS_TEAMS_ICAL
getRoom = (context) ->
room = robot.adapter.client.rtm.dataStore.getChannelOrGroupByName context.message.room
room = robot.adapter.client.rtm.dataStore.getChannelGroupOrDMById context.message.room unless room
room
parseJSON = (response) ->
return response.json()
checkStatus = (response) ->
if response.status >= 200 and response.status < 300
return response
else
error = new Error(response.statusText)
error.response = response
throw error
invalidChannel = (msg) ->
channels = []
for team, key of teams
channel = getRoom message: room: team
channels.push " <\##{channel.id}|#{channel.name}>" if channel
return msg.reply "You can only page for oncall in one of the following project channels: #{channels}"
lookupUser = (name) ->
name = name.replace '.', ' ' if name?
users = _(users).keys().map (id) ->
user = users[id]
id: id
name: user.real_name || user.name
results = fuzzy.filter name, users, extract: (user) -> user.name
if results?.length >= 1
return "<@#{results[0].original.id}>"
else
return name
whoIsOncall = (team, cb) ->
now = moment()
calendar = calendars[team]
ical.fromURL calendar, {}, (err, data) ->
events = _(data).keys().map (id) ->
event = data[id]
start: moment event.start
end: moment event.end
summary: event.summary
id: id
.filter (event) -> now.isBetween event.start, event.end
if events.length is 1
oncall = events[0]
else
events = events.filter (event) -> event.summary.indexOf('OVERRIDE') > -1
if events.length is 1
oncall = events[0]
if oncall
[ __, person ] = oncall.summary.match /(?:OVERRIDE:\s)?(.*)/
cb person
robot.respond /page on\s?call(?:\s+(.*))?/, (msg) ->
[ __, message ] = msg.match
room = getRoom msg
team = teams[room.name]
return invalidChannel msg unless team
whoIsOncall team, (person) ->
if person
fetch "#{url}#{team}",
method: "POST"
body: JSON.stringify
entity_id: "slack-ops"
message_type: "critical"
entity_display_name: "Paged by @#{msg.message.user.name} in ##{room.name}"
state_message: message
.then (res) ->
checkStatus res
.then (res) ->
parseJSON res
.then (json) ->
msg.reply "Paged #{lookupUser person} whom is on call for the `#{team}` team in victorops"
.catch (error) ->
console.log "*[Error]* #{error}"
msg.reply "I have failed at paging #{lookupUser person}. I am shamed"
else
msg.reply "I can't determine who is on call, please contact your friendly administrator"
robot.respond /who\s?is on\s?call/, (msg) ->
room = getRoom msg
team = teams[room.name]
return invalidChannel msg unless team
whoIsOncall team, (person) ->
if person
msg.reply "#{lookupUser person} is on duty for the `#{team}` team"
else
msg.reply "I can't determine who is on call, please contact your friendly administrator"