您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
디시인사이드에 더 나은 단어 차단 기능을 제공합니다
// ==UserScript== // @name Better Blocks // @namespace better-blocks // @description 디시인사이드에 더 나은 단어 차단 기능을 제공합니다 // @version 0.2.0 // @author Sangha Lee // @copyright 2024, Sangha Lee // @license MIT // @match https://www.dcinside.com/ // @match https://gall.dcinside.com/board/* // @match https://gall.dcinside.com/mgallery/board/* // @match https://gall.dcinside.com/mini/board/* // @match https://gall.dcinside.com/person/board/* // @icon https://nstatic.dcinside.com/dc/m/img/dcinside_icon.png // @run-at document-start // @grant GM_getValue // @grant GM_setValue // ==/UserScript== /** * @typedef {Object} Nodes * @property {ElementNode?} $parent * @property {string} parentSelector * @property {string} childrenSelector * @property {bool?} observe */ /** @type {Nodes[]} */ const nodes = [ { // www.dcinside.com: 실시간 베스트 게시글 목록 parentSelector: '#dcbest_list_date', childrenSelector: 'li' }, { // gall.dcinside.com: 게시글 목록 parentSelector: '.gall_list', childrenSelector: 'tr', observe: true }, { // gall.dcinside.com: 댓글 목록 parentSelector: '.comment_wrap', childrenSelector: 'li', observe: true } ] const url = new URL(location.href) const gallery = url.searchParams.get('id') const configs = { ...GM_getValue('configs'), ...JSON.parse(localStorage.getItem('block_parts') ?? '{}') } // 전역 설정 가져오기 configs._ = { ...configs._ ?? {}, ...JSON.parse(localStorage.getItem('block_all') ?? '{}') } // cross-domain 불가능한 localStorage 설정을 유저스크립트 변수와 동기화하기 GM_setValue('configs', configs) const config = { on: 1, word: '', id: '', ip: '', nick: '', ...(configs._.on === 1 ? configs._ : {}), ...(configs[gallery]?.on === 1 ? configs[gallery] : {}) } function isNotEmpty (v) { return v !== '' } const blockedWords = config.word.split('||').filter(isNotEmpty) const blockedIDs = config.ip.split('||').filter(isNotEmpty) const blockedIPs = config.ip.split('||').filter(isNotEmpty) const blockedNicknames = config.nick.split('||').filter(isNotEmpty) function isblockedNode ($node) { // www.dcinside.com: 실시간 베스트 제목 const $bestTitle = $node.querySelector('.besttxt') if ($bestTitle && blockedWords.some(v => $bestTitle.textContent.includes(v))) { return true } // gall.dcinside.com: 게시글 및 댓글 제목과 내용 const $content = $node.querySelector('.ub-word') if ($content && blockedWords.some(v => $content.textContent?.includes(v))) { return true } // gall.dcinside.com: 게시글 및 댓글 작성자 정보 const $author = $node.querySelector('.ub-writer') if ($author) { const i = $author.dataset switch (true) { case i.uid && blockedIDs.some(v => i.uid.includes(v)): case i.ip && blockedIPs.some(v => i.ip.includes(v)): case i.nick && blockedNicknames.some(v => i.nick.includes(v)): return true } } return false } function filterNodes ($nodes) { $nodes .filter(isblockedNode) .map(v => v.classList.add('block-disable')) } // 기존 차단 메소드 비활성화 Object.defineProperty(window, 'chk_user_block', { writable: false, value: undefined }) document.addEventListener('DOMContentLoaded', () => { for (const node of nodes) { node.$parent = document.querySelector(node.parentSelector) if (node.$parent === null || node.observe !== true) { continue } new MutationObserver(() => filterNodes([...$parent.querySelectorAll(node.childrenSelector)])) .observe(node.$parent, { childList: true }) } filterNodes( nodes .map(n => [...n.$parent?.querySelectorAll(n.childrenSelector) ?? []]) .filter(v => v && v.length > 0) .flat() ) })