<commit_before># Description:
#   PagerDuty Integration for checking who's on call, making exceptions, ack, resolve, etc.
#
# Commands:
#
#   hubot who's on call - return the username of who's on call
#   hubot pager me page <msg> - create a new incident
#   hubot pager me 60 - take the pager for 60 minutes
#   hubot pager me incidents - return the current incidents
#   hubot pager me problems - return all open inicidents
#   hubot pager me ack 24 - ack incident #24
#   hubot pager me resolve 24 - resolve incident #24

# Configuration
#
#   HUBOT_PAGERDUTY_USERNAME
#   HUBOT_PAGERDUTY_PASSWORD
#   HUBOT_PAGERDUTY_SUBDOMAIN
#   HUBOT_PAGERDUTY_APIKEY     Service API Key from a 'General API Service'
#   HUBOT_PAGERDUTY_SCHEDULE_ID

pagerDutyUsers = {}
pagerDutyUsername    = process.env.HUBOT_PAGERDUTY_USERNAME
pagerDutyPassword    = <PASSWORD>.<PASSWORD>
pagerDutySubdomain   = process.env.HUBOT_PAGERDUTY_SUBDOMAIN
pagerDutyBaseUrl     = "https://#{pagerDutySubdomain}.pagerduty.com/api/v1"
pagerDutyApiKey      = process.env.HUBOT_PAGERDUTY_APIKEY

