From a3e928c80e87ac9320b9255f68142811bcc6edf7 Mon Sep 17 00:00:00 2001 From: priyatham Date: Sun, 6 Jul 2025 13:18:20 -0700 Subject: [PATCH] plusvibe api calls --- plusvibe_extractor.js | 176 +++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 98 deletions(-) diff --git a/plusvibe_extractor.js b/plusvibe_extractor.js index 9995f12..3c3fd25 100644 --- a/plusvibe_extractor.js +++ b/plusvibe_extractor.js @@ -3,11 +3,28 @@ console.log('=== PLUSVIBE EXTRACTOR LOADING ==='); +async function auther(){ + const resp = await fetch(`https://api.pipl.ai/api/v1/authenticate`, { + headers: { + 'x-api-key': `00b8ea67-12a5640a-5ff001fe-a55f26f8 +`, +'Access-Control-Allow-Origin': '*', +'Access-Control-Allow-Headers': 'Content-Type', +'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS' + + } + }); + + console.log(`authenticate: ${resp.status} ${resp.statusText}`); + const json = await resp.json() + console.log("response" +text); + +} const PlusvibeExtractor = { // Configuration for API access (if available) apiConfig: { apiKey: null, // Will be set from storage - baseUrl: 'https://app.pipl.ai/api/v2', // Adjust based on actual API + baseUrl: 'https://api.pipl.ai/api/v1', // Adjust based on actual API endpoints: { threads: '/threads', messages: '/messages', @@ -16,7 +33,7 @@ const PlusvibeExtractor = { inbox: '/inbox', emails: '/emails', unibox: '/unibox', - threadMessages: '/threads/{threadId}/messages', + //threadMessages: '/threads/{threadId}/messages', conversationMessages: '/conversations/{conversationId}/messages' } }, @@ -43,7 +60,7 @@ const PlusvibeExtractor = { // Test API endpoints to find the correct ones async testAPIEndpoints() { console.log('=== TESTING PLUSVIBE API ENDPOINTS ==='); - + auther(); if (!this.apiConfig.apiKey) { console.error('No API key available for testing'); return; @@ -55,7 +72,7 @@ const PlusvibeExtractor = { '/conversations', '/inbox', '/emails', - '/unibox', + '/unibox/emails', '/me', '/user', '/account' @@ -66,7 +83,7 @@ const PlusvibeExtractor = { console.log(`Testing endpoint: ${endpoint}`); const response = await fetch(`${this.apiConfig.baseUrl}${endpoint}`, { headers: { - 'Authorization': `Bearer ${this.apiConfig.apiKey}`, + 'x-api-key': `${this.apiConfig.apiKey}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } @@ -169,7 +186,7 @@ const PlusvibeExtractor = { if (this.apiConfig.apiKey) { console.log('Attempting API extraction...'); const apiMessages = await this.extractViaAPI(); - if (apiMessages && apiMessages.length > 0) { + if (apiMessages && apiMessages.length > 4) { return apiMessages; } } @@ -180,8 +197,8 @@ const PlusvibeExtractor = { // Validate we got the right thread by checking for consistency if (messages.length > 0) { - const currentThreadId = this.getCurrentThreadId(); - console.log('Validating extracted messages for thread:', currentThreadId); + //const currentThreadId = this.getCurrentThreadId(); + //console.log('Validating extracted messages for thread:', currentThreadId); // Get all unique senders from extracted messages const extractedSenders = new Set(messages.map(msg => msg.sender.toLowerCase())); @@ -268,53 +285,30 @@ const PlusvibeExtractor = { return null; } - const threadId = this.getCurrentThreadId(); + //const threadId = this.getCurrentThreadId(); // Try different API patterns const apiPatterns = [ - // Pattern 1: Direct thread messages - async () => { - if (!threadId) return null; - const url = `${this.apiConfig.baseUrl}/threads/${threadId}/messages`; - return this.makeAPIRequest(url); - }, - - // Pattern 2: Conversation messages - async () => { - if (!threadId) return null; - const url = `${this.apiConfig.baseUrl}/conversations/${threadId}/messages`; - return this.makeAPIRequest(url); - }, - - // Pattern 3: Get thread details first - async () => { - if (!threadId) return null; - const threadUrl = `${this.apiConfig.baseUrl}/threads/${threadId}`; - const threadData = await this.makeAPIRequest(threadUrl); - if (threadData && threadData.messages) { - return { messages: threadData.messages }; - } - return null; - }, - - // Pattern 4: List recent messages and filter - async () => { - const url = `${this.apiConfig.baseUrl}/messages?limit=50`; - const data = await this.makeAPIRequest(url); - if (data && data.messages && threadId) { - // Filter messages by thread ID - const filtered = data.messages.filter(msg => - msg.threadId === threadId || - msg.conversationId === threadId - ); - return { messages: filtered }; - } - return data; - }, - // Pattern 5: Inbox endpoint async () => { - const url = `${this.apiConfig.baseUrl}/inbox`; + var workspace_id = null; + const workspace_url = new URL(`${this.apiConfig.baseUrl}/authenticate`) + const workspace_response = await this.makeAPIRequest(workspace_url); + for(workspace of workspace_response.workspaces){ + if(workspace._id) + { + workspace_id = workspace._id; + break; + + } + } + + + const url = new URL(`${this.apiConfig.baseUrl}/unibox/emails`); + url.searchParams.set('workspace_id',workspace_id) + url.searchParams.set('lead','BenJohnson@WhiteRiver.com') + url.searchParams.set('preview_only','false') + return this.makeAPIRequest(url); } ]; @@ -325,7 +319,7 @@ const PlusvibeExtractor = { console.log(`Trying API pattern ${i + 1}...`); const data = await apiPatterns[i](); - if (data && (data.messages || data.emails || data.conversations)) { + if (data) { console.log(`API pattern ${i + 1} successful`); return this.normalizeAPIResponse(data); } @@ -344,9 +338,7 @@ const PlusvibeExtractor = { const response = await fetch(url, { headers: { - 'Authorization': `Bearer ${this.apiConfig.apiKey}`, - 'Content-Type': 'application/json', - 'Accept': 'application/json' + 'x-api-key': `${this.apiConfig.apiKey}` } }); @@ -358,48 +350,23 @@ const PlusvibeExtractor = { } const data = await response.json(); - console.log('API response received:', data); + console.log('API response received:' + JSON.stringify(data)); return data; }, // Normalize different API response formats normalizeAPIResponse(data) { const messages = []; - // Extract messages from various possible structures - const messageArrays = [ - data.messages, - data.emails, - data.conversations?.map(c => c.messages).flat(), - data.data?.messages, - data.data?.emails, - data.items, - data - ].filter(Array.isArray); + const messageArrays = data.data; - for (const msgArray of messageArrays) { - if (msgArray.length > 0) { - console.log(`Found ${msgArray.length} messages in API response`); + for (const msg of messageArrays) { - msgArray.forEach((msg, index) => { - // Try different field mappings - const message = { - sender: msg.from || msg.sender || msg.sender_email || msg.from_email || 'unknown@email.com', - senderName: msg.sender_name || msg.from_name || msg.name || msg.from?.split('@')[0] || 'Unknown', - timestamp: msg.timestamp || msg.created_at || msg.date || msg.sent_at || new Date().toISOString(), - content: msg.content || msg.body || msg.text || msg.message || msg.html || '', - subject: msg.subject || data.subject || data.thread_subject || 'No Subject', - isReply: index > 0, - messageId: msg.id || msg.message_id || msg._id - }; - if (message.content) { - messages.push(message); + if (msg.body.text) { + messages.push(msg.body.text); } - }); - break; // Use first non-empty array - } } console.log(`Normalized ${messages.length} messages from API response`); @@ -412,12 +379,13 @@ const PlusvibeExtractor = { // NEW: First try to find thread boundaries to scope extraction console.log('Attempting to find thread boundaries first...'); + /* const boundedMessages = this.findThreadBoundaries(); if (boundedMessages && boundedMessages.length > 0) { console.log(`Found ${boundedMessages.length} messages within thread boundaries`); return boundedMessages; } - + testPlusvibeExtraction // Fallback: Method 1 - Look for message containers with common patterns console.log('Thread boundary detection failed, using global search...'); const messageSelectors = [ @@ -458,9 +426,9 @@ const PlusvibeExtractor = { if (messages.length > 0) break; } } - + */ // Method 2: Try MUI/React structure extraction - if (messages.length === 0) { + if (messages.length >= 0) { console.log('Trying MUI/React structure extraction...'); const muiMessages = this.extractFromMUIStructure(); if (muiMessages.length > 0) { @@ -1412,6 +1380,7 @@ const PlusvibeExtractor = { return messageElements; }, + // New method: Extract from MUI/React structures extractFromMUIStructure() { console.log('=== EXTRACTING FROM MUI STRUCTURE ==='); @@ -1419,17 +1388,24 @@ const PlusvibeExtractor = { // Look for MUI Box components that might contain messages const muiSelectors = [ - '.MuiBox-root', - '[class*="MuiBox"]', - '[class*="css-"][class*="root"]', - 'div[class^="css-"]' + '.MuiBox-root' +// '[class*="MuiBox"]', + // '[class*="css-"][class*="root"]', + // 'div[class^="css-"]', ]; + + const replyBox = this.findReplyBox(); +const replyContainer = replyBox.closest('div'); // Find all potential message containers const potentialMessages = []; muiSelectors.forEach(selector => { const elements = document.querySelectorAll(selector); elements.forEach(el => { + +const boxRect = el.getBoundingClientRect(); + const replyRect = replyContainer.getBoundingClientRect(); + if (boxRect.bottom < replyRect.top) { const text = el.textContent; // Check if this element looks like a message (has email and substantial content) if (text && text.includes('@') && text.length > 100 && text.length < 5000) { @@ -1444,17 +1420,21 @@ const PlusvibeExtractor = { }); } } + } }); }); console.log(`Found ${potentialMessages.length} potential message containers`); // Sort by likelihood of being a single message (not too many children, not too much text) - potentialMessages.sort((a, b) => { + potentialMessages.sort((a, b) => b.top - a.top); + + /* potentialMessages.sort((a, b) => { const aScore = Math.abs(500 - a.text.length) + (a.childCount * 10); const bScore = Math.abs(500 - b.text.length) + (b.childCount * 10); return aScore - bScore; }); + */ // Process the most likely candidates const processedElements = new Set(); @@ -1591,8 +1571,8 @@ const PlusvibeExtractor = { const hasReasonableEmails = emailCount >= 2 && emailCount <= 20; // Thread has 2-20 emails max const isReasonableSize = rect.width > 300 && rect.width < window.innerWidth * 0.8; const hasNoInboxElements = !current.querySelector('.inbox-item, input[type="checkbox"]'); - const isMuiDrawer = current.className.includes('MuiDrawer') || - current.closest('.MuiDrawer-root, .MuiDrawer-paper'); + const isMuiDrawer = current.className.includes('MuiRoot') || + current.closest('.MuiBox-root, .MuiBox-root'); if (hasReasonableEmails && isReasonableSize && hasNoInboxElements) { console.log('Found potential thread container at level', level); @@ -1796,8 +1776,8 @@ window.testPlusvibeExtraction = async function() { console.log('=== TESTING PLUSVIBE EXTRACTION ==='); // Test thread ID - const threadId = PlusvibeExtractor.getCurrentThreadId(); - console.log('Thread ID:', threadId); + //const threadId = PlusvibeExtractor.getCurrentThreadId(); + //console.log('Thread ID:', threadId); // Test MUI extraction specifically console.log('\nTesting MUI extraction...'); @@ -1825,8 +1805,8 @@ window.quickDiagnosePlusvibe = function() { console.log('=== QUICK PLUSVIBE DIAGNOSTIC ==='); // 1. Check thread ID - const threadId = PlusvibeExtractor.getCurrentThreadId(); - console.log('Thread ID:', threadId); + //const threadId = PlusvibeExtractor.getCurrentThreadId(); + //console.log('Thread ID:', threadId); // 2. Find reply box const replyBox = PlusvibeExtractor.findReplyBox();