-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
288 lines (252 loc) · 9.27 KB
/
background.js
File metadata and controls
288 lines (252 loc) · 9.27 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
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
287
288
// 视频信息缓存助手 - 后台脚本
// 默认设置
const DEFAULT_SETTINGS = {
maxCacheBilibili: 1000, // BiliBili最大缓存视频数量
maxCacheYouTube: 1000, // YouTube最大缓存视频数量
autoClear: true, // 是否自动清除
clearInterval: 7, // 自动清除间隔(天)
fastSaveMode: true, // 快速保存模式,默认开启
debugMode: false, // debug模式,默认关闭
};
// Debug日志输出函数
function debugLog(...args) {
chrome.storage.local.get("settings", (data) => {
const settings = data.settings || DEFAULT_SETTINGS;
if (settings.debugMode) {
console.log("视频信息缓存助手:", ...args);
}
});
}
// 初始化设置
chrome.runtime.onInstalled.addListener(() => {
// // 初始化设置
// chrome.storage.local.get("settings", (data) => {
// if (!data.settings) {
// chrome.storage.local.set({ settings: DEFAULT_SETTINGS });
// } else {
// // 迁移旧设置到新格式
// const oldSettings = data.settings;
// const newSettings = {
// maxCacheBilibili: oldSettings.maxCache || 100,
// maxCacheYouTube: oldSettings.maxCache || 100,
// autoClear:
// oldSettings.autoClear !== undefined ? oldSettings.autoClear : true,
// clearInterval: oldSettings.clearInterval || 7,
// fastSaveMode:
// oldSettings.fastSaveMode !== undefined
// ? oldSettings.fastSaveMode
// : true,
// };
// chrome.storage.local.set({ settings: newSettings });
// }
// });
// 初始化视频缓存和临时缓存区
chrome.storage.local.get(["videoCache", "tempVideoData"], (data) => {
if (!data.videoCache) {
chrome.storage.local.set({ videoCache: [] });
}
// 检查是否有临时缓存数据需要恢复
if (data.tempVideoData && data.tempVideoData.length > 0) {
debugLog("发现临时保存的数据,尝试恢复", data.tempVideoData.length);
try {
const recoveredVideos = data.tempVideoData.flatMap(
(item) => item.videos || []
);
if (recoveredVideos.length > 0) {
saveVideos(recoveredVideos, "recovered", true)
.then(() => {
debugLog("成功恢复临时数据", recoveredVideos.length);
// 清空临时存储
chrome.storage.local.set({ tempVideoData: [] });
})
.catch((err) => {
debugLog("恢复临时数据失败", err);
});
}
} catch (e) {
debugLog("处理临时数据出错", e);
chrome.storage.local.set({ tempVideoData: [] }); // 重置错误的数据
}
} else if (!data.tempVideoData) {
chrome.storage.local.set({ tempVideoData: [] });
}
});
});
// 监听标签页更新
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// 只在页面完成加载时处理
if (changeInfo.status === "complete") {
// 检查是否是目标网站
const url = tab.url || "";
if (isBilibili(url) || isYouTube(url)) {
// 注入内容脚本
chrome.scripting.executeScript({
target: { tabId: tabId },
files: ["content.js"],
});
}
}
});
// 为快速刷新场景创建临时存储区
let pendingSaveRequests = new Map();
// 监听来自内容脚本的消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "saveVideos") {
// 提前返回响应,避免因页面关闭导致的通信失败
sendResponse({ success: true, received: true });
// 如果是快速保存或紧急模式,先存到临时区域
if (message.isEmergency || message.fastSave) {
// 为每个请求生成唯一标识
const requestId =
Date.now().toString() + Math.random().toString(16).substring(2, 8);
// 保存到临时存储,这是同步操作,确保数据被保存
chrome.storage.local.get("tempVideoData", (data) => {
const tempData = data.tempVideoData || [];
const newTempData = [
...tempData,
{
id: requestId,
videos: message.videos,
pageUrl: sender.tab?.url || "",
timestamp: Date.now(),
},
];
// 限制临时存储大小,防止过大
if (newTempData.length > 20) {
newTempData.splice(0, newTempData.length - 20);
}
chrome.storage.local.set({ tempVideoData: newTempData }, () => {
debugLog(
"已保存到临时区域",
message.videos.length,
"请求ID:",
requestId
);
});
});
}
// 正常保存到主存储
saveVideos(message.videos, sender.tab?.url || "", message.isEmergency)
.then(() => {
debugLog("成功保存视频数据", message.videos.length);
// 完成后可以清理对应的临时数据(在后续版本实现)
})
.catch((error) => {
debugLog("保存视频失败", error);
});
return true; // 表示会异步发送响应
} else if (message.action === "checkFastSaveMode") {
// 查询当前的快速保存模式设置
chrome.storage.local.get("settings", (data) => {
const settings = data.settings || DEFAULT_SETTINGS;
sendResponse({ fastSaveMode: settings.fastSaveMode });
});
return true; // 表示会异步发送响应
}
});
// 添加定期处理临时数据的任务
setInterval(() => {
chrome.storage.local.get("tempVideoData", (data) => {
if (data.tempVideoData && data.tempVideoData.length > 0) {
debugLog("定期检查临时数据", data.tempVideoData.length);
// 按时间排序,优先处理最新的数据
const sortedData = [...data.tempVideoData].sort(
(a, b) => b.timestamp - a.timestamp
);
// 只处理最新的5条,避免一次处理太多
const toProcess = sortedData.slice(0, 5);
const restData = sortedData.slice(5);
// 将所有视频合并处理
const allVideos = toProcess.flatMap((item) => item.videos || []);
if (allVideos.length > 0) {
saveVideos(allVideos, "temp_recovered", true)
.then(() => {
debugLog("成功处理临时数据", allVideos.length);
// 更新临时存储
chrome.storage.local.set({ tempVideoData: restData });
})
.catch((err) => {
debugLog("处理临时数据出错", err);
});
}
}
});
}, 30000); // 每30秒检查一次
// 保存视频信息到缓存
async function saveVideos(videos, pageUrl, isEmergency = false) {
// 获取当前缓存和设置
const data = await chrome.storage.local.get(["videoCache", "settings"]);
let videoCache = data.videoCache || [];
const settings = data.settings || DEFAULT_SETTINGS;
// 确定视频来源
const source = isBilibili(pageUrl) ? "bilibili" : "youtube";
// 处理新视频
const timestamp = Date.now();
const newVideos = videos.map((video) => ({
...video,
id: generateId(),
source,
timestamp,
pageUrl,
}));
// 使用新的覆盖逻辑:新视频会覆盖相同URL的旧视频
const urlMap = new Map();
// 先添加所有新视频到映射表(新视频优先)
newVideos.forEach((video) => {
urlMap.set(video.url, video);
});
// 遍历旧视频,只保留URL不冲突的
const mergedVideos = [...newVideos];
videoCache.forEach((oldVideo) => {
// 如果旧视频的URL不在新视频中,则保留
if (!urlMap.has(oldVideo.url)) {
mergedVideos.push(oldVideo);
}
// 如果URL已存在,新视频已经覆盖了旧视频,不需要再添加
});
videoCache = mergedVideos;
// 按来源分组视频
const bilibiliVideos = videoCache.filter((v) => v.source === "bilibili");
const youtubeVideos = videoCache.filter((v) => v.source === "youtube");
// YouTube视频按原始位置排序(如果有),否则按时间排序
youtubeVideos.sort((a, b) => {
if (a.originalPosition !== undefined && b.originalPosition !== undefined) {
return a.originalPosition - b.originalPosition;
}
return b.timestamp - a.timestamp;
});
// B站视频按时间排序
bilibiliVideos.sort((a, b) => b.timestamp - a.timestamp);
// 根据各自的最大缓存数量进行截取
if (bilibiliVideos.length > settings.maxCacheBilibili) {
bilibiliVideos.splice(settings.maxCacheBilibili);
}
if (youtubeVideos.length > settings.maxCacheYouTube) {
youtubeVideos.splice(settings.maxCacheYouTube);
}
// 合并两个来源的视频
const processedVideos = [...bilibiliVideos, ...youtubeVideos];
// 如果启用了自动清除,删除过期视频
if (settings.autoClear) {
const expirationTime =
timestamp - settings.clearInterval * 24 * 60 * 60 * 1000;
const filteredVideos = processedVideos.filter(
(video) => video.timestamp >= expirationTime
);
await chrome.storage.local.set({ videoCache: filteredVideos });
} else {
await chrome.storage.local.set({ videoCache: processedVideos });
}
}
// 生成唯一ID
function generateId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
}
// 检查是否是哔哩哔哩网站
function isBilibili(url) {
return url.includes("bilibili.com");
}
// 检查是否是YouTube网站
function isYouTube(url) {
return url.includes("youtube.com") || url.includes("youtu.be");
}