cldisk Thumb → PDF Helper

自动将 cldisk 缩略图 URL (…/thumb/96.png) 转换为对应 PDF 链接 (…/pdf/{hash}.pdf),支持复制与一键打开。

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         cldisk Thumb → PDF Helper
// @namespace    https://greasyfork.org/users/yourname
// @version      1.2
// @description  自动将 cldisk 缩略图 URL (…/thumb/96.png) 转换为对应 PDF 链接 (…/pdf/{hash}.pdf),支持复制与一键打开。
// @author       你(基于 GPT 辅助编写)
// @license      MIT
// @icon         https://s3.cldisk.com/favicon.ico
// @match        https://s3.cldisk.com/*
// @grant        GM_notification
// @grant        GM_setClipboard
// @run-at       document-idle
// ==/UserScript==

(function () {
  'use strict';

  const HOST_FILTER = 's3.cldisk.com';

  function thumbUrlToPdfUrl(rawUrl) {
    if (!rawUrl) return null;
    try {
      const url = new URL(rawUrl, location.href);
      if (HOST_FILTER && url.host !== HOST_FILTER) return null;
      const idx = url.pathname.indexOf('/thumb/');
      if (idx === -1) return null;
      const beforeThumb = url.pathname.slice(0, idx);
      const segments = beforeThumb.split('/').filter(Boolean);
      if (!segments.length) return null;
      const hash = segments[segments.length - 1];
      const prefix = '/' + segments.join('/');
      const pdfPath = `${prefix}/pdf/${hash}.pdf`;
      return `${url.protocol}//${url.host}${pdfPath}`;
    } catch {
      return null;
    }
  }

  function notify(msg) {
    if (typeof GM_notification === 'function') GM_notification({ text: msg, timeout: 2000 });
    else console.log('[cldisk-helper]', msg);
  }

  function handleThumb(url) {
    const pdfUrl = thumbUrlToPdfUrl(url);
    if (pdfUrl) {
      console.log('[cldisk-helper] thumb =>', pdfUrl);
      notify('检测到缩略图,已解析对应 PDF');
    }
  }

  // Hook fetch
  if (window.fetch) {
    const f = window.fetch;
    window.fetch = function (input, init) {
      if (typeof input === 'string') handleThumb(input);
      return f.apply(this, arguments);
    };
  }

  // Hook XHR
  const o = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function (method, url) {
    handleThumb(url);
    return o.apply(this, arguments);
  };

  // 扫描页面元素并添加按钮
  function attachBtn(el, url) {
    const pdf = thumbUrlToPdfUrl(url);
    if (!pdf || el.dataset.clPdf) return;
    const btn = document.createElement('button');
    btn.textContent = '打开 PDF';
    btn.style.marginLeft = '5px';
    btn.onclick = () => window.open(pdf, '_blank');
    el.insertAdjacentElement('afterend', btn);
    el.dataset.clPdf = 1;
  }

  function scan() {
    document.querySelectorAll('img,a').forEach(el => {
      const url = el.src || el.href;
      if (url) attachBtn(el, url);
    });
  }

  scan();
  new MutationObserver(scan).observe(document.body, { childList: true, subtree: true });

})();