├── -
├── .bit
├── .config
├── .info
├── config.yml
├── course-details.md
├── responses
│ ├── 1-complete.md
│ ├── 1.1-Week 1 Step 1.md
│ ├── 1.2-Week 1 Step 2.md
│ ├── 1.3-Week 1 Step 3.md
│ ├── 1.4-Week 1 Step 4.md
│ ├── 1.5-Week 1 Step 5.md
│ ├── 1.6-Week 1 Step 6.md
│ ├── 1.7-Week 1 Step 7.md
│ ├── 1.8-Week 1 Step 8.md
│ ├── 1.9-Week 1 Step 9.md
│ ├── 2-complete.md
│ ├── 2.1-Week 2 Step 1.md
│ ├── 2.2-Week 2 Step 2.md
│ ├── 2.3-Week 2 Step 3.md
│ ├── 2.4-Week 2 Step 4.md
│ ├── 2.5-Week 2 Step 5.md
│ ├── 2.6-Week 2 Step 6.md
│ ├── 2.7-Week 2 Step 7.md
│ ├── 2.8-Week 2 Step 8.md
│ ├── 2.9-Week 2 Step 9.md
│ ├── 3-complete.md
│ ├── 3.1-Week 3 Step 1.md
│ ├── 3.2-Week 3 Step 2.md
│ ├── 3.3-Week 3 Step 3.md
│ ├── 3.4-Week 3 Step 4.md
│ ├── 3.5-Week 3 Step 5.md
│ ├── 3.6-Week 3 Step 6.md
│ ├── 3.7-Week 3 Step 7.md
│ ├── 3.8-Week 3 Step 8.md
│ ├── 3.9-Week 3 Step 9.md
│ ├── 4-complete.md
│ ├── 4.1-Week 4 Step 1.md
│ ├── 4.2-Week 4 Step 2.md
│ ├── 4.3-Week 4 Step 3.md
│ ├── 4.4-Week 4 Step 4.md
│ ├── 4.5-Week 4 Step 5.md
│ ├── 4.6-Week 4 Step 6.md
│ ├── 4.7-Week 4 Step 7.md
│ ├── 4.8-Week 4 Step 8.md
│ ├── 5.1-Week 5 Step 1.md
│ ├── 5.2-Week 5 Step 2.md
│ ├── 5.3-Week 5 Step 3.md
│ ├── 5.4-Week 5 Step 4.md
│ ├── 5.5-Week 5 Step 5.md
│ ├── 5.6-Week 5 Step 6.md
│ ├── 5.7-Week 5 Step 7.md
│ ├── bunnimage.md
│ ├── feedback.md
│ ├── finalproject.md
│ ├── getting-emotional.md
│ ├── hackervoice.md
│ ├── hello.md
│ ├── mergepr.md
│ └── twocatz.md
├── scripts
│ ├── commit.sh
│ ├── create.py
│ ├── getProgress.js
│ ├── parse.py
│ └── start.py
├── step-template.md
├── tests
│ ├── cypress.json
│ ├── cypress
│ │ ├── fixtures
│ │ │ └── testimage.jpg
│ │ ├── integration
│ │ │ ├── 4.1.spec.js
│ │ │ ├── 4.2.spec.js
│ │ │ ├── 4.3.spec.js
│ │ │ ├── 4.4.spec.js
│ │ │ ├── 4.5.spec.js
│ │ │ ├── 4.7.spec.js
│ │ │ └── cypress.json
│ │ ├── screenshots
│ │ │ └── 4.1.spec.js
│ │ │ │ └── Testing Bunnimage -- Testing Week 4 Step 1 (failed).png
│ │ └── videos
│ │ │ └── 4.1.spec.js.mp4
│ ├── functions.js
│ ├── sample-solutions
│ │ ├── week1
│ │ │ ├── 1-2.helloworld.js
│ │ │ ├── 1.1-blog.md
│ │ │ ├── 1.4-hackervoice.js
│ │ │ ├── 1.5-hackervoice.js
│ │ │ ├── 1.6-twocatz.js
│ │ │ ├── 1.7-twocatz.js
│ │ │ └── 1.8-morse-code.js
│ │ ├── week2
│ │ │ ├── 2.2-emotional.js
│ │ │ ├── 2.3-emotional.js
│ │ │ ├── 2.4-emotional.js
│ │ │ ├── 2.5-emotional.js
│ │ │ ├── 2.6-songrec.js
│ │ │ ├── 2.7-songrec.js
│ │ │ └── 2.8-songrec.js
│ │ ├── week3
│ │ │ ├── 3.2-bunnimage.js
│ │ │ ├── 3.3-bunnimage.js
│ │ │ ├── 3.4-bunnimage.js
│ │ │ ├── 3.5-bunnimage.js
│ │ │ ├── 3.6-deepsecrets.js
│ │ │ ├── 3.7-deepsecrets.js
│ │ │ ├── 3.8-deepsecrets.js
│ │ │ └── deepsecrets.js
│ │ └── week4
│ │ │ ├── 4.1-bunnimage
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ │ ├── 4.2-bunnimage
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ │ ├── 4.3-bunnimage
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ │ ├── 4.4-bunnimage
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ │ ├── 4.5-twocatz
│ │ │ ├── cat.jpg
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ │ ├── 4.6-twocatz
│ │ │ └── twocatz.js
│ │ │ └── 4.7-twocatz
│ │ │ ├── cat.jpg
│ │ │ ├── index.html
│ │ │ └── script.js
│ ├── spec.js
│ ├── test.1.2.js
│ ├── test.1.4.js
│ ├── test.1.5.js
│ ├── test.1.6.js
│ ├── test.1.7.js
│ ├── test.1.8.js
│ ├── test.2.2.js
│ ├── test.2.3.js
│ ├── test.2.4.js
│ ├── test.2.5.js
│ ├── test.2.6.js
│ ├── test.2.7.js
│ ├── test.2.8.js
│ ├── test.3.1.js
│ ├── test.3.2.js
│ ├── test.3.3.js
│ ├── test.3.5.js
│ ├── test.3.6.js
│ ├── test.3.7.js
│ ├── test.3.8.js
│ ├── test.4.6.js
│ ├── testimage.jpg
│ └── wrongbranch.js
└── workflows
│ ├── bunnimage-frontend.yml
│ ├── bunnimage.yml
│ ├── deepsecrets.yml
│ ├── emotionalgifs.yml
│ ├── hackervoice.yml
│ ├── hello.yml
│ ├── morse.yml
│ ├── song4u.yml
│ ├── twocatz-frontend.yml
│ ├── twocatz.yml
│ └── week5.yml
├── .funcignore
├── .github
├── ISSUE_TEMPLATE
│ ├── ---start-course.md
│ ├── content-bug.md
│ ├── feature-request.md
│ ├── final-project.md
│ └── test-bug.md
├── PULL_REQUEST_TEMPLATE.md
├── stale.yml
└── workflows
│ └── main.yml
├── .gitignore
├── .vscode
└── extensions.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── GETTING_STARTED.md
├── LICENSE
├── README.md
├── blog.md
├── bunnimage
└── index.html
├── checkup.sh
├── cypress.json
├── cypress
├── fixtures
│ └── testimage.jpg
└── integration
│ ├── 4.1.spec.js
│ ├── 4.2.spec.js
│ ├── 4.3.spec.js
│ ├── 4.4.spec.js
│ ├── 4.5.spec.js
│ ├── 4.7.spec.js
│ └── cypress.json
├── host.json
├── package-lock.json
├── package.json
├── project
├── tech.md
└── timeline.md
├── proxies.json
└── setup.sh
/-:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitprj/Intro-To-Serverless/7fd8024b8d259eb4772785db540bc0e01f34c3c1/-
--------------------------------------------------------------------------------
/.bit/.config:
--------------------------------------------------------------------------------
1 | {'1.1-Week 1 Step 1.md': ['GitHub', '✅ Task:', ['blog.md'], 'PRmerge', 'n/a'], '1.2-Week 1 Step 2.md': ['Say "Hello" to VSCode', '✅ Task:', ['n/a'], 'checks', 'test.1.2.js'], '1.3-Week 1 Step 3.md': ['Getting Cat Pics with Postman 🐱', '✅ Task:', ['n/a'], 'IssueComment', 'n/a'], '1.4-Week 1 Step 4.md': ['Building our first function ⚡[HackerVoice]', 'Building our first function ⚡[HackerVoice]', ['n/a'], 'checks', 'test.1.4.js'], '1.5-Week 1 Step 5.md': ['Let me in!', '✅ Tasks:', ['n/a'], 'checks', 'test.1.5.js'], '1.6-Week 1 Step 6.md': ['Trying to make node-fetch happen', '✅ Task:', ['n/a'], 'checks', 'test.1.6.js'], '1.7-Week 1 Step 7.md': ['Name your Cat', '✅ Task:', ['n/a'], 'checks', 'test.1.7.js'], '1.8-Week 1 Step 8.md': ['[TOP SECRET] Morse Code Converter', '✅ Tasks:', ['n/a'], 'checks', 'test.1.8.js'], '1.9-Week 1 Step 9.md': ['📝 Week 1 Livestream Feedback', '📝 Week 1 Livestream Feedback', ['n/a'], 'feedback', 'n/a'], '2.1-Week 2 Step 1.md': ['Getting Emotional ~ With the Face API', '✅ Task:', ['n/a'], 'IssueComment', 'n/a'], '2.2-Week 2 Step 2.md': ['Getting Emotional ~ With Parse-Multipart', '✅ Task:', ['n/a'], 'checks', 'test.2.2.js'], '2.3-Week 2 Step 3.md': ['Getting Emotional ~ With the Face API', '✅ Task:', ['n/a'], 'checks', 'test.2.3.js'], '2.4-Week 2 Step 4.md': ['Getting Emotional ~ Returning the Dominant Emotion', '✅ Task:', ['n/a'], 'checks', 'test.2.4.js'], '2.5-Week 2 Step 5.md': ['Getting Emotional ~ Calling the Giphy API', '✅ Task:', ['n/a'], 'checks', 'test.2.5.js'], '2.6-Week 2 Step 6.md': ['Pose! Send a Pic to Functions', 'Checkpoint 2', ['n/a'], 'checks', 'test.2.6.js'], '2.7-Week 2 Step 7.md': ['How old are you??', 'Setting up the Twilio API', ['n/a'], 'checks', 'test.2.7.js'], '2.8-Week 2 Step 8.md': ['Hit me baby, one more time!', 'Connecting Locally to the Twillio API', ['n/a'], 'IssueComment', 'n/a'], '2.9-Week 2 Step 9.md': ['📝 Week 2 Livestream Feedback', '📝 Week 2 Livestream Feedback', ['n/a'], 'feedback', 'n/a'], '3.1-Week 3 Step 1.md': ['Week 3 Step 1', 'Learning Objectives', ['n/a'], 'IssueComment', 'n/a'], '3.2-Week 3 Step 2.md': ['Week 3 Step 2', 'Calling the Giphy API', ['index.js'], 'PRmerge', 'n/a'], '3.3-Week 3 Step 3.md': ['Week 3 Step 3', 'Sending the GIF', ['index.js'], 'PRmerge', 'n/a'], '3.4-Week 3 Step 4.md': ['Week 3 Step 4', 'Learning Objectives', ['n/a'], 'IssueComment', 'n/a'], '3.5-Week 3 Step 5.md': ['Week 3 Step 5', 'Setting Up Configuration', ['js/databaseContext.js'], 'checks', 'test.databaseContext.js'], '3.6-Week 3 Step 6.md': ['Week 3 Step 6', 'Modifying your Azure Function', ['n/a'], 'IssueComment', 'n/a'], '3.7-Week 3 Step 7.md': ['Week 3 Step 7', '📝 Week 3 Livestream Feedback', ['n/a'], 'feedback', 'n/a'], '4.1-Week 4 Step 1.md': ['Week 4 Step 1', 'Submitting Final Project Proposals', ['n/a'], 'IssueComment', 'n/a'], '4.2-Week 4 Step 2.md': ['Week 4 Step 2', 'Submitting an MVP', [''], '', ''], '4.3-Week 4 Step 3.md': ['Week 4 Step 3', 'Submitting the Final Project', [''], '', ''], '4.4-Week 4 Step 4.md': ['Week 4 Step 4', 'The Lightning Talk', [''], '', '']}
--------------------------------------------------------------------------------
/.bit/.info:
--------------------------------------------------------------------------------
1 | {'responses': ['1.1-Week 1 Step 1.md', '1.2-Week 1 Step 2.md', '1.3-Week 1 Step 3.md', '1.4-Week 1 Step 4.md', '1.5-Week 1 Step 5.md', '1.6-Week 1 Step 6.md', '1.7-Week 1 Step 7.md', '1.8-Week 1 Step 8.md', '1.9-Week 1 Step 9.md', '2.1-Week 2 Step 1.md', '2.2-Week 2 Step 2.md', '2.3-Week 2 Step 3.md', '2.4-Week 2 Step 4.md', '2.5-Week 2 Step 5.md', '2.6-Week 2 Step 6.md', '2.7-Week 2 Step 7.md', '2.8-Week 2 Step 8.md', '2.9-Week 2 Step 9.md', '3.1-Week 3 Step 1.md', '3.2-Week 3 Step 2.md', '3.3-Week 3 Step 3.md', '3.4-Week 3 Step 4.md', '3.5-Week 3 Step 5.md', '3.6-Week 3 Step 6.md', '3.7-Week 3 Step 7.md', '4.1-Week 4 Step 1.md', '4.2-Week 4 Step 2.md', '4.3-Week 4 Step 3.md', '4.4-Week 4 Step 4.md'], 'weeks': ['1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4']}
--------------------------------------------------------------------------------
/.bit/course-details.md:
--------------------------------------------------------------------------------
1 | # Sample Learning Lab
2 |
3 | *Course description: Place your course description here...*
4 |
5 | ## **Week 1**
6 | **Learning Objectives**
7 | -
8 |
9 | ## **Week 2**
10 | **Learning Objectives**
11 | -
12 |
13 | ## **Week 3**
14 | **Learning Objectives**
15 | -
16 |
--------------------------------------------------------------------------------
/.bit/responses/1-complete.md:
--------------------------------------------------------------------------------
1 | That's it for Week 1, move on to Week 2 in your new issue!
--------------------------------------------------------------------------------
/.bit/responses/1.5-Week 1 Step 5.md:
--------------------------------------------------------------------------------
1 | ---
2 | files: n/a
3 | stepType: checks
4 | scripts: test.1.5.js
5 | week: 1
6 | step: 5
7 | name: Week 1 Step 5
8 | ---
9 | Week 1 Step 5 ⬤⬤⬤⬤⬤◯◯◯◯ | 🕐 Estimated completion: 25-35 minutes
10 |
11 | # Let me in!
12 |
13 | ## ✅ Tasks:
14 | - [ ] Run `git pull origin [BRANCH_NAME]`
15 | - [ ] ***1:*** Add on to the HTTP Trigger in the previous issue to check if the user’s parameter input of “password” equals `letmein`.
16 | - If it does, output "Access granted."
17 | - If it doesn’t equal the correct password, output “Access denied.”
18 | - [ ] ***2:*** Commit the update function's code in a file named `hackervoice/index.js` to the root of the `hackervoice` branch!
19 | - [ ] ***3:*** Create a pull request to merges `hackervoice` to `main`, but do not merge unless the bot approves your changes.
20 |
21 | ## 🚧 Test your Work
22 | When you paste your **Function URL** in your browser or make a GET request with **Postman** with a `password` parameter of "letmein", you should get a response of “Access granted.“. Otherwise, your function should output “Access denied.“.
23 |
24 | ‼️ Make sure you follow the *exact* responses we provided. `Access denied.` and `Access granted.`
25 |
26 | ## 1: Return from a Function
27 |
28 | In the previous step, we received the password (the user's input). Now, we need to return either `Access denied.` or `Access granted.` to the user based on their input. **We can do this by returning it in the body of the request!**
29 |
30 | >💡 Recall the `context.res` object we saw in the HTTP Trigger template.
31 |
32 | ```js
33 | context.res = {
34 | // status: 200, /* Defaults to 200 */
35 | body: your_response
36 | };
37 | ```
38 |
39 | Place your message to the user in `your_response`!
40 | ## 📹 Walkthrough Video
41 | [](https://www.youtube.com/watch?v=rdAUUm3XwKE)
--------------------------------------------------------------------------------
/.bit/responses/1.7-Week 1 Step 7.md:
--------------------------------------------------------------------------------
1 | ---
2 | files: n/a
3 | stepType: checks
4 | scripts: test.1.7.js
5 | week: 1
6 | step: 7
7 | name: Week 1 Step 7
8 | ---
9 | Week 1 Step 7 ⬤⬤⬤⬤⬤⬤⬤◯◯ | 🕐 Estimated completion: 5-15 minutes
10 | ## Name your Cat
11 |
12 | ## ✅ Task:
13 | - [ ] Run `git pull`
14 | - [ ] ***1:*** Modify your Azure Function to output TWO generated cat pictures from the cat API and TWO random names from list below:
15 | - "Shreya, Emily, Fifi, Beau, Evelyn, Julia, Daniel, Fardeen"
16 | - Use the CataaS API endpoint: https://cataas.com/cat/cute/says/Bitcamp
17 | - [ ] ***2:*** Return the images, encoded in **base64**, and names in **JSON format** in the body
18 | ```js
19 | body: {
20 | cat1: your-first-catpicture-in-base64,
21 | cat2: your-second-catpicture-in-base64,
22 | names: [name1, name2]
23 | }
24 | ```
25 | - [ ] ***3:*** Commit your updated function code in `twocatz/index.js` to the `twocatz` branch, create a pull request, and only merge the PR when the bot approves your changes!
26 |
27 | > 🚨 **NOTE:** If the CataaS API is not working, please use this alternate endpoint: https://bit-cat.azurewebsites.net/cat/says/serverless
28 | ## 🚧 Test your Work
29 | When you paste your **Function URL** in your browser or make a GET request with **Postman**, you might get something like:
30 | ```json
31 | {
32 | "cat1": "/9j/4AAQSk...",
33 | "cat2": "R0lGODlhCwHI...",
34 | "names": [
35 | "Daniel",
36 | "Shreya"
37 | ]
38 | ```
39 |
40 | ## 1: Select random items out of a list
41 |
42 | 1. Create an array with the names first
43 | 2. Generate a random number within the range of the array length
44 |
45 | ❓ How do I generate two random names?
47 |
48 |
49 | 1. Create an array with the names:
50 | ```js
51 | let names = ["name1", "name2"...]
52 | ```
53 |
54 | 2. Generate a random value in the correct range:
55 | ```js
56 | let random_value = Math.floor(names.length * Math.random())
57 | ```
58 |
59 | 3. Get the name!
60 | ```js
61 | let resultname = names[random_value]
62 | ```
63 |
64 | 4. Wrap the code for generating a random combination into a function that returns resultname and call the function twice to get two names!
65 |
66 |
67 | ❓ How do I return the images using context.res?
75 |
76 |
77 | To return your two images and two names in the output:
78 | ```js
79 | context.res = {
80 | body: {
81 | cat1: your-first-catpicture-in-base64,
82 | cat2: your-second-catpicture-in-base64,
83 | names: [name1, name2]
84 | }
85 | }
86 | ```
87 | ❓ How do I catch empty POST requests?
42 |
43 | Use an try-catch statement to catch when `parse-multipart` is unable to parse the empty body. If catches an error, set the `responseMessage` to "Sorry! No image attached." Otherwise, you can safely parse the body!
44 |
45 | ```js
46 | let responseMessage = ""
47 | try {
48 | let password = // get the header called "codename"
49 | // use parse-multipart to parse the body
50 | // determine the file-type here!
51 | responseMessage = await uploadFile((place your parsedBody here), (place the extension here), (place the "codename" here));
52 | // fill the parameters in!
53 | } catch(err) {
54 | context.log("Undefined body image");
55 | responseMessage = "Sorry! No image attached."
56 | }
57 | ```
58 | > 💡 Hint: `responseMessage` is what we're returning to the user as the output.
59 | ❓ How do I select all secrets?
44 |
45 | ```js
46 | const querySpec = {
47 | query: "SELECT * from c"
48 | };
49 | ```
50 | ❓ How do I generate a random number for the index?
62 |
63 | The `Math.floor()` function returns the [floor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) of the given number - ie. the largest integer less than or equal to a given number. In the example below, the generated random number will never be greater than `items.length`.
64 |
65 | ```js
66 | let random_value = Math.floor(items.length * Math.random());
67 | ```
68 |
16 |
17 |