// ==UserScript== // @name Better DGG Kick Embed // @namespace yuniDev.kickembed // @match https://kick.com/* // @match https://www.destiny.gg/bigscreen // @match https://destiny.gg/bigscreen // @grant GM.registerMenuCommand // @grant GM.setValue // @grant GM.getValue // @version 1.5 // @license MIT // @author yuniDev // @run-at document-idle // @description Slightly hacky solution to embed full kick site instead of the embed. You can toggle kick chat on and off next to the script toggle in your userscript host extension. // @downloadURL none // ==/UserScript== let showChat = false; GM.getValue("show-chat", "false").then(value => showChat = value === "true"); function htmlToNode(html) { const template = document.createElement('template'); template.innerHTML = html; return template.content.firstChild; } function hideFunc(el) { el.style.display = 'none'; } function addObserver(selector, func = hideFunc) { function checkAndHide(obs) { const elToHide = document.querySelector(selector); if (elToHide) { func(elToHide); obs.disconnect(); } } const observer = new MutationObserver((_, obs) => checkAndHide(obs)); observer.observe(document.body, { childList: true, subtree: true }); checkAndHide(observer); } function hideSurroundings() { addObserver("[data-sidebar]", el => { el.setAttribute("data-sidebar", false); el.setAttribute("data-theatre", true); el.setAttribute("data-chat", showChat); }); addObserver(".z-controls.hidden button", el => el.parentNode.style.display = 'none'); addObserver("#channel-chatroom > div:first-child", el => el.style.display = 'none'); addObserver(".z-modal:has(button[data-testid='accept-cookies'])"); } function updateEmbed() { const iframe = document.querySelector("iframe.embed-frame"); const iframeLocation = iframe.src; let channel = null; if (iframeLocation.includes("player.kick")) { channel = iframeLocation.split('/').pop(); } else if (window.location.hash.startsWith("#kick/")) { channel = window.location.hash.split('/')[1]; } if (!iframe || !channel) return; iframe.src = `https://kick.com/${channel}`; iframe.setAttribute("src", `https://kick.com/${channel}`); iframe.setAttribute("is", "x-frame-bypass"); } function loadDGG(channel) { document.body.appendChild(htmlToNode(``)); function embedObserver(list, obs) { for (const mutation of list) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'IFRAME' && node.classList.contains('embed-frame')) updateEmbed(); } } } } const observer = new MutationObserver((obj, obs) => embedObserver(obj, obs)); observer.observe(document.getElementById("embed"), { childList: true, subtree: true }); updateEmbed(); function clearObserver() { observer.disconnect(); removeEventListener('hashchange', clearObserver); } addEventListener('hashchange', clearObserver); } async function toggleKickChat() { let showChat = (await GM.getValue("show-chat", "false")) === "true"; showChat = !showChat; await GM.setValue("show-chat", String(showChat)); const iframe = document.querySelector("iframe.embed-frame"); iframe.contentWindow.postMessage({ type: "yuniDev.kickembed.show-chat", value: showChat }, "*"); } function setupChatToggleCallback() { window.addEventListener("message", ({ data }) => { console.log("Recieved", data); const { type, value } = data; if (type == "yuniDev.kickembed.show-chat") { showChat = value; document.body.querySelector("[data-sidebar]").setAttribute("data-chat", value); } }); } if (window.location.hostname === "kick.com" && window.self !== window.top) { // Kick inside of iframe hideSurroundings(); setInterval(() => { if (![...document.querySelectorAll("nav")].find(el => el.getAttribute("style") && el.getAttribute("style").indexOf("display: none") > -1)) hideSurroundings(); }, 200); setupChatToggleCallback(); } else if (window.location.pathname === "/bigscreen") { loadDGG(); addEventListener('hashchange', loadDGG); GM.registerMenuCommand("Toggle Kick Chat", toggleKickChat); }