您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
隐藏 Bangumi 上的 NSFW 条目
// ==UserScript== // @name Bangumi 隐藏NSFW条目 // @version 3.3 // @description 隐藏 Bangumi 上的 NSFW 条目 // @author 墨云 // @match https://bangumi.tv/* // @match https://chii.in/* // @match https://bgm.tv/* // @grant none // @namespace https://greasyfork.org/users/1354622 // ==/UserScript== (function() { 'use strict'; if (window.location.pathname.startsWith('/subject/')) { return; } const SETTING_KEY = 'bangumi_hide_nsfw_mode'; const CACHE_EXPIRY = 7 * 24 * 60 * 60 * 1000; async function isSubjectChecked(subjectId) { const cacheKey = `nsfw_cache_${subjectId}`; const cachedData = localStorage.getItem(cacheKey); if (cachedData) { try { const data = JSON.parse(cachedData); if (Date.now() < data.timestamp + CACHE_EXPIRY) { return data.value; } } catch (e) { localStorage.removeItem(cacheKey); } } try { const response = await fetch(`/subject/${subjectId}`); const text = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(text, 'text/html'); const isChecked = !!doc.querySelector('a[href*="/tag/R18"]'); if (!isChecked) { console.warn(`R18 tag not found on page for subjectId: ${subjectId}`); } const dataToCache = { value: isChecked, timestamp: Date.now() }; localStorage.setItem(cacheKey, JSON.stringify(dataToCache)); return isChecked; } catch (error) { console.error('Failed to fetch subject detail:', error, 'for subjectId:', subjectId); const dataToCache = { value: false, timestamp: Date.now() }; localStorage.setItem(cacheKey, JSON.stringify(dataToCache)); return false; } } function getSubjectIdFromLink(link) { const url = link.href; const match = url.match(/\/subject\/(\d+)/); return match ? match[1] : null; } async function applyMode(mode, rootElement = document) { const links = rootElement.querySelectorAll('a[href*="/subject/"]'); const promises = []; for (const link of links) { const subjectId = getSubjectIdFromLink(link); if (subjectId) { promises.push(isSubjectChecked(subjectId).then(isChecked => { if (isChecked) { let containerToHide = link.closest('.mainItem, .subject_grid_list > li, .item, .subject-item, .clearit, .info_item, li.line_list, li.clearit, .home_subject_list > li, .list > li, .grid > li'); if (!containerToHide) { containerToHide = link.closest('[id^="item_"]'); } if (!containerToHide) { containerToHide = link.closest('li'); } if (!containerToHide) { console.warn('Could not find a container to hide for the link:', link.href); } if (containerToHide) { containerToHide.style.display = (mode === 'hide') ? 'none' : ''; } } })); } } await Promise.all(promises); } function addNSFWSetting() { if (typeof chiiLib === 'undefined' || typeof chiiLib.ukagaka === 'undefined') { return; } chiiLib.ukagaka.addGeneralConfig({ title: 'NSFW', name: 'nsfwMode', type: 'radio', defaultValue: 'off', getCurrentValue: function() { return $.cookie(SETTING_KEY) || 'off'; }, onChange: function(value) { $.cookie(SETTING_KEY, value, {expires: 30, path: '/'}); applyMode(value); }, options: [ { value: 'off', label: '显示' }, { value: 'hide', label: '隐藏' } ] }); } async function init() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { addNSFWSetting(); const currentMode = $.cookie(SETTING_KEY) || 'off'; applyMode(currentMode); }); } else { addNSFWSetting(); const currentMode = $.cookie(SETTING_KEY) || 'off'; applyMode(currentMode); } const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE && node.querySelector('a[href*="/subject/"]')) { console.log('Detected new entries being loaded. Applying settings...'); applyMode($.cookie(SETTING_KEY) || 'off', node); } }); } } }); observer.observe(document.body, { childList: true, subtree: true }); } init(); })();