console.log('[XAI Background] ✅ Service worker started'); // ===== TẠO MENU: XÓA CŨ → TẠO MỚI, KHÔNG GỘP ===== chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.removeAll(() => { // Menu 1: Comment — KHÔNG cần bôi đen, chỉ trên X chrome.contextMenus.create({ id: 'writeComment', title: '✍️ Viết comment', contexts: ['all'], documentUrlPatterns: ['https://x.com/*'] }); // Menu 2: Dịch — CHỈ hiện khi đã bôi đen text, có thể dùng trên mọi trang chrome.contextMenus.create({ id: 'translateText', title: '🌐 Dịch văn bản', contexts: ['selection'], documentUrlPatterns: ['https://x.com/*', 'http://*/*', 'https://*/*'] }); }); }); // ===== XỬ LÝ CLICK MENU ===== chrome.contextMenus.onClicked.addListener((info, tab) => { if (!tab?.id) return; if (info.menuItemId === 'writeComment') { // Gửi xuống content: mở form comment chrome.tabs.sendMessage(tab.id, { action: 'OPEN_FORM' }).catch(() => {}); return; } if (info.menuItemId === 'translateText' && info.selectionText) { // Gửi xuống content: mở tab Dịch + fill text sẵn chrome.tabs.sendMessage(tab.id, { action: 'OPEN_TRANSLATE_FORM', text: info.selectionText }).catch(() => {}); return; } }); // ===== NHẬN MESSAGE TỪ CONTENT ===== chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'GENERATE_COMMENT') { handleGenerate(request.data, sender.tab.id); sendResponse({ received: true }); return false; } if (request.action === 'TRANSLATE_TEXT') { handleTranslate(request.data, sender.tab.id); sendResponse({ received: true }); return false; } sendResponse({ unknown: true }); return false; }); // ===== GỌI API COMMENT ===== async function handleGenerate({ text, lang, tone, angle }, tabId) { const cfg = await chrome.storage.local.get(['apiUrl', 'apiKey']); if (!cfg.apiUrl || !cfg.apiKey) { await chrome.tabs.sendMessage(tabId, { action: 'SHOW_ERROR', error: '⚠️ Chưa cấu hình API.\n\n👉 Bấm tab ⚙️ Config để nhập URL và Key.' }).catch(() => {}); return; } try { const res = await fetch(cfg.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${cfg.apiKey}` }, body: JSON.stringify({ tweet_text: text, lang, tone, angle }) }); const data = await res.json(); if (!res.ok) throw new Error(`HTTP ${res.status}`); await chrome.tabs.sendMessage(tabId, { action: 'SHOW_RESULT', comment: data.comment || data.text || JSON.stringify(data), model: data.model || '', commentTransVi: data.commentTransVi || '' }).catch(() => {}); } catch (err) { await chrome.tabs.sendMessage(tabId, { action: 'SHOW_ERROR', error: err.message }).catch(() => {}); } } // ===== GỌI API DỊCH ===== async function handleTranslate({ text, target_lang }, tabId) { const cfg = await chrome.storage.local.get(['apiUrl','apiKey','translateUrl','translateKey']); const url = cfg.translateUrl || cfg.apiUrl; const key = cfg.translateKey || cfg.apiKey; if (!url || !key) { await chrome.tabs.sendMessage(tabId, { action: 'SHOW_TRANSLATE_ERROR', error: '⚠️ Chưa cấu hình API.' }).catch(() => {}); return; } try { const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${key}` }, body: JSON.stringify({ text, target_lang }) }); const data = await res.json(); if (!res.ok) throw new Error(`HTTP ${res.status}`); await chrome.tabs.sendMessage(tabId, { action: 'SHOW_TRANSLATE_RESULT', content: data.content || data.text || data.translation || JSON.stringify(data) }).catch(() => {}); } catch (err) { await chrome.tabs.sendMessage(tabId, { action: 'SHOW_TRANSLATE_ERROR', error: err.message }).catch(() => {}); } }