Greasy Fork is available in English.
宁杀错不放过:强力屏蔽引流/币圈/擦边/博彩等机器人内容,支持选中文本后alt+B一键加入屏蔽词。
当前为
// ==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 http://greasyfork.icu/images/blacklogo16.png
// @homepageURL http://greasyfork.icu/zh-CN/scripts/570683
// ==/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);
});