GIG: Would you like your xM On Call info displayed HipChat or Slack?

xMatters is versatile. You can hook anything into xMatters up to and including the kitchen sink oven. So, when our friend Kirk needed a little help getting On Call information into HipChat, I managed to whip together a script to do just that. But then why stop there? I already had code for talking to Slack (and we also have a fully built integration here), so I thought it would be cool to see them both in one place. 

The trick to this is actually in the calls to the xMatters API. Since we can abstract those calls into a function (and maybe some day into a shared function....;) then all we have to do is parse out the group name from the incoming data from the slash command from either system and pass it into our function and Voila!

The following will assume you've set up (or will set up) slash commands (links: Hipchat or Slack, or check the xMatters integration install docs Hipchat or Slack). 

Hipchat

First, we'll pick apart the Hipchat code. Create a new inbound integration that runs a script, like so:

Then paste in the following code. 

// If your data is posted as JSON
hipchatData = JSON.parse( request.body );

// Parse the text from the user. Everything after the slash
// command will be the group name. 
var re = new RegExp( /\/xm_oncall (.*)/ );
var match = re.exec( hipchatData.item.message.message );

// If they didn't put a group in then exit
var groupName = '';
if( match.length === 0 ) {
    console.log( "No group entered. Exiting" );
    return;
}

groupName = match[1];


var getOnCall = http.request({
    'endpoint': 'xMatters',
    'method': 'GET',
    'path': '/api/xm/1/groups/' + groupName + '/calendar'
});

// Submit the request and capture the response
var response = getOnCall.write();
var calendarData = JSON.parse( response.body );

var msg = buildMsg( calendarData, groupName );


//////// Send to HipChat

sendToHipChat( msg );


/*
 * buildMsg - Build the message to send to hipchat
 *
 *  calendarData - The result of a GET to /groups/GROUPNAME/calendar
 *  groupName    - The name of the group we got the schedule for
 *
 */
function buildMsg( calendarData, groupName ) {
    
    var data = calendarData.data;
	var msg = 'On call schedule for ' + groupName + '';
	var getShift;
	
	// Loop through each item in data and
	// retrieve the rest of the details from
	// the shift.
	for( var d in data ) {
	
	    getShift = http.request({
	    	'endpoint': 'xMatters',
	    	'method': 'GET',
	    	'path': data[d].shift.links.self
	    });
	
	    shiftResponse = getShift.write();
	    shift = JSON.parse( shiftResponse.body );
	    
		msg += '  Shift ' + shift.name + '. Start ' + data[d].start + '. End: ' + data[d].end + '<br/>';
		msg += '    Members: <br/>';
	
		members = data[d].members.data;
		for( var m in members ) {
			msg += '      ' + members[m].position + ':' + 
			   members[m].member.firstName + ' ' + members[m].member.lastName + ' (' + members[m].member.targetName + ') delay: ' + members[m].delay + '<br/>';
		}
	
	    console.log( 'MSG: ' + msg );
	}

	return msg;
}


/*
 * sendToHipChat - send a message to hipchat
 *
 *  msg - The text to send
 */
function sendToHipChat( msg ) {

  // Prepare the HTTP request
  var request = http.request({
      'endpoint': 'Hipchat',
      'method': 'POST',
      'headers': {
          'Content-Type': 'application/json'
      }
  });
  
  var color = "gray";
  
  var payload = {
    "message": msg,
    "message_format": "html",
    "color": color,
    "notify": false
  };
  
  
  // Submit the request and capture the response
  var response = request.write( payload );

}
 

To tell xMatters where to put this, login to the Hipchat admin page and click the integrations button. Click Build Your Own. Select the room and give the integration a name. Then copy the "Send messages to this room by posting to this URL" url into a new endpoint in the integration builder in xMatters and name it "Hipchat".

 

Slack

To do the same in Slack, again, create a new inbound integration in your Slack Comm Plan:

Then paste in the following code:

 
// Slack inbound

// Set up the xMatters endpoint for creating the event
// The credentials for authenticating to xM will be stored
// in the endpoint.

// Replace the &s with ",", then the =s with ": " and throw in some {}s, and it's JSON. 
data = JSON.parse( '{"' + request.body.replace( /&/g, '", "' ).replace( /=/g, '": "' ) + '"}' );

