-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackground.js
126 lines (108 loc) · 3.5 KB
/
background.js
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Import JSZip library
importScripts('lib/jszip.min.js');
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "downloadFiles") {
sendResponse({ status: 'processing' });
handleDownloads(request.files);
return true;
}
});
async function handleDownloads(files) {
// Create a new JSZip instance
const zip = new JSZip();
chrome.runtime.sendMessage({
action: "updateProgress",
message: "Starting to prepare files..."
});
for (const file of files) {
try {
// Check if URL is valid
if (!file.url) {
console.error(`Invalid URL for file: ${file.fileName}`);
chrome.runtime.sendMessage({
action: "updateProgress",
message: `Skipped: ${file.fileName} (Invalid URL)`
});
continue;
}
// Try to fetch the file
const response = await fetch(file.url, {
credentials: 'include',
headers: {
'Accept': '*/*'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
let finalFileName = file.fileName;
const hasExtension = finalFileName.toLowerCase().endsWith(`.${file.urlExtension}`);
if (!hasExtension && file.urlExtension) {
finalFileName = `${finalFileName}.${file.urlExtension}`;
}
const sanitizedSectionTitle = sanitizeFileName(file.sectionTitle);
const sanitizedFileName = sanitizeFileName(finalFileName);
const filePath = `${sanitizedSectionTitle}/${sanitizedFileName}`;
zip.file(filePath, blob);
chrome.runtime.sendMessage({
action: "updateProgress",
message: `Added: ${finalFileName}`
});
} catch (error) {
console.error(`Failed to process ${file.fileName}:`, error);
chrome.runtime.sendMessage({
action: "updateProgress",
message: `Failed: ${file.fileName} (${error.message})`
});
}
}
try {
chrome.runtime.sendMessage({
action: "updateProgress",
message: "Generating zip file..."
});
const content = await zip.generateAsync({
type: "blob",
compression: "DEFLATE",
compressionOptions: { level: 5 }
});
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const zipFileName = `course_materials_${timestamp}.zip`;
// Convert blob to base64 string
const reader = new FileReader();
reader.readAsDataURL(content);
reader.onload = function() {
const base64data = reader.result;
chrome.runtime.sendMessage({
action: "processZipDownload",
data: base64data,
filename: zipFileName
});
};
} catch (error) {
console.error('Failed to create zip:', error);
chrome.runtime.sendMessage({
action: "downloadError",
message: "Error creating zip file"
});
}
}
function sanitizeFileName(fileName) {
return fileName.replace(/[<>:"/\\|?*]/g, '-');
}
function waitForDownload(downloadId) {
return new Promise((resolve, reject) => {
chrome.downloads.onChanged.addListener(function onChanged({id, state}) {
if (id === downloadId) {
if (state?.current === 'complete') {
chrome.downloads.onChanged.removeListener(onChanged);
resolve();
} else if (state?.current === 'interrupted') {
chrome.downloads.onChanged.removeListener(onChanged);
reject(new Error('Download interrupted'));
}
}
});
});
}