-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackground.js
286 lines (254 loc) · 9.92 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// Initialize an array to store captured URLs
let capturedURLs = [];
// Function to clear the URL list
function clearCapturedURLs() {
capturedURLs = [];
chrome.storage.local.set({capturedURLs: []});
console.log("Cleared captured URLs list");
}
// Listen for web requests matching our pattern
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
// Check if the URL contains our target pattern
if (details.url.includes('odrmediaclips.cachefly.net') && details.type === 'media') {
console.log("Captured media URL:", details.url);
// Add the URL to our list if not already present
if (!capturedURLs.includes(details.url)) {
capturedURLs.push(details.url);
// Store the updated list in chrome.storage
chrome.storage.local.set({capturedURLs: capturedURLs});
// **Send message to popup to update the URL count**
chrome.runtime.sendMessage({ action: "updateURLCount", urlCount: capturedURLs.length });
}
}
// Don't interfere with the request
return {cancel: false};
},
{urls: ["*://*.cachefly.net/*"], types: ["media"]},
["requestBody"]
);
// Function to extract title from tab and update storage.
async function extractTitleAndUpdate(tabId) {
try {
// Check if the tab URL indicates an audiobook page.
const tab = await chrome.tabs.get(tabId);
if (!tab || !tab.url || !tab.url.includes("listen.overdrive.com")) { // **Corrected URL Check**
console.log("Not an audiobook tab, skipping title extraction.");
return;
}
console.log("Attempting to extract title from tab:", tabId);
const results = await chrome.scripting.executeScript({
target: { tabId: tabId },
function: () => document.title,
});
const pageTitle = results?.[0]?.result;
console.log("Extracted page title:", pageTitle);
if (pageTitle) {
chrome.storage.local.get(['bookTitle'], function(result) {
const storedTitle = result.bookTitle;
console.log("Stored title:", storedTitle);
if (storedTitle && storedTitle !== pageTitle) {
// Titles don't match, clear author name
chrome.storage.local.set({ authorName: '', bookTitle: pageTitle }, () => {
console.log("Title changed, author name cleared.");
// Optionally, send message to popup to updateAuthorField
chrome.runtime.sendMessage({ action: "updateAuthorField" });
});
} else {
// Titles match or no stored title
chrome.storage.local.set({ bookTitle: pageTitle });
console.log("Titles match or no stored title, setting bookTitle to:", pageTitle);
}
});
} else {
console.log("No page title found.");
}
} catch (error) {
console.error("Error extracting title:", error);
}
}
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete') {
clearCapturedURLs();
console.log("Page loaded/reloaded. URL tracking reset for tab:", tabId);
// Extract Title and update bookTitle in storage
extractTitleAndUpdate(tabId);
// **Check if it's a Libby Audiobook Tab before injecting content scripts**
if (tab && tab.url && tab.url.includes("listen.overdrive.com")) { // **Corrected URL Check**
// Prevent multiple injections
chrome.tabs.sendMessage(tabId, { action: "ping" }, (response) => {
if (chrome.runtime.lastError || !response) {
chrome.scripting.executeScript({
target: { tabId: tabId },
files: ['browser-id3-writer.js', 'downloadHelper.js']
}).then(() => {
console.log("Content scripts pre-injected on page load");
}).catch(err => {
console.error("Failed to pre-inject content scripts:", err);
});
} else {
console.log("Content script already loaded");
}
});
} else {
console.log("Not a Libby Audiobook tab, skipping content script injection.");
}
}
});
chrome.tabs.onActivated.addListener(async (activeInfo) => {
console.log("Tab activated. activeInfo:", activeInfo); // Added logging
extractTitleAndUpdate(activeInfo.tabId);
});
// Ensure content script is loaded before attempting download
async function ensureContentScriptLoaded(tabId) {
return new Promise((resolve, reject) => {
// Check if content script is responsive
chrome.tabs.sendMessage(tabId, { action: "ping" }, response => {
if (chrome.runtime.lastError || !response) {
console.log("Content script not ready, injecting it now");
// Inject content script
chrome.scripting.executeScript({
target: {tabId: tabId},
files: ['browser-id3-writer.js', 'downloadHelper.js']
}).then(() => {
// Wait for content script to initialize
setTimeout(resolve, 500);
}).catch(err => {
reject(new Error(`Cannot inject script: ${err.message}`));
});
} else {
// Content script is already loaded
resolve();
}
});
});
}
// Use content script to download with the proper headers
async function downloadAudioFile(url, filename, metadata) {
try {
// Get the active tab
const tabs = await chrome.tabs.query({active: true, currentWindow: true});
if (!tabs || tabs.length === 0) {
throw new Error("No active tab found");
}
const activeTab = tabs[0];
// Ensure content script is loaded first
await ensureContentScriptLoaded(activeTab.id);
// Now send the download message with metadata
return new Promise((resolve, reject) => {
chrome.tabs.sendMessage(
activeTab.id,
{
action: "downloadWithFetch",
url: url,
filename: filename,
metadata: metadata
},
function(response) {
if (chrome.runtime.lastError) {
reject(new Error(`Message error: ${chrome.runtime.lastError.message}`));
} else if (!response || !response.success) {
reject(new Error(response?.error || "Content script failed to download"));
} else {
resolve(true);
}
}
);
});
} catch (error) {
console.error("Download failed:", error);
throw error;
}
}
// Listen for messages from the popup
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.action === "getURLs") {
// Retrieve URLs from storage to ensure persistence
chrome.storage.local.get(['capturedURLs'], function(result) {
if (result.capturedURLs && result.capturedURLs.length > 0) {
// Log each URL to console with the prefix
result.capturedURLs.forEach(url => {
console.log("CapturedURL:", url);
});
sendResponse({status: "Logged URLs to console", count: result.capturedURLs.length});
} else {
sendResponse({status: "No URLs captured yet", count: 0});
}
});
return true; // Required for async sendResponse
}
else if (request.action === "clearURLs") {
// Clear the URLs
clearCapturedURLs();
// Send a response immediately
sendResponse({status: "URLs cleared", count: 0});
}
else if (request.action === "downloadURL") {
let responded = false;
downloadAudioFile(request.url, request.filename, request.metadata)
.then(() => {
responded = true;
sendResponse({ success: true });
})
.catch(error => {
responded = true;
sendResponse({ success: false, error: error.message });
});
// Failsafe timeout to avoid message channel closing unexpectedly
setTimeout(() => {
if (!responded) {
sendResponse({ success: false, error: "Timeout: No response received" });
}
}, 5000); // Adjust timeout if needed
return true; // Keeps the message channel open
}
else if (request.action === "updateAuthorField") {
// Popup needs to update its author field
chrome.storage.local.get({ authorName: '' }, function(result) {
sendResponse({ authorName: result.authorName });
});
return true; // Keep the message channel open
}
// Add captureAudio action
else if (request.action === "captureAudio") {
//Get the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (!tabs || tabs.length === 0) {
sendResponse({status: "Error: No active tab found"});
return;
}
const activeTabId = tabs[0].id;
// Ensure content script is loaded first
ensureContentScriptLoaded(activeTabId)
.then(() => {
// Send message to content script to start capturing audio
chrome.tabs.sendMessage(activeTabId, {action: "startAudioCapture"}, function(response) {
if (chrome.runtime.lastError) {
sendResponse({status: "Error: " + chrome.runtime.lastError.message});
} else if (response && response.status) {
sendResponse({status: response.status});
} else {
sendResponse({status: "Error: Could not start audio capture."});
}
});
})
.catch(error => {
sendResponse({status: "Error: " + error.message});
});
});
return true; // Required for async response
}
// Check if content script is ready
else if (request.action === "contentScriptReady") {
console.log("Content script is ready");
}
// Return true if we're sending a response asynchronously
return true;
}
);
// Clear captured URLs on extension install/update
chrome.runtime.onInstalled.addListener(function() {
clearCapturedURLs();
console.log("Libby Audiobook Helper installed/updated. URL tracking initialized.");
});