您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically hides reposts on X with optional smart filtering by keywords
// ==UserScript== // @name Automatic Repost Hider on X // @description Automatically hides reposts on X with optional smart filtering by keywords // @namespace https://github.com/xechostormx/repost-hider // @version 1.02 // @author xechostormx, hearing_echoes (enhanced by Grok) // @match https://x.com/* // @match https://www.x.com/* // @match https://mobile.x.com/* // @run-at document-end // @grant none // @license MIT // ==/UserScript== 'use strict'; // CSS selectors for tweets and reposts const selectors = { tweet: '[data-testid="cellInnerDiv"]', repost: '[data-testid="socialContext"]', hidden: '[style*="display: none;"]', tweetText: '[data-testid="tweetText"]' // For keyword filtering }; // Configuration const config = { checkInterval: 750, // Increased for better performance debug: false, // Set to true for console logging keywordFilter: [], // Add keywords to filter specific reposts, e.g., ['spam', 'ad'] }; // Track hidden reposts for performance monitoring let hiddenCount = 0; // Debounce function to limit excessive calls during scrolling function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Main function to hide reposts function hideReposts() { const reposts = document.querySelectorAll( `${selectors.tweet}:has(${selectors.repost}):not(${selectors.hidden})` ); reposts.forEach(tweet => { // Optional keyword-based filtering if (config.keywordFilter.length > 0) { const tweetText = tweet.querySelector(selectors.tweetText)?.textContent.toLowerCase() || ''; if (!config.keywordFilter.some(keyword => tweetText.includes(keyword.toLowerCase()))) { return; // Skip if no keywords match } } tweet.style.display = 'none'; hiddenCount++; if (config.debug) { console.debug(`Hid repost #${hiddenCount}`); } }); // Log performance metrics if enabled if (config.debug && reposts.length > 0) { console.debug(`Processed ${reposts.length} reposts in this cycle`); } } // Debounced version of hideReposts const debouncedHideReposts = debounce(hideReposts, config.checkInterval); // Initialize observer for dynamic content function initObserver() { if (!document.body) { if (config.debug) console.debug('Document body not ready, retrying...'); setTimeout(initObserver, 100); return; } const observerConfig = { childList: true, subtree: true }; const observer = new MutationObserver(() => debouncedHideReposts()); observer.observe(document.body, observerConfig); // Clean up observer on page unload window.addEventListener('unload', () => observer.disconnect()); } // Start the script function initialize() { window.addEventListener('scroll', debouncedHideReposts); initObserver(); debouncedHideReposts(); // Initial run } // Run when DOM is ready if (document.readyState === 'complete' || document.readyState === 'interactive') { initialize(); } else { document.addEventListener('DOMContentLoaded', initialize); }