mario-mitchell / starting-serverless

0 stars 0 forks source link

A Song 4 U #13

Open ghost opened 3 years ago

ghost commented 3 years ago

Week 2 Step 6 ⬤⬤⬤⬤⬤⬤◯◯ | 🕐 Estimated completion: 10-15 minutes

Pose! Song Recommendation with Age Recognition

✅ Task:

Create a new Azure Function that parses a Twilio request body and returns the image url.

🚧 Test Your Work

To test your work, try texting a jpg image to your Twilio number. You should receive a link back that contains the image.

:question: How do I find my Twilio number? See your [phone numbers](https://www.twilio.com/console/phone-numbers/incoming).

1. Creating a Twilio Account

In this project, the user will text an image to a Twilio number and an Azure function will analyze the image. The Face API will determine the age of the person in the image. We need to create a Twilio account first so that the user can text an image to your Twilio number.

Sign up for a free Twilio trial account here.

:question: What's the process like for signing up for Twilio? - When you sign up, you'll be asked to verify your personal phone number. This helps Twilio verify your identity and also allows you to send test messages to your phone from your Twilio account while in trial mode. - Once you verify your number, you'll be asked a series of questions to customize your experience. - Once you finish the onboarding flow, you'll arrive at your project dashboard in the Twilio Console. This is where you'll be able to access your Account SID, authentication token, find a Twilio phone number, and more. Learn more about it [here](https://www.twilio.com/docs/usage/tutorials/how-to-use-your-free-trial-account)!

After we get our account set up, we need to get a phone number, which is free from your trial account.

:question: Where can I get a phone number? 1. [Create a new project](https://support.twilio.com/hc/en-us/articles/360011177133-View-and-Create-New-Projects-in-Twilio-Console) on Twilio. 2. [Add a brand new number](https://www.twilio.com/docs/usage/tutorials/how-to-use-your-free-trial-account#get-your-first-twilio-phone-number) for your Twilio project, which will be used to send texts to users. Save this to use for later.

Before you move on, be sure to create a new Azure function!

2. Configuring the Azure Function

Our new Azure function will act as a Twilio webhook.

:bulb: A Twilio webhook is the endpoint that will receive a POST request whenever a Twilio number is used or a text is sent. Twilio sends an HTTP request to a webhook whenever something happens (such as when a text is sent).

You will need to place your function's URL into the settings on your Twilio account.

image

Do you like the command line more? Try using the Twilio CLI instead!

❓ How do I configure it?
1. Go to the [Twilio Console's Numbers page](https://www.twilio.com/console/phone-numbers/incoming) ![image](https://user-images.githubusercontent.com/49426183/120208171-06748000-c1e2-11eb-91a7-06c427967d46.png) 2. Click on the phone number you'd like to modify 3. Scroll down to the Messaging section and the "A MESSAGE COMES IN" option. 4. Paste in your Azure Function URL. Make sure to click `Save` afterwards!! ![image](https://user-images.githubusercontent.com/49426183/120208692-a0d4c380-c1e2-11eb-85fa-ed8463d1da43.png)

3. Coding the Azure Function

Test the webhook out!

If you want more insight into how a webhook actually works, try this:

:exclamation: Log the request body in your console using `context.log(req.body)` and text your Twilio number. Using this code: ```js module.exports = async function (context, req) { var reqbody = req.body context.log(reqbody) context.res = { // status: 200, /* Defaults to 200 */ body: reqbody }; } ``` You might get something like this: ``` ToCountry=US&MediaContentType0=image%2Fjpeg&ToState=MI&SmsMessageSid=MM0fe83458b74a1f626eb0da4685ab28b5&NumMedia=1...... ```

In order to parse the parameters from those values you just saw, we need an npm package.

:package: Install querystring
We need to install the npm package `querystring`. This package parses **query strings**, and we will use it to parse the SMS sent by the user to the Twilio number so we can access the image sent in the text. > :bulb: You only need to use `npm init -y` if you are installing npm packages for the first time on an Function App! As we did when we installed `parse-multipart`, we need to enter `npm init -y` (which initializes the package.json files) before we can install `querystring`:

Screen Shot 2021-05-30 at 7 11 28 PM Now we can install `querystring` by entering `npm install querystring`:

Screen Shot 2021-05-30 at 8 23 18 PM

:exclamation: The parameter value you want to parse with querystring and return from the Azure Function in the body is called MediaUrl0.

Now, to use querystring, first don't forget to initialize it!

const querystring = require('querystring');

Then, let's parse the request body, which is held in req.body.

const queryObject = querystring.parse(req.body);

From this outputted object, we'll find its MediaUrl0 attribute and return it.

:question: How do I return the output? ```js context.res = { body: queryObject.MediaUrl0 }; ```
ghost commented 3 years ago

Week 2 Step 7 ⬤⬤⬤⬤⬤⬤⬤◯ | 🕐 Estimated completion: 15-25 minutes

How old are you??

✅ Task:

Modify your Azure Function so that it determines the user's generation.

Generation Range
GenZ 5 ≤ age ≤ 25
GenY 26 ≤ age ≤ 41
GenX 42 ≤ age ≤ 57
BabyBoomers 58 ≤ age ≤ 76
Unknown Any other age

🚧 Test Your Work

To test your work, try texting a jpg image to your Twilio number (with a face!). After you text the image, you can context.log(age) or context.log(generation) to verify that your program and the FaceAPI is working!

We use context.log and not console.log, because Azure uses the context object in Functions.

❗ Twilio does not allow a simple string to be sent. For example, the following code will NOT send a text back, but will still pass the bot's test, and allow you to move on to the next step.

context.res = {
        body: generation
    };
// THIS CODE WILL NOT RETURN ANYTHING BY TWILIO, but will work on Github!

Downloading image data

Based on the previous step, you should now be able to access your image url. We were able to access it with queryObject.MediaUrl0.

:question: How do I download the image?
Perform a quick GET request with fetch. > :bulb: Remember that you need to initialize variables for your packages! ```js let resp = await fetch(YOUR_URL,{ /*The await expression causes async function execution to pause until a Promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled Promise*/ method: 'GET', }) // receive the response let data = await resp.arrayBuffer() // we are receiving it as a Buffer since this is binary data ```

Analyzing the image

Recall the analyzeImage() function we wrote in the previous project. This time, you will be calling for age data instead of emotion data.

:bulb: Don't forget to read the documentation!

❓ What's the syntax again?
:goal: Retrieve age data from the Face API. ```js async function analyzeImage(img){ const subscriptionKey = process.env['subscriptionkey']; const uriBase = // WHAT'S YOUR ENDPOINT?; // env variables (similar to .gitignore/.env file) to not expose personal info let params = new URLSearchParams({ 'returnFaceId': 'true', 'returnFaceAttributes': //WHAT GOES HERE? }) // making the post request let resp = await fetch(uriBase + '?' + params.toString(),{ method: 'POST', body: img, // img is the parameter inputted headers: { 'Content-Type' : 'application/octet-stream', // HOW DO YOU AUTHENTICATE? } }) // receive the response let data = await resp.json(); return data; } ``` However, this code won't work. Fill in the code where needed **using your previous project and the documentation**.
❓ How do I get an age from my analysis function?
Like you've done before, **call the `analyzeImage()` function with your image you downloaded.** > :bulb: Tip: Always `context.log()` your output so it's easier to determine how to access object attributes. The function returns face data formatted in JSON. We can determine the age like so: ```js let age = result[0].faceAttributes.age ``` This retrieves the **first face**, the `faceAttributes` attribute, and the `age` attribute from the previous object.

Determining and returning Generation

Using the provided names and age ranges, you can use if else logic in Javascript to determine the generation.

:exclamation: Example please!
```js if (age >= 5 && age <= 25) { id = "GenZ" } ``` `id` is the variable we will return as the final generation. `&&` means "and". The age needs to be greater than/equal to 5 AND less than/equal to 20 for the `id = "GenZ` to run.

Remember, Twilio will not allow a simple text like GenZ to go through, so all you have to do is return the generation in the body! We will return more data in the next steps, so you will be able to get a text back.