A few weeks ago we saw how we could use the power of Slack and the Voxbone Provisioning API to build custom commands to purchase Voxbone phone numbers.

VoxAPI provides many more functionalities that range from ordering mechanisms to configurations. This time, we’ll cover how you can easily configure those numbers within your Slack channels using Slack commands and VoxAPI.

Obviously, this tutorial will be building upon what we did in part 1. So if you’ve missed part 1, head over to the previous tutorial.

list-1

configure-1

list-2

Here are a few things that you will need:

Here are a few additional resources in case you get lost:

We will be creating two more Slack commands: 1) Listing your purchased DIDs and 2) Configuring those DIDs with voice URIs.

Making the List DID Command

Setting up the Slack Command

You’ve seen how to set up a Slack command in Part 1. It is super straight-forward and very trivial.

We will use the same process (you have the option to “Set up a Slash Command” when you visit https://api.slack.com/custom-integrations).

slackcmd

We will set up our list DID command to respond to /list (as opposed to /did in part 1 for purchasing numbers). The command will look something like this:

list

Which lists your DIDs based on country, and e164 pattern.

This steps’ biggest difference from the one in part 1 is that you already have your Heroku URL. So if yours was something like https://secret-flower-1982.herokuapp.com/ for the /did command then we will use https://secret-flower-1982.herokuapp.com/list for our list command. We will create this endpoint in our code.

The Code

1. Making the /list endpoint

You are already very familiar with creating NodeJS application by now (if you’ve followed part 1), so we’ll pick up on what we have.

In the previous part, we put all our code into:

app.post('/', function(req, res){

// /did Code goes here

});

to bring our /did command to life. This time, we’ll create a new endpoint that will reflect the /list portion of the URL we setup in the Slack command setup UI.

It’s easy, at the end of that piece of app.post code, we’ll make another one:

app.post('/list', function(req, res){

//  /list code goes here!

});

We are now ready to code that command!

2. Securing the endpoint and fetching the parameters specified by the Slack user

Now you know how security works with Slack, with the use of tokens. For each new command, you will get a new token so go back to your Slack command setup UI and check it out. The code is very similar to part 1:

if (req.body.token == 'gIkuvaNzQIHg97ATvDxqgjtO'){
    //Get the incoming string of text from Slack
    var string = req.body.text;

    //Split the string into parameters separated by a comma and a space
    var parameters = string.split(', ');
    //Assign each variable to its respective Slack text parameter
    var country = parameters[0];
    var e164Pattern = parameters[1];
    //We will also use the response_url for reasons to be developed on later (but you are now familiar with!)
    var response_url = req.body.response_url;
    //On success, launch a series of callback functions that will use these parameters to interact with the VoxAPI
    listDids(0,5000,country,e164Pattern, response_url);
} else{
    //If the token is not present, return some kind of message
    res.status(200).send('You are not authorized to reach this endpoint!');
}

3. Retrieving DIDs from your inventory matching the parameters

We will now build the listDids() function that we called when authentication is successful in the previous step.

This function uses the country and e164 pattern parameters to search for corresponding DIDs in your inventory and will return some information like: didId, actual e164, type, country, city, webrtc, sip uri (needs some tweaking, more on that in the next step!)

function listDids(pageNumber, pageSize, country, e164Pattern, response_url){
		//Now we set up the options that will be sent in the request using the URL declared previously, your auth information, and adding the query parameters to the URL
		var options = {
			url: url+'inventory/did',
			headers: headers,
			"auth": auth,
			qs : {
		        "pageNumber" : pageNumber,
		        "pageSize" : pageSize,
		        "countryCodeA3" : country,
		        //the % sign is used in VoxAPI to specify the pattern to be searched. It indicates that the value passed is part of a larger string.
		        "e164Pattern": '%'+e164Pattern+'%',
	    	} 
		};
		request.get(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	var body = JSON.parse(body);
	        	console.log(body);
	        	var dids = body.dids;
	        	//For each DID in your inventory matching those parameters, we formulate a message to spit back to Slack
	        	for (i=0; i<dids.length; i++) {
	        		var didId = dids[i].didId;
	        		var e164 = dids[i].e164;
	        		var type = dids[i].type;
	        		var country = dids[i].countryCodeA3;
	        		var city = dids[i].cityName;
	        		var webrtc = dids[i].webRtc;
	        		var uriId = dids[i].voiceUriId;
	        		var number = i+1;
	        		//This message is incomplete because it is missing the actual URI - which we retrieve in getUri()
	        		var message_incomplete = '\n'+'number: '+e164+' | id: '+didId+' | type: '+type+' | country: '+country+' | city: '+city+' | webrtc: '+ webrtc;
					console.log('[DEBUG] - DIDs found: #'+dids[i].didId+' uriId: '+ uriId);
					getUri(message_incomplete, uriId, response_url);
	        	}
	        } else {
	        	//If something goes wrong, we send back to the Slack Channel a notification
	        	var message_complete = 'Could not find DIDs!';
			    sendResponse(message_complete, response_url);
	        }
	    });
	}

