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 ───────────────────────────────────────────────
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 ─────────────────────────────────────────────────
@@ -43,30 +43,38 @@
summary: ''
};
// Name
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"]');
// 1. Extract Name (Usually inside a link with /in/)
const nameEl = cardEl.querySelector('.entity-result__title-text, .search-result__title, span[dir="ltr"]');
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
const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle');
// 2. Extract Headline
const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle, .search-result__truncate, .linked-area');
if (headlineEl) {
data.headline = headlineEl.innerText.trim();
}
// Location
const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle');
// 3. Extract Location
const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle, .search-result__info');
if (locationEl) {
data.location = locationEl.innerText.trim();
}
// Summary/Snippet
const summaryEl = cardEl.querySelector('.entity-result__summary');
// 4. Extract Summary
const summaryEl = cardEl.querySelector('.entity-result__summary, .search-result__snippets');
if (summaryEl) {
data.summary = summaryEl.innerText.trim();
}
// Clean up "View Profile" texts
data.name = data.name.replace(/View .* profile/gi, '').trim();
return data;
}
@@ -74,14 +82,20 @@
function injectScanButton(cardEl) {
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');
btn.className = 'lja-scan-person-btn';
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
const resultContainer = document.createElement('div');
resultContainer.className = 'lja-result-wrapper';
@@ -92,16 +106,16 @@
await scanPerson(cardEl, btn, resultContainer);
});
// Try to append button to actions area if possible, else to the item
if (actionArea.classList.contains('entity-result__actions')) {
// Try to append to actions area, if not just append at the end of the card
const actionArea = cardEl.querySelector('.entity-result__actions, .search-result__actions');
if (actionArea) {
actionArea.prepend(btn);
} else {
const titleLine = cardEl.querySelector('.entity-result__title-line') || actionArea;
titleLine.appendChild(btn);
cardEl.appendChild(btn);
}
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 ────────────────────────────────────────────────
@@ -171,11 +185,11 @@
const colorClass = isGreen ? 'green' : 'red';
resultContainer.innerHTML = `
<div class="lja-investor-result ${colorClass}" dir="rtl">
<div class="lja-investor-badge ${colorClass}">
<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">
<span>${badgeIcon}</span> ${badgeText}
</div>
<div class="lja-investor-reason">
<div class="lja-investor-reason" style="margin-top: 5px; font-weight: normal; font-size: 14px;">
${resultData.reason}
</div>
</div>
@@ -185,7 +199,7 @@
} catch (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.innerHTML = '🔍 Scan Investor';
}
@@ -195,17 +209,31 @@
function injectScanAllButton() {
if (document.querySelector('.lja-scan-list-btn')) return;
const container = getSearchResultsContainer();
if (!container) return;
let container = getSearchResultsContainer();
const btn = document.createElement('button');
btn.className = 'lja-scan-list-btn';
btn.innerHTML = '✨ Scan All Investors';
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 () => {
// Allow broader class matches for people cards
const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result');
// Find all cards using our robust selector
const allLis = Array.from(document.querySelectorAll('li'));
const cards = allLis.filter(li => li.querySelector('a[href*="/in/"]'));
if (cards.length === 0) {
alert('No profiles found to scan.');
return;
@@ -214,15 +242,13 @@
btn.disabled = true;
btn.innerHTML = '<span class="lja-spinner"></span> Scanning profiles...';
// Scan sequentially to avoid hammering the API
// Scan sequentially
for (const card of cards) {
const scanBtn = card.querySelector('.lja-scan-person-btn');
if (scanBtn && scanBtn.style.display !== 'none') {
// Scroll to card
card.scrollIntoView({ behavior: 'smooth', block: 'center' });
await new Promise(r => setTimeout(r, 500)); // Small delay
await new Promise(r => setTimeout(r, 500));
scanBtn.click();
// Wait for result
while (scanBtn.disabled && scanBtn.style.display !== 'none') {
await new Promise(r => setTimeout(r, 500));
}
@@ -234,18 +260,32 @@
setTimeout(() => { btn.innerHTML = '✨ Scan All Investors'; }, 3000);
});
container.parentNode.insertBefore(btn, container);
if (container && container.parentNode) {
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');
}
// ─── Process Page ────────────────────────────────────────────────────────
function processPage() {
// Prevent running outside of search page just in case
if (!window.location.href.includes('linkedin.com/search/results/')) return;
injectScanAllButton();
const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result');
// Robustly find any <li> that contains a link to a LinkedIn profile
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) {
injectScanAllButton();
cards.forEach(injectScanButton);
}
}
@@ -257,7 +297,7 @@
observerTimer = setTimeout(() => {
processPage();
observerTimer = null;
}, 800);
}, 1500);
});
// ─── Initialize ──────────────────────────────────────────────────────────
@@ -265,9 +305,6 @@
console.log('[LJA] Initializing Search Analyzer...');
processPage();
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
@@ -276,7 +313,8 @@
if (window.location.href !== lastUrl) {
lastUrl = window.location.href;
if (lastUrl.includes('linkedin.com/search/results/')) {
setTimeout(processPage, 1500);
console.log('[LJA] SPA Navigation detected, re-processing...');
setTimeout(processPage, 2000);
}
}
}, 1000);
@@ -285,6 +323,6 @@
document.addEventListener('DOMContentLoaded', init);
} else {
init();
setTimeout(init, 2000); // Fallback for delayed renders
setTimeout(init, 3000); // Fallback for delayed renders
}
})();