// Extract content from page (injected function) - waits for JS-rendered content function extractPageContent() { return new Promise((resolve) => { function doExtract() { let content = ''; let title = document.title; let image = ''; // First: check og:description — on JS-rendered sites this often contains // the full article text server-side rendered (e.g. spa.gov.sa, wam.ae) // Only use if it's substantial (>300 chars) to avoid short page descriptions const ogDesc = document.querySelector('meta[property="og:description"]'); if (ogDesc && ogDesc.content && ogDesc.content.trim().length > 300) { content = ogDesc.content.trim(); } // Try multiple DOM selectors in order of specificity if (!content || content.trim().length < 300) { const contentSelectors = [ 'article', '[itemprop="articleBody"]', '.article-body', '.post-content', '.entry-content', '.content-body', '.article-content', '#article-body', 'main article', 'main', '[role="main"]', '.content', '#content', '.main-content', '#main-content' ]; for (const selector of contentSelectors) { const element = document.querySelector(selector); if (element && element.innerText && element.innerText.trim().length > 100) { content = element.innerText; break; } } } // Collect all

tags (works well for standard sites) if (!content || content.trim().length < 100) { const paragraphs = document.querySelectorAll('p'); const paragraphTexts = []; for (const p of paragraphs) { const text = p.innerText.trim(); if (text.length > 30) { paragraphTexts.push(text); } } if (paragraphTexts.length > 0) { content = paragraphTexts.join('\n\n'); } } // Largest div fallback if (!content || content.trim().length < 100) { const allDivs = document.querySelectorAll('div, section'); let maxLength = 0; let bestDiv = null; for (const div of allDivs) { const text = div.innerText; if (text && text.length > maxLength && text.length > 200) { const classList = div.className.toLowerCase(); if (!classList.includes('nav') && !classList.includes('menu') && !classList.includes('sidebar') && !classList.includes('footer') && !classList.includes('header') && !classList.includes('ad')) { maxLength = text.length; bestDiv = div; } } } if (bestDiv) content = bestDiv.innerText; } // Last resort: full body if (!content || content.trim().length < 100) { content = document.body.innerText; } // Image: og:image → twitter:image → article img → any large img const ogImage = document.querySelector('meta[property="og:image"]'); if (ogImage && ogImage.content) { image = ogImage.content; } if (!image) { const twitterImage = document.querySelector('meta[name="twitter:image"]'); if (twitterImage && twitterImage.content) image = twitterImage.content; } if (!image) { const articleImgSelectors = ['article img', '.article-body img', '.post-content img', '.entry-content img', '.article-content img', 'main img', '.content img']; for (const selector of articleImgSelectors) { const img = document.querySelector(selector); if (img && img.src && img.src.startsWith('http') && img.width > 200 && img.height > 100) { image = img.src; break; } } } if (!image) { const allImgs = document.querySelectorAll('img'); for (const img of allImgs) { if (img.src && img.src.startsWith('http') && img.width > 300 && img.height > 150 && !img.src.includes('logo') && !img.src.includes('icon') && !img.src.includes('avatar') && !img.src.includes('sprite')) { image = img.src; break; } } } // Title: h1 → og:title → document.title const h1 = document.querySelector('h1'); if (h1 && h1.innerText.trim().length > 0) { title = h1.innerText.trim(); } else { const ogTitle = document.querySelector('meta[property="og:title"]'); if (ogTitle && ogTitle.content.trim().length > 0) title = ogTitle.content.trim(); } return { title, content, image }; } // If content is already there, return immediately const quick = doExtract(); if (quick.content && quick.content.trim().length > 200) { resolve(quick); return; } // Otherwise wait up to 5 seconds for JS to render the page let attempts = 0; const maxAttempts = 10; const interval = setInterval(() => { attempts++; const result = doExtract(); if (result.content && result.content.trim().length > 200 || attempts >= maxAttempts) { clearInterval(interval); resolve(result); } }, 500); }); } // Load current page info chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { const currentTab = tabs[0]; document.getElementById('pageTitle').textContent = currentTab.title; // Auto-detect target site based on content chrome.scripting.executeScript({ target: { tabId: currentTab.id }, func: extractPageContent }).then(async results => { if (results && results[0]) { const pageData = await results[0].result; const detectedSite = detectTargetSite(pageData.title, pageData.content); if (detectedSite) { document.getElementById('targetSite').value = detectedSite; setSectionModeForSite(detectedSite); } } }).catch(err => { console.log('Could not auto-detect site:', err); }); }); // Set section mode based on target site function setSectionModeForSite(site) { let sectionMode = 'custom'; // default if (site === 'dharab' || site === 'mhealthspot') { sectionMode = 'custom'; } else if (site === 'vpnreports' || site === 'bestaitools') { sectionMode = 'auto'; } else if (site === 'intomobile') { sectionMode = 'none'; } // Set the radio button const radioBtn = document.querySelector(`input[name="sectionsMode"][value="${sectionMode}"]`); if (radioBtn) { radioBtn.checked = true; toggleSectionsField(); // Update visibility } } // Auto-detect target site based on content function detectTargetSite(title, content) { const text = (title + ' ' + content).toLowerCase(); // Check for keywords (order matters - most specific first) // GCC countries = DHArab const gccCountries = ['united arab emirates', 'uae', 'dubai', 'abu dhabi', 'qatar', 'doha', 'saudi arabia', 'riyadh', 'jeddah', 'kuwait', 'bahrain', 'oman', 'gcc', 'middle east', 'mena']; if (gccCountries.some(keyword => text.includes(keyword))) { return 'dharab'; } // VPN/Security = VPN Reports const vpnKeywords = ['vpn', 'virtual private network', 'privacy', 'security', 'encryption', 'cybersecurity', 'data protection', 'online security', 'internet privacy', 'proxy', 'firewall', 'malware', 'antivirus']; if (vpnKeywords.some(keyword => text.includes(keyword))) { return 'vpnreports'; } // AI = BestAITools const aiKeywords = ['artificial intelligence', ' ai ', 'machine learning', 'deep learning', 'neural network', 'chatgpt', 'gpt', 'claude', 'gemini', 'llm', 'generative ai', 'ai tool', 'ai model', 'openai', 'anthropic', 'palantir', 'mistral', 'cohere', 'ai startup']; if (aiKeywords.some(keyword => text.includes(keyword))) { return 'bestaitools'; } // Mobile = IntoMobile const mobileKeywords = ['smartphone', 'mobile', 'iphone', 'android', 'galaxy', 'pixel', 'ios', 'mobile app', 'tablet', 'ipad', '5g', 'cellular', 'mobile phone', 'samsung', 'apple', 'google phone']; if (mobileKeywords.some(keyword => text.includes(keyword))) { return 'intomobile'; } // Healthcare = mHealthSpot const healthKeywords = ['health', 'healthcare', 'medical', 'hospital', 'doctor', 'patient', 'medicine', 'clinical', 'diagnosis', 'treatment', 'disease', 'wellness', 'telehealth', 'telemedicine', 'mhealth', 'digital health', 'healthtech', 'pharma', 'pharmaceutical']; if (healthKeywords.some(keyword => text.includes(keyword))) { return 'mhealthspot'; } // Default: no detection return null; } // Toggle sections field visibility function toggleSectionsField() { const selected = document.querySelector('input[name="sectionsMode"]:checked').value; const customField = document.getElementById('customSectionsField'); customField.style.display = selected === 'custom' ? 'block' : 'none'; } document.querySelectorAll('input[name="sectionsMode"]').forEach(radio => { radio.addEventListener('change', toggleSectionsField); }); // Initialize toggleSectionsField(); // Listen for target site changes to auto-adjust section mode document.getElementById('targetSite').addEventListener('change', (e) => { const selectedSite = e.target.value; if (selectedSite) { setSectionModeForSite(selectedSite); } }); // Settings link document.getElementById('settingsLink').addEventListener('click', (e) => { e.preventDefault(); chrome.runtime.openOptionsPage(); }); // Publish button document.getElementById('publishBtn').addEventListener('click', async () => { const targetSite = document.getElementById('targetSite').value; const sectionsMode = document.querySelector('input[name="sectionsMode"]:checked').value; const customSections = document.getElementById('articleSections').value; const statusDiv = document.getElementById('status'); const publishBtn = document.getElementById('publishBtn'); // Validate target site selection if (!targetSite) { showStatus('Please select a target website', 'error'); return; } // Get API keys and settings from extension storage const settings = await chrome.storage.sync.get(['anthropicKey', 'openaiKey', 'defaultStatus']); const anthropicKey = settings.anthropicKey; const openaiKey = settings.openaiKey; const defaultStatus = settings.defaultStatus || 'publish'; if (!anthropicKey) { showStatus('Please configure Anthropic API key in Settings', 'error'); return; } publishBtn.disabled = true; publishBtn.textContent = '⏳ Publishing...'; showStatus('Extracting article content...', 'info'); // Get current tab chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { const currentTab = tabs[0]; // Get WordPress site URL for the selected target const wpSiteUrl = getWordPressSiteUrl(targetSite); if (!wpSiteUrl) { showStatus('Could not determine WordPress URL for selected site', 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; return; } // Extract content from page try { const results = await chrome.scripting.executeScript({ target: { tabId: currentTab.id }, func: extractPageContent }); if (!results || !results[0]) { showStatus('Failed to extract page content', 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; return; } // Await the promise returned by extractPageContent (waits for JS rendering) const pageData = await results[0].result; console.log('Article title:', pageData.title); console.log('Content length:', pageData.content ? pageData.content.length : 0); // Validate we actually have content before sending if (!pageData.content || pageData.content.trim().length < 200) { showStatus( `Could not extract article content from this page (got ${pageData.content ? pageData.content.trim().length : 0} chars).
` + `Please paste the article text manually below.`, 'error' ); document.getElementById('pasteSection').style.display = 'block'; publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; return; } // Prepare data for WordPress const formData = new FormData(); formData.append('action', 'multisite_extension_publish'); formData.append('target_site', targetSite); formData.append('anthropic_api_key', anthropicKey); if (openaiKey) { formData.append('openai_api_key', openaiKey); } formData.append('default_status', defaultStatus); formData.append('source_url', currentTab.url); formData.append('article_title', pageData.title); formData.append('article_text', pageData.content); formData.append('image_url', pageData.image || ''); formData.append('sections_mode', sectionsMode); formData.append('custom_sections', customSections); console.log('Publishing to:', wpSiteUrl); console.log('Target site:', targetSite); console.log('Section mode:', sectionsMode); // Send to WordPress with retry logic const maxRetries = 3; let lastError = null; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { if (attempt === 1) { showStatus('Sending to WordPress...', 'info'); } else { showStatus(`Retrying... (attempt ${attempt} of ${maxRetries})`, 'info'); } const response = await fetch(wpSiteUrl + '/wp-admin/admin-ajax.php', { method: 'POST', body: formData }); console.log(`Attempt ${attempt} - Response status:`, response.status); // Get raw text first so we can log it if JSON parse fails const rawText = await response.text(); console.log(`Attempt ${attempt} - Raw response:`, rawText); let result; try { // Strip anything before the first { in case WordPress leaked output const jsonStart = rawText.indexOf('{'); if (jsonStart === -1) { // No JSON at all - WordPress returned pure HTML (PHP error page) lastError = 'WordPress returned an error: ' + rawText.replace(/<[^>]+>/g, '').substring(0, 150).trim(); console.error(`Attempt ${attempt} - No JSON in response:`, rawText); if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, 2000)); continue; } break; } const cleanText = jsonStart > 0 ? rawText.slice(jsonStart) : rawText; result = JSON.parse(cleanText); } catch (parseError) { lastError = 'Failed to parse response: ' + rawText.substring(0, 150); console.error(`Attempt ${attempt} - Parse error:`, rawText); if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, 2000)); continue; } break; } if (result.success) { const viewLink = result.data.post_url ? `
→ View Post` : ''; showStatus(`✓ Published successfully to ${result.data.site}!${viewLink}`, 'success'); publishBtn.textContent = '✓ Published!'; if (result.data.image_debug) { console.log('=== IMAGE DEBUG ==='); result.data.image_debug.forEach(line => console.log(line)); console.log('==================='); } setTimeout(() => { publishBtn.textContent = 'Publish Article'; publishBtn.disabled = false; }, 3000); return; // success - exit loop } else { // WordPress returned a proper error - don't retry, show it const errorMsg = result.data || 'Unknown error'; console.error('WordPress error:', errorMsg); showStatus('Error: ' + errorMsg, 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; return; // exit loop } } catch (fetchError) { lastError = fetchError.message; console.error(`Attempt ${attempt} - Fetch error:`, fetchError); if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, 2000)); // wait 2s before retry } } } // All retries exhausted showStatus(`Error: ${lastError} — please try again.`, 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; } catch (error) { console.error('Extension error:', error); console.error('Error stack:', error.stack); showStatus('Error: ' + error.message + '
Check browser console (F12) for details', 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish Article'; } }); }); // Get WordPress site URL for target site function getWordPressSiteUrl(targetSite) { const sites = { 'mhealthspot': 'https://mhealthspot.com', 'dharab': 'https://dharab.com', 'intomobile': 'https://intomobile.com', 'vpnreports': 'https://www.vpnreports.com', 'bestaitools': 'https://www.bestaitools.com' }; return sites[targetSite] || null; } function showStatus(message, type) { const statusDiv = document.getElementById('status'); statusDiv.innerHTML = message; statusDiv.className = type; statusDiv.style.display = 'block'; } // Handle publish with manually pasted content document.getElementById('publishWithPasteBtn').addEventListener('click', async () => { const manualContent = document.getElementById('manualContent').value.trim(); if (!manualContent || manualContent.length < 100) { showStatus('Please paste some article content first.', 'error'); return; } const targetSite = document.getElementById('targetSite').value; if (!targetSite) { showStatus('Please select a target website.', 'error'); return; } const sectionsMode = document.querySelector('input[name="sectionsMode"]:checked').value; const customSections = document.getElementById('articleSections').value; const publishBtn = document.getElementById('publishWithPasteBtn'); const settings = await chrome.storage.sync.get(['anthropicKey', 'openaiKey', 'defaultStatus']); const anthropicKey = settings.anthropicKey; const openaiKey = settings.openaiKey; const defaultStatus = settings.defaultStatus || 'publish'; if (!anthropicKey) { showStatus('Please configure Anthropic API key in Settings.', 'error'); return; } const wpSiteUrl = getWordPressSiteUrl(targetSite); if (!wpSiteUrl) { showStatus('Could not determine WordPress URL for selected site.', 'error'); return; } publishBtn.disabled = true; publishBtn.textContent = '⏳ Publishing...'; chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { const currentTab = tabs[0]; const formData = new FormData(); formData.append('action', 'multisite_extension_publish'); formData.append('target_site', targetSite); formData.append('anthropic_api_key', anthropicKey); if (openaiKey) formData.append('openai_api_key', openaiKey); formData.append('default_status', defaultStatus); formData.append('source_url', currentTab.url); formData.append('article_title', document.getElementById('pageTitle').textContent); formData.append('article_text', manualContent); formData.append('image_url', ''); formData.append('sections_mode', sectionsMode); formData.append('custom_sections', customSections); try { showStatus('Sending to WordPress...', 'info'); const response = await fetch(wpSiteUrl + '/wp-admin/admin-ajax.php', { method: 'POST', body: formData }); const rawText = await response.text(); const jsonStart = rawText.indexOf('{'); const cleanText = jsonStart > 0 ? rawText.slice(jsonStart) : rawText; const result = JSON.parse(cleanText); if (result.success) { const viewLink = result.data.post_url ? `
→ View Post` : ''; showStatus(`✓ Published to ${result.data.site}!${viewLink}`, 'success'); publishBtn.textContent = '✓ Published!'; } else { showStatus('Error: ' + (result.data || 'Unknown error'), 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish with Pasted Content'; } } catch (err) { showStatus('Error: ' + err.message, 'error'); publishBtn.disabled = false; publishBtn.textContent = 'Publish with Pasted Content'; } }); });