module.exports = (robot) ->
  robot.respond /pager( me)?$/i, (msg) ->

    cmds = robot.helpCommands()
    cmds = (cmd for cmd in cmds when cmd.match(/(pager me |who's on call)/))
    msg.send cmds.join("\n")

  # Assumes your Campfire usernames and PagerDuty names are identical
  robot.respond /pager( me)? (\d+)/i, (msg) ->
    withPagerDutyUsers msg, (users) ->
      username  = msg.message.user.name
      if username == "Shell"
        username = process.env.USER
      userId    = users[username].id
      now       = new Date()
      start     = now.toISOString()
      minutes   = parseInt msg.match[2]
      end       = now.addMinutes(minutes).toISOString()
      override  = {
        'start':     start,
        'end':       end,
        'user_id':   userId
      }
      withCurrentOncall msg, (old_username) ->
        data = { 'override': override }
        pagerDutyPost msg, "/schedules/#{process.env.HUBOT_PAGERDUTY_SCHEDULE_ID}/overrides", data, (json) ->
          if json.override
            msg.send "rejoice, #{old_username}! #{json.override.user.name} has the pager from #{json.override.start} until #{json.override.end}"

  robot.respond /(pager|major)( me)? (inc|incidents|sup|problems)$/i, (msg) ->
    pagerDutyIncidents msg, (incidents) ->
      if incidents.length > 0
        buffer = "Triggered:\n----------\n"
        for junk, incident of incidents.reverse()
          if incident.status == 'triggered'
            buffer = buffer + formatIncident(incident)
        buffer = buffer + "\nAcknowledged:\n-------------\n"
        for junk, incident of incidents.reverse()
          if incident.status == 'acknowledged'
            buffer = buffer + formatIncident(incident)
        msg.send buffer
      else
        msg.send "Chillin"

  robot.respond /(pager|major)( me)? page (.+)$/i, (msg) ->
    pagerDutyIntegrationAPI msg, "trigger", msg.match[3], (json) ->
      msg.reply "#{json.status}, key: #{json.incident_key}"

  robot.respond /(pager|major)( me)? ack(nowledge)? (.+)$/i, (msg) ->
    updateIncident(msg, msg.match[4], 'acknowledged')

  robot.respond /(pager|major)( me)? res(olve)?(d)? (.+)$/i, (msg) ->
    updateIncident(msg, msg.match[5], 'resolved')

  # who is on call?
  robot.respond /who('s|s| is)? (on call|oncall)/i, (msg) ->
    withCurrentOncall msg, (username) ->
      msg.reply "#{username} is on call"

missingEnvironmentForApi = (msg) ->
  missingAnything = false
  unless pagerDutySubdomain?
    msg.send "PagerDuty Subdomain is missing:  Ensure that HUBOT_PAGERDUTY_SUBDOMAIN is set."
    missingAnything |= true
  unless pagerDutyUsername?
    msg.send "PagerDuty username is missing:  Ensure that HUBOT_PAGERDUTY_USERNAME is set."
    missingAnything |= true
  unless pagerDutyPassword?
    msg.send "PagerDuty password is missing:  Ensure that HUBOT_PAGERDUTY_PASSWORD is set."
    missingAnything |= true
  missingAnything


pagerDutyGet = (msg, url, query, cb) ->
  if missingEnvironmentForApi(msg)
    return

  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .query(query)
    .headers(Authorization: auth, Accept: 'application/json')
    .get() (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 200 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

pagerDutyPut = (msg, url, data, cb) ->
  if missingEnvironmentForApi(msg)
    return

  json = JSON.stringify(data)
  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .headers(Authorization: auth, Accept: 'application/json')
    .header("content-type","application/json")
    .header("content-length",json.length)
    .put(json) (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 200 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

pagerDutyPost = (msg, url, data, cb) ->
  if missingEnvironmentForApi(msg)
    return

  json = JSON.stringify(data)
  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .headers(Authorization: auth, Accept: 'application/json')
    .header("content-type","application/json")
    .header("content-length",json.length)
    .post(json) (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 201 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

withCurrentOncall = (msg, cb) ->
  now = new Date()
  oneHour = now.addHours(1).toISOString()
  now = now.toISOString()
  query = {
    since: now,
    until: oneHour,
    overflow: 'true'
  }
  pagerDutyGet msg, "/schedules/#{process.env.HUBOT_PAGERDUTY_SCHEDULE_ID}/entries", query, (json) ->
    if json.entries and json.entries.length > 0
      cb(json.entries[0].user.name)

withPagerDutyUsers = (msg, cb) ->
  if pagerDutyUsers['loaded'] != true
    pagerDutyGet msg, "/users", {}, (json) ->
      pagerDutyUsers['loaded'] = true
      for user in json.users
        pagerDutyUsers[user.id]   = user
        pagerDutyUsers[user.name] = user
      cb(pagerDutyUsers)
  else
    cb(pagerDutyUsers)

pagerDutyIncidents = (msg, cb) ->
  query =
    status:  "triggered,acknowledged"
    sort_by: "incident_number:asc"
  pagerDutyGet msg, "/incidents", query, (json) ->
    cb(json.incidents)

pagerDutyIntegrationAPI = (msg, cmd, args, cb) ->
  unless pagerDutyApiKey?
    msg.send "PagerDuty API service key is missing."
    msg.send "Ensure that HUBOT_PAGERDUTY_APIKEY is set."
    return

  data = null
  switch cmd<commit_msg>Epic pagerduty improvements.<commit_after># Description:
#   PagerDuty Integration for checking who's on call, making exceptions, ack, resolve, etc.
#
# Commands:
#
#   hubot who's on call - return the username of who's on call
#   hubot pager me page <msg> - create a new incident
#   hubot pager me 60 - take the pager for 60 minutes
#   hubot pager me incidents - return the current incidents
#   hubot pager me problems - return all open inicidents
#   hubot pager me ack 24 - ack incident #24
#   hubot pager me resolve 24 - resolve incident #24
#
# Dependencies:
#  "moment": "1.6.2"
# 
# Configuration:
#
#   HUBOT_PAGERDUTY_USERNAME
#   HUBOT_PAGERDUTY_PASSWORD
#   HUBOT_PAGERDUTY_SUBDOMAIN
#   HUBOT_PAGERDUTY_APIKEY     Service API Key from a 'General API Service'
#   HUBOT_PAGERDUTY_SCHEDULE_ID

inspect = require('util').inspect

moment = require('moment')

pagerDutyUsers = {}
pagerDutyUsername    = process.env.HUBOT_PAGERDUTY_USERNAME
pagerDutyPassword    = <PASSWORD>.<PASSWORD>.<PASSWORD>
pagerDutySubdomain   = process.env.HUBOT_PAGERDUTY_SUBDOMAIN
pagerDutyBaseUrl     = "https://#{pagerDutySubdomain}.pagerduty.com/api/v1"
pagerDutyApiKey      = process.env.HUBOT_PAGERDUTY_APIKEY

module.exports = (robot) ->
  robot.respond /pager( me)?$/i, (msg) ->

    emailNote = if msg.message.user.pagerdutyEmail
                  "You've told me your PagerDuty email is #{msg.message.user.pagerdutyEmail}"
                else if msg.message.user.email_address
                  "I'm assuming your PagerDuty email is #{msg.message.user.email_address}. Change it with `hubot pager me as <EMAIL>`"
                else
                  "I don't know your PagerDuty email. Change it with `hubot pager me as <EMAIL>`"

    cmds = robot.helpCommands()
    cmds = (cmd for cmd in cmds when cmd.match(/(pager me |who's on call)/))
    msg.send emailNote, cmds.join("\n")

  robot.respond /pager(?: me)? as (.*)$/i, (msg) ->
    email = msg.match[1]
    msg.message.user.pagerdutyEmail = email
    msg.send "Okay, I'll remember your PagerDuty email is #{email}"

  # Assumes your Campfire usernames and PagerDuty names are identical
  robot.respond /pager( me)? (\d+)/i, (msg) ->
    withPagerDutyUsers msg, (users) ->
      email  = msg.message.user.pagerdutyEmail || msg.message.user.email_address
      unless email
        msg.send "Sorry, I can't figure out your email address :( Can you tell me with `hubot pager me as <EMAIL>`?"
        return

      userId    = users[email].id

      unless userId
        msg.send "Sorry, I couldn't find a PagerDuty user for #{email}. Double check you have a user, and that I know your PagerDuty email with `hubot pager me as <EMAIL>`"
        return

      now       = new Date()
      start     = moment().format()
      minutes   = parseInt msg.match[2]
      end       = moment().add('minutes', minutes).format()
      override  = {
        'start':     start,
        'end':       end,
        'user_id':   userId
      }
      withCurrentOncall msg, (old_username) ->
        data = { 'override': override }
        pagerDutyPost msg, "/schedules/#{process.env.HUBOT_PAGERDUTY_SCHEDULE_ID}/overrides", data, (json) ->
          if json.override
            start = moment(json.override.start)
            end = moment(json.override.end)
            msg.send "Rejoice, #{old_username}! #{json.override.user.name} has the pager from #{start.calendar()} until #{end.calendar()}"

  robot.respond /(pager|major)( me)? (inc|incidents|sup|problems)$/i, (msg) ->
    pagerDutyIncidents msg, (incidents) ->
      if incidents.length > 0
        buffer = "Triggered:\n----------\n"
        for junk, incident of incidents.reverse()
          if incident.status == 'triggered'
            buffer = buffer + formatIncident(incident)
        buffer = buffer + "\nAcknowledged:\n-------------\n"
        for junk, incident of incidents.reverse()
          if incident.status == 'acknowledged'
            buffer = buffer + formatIncident(incident)
        msg.send buffer
      else
        msg.send "Chillin"

  robot.respond /(pager|major)( me)? page (.+)$/i, (msg) ->
    pagerDutyIntegrationAPI msg, "trigger", msg.match[3], (json) ->
      msg.reply "#{json.status}, key: #{json.incident_key}"

  robot.respond /(pager|major)( me)? ack(nowledge)? (.+)$/i, (msg) ->
    updateIncident(msg, msg.match[4], 'acknowledged')

  robot.respond /(pager|major)( me)? res(olve)?(d)? (.+)$/i, (msg) ->
    updateIncident(msg, msg.match[5], 'resolved')

  # who is on call?
  robot.respond /who('s|s| is)? (on call|oncall)/i, (msg) ->
    withCurrentOncall msg, (username) ->
      msg.reply "#{username} is on call"

missingEnvironmentForApi = (msg) ->
  missingAnything = false
  unless pagerDutySubdomain?
    msg.send "PagerDuty Subdomain is missing:  Ensure that HUBOT_PAGERDUTY_SUBDOMAIN is set."
    missingAnything |= true
  unless pagerDutyUsername?
    msg.send "PagerDuty username is missing:  Ensure that HUBOT_PAGERDUTY_USERNAME is set."
    missingAnything |= true
  unless pagerDutyPassword?
    msg.send "PagerDuty password is missing:  Ensure that HUBOT_PAGERDUTY_PASSWORD is set."
    missingAnything |= true
  missingAnything


pagerDutyGet = (msg, url, query, cb) ->
  if missingEnvironmentForApi(msg)
    return

  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .query(query)
    .headers(Authorization: auth, Accept: 'application/json')
    .get() (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 200 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

pagerDutyPut = (msg, url, data, cb) ->
  if missingEnvironmentForApi(msg)
    return

  json = JSON.stringify(data)
  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .headers(Authorization: auth, Accept: 'application/json')
    .header("content-type","application/json")
    .header("content-length",json.length)
    .put(json) (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 200 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

pagerDutyPost = (msg, url, data, cb) ->
  if missingEnvironmentForApi(msg)
    return

  json = JSON.stringify(data)
  auth = 'Basic ' + new Buffer(pagerDutyUsername + ':' + pagerDutyPassword).toString('base64')
  msg.http(pagerDutyBaseUrl + url)
    .headers(Authorization: auth, Accept: 'application/json')
    .header("content-type","application/json")
    .header("content-length",json.length)
    .post(json) (err, res, body) ->
      json_body = null
      switch res.statusCode
        when 201 then json_body = JSON.parse(body)
        else
          console.log res.statusCode
          console.log body
          json_body = null
      cb json_body

withCurrentOncall = (msg, cb) ->
  oneHour = moment().add('hours', 1).format()
  now = moment().format()

  query = {
    since: now,
    until: oneHour,
    overflow: 'true'
  }
  pagerDutyGet msg, "/schedules/#{process.env.HUBOT_PAGERDUTY_SCHEDULE_ID}/entries", query, (json) ->
    if json.entries and json.entries.length > 0
      cb(json.entries[0].user.name)

withPagerDutyUsers = (msg, cb) ->
  if pagerDutyUsers['loaded'] != true
    pagerDutyGet msg, "/users", {}, (json) ->
      pagerDutyUsers['loaded'] = true
      for user in json.users
        pagerDutyUsers[user.id] = user
        pagerDutyUsers[user.email] = user
        pagerDutyUsers[user.name] = user
      cb(pagerDutyUsers)
  else
    cb(pagerDutyUsers)

pagerDutyIncidents = (msg, cb) ->
  query =
    status:  "triggered,acknowledged"
    sort_by: "incident_number:asc"
  pagerDutyGet msg, "/incidents", query, (json) ->
    cb(json.incidents)

pagerDutyIntegrationAPI = (msg, cmd, args, cb) ->
  unless pagerDutyApiKey?
    msg.send "PagerDuty API service key is missing."
    msg.send "Ensure that HUBOT_PAGERDUTY_APIKEY is set."
    return

  data = null
  switch cmd
{'fraction_non_alphanumeric': 0.1245054075441836, 'fraction_numerical': 0.005011870218939594, 'mean_word_length': 2.9369158878504673, 'pattern_counts': {'":': 1, '<': 14, '<?xml version=': 0, '>': 75, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2334712', 'n_tokens_mistral': 5193, 'n_tokens_neox': 5093, 'n_words': 1235}