huhuih
hzgjuigik
This commit is contained in:
@@ -234,6 +234,121 @@ export class AISorterService {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate suggested rules based on email patterns
|
||||
* Analyzes email samples to detect patterns and suggest rules
|
||||
*/
|
||||
async generateSuggestedRules(userId, emailSamples) {
|
||||
if (!emailSamples || emailSamples.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const suggestions = []
|
||||
const senderCounts = {}
|
||||
const domainCounts = {}
|
||||
const subjectPatterns = {}
|
||||
const categoryPatterns = {}
|
||||
|
||||
// Analyze patterns
|
||||
for (const email of emailSamples) {
|
||||
const from = email.from?.toLowerCase() || ''
|
||||
const subject = email.subject?.toLowerCase() || ''
|
||||
|
||||
// Extract domain
|
||||
const emailMatch = from.match(/@([^\s>]+)/)
|
||||
if (emailMatch) {
|
||||
const domain = emailMatch[1].toLowerCase()
|
||||
domainCounts[domain] = (domainCounts[domain] || 0) + 1
|
||||
}
|
||||
|
||||
// Count senders
|
||||
const senderEmail = from.split('<')[1]?.split('>')[0] || from
|
||||
senderCounts[senderEmail] = (senderCounts[senderEmail] || 0) + 1
|
||||
|
||||
// Detect category patterns
|
||||
const category = email.category || 'review'
|
||||
categoryPatterns[category] = (categoryPatterns[category] || 0) + 1
|
||||
}
|
||||
|
||||
const totalEmails = emailSamples.length
|
||||
const threshold = Math.max(3, Math.ceil(totalEmails * 0.1)) // At least 3 emails or 10% of total
|
||||
|
||||
// Suggest VIP senders (frequent senders)
|
||||
const frequentSenders = Object.entries(senderCounts)
|
||||
.filter(([_, count]) => count >= threshold)
|
||||
.sort(([_, a], [__, b]) => b - a)
|
||||
.slice(0, 3)
|
||||
|
||||
for (const [sender, count] of frequentSenders) {
|
||||
suggestions.push({
|
||||
type: 'vip_sender',
|
||||
name: `Mark ${sender.split('@')[0]} as VIP`,
|
||||
description: `${count} emails from this sender`,
|
||||
confidence: Math.min(0.9, count / totalEmails),
|
||||
action: {
|
||||
type: 'add_vip',
|
||||
email: sender,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Suggest company labels (frequent domains)
|
||||
const frequentDomains = Object.entries(domainCounts)
|
||||
.filter(([domain, count]) => count >= threshold && !KNOWN_COMPANIES[domain])
|
||||
.sort(([_, a], [__, b]) => b - a)
|
||||
.slice(0, 3)
|
||||
|
||||
for (const [domain, count] of frequentDomains) {
|
||||
const companyName = domain.split('.')[0].charAt(0).toUpperCase() + domain.split('.')[0].slice(1)
|
||||
suggestions.push({
|
||||
type: 'company_label',
|
||||
name: `Label ${companyName} emails`,
|
||||
description: `${count} emails from ${domain}`,
|
||||
confidence: Math.min(0.85, count / totalEmails),
|
||||
action: {
|
||||
type: 'add_company_label',
|
||||
name: companyName,
|
||||
condition: `from:${domain}`,
|
||||
category: 'promotions', // Default, user can change
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Suggest category-specific rules based on patterns
|
||||
if (categoryPatterns.newsletters >= threshold) {
|
||||
suggestions.push({
|
||||
type: 'category_rule',
|
||||
name: 'Archive newsletters automatically',
|
||||
description: `${categoryPatterns.newsletters} newsletter emails detected`,
|
||||
confidence: 0.8,
|
||||
action: {
|
||||
type: 'enable_category',
|
||||
category: 'newsletters',
|
||||
action: 'archive_read',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (categoryPatterns.promotions >= threshold) {
|
||||
suggestions.push({
|
||||
type: 'category_rule',
|
||||
name: 'Archive promotions automatically',
|
||||
description: `${categoryPatterns.promotions} promotion emails detected`,
|
||||
confidence: 0.75,
|
||||
action: {
|
||||
type: 'enable_category',
|
||||
category: 'promotions',
|
||||
action: 'archive_read',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Sort by confidence and return top 5
|
||||
return suggestions
|
||||
.sort((a, b) => b.confidence - a.confidence)
|
||||
.slice(0, 5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if email matches a company label condition
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user