73 lines
2.7 KiB
JavaScript
73 lines
2.7 KiB
JavaScript
/* Client-side part of StreamGoose */
|
|
|
|
/* escape HTML entities (for non-server-provided stuff) */
|
|
function esc(s) {
|
|
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
|
.replace(/"/g,'"').replace(/'/g,''')
|
|
}
|
|
|
|
/* handle Twitch, YouTube and Kick emotes */
|
|
function handleEmotes(text) {
|
|
var twurl = 'https://static-cdn.jtvnw.net/emoticons/v2/$id/default/dark/1.0'
|
|
var kickurl = 'https://files.kick.com/emotes/$id/fullsize'
|
|
/* Handle Twitch emotes coming from backends */
|
|
text = text.replace(/#TWEMOTE-[^\s]+#/g,
|
|
a=>'<img src="' + twurl.replace('$id', a.split('-')[1].slice(0,-1)) + '">')
|
|
/* Handle Kick emotes coming from backends */
|
|
text = text.replace(/#KKEMOTE-[^\s]+#/g,
|
|
a=>'<img src="' + kickurl.replace('$id', a.split('-')[1].slice(0,-1)) + '">')
|
|
/* Handle YouTube emotes */
|
|
text = text.replace(/:[^\s]+:/g, a => {
|
|
if(YT_EMOTES.indexOf(a) > -1) /* found in the database */
|
|
return '<img src="/img/yt-emotes/' + a + '.png">'
|
|
else return a
|
|
})
|
|
return text
|
|
}
|
|
|
|
/* detect if there are any overridden styles */
|
|
function overrideStyles(text) {
|
|
var styles = '', re
|
|
if(messageHighlightRules) {
|
|
for(re in messageHighlightRules) {
|
|
if((new RegExp(re, 'iu')).test(text))
|
|
styles += 'color:' + messageHighlightRules[re] + ';'
|
|
}
|
|
}
|
|
if(styles.length > 0) styles = ' style="' + esc(styles) + '"'
|
|
return styles
|
|
}
|
|
|
|
/* individual message appender */
|
|
function gooseAppendMessage(id, type, timestamp, username, text, icon) {
|
|
var html = ""
|
|
if(parseInt(id) > 0 && type.length > 0) {
|
|
var classes = type.split('-'), cl = classes.length, j,
|
|
colorpref = null
|
|
for(j=0;j<cl;j++) { /* detect color preference */
|
|
if(classes[j].startsWith('color'))
|
|
colorpref = classes[j].slice(5) /* remove color word */
|
|
}
|
|
html += '<div data-msg-id="' + id + '" class="' + classes.join(' ') +'">'
|
|
if(icon.length > 0)
|
|
html += '<span class=icon><img src="' + icon + '"></span>'
|
|
html += '<span class=timestamp>' + timestamp + '</span>'
|
|
html += '<span class=username'
|
|
if(colorpref) html += ' style="color:' + colorpref + '"'
|
|
html += '>' + username + '</span>'
|
|
html += '<span class=msg' + overrideStyles(text) +'>' + handleEmotes(text) + '</span></div>'
|
|
}
|
|
document.getElementById("msglist").innerHTML += html
|
|
/* autoscroll to the end */
|
|
window.setTimeout(function(){window.scrollTo(0, document.body.scrollHeight)}, 100)
|
|
}
|
|
|
|
/* entry point, set up an event source */
|
|
window.addEventListener('DOMContentLoaded', function() {
|
|
var msgSource = new EventSource('/sse')
|
|
msgSource.onmessage = e => {
|
|
var msg = JSON.parse(e.data)
|
|
gooseAppendMessage(msg.id, msg.type, msg.timestamp, msg.username, msg.text, msg.icon)
|
|
}
|
|
}, false)
|