SiteMente - AI-Powered Lead Generation Platform
Features: - Mission Control dashboard - HP Submissions tracking - AI Agents integration - Lead management CRM - Marketing email templates - Chrome extension support Tech: Next.js, TypeScript, Tailwind CSS, MySQL
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
// Content Script - runs on X.com
|
||||
// Adds "Save to Hookd" option to tweet/post menu
|
||||
|
||||
console.log('Hookd content script loaded');
|
||||
|
||||
// Listen for messages from background
|
||||
chrome.runtime.onMessage.addListener((msg, sender, response) => {
|
||||
if (msg.type === 'GET_SAVED') {
|
||||
response([]);
|
||||
}
|
||||
});
|
||||
|
||||
// Add "Save to Hookd" to X's menu
|
||||
function addHookdOption() {
|
||||
// Find all "more" buttons (the ... button on tweets/posts)
|
||||
document.querySelectorAll('[data-testid="tweet"] [role="button"], [data-testid="tweet"] [aria-label*="more"], [data-testid="tweet"] [aria-label*="More"]').forEach(menuBtn => {
|
||||
// Check if we already added our option
|
||||
if (menuBtn.closest('[data-testid="tweet"]')?.querySelector('.hookd-menu-option')) continue;
|
||||
|
||||
const tweet = menuBtn.closest('[data-testid="tweet"]');
|
||||
if (!tweet) return;
|
||||
|
||||
// Create save button
|
||||
const saveBtn = document.createElement('div');
|
||||
saveBtn.className = 'hookd-menu-option';
|
||||
saveBtn.style.cssText = `
|
||||
padding: 12px 16px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 15px;
|
||||
color: #fff;
|
||||
`;
|
||||
saveBtn.innerHTML = '<span style="font-size:18px;">📌</span><span>Save to Hookd</span>';
|
||||
|
||||
saveBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
saveTweet(tweet);
|
||||
});
|
||||
|
||||
// Find the dropdown menu and append
|
||||
const dropdown = menuBtn.closest('[role="menu"]') || menuBtn.closest('div[aria-labelledby]');
|
||||
if (dropdown && !dropdown.querySelector('.hookd-menu-option')) {
|
||||
dropdown.appendChild(saveBtn);
|
||||
}
|
||||
});
|
||||
|
||||
// Also try to find DM more options
|
||||
document.querySelectorAll('[data-testid="DMMessage"] [role="button"]').forEach(btn => {
|
||||
if (btn.textContent.includes('more') || btn.getAttribute('aria-label')?.includes('more')) {
|
||||
const dm = btn.closest('[data-testid="DMMessage"]');
|
||||
if (dm && !dm.querySelector('.hookd-menu-option')) {
|
||||
const saveBtn = document.createElement('div');
|
||||
saveBtn.className = 'hookd-menu-option';
|
||||
saveBtn.style.cssText = `
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
`;
|
||||
saveBtn.innerHTML = '📌 Save to Hookd';
|
||||
|
||||
saveBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
saveDM(dm);
|
||||
});
|
||||
|
||||
// Insert after the clickable area
|
||||
btn.parentElement?.appendChild(saveBtn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save tweet
|
||||
function saveTweet(tweetElement) {
|
||||
try {
|
||||
// Extract author
|
||||
const authorEl = tweetElement.querySelector('[data-testid="User-Name"] span a[role="link"]') ||
|
||||
tweetElement.querySelector('a[tabindex="-1"]');
|
||||
const author = authorEl?.textContent?.trim()?.replace('@', '') || 'unknown';
|
||||
|
||||
// Extract content
|
||||
const contentEl = tweetElement.querySelector('[data-testid="tweetText"]');
|
||||
const content = contentEl?.textContent?.trim() || '';
|
||||
|
||||
// Extract link
|
||||
const linkEl = tweetElement.querySelector('a[href*="/status/"]');
|
||||
const link = linkEl?.href || '';
|
||||
|
||||
const item = {
|
||||
id: Date.now(),
|
||||
author: author,
|
||||
content: content.substring(0, 500),
|
||||
link: link,
|
||||
source: 'tweet',
|
||||
time: new Date().toISOString()
|
||||
};
|
||||
|
||||
// Save to storage via background
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'SAVE_ITEM',
|
||||
data: item
|
||||
}, (response) => {
|
||||
if (response?.success) {
|
||||
showNotification('Saved to Hookd!');
|
||||
} else {
|
||||
showNotification('Failed to save');
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Hookd save error:', err);
|
||||
showNotification('Error saving');
|
||||
}
|
||||
}
|
||||
|
||||
// Save DM
|
||||
function saveDM(dmElement) {
|
||||
try {
|
||||
const contentEl = dmElement.querySelector('[data-testid="dmMessageContent"]');
|
||||
const content = contentEl?.textContent?.trim() || '';
|
||||
|
||||
const item = {
|
||||
id: Date.now(),
|
||||
author: 'DM',
|
||||
content: content.substring(0, 500),
|
||||
source: 'dm',
|
||||
time: new Date().toISOString()
|
||||
};
|
||||
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'SAVE_ITEM',
|
||||
data: item
|
||||
}, (response) => {
|
||||
if (response?.success) {
|
||||
showNotification('Saved to Hookd!');
|
||||
} else {
|
||||
showNotification('Failed to save');
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Hookd save error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Show notification
|
||||
function showNotification(message) {
|
||||
const notif = document.createElement('div');
|
||||
notif.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background: #4F46E5;
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
z-index: 99999;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
`;
|
||||
notif.textContent = message;
|
||||
document.body.appendChild(notif);
|
||||
|
||||
setTimeout(() => {
|
||||
notif.style.opacity = '0';
|
||||
notif.style.transition = 'opacity 0.3s';
|
||||
setTimeout(() => notif.remove(), 300);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Watch for new elements
|
||||
const observer = new MutationObserver(() => {
|
||||
addHookdOption();
|
||||
});
|
||||
|
||||
// Start observing
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
// Initial scan
|
||||
setTimeout(addHookdOption, 1000);
|
||||
setTimeout(addHookdOption, 3000);
|
||||
|
||||
console.log('Hookd content script initialized');
|
||||
Reference in New Issue
Block a user