Auto-deploy: 2026-06-05 22:29:04

This commit is contained in:
Hamza-Ayed
2026-06-05 22:29:04 +03:00
parent 58798e784c
commit e28e4f91dc

View File

@@ -31,7 +31,7 @@
// ─── Find Result Container ─────────────────────────────────────────────── // ─── Find Result Container ───────────────────────────────────────────────
function getSearchResultsContainer() { function getSearchResultsContainer() {
return document.querySelector('.search-results-container, .reusable-search__entity-result-list, ul.reusable-search__entity-result-list'); return document.querySelector('.search-results-container, .reusable-search__entity-result-list, ul.reusable-search__entity-result-list, .search-results__list');
} }
// ─── Extract Person Data ───────────────────────────────────────────────── // ─── Extract Person Data ─────────────────────────────────────────────────
@@ -43,30 +43,38 @@
summary: '' summary: ''
}; };
// Name // 1. Extract Name (Usually inside a link with /in/)
const nameEl = cardEl.querySelector('.entity-result__title-text a span[dir="ltr"], .entity-result__title-line a span[dir="ltr"], span.entity-result__title-text, .app-aware-link span[dir="ltr"]'); const nameEl = cardEl.querySelector('.entity-result__title-text, .search-result__title, span[dir="ltr"]');
if (nameEl) { if (nameEl) {
data.name = nameEl.innerText.trim(); data.name = nameEl.innerText.trim().split('\n')[0];
} else {
const profileLinks = Array.from(cardEl.querySelectorAll('a[href*="/in/"]')).filter(a => a.innerText.trim().length > 0);
if (profileLinks.length > 0) {
data.name = profileLinks[0].innerText.trim().split('\n')[0];
}
} }
// Headline // 2. Extract Headline
const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle'); const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle, .search-result__truncate, .linked-area');
if (headlineEl) { if (headlineEl) {
data.headline = headlineEl.innerText.trim(); data.headline = headlineEl.innerText.trim();
} }
// Location // 3. Extract Location
const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle'); const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle, .search-result__info');
if (locationEl) { if (locationEl) {
data.location = locationEl.innerText.trim(); data.location = locationEl.innerText.trim();
} }
// Summary/Snippet // 4. Extract Summary
const summaryEl = cardEl.querySelector('.entity-result__summary'); const summaryEl = cardEl.querySelector('.entity-result__summary, .search-result__snippets');
if (summaryEl) { if (summaryEl) {
data.summary = summaryEl.innerText.trim(); data.summary = summaryEl.innerText.trim();
} }
// Clean up "View Profile" texts
data.name = data.name.replace(/View .* profile/gi, '').trim();
return data; return data;
} }
@@ -74,14 +82,20 @@
function injectScanButton(cardEl) { function injectScanButton(cardEl) {
if (cardEl.querySelector('.lja-scan-person-btn') || cardEl.querySelector('.lja-investor-result')) return; if (cardEl.querySelector('.lja-scan-person-btn') || cardEl.querySelector('.lja-investor-result')) return;
// Find a good place to put the button. Usually near the title or actions.
const actionArea = cardEl.querySelector('.entity-result__actions') || cardEl.querySelector('.entity-result__item');
if (!actionArea) return;
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.className = 'lja-scan-person-btn'; btn.className = 'lja-scan-person-btn';
btn.innerHTML = '🔍 Scan Investor'; btn.innerHTML = '🔍 Scan Investor';
// Add some basic styling just in case CSS fails to load or apply correctly
btn.style.margin = '10px 0';
btn.style.padding = '5px 15px';
btn.style.cursor = 'pointer';
btn.style.backgroundColor = '#6C63FF';
btn.style.color = '#fff';
btn.style.border = 'none';
btn.style.borderRadius = '5px';
btn.style.fontWeight = 'bold';
// Create a container for the result // Create a container for the result
const resultContainer = document.createElement('div'); const resultContainer = document.createElement('div');
resultContainer.className = 'lja-result-wrapper'; resultContainer.className = 'lja-result-wrapper';
@@ -92,16 +106,16 @@
await scanPerson(cardEl, btn, resultContainer); await scanPerson(cardEl, btn, resultContainer);
}); });
// Try to append button to actions area if possible, else to the item // Try to append to actions area, if not just append at the end of the card
if (actionArea.classList.contains('entity-result__actions')) { const actionArea = cardEl.querySelector('.entity-result__actions, .search-result__actions');
if (actionArea) {
actionArea.prepend(btn); actionArea.prepend(btn);
} else { } else {
const titleLine = cardEl.querySelector('.entity-result__title-line') || actionArea; cardEl.appendChild(btn);
titleLine.appendChild(btn);
} }
cardEl.appendChild(resultContainer); cardEl.appendChild(resultContainer);
console.log('[LJA] Injected button for a profile'); console.log('[LJA] Injected button for a profile:', extractPersonData(cardEl).name);
} }
// ─── Scan a Single Person ──────────────────────────────────────────────── // ─── Scan a Single Person ────────────────────────────────────────────────
@@ -171,11 +185,11 @@
const colorClass = isGreen ? 'green' : 'red'; const colorClass = isGreen ? 'green' : 'red';
resultContainer.innerHTML = ` resultContainer.innerHTML = `
<div class="lja-investor-result ${colorClass}" dir="rtl"> <div class="lja-investor-result ${colorClass}" dir="rtl" style="margin-top: 10px; padding: 10px; border-radius: 8px; font-weight: bold; font-family: system-ui; background-color: ${isGreen ? '#e6ffe6' : '#ffe6e6'}; color: ${isGreen ? '#006600' : '#cc0000'}; border: 1px solid ${isGreen ? '#00cc00' : '#ff0000'};">
<div class="lja-investor-badge ${colorClass}"> <div class="lja-investor-badge">
<span>${badgeIcon}</span> ${badgeText} <span>${badgeIcon}</span> ${badgeText}
</div> </div>
<div class="lja-investor-reason"> <div class="lja-investor-reason" style="margin-top: 5px; font-weight: normal; font-size: 14px;">
${resultData.reason} ${resultData.reason}
</div> </div>
</div> </div>
@@ -185,7 +199,7 @@
} catch (e) { } catch (e) {
console.error('[LJA Search]', e); console.error('[LJA Search]', e);
resultContainer.innerHTML = `<div class="lja-investor-result red">❌ Error: ${e.message}</div>`; resultContainer.innerHTML = `<div class="lja-investor-result red" style="color:red; font-weight:bold;">❌ Error: ${e.message}</div>`;
btnEl.disabled = false; btnEl.disabled = false;
btnEl.innerHTML = '🔍 Scan Investor'; btnEl.innerHTML = '🔍 Scan Investor';
} }
@@ -195,17 +209,31 @@
function injectScanAllButton() { function injectScanAllButton() {
if (document.querySelector('.lja-scan-list-btn')) return; if (document.querySelector('.lja-scan-list-btn')) return;
const container = getSearchResultsContainer(); let container = getSearchResultsContainer();
if (!container) return;
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.className = 'lja-scan-list-btn'; btn.className = 'lja-scan-list-btn';
btn.innerHTML = '✨ Scan All Investors'; btn.innerHTML = '✨ Scan All Investors';
btn.title = 'Scan all loaded profiles on this page'; btn.title = 'Scan all loaded profiles on this page';
// Robust styling for the Scan All button
btn.style.margin = '20px auto';
btn.style.display = 'block';
btn.style.padding = '10px 20px';
btn.style.cursor = 'pointer';
btn.style.backgroundColor = '#6C63FF';
btn.style.color = '#fff';
btn.style.border = 'none';
btn.style.borderRadius = '8px';
btn.style.fontWeight = 'bold';
btn.style.fontSize = '16px';
btn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.1)';
btn.addEventListener('click', async () => { btn.addEventListener('click', async () => {
// Allow broader class matches for people cards // Find all cards using our robust selector
const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result'); const allLis = Array.from(document.querySelectorAll('li'));
const cards = allLis.filter(li => li.querySelector('a[href*="/in/"]'));
if (cards.length === 0) { if (cards.length === 0) {
alert('No profiles found to scan.'); alert('No profiles found to scan.');
return; return;
@@ -214,15 +242,13 @@
btn.disabled = true; btn.disabled = true;
btn.innerHTML = '<span class="lja-spinner"></span> Scanning profiles...'; btn.innerHTML = '<span class="lja-spinner"></span> Scanning profiles...';
// Scan sequentially to avoid hammering the API // Scan sequentially
for (const card of cards) { for (const card of cards) {
const scanBtn = card.querySelector('.lja-scan-person-btn'); const scanBtn = card.querySelector('.lja-scan-person-btn');
if (scanBtn && scanBtn.style.display !== 'none') { if (scanBtn && scanBtn.style.display !== 'none') {
// Scroll to card
card.scrollIntoView({ behavior: 'smooth', block: 'center' }); card.scrollIntoView({ behavior: 'smooth', block: 'center' });
await new Promise(r => setTimeout(r, 500)); // Small delay await new Promise(r => setTimeout(r, 500));
scanBtn.click(); scanBtn.click();
// Wait for result
while (scanBtn.disabled && scanBtn.style.display !== 'none') { while (scanBtn.disabled && scanBtn.style.display !== 'none') {
await new Promise(r => setTimeout(r, 500)); await new Promise(r => setTimeout(r, 500));
} }
@@ -234,18 +260,32 @@
setTimeout(() => { btn.innerHTML = '✨ Scan All Investors'; }, 3000); setTimeout(() => { btn.innerHTML = '✨ Scan All Investors'; }, 3000);
}); });
if (container && container.parentNode) {
container.parentNode.insertBefore(btn, container); container.parentNode.insertBefore(btn, container);
} else {
// Fallback: Floating button bottom right
btn.style.position = 'fixed';
btn.style.bottom = '20px';
btn.style.right = '20px';
btn.style.zIndex = '99999';
btn.style.margin = '0';
document.body.appendChild(btn);
}
console.log('[LJA] Injected Scan All button'); console.log('[LJA] Injected Scan All button');
} }
// ─── Process Page ──────────────────────────────────────────────────────── // ─── Process Page ────────────────────────────────────────────────────────
function processPage() { function processPage() {
// Prevent running outside of search page just in case
if (!window.location.href.includes('linkedin.com/search/results/')) return; if (!window.location.href.includes('linkedin.com/search/results/')) return;
injectScanAllButton(); // Robustly find any <li> that contains a link to a LinkedIn profile
const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result'); const allLis = Array.from(document.querySelectorAll('li'));
const cards = allLis.filter(li => li.querySelector('a[href*="/in/"]'));
console.log('[LJA] processPage found cards:', cards.length);
if (cards.length > 0) { if (cards.length > 0) {
injectScanAllButton();
cards.forEach(injectScanButton); cards.forEach(injectScanButton);
} }
} }
@@ -257,7 +297,7 @@
observerTimer = setTimeout(() => { observerTimer = setTimeout(() => {
processPage(); processPage();
observerTimer = null; observerTimer = null;
}, 800); }, 1500);
}); });
// ─── Initialize ────────────────────────────────────────────────────────── // ─── Initialize ──────────────────────────────────────────────────────────
@@ -265,9 +305,6 @@
console.log('[LJA] Initializing Search Analyzer...'); console.log('[LJA] Initializing Search Analyzer...');
processPage(); processPage();
observer.observe(document.body, { childList: true, subtree: true }); observer.observe(document.body, { childList: true, subtree: true });
// Listen for SPA navigation from background script if implemented,
// or just rely on MutationObserver for body changes when URL changes
} }
// Handle SPA navigation by checking URL changes // Handle SPA navigation by checking URL changes
@@ -276,7 +313,8 @@
if (window.location.href !== lastUrl) { if (window.location.href !== lastUrl) {
lastUrl = window.location.href; lastUrl = window.location.href;
if (lastUrl.includes('linkedin.com/search/results/')) { if (lastUrl.includes('linkedin.com/search/results/')) {
setTimeout(processPage, 1500); console.log('[LJA] SPA Navigation detected, re-processing...');
setTimeout(processPage, 2000);
} }
} }
}, 1000); }, 1000);
@@ -285,6 +323,6 @@
document.addEventListener('DOMContentLoaded', init); document.addEventListener('DOMContentLoaded', init);
} else { } else {
init(); init();
setTimeout(init, 2000); // Fallback for delayed renders setTimeout(init, 3000); // Fallback for delayed renders
} }
})(); })();