// ==UserScript==
// @name 广告终结者 v2.0
// @namespace http://tampermonkey.net/
// @version 2.0
// @description [13模块完整版] 动态检测、框架过滤、堆叠拦截、第三方拦截四大系统,增强广告拦截
// @author TMHhz
// @match *://*/*
// @license GPLv3
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_notification
// ==/UserScript==
(function() {
'use strict';
// 核心配置
const CONFIG = {
maxLogs: 100,
adKeywords: [
'ad', 'ads', 'advert', 'banner', 'popup', '推广', '广告', 'gg',
'advertisement', 'sponsor', '推荐', 'adv', 'guanggao', 'syad',
'bfad', '男男', '女女', '弹窗', '悬浮', '浮动', '浮窗', '葡京',
'pop', 'sticky', 'fixed', 'tip', 'tips', 'adbox', 'adsense',
'adserver', 'advertmarket', 'advertising', 'cookie-sync', '国产', '偷拍', '黑料', '横幅'
],
checkAttributes: [
'id', 'class', 'src', 'href', 'data-ad', 'name',
'data-src', 'data-url', 'alt', 'title', 'onclick', 'style'
],
protectionRules: {
minWidth: 50,
minHeight: 20,
iframeSizeThreshold: 2,
zIndexThreshold: 50,
sizeThresholdRatio: 0.15,
similarityThreshold: 0.8,
dynamicIdLength: 10,
dynamicIdDigits: 5,
fixedPositionThreshold: 2,
floatingKeywords: ['float', '悬浮', '弹窗', '浮窗', '浮动','横幅','fixed','sticky','tip','tips','pop'],
adImagePatterns: ['/*.gif', '/*.webp', '/*.swf'],
adContainerSelectors: ['[id*="side"]', '[class*="side"]'],
viewportEdgeThreshold: 10,
maxFrameDepth: 3,
textAdKeywords: ['限时优惠', '立即下载', '免费领取', 'vx:', '点击咨询', '低至1折', '加群', '抢购', '微信', 'telegram', '国产', '偷拍', '黑料']
},
whitelist: {
scriptNamespaces: ['pswMgrDialog', 'userscript-'],
protectedAttributes: [
{name: 'id', values: ['pswMgrDialog', 'userscript-quickFill']},
{name: 'class', values: ['userscript-quickFill']}
],
selectors: ['#pswMgrDialog', '.userscript-quickFill', '.userscript-pswmgrDlg'],
thirdparty: ['cdn.bootcss.com', 'unpkg.com']
},
defaultSettings: {
// 动态检测系统
dynamicIdDetection: true,
attributeSimilarity: true,
sizeAnomaly: true,
adAttributeDetection: true,
// 框架过滤系统
iframeAttributeCheck: true,
parentContainerCheck: true,
nestedFrameDetection: true,
// 堆叠拦截系统
highZIndexDetection: true,
fixedPositionCheck: true,
overlayDetection: true,
floatingLayerCheck: true,
// 第三方拦截
thirdpartyCheck: true,
cookieSyncDetection: true,
// 增强功能
floatingAdDetection: true,
imageAdDetection: true,
sidebarAdDetection: true,
textAdDetection: true
}
};
// ======================= 工具类 =======================
class AdUtils {
static safeRemove(node, module, reason) {
if (!node || !node.parentNode || this.isWhitelisted(node)) {
console.debug('[拦截跳过] 白名单元素:', node);
return false;
}
try {
Logger.logRemoval({
module,
element: {
tag: node.tagName,
id: node.id,
class: node.className,
html: node.outerHTML.slice(0, 500)
},
reason
});
node.parentNode.removeChild(node);
this.cleanAncestors(node.parentNode);
console.log('[成功移除]', module, node);
return true;
} catch (e) {
console.error('元素移除失败:', e);
return false;
}
}
static cleanAncestors(node) {
let current = node;
while (current && current !== document.documentElement) {
if (current.children.length === 0 &&
!current.hasAttribute('data-keep-empty')) {
const parent = current.parentNode;
parent?.removeChild(current);
current = parent;
} else {
break;
}
}
}
static isWhitelisted(element) {
let currentElement = element;
while (currentElement && currentElement !== document.documentElement) {
const src = currentElement.getAttribute('src');
if (src && CONFIG.whitelist.thirdparty.some(domain => src.includes(domain))) return true;
if (CONFIG.whitelist.selectors.some(s => currentElement.matches(s))) return true;
if (CONFIG.whitelist.protectedAttributes.some(attr => {
const attrValue = currentElement.getAttribute(attr.name);
return attrValue && attr.values.some(v =>
attr.name === 'class' ?
currentElement.classList.contains(v) :
attrValue.startsWith(v)
);
})) return true;
if (CONFIG.whitelist.scriptNamespaces.some(ns => {
const id = currentElement.id || '';
const className = currentElement.className || '';
return id.startsWith(ns) || className.startsWith(ns);
})) return true;
currentElement = currentElement.parentElement;
}
return false;
}
static calculateSimilarity(a, b) {
const setA = new Set(a.split(''));
const setB = new Set(b.split(''));
const intersection = new Set([...setA].filter(x => setB.has(x)));
return intersection.size / Math.max(setA.size, setB.size);
}
}
// ======================= 第三方拦截模块 =======================
class ThirdpartyInterceptor {
constructor() {
this.baseHost = this.getCurrentBaseHost();
this.initObserver();
}
getCurrentBaseHost() {
const host = location.hostname;
return this.isIP(host) ? host : this.getBaseDomain(host);
}
isIP(host) {
return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host);
}
getBaseDomain(url) {
try {
const parsed = new URL(url.startsWith('http') ? url : `http://${url}`);
const parts = parsed.hostname.split('.');
if (parts.length <= 1) return parsed.hostname;
return parts.slice(-2).join('.');
} catch {
return this.baseHost;
}
}
isThirdparty(src) {
if (!src || CONFIG.whitelist.thirdparty.some(d => src.includes(d))) return false;
try {
return this.getBaseDomain(src) !== this.baseHost;
} catch {
return false;
}
}
processNode(node) {
const tag = node.tagName.toUpperCase();
if (['SCRIPT', 'IFRAME'].includes(tag)) {
const src = node.getAttribute('src');
if (src && this.isThirdparty(src)) {
AdUtils.safeRemove(node, 'thirdparty', {
type: '第三方资源',
detail: `拦截源: ${this.getBaseDomain(src)}`
});
}
}
}
initObserver() {
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
this.processNode(node);
node.querySelectorAll('script, iframe').forEach(n => this.processNode(n));
}
});
});
});
observer.observe(document, {
childList: true,
subtree: true
});
document.querySelectorAll('script, iframe').forEach(n => this.processNode(n));
}
}
// ======================= 核心拦截系统 =======================
class CoreCleaner {
constructor() {
if (DomainConfig.getConfig('thirdpartyCheck')) {
this.thirdpartyInterceptor = new ThirdpartyInterceptor();
}
if (DomainConfig.getConfig('cookieSyncDetection')) {
this.cookieSyncCheck();
}
if (this.isAnyModuleEnabled()) {
this.initEnhancedObserver();
this.initialCleanup();
}
}
isAnyModuleEnabled() {
return Object.keys(CONFIG.defaultSettings).some(
key => DomainConfig.getConfig(key)
);
}
initEnhancedObserver() {
this.observer = new MutationObserver(mutations => {
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.shadowRoot) {
this.observer.observe(node.shadowRoot, {
childList: true,
subtree: true
});
}
this.checkGenericElements(node);
if (node.tagName === 'IFRAME') this.checkIframes(node);
if (['DIV', 'P', 'SPAN'].includes(node.tagName)) this.checkTextAds(node);
}
});
});
});
this.observer.observe(document, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class', 'id', 'src', 'href']
});
}
initialCleanup() {
if (!this.isAnyModuleEnabled()) return;
this.runDetectionSystems();
this.checkElements('iframe', this.checkIframes.bind(this));
this.checkElements('*', this.checkGenericElements.bind(this));
this.checkElements('img', this.checkImageAds.bind(this));
this.checkElements('*', this.checkFloatingAds.bind(this));
this.checkSidebarContainers();
this.checkElements('div,p,span', this.checkTextAds.bind(this));
}
runDetectionSystems() {
if (DomainConfig.getConfig('highZIndexDetection')) this.checkHighZIndex();
if (DomainConfig.getConfig('fixedPositionCheck')) this.checkFixedPosition();
if (DomainConfig.getConfig('overlayDetection')) this.checkOverlay();
if (DomainConfig.getConfig('floatingLayerCheck')) this.checkFloatingLayers();
}
checkElements(selector, checker) {
if (!this.isAnyModuleEnabled()) return;
document.querySelectorAll(selector).forEach(node => checker(node));
}
// ========== 框架过滤系统 ==========
checkIframes(iframe) {
if (DomainConfig.getConfig('iframeAttributeCheck')) {
this.checkIframeAttributes(iframe);
}
if (DomainConfig.getConfig('parentContainerCheck')) {
this.checkParentContainers(iframe);
}
if (DomainConfig.getConfig('nestedFrameDetection')) {
this.checkNestedFrames(iframe);
}
}
checkParentContainers(iframe) {
const parents = ['div', 'section', 'article']
.map(s => iframe.closest(s))
.filter(Boolean);
parents.forEach(parent => {
if (!AdUtils.isWhitelisted(parent)) {
AdUtils.safeRemove(parent, 'frame-parent', {
type: '父容器过滤',
detail: '可疑iframe容器'
});
}
});
}
checkIframeAttributes(iframe) {
const hasAdSrc = CONFIG.adKeywords.some(kw => iframe.src.includes(kw));
const isHidden = iframe.offsetWidth < CONFIG.protectionRules.iframeSizeThreshold ||
iframe.offsetHeight < CONFIG.protectionRules.iframeSizeThreshold;
if (isHidden || hasAdSrc) {
AdUtils.safeRemove(iframe, 'frame-attr', {
type: 'iframe属性',
detail: hasAdSrc ?
`广告源: ${iframe.src.slice(0, 50)}` :
`隐藏iframe: ${iframe.offsetWidth}x${iframe.offsetHeight}`
});
}
}
checkNestedFrames(iframe) {
try {
const depth = this.getFrameDepth(iframe);
if (depth > CONFIG.protectionRules.maxFrameDepth) {
AdUtils.safeRemove(iframe, 'nested-frame', {
type: '嵌套框架',
detail: `嵌套层级: ${depth}层`
});
}
} catch (e) {
console.log('框架深度检测异常:', e);
}
}
getFrameDepth(node) {
let depth = 0;
let currentNode = node;
while (currentNode.parentNode) {
if (currentNode.tagName === 'IFRAME') depth++;
currentNode = currentNode.parentNode;
}
return depth;
}
// ========== 动态检测系统 ==========
checkGenericElements(element) {
if (DomainConfig.getConfig('dynamicIdDetection')) {
this.checkDynamicId(element);
}
if (DomainConfig.getConfig('attributeSimilarity')) {
this.checkAttributeSimilarity(element);
}
if (DomainConfig.getConfig('sizeAnomaly')) {
this.checkSizeAnomaly(element);
}
if (DomainConfig.getConfig('adAttributeDetection')) {
this.checkAdAttributes(element);
}
}
checkDynamicId(element) {
const id = element.id || '';
if (id.length > CONFIG.protectionRules.dynamicIdLength ||
/\d{5,}/.test(id)) {
AdUtils.safeRemove(element, 'dynamic-id', {
type: '动态ID检测',
detail: `ID特征异常: ${id.slice(0, 50)}`
});
}
}
checkAttributeSimilarity(element) {
const id = element.id || '';
const className = element.className || '';
if (AdUtils.calculateSimilarity(id, className) > CONFIG.protectionRules.similarityThreshold) {
AdUtils.safeRemove(element, 'attr-similarity', {
type: '属性相似度',
detail: `ID与class相似度过高`
});
}
}
checkSizeAnomaly(element) {
const rect = element.getBoundingClientRect();
if (rect.width * rect.height >
window.innerWidth * window.innerHeight * CONFIG.protectionRules.sizeThresholdRatio) {
AdUtils.safeRemove(element, 'size-anomaly', {
type: '尺寸异常',
detail: `占用面积 ${Math.round(rect.width*rect.height)}px²`
});
}
}
checkAdAttributes(element) {
const attrCheck = CONFIG.checkAttributes.find(attr => {
const value = element.getAttribute(attr) || '';
return CONFIG.adKeywords.some(kw => value.includes(kw));
});
if (attrCheck) {
AdUtils.safeRemove(element, 'attr-match', {
type: '属性匹配',
attribute: attrCheck,
value: element.getAttribute(attrCheck).slice(0, 100)
});
}
}
// ========== 堆叠拦截系统 ==========
checkHighZIndex() {
document.querySelectorAll('body *').forEach(el => {
const zIndex = parseInt(getComputedStyle(el).zIndex);
if (!isNaN(zIndex) && zIndex > CONFIG.protectionRules.zIndexThreshold) {
AdUtils.safeRemove(el, 'z-index', {
type: '高堆叠',
detail: `z-index: ${zIndex}`
});
}
});
}
checkFixedPosition() {
const fixedElements = [];
document.querySelectorAll('*').forEach(el => {
const style = getComputedStyle(el);
if (style.position === 'fixed' && !AdUtils.isWhitelisted(el)) {
fixedElements.push(el);
}
});
if (fixedElements.length > CONFIG.protectionRules.fixedPositionThreshold) {
fixedElements.forEach(el => {
AdUtils.safeRemove(el, 'fixed-pos', {
type: '过量固定元素',
detail: `发现${fixedElements.length}个固定元素`
});
});
}
}
checkOverlay() {
document.querySelectorAll('div, section').forEach(el => {
const style = getComputedStyle(el);
if (style.backgroundColor !== 'rgba(0, 0, 0, 0)' &&
parseFloat(style.opacity) > 0.5 &&
el.offsetWidth >= window.innerWidth * 0.8) {
AdUtils.safeRemove(el, 'overlay', {
type: '遮罩层',
detail: `背景色: ${style.backgroundColor}`
});
}
});
}
checkFloatingLayers() {
document.querySelectorAll('*').forEach(el => {
const style = getComputedStyle(el);
if (style.position === 'fixed' &&
(el.offsetWidth < 200 || el.offsetHeight < 100)) {
AdUtils.safeRemove(el, 'floating-layer', {
type: '悬浮层',
detail: `小型浮动元素: ${el.offsetWidth}x${el.offsetHeight}`
});
}
});
}
// ========== 增强功能模块 ==========
checkFloatingAds(element) {
if (!DomainConfig.getConfig('floatingAdDetection')) return;
const style = getComputedStyle(element);
const isFixed = style.position === 'fixed';
const isSticky = style.position === 'sticky';
const hasFloatingClass = CONFIG.protectionRules.floatingKeywords.some(kw =>
element.className.includes(kw) || element.id.includes(kw)
);
const rect = element.getBoundingClientRect();
const edgeDetected =
rect.top <= CONFIG.protectionRules.viewportEdgeThreshold ||
rect.bottom >= window.innerHeight - CONFIG.protectionRules.viewportEdgeThreshold ||
rect.left <= CONFIG.protectionRules.viewportEdgeThreshold ||
rect.right >= window.innerWidth - CONFIG.protectionRules.viewportEdgeThreshold;
if ((isFixed || isSticky || hasFloatingClass) && edgeDetected) {
AdUtils.safeRemove(element, 'floating-ad', {
type: '浮动广告',
detail: `定位方式: ${style.position}, 位置: ${Math.round(rect.top)}px`
});
}
}
checkImageAds(img) {
if (!DomainConfig.getConfig('imageAdDetection')) return;
const src = img.src.toLowerCase();
const isAdImage = CONFIG.protectionRules.adImagePatterns.some(pattern =>
src.endsWith(pattern) || src.includes('adimg')
);
const adDimensions = [
[728, 90], [300, 250], [336, 280], [250, 250], [120, 600],
[160, 600], [468, 60], [900, 100]
];
const isAdSize = adDimensions.some(([w, h]) =>
Math.abs(img.width - w) < 10 &&
Math.abs(img.height - h) < 10
);
if (isAdImage || isAdSize) {
AdUtils.safeRemove(img, 'image-ad', {
type: '图片广告',
detail: `尺寸: ${img.width}x${img.height}, 源: ${src.slice(0, 50)}`
});
}
}
checkSidebarContainers() {
if (!DomainConfig.getConfig('sidebarAdDetection')) return;
document.querySelectorAll(CONFIG.protectionRules.adContainerSelectors.join(',')).forEach(container => {
const rect = container.getBoundingClientRect();
const isSidePositioned =
rect.left <= 10 ||
rect.right >= window.innerWidth - 10;
if (isSidePositioned && container.offsetHeight > 200) {
AdUtils.safeRemove(container, 'sidebar-ad', {
type: '侧边栏容器',
detail: `位置: ${Math.round(rect.left)}px, 高度: ${container.offsetHeight}px`
});
}
});
}
checkTextAds(element) {
if (!DomainConfig.getConfig('textAdDetection')) return;
const text = element.textContent.toLowerCase();
const isSuspicious = CONFIG.protectionRules.textAdKeywords.some(kw =>
text.includes(kw.toLowerCase())
);
if (isSuspicious && element.children.length === 0) {
AdUtils.safeRemove(element, 'text-ad', {
type: '文本广告',
detail: `包含关键词: ${text.slice(0,30)}`
});
}
}
cookieSyncCheck() {
document.querySelectorAll('script').forEach(script => {
const src = script.getAttribute('src');
if (src && src.includes('cookie') && src.includes('sync')) {
AdUtils.safeRemove(script, 'cookie-sync', {
type: 'Cookie同步',
detail: `检测到同步脚本: ${src.slice(0, 50)}`
});
}
});
}
destructor() {
if (this.observer) this.observer.disconnect();
}
}
// ======================= 配置系统 =======================
class DomainConfig {
static get currentDomain() {
return location.hostname.replace(/^www\./, '');
}
static getConfig(key) {
const allConfigs = GM_getValue('domainConfigs', {});
const domainConfig = allConfigs[this.currentDomain] || {...CONFIG.defaultSettings};
return key in domainConfig ? domainConfig[key] : CONFIG.defaultSettings[key];
}
static updateConfig(key, value) {
const allConfigs = GM_getValue('domainConfigs', {});
if (!allConfigs[this.currentDomain]) {
allConfigs[this.currentDomain] = {...CONFIG.defaultSettings};
}
allConfigs[this.currentDomain][key] = value;
GM_setValue('domainConfigs', allConfigs);
}
static resetConfig() {
const allConfigs = GM_getValue('domainConfigs', {});
delete allConfigs[this.currentDomain];
GM_setValue('domainConfigs', allConfigs);
}
}
// ======================= 用户界面 =======================
class UIController {
static init() {
this.registerDomainControls();
this.registerGlobalControls();
this.registerInfoButton();
this.registerMasterSwitch();
}
static registerMasterSwitch() {
const allEnabled = Object.keys(CONFIG.defaultSettings).every(
key => DomainConfig.getConfig(key)
);
GM_registerMenuCommand(
`🔘 一键${allEnabled ? '禁用' : '启用'}所有模块`,
() => this.toggleAllModules()
);
}
static toggleAllModules() {
const allKeys = Object.keys(CONFIG.defaultSettings);
const currentState = allKeys.every(key => DomainConfig.getConfig(key));
allKeys.forEach(key => {
DomainConfig.updateConfig(key, !currentState);
});
GM_notification({
title: '总开关已切换',
text: `所有模块已${!currentState ? '启用' : '禁用'}`,
timeout: 2000
});
window.location.reload();
}
static registerInfoButton() {
GM_registerMenuCommand('📘 13模块说明', () => this.showInstructions());
}
static showInstructions() {
const instructions = `【广告终结者v1.3 - 13大模块说明】
██ 核心拦截系统 ██
1. 第三方资源拦截
✔ 拦截规则:
- 非本站域名的<script>/<iframe>
- 排除白名单中的CDN资源
- 自动识别跟踪脚本
2. iframe属性检测
✔ 拦截规则:
- 尺寸<2x2像素的隐藏框架
- src包含50+广告关键词
- 移除iframe及父容器
3. 父容器检测
✔ 拦截规则:
- 包裹iframe的div/section
- 无有效内容的空容器
- 多层嵌套广告容器
██ 动态检测系统 ██
4. 动态ID检测
✔ 拦截规则:
- ID长度>10字符
- 包含5+连续数字
- 示例:ad_12345
5. 属性相似度
✔ 拦截规则:
- ID与class相似度>80%
- 属性值重复率过高
- 示例:id="ad" class="ad-box"
6. 尺寸异常
✔ 拦截规则:
- 元素面积>屏幕15%
- 自动计算视窗占比
- 响应式布局识别
7. 广告属性检测
✔ 拦截规则:
- 12个属性关键词匹配
- 50+中英文广告词库
- 支持data-*属性
██ 堆叠拦截系统 ██
8. 高z-index检测
✔ 拦截规则:
- z-index值>50
- 排除导航菜单等白名单
- 动态堆叠上下文分析
9. 固定定位检测
✔ 拦截规则:
- fixed元素>2个
- 识别"回到顶部"等正常元素
- 支持sticky定位
10. 遮罩层检测
✔ 拦截规则:
- 半透明背景(rgba)
- 覆盖80%屏幕宽度
- 防点击劫持
11. 浮动层检测
✔ 拦截规则:
- 边缘吸附<10px
- 含float/sticky定位
- 30+中文特征词
██ 增强功能模块 ██
12. 嵌套框架检测
✔ 拦截规则:
- iframe嵌套>3层
- 空白嵌套框架
- 跨域嵌套容器
13. 文本广告检测
✔ 拦截规则:
- 包含20+营销关键词
- 无子元素的纯文本
- 微信号/QQ号识别`;
alert(instructions);
}
static registerDomainControls() {
const SEPARATOR = '───────────────';
GM_registerMenuCommand(SEPARATOR, () => {});
this.registerModuleControls([
'thirdpartyCheck',
'dynamicIdDetection',
'attributeSimilarity',
'sizeAnomaly',
'adAttributeDetection'
]);
GM_registerMenuCommand(SEPARATOR, () => {});
this.registerModuleControls([
'iframeAttributeCheck',
'parentContainerCheck',
'nestedFrameDetection'
]);
GM_registerMenuCommand(SEPARATOR, () => {});
this.registerModuleControls([
'highZIndexDetection',
'fixedPositionCheck',
'overlayDetection',
'floatingLayerCheck'
]);
GM_registerMenuCommand(SEPARATOR, () => {});
this.registerModuleControls([
'floatingAdDetection',
'imageAdDetection',
'sidebarAdDetection',
'textAdDetection',
'cookieSyncDetection'
]);
GM_registerMenuCommand(SEPARATOR, () => {});
GM_registerMenuCommand('🔄 重置当前网站设置', () => {
DomainConfig.resetConfig();
GM_notification({
title: '配置已重置',
text: `${DomainConfig.currentDomain} 设置已恢复默认`,
timeout: 2000
});
window.location.reload();
});
}
static registerModuleControls(keys) {
keys.forEach(key => {
const currentValue = DomainConfig.getConfig(key);
GM_registerMenuCommand(
` ${this.getKeyName(key)} [${currentValue ? '✅' : '❌'}]`,
() => this.toggleConfig(key)
);
});
}
static registerGlobalControls() {
GM_registerMenuCommand('📜 查看拦截日志', this.showLogs.bind(this));
GM_registerMenuCommand('🧹 清除当前日志', this.clearLogs.bind(this));
}
static toggleConfig(key) {
const current = DomainConfig.getConfig(key);
DomainConfig.updateConfig(key, !current);
GM_notification({
title: '配置已更新',
text: `${this.getKeyName(key)} 已${!current ? '启用' : '禁用'}`,
timeout: 1500
});
window.location.reload();
}
static getKeyName(key) {
const names = {
thirdpartyCheck: '第三方拦截',
dynamicIdDetection: '动态ID检测',
attributeSimilarity: '属性相似度',
sizeAnomaly: '尺寸异常',
adAttributeDetection: '广告属性检测',
iframeAttributeCheck: 'iframe属性',
parentContainerCheck: '父容器检测',
nestedFrameDetection: '嵌套框架检测',
highZIndexDetection: '高z-index',
fixedPositionCheck: '固定定位',
overlayDetection: '遮罩层检测',
floatingLayerCheck: '浮动层检测',
floatingAdDetection: '浮动广告检测',
imageAdDetection: '图片广告检测',
sidebarAdDetection: '侧边栏检测',
textAdDetection: '文本广告检测',
cookieSyncDetection: 'Cookie同步检测'
};
return names[key] || key;
}
static showLogs() {
const logs = Logger.getDomainLogs();
alert(logs.length ?
`【${DomainConfig.currentDomain}】拦截记录:\n\n${Logger.formatLogs(logs)}` :
'当前无拦截记录');
}
static clearLogs() {
Logger.clearDomainLogs();
GM_notification({title: '日志已清除', timeout: 1500});
}
}
// ======================= 日志系统 =======================
class Logger {
static logRemoval(record) {
const allLogs = GM_getValue('removalLogs', {});
const domainLogs = allLogs[DomainConfig.currentDomain] || [];
domainLogs.push({
timestamp: new Date().toLocaleString(),
...record
});
if (domainLogs.length > CONFIG.maxLogs) domainLogs.shift();
allLogs[DomainConfig.currentDomain] = domainLogs;
GM_setValue('removalLogs', allLogs);
}
static getDomainLogs() {
const allLogs = GM_getValue('removalLogs', {});
return allLogs[DomainConfig.currentDomain] || [];
}
static clearDomainLogs() {
const allLogs = GM_getValue('removalLogs', {});
delete allLogs[DomainConfig.currentDomain];
GM_setValue('removalLogs', allLogs);
}
static formatLogs(logs) {
return logs.map((log, index) =>
`[${index + 1}] ${log.timestamp}\n模块: ${log.module}\n` +
`类型: ${log.reason.type}\n详情: ${log.reason.detail || ''}`
).join('\n\n');
}
}
// ======================= 系统初始化 =======================
let coreCleaner;
function initialize() {
if (coreCleaner) coreCleaner.destructor();
coreCleaner = new CoreCleaner();
}
initialize();
UIController.init();
// CSS防护规则
const antiRevertStyle = document.createElement('style');
antiRevertStyle.textContent = `
html::-webkit-scrollbar { width: 0 !important }
[style*="overflow:hidden"] { overflow: visible !important }
[data-ad-container] { display: none !important }
`;
document.head.appendChild(antiRevertStyle);
})();