We form a plan to find the common ground between two artists from the spotify api. Then we sketch out a data flow to ensure we have what we need, when we need it.
We are looking at a Spotify API doc here. We want to make a little app that will go ahead and get the related two artists and then compare them to give me a suggestion.
For instance, I give it, let's say index.js, say node index.js. We'll give it Oasis and Blur. We should get some artists recommendations based on those two.
Here, to form a little plan, I'm looking at the API docs. I see I can get several artists or artist with an ID and get their related artists if I have an ID. I'm looking here. There's a search, so I can search for an item here. If we do a quick little test, it says Muse here, so we'll take Muse, and then artist, that's what we want to look for. Here's our URL. Let's copy this for future reference.
We will try it. Sure enough, we get a response here. It looks like this. It has artists which have items. That's all of the items. Now, they actually have their IDs in them. It's artist, then items.
We'll do a similar thing with related. Let's go ahead and just fill in some simple data and try it. If we have some ID, it returns us back artists, but it's not data items. It's just an array of all the other artists here.
Let's go ahead and get started. I'll do MPM in it, and yes, yes, yes, yes. We'll vim index. Let's go ahead and touch index.js in vim here. Let's start by MPM install. I'm going to install my favorite dependencies and we'll use them here.
There's data.either, data.task. Instead of box, we'll use fantasy identities if we need to use those and request just to make a basic HTTP request. We'll go ahead and save all of this right there.
With this plan, we want to take two sets of artists and compare them and figure out the commonality between them. In a normal object-oriented setting, you might start with a class called Spotify. You would go ahead and try to make media class of artist.
We'll put methods on Spotify to go get artists and so on, etc. Here, we're going to do something a little bit different. We're going to build a flow for our data to flow through. We are going to retrieve the data and then just pass it through a series of functions. Let's do that.
We'll start off with a little sketch here. We'll say main. We need some arguments here. We have Oasis and Blur. Let's go ahead and start by console.logging(process.argv) so we can see what we have here. If I run this node index JS, Oasis and Blur, we have an array of args. We have a path to node, the follower using, and the two artists.
This already is breaking a nice rule of functional programming with grabbing this ambient state out of nowhere. What we'll do here is just bringing a task right after that, require("data.task"). We'll wrap our argv in a new task.
Notice, I'm not making a new function every time. It's just one task holding the results of process argv. There it is. I would use this by saying argv.map. What we want to do here is grab the last two or more ignoring these first two arguments.
Why don't go ahead and just get our args? We'll do args slice(2). This'll be our artists. Let's just call it names for now because they're not actually artists from the system here. They're just names.
Back to main, we can call main with names. Let's go ahead and say argv.map and then we'll call main. That'll pass the two names...Oh, I'm sorry. Names map name, there we go because that uses argv. We'll grab our names, pass them into main, and then we will just fork that with a console.error or console.log just like that.
What shall we do with these names? We can destructure them right here in the args here, name one, name two. Remember, we want to go get the search results for each name and then get the related artists from that first result, the best result here. I would say, "We need a find artist." Why don't we call it search? No, let's call it find artist because we want to search but then grab the first artist anyway.
Find the artist with the name one. We will just chain that artist into the call to related artists. What I'm doing here is just sketching out here, we go artist.ID, without coloring anything in. We're just writing a basic workflow. We want to do this for both name one and name two, this find the artist and then get their related artist. Let's pull this out into its own function here. We'll call this related. It will just take a name and do this little process for that name.
By sketching these things out the way we are, we're not going to run into any snags later because we're walking the data through these functions and making sure we have what we need when we need it. I'd rather not do this here.
Why don't we go ahead and do the map artist, artist.ID? We can just class this first class here, related artists, just like that. This is a just a personal preference. I like to see the data transform before it's passed into the function.
Now, if we have the related, R name one, and the related, R name two, and we haven't written find artist or related artists, we have to go write those. What we can do here is assume that we have both pieces of data.
We know if we want to work with two pieces of data at the same time that are independent of each other, we can use applicatives. Since surely related is going to make an HTTP call to do some kind of side effect, we'll have a task.
Let's say task of rels one, rels two. These rels are just the related artists. We'll do something with them. Let's just pop them into an array right now so we can take a look at them. We will apply that to a related. We'll apply that to the other related. There we are.
If we can get this part to work, then we can figure out how to find the similar artists afterwards with both pieces of data.