Skip to content

Instantly share code, notes, and snippets.

@25yeht
Last active October 31, 2024 18:11
Show Gist options
  • Save 25yeht/8d598b2daf9ec3d1a29af7ae0c1be407 to your computer and use it in GitHub Desktop.
Save 25yeht/8d598b2daf9ec3d1a29af7ae0c1be407 to your computer and use it in GitHub Desktop.
Block Ads Pretty Much All Ads On Websites!
javascript:
Object.defineProperties(function() {
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function rn(arr) {
const randomIndex = randomInt(0, arr.length - 1);
return arr[randomIndex];
}
function randomHtmlId(len = 10) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-';
let result = '';
for (let i = 0; i < len; i++) {
result += characters.charAt(randomInt(0, characters.length - 1));
}
while (/^\d/.test(result)) {
result = '';
for (let i = 0; i < len; i++) {
result += characters.charAt(randomInt(0, characters.length - 1));
}
}
return result;
}
const spoofedElements = [document.body];
const originalGetComputedStyle = getComputedStyle.bind(window);
const cloneNode = Node.prototype.cloneNode;
const adBlockingId = randomHtmlId();
const adBlockingStyleSheet = document.createElement("style");
const adBlockingStyles = "." + adBlockingId + "{ display: none !important; }";
adBlockingStyleSheet.textContent = adBlockingStyles;
var spoofedAdBlockingStyles = "";
const spoofAdBlockingStylesProperty = {
get: function() {
return spoofedAdBlockingStyles;
},
set: function(val) {
return spoofedAdBlockingStyles = String(val);
}
};
Object.defineProperty(adBlockingStyleSheet, "textContent", spoofAdBlockingStylesProperty);
Object.defineProperty(adBlockingStyleSheet, "innerHTML", spoofAdBlockingStylesProperty);
Object.defineProperty(adBlockingStyleSheet, "innerText", spoofAdBlockingStylesProperty);
Object.defineProperty(adBlockingStyleSheet, "outerText", spoofAdBlockingStylesProperty);
Object.defineProperty(adBlockingStyleSheet, "outerHTML", {
get: function() {
return "<style>" + spoofedAdBlockingStyles + "</style>";
},
set: function(val) {
return spoofedAdBlockingStyles = String(val);
}
});
document.head.appendChild(adBlockingStyleSheet);
const originalDisplays = new Map();
function spoofStyleDeclaration(result, elt) {
Object.defineProperty(result, "display", {
get: function() {
return originalDisplays.has(elt) ? originalDisplays.get(elt) : "block";
}
});
const realGPV = result.getPropertyValue.bind(result);
result.getPropertyValue = function(property) {
const result = realGPV(...arguments);
if(property === "display") return originalDisplays.has(elt) ? originalDisplays.get(elt) : "block";
return result;
};
return result;
}
getComputedStyle = function(elt, pseudoElt) {
const result = originalGetComputedStyle(...arguments);
if(pseudoElt) return result;
if(spoofedElements.includes(elt)) {
return spoofStyleDeclaration(result, elt);
}
return result;
};
getComputedStyle.toString = function() {
return "function getComputedStyle() { [native code] }";
};
getComputedStyle[Symbol.toPrimitive] = function() {
return "function getComputedStyle() { [native code] }";
};
function parseAttributeList(el, attribute) {
const classesString = el.getAttribute(attribute);
return classesString ? classesString.split(" ") : [];
}
function parseClassName(name) {
const parsedRaw = name.split(/[-_]+|\B(?=[A-Z])/);
const parsed = [];
for(const word of parsedRaw) {
parsed.push(word.toLowerCase());
}
return parsed;
}
function parseAttributeListWords(el, attribute) {
const classList = parseAttributeList(el, attribute);
let classWords = [];
for(const className of classList) {
classWords = classWords.concat(parseClassName(className));
}
return classWords;
}
function parseAttributesListWords(el, attributes) {
let result = [];
for(const attribute of attributes) {
result = result.concat(parseAttributeListWords(el, attribute));
}
return result;
}
function includesAny(arrOrString, includes) {
let doesInclude = false;
for(let i = 0; i < includes.length; i++) {
let searchString = includes[i];
if(arrOrString.includes(searchString)) {
doesInclude = true;
break;
}
}
return doesInclude;
}
const adTokens = ["ad", "ads", "adsense", "adsbygoogle", "aswift", "sponsored", "advertisement", "advertizement", "advert", "interads"];
function checkIfElementIsAnAd(el) {
if(el === document.documentElement || el === document.body) return false;
const text = el.textContent.trim().toLowerCase();
const colorProperty = getComputedStyle(el).getPropertyValue("color");
let parsed = parseAttributesListWords(el, ["class", "id", "title", "aria-label"]);
let isAnAd = includesAny(parsed, adTokens);
for(const token of parsed) {
if(token.startsWith("ads") || token.includes("advert") || token.endsWith("ads")) {
isAnAd = true;
break;
}
}
if(el.tagName === "IFRAME" && el.src) {
const srcURL = new URL(el.src);
if(srcURL.host.includes("syndicatedsearch") || srcURL.host.includes("doubleclick") || srcURL.hostname.endsWith(".goog")) isAnAd = true;
}
if(text === "advertisement" && colorProperty && colorProperty !== "rgb(0, 0, 0)" && colorProperty !== "rgb(255, 255, 255)") isAnAd = true;
if(el.getAttribute("style") && el.getAttribute("style").length > 9000 && countImportant(el.getAttribute("style")) > 200) isAnAd = true;
return isAnAd;
}
var isBlocking = false;
function blockAdElement(el, force) {
const isAd = checkIfElementIsAnAd(el);
if(!isAd && !force) return;
if(!el.classList.contains(adBlockingId)) {
originalDisplays.set(el, originalGetComputedStyle(el).getPropertyValue("display"));
el.classList.add(adBlockingId);
}
if(spoofedElements.includes(el)) return;
if(originalGetComputedStyle(el).display !== "none") {
let originalDisplay = originalGetComputedStyle(el).getPropertyValue("display");
let originalDisplayPriority = originalGetComputedStyle(el).getPropertyPriority("display");
el.style.setProperty("display", "none", "important");
Object.defineProperty(el.style, "display", {
get: function() {
return originalDisplay + (originalDisplayPriority ? " !" + originalDisplayPriority : "");
},
set: function() {}
});
const realGPV = el.style.getPropertyValue.bind(el.style);
el.style.getPropertyValue = function(property) {
const result = realGPV(...arguments);
if(property === "display") return originalDisplay;
return result;
};
el.style.setProperty = function(property, value, priority) {
if(property.toLowerCase() === "display") {
originalDisplay = value;
originalDisplayPriority = priority ? priority : "";
return;
}
};
}
spoofedElements.push(el);
}
function countImportant(str) {
const matches = str.match(/!important/g);
return matches ? matches.length : 0;
}
function noGoogleVignette() {
try {
history.replaceState(null, null, location.href.slice(0, location.href.length - 16));
} catch(err) {}
}
function blockGoogleVignettePath() {
const hash = location.hash;
if(hash === "#google_vignette") noGoogleVignette();
}
function blockAds(nodesToCheck) {
if(isBlocking) return;
isBlocking = true;
for(const node of nodesToCheck) {
if(node.nodeType !== 1) continue;
blockAdElement(node);
}
blockGoogleVignettePath();
isBlocking = false;
}
const observer = new MutationObserver(function(mutations) {
let nodesToCheck = [];
for(const mutation of mutations) {
nodesToCheck.push(mutation.target);
nodesToCheck = nodesToCheck.concat(mutation.addedNodes);
if(Array.from(mutation.removedNodes).includes(adBlockingStyleSheet)) document.head.appendChild(adBlockingStyleSheet);
}
blockAds(nodesToCheck);
});
observer.observe(document, { childList: true, subtree: true, attributes: true });
blockAds(Array.from(document.querySelectorAll("*")));
}, {
toString: {
get: function() {
return function() {
return "";
}
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment