fcc-twitch-api

In this example below you will see how to do a fcc-twitch-api with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by Lee182, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright Lee182 ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>fcc-twitch-api</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"><link rel="stylesheet" href="styl.css"><title>Twitch Stream Tracker</title><meta name="description" content="Building a 1 page app to see who is on twich atm"></head><body><div id="head"><div class="flexcenter"><h1 class="mainTitle"><svg aria-label="Twitch - Main Page" height="1em" role="img" version="1.1" viewbox="0 0 94 32" width="2.9375em" x="0px" y="0px" class="svg_logo_twitch"><title>Twitch</title><desc>Main Page</desc><path clip-rule="evenodd" d="M88,5h-6V0h-9l-6,5h-5.5L59,7.5V5h-5V0H36v5H16l-5-5H0v22l5,5.25L14,32h6v-1.5l3,1.5h12l2-3l1,3h7v-3l3,3h8l0.5-3l2.5,3h10l3-3v3h4l3-3v3h7l7-6V10L88,5z M13,13H8v6h5v6H6l-4-4V2h6v5h5V13z M36,21.5L32.5,25H15V7h6v12h2V7h6v12h2V7h5V21.5z M44,25h-6V7h6V25z M44,5h-6V2h6V5z M57,13h-5v6h5v6h-7l-4-4V2h6v5h5V13z M72,13h-7v6h7v6h-9l-4-4V11l4-4h9V13z M91,25h-6V13h-5v12h-6V2h6v5h7l4,4V25z" fill-rule="evenodd"></path></svg><i class="fa fa-twitch"></i><br><span class="mainTitle_info">Stream Tracker</span></h1></div><div class="flexcenter"><p class="subtitle">Track your twitch streams all in this neat app</p></div></div><div id="chest"><div class="streamers flexwrap"></div></div><div id="aside"></div><div id="foot"></div><script src="bundle.js"></script></body></html>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/Lee182/fcc-twitch-api-vXmyZX */
@import url("https://fonts.googleapis.com/css?family=UbuntuMono:400,700,300");
@import url("https://fonts.googleapis.com/css?family=Quicksand:400,700");
@import url("https://fonts.googleapis.com/css?family=Nunito:400,300");
@import './lib/meyerreset.css';
* {
  box-sizing: border-box;
}
.flexcenter {
  display: flex;
  justify-content: center;
}
.flexwrap {
  display: flex;
  flex-flow: row wrap;
}
.flexItem {
  flex: 1 0 100%;
}
.textcenter {
  text-align: center;
}
.textleft {
  text-align: left;
}
body {
  font-family: 'Nunito';
  background-color: #e7d2a6;
}
.svg_logo_twitch {
  font-size: 1.2em;
}
.svg_logo_twitch path {
  fill: #6441a5;
}
.fa-twitch,
.mainTitle_info {
  vertical-align: top;
}
.mainTitle {
  font-size: 3em;
  font-family: 'Ubuntu Mono';
  color: #6441a5;
}
.mainTitle_info {
  font-size: 0.5em;
}
.subtitle {
  font-size: 1.1em;
  font-weight: 400;
  color: #545454;
}
.logo {
  height: 6em;
  width: 6em;
}
.info {
  height: 6em;
  background-color: #bcbcbc;
  padding: 0.5em;
}
.bottom {
  align-self: flex-end;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.country {
  width: 1.5em;
}
.bullet {
  margin: 0 0.3em;
}
.bullet:after {
  font-size: 0.7em;
  content: '\2022';
}
.stream_name {
  font-family: ubuntu mono;
  font-size: 1.2em;
  text-align: right;
}
.stream_name_status {
  align-self: flex-end;
  font-size: 0.9em;
  text-align: right;
  font-style: italic;
  font-weight: 300;
}
.stream_status {
  position: absolute;
  bottom: 0px;
  background-color: rgba(220,220,220,0.68);
  width: 100%;
  height: 33%;
}
.thumb {
  position: relative;
  background-color: #9790a4;
  height: 6em;
  width: 6em;
  overflow: hidden;
}
.bulb {
  position: absolute;
  top: 0%;
  right: -2%;
  height: 1em;
  width: 1em;
  background-color: #b3c9fe;
  border-radius: 5px;
  border: 2px solid #01174b;
}
.fa-users {
  color: rgba(65,65,65,0.61);
}
.followers .n {
  display: inline;
}
.streamers {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
}
.streamer {
  display: flex;
  flex-flow: row nowrap;
  transition: 1s all ease;
  padding: 0.5em 0;
  max-width: 500px;
  color: #fbfbfb;
}
.streamer .logo {
  filter: grayscale(80%);
}
.streamer .info {
  position: relative;
  background-color: #9790a4;
}
.streamer .info:before {
  content: 'offline';
  position: absolute;
  top: 0.5em;
  left: 0.5em;
}
.streamer.online .logo {
  filter: none;
}
.streamer.online .info {
  position: relative;
  background-color: #a087d0;
}
.streamer.online .info:before {
  content: 'LIVE';
  position: absolute;
  top: 0.5em;
  left: 0.5em;
  background-color: rgba(6,3,3,0.34);
  border: 2px solid rgba(255,255,255,0.77);
  padding: 0 0.2em;
  margin: -3px;
  text-shadow: 1px 1px 2px #f00, 0px 1px 1px #f00;
}
.streamer.error .exclaimMark {
  font-size: 6em;
  text-align: center;
  background-color: #f5683a;
}
.streamer.error .info {
  background-color: #c3672d;
}
.streamer.error .info:before {
  content: 'notify';
}
@media screen and (min-width: 415px) {
  .streamer {
    margin: 0.5em;
  }
}
.stream_status {
  display: none;
}
.stream_name {
  font-size: 1.3em;
  font-weight: 600;
}
#head {
  padding: 2em;
}
.streamers {
  display: table;
  margin: 0 auto;
}
.streamer {
  color: #fbfbfb;
  background-color: #00f;
  padding: 0;
  margin: 0;
  border-top: 3px solid #dedede;
}
.info {
  width: 100%;
}


/*Downloaded from https://www.codeseek.co/Lee182/fcc-twitch-api-vXmyZX */
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var getJSON = require('./lib/getJSON.js')
var jadeJon = require('./lib/jadeJon.js')
window.jTree = jadeJon.jStructure
window.jEl = jadeJon.jEl
function log(a) {
  console.log(a)
  return Promise.resolve(a)
}


var streamurl = 'https://api.twitch.tv/kraken/streams/'
var channelurl = 'https://api.twitch.tv/kraken/channels/'

var users = ["Towelliee","wgleu","freecodecamp","storbeck","habathcx","RobotCaleb","thomasballinger","noobs2ninjas","beohoff", "comster404" ]

var clientID_2016 = '?client_id=g7z5v4se9ek6tkq4qtnoa6sp0yldsus'
users.forEach(function(username){
  getJSON(streamurl + username + clientID_2016).then(decideResponse)
})

function decideResponse(res) {
  console.log(res)
  var streamExsists = res.stream !== null || res.status ==404
  if (res.error) {
    // var el = generateErrorStreamer(res)
    // 2016
    var el = generateErrorStreamer(res)
    console.log(el)
    renderStreamer(el)
    return null
  }
  if (streamExsists) {
    var el = genrateStreamer(res.stream.channel)
    return modifyStreamerSoOnline(res.stream, el).then(renderStreamer)
  }
  else {
    console.log('the else statement with ' + res._links.channel)
    return getJSON(res._links.channel + clientID_2016).then(genrateStreamer).then(renderStreamer)
  }
}


function genrateStreamer(channelRaw) {
  var channel = {
    stream_name_status: channelRaw.status,
    lang: channelRaw.language,
    logo: channelRaw.logo,
    channel_name: channelRaw.display_name,
    url: channelRaw.url,
    followersN: channelRaw.followers
  }
  var el = jTree(`
  .streamer.flexItem
    .thumb
      img.logo
    .info.flexwrap
      .top.flexItem.flexwrap
        .stream_name.flexItem
        .stream_name_status.flexItem
      .bottom.flexItem
        .followers
          i.fa.fa-users
          .n
        .bullet
        img.country
        .bullet
        .channel_name
  `)
  console.log('generateStreamer el:', el)
  for (var prop in channel) {if (channel.hasOwnProperty(prop)) {
    el.dataset[prop] = channel[prop]
  }}
  var dom = {
    stream_name_status: el.querySelector('.stream_name_status'),
    lang: el.querySelector('img.country'),
    logo: el.querySelector('.logo'),
    channel_name: el.querySelector('.channel_name'),
    followersN: el.querySelector('.followers .n')
  }
  if (channel.logo !== null) {
    dom.logo.src= channel.logo
  } else {
    var thumb = dom.logo.parentElement
    dom.logo.remove()
    var twitchIcon = jEl('i.fa.fa-twitch')
    twitchIcon.style.fontSize = '6em'
    thumb.appendChild(twitchIcon)
  }
  dom.stream_name_status.textContent= channel.stream_name_status
  dom.channel_name.textContent= channel.channel_name
  dom.lang.alt= channel.lang
  dom.followersN.textContent = ' ' + channel.followersN
  el.addEventListener('click',function(e){
    window.location.href = ('https://www.twitch.tv/' + el.dataset.channel_name)
  })
  return Promise.resolve(el)
}


function generateErrorStreamer(data) {
  var el = jTree(`
  .streamer.error.flexItem
    .thumb
      .exclaimMark !
    .info.flexwrap
      .top.flexItem.flexwrap
        .stream_name.flexItem ${data.error}
        .stream_name_status.flexItem ${data.message}`)
  return el
}


function renderStreamer(el) {
  var list = document.querySelector('.streamers')
  list.appendChild(el)
}

function modifyStreamerSoOnline(stream, el) {
  el.then(function(el){
    el.classList.add('online')
    el.querySelector('.stream_name').textContent= stream.game
  })
  return Promise.resolve(el)
}

},{"./lib/getJSON.js":2,"./lib/jadeJon.js":3}],2:[function(require,module,exports){
getJSON = function (url, secs) {
  if (!secs){secs = 10000}
  return promise = new Promise(function(done, reject) {
    var req = new XMLHttpRequest()
    req.onload = function() {
      clearTimeout(timer)
      try {
        var obj = JSON.parse(req.response)
        done(obj)
      } catch (e) {
        reject(e)
      }
    };
    req.onerror = function(e) {
      reject(e)
    }
    req.open('get', url, true);
    req.setRequestHeader('Accept', 'application/json');
    req.send();
    var timer = setTimeout(function(){
      reject(new Error((secs / 1000) + ' seconds is way too long'))
    },secs)
  })
}
if (module && module.exports) {
  module.exports = getJSON
}

},{}],3:[function(require,module,exports){
function jStructure(str) {
  var arr = str.split('\n').reduce(cleanUp, [])
  arr = backspace(arr)
  var EL = document.createElement('div')
  arr.forEach(function(str, ii){
    var loci = EL
    var lvl = findLevel(str)
    var el = jEl(str.trimLeft())
    if (lvl === 0) {loci.appendChild(el)}
    if (lvl > 0) {
      for (var i = 1; i <= lvl; i++) {
        loci = loci.childNodes[loci.childElementCount-1]
        if (lvl === i) {
          loci.appendChild(el)
        }
      }
    }
  })
  if (EL.childElementCount === 1) {
    return EL.childNodes[0]
  }
  return EL
}
function backspace(arr) {
  var amount = arr[0].split('  ').length - 1
  return arr.map(function(str){
    return str.substr(amount * 2)
  })
}
function cleanUp(arr, str, i) {
  if (str.trim() !== ''){
    arr.push(str.trimRight())
  }
  return arr
}
function findLevel(str) {
  return str.split('  ').length - 1
}
function jEl(str) {
  var regTag = /(^\w+)/g
  var regClass = /\.([A-z]|(_|-)|\d)+/g
  var regId = /\#([A-z]|(_|-)|\d)+/g

  var tag = str.match(regTag)
  var classim = str.match(regClass)
  var ids = str.match(regId)
  var words = str.split(' ')
  var text = words.splice(1, words.length).join(' ')
  if ( !( tag || classim || ids) ) {
    throw new Error('error in string given')
    return;
  }
  if (tag === null) {tag = 'div'}
  var el = document.createElement(tag)
  if (ids) {
    el.id = ids.map(removeFirstChar).join(' ')
  }
  if (classim) {
    el.className = classim.map(removeFirstChar).join(' ')
  }
  if (text.length >= 1) {
    el.textContent = text
  }
  function removeFirstChar(str) {
    return str.substr(1)
  }
  return el
}

if (module && module.exports) {
  module.exports = {
    jEl: jEl,
    jStructure: jStructure
  }
}

},{}]},{},[1]);

Comments