// ==UserScript==
// @name 小黑盒全能净化引擎 (终极版 V4.0)
// @namespace https://heybox.com/
// @version 4.0.0
// @description 全栈式小黑盒论坛内容过滤:支持帖子过滤(关键词/0赞0评)、评论区净化(插眼/关键词/纯表情/楼中楼),完美适配单页应用。
// @author 架构师AI & kun
// @match https://www.xiaoheihe.cn/app/bbs/*
// @icon https://www.xiaoheihe.cn/favicon.ico
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/554075/%E5%B0%8F%E9%BB%91%E7%9B%92%E5%85%A8%E8%83%BD%E5%87%80%E5%8C%96%E5%BC%95%E6%93%8E%20%28%E7%BB%88%E6%9E%81%E7%89%88%20V40%29.user.js
// @updateURL https://update.greasyfork.icu/scripts/554075/%E5%B0%8F%E9%BB%91%E7%9B%92%E5%85%A8%E8%83%BD%E5%87%80%E5%8C%96%E5%BC%95%E6%93%8E%20%28%E7%BB%88%E6%9E%81%E7%89%88%20V40%29.meta.js
// ==/UserScript==
(function () {
'use strict';
// ==========================================
// 1. 配置中心 (自动持久化)
// ==========================================
const Config = {
data: {
postKeywords: [], // 帖子屏蔽词
commentKeywords: ["副屏", "插眼", "cy", "攻略"], // 评论屏蔽词
blockZeroComment: false,
blockZeroLike: false,
blockPureEmoji: false, // 新增:屏蔽纯表情/空评论
hideMode: 'remove', // 'remove' 完全隐藏, 'dim' 虚化半透明
stats: { postsBlocked: 0, commentsBlocked: 0 }
},
load() {
const saved = GM_getValue('hb_ultimate_config_v4');
if (saved) {
this.data = { ...this.data, ...JSON.parse(saved) };
}
},
save() {
GM_setValue('hb_ultimate_config_v4', JSON.stringify(this.data));
UI.updateStats();
}
};
// ==========================================
// 2. 核心引擎 (双擎驱动 + SPA适配)
// ==========================================
const Engine = {
debounceTimer: null,
run() {
this.filterPosts();
this.filterComments();
},
// 模块A:帖子列表净化
filterPosts() {
const posts = document.querySelectorAll('a.hb-cpt__bbs-content');
let newlyBlocked = 0;
posts.forEach(post => {
if (post.dataset.hbProcessed === Config.data.hideMode) return;
const title = post.querySelector('.bbs-content__title')?.innerText || '';
const content = post.querySelector('.bbs-content__content')?.innerText || '';
const text = (title + content).toLowerCase();
const commentEl = post.querySelector('.content-list__comment-cnt');
const likeEl = post.querySelector('.content-list__like-cnt');
const comments = commentEl ? parseInt(commentEl.textContent.replace(/[^0-9]/g, '') || '0', 10) : -1;
const likes = likeEl ? parseInt(likeEl.textContent.replace(/[^0-9]/g, '') || '0', 10) : -1;
let shouldBlock = false;
if (Config.data.postKeywords.length > 0) {
shouldBlock = Config.data.postKeywords.some(k => text.includes(k.toLowerCase()));
}
if (!shouldBlock && Config.data.blockZeroComment && comments === 0) shouldBlock = true;
if (!shouldBlock && Config.data.blockZeroLike && likes === 0) shouldBlock = true;
if (shouldBlock) {
if (!post.dataset.hbBlocked) newlyBlocked++;
post.dataset.hbBlocked = 'true';
post.dataset.hbProcessed = Config.data.hideMode;
if (Config.data.hideMode === 'remove') {
post.style.display = 'none';
} else {
post.style.display = '';
post.style.opacity = '0.1';
post.style.pointerEvents = 'none';
}
} else {
post.dataset.hbBlocked = 'false';
post.dataset.hbProcessed = '';
post.style.display = '';
post.style.opacity = '1';
post.style.pointerEvents = 'auto';
}
});
if (newlyBlocked > 0) {
Config.data.stats.postsBlocked += newlyBlocked;
Config.save();
}
},
// 模块B:评论区净化 (主评论 + 楼中楼 + 纯表情)
filterComments() {
let newlyBlocked = 0;
const selectors = '.comment-item__content, .children-item__comment-content';
document.querySelectorAll(selectors).forEach(content => {
// 向上寻找该评论的最外层容器(兼容顶层评论和楼中楼)
const commentWrapper = content.closest('.link-comment__comment-item') || content.closest('.comment-children-item');
if (!commentWrapper || commentWrapper.dataset.hbProcessed === 'true') return;
const text = (content.innerText || "").trim();
const hasText = text.length > 0;
let shouldBlock = false;
// 规则1:官方插眼类 (.cy)
if (content.classList.contains('cy')) {
shouldBlock = true;
}
// 规则2:自定义关键词匹配
if (!shouldBlock && Config.data.commentKeywords.length > 0) {
shouldBlock = Config.data.commentKeywords.some(k => text.toLowerCase().includes(k.toLowerCase()));
}
// 规则3:纯表情/空评论 (没有文字的评论,通常只包含表情或完全为空)
if (!shouldBlock && Config.data.blockPureEmoji && !hasText) {
shouldBlock = true;
}
if (shouldBlock) {
commentWrapper.style.display = 'none';
commentWrapper.dataset.hbProcessed = 'true';
newlyBlocked++;
}
});
if (newlyBlocked > 0) {
Config.data.stats.commentsBlocked += newlyBlocked;
Config.save();
}
},
observe() {
const observer = new MutationObserver(() => {
clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(() => this.run(), 300);
});
// 监听整个 body 应对单页应用(SPA)的无刷新路由跳转
observer.observe(document.body, { childList: true, subtree: true });
},
refreshAll() {
// 清除帖子状态并恢复显示
document.querySelectorAll('a.hb-cpt__bbs-content').forEach(p => {
p.dataset.hbProcessed = '';
p.style.display = '';
p.style.opacity = '1';
p.style.pointerEvents = 'auto';
});
// 清除评论状态并恢复显示
document.querySelectorAll('.link-comment__comment-item, .comment-children-item').forEach(c => {
c.dataset.hbProcessed = '';
c.style.display = '';
});
// 重新扫描
this.run();
}
};
// ==========================================
// 3. UI控制器 (Shadow DOM 隔离)
// ==========================================
const UI = {
shadowRoot: null,
init() {
const host = document.createElement('div');
host.id = 'hb-ultimate-host';
document.body.appendChild(host);
this.shadowRoot = host.attachShadow({ mode: 'open' });
this.render();
this.bindEvents();
this.makeDraggable();
GM_registerMenuCommand("⚙️ 净化设置", () => {
const panel = this.shadowRoot.querySelector('#panel');
panel.style.display = panel.style.display === 'none' ? 'flex' : 'none';
});
},
render() {
const style = `
`;
const getTagsHTML = (arr, type) => arr.map(k => `