Welcome back to Part 2 of my Twitch API project walk-through.
You can find Part 1, where I discuss the project objectives and some of the initial challenges I encountered, by clicking here.
I mentioned in Part 1, that the project now requires a workaround to access the Twitch API data. Because of that, there are very few resources available for the project in its current form.
Accessing the Twitch API
Let’s start by talking about how to access the Twitch API and what type of data we can get from it.
There are two different API calls we need to make.
The first returns data about the individual Twitch channel. Here is an example link to the channel API: https://wind-bow.glitch.me/twitch-api/channels/esl_sc2. The last part of the link, in this example “esl_sc2”, specifies the channel for which you would like to access data.
This information is much easier to digest if you install some type of browser extension for displaying JSON data. I use JSON Formatter. Without an extension, the data will display as one continuous string.
The second API call we need to make returns information on the current stream status of a channel. This link will take you to the stream API: https://wind-bow.glitch.me/twitch-api/streams/esl_sc2.
If the channel is currently live you will see that the two API calls return very similar results. But when a channel isn’t live the stream API only contains this information:
That is why it takes both the channel and stream API calls to get the data needed for this project.
Now that we have a better idea of what kind of data we are going to get from the APIs, we can start coding.
I will include code examples as we go along but if you would like to see the code in its entirety you can check out the CodePen.
We are going to start by defining our variables.
When working with an API, I like to keep my variable names consistent with how things are labeled in the API. I do the same thing when naming my HTML elements.
The first variable, “names”, is an array of Twitch streamer names. Most of these are programming streamers I found by searching Twitch. Since none of these streamers are especially active, I added a couple of video game streams so that there will always be at least one live stream at all times.
The other two variables, “displayName” and “logo” will be defined later in the code but they are named after categories from the API. The “displayName” variable represents how the channel name is displayed. The “logo” variable will be used to show a profile picture for the channel.
If you look through the two APIs you will see there is a lot of data available. Feel free to look at the different options and decide what you want to include in your own project.
Next, we want to run the array through a loop so that we can access and store data for each specific channel.
Since we need to run the array through two different APIs, I decided to use the forEach() method. There is nothing wrong with using a for loop, I just found forEach() to be cleaner in this case.
The JS Guy blog has a good article explaining the differences between for loops and forEach() loops.
All the code that we cover from here on out will be contained inside of this forEach() loop.
Next, I created two local variables, one for each API call.
The “channelAPI” variable stores the URL for the channel API we discussed earlier combined with the “name” argument, which pulls a different name from the array each time it runs through the loop.
The “streamAPI” variable does the exact same thing, except it uses the URL stream API.
Don’t forget to add “?callback=?” to the end of both of these strings or the data won’t return properly.
Now that we have defined our local variables, we are going to use them in a $.getJSON function. We are going to use this function to access and display the data for the channels on our list but we’ll get more into that later.
Name vs. displayName
Now that we have the API data from the channel and stream calls, we want to define the “displayName” and “logo” variables that we created earlier.
We do this using the channel and stream arguments that we passed in the JSON function.
The “displayName” variable is equal to the “display_name” category from the channel API. The “logo” variable is equal to the “logo” category from the channel API.
You might have noticed that there is also a third variable, “displayNameRegex”.
I realized that one channel from the array was not being displayed. It turns out, it was because the API data that is returned for “name” and “displayName” is not always the same. Unlike “name”, “displayName” can have special characters, which can cause problems as we will see later.
I created the “displayNameRegex” variable to deal with that. This new variable is equal to displayName, just with all the special characters (like spaces) removed.
Now that we have our forEach() loop running, our APIs accessed, and our variables defined, it is time to start outputting some data.
We’ll do this using an if/else statement.
There is a lot going on in this code block so let’s walk through it together. Remember, you can click on the code snippet to make it larger.
First, we want to determine if a stream is live.
To do this, I used an if statement to test if “stream.stream” (which is the stream category from the stream API) is not equal to “null”.
If “stream.stream” not equal to “null” is true, the stream is live and the code block in the if statement runs. If “stream.stream” not equal to “null” is false, the stream is not live and the code block in the else statement runs.
Let’s look at those code blocks line by line starting with when the if statement is true and the stream is live. Here is a quick look at the HTML to make it easier to see how the different elements tie together.
$(“#names”).prepend(“<div class=’name on’ id='” + displayNameRegex + “‘>”);
This prepends a new div to the ul element that has an id of “names”. This new div has a class of “name on” and an id equal to the “displayNameRegex” variable. This is why we needed to create the special regex variable. We want to turn “displayName” into an id and that won’t work if there are special characters like spaces included. We use prepend for the div because we want the live channels to show up first on the list.
$(“#” + displayNameRegex).append(“<a href=’//twitch.tv/” + name + “‘ target=’_blank’>” + logo + “<h2 class=’displayName’>” + displayName + “</h2></div>” + “<div class=’game’>” + “Currrently streaming <strong>” + stream.stream.channel.game + “</strong> for ” + stream.stream.viewers + ” viewers.</div>” + “<div class=’topic’>” + “<em>” + stream.stream.channel.status + “</em></div></a>”);
This block appends a bunch of data to the div with the id “displayNameRegex” that was created in the previous step. First, it adds an anchor tag to the entire element linking to the Twitch channel. Then, it uses the “logo” variable to add a profile picture. Next, it creates an h2 element with a class of “displayName”. We then reference the “displayName” variable inside the h2 element. Then the div created in the previous step closes and a new div with a class of “game” is added. This new div takes API data in the form of “stream.stream.channel.game” and “stream.stream.viewers” and adds it to a string showing what game is currently being streamed and how many people are currently watching. That div is closed and a final div is created which uses “stream.stream.channel.status” to display the title of the current stream.
The code block that executes in the else statement when the stream is not live is pretty similar, just with fewer details.
$(“#names”).append(“<div class=’name off’ id='” + displayNameRegex + “‘>”);
This is the same basic principle as in the if statement block, except this time we use append since we want the offline channels to be after the online channels.
$(“#” + displayNameRegex).append(“<a href=’//twitch.tv/” + name + “‘ target=’_blank’>” + logo + “<h2 class=’displayName’>” + displayName + “</h2></div></a>”);
Again, this is like the if statement block except it only displays the profile picture and the displayName of the channel.
Below the if/else loop there is another if statement that adds a default profile picture in the event that the channel doesn’t already have one.
All, Online, and Offline Tabs
The only thing left to do now, is to add some functionality to allow the user to sort the data by using the All, Online, and Offline tabs.
If you look back at the HTML image above you can see that we already have an unordered list with an id of “status”. This ul has three li elements with the respective ids of “all”, “online”, and “offline”.
The next section of code will tie-in to those ids.
Remember, in the if/else statement we added divs with the class of either “name on” or “name off”. This code block uses those classes to determine under which tabs channels should be displayed under.
The first section adds a click event to the li element with an id of “all”. When the user clicks the “all” tab, it adds a class of “active” to the li element with an id of “all” and removes the class of “active” from the li elements with an id of “online” and “offline”. It then shows the div elements with a class of “name”.
The second section adds a click event to the li element with an id of “online”. When the user clicks the “online” tab, it adds a class of “active” to the li element with an id of “online” and removes the class of “active” from the li elements with an id of “all” and “offline”. It will then show the div elements with a class of “on” and hide the div elements with a class of “off”.
You have probably figured this out by now, but the last section adds a click event to the li element with an id of “offline”. When the user clicks the “offline” tab, it adds a class of “active” to the li element with an id of “offline” and removes the class of “active” from the li elements with an id of “all” or “online”. It will then show the div elements with a class of “off” and hide the div elements with a class of “on”.
The Simple Version
If this seems confusing, just remember that everything is happening inside of the forEach() loop, one name at a time.
The forEach() loop takes the first name from the “names” array we created in the beginning and runs it through all the code we have talked about.
First, it takes that name and creates the “channelAPI” and “streamAPI” variables. Then it makes the $.getJSON calls using those variables, and then defines the “displayName”, “displayNameRegex”, and “logo” variables. After that, it runs the if/else loop and prepends or appends the appropriate data based on whether the stream is online or not.
Once it runs through all the code with the first name it returns to the top and repeats the process with the second name in the “Names” array. It keeps repeating that process until it reaches the end of the “Names” array.
How Did I do?
This is my first time really diving into the code behind a project like this. Hopefully, it made sense and wasn’t too dry.
As always, if you have any questions, comments, or feedback feel free to drop a line in the comments section. Be sure to let me know if you want more articles like this.
Like I said in Part 1, this project gave me a lot of trouble initially so hopefully this deep dive can help other people with their Twitch API project.
Have fun and keep coding!