4. Retrieving their respective SIP URIs

So far we only return a message with the number, its id, type, country, city, and webrtc status. We are still missing the SIP URI. However, we have its URI ID – we can use this in the /configuration/voiceuri VoxAPI call to retrieve the actual URI. For this we will create the getUri() function we called in the previous step.

function getUri(message_incomplete, uriId, response_url){
		var options = {
			url: url+'configuration/voiceuri',
			headers: headers,
			"auth": auth,
			qs : {
		        "pageNumber" : 0,
		        "pageSize" : 1,
		        "voiceUriId": uriId,
	    	} 
		};
		request.get(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	var body = JSON.parse(body);
	        	var uri = body.voiceUris[0].uri;
	        	//We concatenate the incomplete message from listDids with the URI we retrieved using each DID's URI ID.
	        	var message_complete = message_incomplete+' | uri: '+uri;
				console.log('[DEBUG] - URI found! ID: '+uriId+ 'URI: '+uri);
				//We can now send the response to slack with the complete comfirmation message!
				sendResponse(message_complete, response_url);
	        } else {
	        	//If something goes wrong, we send back to the Slack Channel a notification
	        	var message_complete = 'Could not find URI!';
			    sendResponse(message_complete, response_url);
	        }
	    });
	};

5. Sending the messages back to Slack

We can now send the complete information for each DID in your inventory matching your specified parameters back to the Slack channel.

function sendResponse(message_complete, response_url){
		var options = {
			url: response_url,
			headers: headers,
			body: JSON.stringify({ text : message_complete }) 
		};
		//Here we send back the complete message to the Slack Channel.
		request.post(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	console.log(body);
	        } else {
	        	console.log(body);
	        }
	    });
	}
});

Making the Configure DID Command

Setting up the Slack Command

We will now create another command that will enable you to link SIP URIs to your DIDs.

We will use the same process (you have the option to “Set up a Slash Command” when you visit https://api.slack.com/custom-integrations).

We will set up our configure DID command to respond to /configure (as opposed to /did in part 1 for purchasing numbers or /list in the previous part for listing your inventory). The command will look something like this:

configure

Which enable you to configure a DIDs and assign it a SIP URI and enable/disable WebRTC usage on it.

Similar to the previous step, we will set the command link to be https://secret-flower-1982.herokuapp.com/configure for our configure command and we will create this endpoint in our code.

The Code

1. Making the /configure endpoint

Just like the previous part, we will create a new endpoint in our code. At the end of the /list endpoint code, we’ll make another one:

app.post('/configure, function(req, res){

//  /list code goes here!

});

We are now ready to code that command!

2. Securing the endpoint and fetching the parameters specified by the Slack user

Just like the other endpoints, we will set some kind of authentication mechanism using Slack’s token.

if (req.body.token == 'gIkuvaNzQIHg97ATvDxqgjtO'){
		//Get the incoming string of text from Slack
		var string = req.body.text;
		//Split the string into parameters separated by a comma and a space
		var parameters = string.split(', ');
		//Assign each variable to its respective Slack text parameter
		var number = parameters[0];
		var uri = parameters[1];
		var webrtc = parameters[2];
		//We will also use the response_url for reasons to be developed on later (but you are now familiar with!)    
		var response_url = req.body.response_url;
		//On success, launch a series of callback functions that will use these parameters to interact with the VoxAPI
		checkUri(0, 1, number, uri, webrtc, response_url);
	} else{
		//If the token is not present, return some kind of message
		res.status(200).send('You are not authorized to reach this endpoint!');
	}

3. Checking whether specified URI already exists

The way this endpoint will work is to automate the linking of URIs to DIDs. So, initially we want to make sure that the URI specified in the Slack command does not exist already.

If it does, we can directly launch the series of linking requests. If it does not, we have to create it first.

