自研 - 多个站点 - 反外站拦截

去除某些网站的外站拦截。目前已适配 16 个站点。

// ==UserScript==
// @name               自研 - 多个站点 - 反外站拦截
// @name:en_US         Self-made - Multi-site - Anti-External Site Interception
// @description        去除某些网站的外站拦截。目前已适配 16 个站点。
// @description:en_US  Remove external site interception for some websites. Currently adapted for 16 sites.
// @version            1.0.14
// @author             CPlayerCHN
// @license            MulanPSL-2.0
// @namespace          https://www.gitlink.org.cn/CPlayerCHN
// @match              *://*.zhihu.com/*
// @match              *://www.pixiv.net/*
// @match              *://gitee.com/*
// @match              *://www.tianyancha.com/*
// @match              *://jump2.bdimg.com/safecheck/index
// @match              *://www.vilipix.com/*
// @match              *://www.skland.com/*
// @match              *://weibo.cn/sinaurl
// @match              *://weibo.com/*
// @match              *://m.weibo.cn/*
// @match              *://www.douban.com/*
// @match              *://addons.mozilla.org/*
// @match              *://www.mcmod.cn/*
// @match              *://link.mcmod.cn/target/*
// @match              *://www.curseforge.com/*
// @match              *://cn.bing.com/search
// @match              *://www.gcores.com/*
// @match              *://sspai.com/*
// @match              *://www.bookmarkearth.cn/view/*
// @run-at             document-start
// @noframes
// ==/UserScript==

