Scribd Bypass (domain switch only)

Adds a toolbar button that rewrites Scribd URL to scribd.vdownloaders.com and navigates there.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==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();
    });
  })();
})();