// ==UserScript== // @name Porn Blocker | 色情内容过滤器 // @name:en Porn Blocker // @name:zh-CN 色情内容过滤器 // @name:zh-TW 色情內容過濾器 // @name:zh-HK 色情內容過濾器 // @name:ja アダルトコンテンツブロッカー // @name:ko 성인 컨텐츠 차단기 // @name:ru Блокировщик порнографии // @namespace https://noctiro.moe // @version 2.0.1 // @description A powerful content blocker that helps protect you from inappropriate websites. Features: Auto-detection of adult content, Multi-language support, Smart scoring system, Safe browsing protection. // @description:en A powerful content blocker that helps protect you from inappropriate websites. Features: Auto-detection of adult content, Multi-language support, Smart scoring system, Safe browsing protection. // @description:zh-CN 强大的网页过滤工具,帮助你远离不良网站。功能特点:智能检测色情内容,多语言支持,评分系统,安全浏览保护,支持自定义过滤规则。为了更好的网络环境,从我做起。 // @description:zh-TW 強大的網頁過濾工具,幫助你遠離不良網站。功能特點:智能檢測色情內容,多語言支持,評分系統,安全瀏覽保護,支持自定義過濾規則。為了更好的網絡環境,從我做起。 // @description:zh-HK 強大的網頁過濾工具,幫助你遠離不良網站。功能特點:智能檢測色情內容,多語言支持,評分系統,安全瀏覽保護,支持自定義過濾規則。為了更好的網絡環境,從我做起。 // @description:ja アダルトコンテンツを自動的にブロックする強力なツールです。機能:アダルトコンテンツの自動検出、多言語対応、スコアリングシステム、カスタマイズ可能なフィルタリング。より良いインターネット環境のために。 // @description:ko 성인 컨텐츠를 자동으로 차단하는 강력한 도구입니다. 기능: 성인 컨텐츠 자동 감지, 다국어 지원, 점수 시스템, 안전 브라우징 보호, 맞춤형 필터링 규칙。 // @description:ru Мощный инструмент для блокировки неприемлемого контента. Функции: автоматическое определение, многоязычная поддержка, система оценки, настраиваемые правила фильтрации。 // @license Apache-2.0 // @match *://*/* // @run-at document-start // @run-at document-end // @run-at document-idle // @grant none // @compatible Chrome/80+ // @compatible Firefox/68+ // @compatible Edge/80+ // @compatible Opera/66+ // @compatible Safari/13+ // @compatible Brave/1.0+ // @compatible Vivaldi/2.11+ // @compatible Yandex/20+ // @compatible UC/13+ // @compatible QQBrowser/10+ // @compatible 360Browser/13+ // @downloadURL none // ==/UserScript== (function () { 'use strict'; // 多语言支持 const i18n = { 'en': { title: '🚫 Access Blocked', message: 'This webpage has been identified as inappropriate content.', redirect: 'Redirecting in 4 seconds...', footer: 'Stay healthy · Stay away from harmful content' }, 'zh-CN': { title: '🚫 访问已被拦截', message: '该网页已被识别为不健康内容。', redirect: '4 秒后自动跳转...', footer: '注意身心健康 · 远离不良网站' }, 'zh-TW': { title: '🚫 訪問已被攔截', message: '該網頁已被識別為不健康內容。', redirect: '4 秒後自動跳轉...', footer: '注意身心健康 · 遠離不良網站' }, 'zh-HK': { title: '🚫 訪問已被攔截', message: '該網頁已被識別為不健康內容。', redirect: '4 秒後自動跳轉...', footer: '注意身心健康 · 遠離不良網站' }, 'ja': { title: '🚫 アクセスがブロックされました', message: 'このページは不適切なコンテンツとして識別されました。', redirect: '4 秒後にリダイレクトします...', footer: '健康に注意 · 有害サイトに近づかない' }, 'ko': { title: '🚫 접근이 차단됨', message: '이 웹페이지가 부적절한 콘텐츠로 식별되었습니다.', redirect: '4초 후 자동으로 이동됩니다...', footer: '건강 관리 · 유해 사이트 멀리하기' }, 'ru': { title: '🚫 Доступ заблокирован', message: 'Эта веб-страница определена как неподходящий контент.', redirect: 'Перенаправление через 4 секунды...', footer: 'Будьте здоровы · Держитесь подальше от вредного контента' } }; // 获取用户语言 const getUserLanguage = () => { const lang = navigator.language || navigator.userLanguage; // 检查完整语言代码 if (i18n[lang]) return lang; // 处理中文的特殊情况 if (lang.startsWith('zh')) { const region = lang.toLowerCase(); if (region.includes('tw') || region.includes('hant')) return 'zh-TW'; if (region.includes('hk')) return 'zh-HK'; return 'zh-CN'; } // 检查简单语言代码 const shortLang = lang.split('-')[0]; if (i18n[shortLang]) return shortLang; return 'en'; }; // 浏览器检测函数 const getBrowserType = () => { const ua = navigator.userAgent.toLowerCase(); // Add more browser detection if (ua.includes('ucbrowser')) return 'uc'; if (ua.includes('qqbrowser')) return 'qq'; if (ua.includes('2345explorer')) return '2345'; if (ua.includes('360') || ua.includes('qihu')) return '360'; if (ua.includes('maxthon')) return 'maxthon'; if (ua.includes('firefox')) return 'firefox'; if (ua.includes('edg')) return 'edge'; if (ua.includes('opr') || ua.includes('opera')) return 'opera'; if (ua.includes('brave')) return 'brave'; if (ua.includes('vivaldi')) return 'vivaldi'; if (ua.includes('yabrowser')) return 'yandex'; if (ua.includes('chrome')) return 'chrome'; if (ua.includes('safari') && !ua.includes('chrome')) return 'safari'; return 'other'; }; // 获取浏览器主页URL const getHomePageUrl = () => { switch (getBrowserType()) { case 'firefox': return 'about:home'; case 'chrome': return 'chrome://newtab'; case 'edge': return 'edge://newtab'; case 'safari': return 'topsites://'; case 'opera': return 'opera://startpage'; case 'brave': return 'brave://newtab'; case 'vivaldi': return 'vivaldi://newtab'; case 'yandex': return 'yandex://newtab'; case 'uc': return 'ucenterhome://'; case 'qq': return 'qbrowser://home'; case '360': return 'se://newtab'; case 'maxthon': return 'mx://newtab'; case '2345': return '2345explorer://newtab'; default: // Fallback to a safe default return 'about:blank'; } }; // ----------------- 预编译正则规则 (性能优化) ----------------- const regexCache = { // 色情关键词正则(预编译,避免重复生成) pornRegex: null, // 白名单正则(预编译) whitelistRegex: null, // .xxx后缀正则 xxxRegex: /\.xxx$/i }; // ----------------- 配置项(用户可按需修改) ----------------- const config = { // ================== 色情关键词评分规则 ================== pornKeywords: { // 核心高危词(权重≥3) 'porn': 3, 'nsfw': 3, 'xxx': 3, 'xxxvideos': 3, 'hentai': 3, 'incest': 4, 'rape': 4, 'childporn': 4, 'av': 3, // 身体部位关键词(权重2) 'pussy': 2, 'cock': 2, 'dick': 2, 'boobs': 2, 'tits': 2, 'ass': 2, 'beaver': 1, // 特定群体(权重2~3) 'teen': 3, 'sis': 2, 'milf': 2, 'cuckold': 3, 'virgin': 2, 'luoli': 2, 'gay': 2, // 具体性行为(权重2~3) 'anal': 3, 'blowjob': 3, 'creampie': 2, 'bdsm': 2, 'masturbat': 2, 'doggy': 3, 'handjob': 3, 'footjob': 3, 'rimjob': 3, 'piledriver': 3, 'legjob': 3, 'heeljob': 3, 'pussyjob': 3, 'assjobs': 3, 'hotdogging': 3, 'balljob': 3, // 其他相关词汇(权重1~2) 'camgirl': 2, 'webcam': 2, 'onlyfans': 2, 'nsfwgifs': 3, 'leaked': 2, 'fap': 2, 'erotic': 1, 'escort': 3, 'tube': 1, 'nude': 3, 'naked': 3, 'upskirt': 2, // 高危词 'pornhub': 4, 'xvideo': 4, 'redtube': 4, 'jav': 4, 'youporn': 4, 'spankbang': 4, 'xnxx': 4, 'xhamster': 4, '4tube': 4, 'myfreecams': 4, 'missav': 4, 'onlyfans': 2, 'rule34': 4, 'youjizz': 4, 'paidaa': 4, '3c5g9': 4, // 变体检测 'p0rn': 3, 'pr0n': 3, 'pron': 3, 's3xy': 3, 'sexx': 3, 'adultt': 3, 'porno': 3, // 多语言支持 '情色': 3, '成人': 3, '做爱': 4, 'セックス': 3, 'エロ': 3, '淫': 4, 'секс': 3, 'порн': 3, '性爱': 3, '無修正': 3, 'ポルノ': 3, 'порно': 3, '色情': 3, '海角社区': 4, }, // ================== 白名单减分规则 ================== whitelist: { // 强豁免词(权重-10) 'edu': -10, 'health': -10, 'medical': -10, 'science': -10, 'gov': -10, 'org': -10, 'official': -10, // 常用场景豁免(权重-7) 'academy': -7, 'clinic': -7, 'therapy': -7, 'university': -4, 'research': -7, 'news': -7, 'dictionary': -7, 'library': -7, 'museum': -7, // 动物/自然相关(权重-1) 'animal': -4, 'zoo': -1, 'cat': -1, 'dog': -1, 'pet': -6, 'bird': -1, 'vet': -1, // 科技类(权重-5) 'tech': -5, 'cloud': -5, 'software': -5, 'cyber': -3, }, // ================== 阈值配置 ================== thresholds: { block: 3, // 总分触发阈值(建议3~4) path: 2, // URL路径加分阈值 whitelist: 2 // 进行白名单减分的最低阈值 }, // ================== 域名正则表达式规则 ================== domainPatterns: [ /^mogu\d+\.[a-z]{2,3}$/i, /\d{3}[a-z]{2}/i, /[a-z]{2}\d{3}/i, ], }; // 域名正则检测函数 const checkDomainPatterns = (hostname) => { return config.domainPatterns.some(pattern => pattern.test(hostname)); }; // 预处理正则(仅初始化一次) (function initRegex() { // 色情关键词正则:生成 /porn|xxx|sex|.../gi const pornTerms = Object.keys(config.pornKeywords).join('|'); regexCache.pornRegex = new RegExp(`(${pornTerms})`, 'gi'); // 白名单正则:生成 /education|health|animal/gi const whitelistTerms = Object.keys(config.whitelist).join('|'); regexCache.whitelistRegex = new RegExp(`(${whitelistTerms})`, 'gi'); })(); // ----------------- 评分计算函数 ----------------- const calculateScore = (text) => { // 首先计算色情关键词得分 let score = 0; const pornMatches = text.match(regexCache.pornRegex) || []; pornMatches.forEach(match => { const keyword = match.toLowerCase(); score += config.pornKeywords[keyword] || 0; }); // 只有当分数达到白名单阈值时才进行白名单评分 if (score >= config.thresholds.whitelist) { const whitelistMatches = text.match(regexCache.whitelistRegex) || []; whitelistMatches.forEach(match => { const term = match.toLowerCase(); score += config.whitelist[term] || 0; }); } return score; }; // ----------------- 主检测逻辑 ----------------- const checkUrl = () => { const url = new URL(window.location.href); // 首先检查域名正则表达式 if (checkDomainPatterns(url.hostname)) { return { shouldBlock: true, url: url }; } // 继续原有的评分检测 let score = 0; const pornMatches = url.hostname.match(regexCache.pornRegex) || []; pornMatches.forEach(match => { const keyword = match.toLowerCase(); score += config.pornKeywords[keyword] || 0; }); // 检查路径 const path = url.pathname + url.search; const pathScore = calculateScore(path) * 0.4; score += pathScore; // 检查标题 const titlePornScore = calculateScore(document.title || ""); score += titlePornScore; // 如果超过阈值则白名单减分 if (score >= config.thresholds.whitelist) { const hostMatches = url.hostname.match(regexCache.whitelistRegex) || []; const titleMatches = document.title.match(regexCache.whitelistRegex) || []; function whitelistMatchCount(matches) { matches.forEach(match => { const term = match.toLowerCase(); score += config.whitelist[term] || 0; }); } whitelistMatchCount(hostMatches); whitelistMatchCount(titleMatches); } // 返回评分和URL对象 return { shouldBlock: score >= config.thresholds.block, url: url }; }; // 获取结果 const { shouldBlock: shouldBlock, url: currentUrl } = checkUrl(); if (shouldBlock || regexCache.xxxRegex.test(currentUrl.hostname)) { const lang = getUserLanguage(); const text = i18n[lang]; window.stop(); document.documentElement.innerHTML = `
${text.message}
${text.redirect}