Tải PDF xóa watermark bác sĩ

Tải pdf sạch

(async () => {
  const pdfUrls = new Set();
  const origFetch = window.fetch;
  const origXhrOpen = XMLHttpRequest.prototype.open;

  // --- Cấu hình ---
  const WAIT_AFTER_LAST_PDF_MS = 4000; // chờ sau file cuối
  const MAX_WAIT_MS = 20000;           // thời gian chờ tối đa
  let mergeTimer, merged = false;
  let lastPdfCount = 0;

  console.log("%c👀 Đang theo dõi PDF... (sẽ tự merge sau khi đủ file)", "color: lime");

  function scheduleMerge() {
    clearTimeout(mergeTimer);
    mergeTimer = setTimeout(checkAndMerge, WAIT_AFTER_LAST_PDF_MS);
  }

  async function checkAndMerge() {
    if (merged) return; // đã merge rồi => bỏ qua
    if (pdfUrls.size === lastPdfCount) {
      console.log("📚 Không thấy thêm PDF mới → bắt đầu merge...");
      merged = true;
      await mergeNow();
    } else {
      lastPdfCount = pdfUrls.size;
      scheduleMerge();
    }
  }

  async function mergeNow() {
    const { PDFDocument } = await import("https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/+esm");
    const mergedPdf = await PDFDocument.create();

    const urls = [...pdfUrls];
    console.log(`🔗 Tổng cộng ${urls.length} file PDF được merge:`);

    for (let i = 0; i < urls.length; i++) {
      const url = urls[i];
      console.log(`   📄 [${i + 1}/${urls.length}] ${url}`);
      try {
        const buf = await fetch(url).then(r => r.arrayBuffer());
        const src = await PDFDocument.load(buf);
        const pages = await mergedPdf.copyPages(src, src.getPageIndices());
        pages.forEach(p => mergedPdf.addPage(p));
      } catch (e) {
        console.warn(`⚠️ Không tải được ${url}:`, e);
      }
    }

    const mergedBytes = await mergedPdf.save();
    const blob = new Blob([mergedBytes], { type: "application/pdf" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = "merged.pdf";
    a.click();

    console.log("🎉 Merge hoàn tất, file merged.pdf đã tải xuống!");
  }

  // --- Hook fetch ---
  window.fetch = async function (...args) {
    const url = args[0];
    if (typeof url === "string" && url.match(/\.pdf($|\?)/i)) {
      if (!pdfUrls.has(url)) {
        console.log("📥 Fetch PDF:", url);
        pdfUrls.add(url);
        scheduleMerge();
      }
    }
    return origFetch.apply(this, args);
  };

  // --- Hook XHR ---
  XMLHttpRequest.prototype.open = function (method, url, ...rest) {
    if (typeof url === "string" && url.match(/\.pdf($|\?)/i)) {
      if (!pdfUrls.has(url)) {
        console.log("📥 XHR PDF:", url);
        pdfUrls.add(url);
        scheduleMerge();
      }
    }
    return origXhrOpen.call(this, method, url, ...rest);
  };

  // --- Giới hạn thời gian chờ ---
  setTimeout(() => {
    if (!merged && pdfUrls.size > 0) {
      console.log("⏰ Hết thời gian chờ, tiến hành merge thủ công...");
      merged = true;
      mergeNow();
    } else if (pdfUrls.size === 0) {
      console.warn("⚠️ Không phát hiện file PDF nào trong thời gian giới hạn.");
    }
  }, MAX_WAIT_MS);
})();