Twitter Enhancement

Remove promoted tweets and ads from Twitter feed

目前为 2025-02-23 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Twitter Enhancement
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1.1
  5. // @description Remove promoted tweets and ads from Twitter feed
  6. // @author aspen138
  7. // @match *://twitter.com/*
  8. // @match *://x.com/*
  9. // @grant none
  10. // @license MIT
  11. // @grant GM_addStyle
  12. // @icon https://about.twitter.com/etc/designs/about2-twitter/public/img/favicon-32x32.png
  13. // ==/UserScript==
  14.  
  15.  
  16. // Twitter Ad Remover
  17. (function() {
  18. function hideAd(node) {
  19. if (
  20. !node ||
  21. node.nodeName !== "DIV" ||
  22. node.getAttribute("data-testid") !== "cellInnerDiv"
  23. ) {
  24. return;
  25. }
  26.  
  27. const adArticle = node.querySelector("div[data-testid='placementTracking'] > article");
  28. if (!adArticle) {
  29. return;
  30. }
  31.  
  32. node.style.cssText += "display: none;";
  33. }
  34.  
  35. // Observe for newly added nodes and hide ads in them
  36. new MutationObserver(function(mutations) {
  37. mutations.forEach(function(mutation) {
  38. mutation.addedNodes.forEach(hideAd);
  39. });
  40.  
  41. // Hide the sidebar ad
  42. 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");
  43. if (sidebarAd) {
  44. sidebarAd.style.display = 'none';
  45. }
  46. }).observe(document.body, {
  47. childList: true,
  48. subtree: true
  49. });
  50.  
  51. // Initial pass to hide existing ads
  52. document.querySelectorAll("div[data-testid='cellInnerDiv']").forEach(hideAd);
  53.  
  54. function removePromotedTweets(node) {
  55. node = node || document.body;
  56. const tweets = node.querySelectorAll('article[data-testid="tweet"]');
  57.  
  58. tweets.forEach((tweet) => {
  59. const adLabel = tweet.querySelector('div[dir="ltr"] > span');
  60. if (adLabel && (adLabel.textContent === 'Promoted' || adLabel.textContent === 'Ad')) {
  61. tweet.remove();
  62. }
  63. });
  64. }
  65.  
  66. // Initial removal of promoted tweets
  67. removePromotedTweets();
  68.  
  69. // Observe the DOM for changes and remove newly added promoted tweets
  70. new MutationObserver(function(mutations) {
  71. mutations.forEach(function(mutation) {
  72. mutation.addedNodes.forEach(function(node) {
  73. if (node.nodeType === Node.ELEMENT_NODE) {
  74. removePromotedTweets(node);
  75. }
  76. });
  77. });
  78. }).observe(document.body, {
  79. childList: true,
  80. subtree: true
  81. });
  82. })();
  83.  
  84.  
  85.  
  86. // I can understand summarizing a user's profile. But what's the point of summarizing a tweet that's not even very long????
  87. // hide Grok xAI "explain this post"
  88. (function() {
  89. 'use strict';
  90.  
  91. // Inject a <style> tag with display: none !important for the specific SVG elements
  92. const style = document.createElement('style');
  93. style.innerHTML = 'button[aria-label="Grok actions"] { display: none !important; }';
  94. document.head.appendChild(style);
  95.  
  96. // Select all specific SVG elements based on their class names
  97. const svgElements = document.querySelectorAll('button[aria-label="Grok actions"]');
  98.  
  99. // Hide each matched SVG element
  100. svgElements.forEach(svg => {
  101. svg.style.display = 'none';
  102. });
  103. })();