FifiTeklemedhin / bit-camp-learning-lab-test

https://lab.github.com/natalieh235/creating-a-song-recommendation-engine-with-azure-(and-spotify-api)
0 stars 0 forks source link

Week 4 #5

Open github-learning-lab[bot] opened 4 years ago

github-learning-lab[bot] commented 4 years ago

Overview

Again, for this week you must commit code at each step to move on!

Login to Spotify's developer dashboard here. Then press create an app. Give it a cool name and press Create!

Click into your app and record the Client Id and Client Secret.



Before the actual programming, here's a quick overview of how the project is structured. We're going to be using the revealing module pattern in javascript, which kind of mimics classes in OOP languages like Java.


Watch this video, which gives a brief overview of this concept.



Let's take a look at an example of a module:

Notice that there are parentheses around the function– this indicates that it is an expression and should be evaluated first. So remember:

The first set of parentheses evaluate the function.

The second set of parentheses call the function.

So, the function is essentially declared and run immediately. This is called an IIFE, or immediately invoked function expression.

const car = (function(){
  var speed = 100;
  return {
    forward() {
      speed += 1;
    }
    }
})();



Notice that because the variable speed was declared within this function, it acts as a private variable and can't be accessed outside of the function. However, returning the method forward allows us to change the value of speed indirectly. Important! All methods/variables are private unless included in the return object. This is how modules enable us to encapsulate private variables or methods and reveal other ones through returning them.

//doesn't work!
car.speed = 101;

//works
car.forward();



Also notice that the method forward does not exist globally. It must be called with a reference to car. This encapsulation is what will really make it feel object-oriented, with this example having an object-private field and an object-public method.

//doesn't work
forward();

//works
car.forward();



Essentially, just remember that modules:



For more reading, check out this excerpt on the revealing module pattern, as this is not a natural javascript concept if you're new to object-oriented programming.


In this project, we're going to have two separate modules that handle distinct concerns– one called APIController for handling API calls and the other called UIController for handling our HTML input fields. A third module, called APPController, will handle retrieving and displaying the data. Each module will have public methods that the APPController will call.

modules



To get started, create a new js file called Song.js . I've already declared APPController for you. Finish writing the function expressions for APIController and UIController.

//look at the above example and the APPController declaration for syntax
//both API and UI modules take in no parameters

//spotify api call
const APIController = ??

// UI Module
const UIController = ??

const APPController = (function(UICtrl, APICtrl) {

})(UIController, APIController);

To move on, commit your code!

github-learning-lab[bot] commented 4 years ago

APIController

The APIController module is responsible for making calls to the Spotify API. To have our app get data from the Spotify API, we have to go through an Authorization process. Read the Client Credentials Flow section of the Spotify Authorization Guide here. This type of flow does not allow access to any user-specific data, so we can only access public data.


Inside the APIController module, we're going to write a private method called _getToken that will make the http request for a token. Note: it's common syntax for private methods to have an underscore in the beginning.


Use the information in the Authorization Guide (link again) to fill in the necessary fields. Notice also that we've declared variables for the client ID and secret that you received when you registered the app.


Hint: use clientId and clientSecret in the Authorization section of your http request.

Click for bigger hint:

Read the image!! For syntax:

'Authorization' : 'Basic ' + btoa(clientId + ':' + clientSecret) body: 'grant_type=client_credentials'


const APIController = (function() {

    const clientId = <CLIENT ID(do not add now, add at the end so you do not commit this)>;
    const clientSecret = <CLIENT SECRET(do not add now, add at the end so you do not commit this)>;

    // private methods
    const _getToken = async () => {

        const result = await fetch('<INSERT CORRECT ENDPOINT>', {
            method: '<INSERT CORRECT METHOD>',
            headers: {
                //content-type: how should the parameters be encoded?
                'Content-Type' : '<INSERT CONTENT TYPE>', 

                //btoa() encodes a string in base64
                //what is the string that needs to be encoded?
                'Authorization' : 'Basic ' + btoa('<INSERT AUTH STRING>')
            },

            //what request body parameters are needed?
            //the format should be a string, no spaces. ex/  'parameter_name=value'
            body: '<INSERT REQUEST PARAMETERS>'
        });

        const data = await result.json();
        return data.access_token;
    }

})();



The second private method we need is _getPlaylistItems. This is responsible for getting all the tracks from any playlist. Within the APIController, add in _getPlaylistItems.


_getPlaylistItems has three parameters


Read the documentation for the getting playlist tracks endpoint here. Notice that in the documentation, there are certain Query Parameters that you can add. To add a query parameter, it needs to be in the form of a string like so:

//key-value pairs connected by &
const queryString = '{param_1_Name}={param_1_Value}&{param_2_Name}={param_2_Value}'

//then, add your queryString onto the api endpoint with a question mark before
const result = await fetch('{api_endpoint}' + '?' + queryString, {
  //blah blah stuff here
})


Using the given code, add these things:

  1. find the correct api endpoint
  2. append a queryString that sets the query parameter limit to the limit parameter that the function receives
  3. set the correct headers


Hint: For the headers, there should be one field called Authorization set to the value 'Bearer' + token


Bigger authorization hint: ```javascript //we specify one field called 'Authorization' and set it to 'Bearer' + token headers: { 'Authorization' : 'Bearer ' + token} ```


const _getPlaylistItems = async (token, playlistId, limit) => {
    //set the query parameter limit to this limit ^ param
    const queryString = '<QUERY STRING>'

        //hint: the api endpoint should include the playlistId parameter somewhere
    //'https://api.spotify.com/v1/playlists/' + playlistId + '/tracks'
        const result = await fetch('<API ENDPOINT>' + '?' + queryString, {
            method: 'GET',
            headers: { '<HEADER_FIELD>' : '<HEADER VALUE>'}
        });

        const data = await result.json();
        return data.items;
    }

To move on, commit your code! MAKE SURE YOU ARE NOT COMMITTING YOUR CLIENT ID OR SECRET!!!(I recommend that you keep these variables empty until the end of week 4, when the other parts of your project are done)