Better DGG Kick Embed

I CANNOT GUARANTEE THIS WILL WORK ON EVERY BROWSER/USERSCRIPT RUNNER COMBINATION. Hacky solution to embed full kick site instead of the embed. I can't promise it will continue to work indefinitely. If it bugs out when resizing the window, try refreshing the page.

  1. // ==UserScript==
  2. // @name Better DGG Kick Embed
  3. // @namespace yuniDev.kickembed
  4. // @match https://kick.com/*
  5. // @match https://www.destiny.gg/bigscreen
  6. // @match https://destiny.gg/bigscreen
  7. // @grant none
  8. // @version 1.3
  9. // @license MIT
  10. // @author yuniDev
  11. // @run-at document-idle
  12. // @description I CANNOT GUARANTEE THIS WILL WORK ON EVERY BROWSER/USERSCRIPT RUNNER COMBINATION. Hacky solution to embed full kick site instead of the embed. I can't promise it will continue to work indefinitely. If it bugs out when resizing the window, try refreshing the page.
  13. // ==/UserScript==
  14.  
  15. let prevHash = "";
  16.  
  17. function htmlToNode(html) {
  18. const template = document.createElement('template');
  19. template.innerHTML = html;
  20. return template.content.firstChild;
  21. }
  22.  
  23. function hideElObserver(selector) {
  24. function checkAndHide(obs) {
  25. const elToHide = document.querySelector(selector);
  26. if (elToHide) {
  27. elToHide.style.display = 'none';
  28. obs.disconnect();
  29. }
  30. }
  31. const observer = new MutationObserver((_, obs) => checkAndHide(obs));
  32. observer.observe(document.body, { childList: true, subtree: true });
  33. checkAndHide(observer);
  34. }
  35.  
  36. function hideSurroundings() {
  37. [...document.querySelectorAll("nav")].forEach(el => el.style = "display: none;");
  38.  
  39. hideElObserver("#channel-chatroom");
  40. hideElObserver("#sidebar-wrapper");
  41. hideElObserver("#channel-content");
  42.  
  43. const injectedChannelPlayer = document.getElementById("injected-channel-player");
  44. if (injectedChannelPlayer) {
  45. injectedChannelPlayer.style = "padding: 0px; max-height: max-content;";
  46. injectedChannelPlayer.parentNode.style = "max-height: max-content;";
  47. }
  48.  
  49. const bodyChild = document.body.firstChild;
  50. if (bodyChild) {
  51. bodyChild.style = "height: min-content;";
  52. [...bodyChild.children].forEach(el => el.style = el.getAttribute("style") ?? "" + ";padding-top: 0px;");
  53. }
  54. document.body.style = "height: min-content;";
  55.  
  56. hideElObserver(".z-modal:has(button[data-testid='accept-cookies'])");
  57. }
  58.  
  59. function loadDestinyGG() {
  60. const { hash } = window.location;
  61.  
  62. if (prevHash.startsWith("#kick/") && !hash.startsWith("#kick")) location.reload(); // Reload page if switching away from kick embed
  63. prevHash = hash;
  64.  
  65. // Check if the URL starts with the desired base
  66. const isValidStart = hash.startsWith("#kick/") && window.location.pathname === "/bigscreen";
  67.  
  68. // Extract the channel name
  69. const channel = isValidStart ? hash.split("/")[1] : null;
  70.  
  71. if (channel && isValidStart) { // We are watching a kick embed on Destiny.gg
  72. document.body.appendChild(htmlToNode(`<script type="module" src="https://unpkg.com/x-frame-bypass"></script>`));
  73. const targetUrl = `https://kick.com/${channel}`;
  74.  
  75. id = setInterval(() => {
  76. const embedContainer = document.getElementById("embed");
  77. const existingIframe = embedContainer.querySelector(".embed-frame");
  78. if (!existingIframe) return;
  79.  
  80. existingIframe.remove();
  81.  
  82. clearInterval(id);
  83.  
  84. const iframe = htmlToNode(`<iframe is="x-frame-bypass" class="embed-frame" src="${targetUrl}" allow="fullscreen; autoplay; encrypted-media; picture-in-picture; web-share"></iframe>`);
  85. embedContainer.appendChild(iframe);
  86. iframe.contentDocument.location.reload();
  87. }, 100);
  88. }
  89. }
  90.  
  91. if (window.location.hostname === "kick.com" && window.self !== window.top) { // Kick inside of iframe
  92. hideSurroundings();
  93. setInterval(() => {
  94. if (![...document.querySelectorAll("nav")].find(el => el.getAttribute("style") && el.getAttribute("style").indexOf("display: none") > -1)) hideSurroundings();
  95. }, 200);
  96. } else {
  97. setTimeout(() => {
  98. loadDestinyGG();
  99. addEventListener('hashchange', loadDestinyGG);
  100. }, 100);
  101. }