Greasy Fork镜像 支持简体中文。

Youtube AdBlock Bypass

Bypass Youtube Adblock

目前為 2024-10-03 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Youtube AdBlock Bypass
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Bypass Youtube Adblock
  6. // @author JJJ
  7. // @match https://www.youtube.com/*
  8. // @match https://www.youtube-nocookie.com/*
  9. // @exclude https://www.youtube.com/*/community
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  11. // @grant none
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. 'use strict';
  17.  
  18. const CONFIG = {
  19. IFRAME_ID: 'adblock-bypass-iframe',
  20. RETRY_DELAY_MS: 200,
  21. MAX_RETRIES: 100,
  22. DUPLICATE_CLEANUP_INTERVAL_MS: 5000
  23. };
  24.  
  25. const SELECTORS = {
  26. PLAYABILITY_ERROR: '.yt-playability-error-supported-renderers',
  27. ERROR_SCREEN_CONTAINER: '#error-screen',
  28. VIDEO_PLAYER_CONTAINER: '#movie_player'
  29. };
  30.  
  31. let currentUrl = window.location.href;
  32. let retryCount = 0;
  33.  
  34. // URL Utilities
  35. const urlUtils = {
  36. extractParams(url) {
  37. try {
  38. const params = new URL(url).searchParams;
  39. return {
  40. videoId: params.get('v'),
  41. playlistId: params.get('list'),
  42. index: params.get('index')
  43. };
  44. } catch (e) {
  45. console.error('Failed to extract URL parameters:', e);
  46. return {};
  47. }
  48. },
  49.  
  50. getTimestampFromUrl(url) {
  51. try {
  52. const timestamp = new URL(url).searchParams.get('t');
  53. if (timestamp) {
  54. const timeArray = timestamp.split(/h|m|s/).map(Number);
  55. const timeInSeconds = timeArray.reduce((acc, time, index) =>
  56. acc + time * Math.pow(60, 2 - index), 0);
  57. return `&start=${timeInSeconds}`;
  58. }
  59. } catch (e) {
  60. console.error('Failed to extract timestamp:', e);
  61. }
  62. return '';
  63. }
  64. };
  65.  
  66. // Player Management
  67. const playerManager = {
  68. createIframe(url) {
  69. const { videoId, playlistId, index } = urlUtils.extractParams(url);
  70. if (!videoId) return null;
  71.  
  72. const iframe = document.createElement('iframe');
  73. const commonArgs = 'autoplay=1&modestbranding=1';
  74. const embedUrl = playlistId
  75. ? `https://www.youtube-nocookie.com/embed/${videoId}?${commonArgs}&list=${playlistId}&index=${index}`
  76. : `https://www.youtube-nocookie.com/embed/${videoId}?${commonArgs}${urlUtils.getTimestampFromUrl(url)}`;
  77.  
  78. this.setIframeAttributes(iframe, embedUrl);
  79. return iframe;
  80. },
  81.  
  82. setIframeAttributes(iframe, url) {
  83. iframe.id = CONFIG.IFRAME_ID;
  84. iframe.src = url;
  85. iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share';
  86. iframe.allowFullscreen = true;
  87. iframe.style.cssText = 'height:100%; width:100%; border:none; border-radius:12px;';
  88. },
  89.  
  90. replacePlayer(url) {
  91. const errorScreenContainer = document.querySelector(SELECTORS.ERROR_SCREEN_CONTAINER);
  92. if (!errorScreenContainer) return;
  93.  
  94. let iframe = document.getElementById(CONFIG.IFRAME_ID);
  95. if (iframe) {
  96. this.setIframeAttributes(iframe, url);
  97. } else {
  98. iframe = this.createIframe(url);
  99. if (iframe) {
  100. errorScreenContainer.appendChild(iframe);
  101. }
  102. }
  103. this.bringToFront(CONFIG.IFRAME_ID);
  104. },
  105.  
  106. bringToFront(elementId) {
  107. const element = document.getElementById(elementId);
  108. if (element) {
  109. const maxZIndex = Math.max(
  110. ...Array.from(document.querySelectorAll('*'))
  111. .map(e => parseInt(window.getComputedStyle(e).zIndex) || 0)
  112. );
  113. element.style.zIndex = maxZIndex + 1;
  114. }
  115. },
  116.  
  117. removeDuplicateIframes() {
  118. const iframes = document.querySelectorAll(`#${CONFIG.IFRAME_ID}`);
  119. if (iframes.length > 1) {
  120. Array.from(iframes).slice(1).forEach(iframe => iframe.remove());
  121. }
  122. }
  123. };
  124.  
  125. // Event Handlers
  126. function handleAdBlockError() {
  127. const playabilityError = document.querySelector(SELECTORS.PLAYABILITY_ERROR);
  128. if (playabilityError) {
  129. playabilityError.remove();
  130. playerManager.replacePlayer(window.location.href);
  131. } else if (retryCount < CONFIG.MAX_RETRIES) {
  132. retryCount++;
  133. setTimeout(handleAdBlockError, CONFIG.RETRY_DELAY_MS);
  134. }
  135. }
  136.  
  137. // Event Listeners
  138. function setupEventListeners() {
  139. window.addEventListener('beforeunload', () => {
  140. currentUrl = window.location.href;
  141. });
  142.  
  143. document.addEventListener('yt-navigate-finish', () => {
  144. const newUrl = window.location.href;
  145. if (newUrl !== currentUrl) {
  146. if (newUrl.endsWith('.com/')) {
  147. const iframe = document.getElementById(CONFIG.IFRAME_ID);
  148. iframe?.remove();
  149. } else {
  150. playerManager.replacePlayer(newUrl);
  151. }
  152. currentUrl = newUrl;
  153. }
  154. });
  155.  
  156. // Using MutationObserver for efficient DOM change detection
  157. const observer = new MutationObserver((mutations) => {
  158. for (let mutation of mutations) {
  159. if (mutation.type === 'childList') {
  160. for (let node of mutation.addedNodes) {
  161. if (node.nodeType === Node.ELEMENT_NODE &&
  162. node.matches(SELECTORS.PLAYABILITY_ERROR)) {
  163. handleAdBlockError();
  164. return;
  165. }
  166. }
  167. }
  168. }
  169. });
  170. observer.observe(document.body, { childList: true, subtree: true });
  171. }
  172.  
  173. // Initialize
  174. function initialize() {
  175. setupEventListeners();
  176. handleAdBlockError();
  177. setInterval(() => playerManager.removeDuplicateIframes(), CONFIG.DUPLICATE_CLEANUP_INTERVAL_MS);
  178. }
  179.  
  180. initialize();
  181. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址