您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Blurs images in topics or replies marked as NSFW or by specified users on Bangumi sites.
// ==UserScript== // @name Bangumi NSFW Image Blurrer // @version 0.1.1 // @description Blurs images in topics or replies marked as NSFW or by specified users on Bangumi sites. // @match https://bgm.tv/group/* // @match https://bangumi.tv/group/* // @match https://chii.in/group/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @run-at document-end // @license MIT // @namespace bgmtv // ==/UserScript== (function() { 'use strict'; // --- Configuration --- const DEFAULT_BLUR_AMOUNT = '10px'; const DEFAULT_NSFW_KEYWORDS = ['nsfw', '色图']; let blurAmount = DEFAULT_BLUR_AMOUNT; let nsfwKeywords = []; function loadSettings() { blurAmount = GM_getValue('blurAmount_bgm', DEFAULT_BLUR_AMOUNT); nsfwKeywords = GM_getValue('nsfwKeywords_bgm', DEFAULT_NSFW_KEYWORDS.join(',')).split(',') .map(keyword => keyword.trim()) .filter(keyword => keyword); } // Add blur amount setting menu GM_registerMenuCommand('Set Blur Amount', () => { const currentAmount = GM_getValue('blurAmount_bgm', DEFAULT_BLUR_AMOUNT); const newAmount = prompt( 'Enter blur amount (e.g. 5px, 10px, 15px):\nDefault: 10px', currentAmount ); if (newAmount !== null) { if (/^\d+px$/.test(newAmount)) { GM_setValue('blurAmount_bgm', newAmount); blurAmount = newAmount; updateStyles(); applyBlurringLogic(); } else { console.warn('[BGM NSFW Protection] Invalid blur amount format. Please use format like "10px"'); alert('Invalid format. Please use format like "10px"'); } } }); // Update addGlobalStyle function function updateStyles() { const styleElement = document.getElementById('nsfw-blur-style'); if (styleElement) styleElement.remove(); addGlobalStyle(` .nsfw-blur-userscript { filter: blur(${blurAmount}) !important; transition: filter 0.25s ease-out !important; } .nsfw-blur-userscript:hover { filter: blur(0px) !important; } `, 'nsfw-blur-style'); } // Modified addGlobalStyle to support ID function addGlobalStyle(css, id = '') { const head = document.getElementsByTagName('head')[0]; if (!head) { console.error('[BGM NSFW Protection] Cannot find head element'); return; } const style = document.createElement('style'); if (id) style.id = id; style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } function loadNsfwKeywords() { nsfwKeywords = GM_getValue('nsfwKeywords_bgm', DEFAULT_NSFW_KEYWORDS.join(',')).split(',') .map(keyword => keyword.trim()) .filter(keyword => keyword); } GM_registerMenuCommand('Set NSFW Keywords', () => { const currentKeywords = GM_getValue('nsfwKeywords_bgm', DEFAULT_NSFW_KEYWORDS.join(',')); const newKeywordsInput = prompt( 'Enter comma-separated NSFW keywords (Latin letters are case-insensitive):\nExample: nsfw,色图,R18', currentKeywords ); if (newKeywordsInput !== null) { GM_setValue('nsfwKeywords_bgm', newKeywordsInput); loadNsfwKeywords(); applyBlurringLogic(); } }); function checkNsfwKeywords(text) { return nsfwKeywords.some(keyword => { // For Latin letters, use case-insensitive comparison if (/^[a-zA-Z]+$/.test(keyword)) { return text.toLowerCase().includes(keyword.toLowerCase()); } // For other characters (like Chinese), use case-sensitive comparison return text.includes(keyword); }); } // --- Styles --- function addGlobalStyle(css) { const head = document.getElementsByTagName('head')[0]; if (!head) { return; } const style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } addGlobalStyle(` .nsfw-blur-userscript { filter: blur(${blurAmount}) !important; transition: filter 0.25s ease-out !important; } .nsfw-blur-userscript:hover { filter: blur(0px) !important; } `); // --- NSFW User ID Management --- let nsfwUserIds = []; function loadNsfwUserIds() { nsfwUserIds = GM_getValue('nsfwUserIds_bgm', '').split(',') .map(id => id.trim().toLowerCase()) .filter(id => id); } GM_registerMenuCommand('Set NSFW User IDs', () => { const currentIds = GM_getValue('nsfwUserIds_bgm', ''); const newIdsInput = prompt('Enter comma-separated NSFW user IDs (usernames as seen in URL, e.g., `217781` (金刚可怜)):', currentIds); if (newIdsInput !== null) { GM_setValue('nsfwUserIds_bgm', newIdsInput); loadNsfwUserIds(); applyBlurringLogic(); // Re-apply logic after changing settings } }); // --- Blurring Logic --- function blurImagesInElement(element) { if (!element) return; const images = element.querySelectorAll('img'); // Blurs all img tags, including emojis. // If you want to be more specific, e.g., only 'img.code': // const images = element.querySelectorAll('img.code, .topic_content > img, .message > img'); images.forEach(img => { // Avoid re-blurring images in quotes if the parent is already blurred if (img.closest('.nsfw-blur-userscript') && !img.closest('.quote')) { // If image is inside something already blurred, and not in a quote that might be safe if(!img.parentElement.classList.contains('nsfw-blur-userscript')) { //img.classList.add('nsfw-blur-userscript'); } } else { img.classList.add('nsfw-blur-userscript'); } }); } function applyBlurringLogic() { try { loadNsfwUserIds(); loadSettings(); const topicTitleElement = document.querySelector('#pageHeader h1'); const mainPostContainer = document.querySelector('.postTopic[data-item-user]'); if (mainPostContainer) { const mainPostContentElement = mainPostContainer.querySelector('.topic_content'); const topicTitleText = topicTitleElement ? topicTitleElement.textContent || '' : ''; const mainPostText = mainPostContentElement ? mainPostContentElement.textContent || '' : ''; const mainPosterIdAttr = mainPostContainer.getAttribute('data-item-user'); const mainPosterId = mainPosterIdAttr ? mainPosterIdAttr.toLowerCase() : ''; let topicIsMarkedNSFW = checkNsfwKeywords(topicTitleText) || checkNsfwKeywords(mainPostText); let mainPosterIsNSFW = mainPosterId && nsfwUserIds.includes(mainPosterId); if (topicIsMarkedNSFW || mainPosterIsNSFW) { if (mainPostContentElement) { blurImagesInElement(mainPostContentElement); } } } // Modified replies processing const replies = document.querySelectorAll('.row_reply'); replies.forEach(reply => { try { const replyMessageElement = reply.querySelector('.reply_content .message'); const replyText = replyMessageElement ? replyMessageElement.textContent || '' : ''; // New replierID extraction logic let replierId = reply.getAttribute('data-item-user'); if (!replierId) { console.warn('[BGM NSFW Protection] Cannot find replier ID for reply:', reply); } let replyIsMarkedNSFW = checkNsfwKeywords(replyText); let replierIsNSFW = replierId && nsfwUserIds.includes(replierId.toLowerCase()); if (replyIsMarkedNSFW || replierIsNSFW) { if (replyMessageElement) { blurImagesInElement(replyMessageElement); } } } catch (replyError) { console.error('[BGM NSFW Protection] Error processing reply:', replyError); } }); } catch (error) { console.error('[BGM NSFW Protection] Error in applyBlurringLogic:', error); } } // --- Initialization --- loadSettings(); loadNsfwUserIds(); applyBlurringLogic(); // Optional: Re-apply on dynamic content changes (if any, might be complex) // const observer = new MutationObserver(applyBlurringLogic); // const config = { childList: true, subtree: true }; // const targetNode = document.getElementById('main') || document.body; // if (targetNode) observer.observe(targetNode, config); })();