Files
x-poster-client/chrom-ext/background.js
T
2026-05-21 05:27:30 +00:00

129 lines
4.5 KiB
JavaScript

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 || '',
commentTransModel: data.commentTransModel || '',
}).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, target_model })
});
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),
model: data.model || '',
}).catch(() => {});
} catch (err) {
await chrome.tabs.sendMessage(tabId, { action: 'SHOW_TRANSLATE_ERROR', error: err.message }).catch(() => {});
}
}