Greasy Fork

Greasy Fork is available in English.

掘金文章黑名单

掘金文章黑名单过滤脚本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         掘金文章黑名单
// @namespace    https://github.com/hoc2019/blackList
// @version      1.0
// @description  掘金文章黑名单过滤脚本
// @author       wangzy
// @e-mail       [email protected]
// @match        https://juejin.im/*
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    const myScriptStyle =
        '.black-btn{height:36px;line-height:36px;text-align:center;color:#ccc}.black-btn.in-black{color:#000}.black-sidebar{position:fixed;width:240px;background:#2d303a;font-size: 16px;top:10%;border-radius:0 0 20px 0;padding:20px 20px 20px 0;z-index:999;transform:translate3d(-100%,0,0);transition:transform .4s ease-out}.black-sidebar-show{transform:translate3d(0,0,0)}.hide-icon{display:none}.black-sidebar-show .hide-icon{display:initial}.black-sidebar-show .show-icon{display:none}.toggle{width:50px;padding:5px;background:#2d303a;position:absolute;top:0;right:-60px;color:#fff;border-radius:0 10px 10px 0;cursor:pointer}.black-sidebar ul{height:80px;padding-left:0;overflow-y:auto;overflow-x:hidden;margin:10px 0}.black-sidebar p{padding-left:20px;color:#0ebeff}.black-sidebar ul::-webkit-scrollbar{width:5px;height:5px}.black-sidebar ul::-webkit-scrollbar-thumb{background:rgba(220,220,220,0.5);border-radius:5px}.black-sidebar ul::-webkit-scrollbar-track{background:#201c29}.black-sidebar li{width:80%;font-size:16px;line-height:26px;color:#fff;font-weight:bold;list-style:none;cursor:pointer;padding-left:50px;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.black-sidebar li:hover{background:#000}.black-sidebar li:hover::after{content:"删除";position:absolute;left:10px;font-size:12px;color:#ffdd40}.input-box input{width:82%;border:1px solid rgba(220,220,220,0.4);color:#fff;font-size:16px;line-height:26px;border-radius:4px;background:#262830;margin:5px 0 5px 22px;padding:0 5px}.btn-box{text-align:center}.btn-box span{color:#47cf73;cursor:pointer;margin:0 15px}';
    GM_addStyle(myScriptStyle);

    let authorBlackList = [];
    let keywordsBlackList = [];

    getBlackListFromLocalStorage();
    addBlackListSidebar();

    const pathname = location.pathname.split('/')[1];
    if (pathname === 'timeline' || pathname === 'search') {
        filterArticle(pathname === 'timeline' ? 'entry-list' : 'main-list');
    } else {
        addBlackListBtn();
    }

    document.addEventListener('visibilitychange', function() {
        if (document.visibilityState === 'visible') {
            updateSidebarList();
            if (pathname === 'post') {
                const author = getAuthor();
                const isInBlack = authorBlackList.includes(author);
                console.log(isInBlack);
                if (isInBlack) {
                    $('.panel-btn.black-btn').addClass('in-black');
                } else {
                    $('.panel-btn.black-btn').removeClass('in-black');
                }
            }
        }
    });

    function addBlackListSidebar() {
        const sidebarHtml =
            '<div class="black-sidebar"><div class="toggle">Black<br />List<span class="show-icon">></span><span class="hide-icon"><</span></div><div class="author"><p>作者</p><ul></ul></div><div class="keywords"><p>关键字</p><ul></ul></div><div class="input-box"><input type="text" /></div><div class="btn-box"><span data-type="author">+作者</span><span data-type="keywords">+关键字</span></div></div>';
        $('body').append($(sidebarHtml));
        $('.toggle').click(function() {
            $('.black-sidebar').toggleClass('black-sidebar-show');
        });
        updateSidebarList();
        $('.black-sidebar ul').on('click', 'li', function() {
            const item = $(this);
            blackAction('delete', item.data('type'), item.text());
            item.remove();
        });
        $('.black-sidebar .btn-box span').click(function() {
            const input = $('.black-sidebar input');
            const value = $.trim(input.val());
            if (!value) return;
            const item = $(this);
            blackAction('add', item.data('type'), value);
            input.val('');
        });
    }

    function updateSidebarList() {
        getBlackListFromLocalStorage();
        const authorLi = authorBlackList.map(
            item => `<li data-type="author">${item}<li>`
        );
        const keywordsLi = keywordsBlackList.map(
            item => `<li data-type="keywords">${item}<li>`
        );
        $('.black-sidebar .author ul')
            .empty()
            .append(authorLi);
        $('.black-sidebar .keywords ul')
            .empty()
            .append(keywordsLi);
    }

    function addBlackListBtn() {
        const container = $('#juejin');
        const config = {
            childList: true,
            subtree: true
        };
        let blackBtn;
        const handleLoad = mutationsList => {
            for (let mutation of mutationsList) {
                let type = mutation.type;
                let addedNodes = mutation.addedNodes;
                switch (type) {
                    case 'childList':
                        if (addedNodes.length > 0) {
                            const username = $('.author-info-block .username');
                            if (username.text()) {
                                loadObserver.disconnect();
                                addBtn();
                                return;
                            }
                        }
                        break;
                }
            }
        };
        const loadObserver = createNodeListener(
            container[0],
            config,
            handleLoad
        );
        function addBtn() {
            const box = $('.article-suspended-panel');
            const btn = $('.share-btn.wechat-btn');
            const author = getAuthor();
            const isInBlack = authorBlackList.includes(author);
            blackBtn = btn.clone();
            blackBtn
                .attr('class', 'panel-btn black-btn')
                .text('黑')
                .click(defriend);
            isInBlack && blackBtn.addClass('in-black');
            box.append(blackBtn);
        }
        function defriend() {
            const author = getAuthor();
            const arrIndex = authorBlackList.indexOf(author);
            const isInBlack = arrIndex >= 0;
            if (isInBlack) {
                blackBtn.removeClass('in-black');
                blackAction('delete', 'author', author, arrIndex);
            } else {
                blackBtn.addClass('in-black');
                blackAction('add', 'author', author);
            }
        }
    }

    function filterArticle(articleBox) {
        const container = $('#juejin');
        let list;
        const config = {
            childList: true,
            subtree: true
        };
        const handleLoad = mutationsList => {
            for (let mutation of mutationsList) {
                let type = mutation.type;
                let addedNodes = mutation.addedNodes;
                switch (type) {
                    case 'childList':
                        if (addedNodes.length > 0) {
                            list = $(`.${articleBox}`);
                            if (list.children().length) {
                                loadObserver.disconnect();
                                const articles = $(`.${articleBox}>.item`);
                                filter(articles);
                                createNodeListener(list[0], config, updateLoad);
                            }
                        }
                        break;
                }
            }
        };
        const updateLoad = mutationsList => {
            for (let mutation of mutationsList) {
                let type = mutation.type;
                let addedNodes = mutation.addedNodes;
                switch (type) {
                    case 'childList':
                        if (addedNodes.length > 0) {
                            filter($(addedNodes));
                        }
                        break;
                }
            }
        };
        const loadObserver = createNodeListener(
            container[0],
            config,
            handleLoad
        );
        function filter(articles) {
            if (!(keywordsBlackList.length || authorBlackList.length)) return;
            articles.each(function() {
                const info = $(this);
                const author = info.find('.username').text();
                const title = info.find('.title').text();
                if (authorBlackList.includes(author) || testTitle(title)) {
                    $(this).hide();
                }
            });
        }
        function testTitle(title) {
            const titleRegex = new RegExp(keywordsBlackList.join('|'));
            if (!keywordsBlackList.length) return false;
            return titleRegex.test(title);
        }
    }

    function getBlackListFromLocalStorage() {
        authorBlackList = JSON.parse(
            localStorage.getItem('authorBlackList') || '[]'
        );
        keywordsBlackList = JSON.parse(
            localStorage.getItem('keywordsBlackList') || '[]'
        );
    }

    function blackAction(action, type, name, delIndex) {
        const list = type === 'author' ? authorBlackList : keywordsBlackList;
        if (action === 'add') {
            const node = `<li data-type="${type}">${name}<li>`;
            $(`.black-sidebar .${type} ul`).append(node);
            list.push(name);
        } else {
            const index = delIndex || list.indexOf(name);
            index >= 0 &&
                list.splice(index, 1) &&
                $(`.black-sidebar .${type} li`)
                    .eq(index)
                    .remove();
        }
        localStorage.setItem(`${type}BlackList`, JSON.stringify(list));
    }
    function getAuthor() {
        const authorBox = $('.author-info-block .username').eq(0);
        const author = authorBox.length ? authorBox.text() : '';
        return author;
    }

    function createNodeListener(node, config, mutationCallback) {
        const observer = new MutationObserver(mutationCallback);
        observer.observe(node, config);
        return observer;
    }
})();