Greasy Fork is available in English.
Remove promoted tweets and ads from Twitter feed
当前为
// ==UserScript==
// @name Twitter Enhancement
// @namespace http://tampermonkey.net/
// @version 1.1.1
// @description Remove promoted tweets and ads from Twitter feed
// @author aspen138
// @match *://twitter.com/*
// @match *://x.com/*
// @grant none
// @license MIT
// @grant GM_addStyle
// @icon https://about.twitter.com/etc/designs/about2-twitter/public/img/favicon-32x32.png
// ==/UserScript==
// Twitter Ad Remover
(function() {
function hideAd(node) {
if (
!node ||
node.nodeName !== "DIV" ||
node.getAttribute("data-testid") !== "cellInnerDiv"
) {
return;
}
const adArticle = node.querySelector("div[data-testid='placementTracking'] > article");
if (!adArticle) {
return;
}
node.style.cssText += "display: none;";
}
// Observe for newly added nodes and hide ads in them
new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(hideAd);
});
// Hide the sidebar ad
const sidebarAd = document.querySelector("#react-root > div > div > div.css-175oi2r.r-1f2l425.r-13qz1uu.r-417010.r-18u37iz > main > div > div > div > div.css-175oi2r.r-aqfbo4.r-10f7w94.r-1hycxz > div > div.css-175oi2r.r-1hycxz.r-gtdqiz > div > div > div > div:nth-child(3) > div > aside");
if (sidebarAd) {
sidebarAd.style.display = 'none';
}
}).observe(document.body, {
childList: true,
subtree: true
});
// Initial pass to hide existing ads
document.querySelectorAll("div[data-testid='cellInnerDiv']").forEach(hideAd);
function removePromotedTweets(node) {
node = node || document.body;
const tweets = node.querySelectorAll('article[data-testid="tweet"]');
tweets.forEach((tweet) => {
const adLabel = tweet.querySelector('div[dir="ltr"] > span');
if (adLabel && (adLabel.textContent === 'Promoted' || adLabel.textContent === 'Ad')) {
tweet.remove();
}
});
}
// Initial removal of promoted tweets
removePromotedTweets();
// Observe the DOM for changes and remove newly added promoted tweets
new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
removePromotedTweets(node);
}
});
});
}).observe(document.body, {
childList: true,
subtree: true
});
})();
// I can understand summarizing a user's profile. But what's the point of summarizing a tweet that's not even very long????
// hide Grok xAI "explain this post"
(function() {
'use strict';
// Inject a <style> tag with display: none !important for the specific SVG elements
const style = document.createElement('style');
style.innerHTML = 'button[aria-label="Grok actions"] { display: none !important; }';
document.head.appendChild(style);
// Select all specific SVG elements based on their class names
const svgElements = document.querySelectorAll('button[aria-label="Grok actions"]');
// Hide each matched SVG element
svgElements.forEach(svg => {
svg.style.display = 'none';
});
})();