// ==UserScript== // @name Twitter/X Bot and Flag Post Hider // @namespace http://tampermonkey.net/ // @version 1.4 // @description Hides posts from suspected bot accounts (e.g., Name12345) or users with specific flags (e.g., 🇮🇱) in their name. // @author CL // @match *://x.com/* // @match *://twitter.com/* // @grant none // @run-at document-idle // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // --- Configuration --- // This regex pattern identifies usernames that have letters followed by two or more numbers at the end. const BOT_USERNAME_PATTERN = /[a-zA-Z].*\d{2,}$/; // This array contains strings or emojis to look for in the user's display name. Add more items to this list to hide more users. const HIDE_IF_NAME_INCLUDES = ['🇮🇱']; // How often the script checks for new posts on the page (in milliseconds). const CHECK_INTERVAL = 1000; // --- End Configuration --- let hiddenPostCount = 0; const processedPosts = new Set(); /** * Creates and injects a counter element onto the page to display the number of hidden posts. * @returns {HTMLElement} The created counter element. */ function createCounterElement() { const counterDiv = document.createElement('div'); counterDiv.id = 'bot-hider-counter'; // Apply styles to make the counter visible but not intrusive. Object.assign(counterDiv.style, { position: 'fixed', top: '15px', left: '15px', backgroundColor: 'rgba(29, 155, 240, 0.9)', // A semi-transparent Twitter blue color: 'white', padding: '5px 12px', borderRadius: '15px', zIndex: '10000', fontSize: '14px', fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif', boxShadow: '0 2px 8px rgba(0,0,0,0.2)', userSelect: 'none', transition: 'opacity 0.3s ease-in-out' }); document.body.appendChild(counterDiv); return counterDiv; } const counterElement = createCounterElement(); /** * Checks if a user's display name contains any of the strings specified in the configuration. * @param {string} displayName - The user's display name. * @returns {boolean} - True if the name contains a forbidden string, false otherwise. */ function nameContainsHiddenString(displayName) { return HIDE_IF_NAME_INCLUDES.some(str => displayName.includes(str)); } /** * The main function that finds and hides posts based on configured rules. * It iterates through all tweet articles, checks the author's username and display name, * and hides the post if it matches any rule. */ function hidePosts() { // Select all tweet articles on the page. `data-testid` is a more stable selector than CSS classes. const articles = document.querySelectorAll('article[data-testid="tweet"]'); articles.forEach(article => { // A unique identifier for the tweet, often found in 'aria-labelledby', is used to track processed posts. // This prevents the script from re-evaluating the same post repeatedly. const articleId = article.getAttribute('aria-labelledby'); if (!articleId || processedPosts.has(articleId)) { return; // Skip if it has no ID or has already been processed. } processedPosts.add(articleId); // Find the user's profile link and display name element. const userLink = article.querySelector('a[href^="/"]:not([href*="/status/"])'); const userDisplayNameElement = article.querySelector('[data-testid="User-Name"]'); if (userLink && userDisplayNameElement) { const href = userLink.getAttribute('href'); const username = href.substring(1); // Remove the leading '/' to get the username. const displayName = userDisplayNameElement.textContent || ''; // Check if the post should be hidden based on the username pattern, display name content, or username content. const shouldHide = BOT_USERNAME_PATTERN.test(username) || nameContainsHiddenString(displayName) || href.toLowerCase().includes('jew'); if (shouldHide) { // Traverse up the DOM to find the main container of the post. // Hiding this container removes the entire post from view. const postContainer = article.closest('[data-testid="cellInnerDiv"]'); if (postContainer) { postContainer.style.display = 'none'; hiddenPostCount++; } } } }); // Update the counter display with the latest count. counterElement.textContent = `Hiding ${hiddenPostCount} posts`; } // --- Script Execution --- console.log('Twitter/X Bot & Flag Hider script is now active.'); // Because Twitter is a single-page application that loads content dynamically, // we need to run our function periodically to catch new tweets as they appear. setInterval(hidePosts, CHECK_INTERVAL); })();