Skip to content

Instantly share code, notes, and snippets.

@b0c0de
Created November 20, 2019 04:14
Show Gist options
  • Save b0c0de/a66871f9feb4a9747a90ace63d6add10 to your computer and use it in GitHub Desktop.
Save b0c0de/a66871f9feb4a9747a90ace63d6add10 to your computer and use it in GitHub Desktop.
Using the Twitchtv JSON API
<div class="loading">
<h1>Using the Twitchtv JSON API</h1>
<div><i class="fa fa-spin fa-spinner"></i></div>
<p>Loading...</p>
<p class="info">Please Wait...</p>
</div>
<div class="container">
<header>
<h1>Use the Twitchtv JSON API Project</h1>
<p>Twitch Streams by BoCode</p>
<div class="filter">
<input id="online" type="radio" name='filter' checked value="online" /> <label for="online">Online</label>
<input id="offline" type="radio" name='filter' value="offline" /> <label for="offline">Offline</label>
<input id="all" type="radio" value="all" name='filter' /> <label for="all">All</label>
<input id="unknown" type="radio" value="unknown" name='filter' /> <label for='unknown'>Unknown</label>
</div>
</header>
<ul class='js-list'>
</ul>
<footer>
<p>Coded and designed by BoCode</i></p>
</footer>
</div>
$(document).ready(function(){
var streamers = [
'freecodecamp', 'storbeck', 'terakilobyte', 'beohoff', 'RobotCaleb',
'thomasballinger', 'noobs2ninjas', 'habathcx', 'riotgames', 'starladder1',
'beyondthesummit', 'tsm_theoddone', 'Tsm_dyrus', 'esl_csgo', 'garenatw',
'HiRezTV', 'smitegame', 'Nightblue3', 'nl_kripp', 'imaqtpie', 'esl_lol',
'asiagodtonegg3be0', 'destructoid', 'sodapoppin', 'OGNGlobal', 'ongamenet',
'joindotared', 'faceittv', 'taketv', 'versuta','Voyboy',
'wingsofdeath', 'towelliee', 'TrumpSC', 'leveluplive', 'twitch', 'itshafu',
'dotastarladder_en', 'riotgamesturkish', 'twitchplayspokemon',
'aces_tv', 'gamespot', 'sc2proleague', 'SirhcEz', 'totalbiscuit', 'mlgsc2',
'scarra', 'RocketBeansTV', 'lethalfrag', 'dendi', 'wcs_america', 'mlglol',
'defrancogames', 'shadbasemurdertv', 'yogscast', 'Imt_wildturtle', 'magic',
'streamerhouse', 'dhingameclient', 'wcs_europe', 'sing_sing', 'roomonfire',
'onemoregametv', 'dreamleague', 'syndicate', 'saintvicious', 'brunofin','comster404'
];
var streamUrl = 'https://wind-bow.glitch.me/twitch-api/streams/';
var streamRequests = streamers.map(function(item){
return axios.get(`${streamUrl}${item}?client_id=ac7y4kusg6ljy3317y4cy8hiqknxtj3`, {
validateStatus: function (status) {
return status < 500; // Reject only if the status code is greater than or equal to 500
}
});
});
var userUrl = 'https://wind-bow.glitch.me/twitch-api/users/';
var userRequests = streamers.map(function(item){
return axios.get(`${userUrl}${item}?client_id=ac7y4kusg6ljy3317y4cy8hiqknxtj3`,{
validateStatus: function (status) {
return status < 500; // Reject only if the status code is greater than or equal to 500
}
});
});
axios.all(streamRequests)
.then(function(response){
$('.loading').find('.info').text('Almost Ready!')
return response;
}).then(function(streamResponse){
axios.all(userRequests)
.then(function(userResponse){
$('.loading').hide();
seperateData(streamResponse,userResponse);
});
}).catch(function (response) {
if (response instanceof Error) {
// Something happened in setting up the request that triggered an Error
console.log('Error', response.message);
} else {
// The request was made, but the server responded with a status code
// that falls out of the range of 2xx
console.log(response.data);
console.log(response.status);
console.log(response.headers);
console.log(response.config);
}
});
function seperateData(streamResults,userResults){
var unknownStreamResults = streamResults.filter(function(item){
return item.status === 422;
}).map(function(item){return item.data;});
var unknownUsers = [userResults.pop().data,userResults.pop().data];
//console.log(unknownStreamResults,unknownUsers);
var knownStreamResults = streamResults.filter(function(item){
return item.status === 200;
});
var all = knownStreamResults.map(function(item){
return item.data;
});
var users = userResults.map(function(item){
return item.data;
});
var unknownStreamWithUsers = [];
for(var i=0;i<unknownStreamResults.length;i++){
var temp = unknownStreamResults[i];
temp.user = unknownUsers[i];
unknownStreamWithUsers.push(temp);
}
var streamWithUsers = [];
for(var i=0;i<all.length;i++){
var temp = all[i];
temp.user = users[i];
streamWithUsers.push(temp);
}
var online = streamWithUsers.filter(function(item){
return item.stream && item.user;
});
var offline = streamWithUsers.filter(function(item){
return !item.stream && item.user;
});
$("#online").text('Online ('+online.length+')');
$("#offline").text('Offline ('+offline.length+')');
$("#all").text('All ('+streamWithUsers.length+')');
$('#unknown').text('Unkown ('+unknownStreamWithUsers.length+')');
renderToDom(online);
$('input[type=radio]').on('change',function(e){
switch(e.target.value){
case 'online':
clearDom();
renderToDom(online);
break;
case 'offline':
clearDom();
renderToDom(offline);
break;
case 'all':
clearDom();
renderToDom(streamWithUsers);
break;
case 'unknown':
clearDom();
renderToDom(unknownStreamWithUsers);
break;
}
});
}
function generateCard(data){
var logo = data.user.logo ? data.user.logo : "https://placeholdit.imgix.net/~text?txtsize=14&txt=Logo&w=50&h=50";
if(data.status === 422){
var state = "Account Closed";
}else{
var state = data.stream ? 'online' : 'offline';
}
var bioUrl = data.user.bio ? "https://placeholdit.imgix.net/~text?txtsize=15&txt="+data.user.bio+"&w=300&h=200" : "https://placeholdit.imgix.net/~text?txtsize=160&txt=?&w=300&h=200"
var previewUrl = data.stream ? data.stream.preview.medium : bioUrl;
var lang = data.stream ? data.stream.channel.broadcaster_language : '--';
var viewers = data.stream ? data.stream.viewers : '--';
var playing = data.stream ? data.stream.game : '--';
var twitchUrl = "https://www.twitch.tv/"+data.user.name;
var displayName = data.user.display_name ? data.user.display_name : data.message
return '<li class="animated zoomIn"><a href="'+twitchUrl+'" class="card" target="_blank" ><div class="card-header"><div class="left"><img src="'+logo+'" alt="logo" /></div><div class="right"><div class="top">'+displayName+'</div><div class="bottom '+state+'"><i class="fa fa-circle"></i> '+state[0].toUpperCase()+state.slice(1)+'</div></div></div><div class="card-body"><img src="'+previewUrl+'" alt="preview" /></div><div class="card-footer"><div class="top"><div class="left"><span>Lang</span>: '+lang+'</div><div class="right"><span>Viewers</span>: '+viewers+'</div></div><div class="bottom"><span>Playing</span>: '+playing+'</div></div></a></li>';
}
function renderToDom(data){
data.forEach(function(item){
var card = generateCard(item);
//render card to dom
//console.log(card);
$('.js-list').append(card);
});
}
function clearDom(){
$('.js-list').empty();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.11.1/axios.min.js"></script>
*
box-sizing: border-box
body
margin: 0
padding: 0
font-family: 'Raleway' , sans-serif
letter-spacing: 2px
overflow: hidden
.loading
position: absolute
overflow: hidden
width: 100%
height: 100vh
top: 0
left: 0
z-index: 10
background: black
display: flex
flex-direction: column
justify-content: center
align-items: center
color: rgba(255,255,255,0.7)
font-size: 24px
text-align: center
font-family: 'Pacifico', cursive
h1
font-family: 'Raleway', sans-serif
p
margin: 5px
i
font-size: 40px
.container
position: absolute
width: 100%
margin: 0 auto
height: 100%
overflow-y: auto
footer
text-align: center
font-size: 14px
color: #888
header
letter-spacing: 3px
color: #444
text-align: center
h1,p
color: #F00
p
font-weight: 600
color: #999
h1
margin-bottom: 0
.filter
font-family: 'Open Sans', sans-serif
input[type=radio]
opacity: 0
&:checked + label
background: red
color: black
box-shadow: 1px 2px 8px #eee
label
cursor: pointer
padding: 5px 10px
border: 1px solid #eee
transition: all 0.25s
box-shadow: 1px 2px 4px #eee
&:hover
box-shadow: -1px 4px 8px #eee
ul
padding: 0
list-style: none
width: 80%
background: black
font-family: 'Open Sans', sans-serif
margin: 20px auto
display: flex
flex-wrap: wrap
li
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)
margin: 20px
flex-basis: calc(33.33% - 40px)
.card
color: #888
text-decoration: none
flex-direction: column
.card, .card-header, .card-footer
display: flex
.card-footer
flex-direction: column
span
font-weight: 600
.top
display: flex
justify-content: space-between
padding: 10px
.bottom
text-align: center
padding: 10px
padding-top: 0
.card-body
img
width: 100%
height: 200px
.card-header
padding: 5px
.right
display: flex
flex-direction: column
justify-content: center
.top
font-size: 14px
.bottom
margin-top: 5px
&.online
color: teal
.left
margin-right: 10px
img
width: 50px
height: 50px
border-radius: 50%
@media(max-width: 1024px)
body
.container
ul
width: 100%
@media(max-width: 800px)
body
.container
ul
width: 80%
li
flex-basis: calc(50% - 40px)
@media(max-width: 680px)
body
.container
ul
width: 100%
@media(max-width: 580px)
body
.container
ul
width: 70%
li
flex-basis: calc(100% - 40px)
@media(max-width: 480px)
body
.container
ul
width: 90%
@media(max-width: 350px)
body
.container
ul
width: 100%
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Pacifico|Raleway:400,600" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment