# Plusvibe Thread Extraction Debugging Guide ## Quick Start Testing Open the browser console on Plusvibe and run these commands: ### 1. Test DOM Analysis ```javascript // Analyze the page structure PlusvibeExtractor.analyzeDOMStructure(); ``` ### 2. Test API Endpoints ```javascript // Test which API endpoints work await PlusvibeExtractor.testAPIEndpoints(); ``` ### 3. Test Thread Extraction ```javascript // Try to extract messages const messages = await PlusvibeExtractor.extractThreadMessages(); console.log('Extracted messages:', messages); ``` ### 4. Force DOM Extraction ```javascript // Skip API and test DOM extraction const domMessages = PlusvibeExtractor.extractViaDOM(); console.log('DOM messages:', domMessages); ``` ## Finding the Right Selectors ### Step 1: Identify Message Containers 1. **Right-click on a message** in Plusvibe 2. Select **"Inspect Element"** 3. Look for patterns in the HTML structure 4. Note the class names, IDs, and data attributes Common patterns to look for: - Classes containing: `message`, `email`, `thread`, `conversation` - Data attributes: `data-message-id`, `data-thread-id`, `data-email` - Container elements: `
`, `
`, `
  • `, `
    ` ### Step 2: Test Selectors ```javascript // Test a specific selector const elements = document.querySelectorAll('.your-selector-here'); console.log(`Found ${elements.length} elements`); elements.forEach((el, i) => { console.log(`Element ${i}:`, { text: el.textContent.substring(0, 100), classes: el.className, hasEmail: el.textContent.includes('@') }); }); ``` ### Step 3: Find Thread ID Location ```javascript // Search for thread IDs in various places const locations = [ // URL window.location.href, // Data attributes ...[...document.querySelectorAll('[data-id], [data-thread-id], [data-conversation-id]')].map(el => ({ element: el, id: el.getAttribute('data-id') || el.getAttribute('data-thread-id') || el.getAttribute('data-conversation-id') })), // Text content document.body.innerText.match(/ID:\s*([a-zA-Z0-9\-_]+)/gi) ]; console.log('Thread ID locations:', locations); ``` ## API Integration ### Testing API Authentication ```javascript // Test if your API key works fetch('https://app.pipl.ai/api/v2/me', { headers: { 'Authorization': 'Bearer YOUR_API_KEY_HERE', 'Content-Type': 'application/json' } }).then(r => r.json()).then(console.log); ``` ### Finding the Right Endpoints Try these common patterns: 1. `/api/v2/threads/{threadId}` 2. `/api/v2/conversations/{conversationId}` 3. `/api/v2/messages?thread={threadId}` 4. `/api/v2/inbox/messages` 5. `/api/v1/emails` ### API Response Formats Look for these common structures: ```javascript // Format 1: Direct messages array { "messages": [ { "id": "123", "from": "sender@email.com", "content": "Message text", "timestamp": "2024-01-01T12:00:00Z" } ] } // Format 2: Nested in data { "data": { "messages": [...] } } // Format 3: Thread with messages { "thread": { "id": "thread123", "messages": [...] } } ``` ## Advanced DOM Extraction ### Visual Proximity Method This method finds emails and looks for content nearby: ```javascript // Find all email addresses on the page const emailRegex = /[\w.+-]+@[\w.-]+\.\w+/g; const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, null, false ); const emailNodes = []; let node; while (node = walker.nextNode()) { if (emailRegex.test(node.textContent)) { emailNodes.push({ node: node, parent: node.parentElement, email: node.textContent.match(emailRegex)[0] }); } } console.log('Email nodes found:', emailNodes); ``` ### Pattern-Based Extraction Test different patterns: ```javascript const patterns = { // Pattern 1: "email wrote:" wrote: /([\w.+-]+@[\w.-]+\.\w+)\s+wrote:/gi, // Pattern 2: Timestamp followed by content timestamp: /(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4}.*?)\n([\s\S]+?)(?=\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4}|$)/gi, // Pattern 3: Email in header header: /From:\s*([\w.+-]+@[\w.-]+\.\w+)/gi }; Object.entries(patterns).forEach(([name, pattern]) => { const matches = [...document.body.innerText.matchAll(pattern)]; console.log(`Pattern "${name}" found ${matches.length} matches`); matches.slice(0, 3).forEach((match, i) => { console.log(` Match ${i + 1}:`, match[0].substring(0, 100)); }); }); ``` ## Common Issues and Solutions ### Issue 1: No Messages Found **Solution**: Check if messages are in an iframe ```javascript const iframes = document.querySelectorAll('iframe'); iframes.forEach((iframe, i) => { try { const iframeDoc = iframe.contentDocument; if (iframeDoc && iframeDoc.body.textContent.includes('@')) { console.log(`Iframe ${i} contains email content`); // You may need to run extraction inside the iframe } } catch (e) { console.log(`Iframe ${i} is cross-origin`); } }); ``` ### Issue 2: Dynamic Content Loading **Solution**: Wait for content to load ```javascript // Observer to detect when messages load const observer = new MutationObserver((mutations) => { const hasNewEmails = mutations.some(m => [...m.addedNodes].some(n => n.textContent && n.textContent.includes('@') ) ); if (hasNewEmails) { console.log('New email content detected'); // Re-run extraction PlusvibeExtractor.extractThreadMessages(); } }); observer.observe(document.body, { childList: true, subtree: true }); ``` ### Issue 3: Messages in Shadow DOM **Solution**: Check for shadow roots ```javascript function findShadowRoots(root = document.body) { const elements = []; function traverse(node) { if (node.shadowRoot) { elements.push(node.shadowRoot); traverse(node.shadowRoot); } for (const child of node.children || []) { traverse(child); } } traverse(root); console.log('Found shadow roots:', elements); return elements; } findShadowRoots(); ``` ## Reporting Issues When reporting issues, please provide: 1. **Console output** from: ```javascript PlusvibeExtractor.analyzeDOMStructure(); ``` 2. **Sample HTML** of a message element: ```javascript // Right-click message → Inspect → Copy → Copy outerHTML ``` 3. **API test results** (if using API): ```javascript await PlusvibeExtractor.testAPIEndpoints(); ``` 4. **Current URL format**: ```javascript console.log({ href: window.location.href, pathname: window.location.pathname, search: window.location.search, hash: window.location.hash }); ``` This information will help identify the correct selectors and methods for your Plusvibe instance.