plusvibe api calls
This commit is contained in:
parent
478d064c78
commit
a3e928c80e
1 changed files with 78 additions and 98 deletions
|
|
@ -3,11 +3,28 @@
|
||||||
|
|
||||||
console.log('=== PLUSVIBE EXTRACTOR LOADING ===');
|
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 = {
|
const PlusvibeExtractor = {
|
||||||
// Configuration for API access (if available)
|
// Configuration for API access (if available)
|
||||||
apiConfig: {
|
apiConfig: {
|
||||||
apiKey: null, // Will be set from storage
|
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: {
|
endpoints: {
|
||||||
threads: '/threads',
|
threads: '/threads',
|
||||||
messages: '/messages',
|
messages: '/messages',
|
||||||
|
|
@ -16,7 +33,7 @@ const PlusvibeExtractor = {
|
||||||
inbox: '/inbox',
|
inbox: '/inbox',
|
||||||
emails: '/emails',
|
emails: '/emails',
|
||||||
unibox: '/unibox',
|
unibox: '/unibox',
|
||||||
threadMessages: '/threads/{threadId}/messages',
|
//threadMessages: '/threads/{threadId}/messages',
|
||||||
conversationMessages: '/conversations/{conversationId}/messages'
|
conversationMessages: '/conversations/{conversationId}/messages'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +60,7 @@ const PlusvibeExtractor = {
|
||||||
// Test API endpoints to find the correct ones
|
// Test API endpoints to find the correct ones
|
||||||
async testAPIEndpoints() {
|
async testAPIEndpoints() {
|
||||||
console.log('=== TESTING PLUSVIBE API ENDPOINTS ===');
|
console.log('=== TESTING PLUSVIBE API ENDPOINTS ===');
|
||||||
|
auther();
|
||||||
if (!this.apiConfig.apiKey) {
|
if (!this.apiConfig.apiKey) {
|
||||||
console.error('No API key available for testing');
|
console.error('No API key available for testing');
|
||||||
return;
|
return;
|
||||||
|
|
@ -55,7 +72,7 @@ const PlusvibeExtractor = {
|
||||||
'/conversations',
|
'/conversations',
|
||||||
'/inbox',
|
'/inbox',
|
||||||
'/emails',
|
'/emails',
|
||||||
'/unibox',
|
'/unibox/emails',
|
||||||
'/me',
|
'/me',
|
||||||
'/user',
|
'/user',
|
||||||
'/account'
|
'/account'
|
||||||
|
|
@ -66,7 +83,7 @@ const PlusvibeExtractor = {
|
||||||
console.log(`Testing endpoint: ${endpoint}`);
|
console.log(`Testing endpoint: ${endpoint}`);
|
||||||
const response = await fetch(`${this.apiConfig.baseUrl}${endpoint}`, {
|
const response = await fetch(`${this.apiConfig.baseUrl}${endpoint}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${this.apiConfig.apiKey}`,
|
'x-api-key': `${this.apiConfig.apiKey}`,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +186,7 @@ const PlusvibeExtractor = {
|
||||||
if (this.apiConfig.apiKey) {
|
if (this.apiConfig.apiKey) {
|
||||||
console.log('Attempting API extraction...');
|
console.log('Attempting API extraction...');
|
||||||
const apiMessages = await this.extractViaAPI();
|
const apiMessages = await this.extractViaAPI();
|
||||||
if (apiMessages && apiMessages.length > 0) {
|
if (apiMessages && apiMessages.length > 4) {
|
||||||
return apiMessages;
|
return apiMessages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -180,8 +197,8 @@ const PlusvibeExtractor = {
|
||||||
|
|
||||||
// Validate we got the right thread by checking for consistency
|
// Validate we got the right thread by checking for consistency
|
||||||
if (messages.length > 0) {
|
if (messages.length > 0) {
|
||||||
const currentThreadId = this.getCurrentThreadId();
|
//const currentThreadId = this.getCurrentThreadId();
|
||||||
console.log('Validating extracted messages for thread:', currentThreadId);
|
//console.log('Validating extracted messages for thread:', currentThreadId);
|
||||||
|
|
||||||
// Get all unique senders from extracted messages
|
// Get all unique senders from extracted messages
|
||||||
const extractedSenders = new Set(messages.map(msg => msg.sender.toLowerCase()));
|
const extractedSenders = new Set(messages.map(msg => msg.sender.toLowerCase()));
|
||||||
|
|
@ -268,53 +285,30 @@ const PlusvibeExtractor = {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const threadId = this.getCurrentThreadId();
|
//const threadId = this.getCurrentThreadId();
|
||||||
|
|
||||||
// Try different API patterns
|
// Try different API patterns
|
||||||
const apiPatterns = [
|
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
|
// Pattern 5: Inbox endpoint
|
||||||
async () => {
|
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);
|
return this.makeAPIRequest(url);
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -325,7 +319,7 @@ const PlusvibeExtractor = {
|
||||||
console.log(`Trying API pattern ${i + 1}...`);
|
console.log(`Trying API pattern ${i + 1}...`);
|
||||||
const data = await apiPatterns[i]();
|
const data = await apiPatterns[i]();
|
||||||
|
|
||||||
if (data && (data.messages || data.emails || data.conversations)) {
|
if (data) {
|
||||||
console.log(`API pattern ${i + 1} successful`);
|
console.log(`API pattern ${i + 1} successful`);
|
||||||
return this.normalizeAPIResponse(data);
|
return this.normalizeAPIResponse(data);
|
||||||
}
|
}
|
||||||
|
|
@ -344,9 +338,7 @@ const PlusvibeExtractor = {
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${this.apiConfig.apiKey}`,
|
'x-api-key': `${this.apiConfig.apiKey}`
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -358,48 +350,23 @@ const PlusvibeExtractor = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('API response received:', data);
|
console.log('API response received:' + JSON.stringify(data));
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Normalize different API response formats
|
// Normalize different API response formats
|
||||||
normalizeAPIResponse(data) {
|
normalizeAPIResponse(data) {
|
||||||
const messages = [];
|
const messages = [];
|
||||||
|
|
||||||
// Extract messages from various possible structures
|
// Extract messages from various possible structures
|
||||||
const messageArrays = [
|
const messageArrays = data.data;
|
||||||
data.messages,
|
|
||||||
data.emails,
|
|
||||||
data.conversations?.map(c => c.messages).flat(),
|
|
||||||
data.data?.messages,
|
|
||||||
data.data?.emails,
|
|
||||||
data.items,
|
|
||||||
data
|
|
||||||
].filter(Array.isArray);
|
|
||||||
|
|
||||||
for (const msgArray of messageArrays) {
|
for (const msg of messageArrays) {
|
||||||
if (msgArray.length > 0) {
|
|
||||||
console.log(`Found ${msgArray.length} messages in API response`);
|
|
||||||
|
|
||||||
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) {
|
if (msg.body.text) {
|
||||||
messages.push(message);
|
messages.push(msg.body.text);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
break; // Use first non-empty array
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Normalized ${messages.length} messages from API response`);
|
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
|
// NEW: First try to find thread boundaries to scope extraction
|
||||||
console.log('Attempting to find thread boundaries first...');
|
console.log('Attempting to find thread boundaries first...');
|
||||||
|
/*
|
||||||
const boundedMessages = this.findThreadBoundaries();
|
const boundedMessages = this.findThreadBoundaries();
|
||||||
if (boundedMessages && boundedMessages.length > 0) {
|
if (boundedMessages && boundedMessages.length > 0) {
|
||||||
console.log(`Found ${boundedMessages.length} messages within thread boundaries`);
|
console.log(`Found ${boundedMessages.length} messages within thread boundaries`);
|
||||||
return boundedMessages;
|
return boundedMessages;
|
||||||
}
|
}
|
||||||
|
testPlusvibeExtraction
|
||||||
// Fallback: Method 1 - Look for message containers with common patterns
|
// Fallback: Method 1 - Look for message containers with common patterns
|
||||||
console.log('Thread boundary detection failed, using global search...');
|
console.log('Thread boundary detection failed, using global search...');
|
||||||
const messageSelectors = [
|
const messageSelectors = [
|
||||||
|
|
@ -458,9 +426,9 @@ const PlusvibeExtractor = {
|
||||||
if (messages.length > 0) break;
|
if (messages.length > 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// Method 2: Try MUI/React structure extraction
|
// Method 2: Try MUI/React structure extraction
|
||||||
if (messages.length === 0) {
|
if (messages.length >= 0) {
|
||||||
console.log('Trying MUI/React structure extraction...');
|
console.log('Trying MUI/React structure extraction...');
|
||||||
const muiMessages = this.extractFromMUIStructure();
|
const muiMessages = this.extractFromMUIStructure();
|
||||||
if (muiMessages.length > 0) {
|
if (muiMessages.length > 0) {
|
||||||
|
|
@ -1412,6 +1380,7 @@ const PlusvibeExtractor = {
|
||||||
return messageElements;
|
return messageElements;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// New method: Extract from MUI/React structures
|
// New method: Extract from MUI/React structures
|
||||||
extractFromMUIStructure() {
|
extractFromMUIStructure() {
|
||||||
console.log('=== EXTRACTING FROM MUI STRUCTURE ===');
|
console.log('=== EXTRACTING FROM MUI STRUCTURE ===');
|
||||||
|
|
@ -1419,17 +1388,24 @@ const PlusvibeExtractor = {
|
||||||
|
|
||||||
// Look for MUI Box components that might contain messages
|
// Look for MUI Box components that might contain messages
|
||||||
const muiSelectors = [
|
const muiSelectors = [
|
||||||
'.MuiBox-root',
|
'.MuiBox-root'
|
||||||
'[class*="MuiBox"]',
|
// '[class*="MuiBox"]',
|
||||||
'[class*="css-"][class*="root"]',
|
// '[class*="css-"][class*="root"]',
|
||||||
'div[class^="css-"]'
|
// 'div[class^="css-"]',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const replyBox = this.findReplyBox();
|
||||||
|
const replyContainer = replyBox.closest('div');
|
||||||
|
|
||||||
// Find all potential message containers
|
// Find all potential message containers
|
||||||
const potentialMessages = [];
|
const potentialMessages = [];
|
||||||
muiSelectors.forEach(selector => {
|
muiSelectors.forEach(selector => {
|
||||||
const elements = document.querySelectorAll(selector);
|
const elements = document.querySelectorAll(selector);
|
||||||
elements.forEach(el => {
|
elements.forEach(el => {
|
||||||
|
|
||||||
|
const boxRect = el.getBoundingClientRect();
|
||||||
|
const replyRect = replyContainer.getBoundingClientRect();
|
||||||
|
if (boxRect.bottom < replyRect.top) {
|
||||||
const text = el.textContent;
|
const text = el.textContent;
|
||||||
// Check if this element looks like a message (has email and substantial content)
|
// Check if this element looks like a message (has email and substantial content)
|
||||||
if (text && text.includes('@') && text.length > 100 && text.length < 5000) {
|
if (text && text.includes('@') && text.length > 100 && text.length < 5000) {
|
||||||
|
|
@ -1444,17 +1420,21 @@ const PlusvibeExtractor = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Found ${potentialMessages.length} potential message containers`);
|
console.log(`Found ${potentialMessages.length} potential message containers`);
|
||||||
|
|
||||||
// Sort by likelihood of being a single message (not too many children, not too much text)
|
// 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 aScore = Math.abs(500 - a.text.length) + (a.childCount * 10);
|
||||||
const bScore = Math.abs(500 - b.text.length) + (b.childCount * 10);
|
const bScore = Math.abs(500 - b.text.length) + (b.childCount * 10);
|
||||||
return aScore - bScore;
|
return aScore - bScore;
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
// Process the most likely candidates
|
// Process the most likely candidates
|
||||||
const processedElements = new Set();
|
const processedElements = new Set();
|
||||||
|
|
@ -1591,8 +1571,8 @@ const PlusvibeExtractor = {
|
||||||
const hasReasonableEmails = emailCount >= 2 && emailCount <= 20; // Thread has 2-20 emails max
|
const hasReasonableEmails = emailCount >= 2 && emailCount <= 20; // Thread has 2-20 emails max
|
||||||
const isReasonableSize = rect.width > 300 && rect.width < window.innerWidth * 0.8;
|
const isReasonableSize = rect.width > 300 && rect.width < window.innerWidth * 0.8;
|
||||||
const hasNoInboxElements = !current.querySelector('.inbox-item, input[type="checkbox"]');
|
const hasNoInboxElements = !current.querySelector('.inbox-item, input[type="checkbox"]');
|
||||||
const isMuiDrawer = current.className.includes('MuiDrawer') ||
|
const isMuiDrawer = current.className.includes('MuiRoot') ||
|
||||||
current.closest('.MuiDrawer-root, .MuiDrawer-paper');
|
current.closest('.MuiBox-root, .MuiBox-root');
|
||||||
|
|
||||||
if (hasReasonableEmails && isReasonableSize && hasNoInboxElements) {
|
if (hasReasonableEmails && isReasonableSize && hasNoInboxElements) {
|
||||||
console.log('Found potential thread container at level', level);
|
console.log('Found potential thread container at level', level);
|
||||||
|
|
@ -1796,8 +1776,8 @@ window.testPlusvibeExtraction = async function() {
|
||||||
console.log('=== TESTING PLUSVIBE EXTRACTION ===');
|
console.log('=== TESTING PLUSVIBE EXTRACTION ===');
|
||||||
|
|
||||||
// Test thread ID
|
// Test thread ID
|
||||||
const threadId = PlusvibeExtractor.getCurrentThreadId();
|
//const threadId = PlusvibeExtractor.getCurrentThreadId();
|
||||||
console.log('Thread ID:', threadId);
|
//console.log('Thread ID:', threadId);
|
||||||
|
|
||||||
// Test MUI extraction specifically
|
// Test MUI extraction specifically
|
||||||
console.log('\nTesting MUI extraction...');
|
console.log('\nTesting MUI extraction...');
|
||||||
|
|
@ -1825,8 +1805,8 @@ window.quickDiagnosePlusvibe = function() {
|
||||||
console.log('=== QUICK PLUSVIBE DIAGNOSTIC ===');
|
console.log('=== QUICK PLUSVIBE DIAGNOSTIC ===');
|
||||||
|
|
||||||
// 1. Check thread ID
|
// 1. Check thread ID
|
||||||
const threadId = PlusvibeExtractor.getCurrentThreadId();
|
//const threadId = PlusvibeExtractor.getCurrentThreadId();
|
||||||
console.log('Thread ID:', threadId);
|
//console.log('Thread ID:', threadId);
|
||||||
|
|
||||||
// 2. Find reply box
|
// 2. Find reply box
|
||||||
const replyBox = PlusvibeExtractor.findReplyBox();
|
const replyBox = PlusvibeExtractor.findReplyBox();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue