Github搜索净化

净化Github搜索页,屏蔽cirosantilli等人的敏感仓库。

目前為 2023-12-26 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Github搜索净化
// @name:zh-CN   Github搜索净化
// @name:en      Github Search Purification
// @namespace    https://github.com/danicastarr
// @version      1.1.0
// @description  净化Github搜索页,屏蔽cirosantilli等人的敏感仓库。
// @description:zh-CN  净化Github搜索页,屏蔽敏感仓库。
// @description:en Clean up Github search page, block sensitive repositories by cirosantilli and others.
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAACEUExURUxpcRgWFhsYGBgWFhcWFh8WFhoYGBgWFiUlJRcVFRkWFhgVFRgWFhgVFRsWFhgWFigeHhkWFv////////////r6+h4eHv///xcVFfLx8SMhIUNCQpSTk/r6+jY0NCknJ97e3ru7u+fn51BOTsPCwqGgoISDg6empmpoaK2srNDQ0FhXV3eXcCcAAAAXdFJOUwCBIZXMGP70BuRH2Ze/LpIMUunHkpQR34sfygAAAVpJREFUOMt1U+magjAMDAVb5BDU3W25b9T1/d9vaYpQKDs/rF9nSNJkArDA9ezQZ8wPbc8FE6eAiQUsOO1o19JolFibKCdHGHC0IJezOMD5snx/yE+KOYYr42fPSufSZyazqDoseTPw4lGJNOu6LBXVUPBG3lqYAOv/5ZwnNUfUifzBt8gkgfgINmjxOpgqUA147QWNaocLniqq3QsSVbQHNp45N/BAwoYQz9oUJEiE4GMGfoBSMj5gjeWRIMMqleD/CAzUHFqTLyjOA5zjNnwa4UCEZ2YK3khEcBXHjVBtEFeIZ6+NxYbPqWp1DLKV42t6Ujn2ydyiPi9nX0TTNAkVVZ/gozsl6FbrktkwaVvL2TRK0C8Ca7Hck7f5OBT6FFbLATkL2ugV0tm0RLM9fedDvhWstl8Wp9AFDjFX7yOY/lJrv8AkYuz7fuP8dv9izCYH+x3/LBnj9fYPBTpJDNzX+7cAAAAASUVORK5CYII=
// @license      GPLv3
// @author       DanicaStar ch3rry
// @match        *://github.com/search*
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// ==/UserScript==
(function (){
    "use strict" // 严格模式
    let ban = ['cirosantilli', 'wumaoland', 'codin-stuffs', 'cheezcharmer', 'gege-circle', 'zhaohmng-outlook-com', 'zaohmeing', 'Daravai1234', 'candice531033938', 'jk-ice-cream', 'jk-ice-cream-250', 'sky8964', 'pxvr-official', 'zpc1314521', 'jjzhang166', 'panbinibn', 'programthink', 'hello-world-1989'];
    let isKeepDiv = GM_getValue("isKeepDiv", false);
    let isPrecise = GM_getValue("isPrecise", false);
    let detectMode = GM_getValue("detectMode", "loop");
    let detectDelay = GM_getValue("detectDelay", 100);
    
    // 注册菜单-是否保留屏蔽项目Div的框,默认false
    GM_registerMenuCommand(
        isKeepDiv ? "✅是否保留屏蔽项目Div的框":"❎是否保留屏蔽项目Div的框",
        function () {
            isKeepDiv ? GM_setValue("isKeepDiv", false):GM_setValue("isKeepDiv", true);
            isKeepDiv = !isKeepDiv;
            location.reload();
      }
    );
    
    // 注册菜单-是否精确匹配,默认false
    GM_registerMenuCommand(
        isPrecise ? "✅是否精确匹配":"❎是否精确匹配",
        function () {
            isPrecise ? GM_setValue("isPrecise", false):GM_setValue("isPrecise", true);
            isPrecise = !isPrecise;
            location.reload();
      }
    );
    
    // 注册菜单-检测模式,默认"loop"
    GM_registerMenuCommand(
        detectMode == "loop" ? "♾️检测模式:loop":"👂检测模式:eventListen",
        function () {
            if (detectMode == "loop") {
                GM_setValue("detectMode", "eventListen");
                detectMode == "eventListen";
            }
            else {
                GM_setValue("detectMode", "loop");
                detectMode == "loop";
            }
            location.reload();
      }
    );
    
    // 注册菜单-detectDelay设置
    if (detectMode == "loop") {
        GM_registerMenuCommand(
        "🕑设置检测间隔时间",
        function () {
            let inputValue = prompt("填入循环间隔时间,单位为毫秒(1000毫秒=1秒),默认为100毫秒", detectDelay); //默认显示detectDelay
            if (inputValue !== null) {
                if (inputValue > 0 && inputValue < 10000) {
                    detectDelay = inputValue;
                    GM_setValue("detectDelay", inputValue);
                    location.reload();
                }
                else {
                    alert("数值错误,请重新输入");
                }
            }
        });
    }
    
    // 注册菜单-设置说明
    GM_registerMenuCommand(
        "❔设置说明",
        function () {
            let message1 = "1. 是否保留屏蔽项目Div的框:若选择不保留,会直接在搜索结果中删除被屏蔽仓库;若选择保留,被屏蔽的仓库会显示一个包含信息'⛔该仓库被脚本屏蔽'的框。\n--------------------\n";
            let message2 = "2. 是否精确匹配:若不精确匹配,则任何innerText包含屏蔽词的仓库都会被屏蔽(.include),可能会有误杀情况;若精确匹配,则只会屏蔽屏蔽词内仓库所有者的仓库(==)\n----------\n";
            let message3 = "3. 检测模式:共有两种模式——循环(loop)和事件监听(eventListener),循环简单暴力,屏蔽效果好,但对性能影响较事件监听大;事件监听性能表现可能较好,但屏蔽效果不及循环\n----------\n";
            let message4 = "4. 每次检测循环间隔的时间,单位为毫秒(1000秒 = 1秒),可根据自身设备性能调整,默认为100毫秒";
            alert(message1 + message2 + message3 + message4);
      }
    );
    
    // 注册菜单-重置设置
    GM_registerMenuCommand(
    "🔄️重置设置",
    function () {
        if (confirm("是否重置脚本设置?") == true) {
            GM_setValue("isKeepDiv", false);
            GM_setValue("isPrecise", false);
            GM_setValue("detectMode", "loop");
            GM_setValue("detectDelay", 100);
            location.reload();
            alert("脚本已重置");
        }
    });
    
    
    // 屏蔽执行
    function clean() {
        if (document.querySelector("div[data-testid='results-list']") !== null) {
        let search_list = document.querySelector("div[data-testid='results-list']").childNodes;
            for (let i = 0; i < search_list.length; i++) {
                if (isBan(search_list[i], isPrecise)) {
                    if (isKeepDiv) {
                        search_list[i].firstChild.remove();
                        search_list[i].append("⛔该仓库被脚本屏蔽");
                    }
                    else {
                        search_list[i].remove();
                    }
                }
            }
        }
    };
    
    
    // 判断是否屏蔽
    function isBan(target ,isPrecise) {
        if (isPrecise) {
            if (target.getElementsByTagName("a").length !== 0) {
                let repositoryName = target.getElementsByTagName("a")[0].innerText;
                let userName = repositoryName.split("/")[0];
                for (let j = 0; j < ban.length; j++) {
                    if (userName == ban[j]) {
                        return true;
                    }
                }
                return false;
            }
            else {return false;}
        }
        else {
            for (let j = 0; j < ban.length; j++) {
                if (target.innerText.includes(ban[j])) {
                    return true;
                }
            }
            return false;
        }
    };
    
    //*********************************************
    //*                                           *
    //*               循环检测代码                *
    //*                                           *
    //*********************************************
    function cleanByLoop() {
        setInterval(function(){
            clean();
        },detectDelay);
    };
    
    //*********************************************
    //*                                           *
    //*               监听检测代码                *
    //*                                           *
    //*********************************************
    // github 路由更新时
    function pageChange(url) {
        // 保证时机
        setTimeout(() => {
        clean()
      }, 1000)
    }
    
    
    // 重写 history event
    let _wr = function(type) {
        let orig = history[type];
        return function() {
            let rv = orig.apply(this, arguments);
            let e = new Event(type);
            e.arguments = arguments;
            window.dispatchEvent(e);
            return rv;
        }
    }
    
    function cleanByEventListener() {
        setTimeout(() => {clean()}, 1000);
        clean();
        // 重写方法
        history.pushState = _wr('pushState');
        //监听
        window.addEventListener('pushState', function(e) {
            pageChange(location.href);
        })
    }
    
    //*********************************************
    //*                                           *
    //*                   入口                    *
    //*                                           *
    //*********************************************
    switch (detectMode) {
        case "loop": cleanByLoop();break;
        case "eventListen": cleanByEventListener();break;
    }
    
    })()