(function() {
    'use strict';

    // 定义「配置」变量,「解码」「暂停执行」「点击器」函数。
    const config = [
        // {
        //     "name": "站点名",
        //     "matchLink": /匹配链接/,
        //     "target": "目标",
        //     "reproduce": "复现链接"
        // },
        // 目标可用项:网页参数、元素选择符、自定义脚本`() => { {{自定义脚本}} }`、正则剔除和特殊方式。
        // 特殊方式:`$entireParam`整个网页参数。
        {
            "name": "知乎",
            "matchLink": /^link.zhihu.com/,
            "target": "target",
            "reproduce": ["https://www.zhihu.com/question/646179463/answer/3411700328", "https://zhuanlan.zhihu.com/p/102911463"]
        },
        {
            "name": "Pixiv(予素)",
            "matchLink": /^www.pixiv.net\/jump.php/,
            "target": "$entireParam",
            "reproduce": "https://www.pixiv.net/users/10885193 > 查看个人资料"
        },
        {
            "name": "Gitee",
            "matchLink": /^gitee.com\/link/,
            "target": "target",
            "reproduce": "https://gitee.com/rmbgame/SteamTools#从移动端-steam-app-导入令牌指南"
        },
        {
            "name": "天眼查",
            "matchLink": /^www.tianyancha.com\/security/,
            "target": "target",
            "reproduce": "https://www.tianyancha.com/company/2347945472"
        },
        {
            "name": "百度贴吧",
            "matchLink": /^jump2.bdimg.com\/safecheck\/index/,
            "target": ".warning_info a",
            "reproduce": "https://tieba.baidu.com/p/8459041179 > 5楼 > 彼梦Archi"
        },
        {
            "name": "插画世界",
            "matchLink": /^www.vilipix.com\/jump/,
            "target": "$entireParam",
            "reproduce": "https://www.vilipix.com/illust/108871691"
        },
        {
            "name": "森空岛",
            "matchLink": /^www.skland.com\/third-link/,
            "target": "target",
            "reproduce": "https://www.skland.com/ > 工具箱 > 塞壬唱片"
        },
        {
            "name": "新浪微博",
            "matchLink": /^weibo.cn\/sinaurl/,
            "target": "u",
            "reproduce": ["https://weibo.com/3556190647/LfTSUxUB6", "https://weibo.com/2656274875/Ohfr4edHf", "https://m.weibo.cn/status/NiQw1CyCy"]
        },
        {
            "name": "豆瓣",
            "matchLink": /^www.douban.com\/link2/,
            "target": "url",
            "reproduce": "https://www.douban.com/group/topic/253534825"
        },
        {
            "name": "Firefox 附加组件",
            "matchLink": /^addons.mozilla.org\/[a-z]{2}(-[A-Z]{2})?/,
            "target": () => {

                // 当页面完成解析,就遍历所有链接元素如果是拦截页面就重配置为原链接。
                document.addEventListener('DOMContentLoaded', () => {

                    document.querySelectorAll("a").forEach((link) => {

                        if(/^https:\/\/prod\.outgoing\.prod\.webservices\.mozgcp\.net\/v1\/[a-z0-9]{64}\//.test(link.href)) {

                            link.href = decode(link.href.slice(118));

                        }

                    });

                });

            },
            "reproduce": "https://addons.mozilla.org/zh-CN/firefox/addon/noscript/"
        },
        {
            "name": "MC百科(MCMOD)",
            "matchLink": /^(link|www).mcmod.cn(\/target\/)?/,
            "target": /http(s)?:\/\/link.mcmod.cn\/target\//,
            "reproduce": "https://www.mcmod.cn/class/4170.html"
        },
        {
            "name": "curseForge",
            "matchLink": /^www.curseforge.com\/linkout/,
            "target": "remoteUrl",
            "reproduce": "https://www.curseforge.com/minecraft/mc-mods/timeless-and-classics-zero"
        },
        {
            "name": "中国必应",
            "matchLink": /^cn.bing.com\/search/,
            "target": () => {

                // 当页面完成解析就遍历主体部分所有链接,如果是打开拦截页面就修改链接
                document.addEventListener('DOMContentLoaded', () => {

                    document.querySelectorAll("#b_content a").forEach((link) => {

                        if(/https:\/\/www.bing.com\/ck\/a/.test(link.href)) {

                            link.href = atob(link.href.split("&u=a1")[1].split("&ntb=1")[0].replaceAll(/[-_+]/g), "").split("#:")[0];

                        }

                    });

                });

            },
            "reproduce": "https://cn.bing.com/search?q=test"
        },
        {
            "name": "机核",
            "matchLink": /^www.gcores.com\/link/,
            "target": "target",
            "reproduce": "https://www.gcores.com/articles/158806"
        },
        {
            "name": "少数派",
            "matchLink": /^sspai.com\/link/,
            "target": "target",
            "reproduce": "https://sspai.com/post/89743"
        },
        {
            "name": "书签地球",
            "matchLink": /^www.bookmarkearth.cn\/view/,
            "target": () => {

                // 当页面完成解析就遍历主体部分所有链接,如果是打开拦截页面就修改链接
                document.addEventListener("DOMContentLoaded", () => {

                    location.href = document.querySelector(".wrapper").dataset.url;

                });

            },
            "reproduce": ["https://www.bookmarkearth.cn/view/817eb92893d711edb9f55254005bdbf9", "https://www.bookmarkearth.cn/view/7df2a2b293d711edb9f55254005bdbf9"]
        },
    ];

    function decode(data) {

        // 判断状况并解码。
        // 内容数量为 4 的倍数且不是 `http(s)?` 开头的判断为 base64;内容开头是 `http(s)?` 的判断为 URI 编码。
        if(data.length % 4 === 0 && !/^http(s)?/.test(data)) {

            return atob(data);

        }else if(/^http(s)?/.test(data)) {

            return decodeURIComponent(data);

        }

    };

    function sleep(ms) {

        return new Promise(resolve => setTimeout(resolve, ms));

    }

    async function clicker(elm) {

        // 定义「按钮元素」变量。
        const btn = document.querySelector(elm);

        // 如果「按钮元素」存在就点击,不存在就等待 .1 秒后再次判断。
        if(btn) {

            btn.click();

        }else {

            await sleep(100);
            clicker(elm);

        }

    };


    // 遍历「配置」。
    config.forEach((data) => {

        // 当链接匹配,就判断目标执行方法并执行对应操作。
        if(data.matchLink.test(location.href.replaceAll(/http(s)?:\/\//g, ""))) {

            // 定义「目标」变量。
            const target = data.target;

            // 判断状况执行对应语句。
            // 内容为字符串且包含 `(.#])` 的判断为元素选择符;内容为字符串且内容为判断为特殊方式;内容为字符串判断为网页参数;内容为正则表达式且页面链接与「目标匹配」判断为正则剔除;内容为函数判断为自定义脚本。
            if(typeof target === "string" && /\.|#|\]/.test(target)) {

                clicker(target);

            }else if(typeof target === "string" && location.search !== "" && target === "$entireParam") {

                // 停止网页继续加载。
                window.stop();

                // 访问页面。
                window.open(decode(location.search.substring(1)), "_self");

            }else if(typeof target === "string" && location.search !== "") {

                // 停止网页继续加载。
                window.stop();

                // 定义「网页参数」变量。
                const params = new URLSearchParams(location.search.substring(1));

                // 访问页面。
                window.open(decode(params.get(target)), "_self");

            }else if(Object.prototype.toString.call(target) === "[object RegExp]" && target.test(location.href)) {

                // 停止网页继续加载。
                window.stop();

                // 定义「网页链接」变量。
                const URL = location.href.replace(target, "");

                // 访问页面。
                window.open(decode(URL), "_self");

            }else if(typeof target === "function") {

                target();

            }

        }

    });


    // 定义「侦测器」变量。
    const observer = new MutationObserver(() => {

        // 遍历所有未被修改的链接元素。
        document.querySelectorAll('a:not(.removeIntercepted)').forEach((link) => {

            // 遍历「配置」
            config.forEach((data) => {

                // 定义「目标」变量。
                const target = data.target;

                // 当链接元素地址与目标链接匹配、类型为字符串、内容不包含`(.#])`且不是空内容,就判断目标执行方法并执行对应操作。
                if(data.matchLink.test(link.href.replaceAll(/http(s)?:\/\//g, "")) && typeof target === "string" && !/\.|#|\]/.test(target) && new URL(link.href).search !== "") {

                    if(target === "$entireParam") {

                        // 修改链接地址。
                        link.href = decode(new URL(link.href).search.substring(1));

                    }else {

                        // 定义「网页参数」变量。
                        const params = new URLSearchParams(new URL(link.href).search.substring(1));

                        // 修改链接地址。
                        link.href = decode(params.get(target));

                    }

                    // 添加「removeIntercepted」类,防止重复检测。
                    link.classList.add("removeIntercepted");

                // 当链接元素地址与目标链接匹配、类型为正则表达式且「目标」链接与元素链接匹配
                }else if (data.matchLink.test(link.href.replaceAll(/http(s)?:\/\//g, "")) && Object.prototype.toString.call(target) === "[object RegExp]" && target.test(link.href)) {

                    // 定义「网页链接」变量。
                    const URL = link.href.replace(target, "");

                    // 修改链接地址。
                    link.href = decode(URL);

                }

            });

        });

    });

    // 当页面完成解析,就配置「侦测器」侦测目标节点。
    document.addEventListener('DOMContentLoaded', () => {

        observer.observe(document.body, {
            "subtree": true,
            "childList": true
        });

    });

})();