// The text is coming over with +s instead of spaces, so we replace those
data.text = decodeURI( data.text ).replace( /\+/g, ' ' );

// Now split out the recipients, which should be enclosed in "s and the message which is the rest
re = new RegExp( /.*/ );
match = re.exec( data.text );

// If there is no match, we can't correctly
// parse the recipients and the message...
// So we'll post it back to Slack.
if( match === null ) {
    var msg = 'Error sending event: Could not parse "' + data.text + '". Expected: "/xm_oncall "';
    
    sendToSlack( data.user_name, msg );
    console.log( msg );
    return;
}


groupName = match[1];

var getOnCall = http.request({
    'endpoint': 'xMatters',
    'method': 'GET',
    'path': '/api/xm/1/groups/' + groupName + '/calendar'
});

// Submit the request and capture the response
var response = getOnCall.write();
var calendarData = JSON.parse( response.body );

var msg = buildMsg( calendarData, groupName );

sendToSlack( data.user_name, msg );

/*
 * buildMsg - Build the message to send to hipchat
 *
 *  calendarData - The result of a GET to /groups/GROUPNAME/calendar
 *  groupName    - The name of the group we got the schedule for
 *
 */
function buildMsg( calendarData, groupName ) {
    
    var data = calendarData.data;
	var msg = 'On call schedule for ' + groupName + '';
	var getShift;
	
	// Loop through each item in data and
	// retrieve the rest of the details from
	// the shift.
	for( var d in data ) {
	
	    getShift = http.request({
	    	'endpoint': 'xMatters',
	    	'method': 'GET',
	    	'path': data[d].shift.links.self
	    });
	
	    shiftResponse = getShift.write();
	    shift = JSON.parse( shiftResponse.body );
	    
		msg += '  Shift ' + shift.name + '. Start ' + data[d].start + '. End: ' + data[d].end + '<br/>';
		msg += '    Members: <br/>';
	
		members = data[d].members.data;
		for( var m in members ) {
			msg += '      ' + members[m].position + ':' + 
			   members[m].member.firstName + ' ' + members[m].member.lastName + ' (' + members[m].member.targetName + ') delay: ' + members[m].delay + '<br/>';
		}
	
	    console.log( 'MSG: ' + msg );
	}
	return msg;
	
}

/*
 * sendToSlack - Post a message to the user.
 *
 *   path - The Slack path. For example /H14H1B4F5/Q76HS76A/VaFfAdh865aAA
 *   user - The username to direct message. A '@' will be prepended
 *   message - The text of the message to send to the user
 */
function sendToSlack( user, message ){
	

  var req = http.request({
  	"endpoint": "Slack",
  	"path": path,
  	"method": "POST",
  	"headers": {
  	    "Content-Type": "application/x-www-form-urlencoded"
  	}
  });

  var payload = { 
    "channel": '@' + user, 
    "username": "xMatters Integration Builder",
    "icon_url": "https://support.xmatters.com/hc/en-us/article_attachments/203171869/icon.png", 
    "text": message 
  };

  var temp = req.write( 'payload=' + JSON.stringify( payload ) );


}

 

Finally, you'll need to create an inbound webhook into Slack. From within Slack click the team name > Apps & Integrations. Then click Build in the upper right corner > Make a custom integration. (Or click here). Click Incoming Webhook and select a channel. Then copy the Webhook URL into a new endpoint in the integration builder in xMatters and name it "Slack". 

 

Conclusion

If you inspect each code block, you will see that they are largely the same! The only differences are around how we communicate back to the source system. HipChat has its API and Slack has its own, but we've abstracted much of that out and we can just focus on the xMatters API calls, which are the same regardless of where the originating request came from. 

The end result:

 

 

There are some definite improvements that could be made. Pointedly around the start and end time. I suppose we could add another xM API call to get the timezone of the xMatters user making the request (if they exist... er, exist in xMatters) and modify the start time into their timezone. 

I could also see improvements around the formatting. UI design isn't my strong suit (but I'm learning!!). This is where it gets a little tricky though. HipChat can support HTML tags but Slack instead uses a form of markdown. The script above just formats using raw strings and new lines. Functional, but don't tell the UX people!

 

 

 

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.
Powered by Zendesk