-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoffscreen.js
More file actions
110 lines (92 loc) · 2.96 KB
/
offscreen.js
File metadata and controls
110 lines (92 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
function safeName(s){
return String(s || "").replace(/[\\/:*?"<>|]/g, "_").slice(0, 180);
}
function extFromUrl(url){
try{
const u = new URL(url);
const m = u.pathname.match(/\.([a-z0-9]{2,6})$/i);
return m ? "." + m[1].toLowerCase() : "";
}catch{
return "";
}
}
function inferExt(contentType){
const ct = (contentType || "").toLowerCase();
if (ct.includes("png")) return ".png";
if (ct.includes("jpeg") || ct.includes("jpg")) return ".jpg";
if (ct.includes("webp")) return ".webp";
if (ct.includes("gif")) return ".gif";
if (ct.includes("mp4")) return ".mp4";
return "";
}
async function fetchAsBlob(url){
const res = await fetch(url, { credentials: "omit" });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const ct = res.headers.get("content-type") || "";
const blob = await res.blob();
return { blob, contentType: ct };
}
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg?.type !== "ZIP_BUILD") return;
try{ sendResponse({ ok: true }); }catch{}
(async () => {
const runId = msg.runId || "";
const zipName = safeName(msg.zipName || "pinterest-media.zip");
const folder = safeName(msg.folder || "pinterest-media");
const items = Array.isArray(msg.items) ? msg.items : [];
const zip = new JSZip();
const root = zip.folder(folder);
let added = 0;
let failed = 0;
for (let i = 0; i < items.length; i++) {
const it = items[i];
const url = it?.url;
const kind = it?.kind === "vid" ? "video" : "image";
if (!url) continue;
try{
const { blob, contentType } = await fetchAsBlob(url);
const ext = extFromUrl(url) || inferExt(contentType) || (kind === "video" ? ".mp4" : ".jpg");
const name = `${kind}_${String(i + 1).padStart(6, "0")}${ext}`;
root.file(name, blob);
added++;
}catch{
failed++;
}
if ((i + 1) % 30 === 0) {
chrome.runtime.sendMessage({
type: "ZIP_PROGRESS",
runId,
done: i + 1,
total: items.length,
added,
failed
}).catch(() => {});
await sleep(0);
}
}
chrome.runtime.sendMessage({
type: "ZIP_PROGRESS",
runId,
done: items.length,
total: items.length,
added,
failed,
stage: "zipping"
}).catch(() => {});
const blob = await zip.generateAsync({ type: "blob", compression: "DEFLATE" });
const blobUrl = URL.createObjectURL(blob);
chrome.runtime.sendMessage({
type: "ZIP_READY",
runId,
blobUrl,
filename: zipName.toLowerCase().endsWith(".zip") ? zipName : (zipName + ".zip"),
added,
failed
}).catch(() => {});
setTimeout(() => {
try{ URL.revokeObjectURL(blobUrl); }catch{}
}, 120_000);
})();
return true;
});