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.
// ==UserScript==
// @name Super Duolingo Ad Blocker
// @version 1.0
// @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.
// @author Zinovia
// @match https://*.duolingo.com/*
// @grant none
// @namespace https://greasyfork.org/users/1340999
// ==/UserScript==
(function() {
'use strict';
// Function to inject CSS into the document
function addStyles(css) {
const style = document.createElement('style');
style.type = 'text/css';
style.textContent = css;
document.head.appendChild(style);
}
// CSS to hide specific promotional and ad content
const styles = `
/* Specific divs associated with ads and promotions, conditional on not being essential content */
div[data-test="purchase-step-active"],
div._3D_HB,
div._16rRh,
div._16rRh._2cnFr._1T_BQ,
div._1tzFd,
div._1Qh5D._36g4N._2YF0P.uapW2,
div._3ZUrl._2BflZ,
div.MGk8p,
div._3ywWe,
div._1145W,
div.Vm8CO._2zxQ8,
iframe[name="__privateStripeController7431"] {
display: none !important;
}
`;
// Inject styles into the document
addStyles(styles);
// Function to dynamically hide elements
function hideElements() {
const selectors = [
'div[data-test="purchase-step-active"]',
'div._3D_HB',
'div._16rRh',
'div._16rRh._2cnFr._1T_BQ',
'div._1tzFd',
'div._1Qh5D._36g4N._2YF0P.uapW2',
'div._3ZUrl._2BflZ',
'div.MGk8p',
'div._3ywWe',
'div._1145W',
'div.Vm8CO._2zxQ8',
'iframe[name="__privateStripeController7431"]'
];
selectors.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
if (!element.closest('#session/PlayerFooter') &&
!element.closest('div._1QQhE') &&
!element.closest('div._3rB4d._1VTif._2HXQ9')) { // Ensure essential content is not hidden
element.style.display = 'none';
}
});
});
}
// Function to press the exit button on fullscreen ads
function pressExitButton() {
const exitButton = document.querySelector('._3vGNs._2YF0P._1Udkq');
if (exitButton) {
exitButton.click();
console.log('Fullscreen ad exit button clicked!');
}
}
// Function to click the "No Thanks" button on the new type of full-screen ad
function pressNoThanksButton() {
const noThanksButton = document.querySelector('button._1Qh5D._36g4N._2YF0P._76ebC._3h0lA._1S2uf.cnGdv');
if (noThanksButton) {
noThanksButton.click();
console.log('No Thanks button clicked!');
}
}
// Function to click the button in the lesson
function clickLessonButton() {
const button = document.querySelector('._3vGNs._2YF0P._1Udkq');
if (button) {
button.click();
console.log('Lesson button clicked!');
}
}
// Function to handle the blank screen issue
function handleBlankScreen() {
const continueButton = document.querySelector('button[data-test="player-next"]');
if (continueButton) {
continueButton.click();
console.log('Continue button clicked!');
}
const reviewLessonButton = document.querySelector('button span._1o-YO:contains("Review lesson")');
if (reviewLessonButton) {
reviewLessonButton.click();
console.log('Review lesson button clicked!');
}
}
// Run initial functions
hideElements();
pressExitButton();
pressNoThanksButton();
clickLessonButton();
handleBlankScreen();
// Observe DOM changes and apply modifications as necessary
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
hideElements();
pressExitButton();
pressNoThanksButton();
clickLessonButton();
handleBlankScreen();
}
});
});
// Start observing the body for child list changes
observer.observe(document.body, {
childList: true,
subtree: true
});
console.log('Super Duolingo Ad Blocker initialized.');
})();