canopy/www/js/channel/channel.js

180 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
class channel{
constructor(){
//Establish connetion to the server via socket.io
this.connect();
//Define socket listeners
this.defineListeners();
//Flag youtube iframe-embed api as unloaded
this.ytEmbedAPILoaded = false;
//Scrape channel name off URL
this.channelName = window.location.pathname.split('/c/')[1].split('/')[0];
//Create the Video Player Object
this.player = new player(this);
//Create the Chat Box Object
this.chatBox = new chatBox(this);
//Create the User List Object
this.userList = new userList(this);
//Create the Canopy Panel Object
this.cPanel = new cPanel(this);
//Set defaults for any unset settings and run any required process steps for the current config
this.setDefaults(false, true);
//Freak out any weirdos who take a peek in the dev console for gaffs
console.log("👁️👄👁️ 𝓊𝓃𝒿𝓊𝓇.");
}
connect(){
this.socket = io({
extraHeaders: {
//Include CSRF token
'x-csrf-token': utils.ajax.getCSRFToken()
}
});
}
defineListeners(){
this.socket.on("connect", () => {
document.title = `${this.channelName} - Connected`
});
this.socket.on("kick", async (data) => {
if(data.reason == "Invalid CSRF Token!"){
//Reload the CSRF token
await utils.ajax.reloadCSRFToken();
//Retry the connection
this.connect();
}else{
new canopyUXUtils.popup(`You have been ${data.type} from the channel for the following reason:<br>${data.reason}`);
}
});
this.socket.on("clientMetadata", this.handleClientInfo.bind(this));
this.socket.on("error", utils.ux.displayResponseError);
this.socket.on("queue", (data) => {
this.queue = new Map(data.queue);
});
this.socket.on("lock", (data) => {
this.queueLock = data.locked;
});
}
handleClientInfo(data){
//Ingest user data
this.user = data.user;
//Re-hydrate permission maps
this.user.permMap.site = new Map(data.user.permMap.site);
this.user.permMap.chan = new Map(data.user.permMap.chan);
//Tell the chatbox to handle client info
//should it have its own event listener instead? Guess it's a stylistic choice :P
this.chatBox.handleClientInfo(data);
//Store queue for use by the queue panel
this.queue = new Map(data.queue);
//Store queue lock status
this.queueLock = data.queueLock;
}
setDefaults(force = false, processConfig = false){
//Iterate through default config
for(let [key, value] of channel.defaultConfig){
//If the setting is unset or function was called forcefully
if(force || localStorage.getItem(key) == null){
//Set item from default map
localStorage.setItem(key, value);
}
//If we're running process steps for the config
if(processConfig){
//Process the current config value
this.processConfig(key, localStorage.getItem(key));
}
}
}
processConfig(key, value){
//Switch/case by config key
switch(key){
case 'ytPlayerType':
const embedScript = document.querySelector(".yt-embed-api");
//If the user is running the embedded player and we don't have en embed script loaded
if(value == 'embed' && embedScript == null){
//Find our footer
const footer = document.querySelector('footer');
//Create new script tag
const ytEmbedAPI = document.createElement('script');
//Link the iframe api from youtube
ytEmbedAPI.src = "https://www.youtube.com/iframe_api";
//set the iframe api script id
ytEmbedAPI.classList.add('yt-embed-api');
//Append the script tag to the top of the footer to give everything else access
footer.prepend(ytEmbedAPI);
//If we're not using the embed player but the script is loaded
}else if(embedScript != null){
//Pull all scripts since the main one might have pulled others
const scripts = document.querySelectorAll('script');
//Iterate through all script tags on the page
for(let script of scripts){
//If the script came from youtube
if(script.src.match(/youtube\.com|youtu\.be/)){
//Rip it out
script.remove();
}
}
}
//Stop while we're ahead
return;
}
}
static defaultConfig = new Map([
["ytPlayerType","raw"]
]);
}
//Youtube iframe-embed API load handler
function onYouTubeIframeAPIReady(){
//Set embed api to true
client.ytEmbedAPILoaded = true;
//Get currently playing item
const nowPlaying = client.player.mediaHandler.nowPlaying;
//If we're playing a youtube video and the official embeds are enabled
if(nowPlaying.type == 'yt' && localStorage.getItem('ytPlayerType') == "embed"){
//Restart the video now that the embed api has loaded
client.player.start({media: nowPlaying});
}
}
const client = new channel();