Webinar Transcript:
PRESENTER: So we'll go over a couple of housekeeping items per usual. And all lines are going to be muted just to prevent any background noise. And we're going to be taking questions throughout the webinar via the Q&A box on your console. We'll save all those for the end of the webinar. And just as a reminder, you guys will be receiving a recording for today, so don't worry about taking too detailed notes if that was your plan. And also I want to give you guys a quick thanks for joining us amidst all of the chaos that we're experiencing right now.
But as we said today, we're going to start off with node.js. And I hope this will be educational. You're going to learn from one of the best, which is Dan Tolbert. And we were joking about this beforehand. This is a really outdated picture of him. He's not rocking the slicked back man bun that you see here. He's actually got more of a disheveled curly and crazy look to him at this point. But yeah, he's really fun with giving demos. So hopefully you guys will take something away. He's been doing API things at Bandwidth for a while. And during his time here, he's worked really closely with customers of all sizes during their integrations with Bandwidth. And he currently sits on the technology team helping drive Bandwidth developer experience team forward. And so with that, I will go ahead and turn it over to Dan to kick us off.
DAN TOLBERT: Thank you for the intro. So today we're going to be covering a very small succinct demo with our voice and messaging APIs. And we're going to be using our node.js SDK to build the application that we have set up for everyone today. So with that, we will be sending out a link to the GitHub repo where I put together the demo. Let's see. Questions. We'll get to that in a minute. In a minute, I mean a couple. So first thing I'm going to do is just do a quick overview of where everything is and the world of the internet in relation to Bandwidth.
And so the first thing we want to do is head to dev.bandwidth.com. This is going to be the source of truth for all things documentation. Anything you want to know about how our APIs work or how the sequence of events needs to take place, you can find that here. Specifically, we're going to be driving into the node.js SDK, as I mentioned before. We'll be using express as the middleware manager or HTTP service instead of just basic node. And we're going to be digging into messaging and voice. We have those fairly succinct, and these sections here for voice and messaging. And then we will also need to head to the Bandwidth dashboard eventually. And this is going to be where we log in to actually set up our callbacks and web hooks and get everything up and running as far as ordering a phone number and pointing inbound calls where they need to go. All right.
With that, let's go ahead and just get started. I've got most of this broken down under the README here. We're going to be following along with the tutorial here. It's already prefilled out, ready to run. If you want to clone this repo here, this is open source. GitHub.com/Bandwidth/examples. And in here, you're going to have your index, which is just your key run. Voice and messaging for the corresponding products. And then we'll dig into what conflict.js has later. OK.
So first thing we're going to do when we've got our assumptions, we need to make sure that we have a Bandwidth account, which I fortunately do. If you do not, just Bandwidth.com click sign up, and we will be in touch with you sooner than later. We're going to make sure that you have node.js installed, or you should ensure that you have node.js installed. You can install this through NVM and Brew if you're on a Mac. Or you can go to just node.js and/or Google [INAUDIBLE] what the website is. And download and get up and running.
And then the key point to Bandwidth for running a successful application, you have to have a publicly addressable URL for your server. This is for Bandwidth to send you inbound events for inbound messages, inbound calls, as well as web hooks to let you know about the status of the message and ongoing events with a call. So any time the user presses a button on the phone call, we're going to send you a callback. You need to be able to react to that event. And so ngrok is a lovely little tool, ngrok.com, that lets you spin up a localhost, or a proxy to your localhost so that we can really run and develop this app on my machine or your machine now. Instead of trying to deploy to Heroku, deploy to AWS every single time, we're going to run with ngrok right here.
So with that, we're going to go ahead and get started. Before we do, just see if there's any questions. No [INAUDIBLE]?
PRESENTER: No questions at this point.
DAN TOLBERT: OK. All right. So I'm going to go ahead. And we're going to start from the npm init command. And let me just clean up a little bit. So the first thing I want to do is I'm actually going to make a new directory called node webinar and go ahead and change into that. And let's go ahead and kick it off with the npm init. This is going to set up our package.json and give us a spot to install all our packages. Most of y'all are probably familiar with what this is going to do for us today. I don't need to fill out all this information here. Licence, true. That's fine.
All right. So now let's go ahead and install what we need to use. So the way that Bandwidth has our node SDK broken up, we have it set up in different modules or packages on NPM for each one of our APIs as well as our BXML generator. So we need to go ahead and install the BXML library. That's going to be namespace to at Bandwidth and BXML. And do the same for messaging and voice. I'll just copy both those. Cool.
And as mentioned earlier, we're going to be using express to actually run the server here. All right. And I use a little program called dotenv. This is going to let me put my environment variables in a file called dotenv that lets us decouple our credentials from our source code. This is part of the 12 factor authentication for programs. There's a detailed blog about it, nonetheless. We need a couple of files. We need an index.js. This is going to be our source, our entry point to the application. We're going to need a messaging file. We're going to need a voice file. We're going to need a configuration file that's going to make sure that we have all of our environment variables set up correctly. And then we actually need that environment file.
So we're going to create all those files right now. And if we do a quick list, we can see that we have our config, index, messaging, our node modules, package.json and voice. Let me check. So with that, I'm going go and open up a text editor here. I use Sublime Text. Anything should work. Pretty quick. OK. So we're going to code long. And I've got most of the code already prefilled out here. We're not going to be doing a ton of live coding, so to speak. It's already built. We're just going to be copying and pasting from the tutorial here with some context as I explain to you what's going on.
So we're going to grab this basic index.js. We don't have any routes to find. All we're doing in this file right here is we're going to require that dotenv that we talked about earlier. We're going to go ahead and grab express, we're going to grab our configuration, we're going to pull in that voice file, that messaging file, and we're going to spin up our express app. And we're going to listen to it on that port. So if I save this now, and if I were to run index.js, we don't have anything really running super slick right there now. OK.
Continuing with the code-along, this one, this file, config.js, we use this in our sample apps just to check that all the environment variables are set and they throw errors letting you know which ones you maybe got wrong. So we're just going to use this. This is not anything super complicated. It's just going to explore all these as variables for us to grab instead of having to check the process dotenv every single time. So now in config.js, we're going to paste that. So just real quick to go through. If you don't have the Bandwidth Account ID, it's going to throw an error. If you don't have the messaging token and messaging secret, et cetera, it's going to throw an error. And then it's going to actually export all this for us to grab a little bit more simple later. So if we were to go into our terminal now, and let's try that again. Right. It's going to hit the very first thing we don't have our Bandwidth or our messaging API token configured right now. We're going to get to that in just a second.
Next, we need a fire up ngrok. I've talked about this earlier, but really, we need a way to let Bandwidth to know where in the world wide web do we send callbacks and web hooks. Ngrok is going to be our tool of choice. I'm going to hop into a terminal here and I'm going to launch ngrok on port 3000. And I'm going to accept HTTP request to this little server here. So while that spins up, I'm going to hop over to the Bandwidth dashboard. And I'm going to go ahead and log in. Almost. OK. There we are.
And for the purposes of this demo, I'm actually going to go back over here and I'm going to-- env.sample. I'm going to create a quick sample file that looks like-- the topology is here. This. So we can fill it out. And I don't have to actually-- I'm going to go to the sample. So we can fill this out with everybody because I'm going to keep my environment variables secret from y'all so I don't have to change everything. Because once I display them, we're SOL. OK. So how can I stop sharing my screen real quick?
PRESENTER: Go to the sharing tab. Just up top.
DAN TOLBERT: OK. Just turned off my screen share real quick so I can grab my environment variables safely without having to change everything. And--
PRESENTER: Thanks for hanging in there, guys.
DAN TOLBERT: OK. We're back. So now that I have my environment variables saved off into a super secret file, allow me to run. We're going to be working with this sample file just for the purposes of demonstration. And my base URL, I need to go ahead and paste my ngrok URI right here. So this is going to be the base URL. We're going to use this one for the outbound phone calls. We're not going to get into that until later. And then I want to set my port to port 3000. So I'm running locally on port 3000. Anything that happens at this ngrok URL here is going to forward to my localhost at port 3000. That's up and running now. If I were to go to that URI that I pulled earlier, right here, failed to complete tunnel, but we can actually go ahead and see there is the get request from my browser. And if I pull up their web interface, you can see there is my Chrome browser trying to connect to the server, which is not running anything right now. OK.
So continuing through, we've got our config set up, we've got ngrok set up. So now we actually need to create these Bandwidth resources. So we're going to go to dashboard.bandwidth.com. We're going to create a messaging application. We're going to get those messaging credentials. We're going to get a voice application. We're going to get voice credentials. We're then going to order a phone number, set that up to any location, and then we're going to update that dotenv file with that ngrok URI, which we've already done, and the Bandwidth credentials that we'll pull from the dashboard. OK.
So I've already logged in here. And I have some of this filled out, but we're going to go ahead and start from scratch. First thing I said we need to do is create the messaging application. I'm going to head to the Applications tab. Go ahead and click this Create New. Application name, we're going to do node webinar live. The messaging application, this is going to be that ngrok URI that we talked about earlier. And then if we check here, the callback needs to be message callback. So let's scroll back down here. And [INAUDIBLE]. That's message callback. OK.
So we've created a messaging application. We need this messaging application ID. Going to here. Messaging application ID. Then we're going to need our account ID. And this is global to Bandwidth. We can see it on the screen right here. It's actually this 9900778 for me, yours will be different. It's also at the top of your URI here. I'm just going to copy it right here and then paste that into my account ID. So now I have my account ID and I have my messaging application ID set up. So we can go ahead and save that.
And I need to go ahead and get my API credentials. If you click this API credentials tab, I've got a bunch of token and secrets in here. We're going to actually create a new one. And you can see that's what the copy in here. I need to remember to delete this one. Specifically copy this here. Messaging API token and secret. The voice API username and password's a little different. So you have to bear with me there. But first we need to actually create that voice application.
So to create a new one, we're going to node webinar live. And we're actually going to throw voice on this one because I didn't think about that earlier. We actually do not need anything. We need a POST request and we need a POST request here. We allow you to change the callback method for voice to either GET request or POST request. For all intents and purposes, for me, I don't need but a POST. I'm going to grab that, and then the callback URI, or the path, is going to be voice callback. So in here, I now have a voice application that is set up to forward any inbound phone calls to this call initiated callback URL, specifically whatever that ngrok URI is. Voice callback. And you notice down here we don't have a location set up yet. Let's go ahead and create a location.
So we're going to move over to our Account tab now. You'll see subaccounts locations, users notifications. Subaccount, you should already have a subaccount. If you do not, you can create one here. I have my DTOLB subaccount from my teammates on my account here. So I'm going to go into location. I'm going to create the DTOLB subaccount. The location name, I'm going to call this node live. And that should be fine. The description, we don't anything up, but we'll say live node demo. I do not want this to be default. If I could spell, that'd be helpful. The voice protocol is going to be HTTP. SIP voice is going to be for our more traditional network service customers. If you're following along and you are a network service customer, you should ask your representative at Bandwidth more about HTTP voice to get an idea of what your account would be like for that.
So if I pick this here, I need to select my Associative Voice Application, which we're going to do live voice. But I want to do my demo one. And then under origination settings, this is entirely for folks that are working with the network services or have very detailed knowledge about what they want to throw in their origination and termination settings. If you need any more information about that, raise your hand at the end of the conference or the webinar and I can go into some detail there.
So now we've got a location with our voice, we now need to set up for SMS and MMS. Similarly, we're going to enable SMS. We're just going to go ahead and get crazy with it. Enable toll free and shortcodes. Our geographic reach, this refers to the ability to text what we declassify as zones internationally. So Zone 1 is going to be the US and Canada. Do you know what Zone 2 [INAUDIBLE]?
PRESENTER: I don't know.
DAN TOLBERT: Yeah. I forget as well. It's--
PRESENTER: I'm young.
DAN TOLBERT: --somewhere on the support site. I know, like, Zone 5 is Europe. And these kind of reflect some of the surcharges to text to and from international locations. If you don't know what the rates are, do not enable these before you check, because you could end up with a bill that you're unhappy with. So similar with voice, we want to select the HTTP protocol. Just need to make sure that V2 messaging is enabled. And then the applications, what we talked about before, I have my node webinar live. And then we need MMS. So MMS, we're going to go ahead and enable that. Protocol has to be HTTP. And notice that it inherits all the information from SMS. Then create that location.
And now I need to order a phone number, right? I need to actually be able to interact with this thing. So I'm going to hop over into the Numbers tab here. And I'm going to search for a 919 phone number. By area code. By area code. And sure. Let's go ahead and grab this one. Doesn't necessarily matter. Going to place and purchase. I need this to fall in my subaccount under my node live location. And purchase. I'm about to purchase. OK.
So for everything that we're interacting with during this webinar, we're going to be interfacing with this phone number right here. So I'm just going to copy this now. I've got my ngrok tunnel set up. I've got my location configured with my applications. And just to drive the point home, I'm going to open up dial pad. And I'm going to create a text message to that phone number. [INAUDIBLE]. Send a message. There we are. And I'm just going to select that. And wave, hi.
And if we notice over here, we received a POST request from Bandwidth to this message callback end point. And it's actually going to keep trying again with the way that we have this set up today. Because we're not responding with successful response code, it's actually going to try again. And it's going to back off as it tries again over the course of the day. That's how we handle when your server is unable to respond. Instead of a fallback URL, we try again and we back off exponentially for the next 24 hours. So if I were to pop under my ngrok tunnel here, I can see there is my text. And it doesn't really render great here, but you can see that we have a text from a dial pad number to that Bandwidth number we just ordered. And we waved hello.
We can do the same thing with a call if I were to call this number here. Nothing really should happen, I'm just going to hang up. And we see we now have a voice callback, right? We received that event type initiate. We set received the to and from number. This would be where we would react to that POST event to our server and reply back with some BXML. We'll get to that in just a minute. But this gives me confidence that my Bandwidth setup is correct. And I need to grab my voice API credentials. Finally. Apologies on that. And I need that voice application ID. So I'm going to pop into here, grab my voice, grab this. [INAUDIBLE] voice application ID.
So for the Bandwidth voice product, your API username and API password are not the same as your messaging API token and your messaging API secret. This is actually the same information you used to log into the dashboard or for a specific API credential pair. If I wanted to create an API credential pair, I would go to Account, I'd go to Users, and I would add a new user. I do think I have settings. And just cancel. And we want to specifically select an API access method. This is going to restrict my username and password that I create here to accessing the Bandwidth resources only via the API. This is relatively important as if you select GUI or both when you're creating a user, your password does reset every 90 days. So if you are a user that deploys onto the cloud and you do not create an API user, you will need to update your credentials on your server every 90 days when you get that Bandwidth reset password notification.
So I'm not actually going to create a user here, I already have a couple of users on my account. I'm going to have to unshare my screen and then paste in my example or my credentials into this thing. Next. But I just wanted to show you this would be specifically an API user, basic user, username, password. This is how you access the Bandwidth dashboard API as well as our voice API. So if you give me just a second, I'm going to get my environment set up. All right. Now it's over here. Going to grab my voice API username and password. And I'm going to paste that into my environment. Save that. And then I'm going to delete it, again, from my sample. And I'm going to share my screen again now that I've hidden all my things. And this would be your API user. And this would be your API password. All right.
So at this point, I have my configuration set up. I have a Bandwidth account ID, I have a messaging token, my messaging secret, my messaging application, my voice username, my voice password, my voice application. I've got my base URL set up, and I'm telling the thing to listen on port 3000. OK. Bounce back over to our terminal here. And let us run this thing. Right? We're now able to run. We're listening on port 3000. We're not doing anything for it, but the app did successfully launch and we're waiting. OK.
So now that we have everything set up. Let's actually talk through what this app's going to do today. We spent a lot of time getting set up, let's talk about what's actually going to happen in the app. We're going to a couple of things. We're going to have the ability to have a "call me" function. So if I were to text the word or the phrase "call me" to this phone number, Bandwidth is going to create a phone call to that user that texted "call me." And it's going to ask them for a 10 digit number. And we're going to create a forward. We're going to forward that call to the number we put in there. So you can look at this as, like, a call forwarding service. We [INAUDIBLE] need a mask my phone number to call someone on Craigslist or something like that with the "call me" as the interface to create that call.
If you text that phone number "dog," we're going to send you a picture of a super dog with an emoji. And then if you do anything else other than call or dog, when you're texting in, we're just going to reply with a date-time, just to kind of show an auto response to an inbound text message. And finally, if you call that phone number, so not texting "call me" but if you call this number directly, we're going to play a quick math game on the call to demonstrate how to ask users for input, process input, and then present them with either success or failure based on the input. So we're going to "call me," we're going to text your dog, or text to get a picture of a dog, and then we're going to get a date-time, and we're going to play a math game. OK.
So at this point, we've done a code-along, we've got config set up, we're running successfully there. We've got ngrok running. We have our environment filled out. So let's actually start and play with messaging. So I got us the boilerplate for messaging. I'm going to go ahead and copy this and head into our messaging. I think I'm going to close this. And so what I've done here, I'm pulling in the Bandwidth messaging SDK, I'm grabbing our config. I'm going to go ahead and grab our voice file just to have voice. Because we know we're going to need to make a phone call eventually, when someone texts the phrase, "call me." So I'm going to go ahead and have that reference for us now.
Then I want to go ahead and create a function to send the text message. And with the way we have our library set up today, everything native and returns and native promise. So in modern, I guess 2020 node, we'd async away. We'll see what happens in 2022. But for now, we're going to async away. So we have an asynchronous function. The Bandwidth SDK for messaging, for node, does use the basic off username and basic off password that are correlated to your token and secret. So I need to go ahead and step back for our client. And then I'm actually going to create a new client here called messaging controller. This is hanging off of the Bandwidth messaging API controller. As we talked earlier, I need to get that account ID. So I have that in my URI path to successfully send a request. I also need an application ID as part of the request so that Bandwidth knows where to send status updates.
And then finally, we have our object creator. We're going to create a Bandwidth message request object. And we're going to funnel in what we received from this message here. So we already know what the Bandwidth voice or the Bandwidth messaging API kind of looks like, but we'll go into the API methods. And we're going to create the message. And I'm just going to look at raw HTTP here. We do have the JS selector there if you want to see what that looks like. So looking here, we know we need a "to," a "from," the text, and the application ID. So what we can postulate from the way we have this structured out, is our message here is going to already contain-- I'm just going to do this. It's already got our "to," it's already got our "from," it's already got our text, and it's already got our media. And this is going to be an array of strings here. So all we're doing here is we're actually adding the application ID as that's going to persist regardless of the message that we're sending. So we'll just kind of comment this out and we'll leave this at the top and say something like, message looks something like this. OK.
And then finally, as I talked about earlier, everything is promisified. So we know that we're going to be receiving a promise. So I'm just going to await the create message request here. And I'm going to assign that to my message response and return that. So I'm not actually doing any try catch in this Send Message function here. So I know that if the message request for some failed, we've a rate limit error, I got my credentials wrong, or something happens, I need to catch that error somewhere along the line. So we'll go into that in a minute. But right now, we have our lovely function Send Message that's going to try to send a message via the Bandwidth API to whatever "to" number we specify there. OK.
Continuing on, we actually create a callback handler. So this whole thing, as we talked about earlier, everything is initiated via SMS. So if I were to send a text message, I need to be able to answer that. So we need a callback handler. So I'm going to go through, create a very short and sweet asynchronous function. This is going to take a request and a response. Just express boilerplate code. And the first thing that you'll see here, as I actually go ahead and respond to that request, the very first time when I entered this function.
We do that mainly for the reason that there's not much more with a callback that we need to do except respond back to Bandwidth. Any response that we send to them, if it's a BXML, if it's an inbound message, whatever, it's really looking for a successful response. Looking for a 2xx, 200, a 201, a 202, whatever that may be, I'm just going to immediately respond with 200. Go ahead and close out that connection back to Bandwidth. And then I'm going to actually assign that inbound request to a variable called message. And let's take a look at that real quick.
Our inbound callbacks for inbound group message, we're just going to default to group. Starts off as an array. So everything that we send you is in a list. However, today, I can guarantee that there will only be one item or zero. You could reference the zeroth element of this list any time and you will get one callback per list. We do not currently send more than one callback per. More than one message to get [INAUDIBLE] per callback, it could be something we implement in the future. We wanted to go ahead and future-proof ourselves against that.
So today, we're only ever going to send one callback or one message event per callback. But it is still sent as a list. And I very naively grabbed the zeroth element of that request body. If you were writing a production level software, in order to future-proof yourself, it would be advisable to go ahead and create this handler to expect a list of more than one element just in case we do add some performance enhancements in the future. As I said today, single element. Moving forward to the future, we could do that. I know of 0 plans to launch that any time soon. So you probably are fine just grabbing the zeroth element of every callback.
All right. At this point, let's actually sort of log the message to the screen here. So we know what we've got right now. We have a message controller that's going to handle this message callback. And we're going to print it to screen. But I also need to add that route to my index right here so that we can tell the express application that we have this app. So I'm going to accept a POST request and message callback, and then I'm going to handle, and we'll call that function there.
So at this point, I did everything correct. We do have a server up and running. If I pull up dial pad here, and I send, "Yo," we should see an inbound message. We do. Message received. Says, "Yo." Let's see where it's from. This inbound message here is JSON, as I talked about earlier. Matches very similar to what our callback is here today. All right. So at this point we actually have received that message.
What we also now need to look at is that actually an inbound message or is it a delivery receipt from an outbound message that we've sent earlier. So we're going to run some very quick logic here to just check if it's a DLR. So I'm going to bounce back over to messaging and just kind of paste that in there. And then I'll comment out my console log. So right now I'm saying, hey, let's take a look at the direction of that message. And if it's equal to out, so if that was an outbound message, we know that that's a DLR or a callback.
So if it is a DLR, if it's a delivery receipt, we're just going to log it to the screen. Say, hey, this ID has this status. And we're going to return out of this function. There's really no more action for us to take on that callback and a more robust application here, I would actually probably save this to a database. Maybe update that message record as currently Bandwidth does not have a way to programmatically display message records. That's a feature we have coming out later this year. So today, if I wanted a quick and easy way to get my message history, I'd want to play around in this message ID right here when it's a DLR.
All right. So we're continuing here. So now we want to actually grab some of the relevant information of the message. So the message text, we look here, is tucked away under message. That message, that text. And as you're doing a switch or some logic on this, I am going to actually flatten it to lowercase. And I'm going to trim any beginning or end white spaces so that it really is kind of taking away some of the nuance. If I was to type capital, all caps, "call me," I wouldn't fail in that request there.
And then I'm also going to make this future proof to work with root messages. So if we look at the root message here, we notice that the two here at the top, this is the Bandwidth number and then this within the message object here is a list of all the numbers involved in a group. So I need to intelligently build a response. It's not as simple as me just replying to the phone number in this regard. I need to send it back to the group in its entirety.
So I've got a really quick and dumb function here that just builds the tool array based on that message. So it takes the message "to," it looks if it's in the index, it splices it, it pushes everything back together, and it builds a nice response object for us there. So I'm going to pay that guy right here. And this is to really-- I'm going to add a comment-- build the "to" array based on the inbound message callback. OK.
And we need a logic switch as well. So we're actually going to build a switch. And we've talked about before, "call me." We're being create a voice call, we're going to fill that in later. If it's a "dog," we're going to send that dog MMS. If it's anything else, we're going to respond with a date-time. And then we'll go ahead and start building our message request with that common information because we know that it's always, or mostly always, going to send a text message.
So continuing down here, I have my switch and I have my message request. So right here a very simple JSON object. I'm taking the "to," I'm calling that build away function. I'm passing it the message that I have here, and we're getting back an array or a list assigning that "to" value. The "from" number is always going to be the owner. The Bandwidth method phone number that received this message. So that's message.to.
Again, we talked about this earlier. I'm grabbing the text, I'm flattening it to lowercase, and I'm trimming off any trailing or preceding white text. So now I'm going to create a little switch. The switch is like a big if else tree. So in the case that the message text is "call me," I'm actually just going to return out of here and break the switch. I'm done with this function, we'll fill that in later. If it's a dog, I'm going to set that text to a dog emoji. And I've actually uploaded a picture here of a dog. You'll see it in a minute. It's going to pull that in, sending it in as an MMS. You'll get that as an attachment. And then we'll break out the switch. And then finally, in the default case, just need to set the text to the current date-time in milliseconds. It goes time dot now.
However, we don't actually call to Send Message function yet. Let's go ahead and grab that. We have a little try catch block. You can go into here. And so now we're actually going to try to send that message. We're going to await that. If it's sent, we're going to log it. If it's not, there is an error. We're going to log the error that there was a little error sending to that array, and print it to screen. Probably we're going to have some try again logic or update a database report based on the failure because we are kind of swallowing that error at this point. We're not propagating it up back to Bandwidth, we just want to do more error logic here as needed. Right now, we're not going to worry too much about it.
So at this point, we have a fairly robust message handler. We're going to pull it apart, check if it's a DLR. If it's not a DLR, we're going to keep going on with our lives. We're going to build a "to" array, we're going to flatten that text, we're going to switch on it, if it's "dog," we're going to send an MMS, anything else, we're going to send a date-time. And at this point, we should be live. So we've got this here, like, all said and done, your message should look like that. Your message node js file.
So if I go back up now to Visual Studio Code, apologies, if I go back to dial pad, and say, "Yo," we know it's not going to work because I need to restart my app. Let's try again. "Yo." [INAUDIBLE] here, we send a message. Callback received. So now we have current date-time. We already grabbed this. Let's go here to timestamp to human. March 12th at 2:39. Look at that. So we do know that it's at least smart enough, if it's fake, to fake it with really good accuracy.
And now we'll go ahead and send a message and say, I want to see a picture of a dog. And if we look at our terminal there, we know that we've got the message right there. And there's my super puppy. So at this point, we've built a little app, we don't do a ton, we just receive an inbound message, we spit back out the date-time, and we do a little bit of switching on what the actual text that was sent may be. OK.
So let's take a little bit of a break and drink some water, we've been talking for a while. And before we hop into voice, are there any questions about the messaging app that we've done so far?
PRESENTER: We don't have any in the chat box but you guys don't hesitate. Don't be shy. Feel free to ask anything.
DAN TOLBERT: OK. We'll give that another 30 seconds.
PRESENTER: Oh, [INAUDIBLE]. Do you have Python libs?
DAN TOLBERT: We do have Python libraries. If you go to the documentation, we have the SDKs, and there's Python right here. Note that if you're using Bandwidth V1 APIs, you need to use a different library. But really we have this pipeline SDK and we'll be running a Python webinar that goes over and that's very, very, very similar to this in a couple of weeks. I forget the actual date but--
PRESENTER: I want to say it's April 9th. So you should definitely sign up for that one as well.
DAN TOLBERT: All right. So we're just going to keep going with the voice part of the app. So let's follow along here. So at this point, right. We've got a pretty robust messaging app. Let's expand it here. I'm going to open up my editor if I can find it. And there we are. And I'm going to head over to voice.js. And I'm going to then require the voice SDK. I'm going to require our BXML library. And then to go ahead, I'm going to pull in the default node URL library that's part of this node standard library here that is going to let us build URLs intelligently instead of concatenating strings, just to be safe with your shrinking caps. Pull in that configuration.
And then similar to how the voice or the messaging controller work, we're going to build a voice controller. And in this case, it uses our API user and our API password. And we're going to build that. So this is actually going to set the global level. Could be set within a function if that's what we want it to. We're just going to leave it here global for now. It's the sample app, we're not really trying to build super robust software. Although you should.
And we head into here. We know that we're going to need a few endpoints with the way that BXML works. So every time an action happens, or an action is presented to a user, and they take action, Bandwidth is going to send a webhook or a callback to that individual. So we need to set up a few endpoints.
Oh, hey, so John, you asked, how can you put the app on the public internet? So for me, today, I'm using an app called ngrok, that's going to expose my localhost to the public internet. If you're running this in production, I would very much not recommend ngrok. It's mainly built for rapid prototyping and testing. I would say use something like Heroku or AWS, using their Elastic Beanstalk, Digital Ocean, just pick a virtual server. And as far as making it secure, one thing that we have in the applications, if I look at this one right here, I didn't use it just for sake of demonstration, however, there is this use callback username and password.
I don't want to enable this on this one because it will force me to set it, but if you were to actually enable this, we're going to send or encrypt every single callback from Bandwidth to your server with the username and password you provide here. And then you want to make sure that you set this to HTTPS. So you want to use a secure tunnel. We're going to encrypt that with your username and password. And then it'll be up to you to check that that username and password on that inbound request meets or matches what it set up to be there. So we allow you to specify username and password. We encrypt it with that and then you check that username and password on the inbound handler. So if I were writing, really, I would probably want an app that use-- I forgot what the actual library that they have here, but I would do something here for auth check, whatever that may be. And then I'll just comment that out for now. Let's save that.
Cool. All right. We're going to keep going here. So we've got a few points that we need to have. So I'm going to grab this. We're going to handle inbound calls. And then I know that we're going to create a gather. So I'm going to handle that inbound gather. Let's close this. And if I go to voice, paste that there. So now we have a function to handle inbound call, and a function to handle the end of a gather request. There's nothing there. We know we need to now update our index to actually do those things.
So I'm going to head over to index. And so now we're handling a POST request for a voice callback. So any time we receive an inbound request to this URL, we're going to call this function. And then any time we receive a request to this EndGatherGame, we're going to call this function. Save that. Head back over to voice. Right now this is empty. So let's actually fill it in. So as I said before, for an inbound call, we're going to play a little gather game. A little math game. Very simple.
And so I'm going to go ahead and pull this together. For Bandwidth, we do need to build a Sentence, and build a gather. So I've got links to that. So with BXML, we'll go a little bit over this call control here. This is to kind of give you an idea. [INAUDIBLE] skipped over this. Essentially, Bandwidth is going to make a request to your server when a call begins. Go through. It's going to make a POST or GET request based on what you said. And then you're going to apply with that with BXML, it's part of that entire HTTP request lifecycle.
So when we have an inbound call, we get this callback to call initiate. And then we need to respond with some BXML, so as I said before, we're going to first speak a sentence. And if I look in JavaScript, we create a SpeakSentence object. And we're going to set the Sentence and set the voice. I'm going to head over here. And I'm just going to copy this all in one little swing right now. Back over here. Export for handling an inbound call. I have a SpeakSentence one. Right? It's a Bandwidth verb. It's going to say, let's play a game. It's going to use Susan's voice. And it's going to set the location to the US dialect.
Then I'm going to have another SpeakSentence. And this is our math game. It's going to ask our user, our participant, what is 9 plus 2. And they're going to press the digits on their phone pad to actually answer that quiz. So in order for us to do that, we need to create a gather request.
Same thing as we kind of talked about before. Right words to please press a digit. In this case, we're going to ask them what is 9 plus 2. And then gather requires a URI or a URL. So it knows that whenever you make that request, it's going to create a new request to this endpoint here. Sorry for fumbling that. We didn't actually route logic based on these endpoints like we've done here instead of having a big if statement like we did for messaging. So now I need to set the gather URL. So this is relative to my server based on that inbound call. To EndGatherGame. And I don't want it to give me any more than two digits. So if you're to press three digits, it's only going to send me the first two.
And then finally, I need to build that Bandwidth response. So I need to add that verb, SpeakSentence one, SpeakSentence two, and then finally add the gather. And at this point, in order to generate that string, I called it to BXML function on that response. And then I'm going to send that as a response to the Bandwidth server. Just to kind of demonstrate, I'm going to print that to screen here. OK.
So I'm going to bounce back over to my example here and rerun that. I'm listening on port 3000. And if I send "dog," we know we're going to get a dog message. So let's actually call this and I need to turn my volume up. And how do I mute myself? I have an idea. I'm going to call it with my cell phone. That's all right. 919-335-5733.
AUTOMATED SPEECH: Let's play a game. What is nine plus two?
DAN TOLBERT: And we haven't done anything with that actual response right now. So we know it's not going to do much, but you can see here is our BXML that we sent back to the Bandwidth server. They've tried that on the call and expected us for input. So let's actually handle that input now. I'm heading back over here. We want to play success on input. So I'm just going to grab this copy [INAUDIBLE] here.
PRESENTER: Oh wait. Hold on. Can you guys still hear us on here? I think the connection has been lost.
DAN TOLBERT: Can you still hear us by chance?
PRESENTER: [INAUDIBLE]
DAN TOLBERT: Mine does not say connection lost. OK.
PRESENTER: OK.
DAN TOLBERT: Thank you.
PRESENTER: Yup. Thanks.
DAN TOLBERT: Cool. Wonders--
PRESENTER: My computer is acting funny.
DAN TOLBERT: Wonders of Wi-Fi. This is why we don't do everything live. Even though we are kind of doing things live a little bit now. All right, so let's go ahead and take a look at our function here. I'm just going to grab all this and head back over and paste that into here. So what we're firstly going to do is we're going to grab the data. And that's going to be the body there. I'm going to extract the digits out of that. So if I take a look at the callback that is sent, I'll dive into the voice callbacks gather. There's going to be this field here. Digits.
And this is going to be what was actually pressed on the call. I've got two files here. I've got one that is a success file and one is a fail. And so right now, we only accept dot wav to playback audio on our servers. We're getting mp3 support some time in Q3. I believe it's more of a lift than we originally imagined. So it is, I think, in Q3 three now. It could be earlier, based on priorities, but I would not expect it to be any soon than Q3.
And then finally, we're going to look at our audio file to play back. We do a quick tertiary check. Our digits, was it 11? Like, we know we're asking what is nine plus two? It can only be 11. And if it is, then we're going to play a nice little success. If it is not, we're going to fail. So let's build our BXML. At this point, we know we need to play audio verb. It's going to look something like this guy right here. And again, only WAV files included as PCM or G711 are supported. And we know we're going to play that audio file. And we're going to add that verb. And we're actually going to hang up the call after we're done. We're going to be nice. We're going to clean up after ourselves. So we're going to hang up that call by adding a hang up verb at the very end there. Pretty succinct and self-explanatory and what that point is it's ends the call.
So I'm going to save this. And I'm actually going to put our BXML to the screen here. And I'm going to comment on this one. So now we're going to, on an ML call, we're going to play a game. We're going to ask you what's nine plus two. We're going to create a gather. We're going to grab the response of that. We're going to check it. If it's 11, if it is, we're going to play a success, if not, we're going to fail. And then regardless of that, we're going to end the call.
So I'm back up over here. I'm going to restart our application. I'm going to grab my phone. And I should call that back.
AUTOMATED SPEECH: Play a game. What is nine plus two?
DAN TOLBERT: And I [INAUDIBLE] 22.
[FAIL SOUND]
And so we play our fail. And it ended the call. We'll try again.
AUTOMATED SPEECH: --two?
DAN TOLBERT: And we know that's 11.
[SUCCESS SOUND]
And it plays a little success file for us and hangs up. So relatively trivial. Right? There's not a ton of people building this application, but it does demonstrate how to expect an inbound call, react to it, get some user input, check that input against validity or account numbers. You can imagine what is your account number to start a call. If they get an unknown account number, you could ask them, hey, it doesn't match. Right? It should be five digits starting with one or something like that. Pretty routine use case in that regard. But not everyone is playing a little math wizard that asks the same question over and over again.
So at this point, we have a pretty full demo. We've got about five minutes left. I'll save that for questions. Honestly. The whole app is up and is available on the GitHub repository. We'll just take a look at what the "call me," text looks like under this message dot JS. And this part is relatively simple. All we need to do is make a call to our voice controller to call me. And we're going to say, oh, from and to. And then in that voice package here, our voice library, we have this function Call Me that's exported from here. It creates that API request. It uses this eight answer URL.
This is what we require to know where to send that answer. Again, it's on an outbound call. And [INAUDIBLE] to call it the server, comes back in, and finally, we generate some BXML, and we say, who do you want to transfer this call to? And you can say I want to dial 1-234-123-412-345. And it'll make a call to that 1-234-5 number. You can see how this would look live. If you have all the pre-reqs set up and running, you can clone this repo and just type npm start or run node on index.js. And you can get an idea of what this should do. So we'll take some questions here.
PRESENTER: Don't be shy.
DAN TOLBERT: OK. We have a question. Are you planning to support TypeScript? And we left that interview looking like-- we do have a plan to support TypeScript. We're working on a new suite of libraries for node, for TypeScript, that will also work for node. We're hoping to get those out in Q3 with a sneak peak towards the end of Q2. We are building them using an auto generator pulling from API references using Swagger. So you'll have a way for both types to send these requests. Instead of kind of working with JSON objects, you'll have classes that give you the nice tool tips when you're writing code.
And we have another question about running in the browser. So as we went over today, this is all server side. We very much discourage people from running this level of Bandwidth interaction from the web browser because that would be allowing your clients to send and receive text messages from their browser. It's kind of calling the right click and inspect and running in the console here. Really, because of the way that we authenticate, you would actually be pushing your Bandwidth credentials to the client and they can inspect that request and see what your credentials are. And then once your credentials are exposed, like mine were during this webinar, I need to go through and change all those because it gives you complete access to your account. So very much discouraged in that regard there.
OK. Any other questions?
PRESENTER: We'll give it another, like, 30 seconds to show. But while we're waiting for that, I'll go ahead and thank you guys again for joining us. I'll say this again, we have the Bandwidth.com/DevWithBandwidth that has all of the language sessions that we're going to be running with Dan Tolbert. They're going to happen every week on Thursday afternoon at 2:00 Eastern Time for the next five weeks now. This is our first one. So feel free to come hang out with us and learn some more from Dan.
We have no more other questions pop on. OK.
DAN TOLBERT: No more?
PRESENTER: Well, you guys will receive a recording. I want to say this afternoon, but if not, then sometime tomorrow. But thank you guys again, and thanks, Dan, for--
DAN TOLBERT: Absolutely.
PRESENTER: Have a good one, guys.