├── README.md
└── sampleaudio.mp3
/README.md:
--------------------------------------------------------------------------------
1 | # Chloe's Fake Call Workshop
2 | ☎️ *A workshop to build your own fake boyfriend/boss/sibling/co-worker call with Azure & Twilio* ☎️
3 |
4 | 
5 |
6 | Today we will build a fake calling app using:
7 |
8 | + ⚡ [Azure Functions](https://azure.microsoft.com/en-us/services/functions/?WT.mc_id=github-workshop-chcondon)
9 | + ☎️ [Twilio](https://www.twilio.com/)
10 | + 🔘A [Flic button](http://flic.io/shop/flic-1pack?aff=10)
11 | + 📱Your cellphone
12 |
13 | If you don't own a Flic Button, [you can purchase one at a discounted rate here](http://flic.io/shop/flic-1pack?aff=10). If you're looking for a group purchase for a workshop, or are interested in custom logo buttons- [reach out directly](https://twitter.com/ChloeCondon) and I can help! 🙋♀️
14 |
15 | ⚠️ **YOU DO NOT NEED A FLIC BUTTON TO COMPLETE THIS WORKSHOP** ⚠️
16 | (However, it's [a lot more fun](https://www.youtube.com/watch?v=kAjrKYstfDM) with one! 🙃)
17 |
18 |
19 |
20 | Before we begin, if you're looking for a quick summary and overview on Azure Functions (or found this page early and would like to get a headstart), I recommend [starting here with our documentation](https://docs.microsoft.com/en-us/azure/azure-functions/?WT.mc_id=fakecallworkshop-github-chcondon), or taking 4 minutes to read in more detail [how to create your first Azure Function](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function/?WT.mc_id=fakecallworkshop-github-chcondon), so you have some context on how to use functions within Azure.
21 |
22 | You can learn more about the original project [in my blog post](https://dev.to/azure/an-ambivert-s-guide-to-azure-functions-27b8)!
23 |
24 | Happy coding, friends!
25 | -[Chloe 🎀](https://twitter.com/ChloeCondon)
26 |
27 | ## Let Us Begin!
28 | Today we will build a fake calling app using Azure Functions, Twilio, and a Flic button. We will start by creating a Function App in Azure. Then we will create a Twilio account, create 2 Azure Functions, and test it out on our phones.
29 |
30 | Here's a diagram of what we'll be doing:
31 |
32 | 
33 |
34 | ### Create an Azure Account!
35 | If you don't already have one, create an Azure account for free [here](https://azure.microsoft.com/en-us/free/?WT.mc_id=fakecallworkshop-github-chcondon)!
36 |
37 | I know what you may be thinking... "but Chloe- I'm a developer... this is much too bright for me!". Don't worry- there's a dark mode option. 😎
38 |
39 | 
40 |
41 | If you already have an Azure account, yay!
42 |
43 | ### Create an Azure Function Resource
44 | For the sake of easy to understand visuals/screenshots for this workshop, we'll be using the [Azure portal](https://azure.microsoft.com/en-us/free/?WT.mc_id=fakecallworkshop-github-chcondon) to create this. You can also use [VS Code](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code/?WT.mc_id=fakecallworkshop-github-chcondon), the [Azure CLI](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function-azure-cli/?WT.mc_id=fakecallworkshop-github-chcondon), etc. With Azure Functions you are given the the ability to code and test Functions locally on your machine without having to deploy to the cloud every single time you want to test (a huge time saver!).
45 |
46 | To create an Azure Function, you can just start from the Get Started menu and select Function App.
47 |
48 | 
49 |
50 | Then you’ll need to fill in some basic info about your function here. Including the app name, the Azure subscription you’d like to use, a [resource group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview?WT.mc_id=devto-blog-chcondon/?WT.mc_id=fakecallworkshop-github-chcondon) (create a new one in this case), the Operating System you’d like to use (please select **Windows** for this workshop), the [hosting plan](https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale/?WT.mc_id=fakecallworkshop-github-chcondon) (I’m using consumption), the location you’d like to use (I’m based in California, so West US is usually my default), the runtime stack I’d like to use (I’m using NodeJS in this case), and we have the option to create new [storage](https://docs.microsoft.com/en-us/azure/storage/common/storage-introduction/?WT.mc_id=fakecallworkshop-github-chcondon) or use existing. We'll create a new one in this case.
51 |
52 | 
53 |
54 | Once you have all these filled out, you can go ahead and deploy! Wait about a minute or two, then watch for the **Deployment succeeded** message.
55 |
56 | 🎊 Woo! If you followed those steps, we have our resource! Select **Go to resource** in your notifications (top right corner) to view your new Function App.
57 |
58 | ### Create Your First Azure Function
59 | Now we'll add our functions to our app, starting with a function to send a text message. Click the plus sign in the left-hand side navigation, or select **Add Function** towards the center/bottton of the screen.
60 |
61 | Select in-portal.
62 | 
63 |
64 | And select Webhook + API
65 | 
66 |
67 | It will take about a minute to deploy and then you’ll have a fresh new Azure Function waiting to be called.
68 |
69 | The default code is a simple hello world app. If you paste the function URL (located above your function under the link **> Get function URL**) into your browser’s address bar with the query string value &name= to the end of this URL and press the Enter key on your keyboard, you should be able to execute the request. You should see the response returned by the function displayed in the browser.
70 |
71 | **Try doing this once!** Add the URL with *&name=your-name-here* added to it, and test out that the function works in your browser.
72 |
73 | ### Let’s Create a Fake Boyfriend (or aunt, or cousin, or coworker- whatever!) with Twilio
74 | In a new tab, head over to [Twilio.com](https://www.twilio.com/) and sign up for an account if you don't have one already. Add a trial phone number to your account that has calling and SMS capabilitites (if you'd like to not work in trial mode- you can use code **CHLOE20** to upgrade your account at any point).
75 |
76 | Once you have a trial number, head back to the dashbaord. You'll see a **ACCOUNT SID** and **AUTH TOKEN** for your project. 🚨 Do not share/screenshot/commit these numbers 🚨 Think of them as your username and password for our Twilio number- we will securely store these in Azure shortly.
77 |
78 | ### Add Sample Code to our Function
79 |
80 | Navigate back to the Azure portal, and replace the exsiting code wiith the following code in your index.js file:
81 |
82 | ```
83 | const accountSid = process.env.TWILIO_SID;
84 | const authToken = process.env.TWILIO_TOKEN;
85 | const client = require('twilio')(accountSid, authToken);
86 |
87 | // This can also be accomplished with a Twilio output binding- you can read more on this at http://aka.ms/AA4n3j3
88 |
89 | module.exports = function (context) {
90 | client.messages
91 | .create({ from: process.env.SENDER_NUMBER,
92 | body: 'Woohoo- it worked!',
93 | to: process.env.RECIPIENT_NUMBER
94 | })
95 | .then(message => {
96 | context.log("Message sent");
97 | context.res = {
98 | // status: 200, /* Defaults to 200 */
99 | body: 'Text successfully sent'
100 | };
101 | context.done();
102 | }).catch(err => {
103 | context.log.error("Twilio Error: " + err.message + " -- " + err.code);
104 | context.res = {
105 | status: 500,
106 | body: `Twilio Error Message: ${err.message}\nTwilio Error code: ${err.code}`
107 | };
108 | context.done();
109 | });
110 | }
111 | ```
112 |
113 | This will be the code that is run when our function is called.
114 |
115 | **Take a moment to read and understand the code.** 🕵️♀️ You'll see that we're setting our accountSid & authToken (with credentials we have set in our function's Application Settings). We then have a function that creates a message sent from SENDER_NUMBER, to RECIPIENT_NUMBER (with credentials we have set in our function's Application Settings as well). Next, we're logging that our message is sent, and setting our context as done. Alternatively , if there's an error, we'll log it and set our context to done.
116 |
117 | Once you have an understanding of this code, click **Save**.
118 |
119 | ### Add package.json file to Function
120 |
121 | Add a package.json file to your function. You can do this by navigating to the top-right corner of your function, and adding a file as pictured below (⚠️ Can't find it? The 'View Files' tab is collapsed- scroll *alllllll* the way to the right of your screen):
122 |
123 | 
124 |
125 | Add the following code to your package.json file (adding your desired app name/description/etc):
126 |
127 | ```
128 | {
129 | "name": "your-app-name",
130 | "version": "1.0.0",
131 | "description": "Fake text/call functions",
132 | "main": "index.js",
133 | "scripts": {
134 | "test": "echo \"Error: no test specified\" && exit 1"
135 | },
136 | "author": "your-name",
137 | "license": "MIT",
138 | "dependencies": {
139 | "twilio": "^3.33.1"
140 | }
141 | }
142 | ```
143 |
144 | Click **Save**, and navigate back to your **index.js** file.
145 |
146 | ### Install the Twilio Node.js Module
147 |
148 | Install the Twilio Node helper library using npm. This will install the twilio module so that Node.js scripts in the current directory can use it. Access the Azure console at the bottom of the screen
149 |
150 | 
151 |
152 | In the console, enter the following:
153 |
154 | ```
155 | npm install twilio
156 | ```
157 |
158 | This may take a couple minutes (if you're looking for a good time to go grab a coffee/LaCroix/bathroom break- this is it! ☕️🍕🚽).
159 |
160 | You may see a warnings/notice here- don't worry, you can ignore this. This is notifying us a package-lock.json file has been created.
161 |
162 | ### Add Credential Values Securely in Azure
163 |
164 | Head over to **Configuration** under your Function App in the Azure portal (highlighted in pink, below- click on your Function App Name on the left-hand side).
165 |
166 | 
167 |
168 | Add 2 new application settings named **TWILIO_SID** and **TWILIO_TOKEN**- storing with them the credentials provided to us from Twilio.
169 |
170 | Additionally, add a setting for **SENDER_NUMBER** (adding your Twilio trial number in the format of plus-sign, country code, and number like so as the value: *[+19168675309](https://www.youtube.com/watch?v=6WTdTwcmxyo)*) as well as **RECIPIENT_NUMBER** (add your cell phone number in the same format of *[+19168675309](https://www.youtube.com/watch?v=6WTdTwcmxyo)* as the value for now to test our app).
171 |
172 | 
173 |
174 | 😳😭 Totally lost? Can't find your credentials? ☎️ Log into [Twilio](https://www.twilio.com/) to find them!
175 |
176 | Click **Save**, and navigate back to your function in the console.
177 |
178 | ### Test Your First Azure Function
179 |
180 | Click the **Run** button at the top of your function. Your logs should pop up and show that your function has been called. **This may take a couple minutes on your 1st try, so stay patient!** If all goes smoothly, you should receive a text saying "Woohoo- it worked!". You can also run and test this function by copying and pasting the function URL (located in the **> Get function URL** link above your function) in your browser.
181 |
182 | 📝 NOTE: If you are still using a trial account, texts and calls from Twilio will have a *Sent from your Twilio trial account* message before it. If you'd like to remove this, consider upgrading and adding code **CHLOE20** for some credits.
183 |
184 | 🎊 Great job! 🎊 You made your first Azure function using Twilio to send a text! Feel free to switch the **RECIPIENT_NUMBER** value if you'd prefer to have the app alert a friend (vs. send a message to yourself). Of course, if you're testing- it's easiest to keep your own number for now. Here's [a funny story about that](https://twitter.com/ChloeCondon/status/1105613535487225857). 🙈
185 |
186 | ### Create Your Second Azure Function
187 |
188 | 
189 |
190 | Now we'll add our 2nd function to our app- this time, with the code to send a call (vs. a text).
191 |
192 | Add another function to your app (as we did before on our 1st function- click the plus sign in the left-hand side navigation), and select **HTTPTrigger** again.
193 |
194 | ### Add Sample Code to our Function
195 |
196 | In the Azure portal, replace the exsiting code with the following code in your index.js file:
197 |
198 | ```
199 | const accountSid = process.env.TWILIO_SID;
200 | const authToken = process.env.TWILIO_TOKEN;
201 | const client = require('twilio')(accountSid, authToken);
202 |
203 | module.exports = function (context) {
204 | client.calls
205 | .create({
206 | url: process.env.TWIML_URL,
207 | to: process.env.RECIPIENT_NUMBER,
208 | from: process.env.SENDER_NUMBER,
209 | })
210 | .then(call => {
211 | context.log("Call sent");
212 | context.res = {
213 | // status: 200, /* Defaults to 200 */
214 | body: 'Call successfully sent'
215 | };
216 | context.done();
217 | }).catch(err => {
218 | context.log.error("Twilio Error: " + err.message + " -- " + err.code);
219 | context.res = {
220 | status: 500,
221 | body: `Twilio Error Message: ${err.message}\nTwilio Error code: ${err.code}`
222 | };
223 | context.done();
224 | });
225 | }
226 | ```
227 | This will be the code that is run when our call function is called.
228 |
229 | **Take a moment to read and understand the code for your call function.** You'll see that we're again setting our accountSid & authToken (with credentials we have set in our function's Application Settings). We then have a function that creates a call sent from **SENDER_NUMBER**, to **RECIPIENT_NUMBER**, with a url of **TWIML_URL** (this will be set-up with credentials we have set in our function's Application Settings as well). Next, we're logging that our call is sent, and setting our context as done. Alternatively , if there's an error, we'll log it and set our context to done.
230 |
231 | Click **Save**.
232 |
233 | ### Add package.json file to Function
234 |
235 | Add a package.json file to your function (as we did before on our 1st function).
236 |
237 | Add the following code to your package.json file:
238 |
239 | ```
240 | {
241 | "name": "your-app-name",
242 | "version": "1.0.0",
243 | "description": "Fake text/call functions",
244 | "main": "index.js",
245 | "scripts": {
246 | "test": "echo \"Error: no test specified\" && exit 1"
247 | },
248 | "author": "your-name",
249 | "license": "MIT",
250 | "dependencies": {
251 | "twilio": "^3.33.1"
252 | }
253 | }
254 | ```
255 |
256 | Click Save, and navigate back to your index.js file.
257 |
258 | ### Install the Twilio Node.js Module
259 |
260 | Once again, we'll install the Twilio Node helper library using npm. This will install the twilio module so that Node.js scripts in the current directory can use it. Access the Azure console at the bottom of the screen.
261 |
262 | In the console, enter the following:
263 |
264 | ```
265 | npm install twilio
266 | ```
267 |
268 | Again, this may take a couple minutes (if you're looking for a good time to go grab *another* coffee/LaCroix/bathroom break- this is it! ☕️🍕🚽).
269 |
270 | You may see a warnings/notice here- don't worry, you can ignore this. This is notifying us a package-lock.json file has been created.
271 |
272 | Our configurations are already set in Azure, so no need to add our **TWILIO_SID**, **TWILIO_TOKEN**, **SENDER_NUMBER**, or **RECIPIENT_NUMBER** again.
273 |
274 | ### Create Twilio Asset
275 |
276 | Now we'll create a Twilio Asset to hold our fake call's recorded voice message.
277 |
278 | Download the following MP3 by [clicking here](https://github.com/ChloeCodesThings/FakeCallWorkshop/raw/master/sampleaudio.mp3). Alternatively, you can record [your own MP3 here](https://online-voice-recorder.com/) (or, use whatever MP3 you'd like!)
279 |
280 | Head back to Twilio, and navigate to the **...*** section of the left-side navigation. Select Runtime > Assets.
281 |
282 | 
283 |
284 | Add or drag/drop the Mp3 file, and copy the path of the URL.
285 |
286 | ### Create a TwiML Bin
287 |
288 | Navigate to Runtime > TwiML Bins in the left-side navigation.
289 |
290 | We'll now create a TwiML Bin. TwiML Bins allow you to write TwiML that Twilio will host for you - so you can quickly prototype a solution without spinning up a web server.
291 |
292 | Add the following to your TwiML bin- **make sure to replace **URL-OF-YOUR-TWILIO-ASSET** with the url of the Twilio Asset you just created!** This will play our MP3 when a call is made to the **RECIPIENT_NUMBER**:
293 |
294 | ```
295 |
296 |
297 |
298 | Hey- congrats! Everything is working. You are awesome. You did it- yay!
299 | URL-OF-YOUR-TWILIO-ASSET
300 |
301 | ```
302 |
303 | This TwiML will speak the text, and the URL of the Twilio Asset URL you provide it.
304 |
305 | 
306 |
307 | Save your TwiML bin, and **copy the URL**.
308 |
309 | ### Add TwiML URL to Application Settings
310 |
311 | Navigate to **Configuration** once again to add **TWIML_URL** with the value of your recently created/copied TwiML URL to your **Application Settings**.
312 |
313 | 
314 |
315 | Click **Save**.
316 |
317 | ### Test call
318 |
319 | Navigate to your call function and click **Run** to test the call.
320 |
321 | *This can sometimes take a minute or two, so be patient- and only click run once (otherwise, you may get multiple calls back to back)!*
322 |
323 | 📝 NOTE: If you are still using a trial account, texts and calls from Twilio will have a *Sent from your Twilio trial account* message before it (with calls, you'll need to press any number to run your code). If you'd like to remove this, consider upgrading and adding code **CHLOE20** for some credits.
324 |
325 | 🎊 YOU DID IT!!! 🎊 You made your second Azure function using Twilio to send a call! Feel free to play and switch the **RECIPIENT_NUMBER** value as you wish. Again, I'll reiterate: if you're testing- it's easiest to keep your own number for now. Here's [a funny story about that](https://twitter.com/ChloeCondon/status/1105613535487225857). 🙈
326 |
327 | If all goes well, you'll soon get a call and will be a victim of Rick-Rolling! 😁☎️
328 |
329 | 
330 |
331 | Feel free to play around with the **TWIML_URL** and add/remove your own MP3 Assests within Twilio. Your call can be whatever you'd like it to be! Your mom, dad, cousin, aunt, uncle, sister, brother, co-worker, boss, Rupaul, Justin Trudeau, Barack Obama, or Beyonce-- your choice! Get creative and experiment with your fake call- **if we have time, we'll share it with the group.**
332 |
333 | ### Add URL to Flic Button
334 |
335 | The next steps of this workshop require a Flic Button. If you don't own a Flic Button, [you can purchase one at a discounted rate here](http://flic.io/shop/flic-1pack?aff=10). If you're looking for a group purchase for a workshop, or are interested in custom logo buttons- [reach out directly](https://twitter.com/ChloeCondon) and I can help! 🙋♀️
336 |
337 | For our final step, we'll need to add our Azure Function URLs to the Flic Button app! Download the Flic Button app to your phone on [Google Play](https://play.google.com/store/apps/details?id=io.flic.app&hl=en_US) or [Apple](https://apps.apple.com/us/app/flic-app/id977593793).
338 |
339 | Create an account, and login. Add a button to your phone by clicking the plus sign.
340 |
341 | 
342 |
343 | Click your Flic buttton to add it to your phone (**Note: in a workshop setting, this may be tricky with so many buttons! Make sure you get matched to the correct buttton**)
344 |
345 | 
346 |
347 | Name your Flic button a unique name, and click **Done**.
348 |
349 | 
350 |
351 | Now we'll program our Flic button to send a text when clicked once. Select **Click >**.
352 |
353 | 
354 |
355 | And navigate to **Tools**
356 |
357 | 
358 |
359 | Select **Internet Request** (circled in pink below):
360 |
361 | 
362 |
363 | Now, add the URL of our 1st function (the message/texting function) here. Select **GET** request. You do not need to provide Headers or change anything else here. **Save Action** to continue.
364 |
365 | Once saved, test that your function works with 1 click! You should recieve a text shortly.
366 |
367 | Do the same steps for the **Double Click >** option, navigate to Tools > Internet Request URL and add your call function URL as a GET request.
368 |
369 | Save again, and test that your function works with a double-click! You should recieve a call shortly (don't click the button too many times- be patient!).
370 |
371 | ### Add Contact to Phone
372 |
373 | Now for the cherry-on-top finishing touch! 🍒🍦
374 |
375 | 
376 |
377 | Add a contact to your phone for your Twilio number, and name it whatever you'd like. For example, if you'd like to trigger a fake call from "your BFF" you could upload a picture of The Rock to your contacts, and label it "The Rock". [Here's an example of mine](https://www.youtube.com/watch?v=lCpO16JjoM8) (I used "💕My Boyfriend💕" as the contact with an image of my boo):
378 |
379 | 
380 |
381 | If you've made it this far- CONGRATS! 🎊 You have successfully created 2 Azure Functions, connected them with Twilio, and are now able to trigger them from a Flic Button!
382 |
383 | Here's a diagram you can print and hang on your fridge to remember this moment forever and ever (also, so you can review what we've just accomplished 😉):
384 |
385 | 
386 |
387 | 
388 |
389 | If you're interested in learning more about Azure Functions and want to continue learning, here are some great resources to get started:
390 |
391 | + [Create your first function using Visual Studio Code](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code/?WT.mc_id=github-workshop-chcondon)
392 |
393 | + [Create a function in Azure that is triggered by a timer](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-scheduled-function/?WT.mc_id=github-workshop-chcondon)
394 |
395 | + [Create a function triggered by Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-cosmos-db-triggered-function/?WT.mc_id=github-workshop-chcondon)
396 |
397 | + [Create a function triggered by Azure Blob storage](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-storage-blob-triggered-function/?WT.mc_id=github-workshop-chcondon)
398 |
399 | + [Create a function triggered by Azure Queue storage](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-storage-queue-triggered-function/?WT.mc_id=github-workshop-chcondon)
400 |
401 | + [Azure Functions developer reference](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference/?WT.mc_id=github-workshop-chcondon) (provides more technical information about the Azure Functions runtime and a reference for coding functions and defining triggers and bindings)
402 |
403 | + [Testing Azure Functions](https://docs.microsoft.com/en-us/azure/azure-functions/functions-test-a-function/?WT.mc_id=github-workshop-chcondon)
404 |
405 | + [Azure Functions scale and hosting](https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale/?WT.mc_id=github-workshop-chcondon)
406 |
407 | + [Learn more about Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/overview/?WT.mc_id=github-workshop-chcondon)
408 |
--------------------------------------------------------------------------------
/sampleaudio.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChloeCodesThings/FakeCallWorkshop/61a0ff9ce25195f6762a854f65bffb6e3e9f4791/sampleaudio.mp3
--------------------------------------------------------------------------------