您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Open redirected/cloaked links directly
// ==UserScript== // @name Decloak links and open directly // @description Open redirected/cloaked links directly // @version 2.2.5 // @author wOxxOm // @namespace wOxxOm.scripts // @icon https://i.imgur.com/cfmXJHv.png // @resource icon https://i.imgur.com/cfmXJHv.png // @license MIT License // @run-at document-start // @grant GM_getResourceURL // @match *://*/* // ==/UserScript== 'use strict'; const POPUP = document.createElement('a'); POPUP.id = GM_info.script.name; POPUP.title = 'Original link'; let isPopupStyled; let lastLink; let hoverTimer; let hoverStopTimer; addEventListener('keypress', e => e.which === 13 && decloakLink(e), true); addEventListener('mousedown', decloakLink, true); addEventListener('mouseover', onHover, true); function onHover(event) { const a = decloakLink(event); if (!a) return; if (lastLink) lastLink.removeEventListener('mouseout', cancelHover); lastLink = a; clearTimeout(hoverTimer); hoverTimer = setTimeout(showPopup, 500, a); a.addEventListener('mouseout', cancelHover); } function cancelHover(e) { this.removeEventListener('mouseout', cancelHover); clearTimeout(hoverStopTimer); hoverStopTimer = setTimeout(hidePopup, 500, this); } function showPopup(a) { if (!a.matches(':hover')) return; if (!isPopupStyled) { isPopupStyled = true; POPUP.style.cssText = //'all: unset;' + 'width: 18px;' + 'height: 18px;' + 'background: url("' + GM_getResourceURL('icon', false) + '") center no-repeat, white;' + 'background-size: 16px;' + 'opacity: 0;' + 'transition: opacity .5s;' + 'border: 1px solid #888;' + 'border-radius: 11px;' + 'z-index: 2147483647;' + 'margin-left: 0;' + 'cursor: pointer;' + 'position: absolute;' .replace(/;/g, '!important;'); } const linkStyle = getComputedStyle(a); POPUP.href = a.hrefUndecloaked; POPUP.style.opacity = '0'; POPUP.style.marginLeft = -( (parseFloat(linkStyle.paddingRight) || 0) + (parseFloat(linkStyle.marginRight) || 0) + (parseFloat(linkStyle.borderRightWidth) || 0) + Math.max(0, a.getBoundingClientRect().right + 32 - innerWidth) ) + 'px'; setTimeout(() => (POPUP.style.opacity = '1')); a.parentElement.insertBefore(POPUP, a.nextSibling); POPUP.addEventListener('click', openOriginal); } function hidePopup(a) { if (POPUP.matches(':hover') || lastLink && lastLink.matches(':hover')) { cancelHover.call(a); } else if (POPUP.style.opacity === '1') { POPUP.style.opacity = '0'; cancelHover.call(a); } else { lastLink = null; POPUP.remove(); } } function openOriginal(e) { this.href = ''; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); setTimeout(() => { lastLink.href = lastLink.hrefUndecloaked; lastLink.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); } function decloakLink(event) { const a = getClosestLink(event); if (!a || a === POPUP || !/^https?:$/.test(a.protocol)) return; if (a.hrefUndecloaked) return a; if (/\bthis\.href\s*=[^=]/.test(a.getAttribute('onmousedown'))) a.onmousedown = null; if (/\bthis\.href\s*=[^=]/.test(a.getAttribute('onclick'))) a.onclick = null; const href = a.href.baseVal || a.href; const m = href.match(/([?&][-\w]*referrer[-\w]*(?==))?[=?/]((ftps?|https?)((:|%3[Aa])\/\/[^+&]+|%3[Aa]%2[Ff]%2[Ff][^+&/]+))/); if (!m || m[1] || a.hostname === 'disqus.com' && a.pathname.startsWith('/embed/comments/')) { return; } let realUrl = decodeURIComponent(m[2]); if (a.hostname === 'disq.us' && realUrl.lastIndexOf(':') !== realUrl.indexOf(':')) { realUrl = realUrl.substr(0, realUrl.lastIndexOf(':')); } if (new URL(realUrl).hostname === a.hostname || href.match(/[?&=/]\w*([Ss]ign|[Ll]og)[io]n/)) { console.debug('Decloak skipped: assumed a login redirection.'); return; } a.hrefUndecloaked = href; a.setAttribute('href', realUrl); a.rel = 'external noreferrer nofollow noopener'; return a; } function getClosestLink(event) { return event.composedPath ? event.composedPath().find(el => el.tagName === 'A') : event.target.closest('a'); }