Super Duolingo Ad Blocker

Block ads and unwanted promotional content on Duolingo, including dynamically named ad classes, while preserving essential lesson content and handling fullscreen ads by pressing the exit button automatically or selecting "No Thanks" on specific ads.

  1. // ==UserScript==
  2. // @name Super Duolingo Ad Blocker
  3. // @version 1.0
  4. // @description Block ads and unwanted promotional content on Duolingo, including dynamically named ad classes, while preserving essential lesson content and handling fullscreen ads by pressing the exit button automatically or selecting "No Thanks" on specific ads.
  5. // @author Zinovia
  6. // @match https://*.duolingo.com/*
  7. // @grant none
  8. // @namespace https://gf.qytechs.cn/users/1340999
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. // Function to inject CSS into the document
  15. function addStyles(css) {
  16. const style = document.createElement('style');
  17. style.type = 'text/css';
  18. style.textContent = css;
  19. document.head.appendChild(style);
  20. }
  21.  
  22. // CSS to hide specific promotional and ad content
  23. const styles = `
  24. /* Specific divs associated with ads and promotions, conditional on not being essential content */
  25. div[data-test="purchase-step-active"],
  26. div._3D_HB,
  27. div._16rRh,
  28. div._16rRh._2cnFr._1T_BQ,
  29. div._1tzFd,
  30. div._1Qh5D._36g4N._2YF0P.uapW2,
  31. div._3ZUrl._2BflZ,
  32. div.MGk8p,
  33. div._3ywWe,
  34. div._1145W,
  35. div.Vm8CO._2zxQ8,
  36. iframe[name="__privateStripeController7431"] {
  37. display: none !important;
  38. }
  39. `;
  40.  
  41. // Inject styles into the document
  42. addStyles(styles);
  43.  
  44. // Function to dynamically hide elements
  45. function hideElements() {
  46. const selectors = [
  47. 'div[data-test="purchase-step-active"]',
  48. 'div._3D_HB',
  49. 'div._16rRh',
  50. 'div._16rRh._2cnFr._1T_BQ',
  51. 'div._1tzFd',
  52. 'div._1Qh5D._36g4N._2YF0P.uapW2',
  53. 'div._3ZUrl._2BflZ',
  54. 'div.MGk8p',
  55. 'div._3ywWe',
  56. 'div._1145W',
  57. 'div.Vm8CO._2zxQ8',
  58. 'iframe[name="__privateStripeController7431"]'
  59. ];
  60.  
  61. selectors.forEach(selector => {
  62. document.querySelectorAll(selector).forEach(element => {
  63. if (!element.closest('#session/PlayerFooter') &&
  64. !element.closest('div._1QQhE') &&
  65. !element.closest('div._3rB4d._1VTif._2HXQ9')) { // Ensure essential content is not hidden
  66. element.style.display = 'none';
  67. }
  68. });
  69. });
  70. }
  71.  
  72. // Function to press the exit button on fullscreen ads
  73. function pressExitButton() {
  74. const exitButton = document.querySelector('._3vGNs._2YF0P._1Udkq');
  75. if (exitButton) {
  76. exitButton.click();
  77. console.log('Fullscreen ad exit button clicked!');
  78. }
  79. }
  80.  
  81. // Function to click the "No Thanks" button on the new type of full-screen ad
  82. function pressNoThanksButton() {
  83. const noThanksButton = document.querySelector('button._1Qh5D._36g4N._2YF0P._76ebC._3h0lA._1S2uf.cnGdv');
  84. if (noThanksButton) {
  85. noThanksButton.click();
  86. console.log('No Thanks button clicked!');
  87. }
  88. }
  89.  
  90. // Function to click the button in the lesson
  91. function clickLessonButton() {
  92. const button = document.querySelector('._3vGNs._2YF0P._1Udkq');
  93. if (button) {
  94. button.click();
  95. console.log('Lesson button clicked!');
  96. }
  97. }
  98.  
  99. // Function to handle the blank screen issue
  100. function handleBlankScreen() {
  101. const continueButton = document.querySelector('button[data-test="player-next"]');
  102. if (continueButton) {
  103. continueButton.click();
  104. console.log('Continue button clicked!');
  105. }
  106. const reviewLessonButton = document.querySelector('button span._1o-YO:contains("Review lesson")');
  107. if (reviewLessonButton) {
  108. reviewLessonButton.click();
  109. console.log('Review lesson button clicked!');
  110. }
  111. }
  112.  
  113. // Run initial functions
  114. hideElements();
  115. pressExitButton();
  116. pressNoThanksButton();
  117. clickLessonButton();
  118. handleBlankScreen();
  119.  
  120. // Observe DOM changes and apply modifications as necessary
  121. const observer = new MutationObserver((mutations) => {
  122. mutations.forEach((mutation) => {
  123. if (mutation.type === 'childList') {
  124. hideElements();
  125. pressExitButton();
  126. pressNoThanksButton();
  127. clickLessonButton();
  128. handleBlankScreen();
  129. }
  130. });
  131. });
  132.  
  133. // Start observing the body for child list changes
  134. observer.observe(document.body, {
  135. childList: true,
  136. subtree: true
  137. });
  138.  
  139. console.log('Super Duolingo Ad Blocker initialized.');
  140. })();

QingJ © 2025

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