diff --git a/chrom-ext/background.js b/chrom-ext/background.js index 3c618fc..3e68304 100644 --- a/chrom-ext/background.js +++ b/chrom-ext/background.js @@ -1,34 +1,47 @@ console.log('[XAI Background] ✅ Service worker started'); -// ===== TẠO MENU ===== +// ===== TẠO MENU: XÓA CŨ → TẠO MỚI, KHÔNG GỘP ===== chrome.runtime.onInstalled.addListener(() => { - chrome.contextMenus.create({ - id: 'writeComment', - title: '✍️ Viết comment', - contexts: ['all'], - documentUrlPatterns: ['https://x.com/*'] - }); - chrome.contextMenus.create({ - id: 'translateText', - title: '🌐 Dịch văn bản', - contexts: ['selection'], - documentUrlPatterns: ['https://x.com/*', 'http://*/*', 'https://*/*'] + 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://*/*'] + }); }); }); -// ===== CONTEXT MENU CLICK ===== +// ===== 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) { - chrome.tabs.sendMessage(tab.id, { action: 'OPEN_TRANSLATE_FORM', text: info.selectionText }).catch(() => {}); + // 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; } }); -// ===== MESSAGE LISTENER ===== +// ===== NHẬN MESSAGE TỪ CONTENT ===== chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'GENERATE_COMMENT') { handleGenerate(request.data, sender.tab.id); @@ -44,7 +57,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { return false; }); -// ===== COMMENT API ===== +// ===== 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) { @@ -78,7 +91,7 @@ async function handleGenerate({ text, lang, tone, angle }, tabId) { } } -// ===== TRANSLATE API ===== +// ===== 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; @@ -87,7 +100,7 @@ async function handleTranslate({ text, target_lang }, tabId) { if (!url || !key) { await chrome.tabs.sendMessage(tabId, { action: 'SHOW_TRANSLATE_ERROR', - error: '⚠️ Chưa cấu hình API.\n\n👉 Vào tab ⚙️ Config để nhập URL và Key.' + error: '⚠️ Chưa cấu hình API.' }).catch(() => {}); return; } diff --git a/chrom-ext/content.js b/chrom-ext/content.js index 63de4eb..64370e3 100644 --- a/chrom-ext/content.js +++ b/chrom-ext/content.js @@ -70,14 +70,16 @@ const sel = window.getSelection().toString().trim(); if (sel) lastSelectedText = sel; - // Lưu tweet text + // Lưu tweet text — CHỈ khi click đúng vào article const article = e.target.closest('article'); - if (!article) { lastTweetText = ''; return; } - const textEl = - article.querySelector('[data-testid="tweetText"]') || - article.querySelector('div[lang]') || - article.querySelector('div[dir="auto"]'); - lastTweetText = textEl ? textEl.innerText.trim() : article.innerText.trim().slice(0, 600); + if (article) { + const textEl = + article.querySelector('[data-testid="tweetText"]') || + article.querySelector('div[lang]') || + article.querySelector('div[dir="auto"]'); + lastTweetText = textEl ? textEl.innerText.trim() : article.innerText.trim().slice(0, 600); + } + // ⚠️ KHÔNG xóa lastTweetText nếu không có article (tránh lỗi click vào padding/lề) }); // ===== B. LISTENER ===== @@ -188,7 +190,6 @@ function openSidebar(tweetText) { if (sidebarHost) { - // Nếu sidebar đã mở, chỉ cần mở drawer const drawer = sidebarHost.shadowRoot.querySelector('.drawer'); if (drawer) drawer.classList.add('open'); return; @@ -435,7 +436,6 @@ ); }); - // Comment buttons copyBtn.addEventListener('click', async () => { const text = statusEl.textContent; if (!text || text.startsWith('⏳') || text.startsWith('Lỗi') || text.startsWith('⚠️')) { @@ -556,12 +556,11 @@ const url = urlIn.value.trim(), key = keyIn.value.trim(); if (!url || !key) { showCfgStatus('❌ Comment URL và Key không được để trống!', true); return; } try { new URL(url); } catch { showCfgStatus('❌ URL không hợp lệ', true); return; } - const tUrl = transUrlIn.value.trim() || url; - const tKey = transKeyIn.value.trim() || key; + const tUrl = transUrlIn.value.trim(); + const tKey = transKeyIn.value.trim(); chrome.storage.local.set({ apiUrl: url, apiKey: key, - translateUrl: tUrl === url ? '' : tUrl, - translateKey: transKeyIn.value.trim() + translateUrl: tUrl, translateKey: tKey }, () => { showCfgStatus('✅ Đã lưu!', false); cfgBadge.style.display = 'none'; diff --git a/src/x-cache/x-cache.service.ts b/src/x-cache/x-cache.service.ts index a697ae2..038f25c 100644 --- a/src/x-cache/x-cache.service.ts +++ b/src/x-cache/x-cache.service.ts @@ -22,7 +22,7 @@ export class XCacheService { } async setCacheTwRefreshToken(refreshToken: string) { - await this.cacheManager.set('tw_app_refresh_token', refreshToken, 30 * 24 * 3600); + await this.setCachedKey('tw_app_refresh_token', refreshToken, 30 * 24 * 3600); } async getCacheTwRefreshToken() { @@ -61,16 +61,16 @@ export class XCacheService { async changeStateXCookiesIsAlive() { const cacheKey = 'state_xcookie_status'; const currentState = await this.isXCookiesAlive(); - return this.cacheManager.set(cacheKey, currentState ? 0 : 1, 365 * 24 * 3600); + return this.setCachedKey(cacheKey, currentState ? 0 : 1, 365 * 24 * 3600); } async setStateXCookiesIsDie() { const cacheKey = 'state_xcookie_status'; - return this.cacheManager.set(cacheKey, 0, 365 * 24 * 3600); + return this.setCachedKey(cacheKey, 0, 3 * 24 * 3600); } async setStateXCookiesIsSillALive() { const cacheKey = 'state_xcookie_status'; - return this.cacheManager.set(cacheKey, 1, 365 * 24 * 3600); + return this.setCachedKey(cacheKey, 1, 3 * 24 * 3600); } async isXCookiesAlive() { diff --git a/src/x-poster/x-browser.service.ts b/src/x-poster/x-browser.service.ts index c8ff167..3b5508e 100644 --- a/src/x-poster/x-browser.service.ts +++ b/src/x-poster/x-browser.service.ts @@ -173,7 +173,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy { this.logger.debug('isCookieLive?'); if (page.url().includes('/home')) { this.logger.log('Cookies live'); - // await this.xCacheService.setStateXCookiesIsSillALive(); + await this.xCacheService.setStateXCookiesIsSillALive(); if (sendNotiWhenAlive) { // await this.notifyService.sendMessageToTele('✅Verify cookie pass') } @@ -330,6 +330,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy { // const composer = page.locator('a[href="/compose/post"]').first(); // await page.waitForTimeout(2000 + (Math.random()+Math.random()) * 3000); // await composer.click(); + this.logger.debug('Bắt đầu nhập tweet ...'); const textarea = page.locator('div[data-testid="tweetTextarea_0"]'); await page.waitForTimeout(2000 + (Math.random() + Math.random()) * 3000);