// InsightFlow Chrome Extension - Background Script // 处理扩展的后台逻辑 chrome.runtime.onInstalled.addListener(() => { console.log('[InsightFlow] Extension installed'); // 创建右键菜单 chrome.contextMenus.create({ id: 'insightflow-clip-selection', title: 'Clip selection to InsightFlow', contexts: ['selection'] }); chrome.contextMenus.create({ id: 'insightflow-clip-page', title: 'Clip page to InsightFlow', contexts: ['page'] }); chrome.contextMenus.create({ id: 'insightflow-clip-link', title: 'Clip link to InsightFlow', contexts: ['link'] }); }); // 处理右键菜单点击 chrome.contextMenus.onClicked.addListener((info, tab) => { if (info.menuItemId === 'insightflow-clip-selection') { clipSelection(tab); } else if (info.menuItemId === 'insightflow-clip-page') { clipPage(tab); } else if (info.menuItemId === 'insightflow-clip-link') { clipLink(tab, info.linkUrl); } }); // 处理来自 popup 的消息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'clipPage') { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (tabs[0]) { clipPage(tabs[0]).then(sendResponse); } }); return true; } else if (request.action === 'clipSelection') { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (tabs[0]) { clipSelection(tabs[0]).then(sendResponse); } }); return true; } else if (request.action === 'openClipper') { chrome.action.openPopup(); } }); // 剪辑整个页面 async function clipPage(tab) { try { // 向 content script 发送消息提取内容 const response = await chrome.tabs.sendMessage(tab.id, { action: 'extractContent' }); if (response.success) { // 保存到本地存储 await saveClip(response.data); return { success: true, message: 'Page clipped successfully' }; } } catch (error) { console.error('[InsightFlow] Failed to clip page:', error); return { success: false, error: error.message }; } } // 剪辑选中的内容 async function clipSelection(tab) { try { const response = await chrome.tabs.sendMessage(tab.id, { action: 'getSelection' }); if (response.success && response.data) { const clipData = { url: tab.url, title: tab.title, content: response.data.text, context: response.data.context, contentType: 'selection', extractedAt: new Date().toISOString() }; await saveClip(clipData); return { success: true, message: 'Selection clipped successfully' }; } else { return { success: false, error: 'No text selected' }; } } catch (error) { console.error('[InsightFlow] Failed to clip selection:', error); return { success: false, error: error.message }; } } // 剪辑链接 async function clipLink(tab, linkUrl) { const clipData = { url: linkUrl, title: linkUrl, content: `Link: ${linkUrl}`, sourceUrl: tab.url, contentType: 'link', extractedAt: new Date().toISOString() }; await saveClip(clipData); return { success: true, message: 'Link clipped successfully' }; } // 保存剪辑内容 async function saveClip(data) { // 获取现有剪辑 const result = await chrome.storage.local.get(['clips']); const clips = result.clips || []; // 添加新剪辑 clips.unshift({ id: generateId(), ...data, synced: false }); // 只保留最近 100 条 if (clips.length > 100) { clips.pop(); } // 保存 await chrome.storage.local.set({ clips }); // 尝试同步到服务器 syncToServer(); } // 同步到服务器 async function syncToServer() { const { serverUrl, apiKey } = await chrome.storage.sync.get(['serverUrl', 'apiKey']); if (!serverUrl || !apiKey) { console.log('[InsightFlow] Server not configured, skipping sync'); return; } const result = await chrome.storage.local.get(['clips']); const clips = result.clips || []; const unsyncedClips = clips.filter(c => !c.synced); if (unsyncedClips.length === 0) return; for (const clip of unsyncedClips) { try { const response = await fetch(`${serverUrl}/api/v1/plugins/chrome/import`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey }, body: JSON.stringify({ token: apiKey, url: clip.url, title: clip.title, content: clip.content, html_content: clip.html || null }) }); if (response.ok) { clip.synced = true; clip.syncedAt = new Date().toISOString(); } } catch (error) { console.error('[InsightFlow] Sync failed:', error); } } // 更新存储 await chrome.storage.local.set({ clips }); } // 生成唯一ID function generateId() { return Date.now().toString(36) + Math.random().toString(36).substr(2); } // 定时同步(每5分钟) chrome.alarms.create('syncClips', { periodInMinutes: 5 }); chrome.alarms.onAlarm.addListener((alarm) => { if (alarm.name === 'syncClips') { syncToServer(); } });