@xuda.io/ai_module 1.1.4767 → 1.1.4769
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +59 -2742
- package/old.mjs +2688 -0
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -7207,144 +7207,6 @@ const get_image_blob_from_downloaded_image = async function (url) {
|
|
|
7207
7207
|
return images[0];
|
|
7208
7208
|
};
|
|
7209
7209
|
|
|
7210
|
-
// export const get_business_info = async function (uid, name, email, account_profile_info) {
|
|
7211
|
-
// // Extract lists from your JSON categories array
|
|
7212
|
-
// const categories = [
|
|
7213
|
-
// {
|
|
7214
|
-
// id: 'ind_technology',
|
|
7215
|
-
// name: 'Technology',
|
|
7216
|
-
// sub: ['Software Development', 'AI & Machine Learning', 'Cybersecurity', 'Cloud Computing', 'IT Services', 'SaaS & Platforms', 'Hardware & Electronics'],
|
|
7217
|
-
// },
|
|
7218
|
-
// {
|
|
7219
|
-
// id: 'ind_marketing',
|
|
7220
|
-
// name: 'Marketing & Advertising',
|
|
7221
|
-
// sub: ['Digital Marketing', 'PPC & SEO', 'Content Creation', 'Branding', 'Social Media Management', 'Email Marketing', 'Market Research'],
|
|
7222
|
-
// },
|
|
7223
|
-
// {
|
|
7224
|
-
// id: 'ind_sales',
|
|
7225
|
-
// name: 'Sales',
|
|
7226
|
-
// sub: ['B2B Sales', 'B2C Sales', 'Real Estate Sales', 'Account Management', 'Lead Generation', 'Inside Sales', 'Field Sales'],
|
|
7227
|
-
// },
|
|
7228
|
-
// {
|
|
7229
|
-
// id: 'ind_finance',
|
|
7230
|
-
// name: 'Finance & Accounting',
|
|
7231
|
-
// sub: ['Banking', 'Investment', 'Financial Planning', 'Accounting', 'Bookkeeping', 'Insurance', 'FinTech'],
|
|
7232
|
-
// },
|
|
7233
|
-
// {
|
|
7234
|
-
// id: 'ind_healthcare',
|
|
7235
|
-
// name: 'Healthcare',
|
|
7236
|
-
// sub: ['Medical Clinics', 'Hospitals', 'Pharma', 'Mental Health', 'Healthcare IT', 'Home Care', 'Medical Research'],
|
|
7237
|
-
// },
|
|
7238
|
-
// {
|
|
7239
|
-
// id: 'ind_realestate',
|
|
7240
|
-
// name: 'Real Estate',
|
|
7241
|
-
// sub: ['Residential Real Estate', 'Commercial Real Estate', 'Property Management', 'Investment & BRRRR', 'Construction', 'Architecture', 'Interior Design'],
|
|
7242
|
-
// },
|
|
7243
|
-
// {
|
|
7244
|
-
// id: 'ind_ecommerce',
|
|
7245
|
-
// name: 'E-commerce',
|
|
7246
|
-
// sub: ['Online Store', 'Dropshipping', 'Amazon FBA', 'Marketplace Selling', 'Retail', 'Inventory Management', 'Fulfillment & Logistics'],
|
|
7247
|
-
// },
|
|
7248
|
-
// {
|
|
7249
|
-
// id: 'ind_education',
|
|
7250
|
-
// name: 'Education',
|
|
7251
|
-
// sub: ['Schools', 'Universities', 'Private Tutoring', 'Online Courses', 'EdTech', 'Training & Development'],
|
|
7252
|
-
// },
|
|
7253
|
-
// {
|
|
7254
|
-
// id: 'ind_hospitality',
|
|
7255
|
-
// name: 'Hospitality & Travel',
|
|
7256
|
-
// sub: ['Hotels', 'Restaurants', 'Cafes & Bars', 'Travel Agencies', 'Tourism', 'Events & Catering', 'Transportation'],
|
|
7257
|
-
// },
|
|
7258
|
-
// {
|
|
7259
|
-
// id: 'ind_professional',
|
|
7260
|
-
// name: 'Professional Services',
|
|
7261
|
-
// sub: ['Legal', 'Consulting', 'HR & Recruiting', 'Accounting Firms', 'Business Services', 'Management Consulting'],
|
|
7262
|
-
// },
|
|
7263
|
-
// {
|
|
7264
|
-
// id: 'ind_manufacturing',
|
|
7265
|
-
// name: 'Manufacturing',
|
|
7266
|
-
// sub: ['Automotive', 'Industrial', 'Textile', 'Electronics', 'Food Production', 'Machinery', 'Chemicals'],
|
|
7267
|
-
// },
|
|
7268
|
-
// {
|
|
7269
|
-
// id: 'ind_nonprofit',
|
|
7270
|
-
// name: 'Nonprofit & Government',
|
|
7271
|
-
// sub: ['NGOs', 'Municipality', 'Government Services', 'Public Health', 'Community Organizations', 'Education Programs'],
|
|
7272
|
-
// },
|
|
7273
|
-
// {
|
|
7274
|
-
// id: 'ind_media',
|
|
7275
|
-
// name: 'Media & Entertainment',
|
|
7276
|
-
// sub: ['Film & Video', 'Music', 'Publishing', 'Gaming', 'News & Journalism', 'Influencers', 'Production Studios'],
|
|
7277
|
-
// },
|
|
7278
|
-
// {
|
|
7279
|
-
// id: 'ind_logistics',
|
|
7280
|
-
// name: 'Logistics & Transportation',
|
|
7281
|
-
// sub: ['Shipping', 'Trucking', 'Last-Mile Delivery', 'Warehousing', 'Freight Forwarding', 'Route Optimization'],
|
|
7282
|
-
// },
|
|
7283
|
-
// {
|
|
7284
|
-
// id: 'ind_energy',
|
|
7285
|
-
// name: 'Energy & Utilities',
|
|
7286
|
-
// sub: ['Solar', 'Oil & Gas', 'Electricity Providers', 'Water Utilities', 'Environmental Services', 'Renewable Energy'],
|
|
7287
|
-
// },
|
|
7288
|
-
// {
|
|
7289
|
-
// id: 'ind_construction',
|
|
7290
|
-
// name: 'Construction & Trades',
|
|
7291
|
-
// sub: ['General Contracting', 'Roofing', 'Plumbing', 'HVAC', 'Electrical', 'Renovation', 'Engineering'],
|
|
7292
|
-
// },
|
|
7293
|
-
// {
|
|
7294
|
-
// id: 'ind_food',
|
|
7295
|
-
// name: 'Food & Beverage',
|
|
7296
|
-
// sub: ['Restaurants', 'Catering', 'Food Manufacturing', 'Bakeries', 'Bars & Nightlife', 'Food Delivery'],
|
|
7297
|
-
// },
|
|
7298
|
-
// {
|
|
7299
|
-
// id: 'ind_retail',
|
|
7300
|
-
// name: 'Retail',
|
|
7301
|
-
// sub: ['Physical Stores', 'Boutiques', 'Supermarkets', 'Consumer Goods', 'Fashion Retail', 'Home Goods'],
|
|
7302
|
-
// },
|
|
7303
|
-
// ];
|
|
7304
|
-
// const categoryNames = categories.map((c) => c.name);
|
|
7305
|
-
// const allSubCategories = categories.flatMap((c) => c.sub);
|
|
7306
|
-
|
|
7307
|
-
// const business_info_ret = await submit_chat_gpt_prompt({
|
|
7308
|
-
// uid,
|
|
7309
|
-
// prompt: `Research the company: "${name}" (${email}).
|
|
7310
|
-
// 1. get the company name.
|
|
7311
|
-
// 2. get the domain name from the email.
|
|
7312
|
-
// 2. Provide a professional one-sentence biography of the company.
|
|
7313
|
-
// 3. Categorize them using the provided industry lists.
|
|
7314
|
-
// 4. Identify their primary country as a 2-letter ISO code (e.g., 'US').`,
|
|
7315
|
-
// model: 'gpt-5-nano',
|
|
7316
|
-
// response_format: z.object({
|
|
7317
|
-
// business_name: z.string().describe('the company name'),
|
|
7318
|
-
// business_domain: z.string().describe('the email domain name'),
|
|
7319
|
-
// business_bio: z.string().describe('A concise, professional one-sentence summary of what the business does'),
|
|
7320
|
-
// business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
|
|
7321
|
-
// business_category: z.enum(categoryNames),
|
|
7322
|
-
// business_sub_category: z.enum(allSubCategories),
|
|
7323
|
-
// business_country: z.string().length(2).describe("2-letter ISO country code (e.g., 'US')"),
|
|
7324
|
-
// }),
|
|
7325
|
-
// metadata: { func: 'get_business_info' },
|
|
7326
|
-
// account_profile_info,
|
|
7327
|
-
// tools: [{ type: 'web_search_preview' }],
|
|
7328
|
-
// });
|
|
7329
|
-
|
|
7330
|
-
// try {
|
|
7331
|
-
// if (business_info_ret.code > -1) {
|
|
7332
|
-
// const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
|
|
7333
|
-
|
|
7334
|
-
// // Standardize country to uppercase
|
|
7335
|
-
// if (data.business_country) data.business_country = data.business_country.toUpperCase();
|
|
7336
|
-
|
|
7337
|
-
// // Logic to attach the ID for your database
|
|
7338
|
-
// const matched = categories.find((c) => c.name === data.business_category);
|
|
7339
|
-
// data.business_category_id = matched ? matched.id : null;
|
|
7340
|
-
|
|
7341
|
-
// return data;
|
|
7342
|
-
// }
|
|
7343
|
-
// } catch (error) {
|
|
7344
|
-
// console.error('Error in get_business_info:', error);
|
|
7345
|
-
// }
|
|
7346
|
-
// };
|
|
7347
|
-
|
|
7348
7210
|
const get_chat_picture_cache = async function (uid, docType, key) {
|
|
7349
7211
|
if (!key || typeof key !== 'string') return null;
|
|
7350
7212
|
|
|
@@ -7657,6 +7519,65 @@ Category:`;
|
|
|
7657
7519
|
};
|
|
7658
7520
|
|
|
7659
7521
|
export const categorize_ai_prompt = async function (uid, prompt_text, account_profile_info) {
|
|
7522
|
+
// Helper functions (would be defined elsewhere)
|
|
7523
|
+
async function hashPrompt(text) {
|
|
7524
|
+
// Simple hash function for deduplication
|
|
7525
|
+
const encoder = new TextEncoder();
|
|
7526
|
+
const data = encoder.encode(text);
|
|
7527
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
7528
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
7529
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
7530
|
+
}
|
|
7531
|
+
|
|
7532
|
+
async function analyzePromptComplexity(prompt, category) {
|
|
7533
|
+
// Analyze prompt complexity based on various factors
|
|
7534
|
+
const wordCount = prompt.split(/\s+/).length;
|
|
7535
|
+
const sentenceCount = prompt.split(/[.!?]+/).length;
|
|
7536
|
+
const hasTechnicalTerms = /(\bAPI\b|\balgorithm\b|\bdebug\b|\banalysis\b)/i.test(prompt);
|
|
7537
|
+
const hasMultipleSteps = /(first|then|next|finally|step 1|step 2)/i.test(prompt);
|
|
7538
|
+
const requiresResearch = /(research|find|look up|investigate)/i.test(prompt);
|
|
7539
|
+
|
|
7540
|
+
let complexity = 'Basic';
|
|
7541
|
+
let estimatedTokens = Math.ceil(wordCount * 1.3); // Rough estimation
|
|
7542
|
+
|
|
7543
|
+
if (wordCount > 100 || hasTechnicalTerms || hasMultipleSteps) {
|
|
7544
|
+
complexity = 'Intermediate';
|
|
7545
|
+
}
|
|
7546
|
+
if (wordCount > 300 || requiresResearch || category.includes('Advanced') || category.includes('Expert')) {
|
|
7547
|
+
complexity = 'Advanced';
|
|
7548
|
+
}
|
|
7549
|
+
if (wordCount > 500 || category.includes('Research') || category.includes('Analysis')) {
|
|
7550
|
+
complexity = 'Expert';
|
|
7551
|
+
}
|
|
7552
|
+
|
|
7553
|
+
return {
|
|
7554
|
+
complexity,
|
|
7555
|
+
estimated_tokens: estimatedTokens,
|
|
7556
|
+
requires_specialized_knowledge: hasTechnicalTerms || requiresResearch,
|
|
7557
|
+
word_count: wordCount,
|
|
7558
|
+
sentence_count: sentenceCount,
|
|
7559
|
+
};
|
|
7560
|
+
}
|
|
7561
|
+
|
|
7562
|
+
function getDomainFromCategory(category) {
|
|
7563
|
+
// Map categories to broader domains
|
|
7564
|
+
const domainMap = {
|
|
7565
|
+
Creative: /writing|story|poetry|creative|art|design/i,
|
|
7566
|
+
Technical: /code|programming|technical|software|api|database/i,
|
|
7567
|
+
Business: /business|marketing|sales|strategy|management/i,
|
|
7568
|
+
Academic: /research|study|homework|academic|education/i,
|
|
7569
|
+
Personal: /advice|personal|relationship|health|fitness/i,
|
|
7570
|
+
Analytical: /analysis|data|statistical|trend|forecast/i,
|
|
7571
|
+
};
|
|
7572
|
+
|
|
7573
|
+
for (const [domain, pattern] of Object.entries(domainMap)) {
|
|
7574
|
+
if (pattern.test(category)) {
|
|
7575
|
+
return domain;
|
|
7576
|
+
}
|
|
7577
|
+
}
|
|
7578
|
+
return 'General';
|
|
7579
|
+
}
|
|
7580
|
+
|
|
7660
7581
|
const ai_prompt_categories = [
|
|
7661
7582
|
// Creative & Content Generation (1-15)
|
|
7662
7583
|
'Creative Writing',
|
|
@@ -7983,64 +7904,6 @@ Category:`;
|
|
|
7983
7904
|
}
|
|
7984
7905
|
};
|
|
7985
7906
|
|
|
7986
|
-
// Helper functions (would be defined elsewhere)
|
|
7987
|
-
async function hashPrompt(text) {
|
|
7988
|
-
// Simple hash function for deduplication
|
|
7989
|
-
const encoder = new TextEncoder();
|
|
7990
|
-
const data = encoder.encode(text);
|
|
7991
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
7992
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
7993
|
-
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
7994
|
-
}
|
|
7995
|
-
|
|
7996
|
-
async function analyzePromptComplexity(prompt, category) {
|
|
7997
|
-
// Analyze prompt complexity based on various factors
|
|
7998
|
-
const wordCount = prompt.split(/\s+/).length;
|
|
7999
|
-
const sentenceCount = prompt.split(/[.!?]+/).length;
|
|
8000
|
-
const hasTechnicalTerms = /(\bAPI\b|\balgorithm\b|\bdebug\b|\banalysis\b)/i.test(prompt);
|
|
8001
|
-
const hasMultipleSteps = /(first|then|next|finally|step 1|step 2)/i.test(prompt);
|
|
8002
|
-
const requiresResearch = /(research|find|look up|investigate)/i.test(prompt);
|
|
8003
|
-
|
|
8004
|
-
let complexity = 'Basic';
|
|
8005
|
-
let estimatedTokens = Math.ceil(wordCount * 1.3); // Rough estimation
|
|
8006
|
-
|
|
8007
|
-
if (wordCount > 100 || hasTechnicalTerms || hasMultipleSteps) {
|
|
8008
|
-
complexity = 'Intermediate';
|
|
8009
|
-
}
|
|
8010
|
-
if (wordCount > 300 || requiresResearch || category.includes('Advanced') || category.includes('Expert')) {
|
|
8011
|
-
complexity = 'Advanced';
|
|
8012
|
-
}
|
|
8013
|
-
if (wordCount > 500 || category.includes('Research') || category.includes('Analysis')) {
|
|
8014
|
-
complexity = 'Expert';
|
|
8015
|
-
}
|
|
8016
|
-
|
|
8017
|
-
return {
|
|
8018
|
-
complexity,
|
|
8019
|
-
estimated_tokens: estimatedTokens,
|
|
8020
|
-
requires_specialized_knowledge: hasTechnicalTerms || requiresResearch,
|
|
8021
|
-
word_count: wordCount,
|
|
8022
|
-
sentence_count: sentenceCount,
|
|
8023
|
-
};
|
|
8024
|
-
}
|
|
8025
|
-
|
|
8026
|
-
function getDomainFromCategory(category) {
|
|
8027
|
-
// Map categories to broader domains
|
|
8028
|
-
const domainMap = {
|
|
8029
|
-
Creative: /writing|story|poetry|creative|art|design/i,
|
|
8030
|
-
Technical: /code|programming|technical|software|api|database/i,
|
|
8031
|
-
Business: /business|marketing|sales|strategy|management/i,
|
|
8032
|
-
Academic: /research|study|homework|academic|education/i,
|
|
8033
|
-
Personal: /advice|personal|relationship|health|fitness/i,
|
|
8034
|
-
Analytical: /analysis|data|statistical|trend|forecast/i,
|
|
8035
|
-
};
|
|
8036
|
-
|
|
8037
|
-
for (const [domain, pattern] of Object.entries(domainMap)) {
|
|
8038
|
-
if (pattern.test(category)) {
|
|
8039
|
-
return domain;
|
|
8040
|
-
}
|
|
8041
|
-
}
|
|
8042
|
-
return 'General';
|
|
8043
|
-
}
|
|
8044
7907
|
export const categorize_text_message = async function (uid, text_message, account_profile_info) {
|
|
8045
7908
|
const text_message_categories = [
|
|
8046
7909
|
// Personal Communication (1-20)
|
|
@@ -8747,2552 +8610,6 @@ Category:`;
|
|
|
8747
8610
|
}
|
|
8748
8611
|
};
|
|
8749
8612
|
|
|
8750
|
-
// export const get_business_info = async function (uid, name, email, account_profile_info) {
|
|
8751
|
-
// // ========== HELPER FUNCTIONS ==========
|
|
8752
|
-
|
|
8753
|
-
// function validatePhoneNumber(phone) {
|
|
8754
|
-
// if (!phone || phone.toLowerCase() === 'not available' || phone.trim() === '') {
|
|
8755
|
-
// return 'Not available';
|
|
8756
|
-
// }
|
|
8757
|
-
|
|
8758
|
-
// const cleaned = phone.replace(/[^\d\+\(\)\-\s]/g, '');
|
|
8759
|
-
// const digitCount = (cleaned.match(/\d/g) || []).length;
|
|
8760
|
-
|
|
8761
|
-
// // Require at least 7 digits for a valid phone number
|
|
8762
|
-
// if (digitCount < 7) {
|
|
8763
|
-
// return 'Not available';
|
|
8764
|
-
// }
|
|
8765
|
-
|
|
8766
|
-
// return cleaned.trim();
|
|
8767
|
-
// }
|
|
8768
|
-
|
|
8769
|
-
// function validateWebsite(website) {
|
|
8770
|
-
// if (!website || website.toLowerCase() === 'not available' || website.trim() === '') {
|
|
8771
|
-
// return 'Not available';
|
|
8772
|
-
// }
|
|
8773
|
-
|
|
8774
|
-
// const trimmed = website.trim();
|
|
8775
|
-
|
|
8776
|
-
// // Ensure URL has proper protocol
|
|
8777
|
-
// if (!trimmed.startsWith('http://') && !trimmed.startsWith('https://')) {
|
|
8778
|
-
// // Check if it looks like a domain
|
|
8779
|
-
// if (trimmed.includes('.') && !trimmed.includes(' ')) {
|
|
8780
|
-
// return `https://${trimmed.replace(/^www\./, '')}`;
|
|
8781
|
-
// }
|
|
8782
|
-
// return 'Not available';
|
|
8783
|
-
// }
|
|
8784
|
-
|
|
8785
|
-
// return trimmed;
|
|
8786
|
-
// }
|
|
8787
|
-
|
|
8788
|
-
// function cleanStreetAddress(street) {
|
|
8789
|
-
// if (!street || street.toLowerCase() === 'not available' || street.trim() === '') {
|
|
8790
|
-
// return 'Not available';
|
|
8791
|
-
// }
|
|
8792
|
-
|
|
8793
|
-
// return street
|
|
8794
|
-
// .replace(/\s+/g, ' ')
|
|
8795
|
-
// .replace(/,\s*$/g, '') // Remove trailing commas
|
|
8796
|
-
// .trim();
|
|
8797
|
-
// }
|
|
8798
|
-
|
|
8799
|
-
// function cleanText(text) {
|
|
8800
|
-
// if (!text || text.toLowerCase() === 'not available' || text.trim() === '') {
|
|
8801
|
-
// return 'Not available';
|
|
8802
|
-
// }
|
|
8803
|
-
|
|
8804
|
-
// return text.replace(/\s+/g, ' ').trim();
|
|
8805
|
-
// }
|
|
8806
|
-
|
|
8807
|
-
// function cleanZipCode(zip, country) {
|
|
8808
|
-
// if (!zip || zip.toLowerCase() === 'not available' || zip.trim() === '') {
|
|
8809
|
-
// return 'Not available';
|
|
8810
|
-
// }
|
|
8811
|
-
|
|
8812
|
-
// const cleaned = zip.trim();
|
|
8813
|
-
|
|
8814
|
-
// // Country-specific formatting
|
|
8815
|
-
// switch (country) {
|
|
8816
|
-
// case 'US':
|
|
8817
|
-
// // US ZIP: 5 digits or 5-4 format
|
|
8818
|
-
// return cleaned.replace(/\D/g, '').replace(/^(\d{5})(\d{4})$/, '$1-$2');
|
|
8819
|
-
// case 'CA':
|
|
8820
|
-
// // Canada: A1A 1A1 format
|
|
8821
|
-
// return cleaned.toUpperCase().replace(/\s+/g, '');
|
|
8822
|
-
// case 'UK':
|
|
8823
|
-
// // UK: various formats, preserve as is but uppercase
|
|
8824
|
-
// return cleaned.toUpperCase();
|
|
8825
|
-
// case 'AU':
|
|
8826
|
-
// // Australia: 4 digits
|
|
8827
|
-
// return cleaned.replace(/\D/g, '');
|
|
8828
|
-
// default:
|
|
8829
|
-
// return cleaned;
|
|
8830
|
-
// }
|
|
8831
|
-
// }
|
|
8832
|
-
|
|
8833
|
-
// function cleanStateProvince(state, country) {
|
|
8834
|
-
// if (!state || state.toLowerCase() === 'not available' || state.trim() === '') {
|
|
8835
|
-
// return 'Not available';
|
|
8836
|
-
// }
|
|
8837
|
-
|
|
8838
|
-
// const cleaned = state.trim();
|
|
8839
|
-
|
|
8840
|
-
// // Standardize US state abbreviations
|
|
8841
|
-
// if (country === 'US') {
|
|
8842
|
-
// const stateMap = {
|
|
8843
|
-
// alabama: 'AL',
|
|
8844
|
-
// alaska: 'AK',
|
|
8845
|
-
// arizona: 'AZ',
|
|
8846
|
-
// arkansas: 'AR',
|
|
8847
|
-
// california: 'CA',
|
|
8848
|
-
// colorado: 'CO',
|
|
8849
|
-
// connecticut: 'CT',
|
|
8850
|
-
// delaware: 'DE',
|
|
8851
|
-
// florida: 'FL',
|
|
8852
|
-
// georgia: 'GA',
|
|
8853
|
-
// hawaii: 'HI',
|
|
8854
|
-
// idaho: 'ID',
|
|
8855
|
-
// illinois: 'IL',
|
|
8856
|
-
// indiana: 'IN',
|
|
8857
|
-
// iowa: 'IA',
|
|
8858
|
-
// kansas: 'KS',
|
|
8859
|
-
// kentucky: 'KY',
|
|
8860
|
-
// louisiana: 'LA',
|
|
8861
|
-
// maine: 'ME',
|
|
8862
|
-
// maryland: 'MD',
|
|
8863
|
-
// massachusetts: 'MA',
|
|
8864
|
-
// michigan: 'MI',
|
|
8865
|
-
// minnesota: 'MN',
|
|
8866
|
-
// mississippi: 'MS',
|
|
8867
|
-
// missouri: 'MO',
|
|
8868
|
-
// montana: 'MT',
|
|
8869
|
-
// nebraska: 'NE',
|
|
8870
|
-
// nevada: 'NV',
|
|
8871
|
-
// 'new hampshire': 'NH',
|
|
8872
|
-
// 'new jersey': 'NJ',
|
|
8873
|
-
// 'new mexico': 'NM',
|
|
8874
|
-
// 'new york': 'NY',
|
|
8875
|
-
// 'north carolina': 'NC',
|
|
8876
|
-
// 'north dakota': 'ND',
|
|
8877
|
-
// ohio: 'OH',
|
|
8878
|
-
// oklahoma: 'OK',
|
|
8879
|
-
// oregon: 'OR',
|
|
8880
|
-
// pennsylvania: 'PA',
|
|
8881
|
-
// 'rhode island': 'RI',
|
|
8882
|
-
// 'south carolina': 'SC',
|
|
8883
|
-
// 'south dakota': 'SD',
|
|
8884
|
-
// tennessee: 'TN',
|
|
8885
|
-
// texas: 'TX',
|
|
8886
|
-
// utah: 'UT',
|
|
8887
|
-
// vermont: 'VT',
|
|
8888
|
-
// virginia: 'VA',
|
|
8889
|
-
// washington: 'WA',
|
|
8890
|
-
// 'west virginia': 'WV',
|
|
8891
|
-
// wisconsin: 'WI',
|
|
8892
|
-
// wyoming: 'WY',
|
|
8893
|
-
// 'district of columbia': 'DC',
|
|
8894
|
-
// };
|
|
8895
|
-
|
|
8896
|
-
// const lowerState = cleaned.toLowerCase();
|
|
8897
|
-
// if (stateMap[lowerState]) {
|
|
8898
|
-
// return stateMap[lowerState];
|
|
8899
|
-
// }
|
|
8900
|
-
|
|
8901
|
-
// // If already 2-letter code, uppercase it
|
|
8902
|
-
// if (/^[A-Z]{2}$/i.test(cleaned)) {
|
|
8903
|
-
// return cleaned.toUpperCase();
|
|
8904
|
-
// }
|
|
8905
|
-
// }
|
|
8906
|
-
|
|
8907
|
-
// return cleaned;
|
|
8908
|
-
// }
|
|
8909
|
-
|
|
8910
|
-
// function cleanCountry(country) {
|
|
8911
|
-
// if (!country || country.toLowerCase() === 'not available' || country.trim() === '') {
|
|
8912
|
-
// return 'Not available';
|
|
8913
|
-
// }
|
|
8914
|
-
|
|
8915
|
-
// // Convert 2-letter codes to full country names for display
|
|
8916
|
-
// const countryMap = {
|
|
8917
|
-
// US: 'United States',
|
|
8918
|
-
// CA: 'Canada',
|
|
8919
|
-
// UK: 'United Kingdom',
|
|
8920
|
-
// GB: 'United Kingdom',
|
|
8921
|
-
// AU: 'Australia',
|
|
8922
|
-
// DE: 'Germany',
|
|
8923
|
-
// FR: 'France',
|
|
8924
|
-
// JP: 'Japan',
|
|
8925
|
-
// CN: 'China',
|
|
8926
|
-
// IN: 'India',
|
|
8927
|
-
// BR: 'Brazil',
|
|
8928
|
-
// MX: 'Mexico',
|
|
8929
|
-
// };
|
|
8930
|
-
|
|
8931
|
-
// const upperCountry = country.toUpperCase();
|
|
8932
|
-
// return countryMap[upperCountry] || upperCountry;
|
|
8933
|
-
// }
|
|
8934
|
-
|
|
8935
|
-
// function formatFullAddress(data) {
|
|
8936
|
-
// const parts = [];
|
|
8937
|
-
|
|
8938
|
-
// if (data.business_address_street && data.business_address_street !== 'Not available') {
|
|
8939
|
-
// parts.push(data.business_address_street);
|
|
8940
|
-
// }
|
|
8941
|
-
|
|
8942
|
-
// const cityStateZip = [];
|
|
8943
|
-
// if (data.business_address_city && data.business_address_city !== 'Not available') {
|
|
8944
|
-
// cityStateZip.push(data.business_address_city);
|
|
8945
|
-
// }
|
|
8946
|
-
|
|
8947
|
-
// if (data.business_address_state && data.business_address_state !== 'Not available') {
|
|
8948
|
-
// cityStateZip.push(data.business_address_state);
|
|
8949
|
-
// }
|
|
8950
|
-
|
|
8951
|
-
// if (data.business_address_zip && data.business_address_zip !== 'Not available') {
|
|
8952
|
-
// cityStateZip.push(data.business_address_zip);
|
|
8953
|
-
// }
|
|
8954
|
-
|
|
8955
|
-
// if (cityStateZip.length > 0) {
|
|
8956
|
-
// parts.push(cityStateZip.join(', '));
|
|
8957
|
-
// }
|
|
8958
|
-
|
|
8959
|
-
// if (data.business_address_country && data.business_address_country !== 'Not available') {
|
|
8960
|
-
// parts.push(data.business_address_country);
|
|
8961
|
-
// }
|
|
8962
|
-
|
|
8963
|
-
// return parts.length > 0 ? parts.join(', ') : 'Not available';
|
|
8964
|
-
// }
|
|
8965
|
-
|
|
8966
|
-
// function getRegionFromState(state, country) {
|
|
8967
|
-
// if (country !== 'US' || state === 'Not available') return null;
|
|
8968
|
-
|
|
8969
|
-
// const regions = {
|
|
8970
|
-
// Northeast: ['CT', 'ME', 'MA', 'NH', 'RI', 'VT', 'NJ', 'NY', 'PA'],
|
|
8971
|
-
// Midwest: ['IL', 'IN', 'MI', 'OH', 'WI', 'IA', 'KS', 'MN', 'MO', 'NE', 'ND', 'SD'],
|
|
8972
|
-
// South: ['DE', 'FL', 'GA', 'MD', 'NC', 'SC', 'VA', 'DC', 'WV', 'AL', 'KY', 'MS', 'TN', 'AR', 'LA', 'OK', 'TX'],
|
|
8973
|
-
// West: ['AZ', 'CO', 'ID', 'MT', 'NV', 'NM', 'UT', 'WY', 'AK', 'CA', 'HI', 'OR', 'WA'],
|
|
8974
|
-
// };
|
|
8975
|
-
|
|
8976
|
-
// for (const [region, states] of Object.entries(regions)) {
|
|
8977
|
-
// if (states.includes(state)) {
|
|
8978
|
-
// return region;
|
|
8979
|
-
// }
|
|
8980
|
-
// }
|
|
8981
|
-
|
|
8982
|
-
// return null;
|
|
8983
|
-
// }
|
|
8984
|
-
|
|
8985
|
-
// function getDefaultBusinessInfo(name, email, error = null) {
|
|
8986
|
-
// const domain = email.includes('@') ? email.split('@')[1] : '';
|
|
8987
|
-
|
|
8988
|
-
// return {
|
|
8989
|
-
// business_name: name,
|
|
8990
|
-
// business_domain: domain,
|
|
8991
|
-
// business_bio: 'Information not available',
|
|
8992
|
-
// business_size: 'unknown',
|
|
8993
|
-
// business_category: 'Professional Services',
|
|
8994
|
-
// business_sub_category: 'Business Services',
|
|
8995
|
-
// business_country: 'US',
|
|
8996
|
-
// business_phone: 'Not available',
|
|
8997
|
-
// business_website: 'Not available',
|
|
8998
|
-
|
|
8999
|
-
// // Address components
|
|
9000
|
-
// business_address_street: 'Not available',
|
|
9001
|
-
// business_address_city: 'Not available',
|
|
9002
|
-
// business_address_state: 'Not available',
|
|
9003
|
-
// business_address_zip: 'Not available',
|
|
9004
|
-
// business_address_country: 'Not available',
|
|
9005
|
-
// business_address_full: 'Not available',
|
|
9006
|
-
|
|
9007
|
-
// // Structured objects
|
|
9008
|
-
// business_category_id: null,
|
|
9009
|
-
// business_address: {
|
|
9010
|
-
// street: 'Not available',
|
|
9011
|
-
// city: 'Not available',
|
|
9012
|
-
// state: 'Not available',
|
|
9013
|
-
// zip: 'Not available',
|
|
9014
|
-
// country: 'Not available',
|
|
9015
|
-
// full: 'Not available',
|
|
9016
|
-
// coordinates: null,
|
|
9017
|
-
// timezone: null,
|
|
9018
|
-
// },
|
|
9019
|
-
// business_location: {
|
|
9020
|
-
// region: null,
|
|
9021
|
-
// metro_area: null,
|
|
9022
|
-
// is_headquarters: null,
|
|
9023
|
-
// },
|
|
9024
|
-
// error: error || 'API call failed',
|
|
9025
|
-
// };
|
|
9026
|
-
// }
|
|
9027
|
-
|
|
9028
|
-
// // Extract lists from your JSON categories array
|
|
9029
|
-
// const categories = [
|
|
9030
|
-
// {
|
|
9031
|
-
// id: 'ind_technology',
|
|
9032
|
-
// name: 'Technology',
|
|
9033
|
-
// sub: ['Software Development', 'AI & Machine Learning', 'Cybersecurity', 'Cloud Computing', 'IT Services', 'SaaS & Platforms', 'Hardware & Electronics'],
|
|
9034
|
-
// },
|
|
9035
|
-
// {
|
|
9036
|
-
// id: 'ind_marketing',
|
|
9037
|
-
// name: 'Marketing & Advertising',
|
|
9038
|
-
// sub: ['Digital Marketing', 'PPC & SEO', 'Content Creation', 'Branding', 'Social Media Management', 'Email Marketing', 'Market Research'],
|
|
9039
|
-
// },
|
|
9040
|
-
// {
|
|
9041
|
-
// id: 'ind_sales',
|
|
9042
|
-
// name: 'Sales',
|
|
9043
|
-
// sub: ['B2B Sales', 'B2C Sales', 'Real Estate Sales', 'Account Management', 'Lead Generation', 'Inside Sales', 'Field Sales'],
|
|
9044
|
-
// },
|
|
9045
|
-
// {
|
|
9046
|
-
// id: 'ind_finance',
|
|
9047
|
-
// name: 'Finance & Accounting',
|
|
9048
|
-
// sub: ['Banking', 'Investment', 'Financial Planning', 'Accounting', 'Bookkeeping', 'Insurance', 'FinTech'],
|
|
9049
|
-
// },
|
|
9050
|
-
// {
|
|
9051
|
-
// id: 'ind_healthcare',
|
|
9052
|
-
// name: 'Healthcare',
|
|
9053
|
-
// sub: ['Medical Clinics', 'Hospitals', 'Pharma', 'Mental Health', 'Healthcare IT', 'Home Care', 'Medical Research'],
|
|
9054
|
-
// },
|
|
9055
|
-
// {
|
|
9056
|
-
// id: 'ind_realestate',
|
|
9057
|
-
// name: 'Real Estate',
|
|
9058
|
-
// sub: ['Residential Real Estate', 'Commercial Real Estate', 'Property Management', 'Investment & BRRRR', 'Construction', 'Architecture', 'Interior Design'],
|
|
9059
|
-
// },
|
|
9060
|
-
// {
|
|
9061
|
-
// id: 'ind_ecommerce',
|
|
9062
|
-
// name: 'E-commerce',
|
|
9063
|
-
// sub: ['Online Store', 'Dropshipping', 'Amazon FBA', 'Marketplace Selling', 'Retail', 'Inventory Management', 'Fulfillment & Logistics'],
|
|
9064
|
-
// },
|
|
9065
|
-
// {
|
|
9066
|
-
// id: 'ind_education',
|
|
9067
|
-
// name: 'Education',
|
|
9068
|
-
// sub: ['Schools', 'Universities', 'Private Tutoring', 'Online Courses', 'EdTech', 'Training & Development'],
|
|
9069
|
-
// },
|
|
9070
|
-
// {
|
|
9071
|
-
// id: 'ind_hospitality',
|
|
9072
|
-
// name: 'Hospitality & Travel',
|
|
9073
|
-
// sub: ['Hotels', 'Restaurants', 'Cafes & Bars', 'Travel Agencies', 'Tourism', 'Events & Catering', 'Transportation'],
|
|
9074
|
-
// },
|
|
9075
|
-
// {
|
|
9076
|
-
// id: 'ind_professional',
|
|
9077
|
-
// name: 'Professional Services',
|
|
9078
|
-
// sub: ['Legal', 'Consulting', 'HR & Recruiting', 'Accounting Firms', 'Business Services', 'Management Consulting'],
|
|
9079
|
-
// },
|
|
9080
|
-
// {
|
|
9081
|
-
// id: 'ind_manufacturing',
|
|
9082
|
-
// name: 'Manufacturing',
|
|
9083
|
-
// sub: ['Automotive', 'Industrial', 'Textile', 'Electronics', 'Food Production', 'Machinery', 'Chemicals'],
|
|
9084
|
-
// },
|
|
9085
|
-
// {
|
|
9086
|
-
// id: 'ind_nonprofit',
|
|
9087
|
-
// name: 'Nonprofit & Government',
|
|
9088
|
-
// sub: ['NGOs', 'Municipality', 'Government Services', 'Public Health', 'Community Organizations', 'Education Programs'],
|
|
9089
|
-
// },
|
|
9090
|
-
// {
|
|
9091
|
-
// id: 'ind_media',
|
|
9092
|
-
// name: 'Media & Entertainment',
|
|
9093
|
-
// sub: ['Film & Video', 'Music', 'Publishing', 'Gaming', 'News & Journalism', 'Influencers', 'Production Studios'],
|
|
9094
|
-
// },
|
|
9095
|
-
// {
|
|
9096
|
-
// id: 'ind_logistics',
|
|
9097
|
-
// name: 'Logistics & Transportation',
|
|
9098
|
-
// sub: ['Shipping', 'Trucking', 'Last-Mile Delivery', 'Warehousing', 'Freight Forwarding', 'Route Optimization'],
|
|
9099
|
-
// },
|
|
9100
|
-
// {
|
|
9101
|
-
// id: 'ind_energy',
|
|
9102
|
-
// name: 'Energy & Utilities',
|
|
9103
|
-
// sub: ['Solar', 'Oil & Gas', 'Electricity Providers', 'Water Utilities', 'Environmental Services', 'Renewable Energy'],
|
|
9104
|
-
// },
|
|
9105
|
-
// {
|
|
9106
|
-
// id: 'ind_construction',
|
|
9107
|
-
// name: 'Construction & Trades',
|
|
9108
|
-
// sub: ['General Contracting', 'Roofing', 'Plumbing', 'HVAC', 'Electrical', 'Renovation', 'Engineering'],
|
|
9109
|
-
// },
|
|
9110
|
-
// {
|
|
9111
|
-
// id: 'ind_food',
|
|
9112
|
-
// name: 'Food & Beverage',
|
|
9113
|
-
// sub: ['Restaurants', 'Catering', 'Food Manufacturing', 'Bakeries', 'Bars & Nightlife', 'Food Delivery'],
|
|
9114
|
-
// },
|
|
9115
|
-
// {
|
|
9116
|
-
// id: 'ind_retail',
|
|
9117
|
-
// name: 'Retail',
|
|
9118
|
-
// sub: ['Physical Stores', 'Boutiques', 'Supermarkets', 'Consumer Goods', 'Fashion Retail', 'Home Goods'],
|
|
9119
|
-
// },
|
|
9120
|
-
// ];
|
|
9121
|
-
// const categoryNames = categories.map((c) => c.name);
|
|
9122
|
-
// const allSubCategories = categories.flatMap((c) => c.sub);
|
|
9123
|
-
|
|
9124
|
-
// const business_info_ret = await submit_chat_gpt_prompt({
|
|
9125
|
-
// uid,
|
|
9126
|
-
// prompt: `Research the company: "${name}" (${email}).
|
|
9127
|
-
|
|
9128
|
-
// REQUIRED INFORMATION:
|
|
9129
|
-
// 1. Company name (official name)
|
|
9130
|
-
// 2. Email domain name
|
|
9131
|
-
// 3. Professional one-sentence biography
|
|
9132
|
-
// 4. Industry category and sub-category
|
|
9133
|
-
// 5. Primary country (2-letter ISO code)
|
|
9134
|
-
// 6. Telephone number
|
|
9135
|
-
// 7. Website URL
|
|
9136
|
-
// 8. COMPLETE ADDRESS DETAILS:
|
|
9137
|
-
// - Full street address (street number, street name, suite/apt if applicable)
|
|
9138
|
-
// - City
|
|
9139
|
-
// - State/Province (use abbreviation where standard)
|
|
9140
|
-
// - Zip/Postal code
|
|
9141
|
-
// - Country
|
|
9142
|
-
|
|
9143
|
-
// ADDRESS FORMATTING EXAMPLES:
|
|
9144
|
-
// - Full street: "1600 Amphitheatre Parkway"
|
|
9145
|
-
// - City: "Mountain View"
|
|
9146
|
-
// - State: "CA"
|
|
9147
|
-
// - Zip: "94043"
|
|
9148
|
-
// - Country: "US"
|
|
9149
|
-
// - Full address: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA"
|
|
9150
|
-
|
|
9151
|
-
// INSTRUCTIONS:
|
|
9152
|
-
// - Use web search to find accurate information
|
|
9153
|
-
// - If not found online, infer from typical patterns
|
|
9154
|
-
// - For unknown info, use "Not available"
|
|
9155
|
-
// - For US states, use 2-letter abbreviations (CA, NY, TX, etc.)
|
|
9156
|
-
// - For other countries, use standard regional names
|
|
9157
|
-
|
|
9158
|
-
// Be as precise and accurate as possible.`,
|
|
9159
|
-
// model: 'gpt-5-nano',
|
|
9160
|
-
// response_format: z.object({
|
|
9161
|
-
// business_name: z.string().describe('Official company name'),
|
|
9162
|
-
// business_domain: z.string().describe('Domain name from email'),
|
|
9163
|
-
// business_bio: z.string().describe('One-sentence professional summary'),
|
|
9164
|
-
// business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
|
|
9165
|
-
// business_category: z.enum(categoryNames),
|
|
9166
|
-
// business_sub_category: z.enum(allSubCategories),
|
|
9167
|
-
// business_country: z.string().length(2).describe('2-letter ISO country code'),
|
|
9168
|
-
// business_phone: z.string().describe("Telephone number or 'Not available'"),
|
|
9169
|
-
// business_website: z.string().describe("Website URL or 'Not available'"),
|
|
9170
|
-
|
|
9171
|
-
// // Complete address components
|
|
9172
|
-
// business_address_street: z.string().describe('Full street address (number, street, suite)'),
|
|
9173
|
-
// business_address_city: z.string().describe('City name'),
|
|
9174
|
-
// business_address_state: z.string().describe('State/Province (abbreviation if standard)'),
|
|
9175
|
-
// business_address_zip: z.string().describe('Zip/Postal code'),
|
|
9176
|
-
// business_address_country: z.string().describe('Country name'),
|
|
9177
|
-
// business_address_full: z.string().describe('Complete formatted address'),
|
|
9178
|
-
// }),
|
|
9179
|
-
// metadata: {
|
|
9180
|
-
// func: 'get_business_info',
|
|
9181
|
-
// company_name: name,
|
|
9182
|
-
// company_email: email,
|
|
9183
|
-
// },
|
|
9184
|
-
// account_profile_info,
|
|
9185
|
-
// tools: [{ type: 'web_search_preview' }],
|
|
9186
|
-
// });
|
|
9187
|
-
|
|
9188
|
-
// try {
|
|
9189
|
-
// if (business_info_ret.code > -1) {
|
|
9190
|
-
// const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
|
|
9191
|
-
|
|
9192
|
-
// // Standardize country codes to uppercase
|
|
9193
|
-
// if (data.business_country) data.business_country = data.business_country.toUpperCase();
|
|
9194
|
-
// if (data.business_address_country) {
|
|
9195
|
-
// data.business_address_country = data.business_address_country.toUpperCase();
|
|
9196
|
-
// }
|
|
9197
|
-
|
|
9198
|
-
// // Logic to attach the ID for your database
|
|
9199
|
-
// const matched = categories.find((c) => c.name === data.business_category);
|
|
9200
|
-
// data.business_category_id = matched ? matched.id : null;
|
|
9201
|
-
|
|
9202
|
-
// // Validate and clean all contact information
|
|
9203
|
-
// data.business_phone = validatePhoneNumber(data.business_phone);
|
|
9204
|
-
// data.business_website = validateWebsite(data.business_website);
|
|
9205
|
-
|
|
9206
|
-
// // Clean and standardize all address components
|
|
9207
|
-
// data.business_address_street = cleanStreetAddress(data.business_address_street);
|
|
9208
|
-
// data.business_address_city = cleanText(data.business_address_city);
|
|
9209
|
-
// data.business_address_zip = cleanZipCode(data.business_address_zip, data.business_country);
|
|
9210
|
-
// data.business_address_state = cleanStateProvince(data.business_address_state, data.business_country);
|
|
9211
|
-
// data.business_address_country = cleanCountry(data.business_address_country || data.business_country);
|
|
9212
|
-
// data.business_address_full = formatFullAddress(data);
|
|
9213
|
-
|
|
9214
|
-
// // Create a comprehensive structured address object
|
|
9215
|
-
// data.business_address = {
|
|
9216
|
-
// street: data.business_address_street,
|
|
9217
|
-
// city: data.business_address_city,
|
|
9218
|
-
// state: data.business_address_state,
|
|
9219
|
-
// zip: data.business_address_zip,
|
|
9220
|
-
// country: data.business_address_country,
|
|
9221
|
-
// full: data.business_address_full,
|
|
9222
|
-
// coordinates: null, // Can be populated later with geocoding
|
|
9223
|
-
// timezone: null, // Can be populated later
|
|
9224
|
-
// };
|
|
9225
|
-
|
|
9226
|
-
// // Generate additional useful fields
|
|
9227
|
-
// data.business_location = {
|
|
9228
|
-
// region: getRegionFromState(data.business_address_state, data.business_country),
|
|
9229
|
-
// metro_area: null, // Can be populated later
|
|
9230
|
-
// is_headquarters: null, // Can be determined from address pattern
|
|
9231
|
-
// };
|
|
9232
|
-
|
|
9233
|
-
// return data;
|
|
9234
|
-
// } else {
|
|
9235
|
-
// console.error('Business info API call failed:', business_info_ret);
|
|
9236
|
-
// return getDefaultBusinessInfo(name, email);
|
|
9237
|
-
// }
|
|
9238
|
-
// } catch (error) {
|
|
9239
|
-
// console.error('Error in get_business_info:', error);
|
|
9240
|
-
// return getDefaultBusinessInfo(name, email, error.message);
|
|
9241
|
-
// }
|
|
9242
|
-
// };
|
|
9243
|
-
|
|
9244
|
-
// export const get_person_info = async function (uid, name, email, account_profile_info, email_context = '') {
|
|
9245
|
-
// // ========== HELPER FUNCTIONS ==========
|
|
9246
|
-
|
|
9247
|
-
// async function hashString(str) {
|
|
9248
|
-
// // Simple hash for context tracking
|
|
9249
|
-
// const encoder = new TextEncoder();
|
|
9250
|
-
// const data = encoder.encode(str);
|
|
9251
|
-
// const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
9252
|
-
// const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
9253
|
-
// return hashArray
|
|
9254
|
-
// .map((b) => b.toString(16).padStart(2, '0'))
|
|
9255
|
-
// .join('')
|
|
9256
|
-
// .substring(0, 16);
|
|
9257
|
-
// }
|
|
9258
|
-
|
|
9259
|
-
// function processPersonInfo(data, originalName, originalEmail, emailContext) {
|
|
9260
|
-
// // Ensure basic fields are populated
|
|
9261
|
-
// if (!data.person_first_name || !data.person_last_name) {
|
|
9262
|
-
// const nameParts = originalName.trim().split(/\s+/);
|
|
9263
|
-
// data.person_first_name = data.person_first_name || nameParts[0] || '';
|
|
9264
|
-
// data.person_last_name = data.person_last_name || nameParts.slice(1).join(' ') || '';
|
|
9265
|
-
// }
|
|
9266
|
-
|
|
9267
|
-
// // Set full name if not provided
|
|
9268
|
-
// if (!data.person_full_name) {
|
|
9269
|
-
// data.person_full_name = `${data.person_first_name} ${data.person_last_name}`.trim();
|
|
9270
|
-
// }
|
|
9271
|
-
|
|
9272
|
-
// // Ensure email is set
|
|
9273
|
-
// data.person_email = data.person_email || originalEmail;
|
|
9274
|
-
|
|
9275
|
-
// // Process demographic information
|
|
9276
|
-
// data.person_age = processAge(data.person_age);
|
|
9277
|
-
// data.person_gender = data.person_gender || 'unknown';
|
|
9278
|
-
// data.person_nationality = processNationality(data.person_nationality);
|
|
9279
|
-
|
|
9280
|
-
// // Standardize location fields
|
|
9281
|
-
// data.person_location_city = cleanText(data.person_location_city);
|
|
9282
|
-
// data.person_location_state = cleanStateProvince(data.person_location_state);
|
|
9283
|
-
// data.person_location_country = processCountryCode(data.person_location_country);
|
|
9284
|
-
|
|
9285
|
-
// // Format full location
|
|
9286
|
-
// if (!data.person_location_full || data.person_location_full === 'Not available') {
|
|
9287
|
-
// const locationParts = [];
|
|
9288
|
-
// if (data.person_location_city && data.person_location_city !== 'Not available') {
|
|
9289
|
-
// locationParts.push(data.person_location_city);
|
|
9290
|
-
// }
|
|
9291
|
-
// if (data.person_location_state && data.person_location_state !== 'Not available') {
|
|
9292
|
-
// locationParts.push(data.person_location_state);
|
|
9293
|
-
// }
|
|
9294
|
-
// if (data.person_location_country && data.person_location_country !== 'Not available') {
|
|
9295
|
-
// locationParts.push(countryCodeToName(data.person_location_country));
|
|
9296
|
-
// }
|
|
9297
|
-
// data.person_location_full = locationParts.length > 0 ? locationParts.join(', ') : 'Not available';
|
|
9298
|
-
// }
|
|
9299
|
-
|
|
9300
|
-
// // Clean and validate URLs
|
|
9301
|
-
// data.person_linkedin = validateURL(data.person_linkedin);
|
|
9302
|
-
// data.person_twitter = validateURL(data.person_twitter);
|
|
9303
|
-
// data.person_github = validateURL(data.person_github);
|
|
9304
|
-
// data.person_website = validateURL(data.person_website);
|
|
9305
|
-
|
|
9306
|
-
// // Clean phone number
|
|
9307
|
-
// data.person_phone = validatePhoneNumber(data.person_phone);
|
|
9308
|
-
|
|
9309
|
-
// // Ensure arrays are properly formatted
|
|
9310
|
-
// data.person_skills = ensureArray(data.person_skills);
|
|
9311
|
-
// data.person_expertise = ensureArray(data.person_expertise);
|
|
9312
|
-
// data.person_education = ensureArray(data.person_education);
|
|
9313
|
-
// data.person_languages = ensureArray(data.person_languages);
|
|
9314
|
-
// data.person_interests = ensureArray(data.person_interests);
|
|
9315
|
-
// data.person_context_insights = ensureArray(data.person_context_insights);
|
|
9316
|
-
|
|
9317
|
-
// // Calculate additional metadata
|
|
9318
|
-
// data.person_name_initials = getInitials(data.person_first_name, data.person_last_name);
|
|
9319
|
-
// data.person_age_range = calculateAgeRange(data.person_age);
|
|
9320
|
-
// data.person_seniority_score = calculateSeniorityScore(data);
|
|
9321
|
-
// data.person_pronouns = getPronounsFromGender(data.person_gender);
|
|
9322
|
-
|
|
9323
|
-
// // Extract insights from email context
|
|
9324
|
-
// if (emailContext && !data.person_context_insights) {
|
|
9325
|
-
// data.person_context_insights = extractContextInsights(emailContext);
|
|
9326
|
-
// }
|
|
9327
|
-
|
|
9328
|
-
// // Create structured objects for easier access
|
|
9329
|
-
// data.person_demographics = {
|
|
9330
|
-
// age: data.person_age,
|
|
9331
|
-
// age_range: data.person_age_range,
|
|
9332
|
-
// gender: data.person_gender,
|
|
9333
|
-
// pronouns: data.person_pronouns,
|
|
9334
|
-
// nationality: data.person_nationality,
|
|
9335
|
-
// nationality_name: countryCodeToName(data.person_nationality),
|
|
9336
|
-
// };
|
|
9337
|
-
|
|
9338
|
-
// data.person_contact = {
|
|
9339
|
-
// email: data.person_email,
|
|
9340
|
-
// phone: data.person_phone,
|
|
9341
|
-
// location: {
|
|
9342
|
-
// city: data.person_location_city,
|
|
9343
|
-
// state: data.person_location_state,
|
|
9344
|
-
// country: data.person_location_country,
|
|
9345
|
-
// country_name: countryCodeToName(data.person_location_country),
|
|
9346
|
-
// full: data.person_location_full,
|
|
9347
|
-
// },
|
|
9348
|
-
// };
|
|
9349
|
-
|
|
9350
|
-
// data.person_professional = {
|
|
9351
|
-
// title: data.person_title,
|
|
9352
|
-
// company: data.person_company,
|
|
9353
|
-
// industry: data.person_industry,
|
|
9354
|
-
// career_level: data.person_career_level,
|
|
9355
|
-
// years_experience: data.person_years_experience,
|
|
9356
|
-
// skills: data.person_skills,
|
|
9357
|
-
// expertise: data.person_expertise,
|
|
9358
|
-
// education: data.person_education,
|
|
9359
|
-
// };
|
|
9360
|
-
|
|
9361
|
-
// data.person_online = {
|
|
9362
|
-
// linkedin: data.person_linkedin,
|
|
9363
|
-
// twitter: data.person_twitter,
|
|
9364
|
-
// github: data.person_github,
|
|
9365
|
-
// website: data.person_website,
|
|
9366
|
-
// other: data.person_social_other || [],
|
|
9367
|
-
// };
|
|
9368
|
-
|
|
9369
|
-
// // Add context metadata
|
|
9370
|
-
// data.context_analysis = {
|
|
9371
|
-
// has_context: !!emailContext,
|
|
9372
|
-
// context_length: emailContext?.length || 0,
|
|
9373
|
-
// extracted_insights: data.person_context_insights || [],
|
|
9374
|
-
// context_useful: data.person_has_context_hints || false,
|
|
9375
|
-
// };
|
|
9376
|
-
|
|
9377
|
-
// // Add timestamp
|
|
9378
|
-
// data.retrieved_at = new Date().toISOString();
|
|
9379
|
-
|
|
9380
|
-
// return data;
|
|
9381
|
-
// }
|
|
9382
|
-
|
|
9383
|
-
// function processAge(ageInput) {
|
|
9384
|
-
// if (!ageInput || ageInput === 'unknown' || ageInput === 'Not available') {
|
|
9385
|
-
// return 'unknown';
|
|
9386
|
-
// }
|
|
9387
|
-
|
|
9388
|
-
// if (typeof ageInput === 'number') {
|
|
9389
|
-
// return Math.max(18, Math.min(100, ageInput));
|
|
9390
|
-
// }
|
|
9391
|
-
|
|
9392
|
-
// if (typeof ageInput === 'string') {
|
|
9393
|
-
// // Parse age ranges like "30-40", "35+", "mid-30s"
|
|
9394
|
-
// const rangeMatch = ageInput.match(/(\d+)-(\d+)/);
|
|
9395
|
-
// if (rangeMatch) {
|
|
9396
|
-
// const avg = Math.floor((parseInt(rangeMatch[1]) + parseInt(rangeMatch[2])) / 2);
|
|
9397
|
-
// return avg;
|
|
9398
|
-
// }
|
|
9399
|
-
|
|
9400
|
-
// const numberMatch = ageInput.match(/\d+/);
|
|
9401
|
-
// if (numberMatch) {
|
|
9402
|
-
// const age = parseInt(numberMatch[0]);
|
|
9403
|
-
// if (age >= 18 && age <= 100) return age;
|
|
9404
|
-
// }
|
|
9405
|
-
|
|
9406
|
-
// // Handle textual age descriptions
|
|
9407
|
-
// const text = ageInput.toLowerCase();
|
|
9408
|
-
// if (text.includes('twent') || text.includes('20')) return 25;
|
|
9409
|
-
// if (text.includes('thirt') || text.includes('30')) return 35;
|
|
9410
|
-
// if (text.includes('fort') || text.includes('40')) return 45;
|
|
9411
|
-
// if (text.includes('fift') || text.includes('50')) return 55;
|
|
9412
|
-
// if (text.includes('sixt') || text.includes('60')) return 65;
|
|
9413
|
-
// }
|
|
9414
|
-
|
|
9415
|
-
// return 'unknown';
|
|
9416
|
-
// }
|
|
9417
|
-
|
|
9418
|
-
// function calculateAgeRange(age) {
|
|
9419
|
-
// if (age === 'unknown' || typeof age !== 'number') return 'Unknown';
|
|
9420
|
-
|
|
9421
|
-
// if (age < 25) return '18-24';
|
|
9422
|
-
// if (age < 30) return '25-29';
|
|
9423
|
-
// if (age < 35) return '30-34';
|
|
9424
|
-
// if (age < 40) return '35-39';
|
|
9425
|
-
// if (age < 50) return '40-49';
|
|
9426
|
-
// if (age < 60) return '50-59';
|
|
9427
|
-
// return '60+';
|
|
9428
|
-
// }
|
|
9429
|
-
|
|
9430
|
-
// function processNationality(nationality) {
|
|
9431
|
-
// if (!nationality || nationality.toLowerCase() === 'unknown' || nationality.toLowerCase() === 'not available') {
|
|
9432
|
-
// return 'unknown';
|
|
9433
|
-
// }
|
|
9434
|
-
|
|
9435
|
-
// // Convert to uppercase for country codes
|
|
9436
|
-
// const upper = nationality.toUpperCase();
|
|
9437
|
-
|
|
9438
|
-
// // Map common variations to ISO codes
|
|
9439
|
-
// const countryMap = {
|
|
9440
|
-
// USA: 'US',
|
|
9441
|
-
// 'UNITED STATES': 'US',
|
|
9442
|
-
// AMERICA: 'US',
|
|
9443
|
-
// UK: 'GB',
|
|
9444
|
-
// 'UNITED KINGDOM': 'GB',
|
|
9445
|
-
// ENGLAND: 'GB',
|
|
9446
|
-
// SCOTLAND: 'GB',
|
|
9447
|
-
// CANADA: 'CA',
|
|
9448
|
-
// AUSTRALIA: 'AU',
|
|
9449
|
-
// INDIA: 'IN',
|
|
9450
|
-
// GERMANY: 'DE',
|
|
9451
|
-
// FRANCE: 'FR',
|
|
9452
|
-
// CHINA: 'CN',
|
|
9453
|
-
// JAPAN: 'JP',
|
|
9454
|
-
// BRAZIL: 'BR',
|
|
9455
|
-
// MEXICO: 'MX',
|
|
9456
|
-
// SPAIN: 'ES',
|
|
9457
|
-
// ITALY: 'IT',
|
|
9458
|
-
// NETHERLANDS: 'NL',
|
|
9459
|
-
// SWEDEN: 'SE',
|
|
9460
|
-
// SWITZERLAND: 'CH',
|
|
9461
|
-
// 'SOUTH KOREA': 'KR',
|
|
9462
|
-
// RUSSIA: 'RU',
|
|
9463
|
-
// };
|
|
9464
|
-
|
|
9465
|
-
// if (countryMap[upper]) {
|
|
9466
|
-
// return countryMap[upper];
|
|
9467
|
-
// }
|
|
9468
|
-
|
|
9469
|
-
// // If it's already a 2-letter code, return it
|
|
9470
|
-
// if (/^[A-Z]{2}$/.test(upper)) {
|
|
9471
|
-
// return upper;
|
|
9472
|
-
// }
|
|
9473
|
-
|
|
9474
|
-
// return 'unknown';
|
|
9475
|
-
// }
|
|
9476
|
-
|
|
9477
|
-
// function processCountryCode(country) {
|
|
9478
|
-
// if (!country || country.toLowerCase() === 'not available') {
|
|
9479
|
-
// return 'unknown';
|
|
9480
|
-
// }
|
|
9481
|
-
|
|
9482
|
-
// return processNationality(country);
|
|
9483
|
-
// }
|
|
9484
|
-
|
|
9485
|
-
// function countryCodeToName(code) {
|
|
9486
|
-
// if (!code || code === 'unknown') return 'Unknown';
|
|
9487
|
-
|
|
9488
|
-
// const countryNames = {
|
|
9489
|
-
// US: 'United States',
|
|
9490
|
-
// GB: 'United Kingdom',
|
|
9491
|
-
// CA: 'Canada',
|
|
9492
|
-
// AU: 'Australia',
|
|
9493
|
-
// DE: 'Germany',
|
|
9494
|
-
// FR: 'France',
|
|
9495
|
-
// JP: 'Japan',
|
|
9496
|
-
// CN: 'China',
|
|
9497
|
-
// IN: 'India',
|
|
9498
|
-
// BR: 'Brazil',
|
|
9499
|
-
// MX: 'Mexico',
|
|
9500
|
-
// ES: 'Spain',
|
|
9501
|
-
// IT: 'Italy',
|
|
9502
|
-
// NL: 'Netherlands',
|
|
9503
|
-
// SE: 'Sweden',
|
|
9504
|
-
// CH: 'Switzerland',
|
|
9505
|
-
// KR: 'South Korea',
|
|
9506
|
-
// RU: 'Russia',
|
|
9507
|
-
// };
|
|
9508
|
-
|
|
9509
|
-
// return countryNames[code] || code;
|
|
9510
|
-
// }
|
|
9511
|
-
|
|
9512
|
-
// function getPronounsFromGender(gender) {
|
|
9513
|
-
// switch (gender) {
|
|
9514
|
-
// case 'male':
|
|
9515
|
-
// return ['he/him', 'his'];
|
|
9516
|
-
// case 'female':
|
|
9517
|
-
// return ['she/her', 'hers'];
|
|
9518
|
-
// case 'non-binary':
|
|
9519
|
-
// return ['they/them', 'theirs'];
|
|
9520
|
-
// default:
|
|
9521
|
-
// return ['unknown'];
|
|
9522
|
-
// }
|
|
9523
|
-
// }
|
|
9524
|
-
|
|
9525
|
-
// function extractContextInsights(emailContext) {
|
|
9526
|
-
// if (!emailContext) return [];
|
|
9527
|
-
|
|
9528
|
-
// const insights = [];
|
|
9529
|
-
// const context = emailContext.toLowerCase();
|
|
9530
|
-
|
|
9531
|
-
// // Extract potential job role hints
|
|
9532
|
-
// const rolePatterns = {
|
|
9533
|
-
// manager: ['manage', 'supervise', 'team lead', 'department head'],
|
|
9534
|
-
// engineer: ['engineer', 'developer', 'programmer', 'software'],
|
|
9535
|
-
// sales: ['sales', 'account executive', 'business development'],
|
|
9536
|
-
// marketing: ['marketing', 'campaign', 'brand', 'social media'],
|
|
9537
|
-
// executive: ['ceo', 'cto', 'cfo', 'director', 'vp', 'vice president'],
|
|
9538
|
-
// };
|
|
9539
|
-
|
|
9540
|
-
// for (const [role, patterns] of Object.entries(rolePatterns)) {
|
|
9541
|
-
// if (patterns.some((pattern) => context.includes(pattern))) {
|
|
9542
|
-
// insights.push(`Possible ${role} role indicated in email`);
|
|
9543
|
-
// }
|
|
9544
|
-
// }
|
|
9545
|
-
|
|
9546
|
-
// // Extract company hints
|
|
9547
|
-
// const companyMatch = context.match(/(?:at|from|of)\s+([A-Z][A-Za-z0-9\s&]+)(?:\s|$)/);
|
|
9548
|
-
// if (companyMatch && companyMatch[1].length > 2) {
|
|
9549
|
-
// insights.push(`Mentioned company/organization: ${companyMatch[1].trim()}`);
|
|
9550
|
-
// }
|
|
9551
|
-
|
|
9552
|
-
// // Extract project/technology hints
|
|
9553
|
-
// const techMatch = context.match(/(?:using|with|built\s+in)\s+([A-Za-z0-9\s+#]+)(?:\s|$)/);
|
|
9554
|
-
// if (techMatch) {
|
|
9555
|
-
// insights.push(`Technology mentioned: ${techMatch[1].trim()}`);
|
|
9556
|
-
// }
|
|
9557
|
-
|
|
9558
|
-
// // Extract urgency/priority
|
|
9559
|
-
// if (context.includes('urgent') || context.includes('asap') || context.includes('immediately')) {
|
|
9560
|
-
// insights.push('Email suggests urgency or time sensitivity');
|
|
9561
|
-
// }
|
|
9562
|
-
|
|
9563
|
-
// // Extract tone
|
|
9564
|
-
// if (context.includes('thank you') || context.includes('appreciate') || context.includes('grateful')) {
|
|
9565
|
-
// insights.push('Email shows appreciative/grateful tone');
|
|
9566
|
-
// }
|
|
9567
|
-
|
|
9568
|
-
// return insights.slice(0, 5); // Limit to 5 insights
|
|
9569
|
-
// }
|
|
9570
|
-
|
|
9571
|
-
// // Existing helper functions (kept from previous version)
|
|
9572
|
-
// function validateURL(url) {
|
|
9573
|
-
// /* ... same as before ... */
|
|
9574
|
-
// }
|
|
9575
|
-
// function validatePhoneNumber(phone) {
|
|
9576
|
-
// /* ... same as before ... */
|
|
9577
|
-
// }
|
|
9578
|
-
// function cleanText(text) {
|
|
9579
|
-
// /* ... same as before ... */
|
|
9580
|
-
// }
|
|
9581
|
-
// function cleanStateProvince(state) {
|
|
9582
|
-
// /* ... same as before ... */
|
|
9583
|
-
// }
|
|
9584
|
-
// function ensureArray(value) {
|
|
9585
|
-
// /* ... same as before ... */
|
|
9586
|
-
// }
|
|
9587
|
-
// function getInitials(firstName, lastName) {
|
|
9588
|
-
// /* ... same as before ... */
|
|
9589
|
-
// }
|
|
9590
|
-
// function calculateSeniorityScore(data) {
|
|
9591
|
-
// /* ... same as before ... */
|
|
9592
|
-
// }
|
|
9593
|
-
|
|
9594
|
-
// function getDefaultPersonInfo(name, email, emailContext = '', error = null) {
|
|
9595
|
-
// const nameParts = name.trim().split(/\s+/);
|
|
9596
|
-
// const firstName = nameParts[0] || '';
|
|
9597
|
-
// const lastName = nameParts.slice(1).join(' ') || '';
|
|
9598
|
-
// const domain = email.includes('@') ? email.split('@')[1] : '';
|
|
9599
|
-
// const companyGuess = domain
|
|
9600
|
-
// .replace(/\..*$/, '')
|
|
9601
|
-
// .replace(/[^a-z]/gi, ' ')
|
|
9602
|
-
// .replace(/\b\w/g, (l) => l.toUpperCase());
|
|
9603
|
-
|
|
9604
|
-
// // Extract basic insights from email context
|
|
9605
|
-
// const contextInsights = emailContext ? extractContextInsights(emailContext) : [];
|
|
9606
|
-
|
|
9607
|
-
// return {
|
|
9608
|
-
// // Basic Information
|
|
9609
|
-
// person_full_name: name,
|
|
9610
|
-
// person_first_name: firstName,
|
|
9611
|
-
// person_last_name: lastName,
|
|
9612
|
-
// person_middle_name: '',
|
|
9613
|
-
// person_preferred_name: '',
|
|
9614
|
-
|
|
9615
|
-
// // Demographic Information
|
|
9616
|
-
// person_age: 'unknown',
|
|
9617
|
-
// person_gender: 'unknown',
|
|
9618
|
-
// person_nationality: 'unknown',
|
|
9619
|
-
// person_age_range: 'Unknown',
|
|
9620
|
-
// person_pronouns: ['unknown'],
|
|
9621
|
-
|
|
9622
|
-
// // Professional Information
|
|
9623
|
-
// person_title: 'Professional',
|
|
9624
|
-
// person_company: companyGuess || 'Unknown',
|
|
9625
|
-
// person_industry: 'Technology',
|
|
9626
|
-
// person_bio: 'Information not available',
|
|
9627
|
-
|
|
9628
|
-
// // Location
|
|
9629
|
-
// person_location_city: 'Not available',
|
|
9630
|
-
// person_location_state: 'Not available',
|
|
9631
|
-
// person_location_country: 'unknown',
|
|
9632
|
-
// person_location_full: 'Not available',
|
|
9633
|
-
|
|
9634
|
-
// // Contact Information
|
|
9635
|
-
// person_phone: 'Not available',
|
|
9636
|
-
// person_email: email,
|
|
9637
|
-
// person_email_alternate: '',
|
|
9638
|
-
|
|
9639
|
-
// // Education
|
|
9640
|
-
// person_education: [],
|
|
9641
|
-
// person_education_highest: 'Not available',
|
|
9642
|
-
|
|
9643
|
-
// // Professional Details
|
|
9644
|
-
// person_skills: [],
|
|
9645
|
-
// person_expertise: [],
|
|
9646
|
-
// person_career_level: 'unknown',
|
|
9647
|
-
// person_years_experience: 0,
|
|
9648
|
-
|
|
9649
|
-
// // Social & Online Presence
|
|
9650
|
-
// person_linkedin: 'Not available',
|
|
9651
|
-
// person_twitter: 'Not available',
|
|
9652
|
-
// person_github: 'Not available',
|
|
9653
|
-
// person_website: 'Not available',
|
|
9654
|
-
// person_social_other: [],
|
|
9655
|
-
|
|
9656
|
-
// // Additional Information
|
|
9657
|
-
// person_languages: ['English'],
|
|
9658
|
-
// person_interests: [],
|
|
9659
|
-
// person_achievements: [],
|
|
9660
|
-
// person_current_projects: [],
|
|
9661
|
-
// person_context_insights: contextInsights,
|
|
9662
|
-
|
|
9663
|
-
// // Metadata
|
|
9664
|
-
// person_available_for_opportunities: false,
|
|
9665
|
-
// person_last_updated: new Date().toISOString(),
|
|
9666
|
-
// person_source_confidence: 0,
|
|
9667
|
-
// person_has_context_hints: contextInsights.length > 0,
|
|
9668
|
-
|
|
9669
|
-
// // Processed fields
|
|
9670
|
-
// person_name_initials: getInitials(firstName, lastName),
|
|
9671
|
-
// person_seniority_score: 0,
|
|
9672
|
-
|
|
9673
|
-
// // Structured objects
|
|
9674
|
-
// person_demographics: {
|
|
9675
|
-
// age: 'unknown',
|
|
9676
|
-
// age_range: 'Unknown',
|
|
9677
|
-
// gender: 'unknown',
|
|
9678
|
-
// pronouns: ['unknown'],
|
|
9679
|
-
// nationality: 'unknown',
|
|
9680
|
-
// nationality_name: 'Unknown',
|
|
9681
|
-
// },
|
|
9682
|
-
|
|
9683
|
-
// person_contact: {
|
|
9684
|
-
// email: email,
|
|
9685
|
-
// phone: 'Not available',
|
|
9686
|
-
// location: {
|
|
9687
|
-
// city: 'Not available',
|
|
9688
|
-
// state: 'Not available',
|
|
9689
|
-
// country: 'unknown',
|
|
9690
|
-
// country_name: 'Unknown',
|
|
9691
|
-
// full: 'Not available',
|
|
9692
|
-
// },
|
|
9693
|
-
// },
|
|
9694
|
-
|
|
9695
|
-
// person_professional: {
|
|
9696
|
-
// title: 'Professional',
|
|
9697
|
-
// company: companyGuess || 'Unknown',
|
|
9698
|
-
// industry: 'Technology',
|
|
9699
|
-
// career_level: 'unknown',
|
|
9700
|
-
// years_experience: 0,
|
|
9701
|
-
// skills: [],
|
|
9702
|
-
// expertise: [],
|
|
9703
|
-
// education: [],
|
|
9704
|
-
// },
|
|
9705
|
-
|
|
9706
|
-
// person_online: {
|
|
9707
|
-
// linkedin: 'Not available',
|
|
9708
|
-
// twitter: 'Not available',
|
|
9709
|
-
// github: 'Not available',
|
|
9710
|
-
// website: 'Not available',
|
|
9711
|
-
// other: [],
|
|
9712
|
-
// },
|
|
9713
|
-
|
|
9714
|
-
// context_analysis: {
|
|
9715
|
-
// has_context: !!emailContext,
|
|
9716
|
-
// context_length: emailContext?.length || 0,
|
|
9717
|
-
// extracted_insights: contextInsights,
|
|
9718
|
-
// context_useful: contextInsights.length > 0,
|
|
9719
|
-
// },
|
|
9720
|
-
|
|
9721
|
-
// retrieved_at: new Date().toISOString(),
|
|
9722
|
-
// error: error || 'API call failed',
|
|
9723
|
-
// };
|
|
9724
|
-
// }
|
|
9725
|
-
|
|
9726
|
-
// // Build context-aware prompt
|
|
9727
|
-
// let context_prompt = `Research the person: "${name}" (${email}).`;
|
|
9728
|
-
|
|
9729
|
-
// if (email_context) {
|
|
9730
|
-
// context_prompt += `\n\nEMAIL CONTEXT PROVIDED:\n"${email_context.substring(0, 500)}${email_context.length > 500 ? '...' : ''}"`;
|
|
9731
|
-
// }
|
|
9732
|
-
|
|
9733
|
-
// context_prompt += `
|
|
9734
|
-
|
|
9735
|
-
// REQUIRED PERSON INFORMATION:
|
|
9736
|
-
// 1. Full name (first, middle, last)
|
|
9737
|
-
// 2. Professional title/role
|
|
9738
|
-
// 3. Company/organization they work for
|
|
9739
|
-
// 4. Industry/field they work in
|
|
9740
|
-
// 5. Location (city, state, country)
|
|
9741
|
-
// 6. Professional biography (1-2 sentences)
|
|
9742
|
-
// 7. Education background
|
|
9743
|
-
// 8. Professional skills/expertise
|
|
9744
|
-
// 9. Social media profiles (LinkedIn, Twitter, GitHub, etc.)
|
|
9745
|
-
// 10. Personal website or portfolio
|
|
9746
|
-
|
|
9747
|
-
// DEMOGRAPHIC INFORMATION:
|
|
9748
|
-
// 11. Estimated age (based on career, education, and public information)
|
|
9749
|
-
// 12. Gender (based on name, pronouns in content, or public profiles)
|
|
9750
|
-
// 13. Nationality/country of origin (if discernible) (based on name, pronouns in content, or public profiles)
|
|
9751
|
-
|
|
9752
|
-
// CONTACT INFORMATION:
|
|
9753
|
-
// 14. Phone number (if available)
|
|
9754
|
-
// 15. Alternate email addresses (if available)
|
|
9755
|
-
// 16. Physical address (if available and appropriate)
|
|
9756
|
-
|
|
9757
|
-
// ADDITIONAL INSIGHTS:
|
|
9758
|
-
// 17. Career level (entry, mid, senior, executive, etc.)
|
|
9759
|
-
// 18. Years of experience
|
|
9760
|
-
// 19. Notable achievements/awards
|
|
9761
|
-
// 20. Languages spoken
|
|
9762
|
-
// 21. Professional interests
|
|
9763
|
-
// 22. Current projects
|
|
9764
|
-
// 23. Availability for opportunities
|
|
9765
|
-
|
|
9766
|
-
// INSTRUCTIONS:
|
|
9767
|
-
// - Use web search to find accurate, public information
|
|
9768
|
-
// - Use email context provided to infer additional details
|
|
9769
|
-
// - Respect privacy - only include publicly available information
|
|
9770
|
-
// - For age: provide numeric estimate or range (e.g., 35, 30-40, unknown)
|
|
9771
|
-
// - For gender: use male/female/non-binary/unknown based on available cues
|
|
9772
|
-
// - For country: use 2-letter ISO code (e.g., US, IN, UK)
|
|
9773
|
-
// - If information is not available, use "Not available" or appropriate defaults
|
|
9774
|
-
// - For location, use standard formats (e.g., "San Francisco, CA, USA")
|
|
9775
|
-
// - For social media, provide full URLs when available
|
|
9776
|
-
// - Focus on professional information suitable for business networking
|
|
9777
|
-
|
|
9778
|
-
// Be thorough but respectful of privacy boundaries.`;
|
|
9779
|
-
|
|
9780
|
-
// const person_info_ret = await submit_chat_gpt_prompt({
|
|
9781
|
-
// uid,
|
|
9782
|
-
// prompt: context_prompt,
|
|
9783
|
-
// model: 'gpt-5-nano',
|
|
9784
|
-
// response_format: z.object({
|
|
9785
|
-
// // Basic Information
|
|
9786
|
-
// person_full_name: z.string().describe("Person's full name"),
|
|
9787
|
-
// person_first_name: z.string().describe('First name'),
|
|
9788
|
-
// person_last_name: z.string().describe('Last name'),
|
|
9789
|
-
// person_middle_name: z.string().optional().nullable().describe('Middle name if available'),
|
|
9790
|
-
// person_preferred_name: z.string().optional().nullable().describe('Preferred/nickname if different'),
|
|
9791
|
-
|
|
9792
|
-
// // Demographic Information
|
|
9793
|
-
// person_age: z.union([z.number().int().min(18).max(100), z.string().describe("Age range or 'unknown'")]).describe('find age base on the name Estimated age or range'),
|
|
9794
|
-
// person_gender: z.enum(['male', 'female']).describe('find Gender based on the name'),
|
|
9795
|
-
// person_nationality: z.string().describe('find nationality based on the name Country of origin/nationality (2-letter ISO code)'),
|
|
9796
|
-
|
|
9797
|
-
// // Professional Information
|
|
9798
|
-
// person_title: z.string().describe('Professional title/role'),
|
|
9799
|
-
// person_company: z.string().describe('Current company/organization'),
|
|
9800
|
-
// person_industry: z.string().describe('Primary industry/field'),
|
|
9801
|
-
// person_bio: z.string().describe('Professional biography (1-2 sentences)'),
|
|
9802
|
-
|
|
9803
|
-
// // Location
|
|
9804
|
-
// person_location_city: z.string().describe('City of residence/work'),
|
|
9805
|
-
// person_location_state: z.string().describe('State/province'),
|
|
9806
|
-
// person_location_country: z.string().describe('Country (2-letter ISO code)'),
|
|
9807
|
-
// person_location_full: z.string().describe('Full location string'),
|
|
9808
|
-
|
|
9809
|
-
// // Contact Information
|
|
9810
|
-
// person_phone: z.string().describe("Phone number or 'Not available'"),
|
|
9811
|
-
// person_email: z.string().describe('Primary email address'),
|
|
9812
|
-
// person_email_alternate: z.string().optional().nullable().describe('Alternate email if available'),
|
|
9813
|
-
|
|
9814
|
-
// // Education
|
|
9815
|
-
// person_education: z.array(z.string()).describe('Array of educational institutions/degrees'),
|
|
9816
|
-
// person_education_highest: z.string().describe('Highest degree obtained'),
|
|
9817
|
-
|
|
9818
|
-
// // Professional Details
|
|
9819
|
-
// person_skills: z.array(z.string()).describe('Array of professional skills'),
|
|
9820
|
-
// person_expertise: z.array(z.string()).describe('Areas of expertise'),
|
|
9821
|
-
// person_career_level: z.enum(['entry', 'mid', 'senior', 'lead', 'manager', 'director', 'executive', 'founder', 'unknown']),
|
|
9822
|
-
// person_years_experience: z.number().int().min(0).max(60).describe('Years of professional experience'),
|
|
9823
|
-
|
|
9824
|
-
// // Social & Online Presence
|
|
9825
|
-
// person_linkedin: z.string().describe("LinkedIn profile URL or 'Not available'"),
|
|
9826
|
-
// person_twitter: z.string().describe("Twitter/X profile URL or 'Not available'"),
|
|
9827
|
-
// person_github: z.string().describe("GitHub profile URL or 'Not available'"),
|
|
9828
|
-
// person_website: z.string().describe("Personal website/portfolio or 'Not available'"),
|
|
9829
|
-
// person_social_other: z.array(z.string()).optional().nullable().describe('Other social media profiles'),
|
|
9830
|
-
|
|
9831
|
-
// // Additional Information
|
|
9832
|
-
// person_languages: z.array(z.string()).describe('Languages spoken'),
|
|
9833
|
-
// person_interests: z.array(z.string()).describe('Professional/personal interests'),
|
|
9834
|
-
// person_achievements: z.array(z.string()).optional().nullable().describe('Notable achievements/awards'),
|
|
9835
|
-
// person_current_projects: z.array(z.string()).optional().nullable().describe('Current projects'),
|
|
9836
|
-
|
|
9837
|
-
// // Context Extracted Information
|
|
9838
|
-
// person_context_insights: z.array(z.string()).optional().nullable().describe('Insights extracted from provided email context'),
|
|
9839
|
-
|
|
9840
|
-
// // Metadata
|
|
9841
|
-
// person_available_for_opportunities: z.boolean().describe('Open to new opportunities'),
|
|
9842
|
-
// person_last_updated: z.string().describe('Date information was last verified'),
|
|
9843
|
-
// person_source_confidence: z.number().min(0).max(100).describe('Confidence score for information accuracy'),
|
|
9844
|
-
// person_has_context_hints: z.boolean().describe('Whether email context provided useful hints'),
|
|
9845
|
-
// }),
|
|
9846
|
-
// metadata: {
|
|
9847
|
-
// func: 'get_person_info',
|
|
9848
|
-
// person_name: name,
|
|
9849
|
-
// person_email: email,
|
|
9850
|
-
// has_email_context: !!email_context,
|
|
9851
|
-
// email_context_length: email_context?.length || 0,
|
|
9852
|
-
// context_hash: email_context ? await hashString(email_context.substring(0, 200)) : null,
|
|
9853
|
-
// },
|
|
9854
|
-
// account_profile_info,
|
|
9855
|
-
// tools: [{ type: 'web_search_preview' }],
|
|
9856
|
-
// });
|
|
9857
|
-
|
|
9858
|
-
// try {
|
|
9859
|
-
// if (person_info_ret.code > -1) {
|
|
9860
|
-
// const data = typeof person_info_ret.data === 'string' ? JSON.parse(person_info_ret.data) : person_info_ret.data;
|
|
9861
|
-
|
|
9862
|
-
// // Process and enhance the data
|
|
9863
|
-
// const processedData = processPersonInfo(data, name, email, email_context);
|
|
9864
|
-
|
|
9865
|
-
// return processedData;
|
|
9866
|
-
// } else {
|
|
9867
|
-
// console.error('Person info API call failed:', person_info_ret);
|
|
9868
|
-
// return getDefaultPersonInfo(name, email, email_context);
|
|
9869
|
-
// }
|
|
9870
|
-
// } catch (error) {
|
|
9871
|
-
// console.error('Error in get_person_info:', error);
|
|
9872
|
-
// return getDefaultPersonInfo(name, email, email_context, error.message);
|
|
9873
|
-
// }
|
|
9874
|
-
// };
|
|
9875
|
-
|
|
9876
|
-
// export const analyze_email_account_type = async function (uid, name, email, account_profile_info, email_context = '') {
|
|
9877
|
-
// // ========== HELPER FUNCTIONS ==========
|
|
9878
|
-
|
|
9879
|
-
// function enhanceEmailAnalysis(data, name, email, emailContext) {
|
|
9880
|
-
// const domain = email.split('@')[1] || '';
|
|
9881
|
-
// const localPart = email.split('@')[0] || '';
|
|
9882
|
-
// const nameParts = name.toLowerCase().split(/\s+/);
|
|
9883
|
-
// const firstName = nameParts[0] || '';
|
|
9884
|
-
// const lastName = nameParts.slice(-1)[0] || '';
|
|
9885
|
-
|
|
9886
|
-
// // Enhanced business company detection
|
|
9887
|
-
// if (data.account_type === 'business' && !data.business_company_name) {
|
|
9888
|
-
// data.business_company_name = inferCompanyFromDomain(domain);
|
|
9889
|
-
// }
|
|
9890
|
-
|
|
9891
|
-
// // Enhanced person detection
|
|
9892
|
-
// if (!data.is_real_person) {
|
|
9893
|
-
// data.is_real_person = detectRealPerson(localPart, name, domain);
|
|
9894
|
-
// }
|
|
9895
|
-
|
|
9896
|
-
// if (!data.person_name_in_email) {
|
|
9897
|
-
// data.person_name_in_email = checkNameInEmail(localPart, firstName, lastName);
|
|
9898
|
-
// }
|
|
9899
|
-
|
|
9900
|
-
// // Enhanced pattern analysis
|
|
9901
|
-
// if (data.email_pattern === 'unknown') {
|
|
9902
|
-
// data.email_pattern = analyzeEmailPattern(localPart, domain);
|
|
9903
|
-
// }
|
|
9904
|
-
|
|
9905
|
-
// // Enhanced personal provider detection
|
|
9906
|
-
// if (data.account_type === 'personal' && !data.personal_account_provider) {
|
|
9907
|
-
// data.personal_account_provider = identifyPersonalProvider(domain);
|
|
9908
|
-
// }
|
|
9909
|
-
|
|
9910
|
-
// // Enhanced risk assessment
|
|
9911
|
-
// if (data.spam_risk_level === 'unknown') {
|
|
9912
|
-
// data.spam_risk_level = assessSpamRisk(localPart, domain, data.account_type);
|
|
9913
|
-
// }
|
|
9914
|
-
|
|
9915
|
-
// // Enhanced activity assessment
|
|
9916
|
-
// if (!data.is_likely_active) {
|
|
9917
|
-
// data.is_likely_active = assessEmailActivity(localPart, domain, data.account_type, data.business_account_category);
|
|
9918
|
-
// }
|
|
9919
|
-
|
|
9920
|
-
// // Add domain analysis
|
|
9921
|
-
// data.domain_analysis = {
|
|
9922
|
-
// domain: domain,
|
|
9923
|
-
// is_public_provider: isPublicEmailProvider(domain),
|
|
9924
|
-
// is_custom_domain: isCustomDomain(domain),
|
|
9925
|
-
// is_free_email: isFreeEmailDomain(domain),
|
|
9926
|
-
// is_education: isEducationDomain(domain),
|
|
9927
|
-
// is_government: isGovernmentDomain(domain),
|
|
9928
|
-
// tld: domain.split('.').pop() || '',
|
|
9929
|
-
// };
|
|
9930
|
-
|
|
9931
|
-
// // Add name-email correlation score
|
|
9932
|
-
// data.name_email_correlation = calculateNameEmailCorrelation(localPart, firstName, lastName);
|
|
9933
|
-
|
|
9934
|
-
// // Add professional score
|
|
9935
|
-
// data.professional_score = calculateProfessionalScore(data);
|
|
9936
|
-
|
|
9937
|
-
// // Add structured recommendations
|
|
9938
|
-
// data.recommendations = generateRecommendations(data);
|
|
9939
|
-
|
|
9940
|
-
// // Add verification suggestions
|
|
9941
|
-
// data.verification_suggestions = generateVerificationSuggestions(data, emailContext);
|
|
9942
|
-
|
|
9943
|
-
// // Add timestamp
|
|
9944
|
-
// data.analysis_timestamp = data.analysis_timestamp || new Date().toISOString();
|
|
9945
|
-
|
|
9946
|
-
// return data;
|
|
9947
|
-
// }
|
|
9948
|
-
|
|
9949
|
-
// function inferCompanyFromDomain(domain) {
|
|
9950
|
-
// if (!domain) return 'Unknown';
|
|
9951
|
-
|
|
9952
|
-
// // Remove common TLDs and public providers
|
|
9953
|
-
// const baseDomain = domain.replace(/\.(com|org|net|co|io|ai|tech|app|dev)$/, '');
|
|
9954
|
-
|
|
9955
|
-
// // Remove common subdomains
|
|
9956
|
-
// const cleanDomain = baseDomain.replace(/^(mail\.|email\.|webmail\.|smtp\.|mx\.|imap\.)/, '').replace(/\.(com|org|net)$/, '');
|
|
9957
|
-
|
|
9958
|
-
// // Convert to readable company name
|
|
9959
|
-
// const companyName = cleanDomain
|
|
9960
|
-
// .split(/[\.\-]/)
|
|
9961
|
-
// .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
9962
|
-
// .join(' ');
|
|
9963
|
-
|
|
9964
|
-
// return companyName || 'Unknown';
|
|
9965
|
-
// }
|
|
9966
|
-
|
|
9967
|
-
// function detectRealPerson(localPart, name, domain) {
|
|
9968
|
-
// // Check for generic email addresses
|
|
9969
|
-
// const genericPatterns = [
|
|
9970
|
-
// 'info',
|
|
9971
|
-
// 'support',
|
|
9972
|
-
// 'sales',
|
|
9973
|
-
// 'contact',
|
|
9974
|
-
// 'hello',
|
|
9975
|
-
// 'noreply',
|
|
9976
|
-
// 'no-reply',
|
|
9977
|
-
// 'admin',
|
|
9978
|
-
// 'administrator',
|
|
9979
|
-
// 'webmaster',
|
|
9980
|
-
// 'postmaster',
|
|
9981
|
-
// 'hostmaster',
|
|
9982
|
-
// 'abuse',
|
|
9983
|
-
// 'security',
|
|
9984
|
-
// 'billing',
|
|
9985
|
-
// 'accounts',
|
|
9986
|
-
// 'finance',
|
|
9987
|
-
// 'hr',
|
|
9988
|
-
// 'humanresources',
|
|
9989
|
-
// 'marketing',
|
|
9990
|
-
// 'pr',
|
|
9991
|
-
// 'press',
|
|
9992
|
-
// 'media',
|
|
9993
|
-
// 'legal',
|
|
9994
|
-
// 'it',
|
|
9995
|
-
// 'techsupport',
|
|
9996
|
-
// 'help',
|
|
9997
|
-
// 'service',
|
|
9998
|
-
// 'customerservice',
|
|
9999
|
-
// 'feedback',
|
|
10000
|
-
// 'inquiries',
|
|
10001
|
-
// ];
|
|
10002
|
-
|
|
10003
|
-
// const localLower = localPart.toLowerCase();
|
|
10004
|
-
|
|
10005
|
-
// // If it matches generic patterns, likely not a real person
|
|
10006
|
-
// if (genericPatterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.endsWith('.' + pattern))) {
|
|
10007
|
-
// return false;
|
|
10008
|
-
// }
|
|
10009
|
-
|
|
10010
|
-
// // Check for role-based patterns
|
|
10011
|
-
// const rolePatterns = ['ceo', 'cto', 'cfo', 'coo', 'cm', 'director', 'manager', 'head', 'lead', 'senior', 'junior', 'associate', 'analyst', 'engineer', 'developer', 'designer', 'architect', 'consultant', 'advisor'];
|
|
10012
|
-
|
|
10013
|
-
// // If contains role patterns but not name, might be generic
|
|
10014
|
-
// const hasRolePattern = rolePatterns.some((role) => localLower.includes(role));
|
|
10015
|
-
// const hasNameElements = checkNameInEmail(localPart, name.toLowerCase().split(' ')[0], name.toLowerCase().split(' ').slice(-1)[0]);
|
|
10016
|
-
|
|
10017
|
-
// if (hasRolePattern && !hasNameElements) {
|
|
10018
|
-
// return false;
|
|
10019
|
-
// }
|
|
10020
|
-
|
|
10021
|
-
// // Check for numeric-only or random strings
|
|
10022
|
-
// if (/^\d+$/.test(localPart) || /^[a-f0-9]{32}$/.test(localPart)) {
|
|
10023
|
-
// return false;
|
|
10024
|
-
// }
|
|
10025
|
-
|
|
10026
|
-
// // Check for obvious spam patterns
|
|
10027
|
-
// if (localLower.includes('spam') || localLower.includes('bot') || localLower.includes('test')) {
|
|
10028
|
-
// return false;
|
|
10029
|
-
// }
|
|
10030
|
-
|
|
10031
|
-
// return true;
|
|
10032
|
-
// }
|
|
10033
|
-
|
|
10034
|
-
// function checkNameInEmail(localPart, firstName, lastName) {
|
|
10035
|
-
// if (!firstName && !lastName) return false;
|
|
10036
|
-
|
|
10037
|
-
// const localLower = localPart.toLowerCase();
|
|
10038
|
-
// const firstLower = firstName.toLowerCase();
|
|
10039
|
-
// const lastLower = lastName.toLowerCase();
|
|
10040
|
-
|
|
10041
|
-
// // Check various name patterns
|
|
10042
|
-
// const patterns = [
|
|
10043
|
-
// `${firstLower}.${lastLower}`, // john.doe
|
|
10044
|
-
// `${firstLower}${lastLower}`, // johndoe
|
|
10045
|
-
// `${firstLower.charAt(0)}${lastLower}`, // jdoe
|
|
10046
|
-
// `${firstLower}_${lastLower}`, // john_doe
|
|
10047
|
-
// `${firstLower}-${lastLower}`, // john-doe
|
|
10048
|
-
// `${lastLower}.${firstLower}`, // doe.john
|
|
10049
|
-
// `${firstLower.charAt(0)}.${lastLower}`, // j.doe
|
|
10050
|
-
// `${lastLower}${firstLower}`, // doejohn
|
|
10051
|
-
// `${firstLower}`, // john
|
|
10052
|
-
// `${lastLower}`, // doe
|
|
10053
|
-
// ];
|
|
10054
|
-
|
|
10055
|
-
// return patterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.includes('.' + pattern));
|
|
10056
|
-
// }
|
|
10057
|
-
|
|
10058
|
-
// function analyzeEmailPattern(localPart, domain) {
|
|
10059
|
-
// const localLower = localPart.toLowerCase();
|
|
10060
|
-
|
|
10061
|
-
// // Common business patterns
|
|
10062
|
-
// if (/^[a-z]+\.[a-z]+$/.test(localLower)) return 'first.last@company.com';
|
|
10063
|
-
// if (/^[a-z]+[a-z]+$/.test(localLower) && localLower.length > 5) return 'firstlast@company.com';
|
|
10064
|
-
// if (/^[a-z]\.[a-z]+$/.test(localLower)) return 'f.last@company.com';
|
|
10065
|
-
// if (/^[a-z][a-z]+$/.test(localLower) && localLower.length <= 5) return 'flast@company.com';
|
|
10066
|
-
// if (/^[a-z]+$/.test(localLower) && localLower.length <= 8) return 'first@company.com';
|
|
10067
|
-
// if (/^[a-z]+\.[a-z]+\.[a-z]+$/.test(localLower)) return 'first.m.last@company.com';
|
|
10068
|
-
|
|
10069
|
-
// // Generic patterns
|
|
10070
|
-
// if (/^(info|support|sales|contact|hello)$/.test(localLower)) return 'role@company.com';
|
|
10071
|
-
// if (/^(hr|finance|marketing|it|legal)$/.test(localLower)) return 'department@company.com';
|
|
10072
|
-
|
|
10073
|
-
// // Personal patterns
|
|
10074
|
-
// if (isPublicEmailProvider(domain)) {
|
|
10075
|
-
// if (/^[a-z]+\.[a-z]+$/.test(localLower)) return 'first.last@domain.com';
|
|
10076
|
-
// if (/^[a-z]+[0-9]+$/.test(localLower)) return 'personal@provider.com';
|
|
10077
|
-
// return 'custom@personal.com';
|
|
10078
|
-
// }
|
|
10079
|
-
|
|
10080
|
-
// return 'unknown';
|
|
10081
|
-
// }
|
|
10082
|
-
|
|
10083
|
-
// function identifyPersonalProvider(domain) {
|
|
10084
|
-
// const providers = {
|
|
10085
|
-
// 'gmail.com': 'Google Gmail',
|
|
10086
|
-
// 'googlemail.com': 'Google Gmail',
|
|
10087
|
-
// 'outlook.com': 'Microsoft Outlook',
|
|
10088
|
-
// 'hotmail.com': 'Microsoft Hotmail',
|
|
10089
|
-
// 'live.com': 'Microsoft Live',
|
|
10090
|
-
// 'yahoo.com': 'Yahoo Mail',
|
|
10091
|
-
// 'ymail.com': 'Yahoo Mail',
|
|
10092
|
-
// 'aol.com': 'AOL Mail',
|
|
10093
|
-
// 'icloud.com': 'Apple iCloud',
|
|
10094
|
-
// 'me.com': 'Apple iCloud',
|
|
10095
|
-
// 'mac.com': 'Apple iCloud',
|
|
10096
|
-
// 'protonmail.com': 'ProtonMail',
|
|
10097
|
-
// 'proton.me': 'ProtonMail',
|
|
10098
|
-
// 'zoho.com': 'Zoho Mail',
|
|
10099
|
-
// 'yandex.com': 'Yandex Mail',
|
|
10100
|
-
// 'mail.com': 'Mail.com',
|
|
10101
|
-
// 'gmx.com': 'GMX Mail',
|
|
10102
|
-
// };
|
|
10103
|
-
|
|
10104
|
-
// return providers[domain.toLowerCase()] || 'Custom/Unknown';
|
|
10105
|
-
// }
|
|
10106
|
-
|
|
10107
|
-
// function isPublicEmailProvider(domain) {
|
|
10108
|
-
// const publicProviders = ['gmail.com', 'googlemail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'ymail.com', 'aol.com', 'icloud.com', 'me.com', 'mac.com', 'protonmail.com', 'proton.me', 'zoho.com', 'yandex.com', 'mail.com', 'gmx.com'];
|
|
10109
|
-
|
|
10110
|
-
// return publicProviders.includes(domain.toLowerCase());
|
|
10111
|
-
// }
|
|
10112
|
-
|
|
10113
|
-
// function isFreeEmailDomain(domain) {
|
|
10114
|
-
// const freeDomains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'mail.com', 'gmx.com', 'yandex.com', 'zoho.com'];
|
|
10115
|
-
|
|
10116
|
-
// return freeDomains.includes(domain.toLowerCase());
|
|
10117
|
-
// }
|
|
10118
|
-
|
|
10119
|
-
// function isCustomDomain(domain) {
|
|
10120
|
-
// const publicProviders = ['gmail.com', 'googlemail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'ymail.com', 'aol.com', 'icloud.com', 'me.com', 'mac.com', 'protonmail.com', 'proton.me', 'zoho.com', 'yandex.com', 'mail.com', 'gmx.com', 'edu', 'gov', 'mil', 'org', 'net'];
|
|
10121
|
-
|
|
10122
|
-
// return !publicProviders.some((provider) => domain.toLowerCase().includes(provider));
|
|
10123
|
-
// }
|
|
10124
|
-
|
|
10125
|
-
// function isEducationDomain(domain) {
|
|
10126
|
-
// return domain.toLowerCase().endsWith('.edu') || domain.toLowerCase().includes('.ac.');
|
|
10127
|
-
// }
|
|
10128
|
-
|
|
10129
|
-
// function isGovernmentDomain(domain) {
|
|
10130
|
-
// return domain.toLowerCase().endsWith('.gov') || domain.toLowerCase().endsWith('.mil');
|
|
10131
|
-
// }
|
|
10132
|
-
|
|
10133
|
-
// function assessSpamRisk(localPart, domain, accountType) {
|
|
10134
|
-
// const localLower = localPart.toLowerCase();
|
|
10135
|
-
|
|
10136
|
-
// // High risk indicators
|
|
10137
|
-
// if (localLower.includes('spam') || localLower.includes('bot')) return 'high';
|
|
10138
|
-
// if (/^[a-f0-9]{32}$/.test(localLower)) return 'high'; // MD5 hash-like
|
|
10139
|
-
// if (/^\d+$/.test(localLower)) return 'high'; // Numbers only
|
|
10140
|
-
// if (localLower.includes('temp') || localLower.includes('throwaway')) return 'high';
|
|
10141
|
-
|
|
10142
|
-
// // Medium risk indicators
|
|
10143
|
-
// if (localLower.includes('test') || localLower.includes('demo')) return 'medium';
|
|
10144
|
-
// if (accountType === 'personal' && localLower.includes('+')) return 'medium'; // Plus addressing
|
|
10145
|
-
|
|
10146
|
-
// // Check disposable email domains
|
|
10147
|
-
// if (isDisposableDomain(domain)) return 'high';
|
|
10148
|
-
|
|
10149
|
-
// return 'low';
|
|
10150
|
-
// }
|
|
10151
|
-
|
|
10152
|
-
// function isDisposableDomain(domain) {
|
|
10153
|
-
// // Common disposable/temporary email domains
|
|
10154
|
-
// const disposableDomains = ['tempmail.com', 'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'yopmail.com', 'trashmail.com', 'dispostable.com', 'fakeinbox.com', 'throwawaymail.com', 'temp-mail.org'];
|
|
10155
|
-
|
|
10156
|
-
// return disposableDomains.some((d) => domain.toLowerCase().includes(d));
|
|
10157
|
-
// }
|
|
10158
|
-
|
|
10159
|
-
// function assessEmailActivity(localPart, domain, accountType, businessCategory) {
|
|
10160
|
-
// // Generic/role emails are usually monitored
|
|
10161
|
-
// if (accountType === 'business' && ['generic_role', 'department', 'catch_all'].includes(businessCategory)) {
|
|
10162
|
-
// return true;
|
|
10163
|
-
// }
|
|
10164
|
-
|
|
10165
|
-
// // Personal emails with name patterns are likely active
|
|
10166
|
-
// if (accountType === 'personal' && /^[a-z]+\.[a-z]+$/.test(localPart.toLowerCase())) {
|
|
10167
|
-
// return true;
|
|
10168
|
-
// }
|
|
10169
|
-
|
|
10170
|
-
// // Education and government emails are usually active
|
|
10171
|
-
// if (isEducationDomain(domain) || isGovernmentDomain(domain)) {
|
|
10172
|
-
// return true;
|
|
10173
|
-
// }
|
|
10174
|
-
|
|
10175
|
-
// // Disposable domains are usually inactive after short period
|
|
10176
|
-
// if (isDisposableDomain(domain)) {
|
|
10177
|
-
// return false;
|
|
10178
|
-
// }
|
|
10179
|
-
|
|
10180
|
-
// // Default assumption
|
|
10181
|
-
// return true;
|
|
10182
|
-
// }
|
|
10183
|
-
|
|
10184
|
-
// function calculateNameEmailCorrelation(localPart, firstName, lastName) {
|
|
10185
|
-
// if (!firstName && !lastName) return 0;
|
|
10186
|
-
|
|
10187
|
-
// let score = 0;
|
|
10188
|
-
// const localLower = localPart.toLowerCase();
|
|
10189
|
-
// const firstLower = firstName.toLowerCase();
|
|
10190
|
-
// const lastLower = lastName.toLowerCase();
|
|
10191
|
-
|
|
10192
|
-
// // Exact name patterns
|
|
10193
|
-
// if (localLower === `${firstLower}.${lastLower}`) score += 40;
|
|
10194
|
-
// if (localLower === `${firstLower}${lastLower}`) score += 35;
|
|
10195
|
-
// if (localLower === `${firstLower.charAt(0)}${lastLower}`) score += 30;
|
|
10196
|
-
// if (localLower === `${firstLower}_${lastLower}`) score += 25;
|
|
10197
|
-
|
|
10198
|
-
// // Partial matches
|
|
10199
|
-
// if (localLower.includes(firstLower)) score += 15;
|
|
10200
|
-
// if (localLower.includes(lastLower)) score += 15;
|
|
10201
|
-
|
|
10202
|
-
// // Initial matches
|
|
10203
|
-
// if (localLower.startsWith(firstLower.charAt(0))) score += 10;
|
|
10204
|
-
|
|
10205
|
-
// // Length consideration (shorter emails with names are better)
|
|
10206
|
-
// if (localLower.length <= 20) score += 5;
|
|
10207
|
-
|
|
10208
|
-
// return Math.min(score, 100);
|
|
10209
|
-
// }
|
|
10210
|
-
|
|
10211
|
-
// function calculateProfessionalScore(data) {
|
|
10212
|
-
// let score = 50; // Base score
|
|
10213
|
-
|
|
10214
|
-
// // Account type weights
|
|
10215
|
-
// if (data.account_type === 'business') score += 30;
|
|
10216
|
-
// else if (data.account_type === 'personal') score += 10;
|
|
10217
|
-
|
|
10218
|
-
// // Real person bonus
|
|
10219
|
-
// if (data.is_real_person) score += 20;
|
|
10220
|
-
|
|
10221
|
-
// // Active email bonus
|
|
10222
|
-
// if (data.is_likely_active) score += 15;
|
|
10223
|
-
|
|
10224
|
-
// // Low spam risk bonus
|
|
10225
|
-
// if (data.spam_risk_level === 'low') score += 10;
|
|
10226
|
-
// else if (data.spam_risk_level === 'high') score -= 20;
|
|
10227
|
-
|
|
10228
|
-
// // Name-email correlation bonus
|
|
10229
|
-
// score += (data.name_email_correlation / 100) * 20;
|
|
10230
|
-
|
|
10231
|
-
// // Business category bonus
|
|
10232
|
-
// if (data.business_account_category === 'personal_employee') score += 15;
|
|
10233
|
-
|
|
10234
|
-
// return Math.max(0, Math.min(100, score));
|
|
10235
|
-
// }
|
|
10236
|
-
|
|
10237
|
-
// function generateRecommendations(data) {
|
|
10238
|
-
// const recommendations = [];
|
|
10239
|
-
|
|
10240
|
-
// if (data.account_type === 'business' && data.is_real_person) {
|
|
10241
|
-
// if (data.business_account_category === 'personal_employee') {
|
|
10242
|
-
// recommendations.push('Ideal for direct professional outreach');
|
|
10243
|
-
// recommendations.push('Suitable for sales, recruitment, and partnership discussions');
|
|
10244
|
-
// } else if (data.business_account_category === 'department') {
|
|
10245
|
-
// recommendations.push('Best for department-specific inquiries');
|
|
10246
|
-
// recommendations.push('Use for customer support or service requests');
|
|
10247
|
-
// }
|
|
10248
|
-
// } else if (data.account_type === 'personal') {
|
|
10249
|
-
// recommendations.push('Suitable for networking and personal connections');
|
|
10250
|
-
// recommendations.push('May be used for freelance or consulting work');
|
|
10251
|
-
// }
|
|
10252
|
-
|
|
10253
|
-
// if (data.spam_risk_level === 'high') {
|
|
10254
|
-
// recommendations.push('Consider verifying before important communications');
|
|
10255
|
-
// }
|
|
10256
|
-
|
|
10257
|
-
// if (!data.is_likely_active) {
|
|
10258
|
-
// recommendations.push('Email may not be actively monitored');
|
|
10259
|
-
// }
|
|
10260
|
-
|
|
10261
|
-
// return recommendations;
|
|
10262
|
-
// }
|
|
10263
|
-
|
|
10264
|
-
// function generateVerificationSuggestions(data, emailContext) {
|
|
10265
|
-
// const suggestions = [];
|
|
10266
|
-
|
|
10267
|
-
// if (data.account_type === 'business' && !data.business_company_name) {
|
|
10268
|
-
// suggestions.push('Verify company name through LinkedIn or company website');
|
|
10269
|
-
// }
|
|
10270
|
-
|
|
10271
|
-
// if (!data.is_real_person && data.account_type === 'business') {
|
|
10272
|
-
// suggestions.push('Check if this is a role-based email that forwards to individuals');
|
|
10273
|
-
// }
|
|
10274
|
-
|
|
10275
|
-
// if (data.spam_risk_level === 'medium' || data.spam_risk_level === 'high') {
|
|
10276
|
-
// suggestions.push('Send verification email before important communications');
|
|
10277
|
-
// }
|
|
10278
|
-
|
|
10279
|
-
// if (data.domain_analysis.is_custom_domain) {
|
|
10280
|
-
// suggestions.push('Check company website for email format patterns');
|
|
10281
|
-
// }
|
|
10282
|
-
|
|
10283
|
-
// return suggestions;
|
|
10284
|
-
// }
|
|
10285
|
-
|
|
10286
|
-
// function getDefaultEmailAnalysis(name, email, emailContext = '', error = null) {
|
|
10287
|
-
// const domain = email.split('@')[1] || '';
|
|
10288
|
-
// const localPart = email.split('@')[0] || '';
|
|
10289
|
-
// const nameParts = name.toLowerCase().split(/\s+/);
|
|
10290
|
-
// const firstName = nameParts[0] || '';
|
|
10291
|
-
// const lastName = nameParts.slice(-1)[0] || '';
|
|
10292
|
-
|
|
10293
|
-
// const isPublicProvider = isPublicEmailProvider(domain);
|
|
10294
|
-
// const accountType = isPublicProvider ? 'personal' : 'business';
|
|
10295
|
-
// const isRealPerson = detectRealPerson(localPart, name, domain);
|
|
10296
|
-
|
|
10297
|
-
// return {
|
|
10298
|
-
// success: false,
|
|
10299
|
-
// account_type: accountType,
|
|
10300
|
-
// account_type_confidence: 70,
|
|
10301
|
-
|
|
10302
|
-
// personal_account_provider: isPublicProvider ? identifyPersonalProvider(domain) : undefined,
|
|
10303
|
-
// personal_account_type: 'unknown',
|
|
10304
|
-
// personal_account_age_indicator: 'unknown',
|
|
10305
|
-
|
|
10306
|
-
// business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10307
|
-
// business_company_domain: !isPublicProvider ? domain : undefined,
|
|
10308
|
-
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10309
|
-
// business_account_role: undefined,
|
|
10310
|
-
// business_department: undefined,
|
|
10311
|
-
|
|
10312
|
-
// is_real_person: isRealPerson,
|
|
10313
|
-
// person_name_in_email: checkNameInEmail(localPart, firstName, lastName),
|
|
10314
|
-
// person_title_inferred: undefined,
|
|
10315
|
-
|
|
10316
|
-
// email_pattern: analyzeEmailPattern(localPart, domain),
|
|
10317
|
-
|
|
10318
|
-
// context_supports_business: undefined,
|
|
10319
|
-
// context_supports_personal: undefined,
|
|
10320
|
-
// context_company_mentions: [],
|
|
10321
|
-
|
|
10322
|
-
// is_high_quality_contact: isRealPerson && !isPublicProvider,
|
|
10323
|
-
// is_likely_active: true,
|
|
10324
|
-
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10325
|
-
|
|
10326
|
-
// suggested_use_case: isRealPerson && !isPublicProvider ? 'sales_outreach' : 'networking',
|
|
10327
|
-
|
|
10328
|
-
// analysis_timestamp: new Date().toISOString(),
|
|
10329
|
-
// analysis_notes: ['Default analysis due to API failure'],
|
|
10330
|
-
|
|
10331
|
-
// // Enhanced fields
|
|
10332
|
-
// domain_analysis: {
|
|
10333
|
-
// domain: domain,
|
|
10334
|
-
// is_public_provider: isPublicProvider,
|
|
10335
|
-
// is_custom_domain: isCustomDomain(domain),
|
|
10336
|
-
// is_free_email: isFreeEmailDomain(domain),
|
|
10337
|
-
// is_education: isEducationDomain(domain),
|
|
10338
|
-
// is_government: isGovernmentDomain(domain),
|
|
10339
|
-
// tld: domain.split('.').pop() || '',
|
|
10340
|
-
// },
|
|
10341
|
-
|
|
10342
|
-
// name_email_correlation: calculateNameEmailCorrelation(localPart, firstName, lastName),
|
|
10343
|
-
// professional_score: calculateProfessionalScore({
|
|
10344
|
-
// account_type: accountType,
|
|
10345
|
-
// is_real_person: isRealPerson,
|
|
10346
|
-
// is_likely_active: true,
|
|
10347
|
-
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10348
|
-
// name_email_correlation: calculateNameEmailCorrelation(localPart, firstName, lastName),
|
|
10349
|
-
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10350
|
-
// }),
|
|
10351
|
-
|
|
10352
|
-
// recommendations: generateRecommendations({
|
|
10353
|
-
// account_type: accountType,
|
|
10354
|
-
// is_real_person: isRealPerson,
|
|
10355
|
-
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10356
|
-
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10357
|
-
// is_likely_active: true,
|
|
10358
|
-
// }),
|
|
10359
|
-
|
|
10360
|
-
// verification_suggestions: generateVerificationSuggestions(
|
|
10361
|
-
// {
|
|
10362
|
-
// account_type: accountType,
|
|
10363
|
-
// business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10364
|
-
// is_real_person: isRealPerson,
|
|
10365
|
-
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10366
|
-
// domain_analysis: { is_custom_domain: isCustomDomain(domain) },
|
|
10367
|
-
// },
|
|
10368
|
-
// emailContext,
|
|
10369
|
-
// ),
|
|
10370
|
-
|
|
10371
|
-
// error: error || 'API call failed',
|
|
10372
|
-
// };
|
|
10373
|
-
// }
|
|
10374
|
-
|
|
10375
|
-
// const analysis_ret = await submit_chat_gpt_prompt({
|
|
10376
|
-
// uid,
|
|
10377
|
-
// prompt: `Analyze this email account: "${email}" for person: "${name}"
|
|
10378
|
-
|
|
10379
|
-
// EMAIL CONTEXT (if provided):
|
|
10380
|
-
// "${email_context.substring(0, 400)}${email_context.length > 400 ? '...' : ''}"
|
|
10381
|
-
|
|
10382
|
-
// ANALYSIS TASKS:
|
|
10383
|
-
// 1. Determine if this is a PERSONAL or BUSINESS email account
|
|
10384
|
-
// 2. For BUSINESS accounts:
|
|
10385
|
-
// - Identify the company/organization
|
|
10386
|
-
// - Determine if this email belongs to a REAL PERSON at the company
|
|
10387
|
-
// - Or if it's a generic/role-based account
|
|
10388
|
-
// 3. For PERSONAL accounts:
|
|
10389
|
-
// - Identify which personal email provider is used
|
|
10390
|
-
// - Determine if it's likely a primary or secondary personal account
|
|
10391
|
-
|
|
10392
|
-
// ANALYSIS CRITERIA:
|
|
10393
|
-
// BUSINESS EMAIL INDICATORS:
|
|
10394
|
-
// - Domain matches a known company (not public email providers)
|
|
10395
|
-
// - Email format matches company naming conventions
|
|
10396
|
-
// - Email is mentioned in professional context
|
|
10397
|
-
// - Contains company-specific signature or details
|
|
10398
|
-
|
|
10399
|
-
// PERSONAL EMAIL INDICATORS:
|
|
10400
|
-
// - Domain is from public email providers (gmail.com, outlook.com, yahoo.com, etc.)
|
|
10401
|
-
// - Email format is personal/creative
|
|
10402
|
-
// - No company affiliation in context
|
|
10403
|
-
// - Used for personal communications
|
|
10404
|
-
|
|
10405
|
-
// PERSON VS GENERIC BUSINESS ACCOUNT:
|
|
10406
|
-
// - PERSON: Contains personal name elements (john.doe@company.com)
|
|
10407
|
-
// - GENERIC: info@, support@, sales@, contact@, hello@, noreply@, etc.
|
|
10408
|
-
// - DEPARTMENT: hr@, finance@, marketing@, it@, etc.
|
|
10409
|
-
|
|
10410
|
-
// COMPANY DETECTION:
|
|
10411
|
-
// - Extract company from email domain when possible
|
|
10412
|
-
// - Use name patterns to identify likely companies
|
|
10413
|
-
// - Consider email context for company references
|
|
10414
|
-
|
|
10415
|
-
// PROVIDE DETAILED ANALYSIS WITH CONFIDENCE LEVELS.`,
|
|
10416
|
-
// model: 'gpt-5-nano',
|
|
10417
|
-
// response_format: z.object({
|
|
10418
|
-
// // Primary Classification
|
|
10419
|
-
// account_type: z.enum(['personal', 'business', 'ambiguous']),
|
|
10420
|
-
// account_type_confidence: z.number().min(0).max(100),
|
|
10421
|
-
|
|
10422
|
-
// // Personal Account Details
|
|
10423
|
-
// personal_account_provider: z.string().optional().nullable().describe('Email provider for personal accounts'),
|
|
10424
|
-
// personal_account_type: z.enum(['primary', 'secondary', 'disposable', 'unknown']).optional().nullable(),
|
|
10425
|
-
// personal_account_age_indicator: z.enum(['new', 'established', 'old', 'unknown']).optional().nullable(),
|
|
10426
|
-
|
|
10427
|
-
// // Business Account Details
|
|
10428
|
-
// business_company_name: z.string().optional().nullable().describe('Company name if business account'),
|
|
10429
|
-
// business_company_domain: z.string().optional().nullable().describe('Company domain'),
|
|
10430
|
-
// business_account_category: z.enum(['personal_employee', 'generic_role', 'department', 'catch_all', 'unknown']).optional().nullable(),
|
|
10431
|
-
// business_account_role: z.string().optional().nullable().describe('Role suggested by email address'),
|
|
10432
|
-
// business_department: z.string().optional().nullable().describe('Department if applicable'),
|
|
10433
|
-
|
|
10434
|
-
// // Person Analysis
|
|
10435
|
-
// is_real_person: z.boolean().describe('Whether email belongs to a real person'),
|
|
10436
|
-
// person_name_in_email: z.boolean().describe("Whether person's name appears in email address"),
|
|
10437
|
-
// person_title_inferred: z.string().optional().nullable().describe('Inferred job title from email pattern'),
|
|
10438
|
-
|
|
10439
|
-
// // Email Pattern Analysis
|
|
10440
|
-
// email_pattern: z.enum([
|
|
10441
|
-
// 'first.last@company.com',
|
|
10442
|
-
// 'first.last@domain.com',
|
|
10443
|
-
// 'firstlast@company.com',
|
|
10444
|
-
// 'flast@company.com',
|
|
10445
|
-
// 'first@company.com',
|
|
10446
|
-
// 'f.last@company.com',
|
|
10447
|
-
// 'initial.last@company.com',
|
|
10448
|
-
// 'role@company.com',
|
|
10449
|
-
// 'department@company.com',
|
|
10450
|
-
// 'info@company.com',
|
|
10451
|
-
// 'generic@company.com',
|
|
10452
|
-
// 'personal@provider.com',
|
|
10453
|
-
// 'custom@personal.com',
|
|
10454
|
-
// 'unknown',
|
|
10455
|
-
// ]),
|
|
10456
|
-
|
|
10457
|
-
// // Context Analysis
|
|
10458
|
-
// context_supports_business: z.boolean().optional().nullable().describe('Email context suggests business use'),
|
|
10459
|
-
// context_supports_personal: z.boolean().optional().nullable().describe('Email context suggests personal use'),
|
|
10460
|
-
// context_company_mentions: z.array(z.string()).optional().nullable().describe('Companies mentioned in context'),
|
|
10461
|
-
|
|
10462
|
-
// // Risk & Quality Assessment
|
|
10463
|
-
// is_high_quality_contact: z.boolean().describe('Good contact for professional outreach'),
|
|
10464
|
-
// is_likely_active: z.boolean().describe('Email likely actively monitored'),
|
|
10465
|
-
// spam_risk_level: z.enum(['low', 'medium', 'high', 'unknown']),
|
|
10466
|
-
|
|
10467
|
-
// // Recommendations
|
|
10468
|
-
// suggested_use_case: z.enum(['sales_outreach', 'recruitment', 'customer_support', 'partnership', 'networking', 'personal_contact', 'avoid']),
|
|
10469
|
-
|
|
10470
|
-
// // Metadata
|
|
10471
|
-
// analysis_timestamp: z.string().describe('When analysis was performed'),
|
|
10472
|
-
// analysis_notes: z.array(z.string()).optional().nullable().describe('Key observations from analysis'),
|
|
10473
|
-
// }),
|
|
10474
|
-
// metadata: {
|
|
10475
|
-
// func: 'analyze_email_account_type',
|
|
10476
|
-
// person_name: name,
|
|
10477
|
-
// person_email: email,
|
|
10478
|
-
// has_email_context: !!email_context,
|
|
10479
|
-
// email_length: email_context?.length || 0,
|
|
10480
|
-
// },
|
|
10481
|
-
// account_profile_info,
|
|
10482
|
-
// tools: [{ type: 'web_search_preview' }],
|
|
10483
|
-
// });
|
|
10484
|
-
|
|
10485
|
-
// try {
|
|
10486
|
-
// if (analysis_ret.code > -1) {
|
|
10487
|
-
// const data = typeof analysis_ret.data === 'string' ? JSON.parse(analysis_ret.data) : analysis_ret.data;
|
|
10488
|
-
|
|
10489
|
-
// // Enhance with additional analysis
|
|
10490
|
-
// const enhancedData = enhanceEmailAnalysis(data, name, email, email_context);
|
|
10491
|
-
|
|
10492
|
-
// return {
|
|
10493
|
-
// success: true,
|
|
10494
|
-
// ...enhancedData,
|
|
10495
|
-
// };
|
|
10496
|
-
// } else {
|
|
10497
|
-
// console.error('Email analysis API call failed:', analysis_ret);
|
|
10498
|
-
// return getDefaultEmailAnalysis(name, email, email_context);
|
|
10499
|
-
// }
|
|
10500
|
-
// } catch (error) {
|
|
10501
|
-
// console.error('Error in analyze_email_account_type:', error);
|
|
10502
|
-
// return getDefaultEmailAnalysis(name, email, email_context, error.message);
|
|
10503
|
-
// }
|
|
10504
|
-
// };
|
|
10505
|
-
|
|
10506
|
-
// export const detect_email_type = async function (uid, name, email, account_profile_info, email_body = '', email_subject = '') {
|
|
10507
|
-
// // ========== HELPER FUNCTIONS ==========
|
|
10508
|
-
|
|
10509
|
-
// async function hashString(str) {
|
|
10510
|
-
// const encoder = new TextEncoder();
|
|
10511
|
-
// const data = encoder.encode(str);
|
|
10512
|
-
// const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
10513
|
-
// const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
10514
|
-
// return hashArray
|
|
10515
|
-
// .map((b) => b.toString(16).padStart(2, '0'))
|
|
10516
|
-
// .join('')
|
|
10517
|
-
// .substring(0, 16);
|
|
10518
|
-
// }
|
|
10519
|
-
|
|
10520
|
-
// function enhanceEmailDetection(data, name, email, emailBody, emailSubject) {
|
|
10521
|
-
// // Run additional local analysis
|
|
10522
|
-
// const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
|
|
10523
|
-
|
|
10524
|
-
// // Combine AI analysis with local analysis
|
|
10525
|
-
// const combinedData = {
|
|
10526
|
-
// ...data,
|
|
10527
|
-
// // Override with local analysis if confidence is high
|
|
10528
|
-
// spam_confidence: Math.max(data.spam_confidence, localAnalysis.spamScore),
|
|
10529
|
-
// phishing_risk: localAnalysis.phishingScore > 70 ? 'high' : data.phishing_risk,
|
|
10530
|
-
|
|
10531
|
-
// // Add local analysis results
|
|
10532
|
-
// local_analysis: localAnalysis,
|
|
10533
|
-
|
|
10534
|
-
// // Enhance sender analysis
|
|
10535
|
-
// sender_analysis: analyzeSender(email, name, emailBody),
|
|
10536
|
-
|
|
10537
|
-
// // Content statistics
|
|
10538
|
-
// content_stats: {
|
|
10539
|
-
// word_count: (emailBody.match(/\S+/g) || []).length,
|
|
10540
|
-
// sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
|
|
10541
|
-
// link_count: (emailBody.match(/https?:\/\/[^\s]+/g) || []).length,
|
|
10542
|
-
// uppercase_ratio: calculateUppercaseRatio(emailBody),
|
|
10543
|
-
// exclamation_count: (emailBody.match(/!/g) || []).length,
|
|
10544
|
-
// dollar_sign_count: (emailBody.match(/\$/g) || []).length,
|
|
10545
|
-
// phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
|
|
10546
|
-
// },
|
|
10547
|
-
|
|
10548
|
-
// // Behavioral patterns
|
|
10549
|
-
// behavioral_patterns: detectBehavioralPatterns(emailBody, emailSubject),
|
|
10550
|
-
|
|
10551
|
-
// // Domain reputation
|
|
10552
|
-
// domain_reputation: assessDomainReputation(email),
|
|
10553
|
-
|
|
10554
|
-
// // Add comprehensive risk assessment
|
|
10555
|
-
// comprehensive_risk_score: calculateComprehensiveRisk(data, localAnalysis),
|
|
10556
|
-
|
|
10557
|
-
// // Filter rules that matched
|
|
10558
|
-
// matched_filters: detectMatchedFilters(emailBody, emailSubject, email, name),
|
|
10559
|
-
|
|
10560
|
-
// // Timeline analysis
|
|
10561
|
-
// temporal_analysis: {
|
|
10562
|
-
// is_time_sensitive: detectTimeSensitivity(emailBody),
|
|
10563
|
-
// has_expiry: detectExpiryDate(emailBody),
|
|
10564
|
-
// is_follow_up: detectFollowUpPattern(emailBody, emailSubject),
|
|
10565
|
-
// },
|
|
10566
|
-
|
|
10567
|
-
// // Relationship context
|
|
10568
|
-
// relationship_context: analyzeRelationshipContext(emailBody, emailSubject, name),
|
|
10569
|
-
|
|
10570
|
-
// // Update timestamp
|
|
10571
|
-
// analysis_timestamp: new Date().toISOString(),
|
|
10572
|
-
// content_length: emailBody.length,
|
|
10573
|
-
// };
|
|
10574
|
-
|
|
10575
|
-
// // Calculate final classification confidence
|
|
10576
|
-
// combinedData.final_confidence = calculateFinalConfidence(combinedData);
|
|
10577
|
-
|
|
10578
|
-
// // Generate detailed explanation
|
|
10579
|
-
// combinedData.explanation = generateExplanation(combinedData);
|
|
10580
|
-
|
|
10581
|
-
// // Add compliance flags
|
|
10582
|
-
// combinedData.compliance_flags = checkCompliance(emailBody, emailSubject);
|
|
10583
|
-
|
|
10584
|
-
// return combinedData;
|
|
10585
|
-
// }
|
|
10586
|
-
|
|
10587
|
-
// function analyzeEmailLocally(body, subject, email, name) {
|
|
10588
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
10589
|
-
// let spamScore = 0;
|
|
10590
|
-
// let phishingScore = 0;
|
|
10591
|
-
// let promotionalScore = 0;
|
|
10592
|
-
// let transactionalScore = 0;
|
|
10593
|
-
|
|
10594
|
-
// // SPAM indicators
|
|
10595
|
-
// const spamKeywords = [
|
|
10596
|
-
// 'congratulations',
|
|
10597
|
-
// 'winner',
|
|
10598
|
-
// 'prize',
|
|
10599
|
-
// 'lottery',
|
|
10600
|
-
// 'free',
|
|
10601
|
-
// 'guaranteed',
|
|
10602
|
-
// 'risk-free',
|
|
10603
|
-
// 'act now',
|
|
10604
|
-
// 'limited time',
|
|
10605
|
-
// 'urgent',
|
|
10606
|
-
// 'important',
|
|
10607
|
-
// 'attention',
|
|
10608
|
-
// 'alert',
|
|
10609
|
-
// 'click here',
|
|
10610
|
-
// 'buy now',
|
|
10611
|
-
// 'order now',
|
|
10612
|
-
// 'discount',
|
|
10613
|
-
// 'save big',
|
|
10614
|
-
// 'cheap',
|
|
10615
|
-
// 'viagra',
|
|
10616
|
-
// 'cialis',
|
|
10617
|
-
// 'pharmacy',
|
|
10618
|
-
// 'prescription',
|
|
10619
|
-
// 'enlarge',
|
|
10620
|
-
// 'weight loss',
|
|
10621
|
-
// 'nigerian',
|
|
10622
|
-
// 'prince',
|
|
10623
|
-
// 'inheritance',
|
|
10624
|
-
// 'unclaimed',
|
|
10625
|
-
// 'bank account',
|
|
10626
|
-
// 'password',
|
|
10627
|
-
// 'account suspended',
|
|
10628
|
-
// 'verify',
|
|
10629
|
-
// 'security alert',
|
|
10630
|
-
// 'dear friend',
|
|
10631
|
-
// 'dear customer',
|
|
10632
|
-
// 'dear account holder',
|
|
10633
|
-
// ];
|
|
10634
|
-
|
|
10635
|
-
// spamKeywords.forEach((keyword) => {
|
|
10636
|
-
// if (text.includes(keyword)) spamScore += 2;
|
|
10637
|
-
// });
|
|
10638
|
-
|
|
10639
|
-
// // Phishing indicators
|
|
10640
|
-
// const phishingPatterns = [/login\s*(?:here|now)/i, /verify\s*(?:your|my)\s*account/i, /password\s*(?:reset|expired|change)/i, /suspended\s*account/i, /unauthorized\s*activity/i, /security\s*breach/i, /update\s*(?:your|my)\s*information/i, /confirm\s*(?:your|my)\s*identity/i];
|
|
10641
|
-
|
|
10642
|
-
// phishingPatterns.forEach((pattern) => {
|
|
10643
|
-
// if (pattern.test(text)) phishingScore += 15;
|
|
10644
|
-
// });
|
|
10645
|
-
|
|
10646
|
-
// // Promotional indicators
|
|
10647
|
-
// const promotionalKeywords = ['newsletter', 'subscribe', 'unsubscribe', 'marketing', 'promotion', 'sale', 'offer', 'deal', 'coupon', 'voucher', 'discount code', 'new product', 'announcement', 'launch', 'event', 'webinar', 'limited offer', 'exclusive', 'special offer', 'members only'];
|
|
10648
|
-
|
|
10649
|
-
// promotionalKeywords.forEach((keyword) => {
|
|
10650
|
-
// if (text.includes(keyword)) promotionalScore += 3;
|
|
10651
|
-
// });
|
|
10652
|
-
|
|
10653
|
-
// // Transactional indicators
|
|
10654
|
-
// const transactionalKeywords = ['order', 'invoice', 'receipt', 'payment', 'booking', 'reservation', 'confirmation', 'shipping', 'delivery', 'tracking', 'shipment', 'appointment', 'meeting', 'reminder', 'bill', 'statement', 'account', 'statement', 'balance', 'transaction'];
|
|
10655
|
-
|
|
10656
|
-
// transactionalKeywords.forEach((keyword) => {
|
|
10657
|
-
// if (text.includes(keyword)) transactionalScore += 3;
|
|
10658
|
-
// });
|
|
10659
|
-
|
|
10660
|
-
// // Link analysis
|
|
10661
|
-
// const links = body.match(/https?:\/\/[^\s]+/g) || [];
|
|
10662
|
-
// const suspiciousDomains = ['bit.ly', 'tinyurl', 'shorte.st', 'adf.ly', 'goo.gl'];
|
|
10663
|
-
|
|
10664
|
-
// links.forEach((link) => {
|
|
10665
|
-
// if (suspiciousDomains.some((domain) => link.includes(domain))) {
|
|
10666
|
-
// spamScore += 10;
|
|
10667
|
-
// phishingScore += 10;
|
|
10668
|
-
// }
|
|
10669
|
-
// });
|
|
10670
|
-
|
|
10671
|
-
// // Grammar/spelling analysis (simple)
|
|
10672
|
-
// const misspellings = body.match(/\b(?:recieve|seperate|definately|occured|tomm?orrow)\b/gi) || [];
|
|
10673
|
-
// spamScore += misspellings.length * 2;
|
|
10674
|
-
|
|
10675
|
-
// // Urgency analysis
|
|
10676
|
-
// const urgencyWords = ['urgent', 'immediately', 'asap', 'right now', 'today only'];
|
|
10677
|
-
// let urgencyCount = 0;
|
|
10678
|
-
// urgencyWords.forEach((word) => {
|
|
10679
|
-
// if (text.includes(word)) urgencyCount++;
|
|
10680
|
-
// });
|
|
10681
|
-
// spamScore += urgencyCount * 5;
|
|
10682
|
-
|
|
10683
|
-
// // Personalization check
|
|
10684
|
-
// const hasName = name && body.toLowerCase().includes(name.toLowerCase().split(' ')[0]);
|
|
10685
|
-
// const personalPronouns = ['you', 'your', 'yours'];
|
|
10686
|
-
// let personalCount = 0;
|
|
10687
|
-
// personalPronouns.forEach((pronoun) => {
|
|
10688
|
-
// const regex = new RegExp(`\\b${pronoun}\\b`, 'gi');
|
|
10689
|
-
// personalCount += (body.match(regex) || []).length;
|
|
10690
|
-
// });
|
|
10691
|
-
|
|
10692
|
-
// const personalizationScore = hasName ? 30 : Math.min(personalCount * 2, 20);
|
|
10693
|
-
|
|
10694
|
-
// return {
|
|
10695
|
-
// spamScore: Math.min(spamScore, 100),
|
|
10696
|
-
// phishingScore: Math.min(phishingScore, 100),
|
|
10697
|
-
// promotionalScore: Math.min(promotionalScore, 100),
|
|
10698
|
-
// transactionalScore: Math.min(transactionalScore, 100),
|
|
10699
|
-
// personalizationScore,
|
|
10700
|
-
// linkCount: links.length,
|
|
10701
|
-
// hasUnsubscribe: text.includes('unsubscribe') || text.includes('opt-out'),
|
|
10702
|
-
// hasPhone: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/.test(body),
|
|
10703
|
-
// hasAddress: /\b\d+\s+[\w\s]+(?:street|st|avenue|ave|road|rd|boulevard|blvd|way)\b/i.test(body),
|
|
10704
|
-
// urgencyCount,
|
|
10705
|
-
// misspellingCount: misspellings.length,
|
|
10706
|
-
// };
|
|
10707
|
-
// }
|
|
10708
|
-
|
|
10709
|
-
// function analyzeSender(email, name, body) {
|
|
10710
|
-
// const domain = email.split('@')[1] || '';
|
|
10711
|
-
// const localPart = email.split('@')[0] || '';
|
|
10712
|
-
|
|
10713
|
-
// return {
|
|
10714
|
-
// email: email,
|
|
10715
|
-
// domain: domain,
|
|
10716
|
-
// local_part: localPart,
|
|
10717
|
-
// is_public_domain: isPublicEmailDomain(domain),
|
|
10718
|
-
// is_generic_sender: isGenericSender(localPart, name),
|
|
10719
|
-
// domain_age_indicator: assessDomainAge(domain),
|
|
10720
|
-
// sender_consistency: checkSenderConsistency(name, email, body),
|
|
10721
|
-
// };
|
|
10722
|
-
// }
|
|
10723
|
-
|
|
10724
|
-
// function isPublicEmailDomain(domain) {
|
|
10725
|
-
// const publicDomains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'icloud.com', 'protonmail.com', 'zoho.com', 'yandex.com'];
|
|
10726
|
-
// return publicDomains.includes(domain.toLowerCase());
|
|
10727
|
-
// }
|
|
10728
|
-
|
|
10729
|
-
// function isGenericSender(localPart, name) {
|
|
10730
|
-
// const genericSenders = ['info', 'support', 'sales', 'contact', 'hello', 'noreply', 'admin', 'newsletter', 'marketing', 'team', 'notifications'];
|
|
10731
|
-
|
|
10732
|
-
// const localLower = localPart.toLowerCase();
|
|
10733
|
-
// const nameLower = name.toLowerCase();
|
|
10734
|
-
|
|
10735
|
-
// return genericSenders.some((sender) => localLower.includes(sender) || nameLower.includes(sender));
|
|
10736
|
-
// }
|
|
10737
|
-
|
|
10738
|
-
// function assessDomainAge(domain) {
|
|
10739
|
-
// // This is a simplified version - in production, you'd use a domain age API
|
|
10740
|
-
// const newDomains = ['xyz', 'online', 'site', 'top', 'club', 'shop'];
|
|
10741
|
-
// const tld = domain.split('.').pop() || '';
|
|
10742
|
-
|
|
10743
|
-
// if (newDomains.includes(tld)) return 'likely_new';
|
|
10744
|
-
// if (['com', 'org', 'net', 'edu', 'gov'].includes(tld)) return 'likely_established';
|
|
10745
|
-
// return 'unknown';
|
|
10746
|
-
// }
|
|
10747
|
-
|
|
10748
|
-
// function checkSenderConsistency(name, email, body) {
|
|
10749
|
-
// const emailName = email.split('@')[0].toLowerCase();
|
|
10750
|
-
// const bodyName = name.toLowerCase();
|
|
10751
|
-
|
|
10752
|
-
// // Check if name appears in body
|
|
10753
|
-
// const nameInBody = body.toLowerCase().includes(bodyName.split(' ')[0]);
|
|
10754
|
-
|
|
10755
|
-
// // Check email-name consistency patterns
|
|
10756
|
-
// const nameParts = bodyName.split(' ');
|
|
10757
|
-
// const firstName = nameParts[0] || '';
|
|
10758
|
-
// const lastName = nameParts.slice(-1)[0] || '';
|
|
10759
|
-
|
|
10760
|
-
// const patterns = [`${firstName}.${lastName}`, `${firstName}${lastName}`, `${firstName.charAt(0)}${lastName}`, `${firstName}`];
|
|
10761
|
-
|
|
10762
|
-
// const consistent = patterns.some((pattern) => emailName.includes(pattern.toLowerCase()));
|
|
10763
|
-
|
|
10764
|
-
// return {
|
|
10765
|
-
// name_in_body: nameInBody,
|
|
10766
|
-
// email_name_consistent: consistent,
|
|
10767
|
-
// consistency_score: (nameInBody ? 40 : 0) + (consistent ? 60 : 0),
|
|
10768
|
-
// };
|
|
10769
|
-
// }
|
|
10770
|
-
|
|
10771
|
-
// function calculateUppercaseRatio(text) {
|
|
10772
|
-
// const letters = text.replace(/[^a-zA-Z]/g, '');
|
|
10773
|
-
// if (letters.length === 0) return 0;
|
|
10774
|
-
|
|
10775
|
-
// const uppercase = letters.replace(/[^A-Z]/g, '');
|
|
10776
|
-
// return (uppercase.length / letters.length) * 100;
|
|
10777
|
-
// }
|
|
10778
|
-
|
|
10779
|
-
// function detectBehavioralPatterns(body, subject) {
|
|
10780
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
10781
|
-
// const patterns = [];
|
|
10782
|
-
|
|
10783
|
-
// if (/(?:click|tap)\s+(?:here|this|link|button)/i.test(text)) {
|
|
10784
|
-
// patterns.push('call_to_action_link');
|
|
10785
|
-
// }
|
|
10786
|
-
|
|
10787
|
-
// if (/limited\s+time|offer\s+expires|only\s+\d+\s+left/i.test(text)) {
|
|
10788
|
-
// patterns.push('scarcity_tactic');
|
|
10789
|
-
// }
|
|
10790
|
-
|
|
10791
|
-
// if (/\$\d+|\d+\s*%|\d+\s*off|discount|save|sale/i.test(text)) {
|
|
10792
|
-
// patterns.push('monetary_offer');
|
|
10793
|
-
// }
|
|
10794
|
-
|
|
10795
|
-
// if (/urgent|important|alert|attention|warning/i.test(text)) {
|
|
10796
|
-
// patterns.push('urgency_tactic');
|
|
10797
|
-
// }
|
|
10798
|
-
|
|
10799
|
-
// if (/(?:please|kindly)\s+(?:help|assist|reply)/i.test(text)) {
|
|
10800
|
-
// patterns.push('polite_request');
|
|
10801
|
-
// }
|
|
10802
|
-
|
|
10803
|
-
// if (/unsubscribe|opt.?out|preference|manage subscription/i.test(text)) {
|
|
10804
|
-
// patterns.push('subscription_management');
|
|
10805
|
-
// }
|
|
10806
|
-
|
|
10807
|
-
// return patterns;
|
|
10808
|
-
// }
|
|
10809
|
-
|
|
10810
|
-
// function assessDomainReputation(email) {
|
|
10811
|
-
// const domain = email.split('@')[1] || '';
|
|
10812
|
-
|
|
10813
|
-
// // Known spam domains (simplified list)
|
|
10814
|
-
// const spamDomains = ['spam4.me', 'trashmail.com', 'mailinator.com', 'guerrillamail.com', 'tempmail.com', 'yopmail.com', 'dispostable.com'];
|
|
10815
|
-
|
|
10816
|
-
// if (spamDomains.includes(domain.toLowerCase())) {
|
|
10817
|
-
// return 'known_spam_domain';
|
|
10818
|
-
// }
|
|
10819
|
-
|
|
10820
|
-
// // Professional domains
|
|
10821
|
-
// const professionalTLDs = ['com', 'org', 'net', 'edu', 'gov', 'io', 'ai', 'tech'];
|
|
10822
|
-
// const tld = domain.split('.').pop() || '';
|
|
10823
|
-
|
|
10824
|
-
// if (professionalTLDs.includes(tld.toLowerCase())) {
|
|
10825
|
-
// return 'professional_domain';
|
|
10826
|
-
// }
|
|
10827
|
-
|
|
10828
|
-
// // New/suspicious TLDs
|
|
10829
|
-
// const suspiciousTLDs = ['xyz', 'top', 'win', 'bid', 'download', 'stream'];
|
|
10830
|
-
// if (suspiciousTLDs.includes(tld.toLowerCase())) {
|
|
10831
|
-
// return 'suspicious_tld';
|
|
10832
|
-
// }
|
|
10833
|
-
|
|
10834
|
-
// return 'neutral';
|
|
10835
|
-
// }
|
|
10836
|
-
|
|
10837
|
-
// function calculateComprehensiveRisk(aiData, localAnalysis) {
|
|
10838
|
-
// let risk = 0;
|
|
10839
|
-
|
|
10840
|
-
// // Base on AI classification
|
|
10841
|
-
// switch (aiData.email_type) {
|
|
10842
|
-
// case 'spam':
|
|
10843
|
-
// risk += 80;
|
|
10844
|
-
// break;
|
|
10845
|
-
// case 'promotional':
|
|
10846
|
-
// risk += 30;
|
|
10847
|
-
// break;
|
|
10848
|
-
// case 'transactional':
|
|
10849
|
-
// risk += 10;
|
|
10850
|
-
// break;
|
|
10851
|
-
// case 'personal':
|
|
10852
|
-
// risk += 5;
|
|
10853
|
-
// break;
|
|
10854
|
-
// case 'business':
|
|
10855
|
-
// risk += 15;
|
|
10856
|
-
// break;
|
|
10857
|
-
// }
|
|
10858
|
-
|
|
10859
|
-
// // Add local analysis scores
|
|
10860
|
-
// risk += localAnalysis.spamScore * 0.2;
|
|
10861
|
-
// risk += localAnalysis.phishingScore * 0.3;
|
|
10862
|
-
|
|
10863
|
-
// // Adjust for phishing risk
|
|
10864
|
-
// switch (aiData.phishing_risk) {
|
|
10865
|
-
// case 'critical':
|
|
10866
|
-
// risk += 40;
|
|
10867
|
-
// break;
|
|
10868
|
-
// case 'high':
|
|
10869
|
-
// risk += 30;
|
|
10870
|
-
// break;
|
|
10871
|
-
// case 'medium':
|
|
10872
|
-
// risk += 15;
|
|
10873
|
-
// break;
|
|
10874
|
-
// case 'low':
|
|
10875
|
-
// risk += 5;
|
|
10876
|
-
// break;
|
|
10877
|
-
// }
|
|
10878
|
-
|
|
10879
|
-
// // Adjust for unsolicited
|
|
10880
|
-
// if (aiData.is_unsolicited) risk += 20;
|
|
10881
|
-
|
|
10882
|
-
// // Adjust for urgency
|
|
10883
|
-
// if (aiData.is_urgent) risk += 10;
|
|
10884
|
-
|
|
10885
|
-
// return Math.min(risk, 100);
|
|
10886
|
-
// }
|
|
10887
|
-
|
|
10888
|
-
// function detectMatchedFilters(body, subject, email, name) {
|
|
10889
|
-
// const filters = [];
|
|
10890
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
10891
|
-
|
|
10892
|
-
// // Spam filters
|
|
10893
|
-
// if (/(?:viagra|cialis|penis|enlarge)/i.test(text)) filters.push('adult_content_filter');
|
|
10894
|
-
// if (/(?:lottery|winner|prize|jackpot)/i.test(text)) filters.push('lottery_scam_filter');
|
|
10895
|
-
// if (/(?:nigerian|prince|inheritance|unclaimed)/i.test(text)) filters.push('inheritance_scam_filter');
|
|
10896
|
-
// if (/password\s+reset|verify\s+account/i.test(text)) filters.push('account_verification_filter');
|
|
10897
|
-
|
|
10898
|
-
// // Promotional filters
|
|
10899
|
-
// if (/newsletter|subscribe|unsubscribe/i.test(text)) filters.push('newsletter_filter');
|
|
10900
|
-
// if (/sale|discount|offer|coupon/i.test(text)) filters.push('promotional_offer_filter');
|
|
10901
|
-
// if (/webinar|event|conference/i.test(text)) filters.push('event_filter');
|
|
10902
|
-
|
|
10903
|
-
// // Transactional filters
|
|
10904
|
-
// if (/order|invoice|receipt|payment/i.test(text)) filters.push('transaction_filter');
|
|
10905
|
-
// if (/shipping|delivery|tracking/i.test(text)) filters.push('shipping_filter');
|
|
10906
|
-
// if (/appointment|meeting|reminder/i.test(text)) filters.push('calendar_filter');
|
|
10907
|
-
|
|
10908
|
-
// return filters;
|
|
10909
|
-
// }
|
|
10910
|
-
|
|
10911
|
-
// function detectTimeSensitivity(body) {
|
|
10912
|
-
// const text = body.toLowerCase();
|
|
10913
|
-
// const patterns = [/today|tomorrow|this\s+week|immediately|asap/i, /deadline|due\s+by|expires|limited\s+time/i, /urgent|important|attention|alert/i];
|
|
10914
|
-
|
|
10915
|
-
// return patterns.some((pattern) => pattern.test(text));
|
|
10916
|
-
// }
|
|
10917
|
-
|
|
10918
|
-
// function detectExpiryDate(body) {
|
|
10919
|
-
// const datePatterns = [/\b\d{1,2}\/\d{1,2}\/\d{2,4}\b/g, /\b\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{2,4}\b/gi, /\bexpires?\s+(?:on|by)?\s*[:]?\s*\d{1,2}\/\d{1,2}\/\d{2,4}\b/gi];
|
|
10920
|
-
|
|
10921
|
-
// return datePatterns.some((pattern) => pattern.test(body.toLowerCase()));
|
|
10922
|
-
// }
|
|
10923
|
-
|
|
10924
|
-
// function detectFollowUpPattern(body, subject) {
|
|
10925
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
10926
|
-
// return /follow.?up|following.?up|checking.?in|touch.?base|re:.?re:/i.test(text);
|
|
10927
|
-
// }
|
|
10928
|
-
|
|
10929
|
-
// function analyzeRelationshipContext(body, subject, name) {
|
|
10930
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
10931
|
-
// const nameParts = name.toLowerCase().split(' ');
|
|
10932
|
-
// const firstName = nameParts[0] || '';
|
|
10933
|
-
|
|
10934
|
-
// const indicators = {
|
|
10935
|
-
// uses_name: firstName && text.includes(firstName),
|
|
10936
|
-
// uses_personal_pronouns: /\b(?:i|me|my|mine|you|your|yours)\b/gi.test(text),
|
|
10937
|
-
// has_greeting: /^(?:hi|hello|hey|dear|greetings)\b/im.test(body),
|
|
10938
|
-
// has_signature: /(?:best|regards|sincerely|thanks|thank you)\s*[,]?\s*\n/im.test(body),
|
|
10939
|
-
// has_questions: /\?/.test(text) && /(?:can|could|would|will|do|are|is)\s+you/i.test(text),
|
|
10940
|
-
// };
|
|
10941
|
-
|
|
10942
|
-
// const relationshipScore = Object.values(indicators).filter(Boolean).length * 20;
|
|
10943
|
-
|
|
10944
|
-
// return {
|
|
10945
|
-
// ...indicators,
|
|
10946
|
-
// relationship_score: Math.min(relationshipScore, 100),
|
|
10947
|
-
// likely_known_sender: relationshipScore >= 40,
|
|
10948
|
-
// };
|
|
10949
|
-
// }
|
|
10950
|
-
|
|
10951
|
-
// function calculateFinalConfidence(data) {
|
|
10952
|
-
// let confidence = data.email_type_confidence;
|
|
10953
|
-
|
|
10954
|
-
// // Adjust based on local analysis
|
|
10955
|
-
// if (data.local_analysis.spamScore > 70 && data.email_type !== 'spam') {
|
|
10956
|
-
// confidence -= 20;
|
|
10957
|
-
// }
|
|
10958
|
-
|
|
10959
|
-
// // Adjust based on phishing risk
|
|
10960
|
-
// if (data.phishing_risk === 'critical' || data.phishing_risk === 'high') {
|
|
10961
|
-
// confidence += 15;
|
|
10962
|
-
// }
|
|
10963
|
-
|
|
10964
|
-
// // Adjust based on personalization
|
|
10965
|
-
// if (data.is_personalized) {
|
|
10966
|
-
// confidence += 10;
|
|
10967
|
-
// }
|
|
10968
|
-
|
|
10969
|
-
// // Adjust based on content stats
|
|
10970
|
-
// if (data.content_stats.link_count > 5) {
|
|
10971
|
-
// confidence += 5;
|
|
10972
|
-
// }
|
|
10973
|
-
|
|
10974
|
-
// return Math.max(0, Math.min(100, confidence));
|
|
10975
|
-
// }
|
|
10976
|
-
|
|
10977
|
-
// function generateExplanation(data) {
|
|
10978
|
-
// const explanations = [];
|
|
10979
|
-
|
|
10980
|
-
// if (data.email_type === 'spam') {
|
|
10981
|
-
// explanations.push('Classified as spam due to:');
|
|
10982
|
-
// if (data.spam_confidence > 70) explanations.push(`- High spam confidence (${data.spam_confidence}%)`);
|
|
10983
|
-
// if (data.phishing_risk !== 'none') explanations.push(`- ${data.phishing_risk} phishing risk`);
|
|
10984
|
-
// if (data.local_analysis.spamScore > 60) explanations.push('- Contains spam indicators');
|
|
10985
|
-
// }
|
|
10986
|
-
|
|
10987
|
-
// if (data.email_type === 'promotional') {
|
|
10988
|
-
// explanations.push('Classified as promotional due to:');
|
|
10989
|
-
// if (data.is_commercial) explanations.push('- Commercial intent detected');
|
|
10990
|
-
// if (data.local_analysis.hasUnsubscribe) explanations.push('- Contains unsubscribe option');
|
|
10991
|
-
// if (data.local_analysis.promotionalScore > 30) explanations.push('- Promotional content detected');
|
|
10992
|
-
// }
|
|
10993
|
-
|
|
10994
|
-
// if (data.key_indicators && data.key_indicators.length > 0) {
|
|
10995
|
-
// explanations.push('Key indicators:');
|
|
10996
|
-
// data.key_indicators.forEach((indicator) => {
|
|
10997
|
-
// explanations.push(`- ${indicator}`);
|
|
10998
|
-
// });
|
|
10999
|
-
// }
|
|
11000
|
-
|
|
11001
|
-
// return explanations.join('\n');
|
|
11002
|
-
// }
|
|
11003
|
-
|
|
11004
|
-
// function checkCompliance(body, subject) {
|
|
11005
|
-
// const text = (subject + ' ' + body).toLowerCase();
|
|
11006
|
-
// const flags = [];
|
|
11007
|
-
|
|
11008
|
-
// // CAN-SPAM Act compliance (US)
|
|
11009
|
-
// if (text.includes('unsubscribe') || text.includes('opt-out')) {
|
|
11010
|
-
// flags.push('has_unsubscribe_option');
|
|
11011
|
-
// }
|
|
11012
|
-
|
|
11013
|
-
// if (/\b\d{10}\b/.test(body.replace(/\D/g, ''))) {
|
|
11014
|
-
// flags.push('contains_phone_number');
|
|
11015
|
-
// }
|
|
11016
|
-
|
|
11017
|
-
// if (/address\s*[:]?\s*\d+\s+[\w\s]+/i.test(body)) {
|
|
11018
|
-
// flags.push('contains_physical_address');
|
|
11019
|
-
// }
|
|
11020
|
-
|
|
11021
|
-
// // GDPR indicators (EU)
|
|
11022
|
-
// if (/privacy\s+policy|gdpr|data\s+protection/i.test(text)) {
|
|
11023
|
-
// flags.push('gdpr_mentions');
|
|
11024
|
-
// }
|
|
11025
|
-
|
|
11026
|
-
// if (/consent|opt.?in|permission/i.test(text)) {
|
|
11027
|
-
// flags.push('consent_mentions');
|
|
11028
|
-
// }
|
|
11029
|
-
|
|
11030
|
-
// return flags;
|
|
11031
|
-
// }
|
|
11032
|
-
|
|
11033
|
-
// function getDefaultEmailDetection(name, email, emailBody, emailSubject, error = null) {
|
|
11034
|
-
// const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
|
|
11035
|
-
|
|
11036
|
-
// // Determine type based on local analysis
|
|
11037
|
-
// let emailType = 'ambiguous';
|
|
11038
|
-
// if (localAnalysis.spamScore > 70) emailType = 'spam';
|
|
11039
|
-
// else if (localAnalysis.promotionalScore > localAnalysis.transactionalScore && localAnalysis.promotionalScore > 30) emailType = 'promotional';
|
|
11040
|
-
// else if (localAnalysis.transactionalScore > 40) emailType = 'transactional';
|
|
11041
|
-
|
|
11042
|
-
// const spamConfidence = localAnalysis.spamScore;
|
|
11043
|
-
// const phishingRisk = localAnalysis.phishingScore > 50 ? 'medium' : 'low';
|
|
11044
|
-
|
|
11045
|
-
// return {
|
|
11046
|
-
// success: false,
|
|
11047
|
-
// email_type: emailType,
|
|
11048
|
-
// email_type_confidence: Math.max(50, spamConfidence),
|
|
11049
|
-
// email_subtype: 'personal_message',
|
|
11050
|
-
|
|
11051
|
-
// spam_confidence: spamConfidence,
|
|
11052
|
-
// phishing_risk: phishingRisk,
|
|
11053
|
-
// malware_risk: 'none',
|
|
11054
|
-
|
|
11055
|
-
// is_unsolicited: true,
|
|
11056
|
-
// is_commercial: localAnalysis.promotionalScore > 30,
|
|
11057
|
-
// is_urgent: localAnalysis.urgencyCount > 0,
|
|
11058
|
-
// is_personalized: localAnalysis.personalizationScore > 20,
|
|
11059
|
-
|
|
11060
|
-
// sender_legitimacy: 'unknown',
|
|
11061
|
-
// sender_intent: 'unknown',
|
|
11062
|
-
|
|
11063
|
-
// contains_links: localAnalysis.linkCount > 0,
|
|
11064
|
-
// contains_attachments: false,
|
|
11065
|
-
// contains_unsubscribe: localAnalysis.hasUnsubscribe,
|
|
11066
|
-
// contains_phone_number: localAnalysis.hasPhone,
|
|
11067
|
-
// contains_address: localAnalysis.hasAddress,
|
|
11068
|
-
|
|
11069
|
-
// language_quality: localAnalysis.misspellingCount > 3 ? 'poor' : 'average',
|
|
11070
|
-
// urgency_level: localAnalysis.urgencyCount > 2 ? 'high' : 'low',
|
|
11071
|
-
// personalization_score: localAnalysis.personalizationScore,
|
|
11072
|
-
|
|
11073
|
-
// suggested_action: emailType === 'spam' ? 'mark_as_spam' : 'keep_in_inbox',
|
|
11074
|
-
// auto_filter_suggestion: emailType === 'spam' ? 'spam_filter' : 'no_filter',
|
|
11075
|
-
// inbox_priority: emailType === 'spam' ? 'ignore' : 'normal',
|
|
11076
|
-
|
|
11077
|
-
// key_indicators: ['Local analysis only - API failed'],
|
|
11078
|
-
// risk_factors: [],
|
|
11079
|
-
// legitimacy_signals: [],
|
|
11080
|
-
|
|
11081
|
-
// analysis_timestamp: new Date().toISOString(),
|
|
11082
|
-
// content_length: emailBody.length,
|
|
11083
|
-
// analysis_complexity: 'simple',
|
|
11084
|
-
|
|
11085
|
-
// // Enhanced fields
|
|
11086
|
-
// local_analysis: localAnalysis,
|
|
11087
|
-
// sender_analysis: analyzeSender(email, name, emailBody),
|
|
11088
|
-
// content_stats: {
|
|
11089
|
-
// word_count: (emailBody.match(/\S+/g) || []).length,
|
|
11090
|
-
// sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
|
|
11091
|
-
// link_count: localAnalysis.linkCount,
|
|
11092
|
-
// uppercase_ratio: calculateUppercaseRatio(emailBody),
|
|
11093
|
-
// exclamation_count: (emailBody.match(/!/g) || []).length,
|
|
11094
|
-
// dollar_sign_count: (emailBody.match(/\$/g) || []).length,
|
|
11095
|
-
// phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
|
|
11096
|
-
// },
|
|
11097
|
-
|
|
11098
|
-
// comprehensive_risk_score: calculateComprehensiveRisk({ email_type: emailType, phishing_risk: phishingRisk, is_unsolicited: true, is_urgent: localAnalysis.urgencyCount > 0 }, localAnalysis),
|
|
11099
|
-
|
|
11100
|
-
// final_confidence: Math.max(50, spamConfidence),
|
|
11101
|
-
// explanation: 'Default analysis due to API failure',
|
|
11102
|
-
// error: error || 'API call failed',
|
|
11103
|
-
// };
|
|
11104
|
-
// }
|
|
11105
|
-
|
|
11106
|
-
// const detection_ret = await submit_chat_gpt_prompt({
|
|
11107
|
-
// uid,
|
|
11108
|
-
// prompt: `Analyze this email and determine if it's SPAM, PROMOTIONAL, TRANSACTIONAL, or PERSONAL/BUSINESS communication.
|
|
11109
|
-
|
|
11110
|
-
// FROM: "${name}" <${email}>
|
|
11111
|
-
// SUBJECT: "${email_subject}"
|
|
11112
|
-
// BODY: "${email_body.substring(0, 800)}${email_body.length > 800 ? '...' : ''}"
|
|
11113
|
-
|
|
11114
|
-
// ANALYSIS CRITERIA:
|
|
11115
|
-
|
|
11116
|
-
// SPAM INDICATORS:
|
|
11117
|
-
// - Unsolicited commercial content
|
|
11118
|
-
// - Phishing attempts or suspicious links
|
|
11119
|
-
// - Poor grammar/spelling
|
|
11120
|
-
// - Urgent/panic-inducing language
|
|
11121
|
-
// - Requests for personal information
|
|
11122
|
-
// - Too good to be true offers
|
|
11123
|
-
// - Hidden/unclear sender identity
|
|
11124
|
-
// - Multiple recipient addresses visible
|
|
11125
|
-
// - Stock/"spammy" subject lines
|
|
11126
|
-
|
|
11127
|
-
// PROMOTIONAL INDICATORS:
|
|
11128
|
-
// - Marketing/sales content
|
|
11129
|
-
// - Product announcements
|
|
11130
|
-
// - Newsletter content
|
|
11131
|
-
// - Discount/coupon offers
|
|
11132
|
-
// - Event invitations (commercial)
|
|
11133
|
-
// - Company updates (marketing focused)
|
|
11134
|
-
// - Clear opt-out/unsubscribe option
|
|
11135
|
-
// - Professional branding/templates
|
|
11136
|
-
// - Call-to-action buttons
|
|
11137
|
-
|
|
11138
|
-
// TRANSACTIONAL INDICATORS:
|
|
11139
|
-
// - Order confirmations
|
|
11140
|
-
// - Shipping notifications
|
|
11141
|
-
// - Invoice/billing
|
|
11142
|
-
// - Account notifications
|
|
11143
|
-
// - Password resets
|
|
11144
|
-
// - Booking confirmations
|
|
11145
|
-
// - Appointment reminders
|
|
11146
|
-
// - Payment receipts
|
|
11147
|
-
// - Service updates
|
|
11148
|
-
|
|
11149
|
-
// PERSONAL/BUSINESS INDICATORS:
|
|
11150
|
-
// - Direct communication to you
|
|
11151
|
-
// - Known sender relationship
|
|
11152
|
-
// - Work/project related
|
|
11153
|
-
// - Personal conversations
|
|
11154
|
-
// - One-on-one correspondence
|
|
11155
|
-
// - Contains your name specifically
|
|
11156
|
-
// - Contextually relevant to you
|
|
11157
|
-
|
|
11158
|
-
// ADDITIONAL FACTORS TO CONSIDER:
|
|
11159
|
-
// - Sender reputation (company vs personal)
|
|
11160
|
-
// - Your relationship with sender
|
|
11161
|
-
// - Email formatting quality
|
|
11162
|
-
// - Personalization level
|
|
11163
|
-
// - Expected vs unexpected content
|
|
11164
|
-
// - Action requested (if any)
|
|
11165
|
-
|
|
11166
|
-
// PROVIDE DETAILED ANALYSIS WITH CONFIDENCE SCORES.`,
|
|
11167
|
-
// model: 'gpt-5-nano',
|
|
11168
|
-
// response_format: z.object({
|
|
11169
|
-
// // Primary Classification
|
|
11170
|
-
// email_type: z.enum(['spam', 'promotional', 'transactional', 'personal', 'business', 'ambiguous']),
|
|
11171
|
-
// email_type_confidence: z.number().min(0).max(100),
|
|
11172
|
-
|
|
11173
|
-
// // Sub-classification
|
|
11174
|
-
// email_subtype: z.enum([
|
|
11175
|
-
// // Spam types
|
|
11176
|
-
// 'phishing_attempt',
|
|
11177
|
-
// 'scam_offer',
|
|
11178
|
-
// 'malware_risk',
|
|
11179
|
-
// 'adult_content',
|
|
11180
|
-
// 'financial_scam',
|
|
11181
|
-
// 'lottery_scam',
|
|
11182
|
-
// 'inheritance_scam',
|
|
11183
|
-
// 'romance_scam',
|
|
11184
|
-
// 'tech_support_scam',
|
|
11185
|
-
|
|
11186
|
-
// // Promotional types
|
|
11187
|
-
// 'marketing_newsletter',
|
|
11188
|
-
// 'product_announcement',
|
|
11189
|
-
// 'discount_offer',
|
|
11190
|
-
// 'event_invitation',
|
|
11191
|
-
// 'company_update',
|
|
11192
|
-
// 'blog_newsletter',
|
|
11193
|
-
// 'educational_content',
|
|
11194
|
-
// 'lead_magnet',
|
|
11195
|
-
|
|
11196
|
-
// // Transactional types
|
|
11197
|
-
// 'order_confirmation',
|
|
11198
|
-
// 'shipping_notification',
|
|
11199
|
-
// 'invoice_billing',
|
|
11200
|
-
// 'payment_receipt',
|
|
11201
|
-
// 'account_verification',
|
|
11202
|
-
// 'password_reset',
|
|
11203
|
-
// 'appointment_reminder',
|
|
11204
|
-
// 'service_notification',
|
|
11205
|
-
|
|
11206
|
-
// // Personal/Business types
|
|
11207
|
-
// 'personal_message',
|
|
11208
|
-
// 'work_collaboration',
|
|
11209
|
-
// 'client_communication',
|
|
11210
|
-
// 'team_announcement',
|
|
11211
|
-
// 'meeting_invitation',
|
|
11212
|
-
// 'project_update',
|
|
11213
|
-
// 'direct_inquiry',
|
|
11214
|
-
// 'networking_request',
|
|
11215
|
-
// ]),
|
|
11216
|
-
|
|
11217
|
-
// // Risk Assessment
|
|
11218
|
-
// spam_confidence: z.number().min(0).max(100).describe('Confidence this is spam'),
|
|
11219
|
-
// phishing_risk: z.enum(['none', 'low', 'medium', 'high', 'critical']),
|
|
11220
|
-
// malware_risk: z.enum(['none', 'low', 'medium', 'high']),
|
|
11221
|
-
|
|
11222
|
-
// // Content Analysis
|
|
11223
|
-
// is_unsolicited: z.boolean().describe('Email was not requested/expected'),
|
|
11224
|
-
// is_commercial: z.boolean().describe('Contains commercial intent'),
|
|
11225
|
-
// is_urgent: z.boolean().describe('Uses urgent/time-sensitive language'),
|
|
11226
|
-
// is_personalized: z.boolean().describe('Content is personalized to recipient'),
|
|
11227
|
-
|
|
11228
|
-
// // Sender Analysis
|
|
11229
|
-
// sender_legitimacy: z.enum(['verified', 'likely_legitimate', 'suspicious', 'likely_fake', 'unknown']),
|
|
11230
|
-
// sender_intent: z.enum(['inform', 'sell', 'scam', 'build_relationship', 'request_action', 'unknown']),
|
|
11231
|
-
|
|
11232
|
-
// // Content Characteristics
|
|
11233
|
-
// contains_links: z.boolean(),
|
|
11234
|
-
// contains_attachments: z.boolean(),
|
|
11235
|
-
// contains_unsubscribe: z.boolean(),
|
|
11236
|
-
// contains_phone_number: z.boolean(),
|
|
11237
|
-
// contains_address: z.boolean(),
|
|
11238
|
-
|
|
11239
|
-
// // Language Analysis
|
|
11240
|
-
// language_quality: z.enum(['excellent', 'good', 'average', 'poor', 'spammy']),
|
|
11241
|
-
// urgency_level: z.enum(['none', 'low', 'medium', 'high', 'extreme']),
|
|
11242
|
-
// personalization_score: z.number().min(0).max(100).describe('How personalized the content is'),
|
|
11243
|
-
|
|
11244
|
-
// // Action Recommendations
|
|
11245
|
-
// suggested_action: z.enum(['delete_immediately', 'mark_as_spam', 'move_to_promotions', 'respond_politely', 'follow_up', 'archive', 'keep_in_inbox', 'add_to_contacts', 'report_phishing']),
|
|
11246
|
-
|
|
11247
|
-
// // Filter Recommendations
|
|
11248
|
-
// auto_filter_suggestion: z.enum(['spam_filter', 'promotions_filter', 'social_filter', 'updates_filter', 'primary_inbox', 'no_filter']),
|
|
11249
|
-
|
|
11250
|
-
// // Priority
|
|
11251
|
-
// inbox_priority: z.enum(['critical', 'high', 'normal', 'low', 'ignore']),
|
|
11252
|
-
|
|
11253
|
-
// // Detailed Analysis
|
|
11254
|
-
// key_indicators: z.array(z.string()).describe('Key factors influencing classification'),
|
|
11255
|
-
// risk_factors: z.array(z.string()).describe('Specific risks identified'),
|
|
11256
|
-
// legitimacy_signals: z.array(z.string()).describe('Signals of legitimate communication'),
|
|
11257
|
-
|
|
11258
|
-
// // Metadata
|
|
11259
|
-
// analysis_timestamp: z.string(),
|
|
11260
|
-
// content_length: z.number().describe('Length of email body analyzed'),
|
|
11261
|
-
// analysis_complexity: z.enum(['simple', 'moderate', 'complex', 'ambiguous']),
|
|
11262
|
-
// }),
|
|
11263
|
-
// metadata: {
|
|
11264
|
-
// func: 'detect_email_type',
|
|
11265
|
-
// sender_name: name,
|
|
11266
|
-
// sender_email: email,
|
|
11267
|
-
// subject_length: email_subject?.length || 0,
|
|
11268
|
-
// body_length: email_body?.length || 0,
|
|
11269
|
-
// body_preview_hash: await hashString(email_body.substring(0, 200)),
|
|
11270
|
-
// },
|
|
11271
|
-
// account_profile_info,
|
|
11272
|
-
// tools: [{ type: 'web_search_preview' }],
|
|
11273
|
-
// });
|
|
11274
|
-
|
|
11275
|
-
// try {
|
|
11276
|
-
// if (detection_ret.code > -1) {
|
|
11277
|
-
// const data = typeof detection_ret.data === 'string' ? JSON.parse(detection_ret.data) : detection_ret.data;
|
|
11278
|
-
|
|
11279
|
-
// // Enhance with additional analysis
|
|
11280
|
-
// const enhancedData = enhanceEmailDetection(data, name, email, email_body, email_subject);
|
|
11281
|
-
|
|
11282
|
-
// return {
|
|
11283
|
-
// success: true,
|
|
11284
|
-
// ...enhancedData,
|
|
11285
|
-
// };
|
|
11286
|
-
// } else {
|
|
11287
|
-
// console.error('Email detection API call failed:', detection_ret);
|
|
11288
|
-
// return getDefaultEmailDetection(name, email, email_body, email_subject);
|
|
11289
|
-
// }
|
|
11290
|
-
// } catch (error) {
|
|
11291
|
-
// console.error('Error in detect_email_type:', error);
|
|
11292
|
-
// return getDefaultEmailDetection(name, email, email_body, email_subject, error.message);
|
|
11293
|
-
// }
|
|
11294
|
-
// };
|
|
11295
|
-
|
|
11296
8613
|
export const get_business_info = async function (uid, name, email, account_profile_info, options = {}) {
|
|
11297
8614
|
// ========== HELPER FUNCTIONS ==========
|
|
11298
8615
|
|