// ==UserScript== // @name 哔哩哔哩过滤评论区 // @description 根据关键词/用户等级过滤评论区 // @version 1.0.7 // @author girl-dream // @license The Unlicense // @namespace https://github.com/girl-dream/ // @icon https://www.bilibili.com/favicon.ico // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/list/* // @match https://www.bilibili.com/bangumi/play/* // @match https://t.bilibili.com/* // @match https://www.bilibili.com/opus/* // @match https://space.bilibili.com/*/dynamic // @match https://www.bilibili.com/v/topic/detail/* // @match https://www.bilibili.com/cheese/play/* // @match https://www.bilibili.com/festival/* // @match https://www.bilibili.com/blackboard/* // @match https://www.bilibili.com/blackroom/ban/* // @match https://www.bilibili.com/read/* // @match https://manga.bilibili.com/* // @match https://www.bilibili.com/v/topic/detail* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant unsafeWindow // @run-at document-end // ==/UserScript== (async () => { 'use strict' let keyWords = GM_getValue('filter_keywords', [ '关于我升', '六级不在', '拍个照', '合个影' ]) // 账号等级排除:勾选的等级(LV1~LV6)对应的账号评论将被过滤 let excludedLevels = GM_getValue('filter_excluded_levels', []) GM_registerMenuCommand('设置过滤关键词', () => { const div = document.createElement('div') div.id = 'bili-filter-settings' div.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 999999; ` const content = document.createElement('div') content.style.cssText = ` background: var(--bg1_float); padding: 20px; border-radius: 8px; width: 400px; max-width: 90%; max-height: 80vh; overflow-y: auto; color:var(--text1); ` content.innerHTML = `
过滤关键词设置

每行一个关键词,评论包含任意关键词即被过滤

排除指定等级账号 (勾选即排除):
${[0,1,2,3,4,5,6].map(l => ` `).join('')}
` // 填充当前关键词 const textarea = content.querySelector('#keywords-input') textarea.value = keyWords.join('\n') content.querySelector('#cancel-btn').onclick = () => { div.remove() } content.querySelector('#save-btn').onclick = () => { const newKeywords = textarea.value .split('\n') .map(k => k.trim()) .filter(k => k.length > 0) const newExcluded = Array.from(content.querySelectorAll('.excl-level-cb')) .filter(cb => cb.checked) .map(cb => parseInt(cb.value, 10)) GM_setValue('filter_keywords', newKeywords) GM_setValue('filter_excluded_levels', newExcluded) keyWords = newKeywords excludedLevels = newExcluded div.remove() location.reload() } div.appendChild(content) document.body.appendChild(div) }) const filterReplies = (replies) => { return replies.filter(reply => { let msg = reply.content?.message || '' if (msg.includes('回复 @')) msg = msg.substring(4) const hasKeyword = keyWords.some(keyword => msg.includes(keyword)) if (hasKeyword) { return false } // 账号等级排除:勾选等级的账号评论直接过滤 if (excludedLevels.length > 0) { const level = reply.member?.level_info?.current_level if (typeof level === 'number' && excludedLevels.includes(level)) { return false } } if (reply.replies && Array.isArray(reply.replies)) { reply.replies = filterReplies(reply.replies) } return true }) } const originalFetch = window.fetch unsafeWindow.fetch = async (...args) => { const response = await originalFetch.apply(this, args) if (args[0].includes('reply')) { const clonedResponse = response.clone() let data = await clonedResponse.json() let modified = false if (data.data?.replies && Array.isArray(data.data.replies)) { data.data.replies = filterReplies(data.data.replies) modified = true } // 置顶评论单独存放,同样需要过滤 if (data.data?.top_replies && Array.isArray(data.data.top_replies)) { data.data.top_replies = filterReplies(data.data.top_replies) modified = true } if (modified) { return new Response(JSON.stringify(data), response) } } return response } })()