112 lines
3.6 KiB
TypeScript
Executable File
112 lines
3.6 KiB
TypeScript
Executable File
/**
|
|
* geminiService.ts
|
|
*
|
|
* @author Descomplicar® Crescimento Digital
|
|
* @link https://descomplicar.pt
|
|
* @copyright 2025 Descomplicar®
|
|
*/
|
|
|
|
import { GoogleGenAI, Type } from "@google/genai";
|
|
import type { Email, ClassifiedCategory, CategorizedEmails } from "../types";
|
|
import { EmailCategory } from "../types";
|
|
|
|
const MOCKED_RESPONSE: ClassifiedCategory[] = [
|
|
{
|
|
category: EmailCategory.PROMOTIONS,
|
|
summary: "Ofertas especiais e descontos de várias lojas online.",
|
|
email_ids: [2, 5, 8, 11]
|
|
},
|
|
{
|
|
category: EmailCategory.NOTIFICATIONS,
|
|
summary: "Alertas de login, atualizações de projetos e menções em redes sociais.",
|
|
email_ids: [1, 4, 7, 10, 13]
|
|
},
|
|
{
|
|
category: EmailCategory.NEWSLETTERS,
|
|
summary: "Boletins informativos de tecnologia, design e notícias gerais.",
|
|
email_ids: [3, 6, 9, 12, 14]
|
|
}
|
|
];
|
|
|
|
const processApiResponse = (
|
|
response: ClassifiedCategory[],
|
|
allEmails: Email[]
|
|
): CategorizedEmails => {
|
|
const categorized: CategorizedEmails = {};
|
|
|
|
for (const item of response) {
|
|
const categoryKey = item.category;
|
|
|
|
if (categoryKey !== EmailCategory.IMPORTANT && categoryKey !== EmailCategory.UNKNOWN) {
|
|
const emailsInCategory = item.email_ids.map(id =>
|
|
allEmails.find(email => email.id === id)
|
|
).filter((email): email is Email => email !== undefined);
|
|
|
|
if(emailsInCategory.length > 0) {
|
|
if (!categorized[categoryKey]) {
|
|
categorized[categoryKey] = { summary: item.summary, emails: [] };
|
|
}
|
|
categorized[categoryKey].summary = item.summary;
|
|
categorized[categoryKey].emails.push(...emailsInCategory);
|
|
}
|
|
}
|
|
}
|
|
|
|
return categorized;
|
|
};
|
|
|
|
export const classifyEmails = async (emails: Email[], apiKey: string): Promise<CategorizedEmails> => {
|
|
if (!apiKey) {
|
|
console.warn("API_KEY for Gemini is not provided. Using mocked data.");
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
return processApiResponse(MOCKED_RESPONSE, emails);
|
|
}
|
|
|
|
const ai = new GoogleGenAI({ apiKey });
|
|
|
|
const emailPromptData = emails.map(e => ({
|
|
id: e.id,
|
|
from: e.sender,
|
|
subject: e.subject,
|
|
snippet: e.snippet
|
|
}));
|
|
|
|
|
|
const prompt = `
|
|
Você é um especialista em organização de e-mails. Analise a seguinte lista de e-mails em formato JSON.
|
|
1. Categorize cada e-mail em uma das seguintes categorias base: ${Object.values(EmailCategory).join(', ')}.
|
|
2. Agrupe os e-mails por categoria. Para cada categoria, forneça um breve resumo em português do conteúdo e uma lista dos IDs dos e-mails correspondentes.
|
|
3. NÃO inclua a categoria 'IMPORTANTE' no resultado final.
|
|
|
|
Aqui está a lista de e-mails:
|
|
${JSON.stringify(emailPromptData, null, 2)}
|
|
`;
|
|
|
|
try {
|
|
const response = await ai.models.generateContent({
|
|
model: "gemini-2.5-flash",
|
|
contents: prompt,
|
|
config: {
|
|
responseMimeType: "application/json",
|
|
responseSchema: {
|
|
type: Type.ARRAY,
|
|
items: {
|
|
type: Type.OBJECT,
|
|
properties: {
|
|
category: { type: Type.STRING },
|
|
summary: { type: Type.STRING },
|
|
email_ids: { type: Type.ARRAY, items: { type: Type.INTEGER } }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
const classifiedData = JSON.parse(response.text);
|
|
return processApiResponse(classifiedData, emails);
|
|
|
|
} catch (error) {
|
|
console.error("Error calling Gemini API:", error);
|
|
throw new Error("Failed to classify emails with Gemini API.");
|
|
}
|
|
}; |