Greasy Fork is available in English.
Hides posts on X with Hindi, other Indian languages, Arabic, Japanese, or Thai scripts, with enhanced spam detection
// ==UserScript==
// @name JeetDelete X.com
// @namespace http://tampermonkey.net/
// @version 1.4.6
// @description Hides posts on X with Hindi, other Indian languages, Arabic, Japanese, or Thai scripts, with enhanced spam detection
// @author xechostormx, hearing_echoes
// @match https://x.com/*
// @match https://www.x.com/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// Detect target language scripts
function isTargetLanguage(text) {
if (!text || typeof text !== 'string') return false;
const ranges = [
/[\u0900-\u097F]/, // Devanagari (Hindi)
/[\u0B80-\u0BFF]/, // Tamil
/[\u0C00-\u0C7F]/, // Telugu
/[\u0980-\u09FF]/, // Bengali
/[\u0A80-\u0AFF]/, // Gujarati
/[\u0B00-\u0B7F]/, // Odia
/[\u0A00-\u0A7F]/, // Gurmukhi
/[\u0C80-\u0CFF]/, // Kannada
/[\u0D00-\u0D7F]/, // Malayalam
/[\u0600-\u06FF\u0750-\u077F\uFB50-\uFDFF\uFE70-\uFEFF]/, // Arabic
/[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/, // Japanese
/[\u0E00-\u0E7F]/ // Thai
];
const totalChars = text.length;
const targetChars = ranges.reduce((count, rx) => count + (text.match(rx) || []).length, 0);
// Count unique scripts
const scripts = new Set();
ranges.forEach((rx, i) => {
if (text.match(rx)) scripts.add(i);
});
// Debug log
console.log(`Text: "${text.slice(0, 20)}...", Total: ${totalChars}, Target: ${targetChars}, Scripts: ${scripts.size}`);
// Flag if any target chars OR all text is hashtags with multiple scripts
const isAllHashtags = text.replace(/#[^\s#]+/g, '').trim().length === 0;
return targetChars > 0 || (isAllHashtags && scripts.size > 1);
}
// Hide matching posts
function hideTargetLanguagePosts() {
const selector = 'div[data-testid="tweetText"]';
const tweetTexts = document.querySelectorAll(selector);
if (!tweetTexts.length) {
console.warn('No tweet text elements found with selector:', selector);
return;
}
console.log(`Scanning ${tweetTexts.length} tweet texts`);
tweetTexts.forEach((textEl) => {
const tweet = textEl.closest('article[data-testid="tweet"]') || textEl.closest('div[data-testid="cellInnerDiv"]');
if (!tweet) return;
const txt = textEl.textContent || '';
if (isTargetLanguage(txt)) {
tweet.style.display = 'none';
console.log('Hid tweet:', txt.trim().slice(0, 50));
}
});
}
console.log('X-HideLang script initialized @', new Date().toLocaleTimeString());
// Wait for timeline to load
function waitForTimeline() {
const timeline = document.querySelector('div[aria-label*="Timeline"]');
if (timeline) {
hideTargetLanguagePosts();
observeTimeline(timeline);
} else {
requestAnimationFrame(waitForTimeline);
}
}
// Observe timeline for new tweets
function observeTimeline(timeline) {
let debounceTimer = null; // Initialized to null to avoid const error
const observer = new MutationObserver(() => {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(hideTargetLanguagePosts, 200);
});
observer.observe(timeline, { childList: true, subtree: true });
console.log('Observer attached to timeline');
// Cleanup on page unload
window.addEventListener('unload', () => {
clearTimeout(debounceTimer);
observer.disconnect();
});
}
// Start when ready
requestAnimationFrame(waitForTimeline);
})();