YouTube iFrame AdBlocker

Bypass YouTube's ad-blocker detection by dynamically replacing the video player with an iframe.

当前为 2023-10-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube iFrame AdBlocker
  3. // @namespace Booth-Stash
  4. // @license MIT
  5. // @version 1.0
  6. // @description Bypass YouTube's ad-blocker detection by dynamically replacing the video player with an iframe.
  7. // @author ils94
  8. // @match https://www.youtube.com/*
  9. // @grant none
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13. // Utility functions
  14. function getAutoplayState() {
  15. return localStorage.getItem('autoplayNext') === 'true';
  16. }
  17. function setAutoplayState(state) {
  18. localStorage.setItem('autoplayNext', state.toString());
  19. }
  20. function toggleAutoplayState(button) {
  21. const autoplayNext = !getAutoplayState();
  22. setAutoplayState(autoplayNext);
  23. button.title = autoplayNext ? 'Autoplay is on' : 'Autoplay is off';
  24. button.setAttribute('aria-label', autoplayNext ? 'Autoplay is on' : 'Autoplay is off');
  25. button.querySelector('.ytp-autonav-toggle-button').setAttribute('aria-checked', autoplayNext.toString());
  26. return autoplayNext;
  27. }
  28. function isVideoEnded(iframeDoc) {
  29. return iframeDoc.querySelector('.html5-endscreen.ytp-show-tiles') !== null;
  30. }
  31. // Main script
  32. function replaceElement(oldElement) {
  33. const urlParams = new URLSearchParams(window.location.search);
  34. const videoId = urlParams.get('v');
  35. if (!videoId) {
  36. console.error('Video ID not found in URL');
  37. return;
  38. }
  39. console.log(`Video ID: ${videoId}`);
  40. console.log('Old element found');
  41. // Calculate the size based on the current screen size
  42. const screenWidth = window.innerWidth;
  43. const screenHeight = window.innerHeight;
  44. // Set the width and height to 75% of the screen size
  45. const newWidth = screenWidth * 0.75;
  46. const newHeight = screenHeight * 0.75;
  47. // Create a container element for the iframe
  48. const container = document.createElement('div');
  49. container.style.width = newWidth + 'px';
  50. container.style.height = newHeight + 'px';
  51. container.style.margin = "0 auto"; // Center the container
  52. container.style.position = "relative"; // Position the container relative to the page
  53. // Create the close button
  54. const closeButton = document.createElement('button');
  55. closeButton.textContent = 'YouTube Home';
  56. closeButton.style.position = 'absolute';
  57. closeButton.style.top = '5px';
  58. closeButton.style.right = '5px';
  59. closeButton.style.zIndex = '9999';
  60. closeButton.addEventListener('click', () => {
  61. window.location.href = 'https://www.youtube.com'; // Redirect to YouTube.com
  62. });
  63. // Create the iframe element
  64. const newElement = document.createElement('iframe');
  65. newElement.width = '100%';
  66. newElement.height = '100%';
  67. newElement.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
  68. newElement.title = 'YouTube video player';
  69. newElement.frameBorder = '0';
  70. newElement.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share';
  71. newElement.allowFullscreen = true;
  72. // Append the iframe and close button to the container
  73. container.appendChild(closeButton);
  74. container.appendChild(newElement);
  75. // Replace the old element with the container
  76. oldElement.parentNode.replaceChild(container, oldElement);
  77. console.log('Element replaced successfully');
  78. newElement.onload = () => {
  79. const iframeDoc = newElement.contentDocument;
  80. const refButton = iframeDoc.querySelector('.ytp-subtitles-button');
  81. const youtubeButton = iframeDoc.querySelector('.ytp-youtube-button');
  82. if (youtubeButton) {
  83. youtubeButton.parentNode.removeChild(youtubeButton);
  84. } else {
  85. console.error('YouTube button not found');
  86. }
  87. if (refButton) {
  88. const autoPlayButton = document.createElement('button');
  89. autoPlayButton.className = 'ytp-button';
  90. autoPlayButton.setAttribute('data-priority', '2');
  91. autoPlayButton.setAttribute('data-tooltip-target-id', 'ytp-autonav-toggle-button');
  92. autoPlayButton.title = getAutoplayState() ? 'Autoplay is on' : 'Autoplay is off';
  93. autoPlayButton.setAttribute('aria-label', getAutoplayState() ? 'Autoplay is on' : 'Autoplay is off');
  94. autoPlayButton.innerHTML = `
  95. <div class="ytp-autonav-toggle-button-container">
  96. <div class="ytp-autonav-toggle-button" aria-checked="${getAutoplayState().toString()}"></div>
  97. </div>
  98. `;
  99. refButton.parentNode.insertBefore(autoPlayButton, refButton.nextSibling);
  100. autoPlayButton.addEventListener('click', () => {
  101. const isAutoplayOn = toggleAutoplayState(autoPlayButton);
  102. if (isAutoplayOn && isVideoEnded(iframeDoc)) {
  103. playNextVideo();
  104. }
  105. });
  106. } else {
  107. console.error('Reference button not found');
  108. }
  109. const endScreenObserver = new MutationObserver((mutations) => {
  110. for (const mutation of mutations) {
  111. if (mutation.target.classList.contains('ytp-show-tiles') && getAutoplayState()) {
  112. playNextVideo();
  113. break;
  114. }
  115. }
  116. });
  117. endScreenObserver.observe(iframeDoc, { attributes: true, subtree: true, attributeFilter: ['class'] });
  118. };
  119. }
  120. function playNextVideo() {
  121. const rendererElements = document.querySelectorAll('ytd-compact-video-renderer');
  122. for (let rendererElement of rendererElements) {
  123. if (!rendererElement.querySelector('ytd-compact-radio-renderer')) {
  124. const nextVideoLink = rendererElement.querySelector('a#thumbnail');
  125. if (nextVideoLink && nextVideoLink.href) {
  126. const autoplayURL = new URL(nextVideoLink.href);
  127. autoplayURL.searchParams.set('autoplay', '1');
  128. console.log(`Found next video link: ${autoplayURL.href}`);
  129. window.location.href = autoplayURL.href;
  130. return;
  131. }
  132. }
  133. }
  134. console.error('Next video link not found');
  135. }
  136. const observer = new MutationObserver((mutationsList) => {
  137. for (let mutation of mutationsList) {
  138. if (mutation.addedNodes.length) {
  139. for (let node of mutation.addedNodes) {
  140. if (node.nodeName.toLowerCase() === 'ytd-enforcement-message-view-model') {
  141. replaceElement(node);
  142. }
  143. }
  144. }
  145. }
  146. });
  147. observer.observe(document, { childList: true, subtree: true });
  148. })();