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