Build a Custom IVR Using Twilio
Ever call a company and, as you try to figure out whether you should be pressing 1 or 4, thought, "I could make this so much better"? Now's your chance! Nathaniel Okenwa will teach us to build a custom IVR system with Twilio
Links & Resources
- https://twilio.com
- https://github.com/aaronfrost/DonutsApi
- https://www.learnwithjason.dev/build-a-video-app-with-twilio-gatsby
- https://www.learnwithjason.dev/text-to-play-games-with-twilio
- https://www.learnwithjason.dev/text-to-play-games-with-twilio-part-2
- https://twitter.com/chatterboxCoder/status/1380564275685625860
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
- https://www.twitch.tv/twilio
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everybody, and welcome to another episode of Learn With Jason. Today on the show we're bringing back Nathaniel Okenwa, the original Chatterbox coder. How are you doing?
NATHANIEL: I am good. You said the original. I'm wondering, is there another flavor?
JASON: Often imitated never duplicated.
NATHANIEL: I love it. How are you doing man?
JASON: I'm doing great. Super excited to have you back on the show. It's also a blast when you're around. I'm also excited because we're doing something that I think is very exciting and also such a good opportunity for trolling. Thank you for the sub. Thank you so much. Just hit a year of sub, 12 months of subscriptions. Holy crap.
NATHANIEL: Shoutout.
JASON: I still can't believe I've been doing the show for a year. It's been like
NATHANIEL: Dang, you've come in I don't to say your legacy. Legacy is not always a good thing, but you're aging like a fine wine.
JASON: Why, thank you.
NATHANIEL: I shouldn't have said aging. I mean the stream is aging like a fine wine. Nathaniel, just digging.
JASON: I'm aging like bread, but the stream is going great. Like a nice cast bourbon.
NATHANIEL: People are shouting all Milner in the corner. Yes, go, Milner.
JASON: Yes. I feel like what we're doing today is something that we all deal with when we call somewhere, right? You call in and then you get told, like, you know, press 1 for Account Information, press 2 for Customer Service, para Espanol prima nueve. And that is called an IVR, which I just learned is short for
NATHANIEL: Interactive Voice Response. I forgot and I had to Google a couple of seconds ago. Do you have those things you know what the acronym is, you just forget what it stands for?
JASON: My whole life.
NATHANIEL: Happens to me all the time.
JASON: So many things I spout off acronyms and jargon and I'm like please don't ask me to define that. I've completely forgotten. Nicky. Yeah, so, okay, I'm really excited about that one. Before we talk about that, let's talk about you. You've been on the show before, but for folx meeting you for the first time, you want to give us a little background.
NATHANIEL: My name is Nathaniel Okenwa, AKA Chatterbox coder because I love to talk. My job is pretty much to go wherever developers after. Before the panoramic, I'm calling it the panoramic deliberately, it was in person at conferences, at events, now it's been online, on Twitch, other places. I'm looking forward to meeting people in person as well. I've had a lot of fun. I've started streaming. I joined the streamers club. I stream on Fridays around midday BST. I build cool stuff and eat donuts. If you like donuts, cool stuff and people acting silly, come and watch. We do a lot of JavaScript projects.
JASON: It's such a good idea, one I am very tempted to steal. So, tell me how the donuts work, because I love this format.
NATHANIEL: So, at the start of every stream, I basically write milestones. So I'll be like, okay, I want to build all right, last week I built a thing where if you're talking on the phone, you can talk to someone and it translates. I'll be speaking in English, but they'll be hearing Spanish. If they speak Spanish, it comes back to me in English, right? So, at the start, I break the problem down into the steps that I think I need to do and I try to work through those. If I get through enough of them by the end of the stream, I'll ask the audience. There is always someone who says yes. Which is good. Luckily people in the chat, they love me, so I get to have a donut, a special donut. It changes each week. I'm very excited.
JASON: Have you ever not gotten your donut? No donut for you. You got to throw it in the trash.
NATHANIEL: You know what? There is Diamond Boy, I'm not sure if he's around, but he's always trying to stop me from getting my donut. I've been able to find people in the chat who will always support me. And worstcase scenario, and I've said this before, worstcase scenario, we all know I can turn the stream off and eat it by myself anyway. ( Laughter )
JASON: But at that point, it's more of like a shame donut. You got to eat it in the dark by yourself.
NATHANIEL: I know I didn't earn this, but I need it. I need it.
JASON: No, that's great. And also, thank you everybody for the bits. Thank you Eco. Eco is at 18 months of subscriptions. Holy buckets.
NATHANIEL: Thank you, Eco.
JASON: I can't believe y'all have been hanging out with me for that long. It is absolutely wonderful. It warms my heart. So, Nathaniel, today, we're going to work on an IVR.
NATHANIEL: Cool.
JASON: Which we just learned, both of us, it stands for Interactive Voice Response. When we talk about an Interactive Voice Response, I feel like there are a few varieties, right? There's the classic one. You press 1 to go to a different department, and it kind of it turns phones into a choose your own adventure game.
NATHANIEL: Pretty much.
JASON: But that's not the only way you can do it, right? There's the one you have to talk to and the ones that, like, look stuff up. I know when I call, like, my credit card company, it uses my phone number to figure out if it recognizes my account and then it kind of gives me some basic details. If I put in my pin or whatever, it will let me check my so it kind of jumps through some hoops and stuff. This is all stuff you can build with Twilio, right?
NATHANIEL: Yeah, what Twilio started with and lots of times I talk to people, have you heard of Twilio. They're like, oh, yeah, the SMS company. Yeah, but we do so much more. We had building blocks to allow you to interact with phone calls and do stuff. People began to build really, really complex sort of applications that got hard to build, and then we focused on not just building those building blocks, but building tools that help people make those complex applications and abstract all of the sameness, hard things that you have to deal with when you're building IVRs.
JASON: Yeah, I mean, it's kind of a daunting problem to think about because you're dealing with, like, so, phones are cool because phones are it's, like, technology that's pretty old, but we do things that it's not really meant to do. Like the thing that I always found interesting about it is what you're doing when you do, like, the press 1 for whatever, you're not, like, it's not like you're pushing the button and the other end is receiving that button press. You're pushing 1 and it's making a tone.
NATHANIEL: A tone, yeah.
JASON: And the other end is basically listening for the right pitch and making a choice based on the pitch it hears, which is wild. That's why you can't use rotary phones anymore, right? They don't make touch tones. The tone isn't there. So, it's fascinating. So, what you're doing with Twilio is abstracting that part away. Because there's no, like, you know, on the web, you've got click events, you've got kind of universal things, but you don't have a push 1 event on a phone. You gotta, like, identify the pitch of the 1 button and then make a decision based off that.
NATHANIEL: Exactly, right? So, it takes all of the information. And the thing about, like, phones, even though we're in the age of the internet, everyone's got smartphones and stuff, still, smartphones are not as wide spread as phones. Phones are everywhere, and sort of telecoms, like, technology is so widespread. So, like, for example, any company, it makes sense to be able to build your sort of customer experiences in ways is that have this massive, like, users amount of users on it, and then being able to still port that over to smart, fancy stuff, make with AI, with all sorts of things, and being able to just, like, create cool stuff. That's the way I look at it.
JASON: Yeah, it's really fun. It's really good stuff. So, today, what did you have in mind for today? Like how far do we want to push this? How are we gonna earn our donuts?
NATHANIEL: How are we gonna earn our donuts? So now you've got me going down the donut train. There's a couple of things. We usually call these, like, phone calls, there is a goal, there is something we're trying to get to. You kind of have to jump all these hoops, give it the right information so that you can get to wherever your goal is. I feel like the goal should be a type of donut, right? Maybe we create an IVR that takes you don't a phone tree and figures out the right donut for you. Because there are so many different flavors, so many different things, but imagine, like, you could phone this number and it will tell you what the right donut for you is.
JASON: Absolutely. Let's take this to the VCs. I feel like this is we can get investments for this. Take my money.
NATHANIEL: Absolutely. Absolutely.
JASON: Donutmatch.com. Oh, yeah, playing sound effects from the stream based on a
NATHANIEL: We could do that.
JASON: So, that's a fun followup, I think, because I don't know how we would do that just yet, but once Nathaniel teaches me how IVR works, then I could extend that and make it so that you could call a number and, like, affect the stream, which would be really cool.
NATHANIEL: I've taken phone calls on my streams. I've connected my phone to Twitch, so, like, sometimes people call in and talk. It's fun.
JASON: I love it. Dinder, Tinder for donuts. That's what we're pitching, everybody. I love it.
NATHANIEL: I love this.
JASON: Yeah, I'm so on board. Let's build Dinder. So, first and foremost, let's take a second, let's get over to pair programming view, and make sure that you go and check out the homepage of learnwithJason.dev where you have live captioning going on right now. We've got Jordan with us today writing down everything we say, which is bad for Jordan, great for you.
NATHANIEL: You are awesome. I'm sorry that I talk so fast and talk too much.
JASON: Yes. And that is made possible by our sponsors. We've got Netlify, Fauna, Auth0 to make that possible. Make sure you check that out. Make sure you go ahead and head over to Twitter and follow Nathaniel. So I can do this right on the first try. I can spell. Go follow Nathaniel. It is a Twitter stream full of information and pictures of donuts. It's really wonderful.
NATHANIEL: Is my last picture if you go to media, I'm trying to remember what my last donut picture was.
JASON: Let's see. Where's the donut.
NATHANIEL: If you go down. One more. I feel like what? There we go.
JASON: There's the donut.
NATHANIEL: I may have posted it. Not sure if I did.
JASON: Cookie donut.
NATHANIEL: No, it was a cookie dough donut. It was a donut that had cookie dough in it. If you click on the what flavor question, I posted a link
JASON: Like for part 2.
NATHANIEL: There is a song called the donut day. This is hilarious.
JASON: I love this. Okay. We're just gonna drop this. Here you go, chat. Go play with that. While you're watching that video, we're going to get ourselves set up to run here. So, I have Twilio, but let's head over to the Twilio homepage, how about that? So, let's take a look. Twilio itself does a bunch of things. As you said, I think a lot of people think about Twilio as a company that specializes in SMS, but it does so much more than that. I just realized I don't have sound routed in the right direction. I'll change that to make sure we can all hear things. Twilio is a company that does phones, but it does a ton. We won't get through everything, but do you want to give us some of the highlights of the few things that y'all do.
NATHANIEL: Well, honestly, it's just communication. So, SMS. That means a lot of things. A notification like your delivery is on the way. Twofactor authentication. You have video chat. We have sort of WhatsApp API that's getting pretty popular as well. There's a lot of stuff that goes in the background to help those things, so we have, like, sync, which helps you manage you have to do that for chats. We have sort of now everything is jumping out of my head. We have Task Router, a fancy way to take tasks and assign them to the right people. You do that in contact centers. There is all sorts of cool technology layered on top of each other.
JASON: Yeah, and we've done a couple episodes on this. See if I can find you. This is how good my site search is, is I have to just do a find and replace, like I'm sorry, everybody.
NATHANIEL: No worries.
JASON: I will fix this some day. But so, yeah, check this out. So, we've got, like, video streaming and we've got this is a polling game not even a game, it was just polling that I swear to God one of these days I'm going to finish and actually work into the stream so that we can do live polls, but, you know, this just goes into some of the things. We get into Twilio serverless functions. We look at video chat functionality. The sync service you just talked about, we use that. If you want to see more of what Twilio can do, make sure you go watch these episodes. They're a lot of fun. Today, though, we're going to be working with the OG Twilio use case which is telephony.
NATHANIEL: Yep, back to basics. One of the things we always say at Twilio, you buy a phone and you can do whatever you want with it, and this is kind of where we're going down. So, there's a couple of things we want to do. We want to, first of all, be able to gather information from a person. Be able to take a phone call. We want to be able to sort of gather information about them and take them down a certain path. And then we can give them something at the end. Maybe we want to connect them to someone else. We can do all sorts of things.
JASON: Yeah, so let's do this. I'm going to start writing down notes here, and we will let's plan. Which will be a first maybe for Learn With Jason, to actually start with a plan. So, what we want to do here is we're gonna build Dinder. Remind me who came up with that idea. I want to make sure you get credit because it's so good
NATHANIEL: MazaDeeb. I think I'm pronouncing that write.
JASON: All right. What we want to be able to do here, first and foremost, we need a phone number.
NATHANIEL: Yeah.
JASON: And then you said we needed to get information. So, what are we looking for in terms of information, do you think?
NATHANIEL: So, we're probably gonna, like, ask them some questions about maybe the flavors or things that they like. So, for example, which is better, like, jam or custard? Custard, ah, jam, yes, kind of thing. So, maybe we can sort of take them down that route and find out what their favorite filling is and what their favorite topping is. Maybe we can ask for their favorite filling and favorite topping, and then we create this magical donut for them. I'm just going on Krispy Kreme and checking if they have an API, because that would be fun to build with. I doubt they do, but that would just be perfect.
JASON: If Krispy Kreme has an API donuts API wait.
NATHANIEL: There's a donuts API. Yes! It returns donuts, donut types.
JASON: It scrapes Krispy Kreme's website to get donut info.
NATHANIEL: Let's do it. Yes. Yes. I love it. I love it.
JASON: Okay. So, the following donut the following APIs are available after you run NPM Run Build. Okay, so this is really fun. Let's see what happens if I get this. So, I'm gonna grab this.
NATHANIEL: I'm gonna add this to my stream immediately. How do I not
JASON: Let's see. I'm gonna put this. Just gonna make a new directory. I have this habit that I picked up from Chris Biscardi where a create a GitHub structure that matches the actual GitHub paths and that lets me do this shortcut here where I'm able to make a direct link out of my terminal so I can go straight to the repo if I need to.
NATHANIEL: Cool.
JASON: What do I need to do to start? I need to NPM run build. A package JSON, so let's install. And then while we let that happen, let's keep thinking about what we're going to do. We'll be able to use this donut API as our service here, and then we're also going to be able to so, we'll ask about flavors, we'll ask about toppings, and then at the end, theoretically speaking, we should be able to, like, narrow these down.
NATHANIEL: Yep.
JASON: To show what's left. This might be a little more clever than we want it to be, so we can also do a little more guided, and at the end, recommend a donut.
NATHANIEL: Cool.
JASON: Okay. That seems like it would work. Should we do something like text them the recommendation?
NATHANIEL: Yep. We can do that. I won't be surprised. Krispy Kreme has a website, so there may be URLs to the flavor of the donut.
JASON: That would be amazing. Okay. So, now we're gonna npm run build. This is probably gonna take a while since it's scraping, I would assume.
NATHANIEL: Yeah, that makes sense.
JASON: I just realized I'm executing completely unvetted code on my local machine. Like oh, here we go. Krispy Kreme donuts.
NATHANIEL: 1 of 48. Oh, wait, that's 1 of 48 of recent
JASON: This will take a minute. That's okay.
NATHANIEL: We probably want to
JASON: The tm in the fascinating, how'd they get that in the URL? I guess you can use nonletter characters in there. Let's see. A conversation to be add as to what constitutes a donut.
NATHANIEL: Jacob I don't know if you actually have seen me talking about we actually addressed this on our last stream, literally on the last stream. Oh, my days. According to the cube of food, it depends, it is a ring donut or a donut with a filling in it? If it's a donut with a filling in it, it is a calzone because it starts with the filling inside. If it is a donut as a ring, it is Sushi, a ring with a gap in the middle.
JASON: What about a donut hole?
NATHANIEL: A donut hole? See, it's a toast. It's a toast because there's nothing in it. It's just one piece of starch. It's a toast.
JASON: I love it. I would argue all of them are sandwiches because calzones and sushis are variations on sandwiches.
NATHANIEL: Yeah, I get that. I get that. That is an argument I will allow.
JASON: I subscribe to what I would consider the lunch special philosophy of sandwiches. Everything is either a soup, salad or sandwich. That's really how it goes.
NATHANIEL: Salad or sandwich. That is smart. That makes sense. That makes sense.
JASON: Keeping it simple. Let's see. That would make most blue star donuts into cakes. Yeah, you're probably not wrong.
NATHANIEL: What's a blue star donut?
JASON: So, Blue Star is a donut shop in Portland, Oregon, that they specialize in, like, very hipster donuts. So, like, their classic is an orchata glazed donut and fancy stuff like that. Pizza is an openfaced sandwich. There is also Voodoo Donuts.
NATHANIEL: I've been told about Voodoo Donuts.
JASON: It's a good donut shop. Really what's cool is the novelty of it because they do donuts that are not safe for work. They do donuts that are like a Voodoo doll full of red jam, they stab it with a pretzel stick so it looks like a Voodoo doll that's bleeding. That part's really fun. The donuts themselves, they're okay.
NATHANIEL: Just said in the chat actually said I should go to Portland donuts go to Portland so I can have Voodoo Donuts. I will roll into Portland at some point just to get the donuts, fly in, grab the donut, fly out.
JASON: Well, I won't take that personally at all.
NATHANIEL: I'm joking.
JASON: All right. So we've got our donuts. So, let me run this, and this should give us a donut API at local host 3000. So, this is in the wrong browser. So, let me open it over here. And now we get API donuts look at all these donuts. Okay. And we do get back a URL, so we'll be able to text a URL of the donut.
NATHANIEL: Nice.
JASON: Okay. So, that's really fun.
NATHANIEL: Perfect. And it's got types, right?
JASON: You just went, like, very ASMR. Hello. Let's talk a little bit about donuts today.
NATHANIEL: It's my bad. I literally turned and started speaking into the mic.
JASON: I thought you were getting very serious.
NATHANIEL: Donuts are a very serious thing. Important. So, the cool thing is it actually tells you the types as well, so you can see like the first one, you've got filled. You've got all sorts of interesting stuff here.
JASON: Yeah, so let's grab one of these by ID. How are we doing that? Somewhere in here there's gonna be an ID. There's a description. There's do we not have an ID?
NATHANIEL: It definitely said there was an ID.
JASON: ID, ah.
NATHANIEL: In the documentation.
JASON: Got it. So, let's grab one of these. All right. So, we get a single donut back, and this gives us, yeah, all sorts of things. So we've got the type, and there's categories here, so we'll be able to kind of pull those in. Does it give us did it give us, like, generics, types? Yes. So here are our available types of donuts. So, we can even we could even start by saying, like, if we did I think it was donuts types and then I could do, like, filled, and I think it filters. Is that right? I think that was the format. Type equals ice filled. So, I did that wrong. It should be type. So, this would give us a subset, or we could do, like, iced.
NATHANIEL: Yeah.
JASON: Okay. I love it. Okay. So we can actually, like, filter down. That will be really fun, actually. Because the other oh, you know what we could do? Is we could you could start by choosing from all of the available types and then we could get a subset of what's left after you've chosen your types and filter down until you've chosen everything and then it could give you, I don't know, the top three.
NATHANIEL: That makes sense.
JASON: Okay. So, that could work. Cool. All right. So I think I'm ready. I think I'm ready to get started on this setup here. So okay
NATHANIEL: First thing.
JASON: Write that down. First, choose one of the available types. Filter results for remaining types. Repeat until no types left. Choose from top 3 donuts. Match. Okay. And then we'll text URL of selection. All right. So that, I think, is this seems doable. Like we can earn this donut.
NATHANIEL: Absolutely. Absolutely. You know what? I'm so disappointed that I didn't go. Because I walked past the Krispy Kremes.
JASON: We should have planned it. I totally would have gotten a donut. Yes, some of the donuts do have multiple types, so what we'll be doing is basically keeping tracks of which types have been selected and finding them that match all of the things. You can get a Boston Cream would be a custardfilled donut with chocolate icing or things like that. So, we'll be able to or, you know, a filled donut with chocolate icing and sprinkles would be filled, iced and topped. Hopefully by making these selections, we'll end up with a subset of donuts well, we'll have to be because we'll be filtering the results to see what types are left, and once we run out of, like, additional subsets, we'll just choose the top three.
NATHANIEL: Cool.
JASON: Cool. So, I'm ready then to do this. Which means I now have no idea how to start with a, like, a Twilio telephony app.
NATHANIEL: So, we're going to, first of all, do a basic thing and then go and talk about how complex it can get, and then skip to the tool that takes away that complexity.
JASON: Great.
NATHANIEL: Cool. So, number one, we need to buy a phone number.
JASON: Okay.
NATHANIEL: So, we should be able to just head over to the Console.
JASON: Let me get logged in here. Get this off the screen. No, it's not gonna let me do that. Let me do it over here. There's my Twilio. Am I in? I'm in. Okay. I'm in. I need a phone number, and my phone number is this one here. Looks like a number. That's how I knew.
NATHANIEL: Do you want to try the beta console that was built on a really, really cool platform?
JASON: Oh, yeah, I do.
NATHANIEL: Up top.
JASON: What?
NATHANIEL: We just launched a beta the beta Console which makes everything look different. It actually makes things easier to find as well.
JASON: I am very excited about this. So, looking for where's our route request here? This one? Console.Twilio? Look at this. Y'all, Twilio is deployed on Netlify now. I'm really excited. I'm super pumped. And, like, how cool is it that you can deploy something this complicated on, like, the jam stack on Netlify?
NATHANIEL: Nice.
JASON: It's very, very, very cool. Yeah, that's not what we're talking about today. Today we're talking about is we want a phone number. So, I have a couple of things that we've got here. We've got this polling app, so we could theoretically use that one, but let's not. Let's get a new number.
NATHANIEL: You've got some GitHub actions as well. Nice.
JASON: I do. I set one up I think with Brian Douglas. He and I set one up to text when somebody pushed to a repo, which was pretty fun.
NATHANIEL: That makes sense.
JASON: Let's see. Match to the first part of the number. What about a Portland number? Oh, wait, what's the original? 503. And we want voice, right?
NATHANIEL: Yep.
JASON: Any 503s? We get a 503. Yeah, one of these will work. How about this one?
NATHANIEL: Cool.
JASON: Okay. So, I'm getting my phone number. Voice, fax, SMS, MMS, so that's everything that a phone number can do, right?
NATHANIEL: Yeah, these are all the different so, different phone numbers, especially in different countries. In the US and in the UK, it's not necessarily, like, so hard, but in some countries, there's not necessarily it's not easy to find a number that does voice and SMS and fax or does one or the other. So, there's different ones. Also, you may not need SMS. So, if there is no need to buy a number that has it if you just need calls.
JASON: Nice. Okay. So, I'm here. I'm ready. I've got it. I've got a SID.
NATHANIEL: So, now what we want to do is configure it. If you scroll down a little bit further, you're going to see what we can do. We can say it should accept incoming phone calls, and when a call comes in, it will make a it will create a post request to a URL that we will [ Inaudible ]
JASON: Okay.
NATHANIEL: We can quickly spin up a Node server that will give it some TwiML.
JASON: We can do this with Netlify Functions, right? Let's go incoming call.js. I'm going to have to deploy this so it can hit it, right?
NATHANIEL: Yes. You can deploy it or use a tool built by a Twilion basically to solve this very thing, but useful for everything else, right? If you're working locally and for some reason you need to expose the local host on to the web, you create a tunnel from a URL to your local host. It's temporary, so it's not something you would ever do in production, but it's really useful when you're developing locally. I like to use it sometimes if I'm working with working to build a friend or a little person outside of work, I send them a link so I don't have to go about deploying the changes every time when it's just like a tiny change.
JASON: Gotcha. Okay. So, let's go to GitHub Learn With Jason Twilion IVR. And then I think what I can do is Netlify Dev live, which I think will use ngrok. Let's see. I need to initialize this. I'm going to get add everything. And we'll git commit as a work in progress. Twilio IVR. Okay. And then I'm going to GitHub repo create learnwithJasonTwilion IVR. I love this CLR so much.
NATHANIEL: It is so cool.
JASON: We're going to create that. Got it. Git push, upstream origin main. Got it. And then I can Netlify in it with the Netlify CLI and this will create and configure a new site. I'm going to put it on my team. We'll cull this Twilio IVR. I don't have a build command yet. I don't have a direct route of deploy. It auto detected Netlify Functions, so I'm gonna run that. Deploy
NATHANIEL: This is so smooth. You know what? Even I've used the Netlify CLI before, like, seeing someone who uses it sort of every day, it's I guess it's probably the way people maybe feel when they see me using the Twilio CLI. It looks so beautiful. Just how easily you can do things and get stuff done.
JASON: Okay. So, theoretically speaking, I should be able to Netlifyfunctionsincomingcall and it responds okay. We have a running local server to use as part of our development flow. I'm going to drop this in here. This isn't going to work.
NATHANIEL: Twilio markup language.
JASON: Got it. Is there an easy way to test this? Is there a hello world kind of default?
NATHANIEL: If you just change the status type. The content time to xml
JASON: Okay.
NATHANIEL: So, you want to return to xml.
JASON: I'll go content type is, what is it application xml?
NATHANIEL: I believe so. Text/xml, I think.
JASON: Cool. Yeah. I believe it.
NATHANIEL: And the body we want to do. If you just say it needs the opening tag response, so open and close tag response, and then inside that, it needs to have
JASON: Like this or lowercase?
NATHANIEL: No, capital for the R and then let's put a say in there. Say welcome to your phone number or something like that.
JASON: Okay. So I'm going to save this. It says it successfully reloaded. All right. If I call my phone number, theoretically speaking, I need to get my phone hooked into here so that we can actually hear it. I'll put it on speaker so that we can try it. I'm going to call my phone number. So, 5033860093. I'm gonna call that, put it on speaker and it should
**Welcome to your phone number. ( Laughter )
JASON: Holy crap, that was so much easier than I thought it would be. That is outstanding. I'm not kidding. Like, wow. That is wild. Like we just ran we just ran a phone number okay. I'm just going to say this out loud because it sounds bonkers in my head. So, we've been doing this now after we stopped screwing around for about ten minutes, we have purchased a phone number, we've set up a new website, a server, and got it set up in such a way that Twilio is when I call my new phone number that I just bought, it is hitting a serverless function and then responding in language that I wrote with this just basic XML here.
NATHANIEL: Exactly. Precisely.
JASON: Wow. Dang, that is cool.
NATHANIEL: And the cool thing is
JASON: This is really, really cool.
NATHANIEL: Right now we've kind of written the XML as a string, but what you can eventually do, and we'll do this in a second, when you use the Node Helper Library to do it, it can become more dynamic and add more complexity still in a very straightforward manner.
JASON: Yeah, I'm, like, I'm very, very happy about this. Like the whole thing, it feels like a super power, right? When you can do something like this this quickly, you just go it makes me just want to be, I'm the smartest developer alive!
NATHANIEL: Absolutely. Absolutely.
JASON: Please don't clip that, chat. They're already doing it. ( Laughter ) Coming soon to a sound effect near you.
NATHANIEL: Oh, man. Please take that so I can turn it into a GIF and use it any time I'm feeling really good about something I've built.
JASON: Good.
NATHANIEL: So, I'm guessing what's next is now if we go back to our readme what did we have as our next part of the task? So, we've got a number to call.
JASON: So now we need to ask questions.
NATHANIEL: Ask questions, right.
JASON: So, we can get our list of available types, which I'm actually wondering if maybe we can this runs TS Node, which means I'm gonna have to I guess it can work locally because this is local and I'll figure out how to deploy it later. I don't know how to deploy a Node server super easily. I wonder if I could, like, scrape it and just put it into a JSON file or something.
NATHANIEL: I think it is a JSON file. I think when you run NPM run build, it just creates a JSON file. I think I saw that in the in the
JASON: Oops.
NATHANIEL: Yeah, donuts.JSON file in your project folder, it should hold everything.
JASON: Beautiful. Okay. So, the part that I don't have is this server is what's doing the filtering on the data.
NATHANIEL: Yeah.
JASON: So, for now, let's we'll just try to run it locally. Let's make sure we can do that. I will run this as run serve, and then let's get one donut and say its name. So we've got where is our donut? We've got one donut here. We'll get this the original filled do I have to put the tm in there? You do. You have to put the tm in there. That's wild. Fortunately, I know how to do that. Okay. So, then I have a title.
NATHANIEL: Cool.
JASON: So, if we take this, then what I should be able to do in here is we can do, like, let's get fetch equals require node fetch and then we'll get the donuts. Will equal await fetch
NATHANIEL: I love how we're I wonder if you knew what we were building or if you just saw me on a stream and was like, there's donuts somewhere. I really want to know because that would be hilarious. I didn't bring any donuts today, unfortunately. But that's cool. So now we've got the title, and now we can have you already got perfect. Now you can say what the title is.
JASON: Right. So, that should theoretically work, so I need to come over here. I'm gonna stop this NPM install Node fetch so that we've got that available. Then let's run this again. We're gonna have to change up our live port because I just stopped and restarted the server. So, take this one. And we're gonna drop this in here. Okay. Save that. And assuming this works, I can call this number again. So, we'll go to my recent. Call it.
**Original filled, original cream.
JASON: Oh, my goodness, y'all. I can't even get my head around how I was really expecting this to be so hard. I'm not lying. Like, I was, oh, we're gonna get 10% through this.
**Aha, behold, my bucket.
**Indeed, behold my busket. We're in great shape. I'm so excited right now. We have. This is our code. So we're able to get our donuts, right? I guess now is the part where right now all we're doing is we're returning information. We're not doing any kind of interactivity, right? So, if I want to so, we can get our donuts. So we can get a list of the available types, which I could do something like if we do types, right? That was the was that the
NATHANIEL: Yeah, I think it was types. No, it was
JASON: Types. That will give us an array.
NATHANIEL: Yeah, there we go.
JASON: All right. So once we've got our array of types, we can do, like, we can let's see. Text would equal, like,
NATHANIEL: Well, okay, so
JASON: Choose from
NATHANIEL: Okay.
JASON: What do you think? Should I do something different?
NATHANIEL: That is that is where I was kind of going, but the thing is rather than sort of writing out the whole string, I was going to suggest, like, if we used the Helper Library, what we can do is just iterate over that so, we can say please choose from one of the following options and then just iterate over the options and use that to add the next line of what to say.
JASON: Let's do that. Because I feel like otherwise I'm gonna burn a bunch of time and I want to make sure we get through this. So let's do what's the Helper Library?
NATHANIEL: Twilio.
JASON: Oh, that's easy. Okay. So, we're going to install Twilio. And then I'll be able to get Twilio, acquire Twilio. And what am I using out of here?
NATHANIEL: If you go so, if you go to Twilio and then you come down one more and you create a messaging response, so const messaging response. I like to put it in capital letters.
JASON: Like that?
NATHANIEL: Yeah. It equals Twilio.TwiML.messagingresponse.
JASON: Any arguments?
NATHANIEL: Not yet. So what we do now is if you go down to inside your actual inside your function, if we do just do const TwiML, which is what we need to generate, equals a new messaging response. Cool. And then now what we can do is we can go TwiML.say. It takes an argument which is a string and we say please choose from one of the following options. And then what we can do is because we have an array, right? Types is an array. We can go types.foreach.donuttype and in there go twiml.say, the name of the donut, but then we want to say press index plus 1 because you can't go plus 0. So, press index plus 1. For and then donut type.
JASON: Okay. All right.
NATHANIEL: So now they can say what type they want. And then what we want to do is instead of that, we just go twiml.tostring.
JASON: Beautiful.
NATHANIEL: So, that just makes it easier when you're generating. I can see we've got why has TwiML got a squiggly line?
JASON: I've got spell check. There we go.
NATHANIEL: Cool. All right.
JASON: Okay. So then this should work, right?
NATHANIEL: So, now mmhmm.
JASON: Okay. Let's get our endpoint updated in the panel. I'm also just completely blown away by the fact that we are running this live. I'm not gonna lie, this is actually the first time I've used Netlify Dev live, and usually I just don't need the local server to be available live, so this is this feels like a little bit of a gamechanger here. Okay. So, now if I run this, I'm gonna call the number again.
**We're sorry, an application error has occurred.
NATHANIEL: Oh, what went wrong.
**Goodbye.
NATHANIEL: Can you go to that URL in your browser? Because what should happen is that should generate the same XML that we're kind of expecting.
JASON: Oh, okay. What have we done wrong? Error. TwiML.say is not a function.
NATHANIEL: Do you want to go back? Oh, I'm an idiot. See how I said messaging response? It's voice response. ( Laughter ) You know it's crazy how I just remembered. That messaging should be replaced with voice response. That was such a silly mistake.
JASON: It's okay. We all forgive you. Successfully reloaded, but it's not do I need to, like, stop and restart here? I'm gonna stop and restart. Let's stop and restart. And then oh, I think I know what I was doing wrong. I think I'm on an old version. So, let's
NATHANIEL: Thank you.
JASON: There we go. So, that's doing what we want. So let's get this in here. Oh, wait. I need this one. Okay. I'm gonna save. Let's try again.
**Please choose from one of the following options. Press 1 for filled. Press 2 for iced. Press 3 for chocolate. Press 4 for glazed.
JASON: I love it. There was some feeling. Press three for chocolate. Like he's trying to sell that.
NATHANIEL: Oh, so you can actually change the voices when you use that Amazon poly or povy voices? They actually sound sometimes they sound ridiculous. One thing I love is you can put accents on them. I love going and putting on an Australian accent on everything. Just for the laughs. ( Laughter ) It's hilarious. All right. So, now that we've kind of been able to sort of give these people the options, the next thing we want to do is we want to actually collect some information. And the way we do that is with a gather. So, what you will do is just write twiml.gather.
JASON: Okay.
NATHANIEL: And that's going to take a couple of options. So, it actually takes in an object you can actually just do it like that, but let's put an object, and it's gonna have an action, although, it might be able to read the action. Should be an action.
JASON: This action.
NATHANIEL: Yeah, action. That's gonna be a URL. So, what's gonna happen is when it gathers the information, it's gonna make a call to the URL of action, which asks, like, here's the information, what do you want to do with it? And then that URL needs to create TwiML. Now, what I like to usually do. Even if you leave it blank, it just goes back to the URL. Sort of the route an the Americans like to say or the route that you're already on. So I usually like to go back to the route, but then add parameters into and all the, like, things that you gather will be included in that request. I can be like, has the person already made an option? If they have, let's not just repeat the whole first step. Let's
JASON: And does it post?
NATHANIEL: Yes.
JASON: Okay. And so the body would be, like is it gonna send as JSON like that? Like if I do or how does it come in?
NATHANIEL: Yes. That is how it comes in. So it should be a JSON. And then you should be able to go so, let's console.log that body first. If certain things are in there, if we already know a little bit about them
JASON: If we want it to loop, then, we can just leave this empty?
NATHANIEL: Yes.
JASON: Okay. So, let's do that. And we will have it gather. And I think it's still running. It is. So let's just try that again.
**Please choose from one of the following options. Press 1 for filled. Press 2 for
NATHANIEL: There is one thing I should change, actually.
**Press 4 for glazed. Press 5 for toppings. Press 6 for other varieties. Press 7 for fruit. Press 8 for cake.
JASON: 3 for chocolate. And then it should have logged something. It did.
**Please choose from one of the following options. Press 1 for filled.
JASON: At least I think it that looks like it did what it wanted, right? Did I just dox myself? I did.
NATHANIEL: Oh, wait, can you scroll down?
JASON: Yep.
NATHANIEL: There is the second one. Right at the bottom, gather end. Did you press an option?
JASON: I did. And the option that I pressed was at least I thought I did.
NATHANIEL: It should be on input, so if there's an input
JASON: Whoops. No!
NATHANIEL: No worries. No worries.
JASON: Well, didn't mean to do that. Let's go here.
NATHANIEL: All right. One thing that we should do as well is we should kind of move our says. So, right now we have our say first then our gather. So if a person, like, pressing digits before let's say the first one was what they wanted, it's still they've got to wait until the whole thing plays.
JASON: Okay.
NATHANIEL: If you move the gather a little bit further up, and if you change it so that if you go const gather, const gather equals twiml.gather and then change the order of more.says to gather.says, it's saying these says live inside our gather, so if the person, like, presses a button, it should be that's totally fine.
JASON: Okay. Yeah. All right. Let's see if that process ended when I closed that. It looks like it did. Okay. So let me grab this. Throw this in here. Save. And then let's try again and let's see if we get
**Please choose from one of the following options. Press 1 for filled. Press for iced. Press 3 for chocolate. Press 4 for glazed.
JASON: Okay. So, that time it did gather and we should see an input.
**Please choose from one of the following options.
JASON: So it hits 3
NATHANIEL: If you see digits I can see it move up, left, up, there we go. Digits 3.
JASON: Okay. So, now I should be able to so this isn't it's not a string, it's a query parameter, so I can here do qs equals require querystring, and then I can qs parse. Okay. And then what I want is the digit and what else? Should I get, like, the message or anything?
NATHANIEL: Um
JASON: Or digits?
NATHANIEL: Do we I'm trying to think, is there anything else that we're missing? I can't think of anything. See, we should go on.
JASON: Well, we'll need additional like some kind of state to let us know what phase we're in, won't we?
NATHANIEL: Yes, we would. So, I'm trying to remember see, this is where we start to get really complex. So, what a lot of people do is they add extra parameters on to the request so that Twilio can sort of keep track. So that you can keep track of how far the person's gotten. You get really complex and end up building a state machine. So, now this is where I go, like, we're going to go down the bridge of diminishes returns.
**Press 3 for
JASON: Okay. I pressed 3.
NATHANIEL: And it's just gonna read back.
**Please choose from one of the following.
JASON: Okay. So, it's doing what we expect, but we don't currently so, like here because we only have one step right now, we have, like, this is we can manage this.
NATHANIEL: Yeah.
JASON: But with two steps we wouldn't know if we were at step one or step two. This is, like you said, if left unattended what I did I just open? Hello? Back here? No? Anyone? How did I do this? What have I done? I don't want to nope. Help! Anyone who knows how vs code work
NATHANIEL: You've got your uncommitted changes. You're looking at the tree. I think if you
JASON: What have I done?
NATHANIEL: If you click on the
JASON: Yeah, you're right, I pushed this button. I've never seen that button before. That's okay. Yeah,.
NATHANIEL: So, no worries. So now this is where to basically track state. The normal way to well, the developer way to do it, if we wanted to only write code is we'd basically track cookies. So we would send we would create sort of a session for this and then just keep updating it every time and then create an option and we'd slowly be able to fill ow that piece of information. So, we can say this is the question we asked and this is the answer and use the information later. However, that gets really, really tedious.
JASON: Sure.
NATHANIEL: And also what we've had is we've had, like, hundreds of customers build state machines. We're like, you know what? Why don't we do it for them. So if you go over to the Twilio Console, Twilio Console, we're kind of getting away from a bit of code. Just a little bit.
JASON: Okay.
NATHANIEL: There should be an option called Studio. On the left, explore products and add Studio.
JASON: Oh, no, beta.
NATHANIEL: There we go. If you scroll down, you should find Studio. Solutions, Developer Tools. Studio. So, Studio is basically a drag and drop solution that allows you to create your tree. We call them flows because that's kind of what's going on, you're flowing from one to the other.
JASON: Okay.
NATHANIEL: We can start from scratch or we can use something built in.
JASON: Let's start from scratch. That sounds like fun. So, we're gonna go next.
NATHANIEL: Perfect.
JASON: And
NATHANIEL: Get rid of that.
JASON: Incoming call.
NATHANIEL: So, we're going to use incoming call. If you go on the right, you see you've got this widget library, and this is basically all the things we can do. Gather input on call. Just drag that over. If you drag it down underneath, and then connect that red dot there you go. And voila. So, if you go into that gather input on call options. So, yeah, we can then add some configuration. That's really interesting how your thing is squashed up.
JASON: I think I have a smaller screen, so I'm like zoomed way
NATHANIEL: Oh, that makes sense. So, if you go to the config first on the left.
JASON: Config.
NATHANIEL: There we go. So, you can do a couple of things. You can either say a message or play a message. So, for that say is where we'd want to give it all of those different sort of options. What I think we should do, for now, just to save time, because we've already done it, is if we go what we want to do is actually fill that out with our questions. And the way you can actually do that is we can do it in a couple of ways. We can actually write the question out, we can record it, but what I am thinking is we want to be able to go over to our code that we're writing and just get it, get all of that twiml written out already because we've done it. So, we're gonna add a different widget. So, if you hit the small arrow, the small back arrow, that one, and this time scroll down, you should see one that says twiml right towards the bottom. Make HTTP Request, actually. Sorry, add twiml redirect is what I meant. Add twiml redirect.
JASON: Okay.
NATHANIEL: So, what we can do
JASON: Like am I connecting this one instead?
NATHANIEL: Connecting that, and then what you're gonna do is configure that so that points to the URL that we've done so far.
JASON: Got it. Okay. So, that's here. Here. And then we're gonna go to Netlify. Whoops. Functions. Incoming call. Post. Timeout. All makes sense.
NATHANIEL: Cool.
JASON: Okay.
NATHANIEL: If we so now what that's gonna do if you get rid of that one. Hit publish. Right at the top. So, after saving, you have to publish, and then we need to just quickly go and change our phone number. So, maybe you want to open that in another tab. If we go back to our phone number, and now point our phone number to this URL. If that makes sense. So, if you go to phone numbers
JASON: Here?
NATHANIEL: Yep.
JASON: Manage. And we've got oh, manage.
NATHANIEL: That's numbers.
JASON: Okay. Here's
NATHANIEL: Just click the number.
JASON: Now I need this number?
NATHANIEL: You don't. No, you don't. If you go back to it.
JASON: Back to here?
NATHANIEL: Yep. And scroll down to where we changed the URL. Change that for when a call comes in. Studio Flow.
JASON: Oh, slick. Okay.
NATHANIEL: And then now hit save.
JASON: Okay.
NATHANIEL: So now your phone's gonna go through that state machine, and what we can do is we can let that state machine handle states and just go, this is the first question to ask, this is the second question to ask.
JASON: Okay.
NATHANIEL: And this is how we go through it.
JASON: And do I do that in Transitions?
NATHANIEL: So, yeah, we can add more things. So, right now it's already going to work and recreate what we've done before.
JASON: Okay. Let's we can validate.
NATHANIEL: Drum roll. Find out if I'm right, if I've made any mistakes.
**Please choose from one of the following options. Perez 1 for filled. Press for iced. Press 3 for chocolate.
JASON: Chocolate. Okay. So, that did what we expected.
NATHANIEL: That did what we expected.
**Please choose from one of the following options.
JASON: Okay. So, that's better. We're already, like, we're here, it's working, it's doing what we expect, so then we're so we're getting that first response where I'm pressing 2 or whatever number and we're getting the number back. So once we have that, we now need to respond again and we're gonna do that through what?
NATHANIEL: So, the last thing we need to do is we need to go back to our the code that we have written. And the last thing we need to do is we need to hand so, basically the twiml redirect, the reason it was created is so that you can sort of do whatever you want in code. We could have written to gather manually, but what I'm thinking would be really smart is have the API go, okay, here's the options I already know, let's go through them. So what we want to do is right at the end, we want to do a redirect, so we want to basically say hand, like, sort of power back to the hold on. I need to pause and, like, think in my head. Are we doing this in the best way? Because I'm thinking we're about to go into, like, a loop and about to dox ourselves if we're constantly hitting gather, sending gather back to the same spot. So, I feel like I'm sorry, I'm apologizing, but I feel like we're gonna have to slightly change our approach.
JASON: Sure.
NATHANIEL: And the way were going to do that is we are going to so, we've gone through all of the things that we gathered there. We gathered there. Sort of answer. And then we if we do have the answer, what we want to do is return that back to TwiML Studio. If we go back to Twilio Studio, and if we change if we hit if we change this Netlify function and add instead if we add a new sort of widget, that's what I mean, a new widget. Let's add splits based on. And if we put it underneath when we get the return, perfect. So then now what we can do is maybe we can say we can test the variable digits and we can see what they said and we can do something based on that.
JASON: Okay.
NATHANIEL: If that makes sense. Type select.
JASON: Choice?
NATHANIEL: So, what we need to do if you just give me one second, I'm just trying to remember how to get digits. So, if you go to Netlify Function. Can you type in Netlify Function? Netlify Function that should have outputs. Give me one second.
JASON: Do I need to, like, specify those or anything?
NATHANIEL: No. Because what happens is when it comes back, when you when you come back, you should have it just in there.
JASON: Okay.
NATHANIEL: Just give me one second. I'm just gonna quickly look into the docs because I don't remember everything, but what we want to do is basically we're going to go through the state machine and slowly add things on and on. But you know what? Let's actually just do this a different way. Let's go back and create a new widget, and the widget we're going to use is a gather. I'm going to stop overcomplicating it in my head.
JASON: The gather put on call.
NATHANIEL: Yeah. And then what we're going to do is we're going to say in the Say Message on the right, and then we're going to basically write out those options. So, we're gonna say, please press 1 for iced, and we need to go through the donut API to just make sure we have all the options.
JASON: Okay. So we we won't be able to use the donut API to
NATHANIEL: To do it or we I can't think in my head right now of an efficient way to do it quickly.
JASON: Would it work to so, one of the things that we could do is we could also just create multiple functions.
NATHANIEL: So, yeah, we could create multiple functions and just return those.
JASON: Because if we can drop that into the gather as the action, because then we'd be able we wouldn't have to keep state.
NATHANIEL: Yeah, that's actually a really good way to do it.
JASON: Okay. Let's do that. So, we can do, like, step one. I guess we'll call this one step two.js, and then that would be we can get all of this and we'll get the digits. So we'd be able to drop the digits out of here. But what we'll be able to do on this one is we'll have a digits and then we'll have our types, and so we can do selected type equals
NATHANIEL: The index
JASON: Types digits 1. Okay. Console.error so that we can figure out what we did wrong. And then if we'll just assume that's gonna work because it should. So then we've got our types. And once we know what our selected type is, then we can make a donuts would be await. Fetch. And that'll be HTTP local host.
NATHANIEL: What else was there?
JASON: 3000 donuts. Type equals. Selected type.
NATHANIEL: Cool.
JASON: And then we will get the response. Do res.JSON. This might backfire on us. What might end up happening is we can do a donuts. what am I looking for? If I want to get a unique oh, God, I'm going to have to reduce this, aren't I?
NATHANIEL: If you want to get a
JASON: If I want to get a unique set of remaining types, I'm probably gonna need to
NATHANIEL: Filter.
JASON: So, let's do it like this. We're gonna do a new set, I think. And then we can do, like, donuts.foreachdonut. And then here we can do a donut.foreach no, donut.type.
NATHANIEL: Other than type, do we have any other what other information did we have?
JASON: We don't get a lot. Let me use the network here because this will give us an easier so, for each of these, we get a banner URL, description ID, image, nutritional facts, type. I think types are the only thing we're getting that is gonna help us. What we should be able to do is donut types for each, and then what we can do is call it dType. And then we can say. Actually, it will be if dType does not equal selectedType because we want to drop that from the options, then we can do remainingTypes.set dType.
NATHANIEL: That makes sense.
JASON: This should, theoretically speaking
NATHANIEL: Tell us. But what happens if, like, somebody wants eight donuts and only one type?
JASON: This is the part we'd have to figure out, right? If we only get one type, I don't know, I don't think this is gonna be the best, like, we're probably not gonna get you to your ideal.
NATHANIEL: We could always do 0. Like if you're fine with all these options, press 0.
JASON: Yeah, we could do that, actually. So, if we get to remaining types, what this should do is this should give us a list of what our remaining donut types are.
NATHANIEL: Mmhmm.
JASON: And then maybe what we can do down here is that sounds delicious. Do you want to further refine your donut match?
NATHANIEL: And you can say, if yes, press, like, the number for the type you want. If no, press 0.
JASON: Yeah, so the last one would be gather.say. If you're happy with your donut type, press 0.
NATHANIEL: Cool.
JASON: Okay. So, theoretically speaking, this will work. Maybe.
NATHANIEL: Yeah, let's go update our phone number and find out.
JASON: Okay. Well, we need to update this one to send to our second action type.
NATHANIEL: Yep.
JASON: To do that, I need to
NATHANIEL: You can just give it a what's the word, a
JASON: Relative.
NATHANIEL: Just a slash. That's the word I was looking for. A relative URL.
JASON: Step two. Okay. So, theoretically speaking then did I stop and restart this? I did not. Oh, but we have a new function, so I'm gonna do it again. Okay. So, we've got this one. We're in our console. I'm gonna set up our phone is gonna go to a web hook again. Netlify Functions, incoming call. Let's see. I'm gonna save that. Let's try this again. This is very exciting.
**Please choose from one of the following options. Press 1 for filled. Press 2 for iced. Press 3 for chocolate. Press 4 for glazed.
**We're sorry, an
NATHANIEL: So it went wrong. Do we have any logs in your
JASON: Let's find out. End. Remaining types.set. Oh, wait, I just screwed up my I screwed up my code. I bet somebody told me that in the chat and I didn't read it. So what I wanted for a set is I wanted to add not set.
NATHANIEL: What did oh, okay.
JASON: Okay. So in here, I want to add. Okay. I think that will do. That should do the business. It says it reloaded. Let's try again.
NATHANIEL: Drum roll.
JASON: Come on, phone. It's just calling. Let's try that again.
**Please choose from one of the following options. Press 1 for filled. Press 2 for iced. Press 3 for
JASON: Tell me it sounds delicious. Come on.
**That sounds delicious. If you want to further refine your donut search
NATHANIEL: Say 1 for all of them. Why is it doing that?
JASON: I did something wrong. Press cake 1 for cake. I mean, yeah, cake 1 for cake is really what I'm after. What have I done wrong here? Remaining types for each
NATHANIEL: Do we have an index?
JASON: I think I need to just turn it back into an array is all.
NATHANIEL: Oh, okay.
JASON: So, this should that should work. So, let's so let's see if we can get the next step going here. So we're gathering. And then our next, next step would be to take this to, like, a step three.
NATHANIEL: Step three, yeah.
JASON: Okay. So, let's take our step three. And with this one, maybe what we can do is we can do a query for the two types and then just return our top donut and then because we're at about ten minutes here, so that'll give us that'll give us enough, I think. So, let's duplicate this one. Is there a duplicate button? I thought there was. There's not. Okay. Fine.
NATHANIEL: Wait, but you did do a duplicate. Oh, it just renamed it when you did that. Okay. That makes sense.
JASON: So I have my step two in here.
NATHANIEL: Step two needs to point to step three. The gather. There we go.
JASON: Okay. So, that's pointing to step three. Now in here we'll get digits again. We'll have what our digit was. And this time we're going to we're going to get our types, ooh, but we lost our original selection.
NATHANIEL: First type.
JASON: Crap. Is there a way to just, like, pass that through with here? Like can we oh
NATHANIEL: I go on.
JASON: I'm wondering if I can, like, include it in the query string?
NATHANIEL: Yes, you could. Oh, that's what that's what we should have just done from the beginning.
JASON: Yeah, I know.
NATHANIEL: Because we can basically have a query string with, like, all of the inputs that we've ever collected and kind of use that.
JASON: We definitely could have. What have we learned today? So, it was selected type? Yeah.
NATHANIEL: Yeah.
JASON: Okay. So let's do that, and then we'll also get a query string prem. So, it'll be selected type no, what was it? Type equals event.querystringParameters I think it is.
NATHANIEL: Yep.
JASON: Okay. And then here we're not gonna do a query for types anymore. Instead, we're gonna do a query for donuts that have a type of
NATHANIEL: Type.
JASON: Yeah, a type of type and then the oh, crap. We do need the types again because I got to
NATHANIEL: Well, what we could do, if you go back to step two, right, in that URL, we put the selected type, right? What we could do is over in step three okay, so in step three, we hold on.
JASON: Because I need to pull the type out that we need here.
NATHANIEL: Yeah.
JASON: Okay. So let me let me just undo all of what I just did because we're gonna have to look this up again. So, we've got our types, but I do have my parameters. And so then my selected type is gonna be digits. So we'll do, like, first type equals types type minus one or hold on. No, we're just passing in the actual actual value there. So that one can stay. And then so let's rename this one to first type. Rename this one to secondType. And then we're going to do firstType.
NATHANIEL: That makes sense.
JASON: SecondType. We're introducing a problem, if you were to press 0, this wouldn't work, but we're out of time, so we're gonna try to get a donut back is really what I'm after here. So once we look up donuts, I want to get let's just get the first donut, and we can text that back to the number. Seems like the right thing to do.
NATHANIEL: Cool.
JASON: So, this way we can get the donuts.0, and then with my donut, I want to, like, my text message should be something like be like "your dream donut is is a donut.title and then we would, like, donut.URL, I think. Let's look at the console log here and make sure that's the correct thing.
NATHANIEL: Yep.
JASON: So, this will take us to the donut. Okay. So, theoretically speaking, this would be our message.
NATHANIEL: Cool.
JASON: So, instead of sending back more TwiML here, we would actually want to
NATHANIEL: Do you want to say the message as well? Should we just say it and text it?
JASON: Yes. So, let's do twiml as a voice response. So we are gonna to
NATHANIEL: Twiml.saymessage.
JASON: We'll say twiml.saymessage, and then we also wanna add, we will text you this information for posterity. Mostly I want to hear what the robo voice does with the word posterity. Okay. Then in here, we want to send a text message.
NATHANIEL: So, to send a text message, we're going to need to authenticate our Twilio client.
JASON: Okay.
NATHANIEL: You're going to need your account Auth token. Go to secret page soon. So if you go back to sorry
JASON: Here's what I'll do on this side. I can use a.env.
NATHANIEL: _account underscore SID. And your Auth token is also down there.
JASON: This one I can take and copy. I'm going to pull this off screen before I click any buttons. I'm also going to pull this off screen. Let me click my Auth token that is copied.
NATHANIEL: I love that. Your choice was Supercalifragilisticexpialidocious. Where is that from? I feel like I've heard that somewhere.
JASON: What is that from? It's from "The Sound of Music," "Mary Poppins." One of those two.
NATHANIEL: Yes.
JASON: Set up with the Auth token. So then it should pick those up automatically, you said?
NATHANIEL: No, what you've got to do is const client equals Twilio because we've brought already Twilio and then just put brackets next to it. Then you go. Now it's authenticated. Then if you go client.messages.create
JASON: Okay.
NATHANIEL: And it takes an object. It takes in a to, a from, and a body.
JASON: Okay. So, to is gonna be we need to pull up the number.
NATHANIEL: Events.from.
JASON: Like this, right?
NATHANIEL: Yeah.
JASON: Okay. And then the or wait the from is from what I send, right?
NATHANIEL: Yeah, so if you do a from well, you don't even need to no, no, you don't even need to do that, you can just do from and to.
JASON: But we're inverting them, right?
NATHANIEL: Yes. Yeah, that makes sense, yeah.
JASON: So this way when we get when we invert it, it'll actually make sense down here. To number from. From number and then message what is it?
NATHANIEL: Body. I think it's body.
JASON: And body will just be message? Do you need anything else?
NATHANIEL: Nope.
JASON: Okay. Let's try this. Moment of truth here. We I have to stop and restart to get those tokens to show up. So, because I added a.env, Netlify's smart enough to pick those up for us, so I can grab this and then I go into my Twilio account, phone numbers, Manage, active numbers, and I'm going to grab my IVR.
NATHANIEL: I can't wait for you to, like, do this with a CLI. You're going to find updated numbers so awesome with the CLI.
JASON: Okay. So here we're gonna save it. All right. Now, moment of truth, what should happen, assuming that we didn't typo anything, which is a 10,000foot if, I should be able to choose two types.
**Please choose from one of the following options. Press 1 for filled. Press 2 for iced. Press 3 for chocolate. That sounds delicious. Do you want to further refine your donut match, press 1 for iced, press 2 for filled.
NATHANIEL: Do it. Do it.
JASON: Come on.
**Your dream donut is a classic donut. HTTPS www.
NATHANIEL: We put the URL message in that.
JASON: Look at it, chat, I got my text message. Oh, it's beautiful. Okay. So, this is wonderful. So, we screwed up a couple of things. One is that we
**Aha, behold, my bucket! Holy buckets, did that just work?
JASON: What we need to do is take off the URL.
NATHANIEL: Instead add that to the body.
JASON: Put that down here. So, now we're including the message in the donut URL, but we won't say that in the out loud because that doesn't make any sense. So, this, I mean, this is sick. Like, I'm not gonna lie, we got further than I thought we would, given how this is pretty, like, aggressive stuff, right? So, I'm going to make sure that I remember to ignore this.env file. I'm gonna have to do a lot in here to make sure we're all set up to not, like, commit anything that we shouldn't be, but we're out of time, so let's do a quick round of shoutouts. First of all, we've had Jordan with us all day from White Coat Captioning doing live captioning.
NATHANIEL: Thank you, Jordan.
JASON: Thank you so much, Jordan, for hanging out with us. That is made possible by our sponsors, Netlify, Fauna, Auth0 and Hasura. Making this more accessible. It helps me out a lot. No way I could afford it on my own. Very much appreciated. We've got great stuff coming up. Shaudai teaching us functional React Native. The host while I go on vacation. Both going to be here doing some really interesting stuff. We're gonna learn Kotlin. Lots and lots of good stuff coming up. Make sure you do that. Nathaniel, where should someone go if they want to learn more about you and want to learn more about Twilio?
NATHANIEL: Want to learn more about me, find me online on Twitter @chatterboxcoder and Twitch @chatterboxcoder. If you want to find out more about Twilio, head over to Twitch. We put videos on YouTube. You can also go to Twilio.com and check out the awesome stuff we have there.
JASON: All right, y'all, on that note, and with the stampede to send us off, we're gonna call this episode a success. Nathaniel, thank you so, so much for hanging out.
NATHANIEL: Thanks for having me.
JASON: We're gonna go find somebody to raid. We will see you next time.
Learn With Jason is made possible by our sponsors: