107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
import { showPageMarker } from "@/components/page-marker";
|
||
import { PinCollector } from "#imports";
|
||
import { AutoLoader } from '@/components/autoLoader';
|
||
import type { PinData } from '#imports';
|
||
|
||
let loader: AutoLoader | null = null;
|
||
|
||
export default defineContentScript({
|
||
matches: ['*://*.huaban.com/*'],
|
||
runAt: 'document_idle',
|
||
|
||
main() {
|
||
sayHello();
|
||
|
||
const collector = new PinCollector();
|
||
|
||
// 允许 popup 主动触发重新收集
|
||
browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||
if (msg.type === 'COLLECT_PINS') {
|
||
const pins = collector.collect();
|
||
sendResponse({ success: true, count: pins.length, pins });
|
||
return true; // 异步响应
|
||
}
|
||
});
|
||
|
||
// TODO: 首次加载自动收集并存储
|
||
|
||
browser.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
|
||
if (msg.action === 'start') {
|
||
const id = location.pathname.match(/\/boards\/(\d+)/)?.[1] ?? '';
|
||
|
||
if (!id) {
|
||
console.warn('[content] 当前页面不是画板页,无法启动');
|
||
sendResponse({ ok: false, error: '不在画板页' });
|
||
return true;
|
||
}
|
||
|
||
loader = new AutoLoader({
|
||
endpoint: `https://huaban.com/v3/boards/${id}/pins`,
|
||
paginationMode: 'cursor',
|
||
limit: 40,
|
||
cursor: { paramName: 'max', valuePath: 'pin_id' },
|
||
interval: 1000,
|
||
itemsPath: 'pins',
|
||
baseParams: { sort: 'seq', fields: 'pins:PIN|board:BOARD_DETAIL|check' },
|
||
onProgress: (p) => {
|
||
browser.runtime.sendMessage({ type: 'progress', ...p });
|
||
},
|
||
onError: (err, pageOrCursor) => {
|
||
browser.runtime.sendMessage({
|
||
type: 'progress',
|
||
requestCount: -1,
|
||
totalItems: -1,
|
||
newItems: 0,
|
||
done: false,
|
||
error: err.message,
|
||
}).catch(() => { });
|
||
},
|
||
onData: async (items) => {
|
||
const newPins: PinData[] = items.map((pin: any) => extractPinData(pin));
|
||
// 读取已有数据,按 pin_id 去重合并
|
||
const stored = await browser.storage.local.get('collectedPins') as { collectedPins?: PinData[] };
|
||
const existing: PinData[] = stored.collectedPins || [];
|
||
const existingIds = new Set(existing.map((p) => p.pinId));
|
||
const merged = [...existing, ...newPins.filter((p) => !existingIds.has(p.pinId))];
|
||
await browser.storage.local.set({ collectedPins: merged });
|
||
console.log(`[content] 已写入 storage,累计 ${merged.length} 条`);
|
||
},
|
||
});
|
||
loader.start();
|
||
sendResponse({ ok: true });
|
||
return true;
|
||
}
|
||
|
||
if (msg.action === 'stop') {
|
||
loader?.stop();
|
||
sendResponse({ ok: true });
|
||
return true;
|
||
}
|
||
});
|
||
},
|
||
});
|
||
|
||
function sayHello() {
|
||
console.log('检测到花瓣网!', window.location.href);
|
||
console.log('这个插件是一个用于自动收集图片的插件。');
|
||
showPageMarker({
|
||
text: '检测到花瓣网!插件已启动',
|
||
position: 'top-right',
|
||
backgroundColor: 'rgba(34, 139, 34, 0.9)',
|
||
closable: true, // 用户可点击 × 关闭
|
||
autoRemoveSeconds: 10,
|
||
});
|
||
}
|
||
|
||
function extractPinData(pin: any): PinData {
|
||
return {
|
||
pinId: pin.pin_id ?? '',
|
||
imgSmallSrc: pin.file?.url ?? '',
|
||
imgSrc: (pin.file?.url ?? '').replace(/_fw\d+webp|_png/, ''),
|
||
alt: pin.raw_text ?? '',
|
||
author: pin.user?.username ?? '',
|
||
time: pin.created_at ?? '',
|
||
tags: pin.tags?.map((t: any) => t.tag ?? t) ?? [],
|
||
url: `/pins/${pin.pin_id}/`,
|
||
};
|
||
} |