var s;
var antiflood = false;
var is_connected = false;
var chat_num = 0;
var focused = true;
var comments_hidden = false;
var video, hls, dash;
var current_source;
var notice_audio;
var loading_timer;
var live_mode = "hls";
var live_time = -1;
var modpanel = null;
var mod = false;
var mod_name = "";
var is_fullscreen;
var fullscreen_activity = {on: false, hide: null};
var notice_activity = {on: false, hide: null, blink: null};
var CHAT_FACTOR = (ANIM_MAX - ANIM_MIN) / MAXCHAR;
function removeThis(e) {
e.target.parentElement.removeChild(e.target);
}
const formatTime = (seconds, h = Math.floor(seconds / 3600), m = Math.floor((seconds % 3600) / 60), s = Math.floor(seconds) % 60) => [h, m > 9 ? m : '0' + m, s > 9 ? s : '0' + s].filter(s => s).join(':');
function escapeColon(msg) {
return msg ? msg.replace(/:/g, "%3A") : "";
}
function translateColon(msg) {
return msg ? msg.replace(/%3A/g, ":") : "";
}
function escapeHTML(unsafe) {
return unsafe
.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
function show_chat(msg, color, own) {
if(!focused) return;
var chat = document.getElementById("chat");
var chats = chat.children;
var chat_rect = chat.getBoundingClientRect();
var line = 0;
for(var i = 0; i < chats.length; i++) {
var el = chats[i];
var rect = el.getBoundingClientRect();
if(
el.dataset.line == line &&
(rect.left - chat_rect.left + rect.width) > (chat_rect.width - CHAT_SEP)
)
{
i = 0;
line++;
}
}
var obj = document.createElement('span');
obj.style.boxSizing = "content-box";
obj.textContent = msg;
obj.dataset.line = line;
obj.addEventListener("transitionend", removeThis);
obj.classList.add("c"+color);
chat.appendChild(obj);
if(own)
obj.classList.add("own");
var width = Math.round(obj.getBoundingClientRect().width);
var height = parseFloat(getComputedStyle(obj).getPropertyValue("height"));
obj.style.top = ((height+LINE_SEP)*line) + "px";
obj.style.transitionDuration = (ANIM_MIN + (msg.length * CHAT_FACTOR)) + "s";
obj.style.left = "-" + width + "px";
}
function show_notice(name, msg) {
document.getElementById("noticebox").style.backgroundImage = "none";
document.getElementById("notice").innerHTML = anchorme(escapeHTML(msg), {truncate: 20});
document.getElementById("notice").style.animation = "blinker 0.2s step-start infinite";
document.getElementById("author").textContent = (name ? name : "Streamer");
if(is_fullscreen)
document.getElementById("noticebox").style.display = "block";
if(!video.muted) {
if(typeof variable === 'undefined')
notice_sound = new Audio("notice.opus");
notice_sound.volume = video.volume;
notice_sound.play();
}
clearTimeout(notice_activity.hide);
clearTimeout(notice_activity.blink);
notice_activity.hide = setTimeout(hide_notice, NOTICE_TIME);
notice_activity.blink = setTimeout(stop_notice_blink, NOTICE_BLINK_TIME);
notice_activity.on = true;
}
function stop_notice_blink() {
document.getElementById("notice").style.animation = "none";
}
function hide_notice() {
document.getElementById("noticebox").style.backgroundImage = "url('baitvlogo.png')";
document.getElementById("notice").textContent = "";
document.getElementById("author").textContent = "";
if(is_fullscreen)
document.getElementById("noticebox").style.display = "none";
notice_activity.on = false;
}
function get_time() {
var time = new Date();
return (
("0" + time.getHours()).slice(-2) + ":" +
("0" + time.getMinutes()).slice(-2) + ":" +
("0" + time.getSeconds()).slice(-2));
}
function show_tt(e) {
var tt = document.getElementById("tt");
tt.style.visibility = "visible";
tt.textContent = this.children[0].textContent;
tt.style.left = (e.pageX + 10) + "px";
tt.style.top = (e.pageY + 10) + "px";
}
function hide_tt(e) {
var tt = document.getElementById("tt");
tt.style.visibility = "hidden";
}
function show_chatbox(msg, classname) {
var chatbox = document.getElementById("chatbox");
var chatbox_length = chatbox.children.length;
if(chatbox_length >= CHATBOX_MAX)
chatbox.removeChild(chatbox.firstChild);
var line = document.createElement('div');
var content = document.createElement('span');
var time = document.createElement('span');
//line.classList.add("l" + (chat_num ^= 1));
line.addEventListener("mousemove", show_tt);
line.addEventListener("mouseout", hide_tt);
if(classname)
line.classList.add(classname);
content.textContent = msg;
content.className = "msg";
line.appendChild(content);
//time.textContent = get_time();
time.textContent = get_live_time();
time.className = "time";
line.appendChild(time);
chatbox.appendChild(line);
chatbox.scrollTop = chatbox.scrollHeight;
}
function on_msg(line) {
console.log("<< " + line);
var args = line.split(':');
if(args[0] == "MSG") {
var color = args[1];
var msg = translateColon(args[2]);
show_chat(msg, color, false);
show_chatbox(msg, null);
} else if (args[0] == "FMSG") {
var id = args[1];
var color = args[2];
var msg = translateColon(args[3]);
show_chat(msg, color, false);
show_chatbox("["+id+"] " + msg, null);
} else if (args[0] == "NOTICE") {
var name = args[1];
var msg = translateColon(args[2]);
show_notice(name, msg);
show_chatbox((name ? "["+name+"] "+msg : msg), "mod");
} else if (args[0] == "COUNT") {
document.getElementById("viewers").textContent = args[1];
} else if (args[0] == "SOURCE") {
switch_source(args[1], parseInt(args[2]));
} else if (args[0] == "TITLE") {
var title = translateColon(args[1]);
set_title(title);
} else if (args[0] == "KICKED" || args[0] == "BANNED") {
show_chatbox("Un usuario fue expulsado.", "warn");
} else if (args[0] == "YOU_KICKED" || args[0] == "YOU_BANNED") {
show_chatbox("¡Fuiste expulsado!", "warn");
} else if (args[0] == "BADPASS") {
set_status("Mod: PSK erróneo.");
} else if (args[0] == "LOGIN_OK") {
set_status("Mod: Log in suceso.");
enable_modpanel(true, args[1]);
} else if (args[0] == "LOGOUT_OK") {
set_status("Mod: Log out suceso.");
enable_modpanel(false, "");
} else {
if(mod) set_status(line);
}
}
function set_title(title) {
document.getElementById("title").textContent = title ? title : "Sin título";
}
function set_status(msg) {
show_chatbox(msg, "sys");
console.log(msg);
}
function video_play() {
video.muted = false;
if(typeof Promise === "function") {
var promise = video.play();
promise.catch(function(e) {
console.log("Your browser is rejecting autoplay; attempting to play muted.");
video.muted = true;
video.play();
});
} else {
console.log("Promise not supported; muting just in case.");
video.muted = true;
video.play();
}
}
function video_volume() {
if(video.muted) video.muted = false;
video.volume = this.value;
}
function parse_state(msg) {
var state = JSON.parse(msg);
switch_source(state.source, state.source_time);
set_title(translateColon(state.title));
if(state.welcome)
show_chatbox(state.welcome, "sys");
}
function switch_source(source, src_time) {
if(!PLAY) return;
if(current_source == source) return;
console.log("Switching source to: " + source);
if(source == "live") {
console.log(src_time);
// hls.js
video.src = "";
video.loop = false;
video.addEventListener("waiting", event_waiting);
video.addEventListener("canplay", event_canplay);
source_time = src_time
if(live_mode == "hls") {
if(Hls.isSupported()) {
hls = new Hls(HLS_CONFIG);
hls.loadSource(MEDIA_HLS_URL);
hls.attachMedia(video);
video_play();
hls.on(Hls.Events.MANIFEST_PARSED,function() {video_play();});
hls.on(Hls.Events.ERROR, on_hls_error);
hls.on(Hls.Events.FRAG_CHANGED,function(event,data) {
live_time = Math.floor((data.frag.programDateTime / 1000) - data.frag.start) - source_time;
});
} else { set_status("Tu navegador no soporta HLS. Cancelando."); return; }
} else if(live_mode == "dash") {
if ( typeof ( window.MediaSource || window.WebKitMediaSource ) === "function" ) {
if(!dash) dash = dashjs.MediaPlayer().create();
dash.initialize();
//dash.getDebug().setLogToBrowserConsole(true);
dash.setAutoPlay(false);
dash.setManifestLoaderRetryAttempts(7);
dash.setManifestLoaderRetryInterval(5);
dash.on(dashjs.MediaPlayer.events.CAN_PLAY, video_play);
dash.attachView(video);
dash.attachSource(MEDIA_DASH_URL);
event_waiting();
live_time = 0;
set_status("Nota: Utilizando DASH. ¡Experimental!");
} else { set_status("Tu navegador no soporta MediaSource. Cancelando."); return; }
} else if(live_mode == "rx") {
if ( typeof ( window.MediaSource || window.WebKitMediaSource ) === "function" ) {
var rx = new RxPlayer({videoElement: video});
rx.loadVideo({url: MEDIA_DASH_URL, transport:"dash", autoPlay:false});
live_time = 0;
set_status("Nota: Utilizando DASH (rx). ¡Experimental!");
video_play();
} else { set_status("Tu navegador no soporta MediaSource. Cancelando."); return; }
} else if(live_mode == "shaka") {
shaka.polyfill.installAll();
if(shaka.Player.isBrowserSupported()) {
var player = shaka.Player(video);
player.load(MEDIA_DASH_URL).then(video_play);
live_time = 0;
set_status("Nota: Utilizando DASH (shaka). ¡Experimental!");
} else { set_status("Tu navegador no soporta Shaka. Cancelando."); return; }
}
document.getElementById("livestatus").classList.add("live");
} else {
if(current_source == "live") {
if(hls) {
hls.detachMedia();
hls.destroy();
console.log("hls.js destroyed");
}
if(dash) {
dash.reset();
console.log("dash.js destroyed");
}
}
source_time = -1
live_time = -1;
document.getElementById("time").textContent = "--:--";
video.src = IDLE_VIDEO;
video.loop = true;
video.muted = true;
video.removeEventListener("waiting", event_waiting);
video.removeEventListener("canplay", event_canplay);
event_canplay();
video.play();
document.getElementById("livestatus").classList.remove("live");
}
current_source = source;
}
function on_hls_error(e, data) {
console.log(data['type']);
console.log(data['details']);
}
function update_controls() {
document.getElementById("volume").style.opacity = video.muted ? 0.5 : 1;
document.getElementById("mute").children[0].style.display = video.muted ? "none" : "block";
document.getElementById("mute").children[1].style.display = video.muted ? "block" : "none";
document.getElementById("volume").value = video.volume;
}
function get_live_time() {
if(current_source == "live") {
return formatTime(live_time + video.currentTime);
} else {
return "--:--"
}
}
function update_time() {
if(current_source == "live")
document.getElementById("time").textContent = get_live_time();
}
function on_play() {
if(video.paused)
video.play()
else
video.pause()
}
function on_mute() {
video.muted = !video.muted;
}
function on_hidecomments() {
if(comments_hidden) {
document.getElementById("chat").style.visibility = "visible";
document.getElementById("hidecomments").children[0].style.display = "block";
document.getElementById("hidecomments").children[1].style.display = "none";
comments_hidden = false;
} else {
document.getElementById("chat").style.visibility = "hidden";
document.getElementById("hidecomments").children[0].style.display = "none";
document.getElementById("hidecomments").children[1].style.display = "block";
comments_hidden = true;
}
}
function fullscreenElement() {
return (document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement);
}
function on_fullscreen() {
var elem = document.getElementById("player");
if (fullscreenElement()) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) { /* Firefox */
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) { /* Chrome, Safari and Opera */
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) { /* IE/Edge */
document.msExitFullscreen();
}
} else {
console.log("requesting full screen");
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.mozRequestFullScreen) { /* Firefox */
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
elem.webkitRequestFullscreen();
} else if (elem.msRequestFullscreen) { /* IE/Edge */
elem.msRequestFullscreen();
}
}
}
function fullscreen_clear() {
fullscreen_base(false);
clearTimeout(fullscreen_activity.hide);
fullscreen_activity.on = false;
}
function fullscreen_base(show) {
var base = document.getElementById("base");
base.style.visibility = show ? "" : "hidden";
document.getElementById("player").style.cursor = show ? "" : "none";
}
function fullscreen_move(e) {
if(!fullscreen_activity.on) {
fullscreen_base(true);
fullscreen_activity.on = true;
}
clearInterval(fullscreen_activity.hide);
fullscreen_activity.hide = setInterval(fullscreen_clear, BASE_SHOW_TIME);
}
function fullscreen_event() {
var noticebox = document.getElementById("noticebox");
var base = document.getElementById("base");
if(fullscreenElement()) {
base.style.position = "absolute";
base.style.opacity = "0.7";
noticebox.style.position = "absolute";
if(!notice_activity.on) {
noticebox.style.display = "none";
}
fullscreen_move(null);
document.getElementById("chat").style.fontSize = "4.6vw";
document.getElementById("player").addEventListener("mousemove", fullscreen_move);
document.getElementById("player").addEventListener("keypress", fullscreen_move);
document.getElementById("chat_msg").focus();
is_fullscreen = true;
} else {
base.style.position = "";
base.style.opacity = "";
noticebox.style.position = "";
noticebox.style.display = "";
clearInterval(fullscreen_activity.hide);
fullscreen_base(true);
document.getElementById("chat").style.fontSize = "";
document.getElementById("player").removeEventListener("mousemove", fullscreen_move);
document.getElementById("player").removeEventListener("keypress", fullscreen_move);
is_fullscreen = false;
}
}
function event_waiting() {
loading_timer = setTimeout(show_loading, 1000);
}
function show_loading() {
document.getElementById("loading").style.display="block";
}
function event_canplay() {
clearInterval(loading_timer);
document.getElementById("loading").style.display="none";
}
function start() {
console.log("baitv.js 0.4");
if(window.location.href.endsWith("?dash")) live_mode = "dash";
if(window.location.href.endsWith("?rx")) live_mode = "rx";
if(window.location.href.endsWith("?shaka")) live_mode = "shaka";
video = document.getElementById('video');
if(PLAY) {
var req = new XMLHttpRequest();
req.onload = function(e) { parse_state(req.response); }
req.open("GET", STATE_URL + "?t=" + Date.now());
req.send();
}
if(CONNECT) {
s = new WebSocket(ADDRESS);
s.addEventListener("message", function(e) { on_msg(e.data); });
s.addEventListener("open", function(e) { set_status("Conectado al chat."); is_connected = true; enable_chat(); });
s.addEventListener("close", function(e) {
set_status("Desconectado del chat. " + (e.reason ? "Razón: "+e.reason : "Código: "+e.code));
is_connected = false;
document.getElementById("viewers").textContent = "-";
});
}
document.getElementById("sendchat").addEventListener("click", on_send);
//document.getElementById("playbtn").addEventListener("click", on_play);
document.getElementById("mute").addEventListener("click", on_mute);
document.getElementById("hidecomments").addEventListener("click", on_hidecomments);
document.getElementById("fullscreen").addEventListener("click", on_fullscreen);
var vol = document.getElementById("volume");
vol.min = 0;
vol.max = 1;
vol.step = 0.01;
vol.addEventListener("input", video_volume);
video.addEventListener("volumechange", update_controls);
video.addEventListener("timeupdate", update_time);
//video.addEventListener("stalled", function() {console.log("stalled");});
//video.addEventListener("playing", function() {console.log("playing");});
document.getElementById("chat_msg").focus();
}
function send_msg(msg) {
console.log(">> " + msg);
s.send(msg);
}
function enable_chat() {
antiflood = false;
document.getElementById("sendchat").disabled = false;
}
function on_send(e) {
e.preventDefault();
if(!is_connected) return;
if(antiflood) return;
var msg = document.getElementById("chat_msg");
var msg_str = msg.value.trim().substr(0, MAXCHAR);
var send = document.getElementById("sendchat");
var colors = document.getElementById("colors");
if(!msg_str) return;
if(is_connected) send_msg("MSG:" + colors.value + ":" + escapeColon(msg_str));
show_chat(msg_str, colors.value, true);
show_chatbox(msg_str, "own");
if(is_fullscreen) fullscreen_clear();
msg.value = "";
antiflood = true;
send.disabled = true;
setTimeout(enable_chat, FLOOD_TIME);
}
window.addEventListener("load", start);
window.onfocus = function() {focused = true;};
window.onblur = function() {focused = false;};
window.addEventListener ("keydown", function (e) {
if (e.ctrlKey && e.key === ",") {
console.log("Showing mod panel");
toggle_modpanel();
}
});
document.addEventListener("fullscreenchange", fullscreen_event);
document.addEventListener("mozfullscreenchange", fullscreen_event);
document.addEventListener("webkitfullscreenchange", fullscreen_event);
document.addEventListener("msfullscreenchange", fullscreen_event);
function enable_modpanel(val, name) {
mod = val;
mod_name = name;
document.getElementById("txt_psk").disabled = val;
document.getElementById("btn_psk").textContent = val ? "Salir" : "Identificarse";
document.getElementById("txt_notice").disabled = !val;
document.getElementById("btn_notice").disabled = !val;
document.getElementById("chk_showname").disabled = !val;
document.getElementById("txt_mod").disabled = !val;
document.getElementById("btn_kick").disabled = !val;
document.getElementById("btn_ban").disabled = !val;
document.getElementById("txt_title").disabled = !val;
document.getElementById("btn_title").disabled = !val;
document.getElementById("lbl_subtitle").textContent = name ? "Identificado como: " + name : "Sin permisos"
}
function toggle_modpanel() {
if(modpanel == null) {
modpanel = document.createElement("div");
modpanel.className = "modpanel";
modpanel.style.display = "none";
var title = document.createElement("h3");
title.textContent = "Panel de streamer";
modpanel.appendChild(title);
var subtitle = document.createElement("h4");
subtitle.id = "lbl_subtitle";
subtitle.textContent = "Sin permisos";
modpanel.appendChild(subtitle);
var line1 = document.createElement("div");
var line2 = document.createElement("div");
var line3 = document.createElement("div");
var line4 = document.createElement("div");
line1.appendChild(document.createTextNode("PSK: "));
var txt_psk = document.createElement("input");
txt_psk.id = "txt_psk";
txt_psk.type = "password";
txt_psk.size = "20";
txt_psk.addEventListener("keydown", function(e) {if (e.keyCode === 13) btn_psk.click();});
line1.appendChild(txt_psk);
var btn_psk = document.createElement("button");
btn_psk.id = "btn_psk";
btn_psk.type = "button";
btn_psk.textContent = "Identificarse";
btn_psk.onclick = function() { if(txt_psk.value && is_connected) {send_msg(mod ? "LOGOUT" : "LOGIN:" + txt_psk.value); txt_psk.value = "";} };
line1.appendChild(btn_psk);
line2.appendChild(document.createTextNode("Noticia: "));
var txt_notice = document.createElement("input");
txt_notice.id = "txt_notice";
txt_notice.type = "text";
txt_notice.size = "40";
txt_notice.maxlength = "80";
txt_notice.disabled = true;
txt_notice.addEventListener("keydown", function(e) {if (e.keyCode === 13) btn_notice.click();});
line2.appendChild(txt_notice);
var chk_showname = document.createElement("input");
chk_showname.id = "chk_showname";
chk_showname.type = "checkbox";
chk_showname.disabled = true;
var lbl_showname = document.createElement("label");
lbl_showname.appendChild(chk_showname);
var lbl_lbl = document.createElement("small");
lbl_lbl.textContent = "Usar nombre";
lbl_showname.appendChild(lbl_lbl);
line2.appendChild(lbl_showname);
var btn_notice = document.createElement("button");
btn_notice.id = "btn_notice";
btn_notice.type = "button";
btn_notice.disabled = true;
btn_notice.textContent = "Enviar";
btn_notice.onclick = function() { if(txt_notice.value && is_connected) {
var msg = txt_notice.value;
var showname = chk_showname.checked;
send_msg("NOTICE:" + (showname?"1":"0") + ":" + escapeColon(msg));
show_notice((showname?mod_name:""), msg);
show_chatbox((showname ? "["+mod_name+"] "+msg : msg), "mod");
txt_notice.value = "";
}};
line2.appendChild(btn_notice);
line3.appendChild(document.createTextNode("Moderación: "));
var txt_mod = document.createElement("input");
txt_mod.id = "txt_mod";
txt_mod.type = "text";
txt_mod.disabled = true;
line3.appendChild(txt_mod);
var btn_kick = document.createElement("button");
btn_kick.id = "btn_kick";
btn_kick.type = "button";
btn_kick.disabled = true;
btn_kick.textContent = "Kickear";
btn_kick.onclick = function() { if(txt_mod.value && is_connected) {send_msg("KICK:" + txt_mod.value); txt_mod.value = "";} };
line3.appendChild(btn_kick);
var btn_ban = document.createElement("button");
btn_ban.id = "btn_ban";
btn_ban.type = "button";
btn_ban.disabled = true;
btn_ban.textContent = "Banear";
line3.appendChild(btn_ban);
line4.appendChild(document.createTextNode("Título: "));
var txt_title = document.createElement("input");
txt_title.id = "txt_title";
txt_title.type = "text";
txt_title.size = "30";
txt_title.maxlength = "35";
txt_title.disabled = true;
txt_title.addEventListener("keydown", function(e) {if (e.keyCode === 13) btn_title.click();});
line4.appendChild(txt_title);
var btn_title = document.createElement("button");
btn_title.id = "btn_title";
btn_title.type = "button";
btn_title.disabled = true;
btn_title.textContent = "Cambiar";
btn_title.onclick = function() {
if(is_connected) send_msg("SETTITLE:" + escapeColon(txt_title.value));
set_title(txt_title.value);
txt_title.value = "";
};
line4.appendChild(btn_title);
modpanel.appendChild(line1);
modpanel.appendChild(line2);
modpanel.appendChild(line3);
modpanel.appendChild(line4);
document.getElementById("bottompanel").appendChild(modpanel);
}
modpanel.style.display = (modpanel.style.display == "block" ? "none" : "block");
}