Skip to content

Instantly share code, notes, and snippets.

@extratone
Created March 4, 2025 18:32
Show Gist options
  • Save extratone/0486303f4e9e220013ac6a08cc02a1d9 to your computer and use it in GitHub Desktop.
Save extratone/0486303f4e9e220013ac6a08cc02a1d9 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Universal Downvote Blocker
// @namespace http://tampermonkey.net/
// @version 0.5
// @description Blocks downvote/thumbs-down buttons on various websites.
// @author You (and Gemini)
// @match *://*.youtube.com/*
// @match *://*.reddit.com/*
// @match *://*.urbandictionary.com/*
// @match *://*.stackoverflow.com/*
// @match *://*.stackexchange.com/*
// @match *://*.facebook.com/*
// @match *://*.twitter.com/*
// @match *://*.instagram.com/*
// @match *://*.tiktok.com/*
// @match *://*.linkedin.com/*
// @grant GM_addStyle
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// --- CSS for Hiding Elements (Fastest Initial Blocking) ---
GM_addStyle(`
/* YouTube */
ytd-menu-renderer #top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2),
#segmented-dislike-button,
button[aria-label^="Dislike"],
button[title^="Dislike"] {
display: none !important;
visibility: hidden !important; /* Extra precaution */
pointer-events: none !important; /* Prevent clicks even if visible */
}
/* Reddit (Old and New) */
.arrow.down, .arrow.downmod,
div[data-click-id="downvote"] button, /* New Reddit (more specific)*/
button[aria-label="downvote"]{
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Urban Dictionary */
a.down, .down{
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Stack Overflow/Exchange */
.js-vote-down-btn,
button.vote-down-off{
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Facebook */
/* Facebook dynamically changes, making consistent targeting very hard. JS blocking below is more reliable. */
/* Twitter (X) */
div[data-testid="unlike"] {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Instagram */
/* Similar to Facebook, dynamic changes are frequent. Rely more on JS. */
/* TikTok */
button[data-e2e="dislike-icon"]{
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* LinkedIn */
/* LinkedIn also uses dynamically generated classes, rely on JS */
`);
// --- JavaScript for Robust Blocking and Dynamic Elements ---
function blockDownvotes() {
// --- Generic Blocking (using attribute selectors - works across many sites) ---
const downvoteSelectors = [
'[aria-label*="dislike" i]', // Case-insensitive attribute check
'[aria-label*="downvote" i]',
'[title*="dislike" i]',
'[title*="downvote" i]',
'[data-testid*="downvote" i]', //Common pattern for React-based sites
'[data-testid*="dislike" i]',
'[data-e2e*="dislike" i]',
];
downvoteSelectors.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
element.style.display = 'none';
element.style.visibility = 'hidden';
element.style.pointerEvents = 'none';
element.onclick = (e) => { e.preventDefault(); e.stopPropagation(); return false; }; // Prevent click events
element.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
}, true); // Capture phase blocking
});
});
// --- Site-Specific (Add more as needed) ---
// Reddit (Handles dynamically loaded content better)
document.querySelectorAll('.arrow.down, .arrow.downmod, div[data-click-id="downvote"] button, button[aria-label="downvote"]').forEach(el => {
el.style.display = 'none';
el.onclick = (e) => { e.preventDefault(); e.stopPropagation(); return false;};
});
// YouTube
document.querySelectorAll('ytd-menu-renderer #top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2), #segmented-dislike-button, button[aria-label^="Dislike"], button[title^="Dislike"]').forEach(el => {
el.style.display = 'none';
el.onclick = (e) => { e.preventDefault(); e.stopPropagation(); return false;};
});
}
// Initial blocking
blockDownvotes();
// Observe changes to the DOM (for dynamically loaded content)
const observer = new MutationObserver(blockDownvotes);
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false, // We're handling style changes in blockDownvotes
characterData: false
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment