Adding BTTV Emotes to claack + youtube videos

Recently I added Better TwitchTV emotes to claack. Below you can see them in action. Currently there are over 50k emotes supported. I’m making a post on this because it’s surprisingly easy to do but a lot of websites DON’T do this for some reason, despite it being actually very easy to rely on BTTV’s api much like a lot of the Twitch userbase does.

Best of all, it took only 30 minutes to do. I simply went to the bttv website and monitored the XHR requests to get the URI to their API and then wrote a very simple script to dump the emotes to a dictionary for me.

import requests
import json

emoteTable = {}

def updateEmoteTable(offset, limit):
    url = "https://api.betterttv.net/3/emotes/shared/top?offset=%d&limit=%d" % (offset, limit)

    r = requests.get(url)
    
    js = r.json()

    for i in range(0, len(js)):
        emote = js[i]['emote']
        code = emote['code']
        if code not in emoteTable:
            id = emote['id']
            emoteTable[code] = id
        
        
for i in range(0, 1000):
    updateEmoteTable(i * 100, 100)
        
print(emoteTable)

The way we do something like output DOM elements for a string of text in react is pretty simple too

renderTextLine(message) {
    let tokens = message.split(' ')
    tokens = tokens.map(token => {
      if (token in emoteTable)  {
        return <span><img class="emote" src={ "https://cdn.betterttv.net/emote/" + emoteTable[token] + "/1x"}/> </span>
      }
       return (<span>{token} </span>)
    })
    return tokens
}

and then we can call renderTextLine on any message to map emote tokens to our table. Pretty straight forward.

Additionally, it’s not hard to support Youtube videos too

renderTextLine(message) {
    let tokens = message.split(' ')
    let vids = []
    tokens = tokens.map(token => {
      if (token in emoteTable)  {
        return <span><img class="emote" src={ "https://cdn.betterttv.net/emote/" + emoteTable[token] + "/3x"}/> </span>
      }
      if (token.indexOf('youtu') != -1) {
          let vid = this.parseYoutubeURL(token)
          // Delete the video, add it to the list
          if (vid) {
              vids = vids.concat((<iframe width="560" height="315" src={"https://www.youtube.com/embed/" + vid} frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>))
              return
          }
      }
       return (<span>{token} </span>)
    })
    
    // Videos go at the end
    tokens = tokens.concat(vids)
    return tokens
}

parseYoutubeURL(url) {
    var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
    var match = url.match(regExp);
    return (match&&match[7].length==11)? match[7] : false;
}

And that’s about it!

Back