您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a toolbar button that rewrites Scribd URL to scribd.vdownloaders.com and navigates there.
// ==UserScript== // @name Scribd Bypass (domain switch only) // @description Adds a toolbar button that rewrites Scribd URL to scribd.vdownloaders.com and navigates there. // @author 573dave // @version 2.7 // @license MIT // @match *://*.scribd.com/* // @grant GM_addStyle // @run-at document-idle // @noframes // @namespace https://greasyfork.org/users/1294930 // ==/UserScript== (function () { 'use strict'; // ----- Styles ----- GM_addStyle(` .sb-bar{position:fixed;top:0;left:50%;transform:translateX(-50%); display:flex;gap:6px;z-index:2147483646;background:rgba(255,255,255,.92); padding:6px 10px;border-radius:0 0 6px 6px;box-shadow:0 2px 6px rgba(0,0,0,.2); backdrop-filter:saturate(120%) blur(4px)} .sb-btn{font:12px/1.2 system-ui,-apple-system,Segoe UI,Roboto,sans-serif; padding:6px 10px;background:#FFC017;color:#111;border:none;border-radius:6px; cursor:pointer;transition:filter .2s} .sb-btn:hover{filter:brightness(.95)} `); // ----- Helpers ----- const byId = (id) => document.getElementById(id); const create = (tag, props = {}, kids = []) => { const el = document.createElement(tag); for (const [k, v] of Object.entries(props)) { if (k === 'class') el.className = v; else if (k === 'text') el.textContent = v; else if (k.startsWith('on') && typeof v === 'function') el.addEventListener(k.slice(2), v); else el.setAttribute(k, v); } for (const kid of kids) el.appendChild(kid); return el; }; const waitDOM = () => new Promise((r) => (document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', r, { once: true }) : r())); // Build the toolbar if on a document-like page function mountBar() { if (byId('sb-bar')) return; // Only show on typical doc-like routes to avoid cluttering account/home pages const path = location.pathname; const looksDoc = /(\/(doc|document|presentation|book|read)\/\d+\/?)|(^\/read\/\d+)/i.test(path); if (!looksDoc) return; const bar = create('div', { id: 'sb-bar', class: 'sb-bar' }); const dlBtn = create('button', { class: 'sb-btn', text: 'Download (switch domain)', onclick: () => { // Rewrite: https://www.scribd.com/<path> -> https://scribd.vdownloaders.com/<path> // Leave path & query intact; the downloader usually accepts the same structure. const u = new URL(location.href); u.protocol = 'https:'; // normalize u.hostname = 'scribd.vdownloaders.com'; // Optional: remove marketing params if any (kept minimal) // u.searchParams.delete('utm_source'); u.searchParams.delete('utm_medium'); u.searchParams.delete('utm_campaign'); location.assign(u.toString()); }, }); bar.append(dlBtn); document.documentElement.appendChild(bar); } // Re-run when SPA navigation occurs function onURLChange(cb) { let last = location.href; const fire = () => { const now = location.href; if (now !== last) { last = now; cb(); } }; const wrap = (prop) => { const orig = history[prop]; return function () { const ret = orig.apply(this, arguments); fire(); return ret; }; }; history.pushState = wrap('pushState'); history.replaceState = wrap('replaceState'); window.addEventListener('popstate', fire); // Lightweight observer as a fallback for dynamic DOM/router changes const mo = new MutationObserver(() => fire()); mo.observe(document, { subtree: true, childList: true }); } // Init (async () => { await waitDOM(); mountBar(); onURLChange(() => { // Remove prior bar if we left a doc page, then (re)mount if needed const old = byId('sb-bar'); if (old) old.remove(); mountBar(); }); })(); })();