function checkUri(pageNumber, pageSize, number, uri, webrtc, response_url){
		var options = {
			url: url+'configuration/voiceuri',
			headers: headers,
			"auth": auth,
			qs : {
		        "pageNumber" : pageNumber,
		        "pageSize" : pageSize,
		        "uri" : uri
	    	} 
		};
		request.get(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	var body = JSON.parse(body);
	        	var voiceUri = body.voiceUris[0];
	        	//Check whether the returned list of voice URIs specified from Slack is null or !null
	        	if (voiceUri != null) {
	        		//!null -> URI exists -> link URI
	        		var uriId = voiceUri.voiceUriId;
					console.log('[DEBUG] - URI exists -> Linking URI...');
					//We retrieve the DID ID based on the e164 number
	        		getDid(0, 1, number, uri, webrtc, uriId, response_url);
	        	}else{
	        		//null -> URI does not exist -> Create URI
					console.log('[DEBUG] - URI does not exist -> Creating URI...');
					//We create the URI
					createUri(number, uri, webrtc, uriId, response_url);
	        	}
	        } else {
				var message = 'Error while trying to find URI';
				sendResponse(message, response_url);

	        }
	    });
	}

4. Create the URI

Let’s tackle the scenario where the URI does not exist yet first. In this case, we first need to create the URI before we can link it to the DID.

If the URI is created successfully, we have to retrieve the DID’s ID first before we can link the URI to it.

function createUri(number, uri, webrtc, uriId, response_url){
		var options = {
			url: url+'configuration/voiceuri',
			headers: headers,
			"auth": auth,
			body: JSON.stringify({ voiceUri : {voiceUriProtocol: "SIP", uri: uri, description: "uri for "+number}}) 
		};
		request.put(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	console.log('[DEBUG] - URI Created -> Linking URI');
	        	var body = JSON.parse(body);
	        	//We retrieve the URI ID from the newly created URI
	        	var newUriId = body.voiceUri.voiceUriId;
	        	//We retrieve the DID ID based on the e164 number
	        	getDid(0, 1, number, uri, webrtc, newUriId, response_url);
	        } else {
	        	console.log('[DEBUG] - Creating URI unsuccessful!');
	        	var message = 'Error creating URI!';
	        	//If something goes wrong, we send back an error message to the Slack Channel.
	        	sendResponse(message, response_url);
	        }
	    });
	}

5. Retrieve DID ID from number passed in parameter

So far, what we have is the actual E164 number and URI ID, VoxAPI requires the DID ID and URI ID. So we will be retrieving the DID ID from the specified number.

function getDid(pageNumber, pageSize, number, uri, webrtc, uriId, response_url){
		var options = {
			url: url+'inventory/did',
			headers: headers,
			"auth": auth,
			qs : {
		        "pageNumber" : pageNumber,
		        "pageSize" : pageSize,
		        "e164Pattern" : '%'+number+'%'
	    	} 
		};
		request.get(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	var body = JSON.parse(body);
	        	var didId = body.dids[0].didId;
	        	console.log('[DEBUG] - DID ID found -> Linking URI...');
	        	//Now that we've retrieved the DID ID, we can link the URI ID to the DID ID.
	        	linkUri(number, uri, webrtc, uriId, didId, response_url);
	        } else {
	        	console.log('[DEBUG] - DID ID not found -> aborting...');
	        	//If something goes wrong, we send back an error message to the Slack Channel.
				var message = 'Could not find DID!';
				sendResponse(message, response_url);
	        }
	    });
	}

6. Link the URI to the DID

We can now link the phone number to the URI and also apply the setting for WebRTC (true or false).

function linkUri(number, uri, webrtc, uriId, didId, response_url){
		var options = {
			url: url+'configuration/configuration',
			headers: headers,
			"auth": auth,
			body: JSON.stringify({ didIds : [ didId ],voiceUriId: uriId, webRtcEnabled: webrtc}) 
		};
		request.post(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	console.log('[DEBUG] - Linking successful!');
	        	console.log(body);
	        	var message = 'URI: '+ uri + ' has been linked to '+ number+ ' and webRTC functionality set to '+ webrtc;
	        	//Once we have a successful link, we send back a confirmation to the Slack channel.
				sendResponse(message, response_url);
	        } else {
	        	console.log('[DEBUG] - Linking unsuccessful!');
	        	var message = 'Error linking URI!';
	        	//If something goes wrong, we send back an error message to the Slack Channel.
	        	sendResponse(message, response_url);
	        }
	    });
	}

7. Sending the Confirmation back to Slack

Once this is done, we can send a message back to Slack!

function sendResponse(message, response_url){
		var options = {
			url: response_url,
			headers: headers,
			body: JSON.stringify({ text : message }) 
		};
		request.post(options, function (error, response, body) {
	        if (!error && response.statusCode == 200) {
	        	console.log(response);
	        } else {
	        	console.log(response);
	        }
	    });
	}

That’s it! You now have a fully functional provisioning bot for your Slack channel! You can buy dids with the /did command, list them with /list, and configure them with /configure. Feel free to check out the VoxAPI documentation to see all of the other great things you can build!

Next time we will use the power of WebRTC to bring all this together and implement a voice communication tool within your Slack channel!