// ==UserScript== // @name X 黄推+币圈机器人终极隐藏器 // @namespace https://grok.x.ai // @version 1.1 // @description 宁杀错不放过:强力屏蔽引流/币圈/擦边/博彩等机器人内容,支持选中文本后alt+B一键加入屏蔽词。 // @author Grok、codex // @match https://x.com/* // @match https://twitter.com/* // @grant none // @run-at document-start // @license MIT // @icon https://greasyfork.org/images/blacklogo16.png // @homepageURL https://greasyfork.org/zh-CN/scripts/570683 // @downloadURL none // ==/UserScript== (function () { 'use strict'; const STORAGE_KEY = 'x_block_words_v1'; const HIDDEN_ATTR = 'data-x-ultra-hidden'; const BUILTIN_PATTERNS = [ /男大/i, /足控/i, /蜜桃臀/i, /主人|舔狗|小狗|真人|线下|上门|男搭讪|急找|在线|蹲一个|有线下吗/i, /谁来当我主人|小狗想跟你玩|小狗在线找主人|小狗在线等你|主人快来领我/i, /找个长期搭子|有没有单男|有没有游戏搭子|有没有单女/i, /急需一位|找个哥哥|调教|附近的有没有|满足我|看做爱|不如做爱/i, /小母狗|母狗|欲望少女|纯欲|反差/i, /我是真人 有线下吗|➡️小狗在线等你|➡️(急需|找个|蹲一个|谁来当我)/i, /那亲亲吧|你的娱乐群|小狗在线等你/i, /找个同城哥哥|找个温柔主人|dd个线下|找个线下哥哥|小狗求主人抱抱/i, /空投|USDT.*(奖池|交易|转账|推广)|拉盘|打新项目|上币路线|Pre-IPO|合约.*(喊单|爆仓)/i, /引流|私信|DM|加V|VX|微信|电报|TG|群号|群聊|福利群|进群|进组/i, /开户|理财|搬砖|量化|带单|套利|返利|高收益|稳赚|保本|日赚/i, /博彩|赌场|下注|百家乐|时时彩|快三|网投|棋牌游戏/i, /约炮|一夜情|同城|上门服务|包夜|全套|外围|小姐|嫩模|学生妹/i, /裸聊|视频聊天|视频交友|语音交友|聊骚|骚扰|撩骚/i, /兼职|日结|招募|代理|推广员|刷单|返现|冲量/i, /空降|互关|互粉|互赞|点赞关注|关注我|回关|求关/i, /[\u2196\u2197\u2198\u2199\u2190\u2191\u2192\u2193\u2B05\u2B06\u2B07\u27A1]/, /蹲|搭子|固炮|反差/i, /同城(哥哥|弟弟|姐姐|妹妹)|陪聊|陪玩|陪睡|宠物系|恋爱搭子|陪伴搭子/i, /小狗找主人|小狗求主人|找(个|位)?主人|找(个|位)?哥哥|找(个|位)?弟弟/i, /主(人|子)快来领我|求主人抱抱|在线等(你|哥哥|弟弟)/i, /淫/i, /温柔主(人)?|同城|万达广场附近/i, /(^|[^A-Za-z0-9])[sSmM]([^A-Za-z0-9]|$)/, /萌猫|小烧货|千万次心跳|护士姐姐|学妹|学姐|反差婊/i, /(萌|甜|软|奶|乖|小|可爱).*(猫|狗|兔|鹿|狐|虎|猫咪)/i, /(护士|学妹|学姐|老师|姐姐|妹妹).*(小烧货|反差|纯欲|欲望)/i, /\b[A-Z][a-z]+[A-Z][a-z]+\d{3,}\b/, /蹲一个男搭子|有没有离得近的|被.*(小烧货|骚货|sao货)|扣1白给|温柔s|爹系男友/i, /射射|色色|涩涩|瑟瑟|视频|瓦学弟|破处/i ]; const NAME_PATTERNS = [ /反差|母狗|臀|破处|处男|处女|找主人|温柔主/i, /(^|[^A-Za-z0-9])[sSmM]([^A-Za-z0-9]|$)/, /男大|足控|蜜桃臀/i ]; function escapeRegExp(text) { return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function normalize(text) { return (text || '') .toLowerCase() .replace(/[\s\.\,\!\?\-_/\\()\[\]{}"'`~@#$%^&*+=<>|:;、,。!?【】()《》“”‘’·]+/g, ''); } function isMostlyEmoji(text) { const stripped = (text || '').replace(/[\p{Extended_Pictographic}\s\.,!?;:、,。!?【】()《》“”‘’·~`'"-]/gu, ''); return stripped.length <= 1 && /[\p{Extended_Pictographic}]/u.test(text || ''); } function emojiOnlyWithHearts(text) { const t = text || ''; const nonEmoji = t.replace(/[\p{Extended_Pictographic}\s\.,!?;:、,。!?【】()《》“”‘’·~`'"-]/gu, ''); if (nonEmoji.length > 0) return false; const emojis = (t.match(/[\p{Extended_Pictographic}]/gu) || []).length; if (emojis < 3) return false; return /[\u2764\uFE0F\u1F49B\u1F49A\u1F499\u1F49C\u1F90E\u1F90D\u1F5A4]/u.test(t); } function loadUserWords() { try { const raw = localStorage.getItem(STORAGE_KEY); const list = raw ? JSON.parse(raw) : []; return Array.isArray(list) ? list : []; } catch { return []; } } let userWords = loadUserWords(); let userRegexes = buildUserRegexes(userWords); function buildUserRegexes(words) { return words .map(w => String(w || '').trim()) .filter(Boolean) .map(w => new RegExp(`.*${escapeRegExp(w)}.*`, 'i')); // 贪婪匹配 } function saveUserWords() { localStorage.setItem(STORAGE_KEY, JSON.stringify(userWords)); userRegexes = buildUserRegexes(userWords); } function addUserWord(word) { const w = String(word || '').trim(); if (!w) return; if (userWords.includes(w)) return; userWords.push(w); saveUserWords(); toast(`已加入屏蔽词:${w}`); scheduleScan(); } function shouldHide(text, nameText) { const original = text || ''; const compact = normalize(original); const name = nameText || ''; const nameCompact = normalize(name); return emojiOnlyWithHearts(original) || isMostlyEmoji(original) || NAME_PATTERNS.some(r => r.test(name) || r.test(nameCompact)) || BUILTIN_PATTERNS.some(r => r.test(original) || r.test(compact)) || userRegexes.some(r => r.test(original) || r.test(compact) || r.test(name) || r.test(nameCompact)); } function collectArticleText(article) { const parts = []; const text = article.textContent || ''; if (text) parts.push(text); article.querySelectorAll('[alt],[title],[aria-label]').forEach(el => { const alt = el.getAttribute('alt'); const title = el.getAttribute('title'); const aria = el.getAttribute('aria-label'); if (alt) parts.push(alt); if (title) parts.push(title); if (aria) parts.push(aria); }); return parts.join(' '); } function collectNameText(article) { const nameNode = article.querySelector('[data-testid="User-Name"]'); return nameNode ? (nameNode.textContent || '') : ''; } function hideArticle(article) { if (article.getAttribute(HIDDEN_ATTR)) return; const text = collectArticleText(article).trim(); const nameText = collectNameText(article).trim(); if (!shouldHide(text, nameText)) return; article.setAttribute(HIDDEN_ATTR, '1'); article.style.setProperty('display', 'none', 'important'); article.style.setProperty('visibility', 'hidden', 'important'); const container = article.closest('div[data-testid="cellInnerDiv"]'); if (container) container.style.setProperty('display', 'none', 'important'); } function scanAll() { document.querySelectorAll('article[data-testid="tweet"]').forEach(hideArticle); } let scanInProgress = false; function scheduleScan() { if (scanInProgress) return; scanInProgress = true; scanAll(); scanInProgress = false; } function handleMutations(mutations) { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== 1) continue; if (node.matches && node.matches('article[data-testid="tweet"]')) { hideArticle(node); } else if (node.querySelectorAll) { node.querySelectorAll('article[data-testid="tweet"]').forEach(hideArticle); } } } } function getSelectionText() { return String(window.getSelection && window.getSelection().toString() || '').trim(); } function createManagePanel() { const panel = document.createElement('div'); panel.id = 'x-ultra-block-panel'; panel.style.cssText = [ 'position:fixed', 'right:16px', 'bottom:64px', 'width:280px', 'max-height:360px', 'overflow:auto', 'background:#111', 'color:#fff', 'border:1px solid #444', 'border-radius:10px', 'padding:10px', 'font-size:12px', 'z-index:2147483647', 'display:none' ].join(';'); const header = document.createElement('div'); header.textContent = '屏蔽词管理'; header.style.cssText = 'font-weight:600; margin-bottom:8px;'; const list = document.createElement('div'); const inputRow = document.createElement('div'); inputRow.style.cssText = 'display:flex; gap:6px; margin-bottom:8px;'; const input = document.createElement('input'); input.placeholder = '手动添加屏蔽词'; input.style.cssText = 'flex:1; padding:4px 6px; border:1px solid #333; border-radius:6px; background:#0b0b0b; color:#fff;'; const addBtn = document.createElement('button'); addBtn.textContent = '添加'; addBtn.style.cssText = 'padding:4px 8px; cursor:pointer;'; inputRow.appendChild(input); inputRow.appendChild(addBtn); const quickRow = document.createElement('div'); quickRow.style.cssText = 'display:flex; gap:6px; margin-bottom:8px;'; const addSelBtn = document.createElement('button'); addSelBtn.textContent = '添加选中'; addSelBtn.style.cssText = 'flex:1; padding:4px 6px; cursor:pointer;'; const hint = document.createElement('div'); hint.textContent = '快捷键:Alt+B 添加选中文本'; hint.style.cssText = 'flex:2; color:#aaa; align-self:center;'; quickRow.appendChild(addSelBtn); quickRow.appendChild(hint); const actions = document.createElement('div'); actions.style.cssText = 'margin-top:8px; display:flex; gap:6px;'; const clearBtn = document.createElement('button'); clearBtn.textContent = '清空'; clearBtn.style.cssText = 'flex:1; padding:4px 6px; cursor:pointer;'; const closeBtn = document.createElement('button'); closeBtn.textContent = '关闭'; closeBtn.style.cssText = 'flex:1; padding:4px 6px; cursor:pointer;'; actions.appendChild(clearBtn); actions.appendChild(closeBtn); panel.appendChild(header); panel.appendChild(inputRow); panel.appendChild(quickRow); panel.appendChild(list); panel.appendChild(actions); document.documentElement.appendChild(panel); function renderList() { list.innerHTML = ''; if (!userWords.length) { const empty = document.createElement('div'); empty.textContent = '暂无自定义屏蔽词'; empty.style.cssText = 'color:#888; padding:4px 0;'; list.appendChild(empty); return; } userWords.forEach((w, idx) => { const row = document.createElement('div'); row.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding:4px 0; border-bottom:1px dashed #333;'; const text = document.createElement('span'); text.textContent = w; const del = document.createElement('button'); del.textContent = '删除'; del.style.cssText = 'margin-left:8px; cursor:pointer;'; del.addEventListener('click', () => { userWords.splice(idx, 1); saveUserWords(); renderList(); scheduleScan(); }); row.appendChild(text); row.appendChild(del); list.appendChild(row); }); } clearBtn.addEventListener('click', () => { userWords = []; saveUserWords(); renderList(); scheduleScan(); }); closeBtn.addEventListener('click', () => { panel.style.display = 'none'; }); function togglePanel() { renderList(); panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; } const toggleBtn = document.createElement('div'); toggleBtn.textContent = '屏蔽词'; toggleBtn.style.cssText = [ 'position:fixed', 'right:16px', 'bottom:16px', 'background:#111', 'color:#fff', 'border:1px solid #444', 'border-radius:999px', 'padding:6px 10px', 'font-size:12px', 'cursor:pointer', 'z-index:2147483647' ].join(';'); toggleBtn.addEventListener('click', togglePanel); document.documentElement.appendChild(toggleBtn); } function toast(message) { const node = document.createElement('div'); node.textContent = message; node.style.cssText = [ 'position:fixed', 'right:16px', 'bottom:16px', 'background:#222', 'color:#fff', 'border:1px solid #444', 'padding:8px 10px', 'border-radius:8px', 'font-size:12px', 'z-index:2147483647' ].join(';'); document.documentElement.appendChild(node); setTimeout(() => node.remove(), 1600); } function init() { scanAll(); const observer = new MutationObserver(handleMutations); observer.observe(document.documentElement, { childList: true, subtree: true }); window.addEventListener('load', scheduleScan); window.addEventListener('popstate', scheduleScan); const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function () { const result = originalPushState.apply(this, arguments); scheduleScan(); return result; }; history.replaceState = function () { const result = originalReplaceState.apply(this, arguments); scheduleScan(); return result; }; window.addEventListener('scroll', () => { if (Math.random() < 0.08) scheduleScan(); }, { passive: true }); setInterval(scheduleScan, 1200); createManagePanel(); document.addEventListener('keydown', (event) => { if (event.altKey && !event.ctrlKey && !event.metaKey && event.key.toLowerCase() === 'b') { const sel = getSelectionText(); if (sel) addUserWord(sel); } }, { capture: true }); } if (document.documentElement) { init(); } else { document.addEventListener('readystatechange', () => { if (document.documentElement) init(); }, { once: true }); } console.log('✅ X 强力隐藏器已加载(宁杀错不放过)'); })(); addBtn.addEventListener('click', () => { addUserWord(input.value); input.value = ''; }); input.addEventListener('keydown', (event) => { if (event.key === 'Enter') { addUserWord(input.value); input.value = ''; } }); addSelBtn.addEventListener('click', () => { const sel = getSelectionText(); if (sel) addUserWord(sel); });