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