// ==UserScript==
// @name Remove Youtube Propaganda
// @namespace https://gitlab.com/Dwyriel
// @version 1.9.0
// @description Tries to remove any banner and other dismissibles that are plain annoying (or straight up propaganda).
// @author Dwyriel
// @license MIT
// @match *://*.youtube.com/*
// @grant GM.registerMenuCommand
// @homepageURL https://gitlab.com/Dwyriel/Greasyfork-Scripts
// ==/UserScript==
(function () {
'use strict';
// #region Variables and constants
const userscriptName = "[Remove Youtube Propaganda]";
const userscriptPolicyName = "RYP_Policy";
let mutationObs;
const idsToRemove = [
"big-yoodle", //main page banner
"clarify-box" //video page "clarification"
];
const elementsToRemove = [
"ytm-statement-banner-renderer", "ytd-statement-banner-renderer", //main page banner
"ytm-clarification-renderer", "ytd-clarification-renderer", //search and video page "clarification" (specific topics only)
"ytm-info-panel-container-renderer", "ytd-info-panel-container-renderer", //search page "clarification" (specific topics only)
"ytd-info-panel-content-renderer", //Extra info/propaganda about the channel, seems to be desktop only
"ytm-brand-video-singleton-renderer", "ytd-brand-video-singleton-renderer", //a very specific video youtube is promoting in the main page (for reasons)
"yt-mealbar-promo-renderer" //youtube premium/ad-free popup, afaik there's no mobile version
];
const elementsByClassToRemove = [];
// #endregion
// #region Utility Functions
const mutationObsStart = () => { mutationObs.observe(document.body, { attributes: true, childList: true, subtree: true }); };
const yesNoString = (bool) => { return bool ? "Yes" : "No"; };
// #endregion
// #region Optional features
// #region ReplaceYoutubeLogo
const youtubeMobileLogoReplacement = `<c3-icon class="mobile-topbar-logo ringo-logo" id="home-icon"><qfgtuef style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;"><div style="width: 100%; height: 100%; fill: currentcolor;"><div style="width: 100%; height: 100%; fill: currentcolor;"><div style="width: 100%; height: 100%; fill: currentcolor;"><div style="width: 100%; height: 100%; fill: currentcolor;"><svg viewBox="0 0 380.9 85.1"><path id="rectangle" fill="#ff0000" d="M 60.699219 0.30078125 C 60.699219 0.30078125 22.699219 0.30078125 13.199219 2.8007812 C 7.9992187 4.2007813 3.9 8.3 2.5 13.5 C 0 23 0 42.699219 0 42.699219 C 0 42.699219 0 62.500391 2.5 71.900391 C 3.9 77.100391 7.9992188 81.199609 13.199219 82.599609 C 22.699219 85.099609 60.699219 85.099609 60.699219 85.099609 C 60.699219 85.099609 98.699219 85.099609 108.19922 82.599609 C 113.39922 81.199609 117.50039 77.100391 118.90039 71.900391 C 121.40039 62.400391 121.40039 42.699219 121.40039 42.699219 C 121.40039 42.699219 121.40039 23 118.90039 13.5 C 117.50039 8.3 113.39922 4.2007812 108.19922 2.8007812 C 98.699219 0.30078125 60.699219 0.30078125 60.699219 0.30078125 z M 48.5 24.5 L 80.099609 42.800781 L 48.5 61 L 48.5 24.5 z "></path><path id="triangle" fill="#ffffff" d="M 48.5,61 80.1,42.8 48.5,24.5 Z"></path><path d="M147.1 55.5L133.5 6.2h11.9l4.8 22.3c1.2 5.5 2.1 10.2 2.7 14.1h.3c.4-2.8 1.3-7.4 2.7-14l5-22.4h11.9L159 55.5v23.7h-11.8l-.1-23.7zm29.2 22.1c-2.4-1.6-4.1-4.1-5.1-7.6-1-3.4-1.5-8-1.5-13.6v-7.7c0-5.7.6-10.3 1.7-13.8 1.2-3.5 3-6 5.4-7.6 2.5-1.6 5.7-2.4 9.7-2.4 3.9 0 7.1.8 9.5 2.4s4.1 4.2 5.2 7.6 1.7 8 1.7 13.8v7.7c0 5.7-.5 10.2-1.6 13.7-1.1 3.4-2.8 6-5.2 7.6-2.4 1.6-5.7 2.4-9.8 2.4-4.3-.1-7.6-.9-10-2.5zm13.5-8.3c.7-1.7 1-4.6 1-8.5V44.2c0-3.8-.3-6.6-1-8.4s-1.8-2.6-3.5-2.6c-1.6 0-2.8.9-3.4 2.6-.7 1.8-1 4.6-1 8.4v16.6c0 3.9.3 6.8 1 8.5.6 1.7 1.8 2.6 3.5 2.6 1.5 0 2.7-.9 3.4-2.6zm51.7-43.4v53.3h-9.4l-1-6.5h-.3c-2.5 4.9-6.4 7.4-11.5 7.4-3.5 0-6.1-1.2-7.8-3.5-1.7-2.3-2.5-5.9-2.5-10.9V25.9h12V65c0 2.4.3 4.1.8 5.1s1.4 1.5 2.6 1.5c1 0 2-.3 3-1 1-.6 1.7-1.4 2.1-2.4V25.9h12z"></path><path d="M274.1 15.9h-11.9v63.3h-11.7V16h-11.9V6.4h35.5v9.5z"></path><path d="M303 25.9v53.3h-9.4l-1-6.5h-.3c-2.5 4.9-6.4 7.4-11.5 7.4-3.5 0-6.1-1.2-7.8-3.5-1.7-2.3-2.5-5.9-2.5-10.9V25.9h12V65c0 2.4.3 4.1.8 5.1s1.4 1.5 2.6 1.5c1 0 2-.3 3-1 1-.6 1.7-1.4 2.1-2.4V25.9h12zm39.7 8.5c-.7-3.4-1.9-5.8-3.5-7.3s-3.9-2.3-6.7-2.3c-2.2 0-4.3.6-6.2 1.9-1.9 1.2-3.4 2.9-4.4 4.9h-.1V3.5h-11.6v75.7h9.9l1.2-5h.3c.9 1.8 2.3 3.2 4.2 4.3 1.9 1 3.9 1.6 6.2 1.6 4.1 0 7-1.9 8.9-5.6 1.9-3.7 2.9-9.6 2.9-17.5v-8.4c0-6.2-.4-10.8-1.1-14.2zm-11 21.7c0 3.9-.2 6.9-.5 9.1-.3 2.2-.9 3.8-1.6 4.7-.8.9-1.8 1.4-3 1.4-1 0-1.9-.2-2.7-.7-.8-.5-1.5-1.2-2-2.1V38.3c.4-1.4 1.1-2.6 2.1-3.6 1-.9 2.1-1.4 3.2-1.4 1.2 0 2.2.5 2.8 1.4.7 1 1.1 2.6 1.4 4.8.3 2.3.4 5.5.4 9.6l-.1 7zm29.1.4v2.7c0 3.4.1 6 .3 7.7.2 1.7.6 3 1.3 3.7.6.8 1.6 1.2 3 1.2 1.8 0 3-.7 3.7-2.1.7-1.4 1-3.7 1.1-7l10.3.6c.1.5.1 1.1.1 1.9 0 4.9-1.3 8.6-4 11s-6.5 3.6-11.4 3.6c-5.9 0-10-1.9-12.4-5.6-2.4-3.7-3.6-9.4-3.6-17.2v-9.3c0-8 1.2-13.8 3.7-17.5s6.7-5.5 12.6-5.5c4.1 0 7.3.8 9.5 2.3s3.7 3.9 4.6 7c.9 3.2 1.3 7.6 1.3 13.2v9.1h-20.1v.2zm1.5-22.4c-.6.8-1 2-1.2 3.7s-.3 4.3-.3 7.8v3.8h8.8v-3.8c0-3.4-.1-6-.3-7.8-.2-1.8-.7-3-1.3-3.7-.6-.7-1.6-1.1-2.8-1.1-1.3 0-2.3.4-2.9 1.1z"></path></svg></div></div></div></div></qfgtuef></c3-icon>`;
const replaceLogoKey = "RYP_replace_logo";
const replaceLogoMenuString = "Replace event logo: ";
let shouldReplaceLogo = false;
const replaceYoutubeLogoDesktop = (youtubeLogo) => {
let isEventLogoActive = youtubeLogo.getAttribute("hidden") === null;
if (!isEventLogoActive)
return;
youtubeLogo.parentElement.getElementsByTagName("div")[0]?.removeAttribute("hidden");
youtubeLogo.setAttribute("hidden", "");
console.log(`${userscriptName} (Desktop) Replaced youtube logo with default one`);
};
const replaceYoutubeLogoMobile = (youtubeLogo) => {
let parentElement = youtubeLogo.parentElement;
try {
if (trustedTypes) {
const trustedTypesPolice = trustedTypes.createPolicy(userscriptPolicyName, { createHTML: (string) => string });
parentElement.innerHTML = trustedTypesPolice.createHTML(youtubeMobileLogoReplacement);
} else {
parentElement.innerHTML = youtubeMobileLogoReplacement;
}
parentElement.setAttribute("key", "logo");
console.log(`${userscriptName} (Mobile) Replaced youtube logo with default one`);
} catch (err) {
console.error(`${userscriptName} (Mobile) Couldn't replace youtube logo`);
console.error(err);
}
};
const replaceYoutubeLogo = () => {
//context: usually returns an array with two elements, second one was always hidden, no idea what it's used for.
let youtubeLogo = document.getElementsByTagName("ytd-yoodle-renderer")[0];
if (youtubeLogo) {
replaceYoutubeLogoDesktop(youtubeLogo);
return;
}
youtubeLogo = document.getElementsByTagName("ytm-logo-entity")[0];
if (youtubeLogo)
replaceYoutubeLogoMobile(youtubeLogo);
};
const menuEntry_ReplaceLogoAction = () => {
mutationObs.disconnect();
shouldReplaceLogo = !shouldReplaceLogo;
localStorage.setItem(replaceLogoKey, shouldReplaceLogo);
if (shouldReplaceLogo)
replaceYoutubeLogo();
GM.registerMenuCommand(replaceLogoMenuString + yesNoString(shouldReplaceLogo), menuEntry_ReplaceLogoAction, { id: replaceLogoKey, autoClose: false });
mutationObsStart();
};
// #endregion
// #region RemoveShorts
const removeShortsKey = "RYP_remove_shorts";
const removeShortsMenuString = "Remove shorts section: ";
let shouldRemoveShorts = false;
const removeShortSection = () => {
document.querySelectorAll("ytd-rich-shelf-renderer[is-shorts]:not(.ryp-hidden)").forEach((ele) => {
let sect = ele.closest("ytd-rich-section-renderer");
if (sect == null)
return;
console.log("Hidding element: ", sect);
ele.classList.add("ryp-hidden");
sect.style.display = "none";
});
document.querySelectorAll("ytm-rich-section-renderer:not(.ryp-hidden) h2[class*='shelf-header-layout'] span").forEach((ele) => {
if (ele.innerText == "Shorts") { //note: English only, couldn't find any other way to properly identify the "Shorts" mobile section without hardcoding the search
let sect = ele.closest("ytm-rich-section-renderer");
if (sect == null)
return;
console.log("Hidding element: ", sect);
sect.classList.add("ryp-hidden");
sect.style.display = "none";
}
});
};
const menuEntry_RemoveShortsAction = () => {
mutationObs.disconnect();
shouldRemoveShorts = !shouldRemoveShorts;
localStorage.setItem(removeShortsKey, shouldRemoveShorts);
if (shouldRemoveShorts)
removeShortSection();
GM.registerMenuCommand(removeShortsMenuString + yesNoString(shouldRemoveShorts), menuEntry_RemoveShortsAction, { id: removeShortsKey, autoClose: false });
mutationObsStart();
};
// #endregion
// #region RemoveForYou
const removeForYouKey = "RYP_remove_for_you";
const removeForYouMenuString = "Remove \"for you\" channel section: ";
let shouldRemoveForYou = false;
const removeForYouSection = () => { //note: English only, couldn't find any other way to properly identify the "For you" section without hardcoding the search
if (!window.location.pathname.includes("/@"))
return;
let sectionRenderer = document.getElementsByTagName("ytd-section-list-renderer"); //search page also uses it, and all tags still exist in the html even when not being used (they're just hidden)
if (sectionRenderer.length > 0)
for (let ytdSectRenderer of sectionRenderer) {
let sections = ytdSectRenderer.querySelector(`div[id="contents"]`).childNodes;
for (let sect of sections) {
let spans = sect.querySelectorAll("span");
for (let span of spans)
if (RegExp("^For You").test(span.innerText)) {
sect.remove();
console.log(`${userscriptName} Removed "For You" section`);
return;
}
}
}
else {
sectionRenderer = document.getElementsByTagName("ytm-item-section-renderer");
for (let ytmSectRenderer of sectionRenderer) {
let sections = ytmSectRenderer.querySelectorAll("ytm-horizontal-card-list-renderer");
for (let sect of sections) {
let spans = sect.querySelectorAll("span");
for (let span of spans)
if (RegExp("^For You").test(span.innerText)) {
if (sectionRenderer.length == 1)
ytmSectRenderer.remove();
else
sect.remove();
console.log(`${userscriptName} Removed "For You" section`);
return;
}
}
}
}
};
const menuEntry_RemoveForYouAction = () => {
mutationObs.disconnect();
shouldRemoveForYou = !shouldRemoveForYou;
localStorage.setItem(removeForYouKey, shouldRemoveForYou);
if (shouldRemoveForYou)
removeForYouSection();
GM.registerMenuCommand(removeForYouMenuString + yesNoString(shouldRemoveForYou), menuEntry_RemoveForYouAction, { id: removeForYouKey, autoClose: false });
mutationObsStart();
};
// #endregion
// #region RemovePeopleMentioned
const removePeopleMentionedKey = "RYP_remove_people_mentioned";
const removePeopleMentionedMenuString = "Remove people mentioned: ";
let shouldRemovePeopleMentioned = false;
const removePeopleMentioned = () => {
let elements = document.getElementsByTagName("yt-video-attributes-section-view-model"); //same for both desktop & mobile, seems to only be used to show the "People Mentioned" section
for (let element of elements)
element.remove();
};
const menuEntry_RemovePeopleMentionedAction = () => {
mutationObs.disconnect();
shouldRemovePeopleMentioned = !shouldRemovePeopleMentioned;
localStorage.setItem(removePeopleMentionedKey, shouldRemovePeopleMentioned);
if(shouldRemovePeopleMentioned)
removePeopleMentioned();
GM.registerMenuCommand(removePeopleMentionedMenuString + yesNoString(shouldRemovePeopleMentioned), menuEntry_RemovePeopleMentionedAction, { id: removePeopleMentionedKey, autoClose: false });
mutationObsStart();
};
// #endregion
// #endregion
const callback = () => {
mutationObs.disconnect();
for (let id of idsToRemove) {
let element = document.getElementById(id);
if (element) {
element.remove();
console.log(`${userscriptName} Removed element of id: ${id}`);
}
}
for (let elementName of elementsToRemove) {
let elements = document.getElementsByTagName(elementName);
for (let element of elements) {
element.remove();
console.log(`${userscriptName} Removed element with tag name: ${elementName}`);
}
}
for (let className of elementsByClassToRemove) {
let elements = document.getElementsByClassName(className);
for (let element of elements) {
element.remove();
console.log(`${userscriptName} Removed element with class: ${className}`);
}
}
if (shouldReplaceLogo)
replaceYoutubeLogo();
if (shouldRemoveShorts)
removeShortSection();
if (shouldRemoveForYou)
removeForYouSection();
if (shouldRemovePeopleMentioned)
removePeopleMentioned();
mutationObsStart();
};
/* Script start */
mutationObs = new MutationObserver(callback);
try {
let replaceLogoStorageValue = localStorage.getItem(replaceLogoKey);
if (replaceLogoStorageValue)
shouldReplaceLogo = replaceLogoStorageValue == "true";
let removeShortsStorageValue = localStorage.getItem(removeShortsKey);
if (removeShortsStorageValue)
shouldRemoveShorts = removeShortsStorageValue == "true";
let removeForYouStorageValue = localStorage.getItem(removeForYouKey);
if (removeForYouStorageValue)
shouldRemoveForYou = removeForYouStorageValue == "true";
let removePeopleMentionedValue = localStorage.getItem(removePeopleMentionedKey);
if (removePeopleMentionedValue)
shouldRemovePeopleMentioned = removePeopleMentionedValue == "true";
} catch {
console.error(`${userscriptName} Couldn't read saved settings from localStorage`);
}
try {
GM.registerMenuCommand(replaceLogoMenuString + yesNoString(shouldReplaceLogo), menuEntry_ReplaceLogoAction, { id: replaceLogoKey, autoClose: false });
GM.registerMenuCommand(removeShortsMenuString + yesNoString(shouldRemoveShorts), menuEntry_RemoveShortsAction, { id: removeShortsKey, autoClose: false });
GM.registerMenuCommand(removeForYouMenuString + yesNoString(shouldRemoveForYou), menuEntry_RemoveForYouAction, { id: removeForYouKey, autoClose: false });
GM.registerMenuCommand(removePeopleMentionedMenuString + yesNoString(shouldRemovePeopleMentioned), menuEntry_RemovePeopleMentionedAction, { id: removePeopleMentionedKey, autoClose: false });
} catch {
console.error(`${userscriptName} Couldn't add GM menu entries`);
}
callback();
})();