Configurcion de personalidad
This commit is contained in:
@@ -10,6 +10,7 @@ import makeWASocket, {
|
||||
fetchLatestBaileysVersion,
|
||||
WASocket,
|
||||
downloadMediaMessage,
|
||||
normalizeMessageContent,
|
||||
} from "@whiskeysockets/baileys";
|
||||
import { Boom } from "@hapi/boom";
|
||||
import * as path from "path";
|
||||
@@ -19,6 +20,7 @@ import { LeadsService } from "../leads/leads.service";
|
||||
import { ConversacionService } from "../conversacion/conversacion.service";
|
||||
import { ClaudeService } from "../claude/claude.service";
|
||||
import { MediaService } from "../media/media.service";
|
||||
import { WhatsappDebounceService } from "./whatsapp-debounce.service";
|
||||
import { wrapSocket } from "baileys-antiban";
|
||||
|
||||
const ESTADOS_TERMINALES = [
|
||||
@@ -34,12 +36,15 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
|
||||
private readonly logger = new Logger(WhatsappService.name);
|
||||
private sock: WASocket | null = null;
|
||||
private authDir = path.join(process.cwd(), "auth_info_baileys");
|
||||
private readonly ultimoMsgPorJid = new Map<string, any>();
|
||||
private baileysLogger = pino({ level: "info" });
|
||||
|
||||
constructor(
|
||||
private readonly leadsService: LeadsService,
|
||||
private readonly conversacionService: ConversacionService,
|
||||
private readonly claudeService: ClaudeService,
|
||||
private readonly mediaService: MediaService,
|
||||
private readonly debounceService: WhatsappDebounceService,
|
||||
) {}
|
||||
|
||||
async onModuleInit() {
|
||||
@@ -71,11 +76,13 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
|
||||
const { state, saveCreds } = await useMultiFileAuthState(this.authDir);
|
||||
const { version } = await fetchLatestBaileysVersion();
|
||||
|
||||
this.baileysLogger = pino({ level: "info" }) as any;
|
||||
|
||||
this.sock = makeWASocket({
|
||||
version,
|
||||
auth: state,
|
||||
printQRInTerminal: false,
|
||||
logger: pino({ level: "info" }) as any,
|
||||
logger: this.baileysLogger,
|
||||
markOnlineOnConnect: false,
|
||||
generateHighQualityLinkPreview: false,
|
||||
syncFullHistory: false,
|
||||
@@ -132,11 +139,49 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.procesarMensaje(msg);
|
||||
await this.encolarMensaje(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private extraerTextoPlano(msg: any): string | null {
|
||||
const msgContent = msg.message;
|
||||
if (!msgContent) return null;
|
||||
|
||||
if (msgContent.conversation || msgContent.extendedTextMessage) {
|
||||
const texto =
|
||||
msgContent.conversation || msgContent.extendedTextMessage?.text || "";
|
||||
return texto.trim() ? texto : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private crearMsgConTexto(msg: any, texto: string): any {
|
||||
return {
|
||||
...msg,
|
||||
message: { conversation: texto },
|
||||
};
|
||||
}
|
||||
|
||||
private async encolarMensaje(msg: any): Promise<void> {
|
||||
const jid = msg.key.remoteJid!;
|
||||
const textoPlano = this.extraerTextoPlano(msg);
|
||||
|
||||
if (textoPlano === null) {
|
||||
await this.procesarMensaje(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.ultimoMsgPorJid.set(jid, msg);
|
||||
|
||||
await this.debounceService.add(jid, textoPlano, async (combinedMessage) => {
|
||||
const baseMsg = this.ultimoMsgPorJid.get(jid) ?? msg;
|
||||
this.ultimoMsgPorJid.delete(jid);
|
||||
await this.procesarMensaje(this.crearMsgConTexto(baseMsg, combinedMessage));
|
||||
});
|
||||
}
|
||||
|
||||
private async procesarMensaje(msg: any): Promise<void> {
|
||||
const jid = msg.key.remoteJid!;
|
||||
|
||||
@@ -155,7 +200,7 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
|
||||
}
|
||||
|
||||
let textoNormalizado = "";
|
||||
const msgContent = msg.message;
|
||||
const msgContent = normalizeMessageContent(msg.message);
|
||||
|
||||
if (!msgContent) return;
|
||||
|
||||
@@ -163,24 +208,62 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
|
||||
textoNormalizado =
|
||||
msgContent.conversation || msgContent.extendedTextMessage?.text || "";
|
||||
} else if (msgContent.audioMessage) {
|
||||
const audioMeta = msgContent.audioMessage;
|
||||
const mimeType = audioMeta.mimetype || "audio/ogg; codecs=opus";
|
||||
|
||||
this.logger.log(
|
||||
`Audio recibido de lead id=${lead.id}. Transcribiendo...`,
|
||||
`[AUDIO 1/4] Recibido — lead=${lead.id}, ptt=${audioMeta.ptt ?? false}, seconds=${audioMeta.seconds ?? "?"}, mimetype=${mimeType}, fileLength=${audioMeta.fileLength ?? "?"}, url=${audioMeta.url ? "si" : "no"}`,
|
||||
);
|
||||
const buffer = await downloadMediaMessage(msg as any, "buffer", {});
|
||||
const mimeType =
|
||||
msgContent.audioMessage.mimetype || "audio/ogg; codecs=opus";
|
||||
|
||||
if (!this.sock) {
|
||||
this.logger.error("[AUDIO 1/4] Socket no disponible para descargar audio");
|
||||
return;
|
||||
}
|
||||
|
||||
const buffer = await downloadMediaMessage(
|
||||
msg as any,
|
||||
"buffer",
|
||||
{},
|
||||
{
|
||||
logger: this.baileysLogger,
|
||||
reuploadRequest: this.sock.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
|
||||
const audioBuffer = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
|
||||
const magicHex = audioBuffer.subarray(0, 4).toString("hex");
|
||||
|
||||
this.logger.log(
|
||||
`[AUDIO 1/4] Buffer descargado — size=${audioBuffer.length} bytes, magic_hex=${magicHex}, esperado_ogg=4f676753`,
|
||||
);
|
||||
|
||||
textoNormalizado = await this.mediaService.transcribirAudio(
|
||||
buffer as Buffer,
|
||||
audioBuffer,
|
||||
mimeType,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`[AUDIO 1/4] Transcripcion recibida en procesarMensaje — "${textoNormalizado.slice(0, 200).replace(/\n/g, "\\n")}"`,
|
||||
);
|
||||
} else if (msgContent.imageMessage) {
|
||||
this.logger.log(
|
||||
`Imagen recibida de lead id=${lead.id}. Analizando con Vision...`,
|
||||
);
|
||||
const buffer = await downloadMediaMessage(msg as any, "buffer", {});
|
||||
|
||||
if (!this.sock) return;
|
||||
|
||||
const buffer = await downloadMediaMessage(
|
||||
msg as any,
|
||||
"buffer",
|
||||
{},
|
||||
{
|
||||
logger: this.baileysLogger,
|
||||
reuploadRequest: this.sock.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
const mimeType = msgContent.imageMessage.mimetype || "image/jpeg";
|
||||
textoNormalizado = await this.mediaService.inferirImagen(
|
||||
buffer as Buffer,
|
||||
Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer),
|
||||
mimeType,
|
||||
lead.estado_actual,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user