能原地解析的链接绝不在后台访问,去除重定向的过程快速且高效,平均时间在0.02ms~0.05ms之间。几乎没有任何在后台访问网页获取去重链接的操作,一切都在原地进行,对速度精益求精。去除网页内链接的重定向,具有高准确性和高稳定性,以及相比同类插件更低的时间占用。并且保证去除重定向的有效性,采用三级方案,原地解析->自动跳转->后台访问,保证了一定能去除重定向链接
// ==UserScript== // @name 去除链接重定向 // @author Meriel // @description 能原地解析的链接绝不在后台访问,去除重定向的过程快速且高效,平均时间在0.02ms~0.05ms之间。几乎没有任何在后台访问网页获取去重链接的操作,一切都在原地进行,对速度精益求精。去除网页内链接的重定向,具有高准确性和高稳定性,以及相比同类插件更低的时间占用。并且保证去除重定向的有效性,采用三级方案,原地解析->自动跳转->后台访问,保证了一定能去除重定向链接 // @version 2.8.0 // @namespace Violentmonkey Scripts // @grant GM.xmlHttpRequest // @match *://*/* // @connect * // @icon https://cdn-icons-png.flaticon.com/512/208/208895.png // @supportURL https://github.com/MerielVaren/remove-link-redirects // @homepage https://greasyfork.org/zh-CN/scripts/483475-%E5%8E%BB%E9%99%A4%E9%93%BE%E6%8E%A5%E9%87%8D%E5%AE%9A%E5%90%91 // @run-at document-end // @namespace https://greasyfork.org/zh-CN/users/876245-meriel-varen // @license MIT // ==/UserScript== (() => { /********** 以下为自动跳转部分 **********/ class AutoJumpApp { constructor() { this.registeredProvider = void 0; } /** * 注册服务提供者 * @param providers */ registerProvider() { for (const provider of AutoJumpApp.providers) { if ( provider.urlTest instanceof RegExp && !provider.urlTest.test(location.href) ) { continue; } if (provider.urlTest === false) { continue; } if (typeof provider.urlTest === "function" && !provider.urlTest()) { continue; } this.registeredProvider = provider; break; } return this; } /** * 启动应用 * @returns * */ bootstrap() { this.registerProvider(); if (this.registeredProvider) { this.registeredProvider.resolveAutoJump(); return true; } return false; } static providers = [ { name: "#安", urlTest: /www\.coolapk\.com\/link\?.*url=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("url") ); }, }, { name: "CSDN", urlTest: /link\.csdn\.net\/\?.*target=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("target") ); }, }, { name: "腾讯兔小巢", urlTest: /support\.qq\.com\/.*link-jump\?jump=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("jump") ); }, }, { name: "QQ邮箱", urlTest: /mail\.qq\.com\/.*gourl=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("gourl") ); }, }, { name: "印象笔记", urlTest: /app\.yinxiang\.com\/OutboundRedirect\.action\?.*dest=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("dest") ); }, }, { name: "Youtube", urlTest: /www\.youtube\.com\/redirect\?.*q=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("q") ); }, }, { name: "微信开放社区", urlTest: /developers\.weixin\.qq\.com\/.*href=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("href") ); }, }, { name: "pc6下载站", urlTest: /www\.pc6\.com\/.*gourl=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("gourl") ); }, }, { name: "51CTO博客", urlTest: /blog\.51cto\.com\/transfer\?(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( this.urlTest.exec(location.href)[1] ); }, }, { name: "QQ", urlTest: /c\.pc\.qq\.com.*pfurl=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("pfurl") ); }, }, { name: "QQ", urlTest: /c\.pc\.qq\.com.*url=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("url") ); }, }, { name: "UrlShare", urlTest: /.+\.urlshare\..+\/.*url=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("url") ); }, }, { name: "腾讯文档", urlTest: /docs\.qq\.com\/.*\?url=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("url") ); }, }, { name: "金山文档", urlTest: /www\.kdocs\.cn\/office\/link\?.*target=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("target") ); }, }, { name: "NodeSeek", urlTest: /www\.nodeseek\.com\/jump\?.*to=(.*)/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("to") ); }, }, { name: "新版QQ邮箱", urlTest: /wx\.mail\.qq\.com\/xmspamcheck\/xmsafejump\?/, resolveAutoJump: function () { location.href = decodeURIComponent( new URL(location.href).searchParams.get("url") ); }, }, ]; } /********** 以下为重定向解析部分 **********/ class RedirectApp { /** * 调节providers的顺序 * 将匹配到的provider放到最前 * @param provider */ adjustProviderOrderOnce = (function () { let executed = false; // 标志变量,用于跟踪函数是否已执行 return function (provider) { if (!executed) { const index = this.registeredProviders.indexOf(provider); if (index !== -1) { this.registeredProviders.splice(index, 1); this.registeredProviders.unshift(provider); } executed = true; } }; })(); /** * A 标签是否匹配服务提供者 * @param element * @param provider */ static isMatchProvider(element, provider) { if (element.getAttribute(RedirectApp.REDIRECT_COMPLETED)) { return false; } if ( provider.linkTest instanceof RegExp && !provider.linkTest.test(element.href) ) { return false; } if (provider.linkTest instanceof Boolean) { return provider.linkTest; } if ( typeof provider.linkTest === "function" && !provider.linkTest(element) ) { return false; } return true; } /** * 解析完成的标志 */ static REDIRECT_COMPLETED = "redirect-completed"; /** * 兜底解析器 * 用于解析无法解析的链接 * 通过GM.xmlHttpRequest获取最终链接 */ static FallbackResolver = class { constructor() { this.processedUrls = new Map(); } async resolveRedirect(element) { const href = element.href; if (!this.processedUrls.has(href)) { // 创建一个新的 Promise 并存储在 Map 中 let resolvePromise; const promise = new Promise((resolve) => { resolvePromise = resolve; }); this.processedUrls.set(href, promise); try { const res = await GM.xmlHttpRequest({ method: "GET", url: href, anonymous: true, }); if (res.finalUrl) { const url = res.finalUrl; this.processedUrls.set(href, url); element.href = url; } else { this.processedUrls.delete(href); // 请求失败时删除占位符 } } catch (error) { console.error("请求失败:", error); this.processedUrls.delete(href); // 请求失败时删除占位符 } finally { resolvePromise(); // 请求完成后解析 Promise } } else { const cachedValue = this.processedUrls.get(href); if (cachedValue instanceof Promise) { // 如果是 Promise,等待其完成 await cachedValue; element.href = this.processedUrls.get(href); } else { // 否则直接使用缓存值 element.href = cachedValue; } } } }; /** * 移除链接重定向 * 首先判断是否可以直接解析链接,如果可以则直接解析 * 如果不行,则调用fallbackResolver解析 * @param caller 调用者 * @param element 链接元素 * @param realUrl 真实链接 * @param options 配置项 * @returns * */ static removeLinkRedirect(caller, element, realUrl, options) { element.setAttribute(RedirectApp.REDIRECT_COMPLETED, "true"); if ((realUrl && element.href !== realUrl) || options?.force) { try { element.href = decodeURIComponent(realUrl); } catch (_) { element.href = realUrl; } } else if (caller) { if (!caller.fallbackResolver) { caller.fallbackResolver = new RedirectApp.FallbackResolver(); } caller.fallbackResolver.resolveRedirect(element); } } /** * 监听URL变化 * @param operation * @returns * */ static monitorUrlChange(operation) { function urlChange(event) { const destinationUrl = event?.destination?.url || ""; if (destinationUrl.startsWith("about:blank")) return; const href = destinationUrl || location.href; if (href !== location.href) { operation(href); } } unsafeWindow?.navigation?.addEventListener("navigate", urlChange); unsafeWindow.addEventListener("replaceState", urlChange); unsafeWindow.addEventListener("pushState", urlChange); unsafeWindow.addEventListener("popState", urlChange); unsafeWindow.addEventListener("hashchange", urlChange); } constructor() { this.registeredProviders = []; this.mutationObserver = new MutationObserver((mutations) => { mutations.forEach(this.handleMutation.bind(this)); }); } /** * 处理变动 * @param mutation * @returns * */ handleMutation(mutation) { if (mutation.type === "childList") { mutation.addedNodes.forEach((node) => { if (node instanceof HTMLAnchorElement) { this.handleNode(node); } else { // 有些网站被observer观察到的是一个div,里面包含了很多a标签 // 这种情况下,需要对所有的a标签进行处理 node ?.querySelectorAll?.(`a:not([${RedirectApp.REDIRECT_COMPLETED}])`) ?.forEach((aNode) => this.handleNode(aNode)); } }); } } /** * 处理节点 * @param node * @returns */ handleNode(node) { for (const provider of this.registeredProviders) { if (RedirectApp.isMatchProvider(node, provider)) { provider.resolveRedirect(node); this.adjustProviderOrderOnce(provider); break; } } } /** * 当页面准备就绪时,进行初始化动作 * 有一些服务提供者需要在页面准备就绪时进行特殊的初始化操作 * 比如百度搜索,需要监听URL变化 * 以及一些情况不需要RediectApp介入 * 如谷歌搜索需要监听的是href变化,而链接本身没有重定向 */ async initProviders() { for (const provider of this.registeredProviders) { if (provider.onInit) { await provider.onInit(); } } } /** * 注册服务提供者 * @param providers */ registerProviders() { for (const provider of RedirectApp.providers) { if (provider.urlTest === false) { continue; } if ( provider.urlTest instanceof RegExp && !provider.urlTest.test(location.href) ) { continue; } if (typeof provider.urlTest === "function" && !provider.urlTest()) { continue; } this.registeredProviders.push(provider); } return this; } /** * 启动应用 */ bootstrap() { this.registerProviders(); document.querySelectorAll("a").forEach((element) => { this.handleNode(element); }); console.log("去除重定向服务正在运行:", this.registeredProviders); addEventListener("DOMContentLoaded", this.initProviders.bind(this)); this.mutationObserver.observe(document, { childList: true, subtree: true, }); } static providers = [ { name: "如有乐享", urlTest: /51\.ruyo\.net/, linkTest: /\/[^\?]*\?u=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("u") ); }, }, { name: "Mozilla", urlTest: /addons\.mozilla\.org/, linkTest: /outgoing\.prod\.mozaws\.net\/v\d\/\w+\/(.*)/, resolveRedirect: function (element) { let url = void 0; const match = this.linkTest.exec(element.href); if (match && match[1]) { try { url = decodeURIComponent(match[1]); } catch (_) { url = /(http|https)?:\/\//.test(match[1]) ? match[1] : void 0; } } RedirectApp.removeLinkRedirect(this, element, url); }, }, { name: "#发电", urlTest: /afdian\.net/, linkTest: /afdian\.net\/link\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "印象笔记", urlTest: /(www|app)\.yinxiang\.com/, linkTest: true, resolveRedirect: function (element) { if (element.hasAttribute("data-mce-href")) { if (!element.onclick) { RedirectApp.removeLinkRedirect(this, element, element.href, { force: true, }); element.onclick = function (e) { // 阻止事件冒泡, 因为上层元素绑定的click事件会重定向 e.stopPropagation?.(); element.setAttribute("target", "_blank"); window.top ? window.top.open(element.href) : window.open(element.href); }; } } }, onInit: async function () { const handler = function (e) { const dom = e.target; const tagName = dom.tagName.toUpperCase(); switch (tagName) { case "A": { this.resolveRedirect(dom); break; } case "IFRAME": { if (dom.hasAttribute("redirect-link-removed")) { return; } dom.setAttribute("redirect-link-removed", "true"); dom.contentWindow.document.addEventListener( "mouseover", handler ); break; } } }; document.addEventListener("mouseover", handler); }, }, { name: "印象笔记", urlTest: /app\.yinxiang\.com/, linkTest: /(www|app)\.yinxiang\.com\/OutboundRedirect\.action\?dest=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("dest") ); }, }, { name: "Bing", urlTest: /bing\.com/, linkTest: /.+\.bing\.com\/ck\/a\?.*&u=a1(.*)&ntb=1/, textDecoder: new TextDecoder("utf-8"), resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, this.textDecoder.decode( Uint8Array.from( Array.from( atob( element.href .split("&u=a1")[1] .split("&ntb=1")[0] .replace(/[-_]/g, (e) => ("-" === e ? "+" : "/")) .replace(/[^A-Za-z0-9\\+\\/]/g, "") ) ).map((e) => e.charCodeAt(0)) ) ) ); }, }, { name: "51CTO博客", urlTest: /blog\.51cto\.com/, linkTest: true, resolveRedirect: function (element) { const container = document.querySelector(".article-detail"); if (container?.contains(element)) { if (!element.onclick && element.href) { element.onclick = function (e) { e.stopPropagation?.(); const $a = document.createElement("a"); $a.href = element.href; $a.target = element.target; $a.click(); }; } } }, }, { name: "51CTO博客", urlTest: /blog\.51cto\.com/, linkTest: /blog\.51cto\.com\/.*transfer\?(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "CSDN", urlTest: /blog\.csdn\.net/, linkTest: true, resolveRedirect: function (element) { const container = document.querySelector("#content_views"); if (!container?.contains(element)) { return; } if (!element.onclick && element.origin !== window.location.origin) { RedirectApp.removeLinkRedirect(this, element, element.href, { force: true, }); element.onclick = function (e) { // 阻止事件冒泡, 因为上层元素绑定的click事件会重定向 e.stopPropagation?.(); e.preventDefault?.(); e.stopImmediatePropagation?.(); }; } }, }, { name: "知乎日报", urlTest: /daily\.zhihu\.com/, linkTest: /zhihu\.com\/\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "Google Docs", urlTest: /docs\.google\.com/, linkTest: /www\.google\.com\/url\?q=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("q") ); }, }, { name: "Pocket", urlTest: /getpocket\.com/, linkTest: /getpocket\.com\/redirect\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "Gitee", urlTest: /gitee\.com/, linkTest: /gitee\.com\/link\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "InfoQ", urlTest: /infoq\.cn/, linkTest: /infoq\.cn\/link\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "掘金", urlTest: /juejin\.(im|cn)/, linkTest: /link\.juejin\.(im|cn)\/\?target=(.*)/, resolveRedirect: function (element) { const finalURL = new URL(element.href).searchParams.get("target"); RedirectApp.removeLinkRedirect(this, element, finalURL); if (this.linkTest.test(element.title)) { element.title = finalURL; } }, }, { name: "QQ邮箱", urlTest: /mail\.qq\.com/, linkTest: true, resolveRedirect: function (element) { const container = document.querySelector("#contentDiv"); if (container?.contains(element)) { if (!element.onclick) { element.onclick = function (e) { // 阻止事件冒泡, 因为上层元素绑定的click事件会重定向 e.stopPropagation?.(); }; } } }, }, { name: "QQ邮箱", urlTest: /mail\.qq\.com/, linkTest: /mail\.qq\.com.+gourl=(.+).*/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("gourl") ); }, }, { name: "新版QQ邮箱", urlTest: () => { if ( /mail\.qq\.com/.test(location.href) || /wx\.mail\.qq\.com/.test(location.href) ) { return true; } return false; }, linkTest: /wx\.mail\.qq\.com\/xmspamcheck\/xmsafejump\?/, resolveRedirect: function (element) { const url = new URL(element.href).searchParams.get("url"); RedirectApp.removeLinkRedirect(this, element, url); }, }, { name: "OS #####", urlTest: /os#####\.net/, linkTest: /os#####\.net\/action\/GoToLink\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "Google Play", urlTest: /play\.google\.com/, linkTest: function (element) { if (/google\.com\/url\?q=(.*)/.test(element.href)) { return true; } else if (/^\/store\/apps\/details/.test(location.pathname)) { return true; } return false; }, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("q") ); const eles = [].slice.call(document.querySelectorAll("a.hrTbp")); for (const ele of eles) { if (!ele.href || ele.getAttribute(RedirectApp.REDIRECT_COMPLETED)) { continue; } ele.setAttribute(RedirectApp.REDIRECT_COMPLETED, "true"); ele.setAttribute("target", "_blank"); ele.addEventListener( "click", (event) => { event.stopPropagation(); }, true ); } }, }, { name: "少数派", urlTest: /sspai\.com/, linkTest: /sspai\.com\/link\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "Steam Community", urlTest: /steamcommunity\.com/, linkTest: /steamcommunity\.com\/linkfilter\/\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "百度贴吧", urlTest: /tieba\.baidu\.com/, linkTest: /jump\d*\.bdimg\.com/, resolveRedirect: function (element) { let url = void 0; const text = element.innerText || element.textContent || void 0; const isUrl = /(http|https)?:\/\//.test(text); if (isUrl) { try { url = decodeURIComponent(text); } catch (_) { url = text; } } RedirectApp.removeLinkRedirect(this, element, url); }, }, { name: "Twitter", urlTest: /(twitter|x)\.com/, linkTest: /t\.co\/\w+/, resolveRedirect: async function (element) { if (/(http|https)?:\/\//.test(element.title)) { const url = decodeURIComponent(element.title); RedirectApp.removeLinkRedirect(this, element, url); return; } const textContent = element.textContent.replace(/…$/, ""); if (/(http|https)?:\/\//.test(textContent)) { RedirectApp.removeLinkRedirect(this, element, textContent); return; } else { const res = await GM.xmlHttpRequest({ method: "GET", url: "https://" + textContent, anonymous: true, }); if (res.status === 200) { RedirectApp.removeLinkRedirect(this, element, res.finalUrl); } else { RedirectApp.removeLinkRedirect( this, element, "http://" + textContent ); } } }, }, { name: "微博", urlTest: /\.weibo\.(com|cn)/, linkTest: /t\.cn\/\w+/, resolveRedirect: function (element) { if (!/^(http|https)?:\/\//.test(element.title)) { return; } let url = void 0; try { url = decodeURIComponent(element.title); } catch (_) {} RedirectApp.removeLinkRedirect(this, element, url); }, }, { name: "微博", urlTest: /weibo\.(com|cn)/, linkTest: /weibo\.(com|cn)\/sinaurl\?u=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, decodeURIComponent(new URL(element.href).searchParams.get("u")) ); }, }, { name: "百度搜索", urlTest: /www\.baidu\.com/, linkTest: /www\.baidu\.com\/link\?url=/, unresolvableWebsites: ["nourl.ubs.baidu.com", "lightapp.baidu.com"], specialElements: [ ".cos-row", ".c-group-wrapper", ".subLink_answer", ".subLink_answer ~ a", "[class*=catalog-list]", "[class*=group-content]", ], fallbackResolver: new RedirectApp.FallbackResolver(), resolveRedirect: async function (element) { const url = this.specialElements.some((selector) => element.closest(selector) ) ? void 0 : element.closest(".c-container[mu]")?.getAttribute("mu"); if ( url && url !== "null" && url !== "undefined" && url !== "" && url !== "about:blank" && url !== "javascript:void(0);" && !this.unresolvableWebsites.some((u) => url?.includes(u)) ) { RedirectApp.removeLinkRedirect(this, element, url); } else { this.fallbackResolver.resolveRedirect(element); } }, // onInit: async function () { // RedirectApp.monitorUrlChange((href) => { // const url = new URL(location.href); // if (url.searchParams.has("wd")) { // location.href = href; // } // }); // }, }, { name: "豆瓣", urlTest: /douban\.com/, linkTest: /douban\.com\/link2\/?\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "Google搜索", urlTest: /\w+\.google\./, linkTest: true, resolveRedirect: function (element) { const traceProperties = [ "ping", "data-jsarwt", "data-usg", "data-ved", ]; // 移除追踪 for (const property of traceProperties) { if (element.getAttribute(property)) { element.removeAttribute(property); } } // 移除多余的事件 if (element.getAttribute("onmousedown")) { element.removeAttribute("onmousedown"); } // 尝试去除重定向 if (element.getAttribute("data-href")) { const realUrl = element.getAttribute("data-href"); RedirectApp.removeLinkRedirect(this, element, realUrl); } if (element && element.href) { const url = new URL(element?.href); if (url?.searchParams.get("url")) { RedirectApp.removeLinkRedirect( this, element, url.searchParams.get("url") ); } } }, }, { name: "简书", urlTest: /www\.jianshu\.com/, linkTest: function (element) { const isLink1 = /links\.jianshu\.com\/go/.test(element.href); const isLink2 = /link\.jianshu\.com(\/)?\?t=/.test(element.href); const isLink3 = /jianshu\.com\/go-wild\/?\?(.*)url=/.test( element.href ); if (isLink1 || isLink2 || isLink3) { return true; } return false; }, resolveRedirect: function (element) { const search = new URL(element.href).searchParams; RedirectApp.removeLinkRedirect( this, element, search.get("to") || search.get("t") || search.get("url") ); }, onInit: async function () { document .querySelectorAll(`a:not[${RedirectApp.REDIRECT_COMPLETED}]`) .forEach((element) => { if (this.linkTest(element)) { this.resolveRedirect(element); } }); }, }, { name: "标志情报局", urlTest: /www\.logonews\.cn/, linkTest: /link\.logonews\.cn\/\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "360搜索", urlTest: /www\.so\.com/, linkTest: /so\.com\/link\?(.*)/, resolveRedirect: function (element) { const url = element.getAttribute("data-mdurl") || element.getAttribute("e-landurl"); if (url) { RedirectApp.removeLinkRedirect(this, element, url); } // remove track element.removeAttribute("e_href"); element.removeAttribute("data-res"); }, }, { name: "搜狗搜索", urlTest: /www\.sogou\.com/, linkTest: /www\.sogou\.com\/link\?url=/, resolveRedirect: function (element) { const vrwrap = element.closest(".vrwrap"); const rSech = vrwrap.querySelector(".r-sech[data-url]"); const url = rSech.getAttribute("data-url"); RedirectApp.removeLinkRedirect(this, element, url); }, }, { name: "Youtube", urlTest: /www\.youtube\.com/, linkTest: /www\.youtube\.com\/redirect\?.{1,}/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("q") ); }, }, { name: "知乎", urlTest: /www\.zhihu\.com/, linkTest: /zhihu\.com\/\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "百度学术", urlTest: /xueshu\.baidu\.com/, linkTest: /xueshu\.baidu\.com\/s?\?(.*)/, resolveRedirect: function (element) { const url = element.getAttribute("data-link") || element.getAttribute("data-url") || void 0; RedirectApp.removeLinkRedirect( this, element, decodeURIComponent(url) ); }, }, { name: "知乎专栏", urlTest: /zhuanlan\.zhihu\.com/, linkTest: /link\.zhihu\.com\/\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "力扣", urlTest: /leetcode\.(cn|com)/, linkTest: /leetcode\.(cn|com)\/link\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "腾讯开发者社区", urlTest: /cloud\.tencent\.com/, linkTest: /cloud\.tencent\.com\/developer\/tools\/blog-entry\?target=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("target") ); }, }, { name: "#安", urlTest: true, linkTest: /www\.coolapk\.com\/link\?url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("url") ); }, }, { name: "腾讯兔小巢", urlTest: /support\.qq\.com/, linkTest: /support\.qq\.com\/.*link-jump\?jump=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("jump") ); }, }, { name: "微信开放社区", urlTest: /developers\.weixin\.qq\.com/, linkTest: /developers\.weixin\.qq\.com\/.*href=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("href") ); }, }, { name: "pc6下载站", urlTest: /www\.pc6\.com/, linkTest: /www\.pc6\.com\/.*\?gourl=(.*)/, customDecode: function (encoded) { const key = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const len = key.length; let d = 0; let s = new Array(Math.floor(encoded.length / 3)); const b = s.length; for (let i = 0; i < b; i++) { const b1 = key.indexOf(encoded.charAt(d++)); const b2 = key.indexOf(encoded.charAt(d++)); const b3 = key.indexOf(encoded.charAt(d++)); s[i] = b1 * len * len + b2 * len + b3; } const decoded = String.fromCharCode(...s); return decoded; }, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, this.customDecode(new URL(element.href).searchParams.get("gourl")) ); }, }, { name: "QQ", urlTest: true, linkTest: /c\.pc\.qq\.com.*pfurl=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("pfurl") ); }, }, { name: "QQ", urlTest: true, linkTest: /c\.pc\.qq\.com.*url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, decodeURIComponent(new URL(element.href).searchParams.get("url")) ); }, }, { name: "UrlShare", urlTest: function () { return ![/www\.jun\.la/].some((r) => r.test(location.href)); }, linkTest: /.+\.urlshare\..+\/.*url=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, decodeURIComponent(new URL(element.href).searchParams.get("url")) ); }, }, { name: "PHP中文网", urlTest: /www\.php\.cn/, linkTest: /www\.php\.cn\/link(.*)/, resolveRedirect: async function (element) { const res = await GM.xmlHttpRequest({ method: "GET", url: element.href, anonymous: true, }); const parser = new DOMParser(); const doc = parser.parseFromString(res.responseText, "text/html"); const a = doc.querySelector("a"); if (a) { RedirectApp.removeLinkRedirect(this, element, a.href); } }, }, { name: "NodeSeek", urlTest: /www\.nodeseek\.com/, linkTest: /www\.nodeseek\.com\/jump\?to=(.*)/, resolveRedirect: function (element) { RedirectApp.removeLinkRedirect( this, element, new URL(element.href).searchParams.get("to") ); }, }, { name: "Google搜索", urlTest: /w+\.google\./, linkTest: false, onInit: function () { window.addEventListener("mousedown", function (event) { const $a = event?.target?.closest("a"); if ($a && !$a.getAttribute(RedirectApp.REDIRECT_COMPLETED)) { const oldUrl = $a.href; const newUrl = decodeURIComponent( new URL($a.href).searchParams.get("url") ); $a.href = newUrl == "null" ? oldUrl : newUrl; $a.setAttribute(RedirectApp.REDIRECT_COMPLETED, "true"); } }); }, }, { name: "菁优网", urlTest: /www\.jyeoo\.com/, linkTest: true, onInit: function () {}, resolveRedirect: function (element) {}, }, ]; } const autoJumpApp = new AutoJumpApp(); const autoJumpR###lt = autoJumpApp.bootstrap(); if (autoJumpR###lt) return; const redirectApp = new RedirectApp(); redirectApp.bootstrap(); })();