2025-05-06 14:04:11 +00:00
const express = require ( 'express' ) ;
const qrcode = require ( 'qrcode' ) ;
2025-05-06 20:25:52 +00:00
const path = require ( 'path' ) ;
const fs = require ( 'fs' ) ;
const NodeCache = require ( 'node-cache' ) ;
2025-05-06 19:25:43 +00:00
const {
2025-05-06 20:21:45 +00:00
default : makeWASocket ,
2025-05-06 19:25:43 +00:00
useMultiFileAuthState ,
DisconnectReason ,
fetchLatestBaileysVersion ,
2025-05-06 20:25:52 +00:00
proto ,
generateWAMessageFromContent
} = require ( '@fizzxydev/baileys-pro' ) ;
2025-05-06 20:12:39 +00:00
2025-05-06 14:04:11 +00:00
const app = express ( ) ;
app . use ( express . json ( ) ) ;
2025-05-06 20:24:10 +00:00
app . use ( express . static ( 'public' ) ) ;
2025-05-06 18:21:47 +00:00
let sock ;
2025-05-06 20:25:52 +00:00
let qrData = null ;
2025-05-06 14:04:11 +00:00
let isConnected = false ;
2025-05-06 08:51:13 +00:00
2025-05-06 20:25:52 +00:00
// 💾 Group Metadata Cache (5 minutes)
const groupCache = new NodeCache ( { stdTTL : 300 , useClones : false } ) ;
// Simule une récupération de message depuis un store pour getMessage
async function getMessageFromStore ( key ) {
// À adapter selon ta logique réelle
return { conversation : "Message temporaire pour retry" } ;
}
const initBaileys = async ( ) => {
2025-05-06 18:21:47 +00:00
const { version } = await fetchLatestBaileysVersion ( ) ;
2025-05-06 20:25:52 +00:00
const { state , saveCreds } = await useMultiFileAuthState ( 'auth' ) ;
2025-05-06 18:21:47 +00:00
sock = makeWASocket ( {
version ,
auth : state ,
2025-05-06 20:25:52 +00:00
markOnlineOnConnect : false ,
getMessage : async ( key ) => await getMessageFromStore ( key ) ,
cachedGroupMetadata : async ( jid ) => groupCache . get ( jid )
2025-05-06 14:04:11 +00:00
} ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 19:25:43 +00:00
sock . ev . on ( 'connection.update' , async ( { connection , lastDisconnect , qr } ) => {
2025-05-06 18:21:47 +00:00
if ( qr ) {
2025-05-06 20:25:52 +00:00
qrData = await qrcode . toDataURL ( qr ) ;
isConnected = false ;
2025-05-06 18:21:47 +00:00
}
2025-05-06 19:25:43 +00:00
2025-05-06 18:21:47 +00:00
if ( connection === 'close' ) {
2025-05-06 20:25:52 +00:00
const shouldReconnect = lastDisconnect ? . error ? . output ? . statusCode !== DisconnectReason . loggedOut ;
console . log ( shouldReconnect ? '🔁 Reconnexion...' : '❌ Déconnecté.' ) ;
if ( shouldReconnect ) initBaileys ( ) ;
2025-05-06 18:21:47 +00:00
} else if ( connection === 'open' ) {
console . log ( '✅ Connecté à WhatsApp' ) ;
isConnected = true ;
2025-05-06 10:12:55 +00:00
}
2025-05-06 14:04:11 +00:00
} ) ;
2025-05-06 10:12:55 +00:00
2025-05-06 18:21:47 +00:00
sock . ev . on ( 'creds.update' , saveCreds ) ;
2025-05-06 19:25:43 +00:00
2025-05-06 20:25:52 +00:00
// 📌 Caching des groupes
sock . ev . on ( 'groups.update' , async ( [ event ] ) => {
const metadata = await sock . groupMetadata ( event . id ) ;
groupCache . set ( event . id , metadata ) ;
} ) ;
sock . ev . on ( 'group-participants.update' , async ( event ) => {
const metadata = await sock . groupMetadata ( event . id ) ;
groupCache . set ( event . id , metadata ) ;
} ) ;
// (Facultatif) Gestion des messages reçus
sock . ev . on ( 'messages.upsert' , async ( { messages } ) => {
const msg = messages [ 0 ] ;
2025-05-07 05:19:18 +00:00
2025-05-06 20:25:52 +00:00
if ( ! msg . key . fromMe && msg . message ? . conversation ) {
console . log ( '💬 Message reçu de' , msg . key . remoteJid , ':' , msg . message . conversation ) ;
}
2025-05-07 05:19:18 +00:00
if ( ! msg . message || ! msg . key . fromMe ) {
const jid = msg . key . remoteJid ;
const buttonId = msg . message . buttonsResponseMessage ? . selectedButtonId ;
if ( buttonId === 'doc_1' ) {
await sock . sendMessage ( jid , {
document : {
2025-05-07 05:34:09 +00:00
url : 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf' ,
2025-05-07 05:19:18 +00:00
} ,
mimetype : 'application/pdf' ,
fileName : 'Document_1.pdf' ,
caption : 'Voici votre *Document 1* 📄' ,
footer : '© Fizzxy Dev' ,
} ) ;
} else if ( buttonId === 'doc_2' ) {
await sock . sendMessage ( jid , {
document : {
2025-05-07 05:34:09 +00:00
url : 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf' ,
2025-05-07 05:19:18 +00:00
} ,
mimetype : 'application/pdf' ,
fileName : 'Document_2.pdf' ,
caption : 'Voici votre *Document 2* 📄' ,
footer : '© Fizzxy Dev' ,
} ) ;
}
2025-05-07 05:16:23 +00:00
}
2025-05-06 20:25:52 +00:00
} ) ;
} ;
initBaileys ( ) ;
app . use ( '/static' , express . static ( path . join ( _ _dirname , 'public' ) ) ) ;
app . get ( '/login' , ( req , res ) => {
res . sendFile ( path . join ( _ _dirname , 'public' , 'login.html' ) ) ;
} ) ;
2025-05-06 09:54:23 +00:00
app . get ( '/api/qrcode' , ( req , res ) => {
2025-05-06 20:25:52 +00:00
res . json ( { qr : qrData , connected : isConnected } ) ;
2025-05-06 14:04:11 +00:00
} ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 09:38:23 +00:00
app . post ( '/sendText' , async ( req , res ) => {
2025-05-06 14:04:11 +00:00
const { phone , message } = req . body ;
2025-05-06 18:21:47 +00:00
if ( ! sock || ! isConnected ) return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
2025-05-06 09:38:23 +00:00
try {
2025-05-06 18:21:47 +00:00
await sock . sendMessage ( ` ${ phone } @s.whatsapp.net ` , { text : message } ) ;
2025-05-06 14:04:11 +00:00
res . json ( { success : true } ) ;
2025-05-06 09:54:23 +00:00
} catch ( e ) {
2025-05-06 14:04:11 +00:00
res . status ( 500 ) . json ( { error : e . message } ) ;
2025-05-06 09:38:23 +00:00
}
2025-05-06 14:04:11 +00:00
} ) ;
2025-05-06 20:25:52 +00:00
app . post ( '/testButtons' , async ( req , res ) => {
const { phone } = req . body ;
2025-05-06 09:43:48 +00:00
2025-05-06 20:25:52 +00:00
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
2025-05-06 11:53:28 +00:00
}
2025-05-06 19:14:46 +00:00
2025-05-06 20:25:52 +00:00
const jid = ` ${ phone } @s.whatsapp.net ` ;
2025-05-06 20:21:45 +00:00
try {
2025-05-06 20:25:52 +00:00
await sock . sendMessage ( jid , {
image : { url : "https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg" } , // Can buffer
text : "Hello Wolrd !;" ,
caption : "Description Of Messages" , //Additional information
footer : "© Fizzxy Dev" ,
media : true ,
image : {
url : 'https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg'
} ,
buttons : [
{
buttonId : '.tes' ,
buttonText : {
displayText : 'TESTING BOT'
} ,
type : 1
} ,
{
buttonId : ' ' ,
buttonText : {
displayText : 'PRIVATE SCRIPT'
} ,
type : 1
} ,
{
buttonId : 'action' ,
buttonText : {
displayText : 'ini pesan interactiveMeta'
} ,
type : 4 ,
nativeFlowInfo : {
name : 'single_select' ,
paramsJson : JSON . stringify ( {
title : 'message' ,
sections : [
{
title : 'FizzxyDev - 2025' ,
highlight _label : '😜' ,
rows : [
{
header : 'HEADER' ,
title : 'TITLE' ,
description : 'DESCRIPTION' ,
id : 'YOUR ID 1'
} ,
{
header : 'HEADER' ,
title : 'TITLE' ,
description : 'DESCRIPTION' ,
id : 'YOUR ID 2'
}
]
}
]
} )
}
}
] ,
headerType : 1 ,
viewOnce : true
} , {
quoted : null // ou tu peux injecter un msg pour reply ici
2025-05-06 20:21:45 +00:00
} ) ;
2025-05-06 20:25:52 +00:00
2025-05-06 20:21:45 +00:00
res . json ( { success : true } ) ;
} catch ( e ) {
2025-05-06 20:25:52 +00:00
console . error ( '❌ Erreur testButtons :' , e ) ;
2025-05-06 20:21:45 +00:00
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-06 20:25:52 +00:00
app . post ( '/sendButtons' , async ( req , res ) => {
2025-05-06 19:51:17 +00:00
const { phone } = req . body ;
2025-05-06 20:25:52 +00:00
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
}
const BASE _URL = process . env . BASE _URL || 'https://wa.canguidev.fr' ;
const imageUrl = ` ${ BASE _URL } /static/logo-merlo-cs-FR.jpg ` ;
const jid = ` ${ phone } @s.whatsapp.net ` ;
2025-05-06 20:21:45 +00:00
try {
const content = {
viewOnceMessage : {
message : {
messageContextInfo : {
deviceListMetadata : { } ,
deviceListMetadataVersion : 2
2025-05-06 19:54:47 +00:00
} ,
2025-05-06 20:21:45 +00:00
interactiveMessage : proto . Message . InteractiveMessage . create ( {
2025-05-06 20:25:52 +00:00
body : { text : "Bienvenue sur notre service !" } ,
footer : { text : "Choisis une action ci-dessous" } ,
header : {
hasMediaAttachment : true ,
imageMessage : { url : imageUrl }
} ,
2025-05-06 20:21:45 +00:00
nativeFlowMessage : {
buttons : [
{
2025-05-06 20:25:52 +00:00
name : "cta_reply" ,
buttonParamsJson : JSON . stringify ( {
display _text : "📩 Contacter support" ,
id : "support_action"
} )
} ,
{
name : "cta_url" ,
2025-05-06 20:21:45 +00:00
buttonParamsJson : JSON . stringify ( {
2025-05-06 20:25:52 +00:00
display _text : "🌐 Voir notre site" ,
url : "https://canguidev.fr"
2025-05-06 20:21:45 +00:00
} )
} ,
{
2025-05-06 20:25:52 +00:00
name : "cta_call" ,
2025-05-06 20:21:45 +00:00
buttonParamsJson : JSON . stringify ( {
2025-05-06 20:25:52 +00:00
display _text : "📞 Appeler le support" ,
id : "+33612345678"
2025-05-06 20:21:45 +00:00
} )
}
]
}
} )
}
2025-05-06 19:54:47 +00:00
}
2025-05-06 20:21:45 +00:00
} ;
2025-05-06 20:16:28 +00:00
const msg = generateWAMessageFromContent ( jid , content , { } ) ;
await sock . relayMessage ( jid , msg . message , { messageId : msg . key . id } ) ;
2025-05-06 20:21:45 +00:00
2025-05-06 20:16:28 +00:00
res . json ( { success : true } ) ;
} catch ( e ) {
2025-05-06 20:25:52 +00:00
console . error ( '❌ Erreur bouton actif :' , e ) ;
2025-05-06 20:16:28 +00:00
res . status ( 500 ) . json ( { error : e . message } ) ;
}
2025-05-06 19:54:47 +00:00
} ) ;
2025-05-06 20:25:52 +00:00
// Votre route POST
app . post ( '/sendInteractiveImage' , async ( req , res ) => {
const { phone , caption , title , subtitle , footer } = req . body ;
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté à WhatsApp' } ) ;
}
try {
const BASE _URL = process . env . BASE _URL || 'https://wa.canguidev.fr' ;
const imageUrl = ` ${ BASE _URL } /static/logo-merlo-cs-FR.jpg ` ;
// Construire le Header correct
const header = proto . Message . InteractiveMessage . create ( {
// ici on injecte l'image dans le header sans besoin de type explicite
header : proto . Message . InteractiveMessage . Header . create ( {
title : 'Igna' ,
subtitle : 'test'
} ) ,
} )
// Body et Footer
const body = proto . Message . InteractiveMessage . Body . create ( {
text : caption || 'Description par défaut'
} ) ;
const foot = proto . Message . InteractiveMessage . Footer . create ( {
text : footer || 'Pied de page'
} ) ;
// Vos boutons URL
const nativeFlow = proto . Message . InteractiveMessage . NativeFlowMessage . create ( {
buttons : [
{
name : 'cta_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : '📄 Voir proposition' ,
url : 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf'
} )
} ,
{
name : 'cta_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : '🔧 Spécifications' ,
url : 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf'
} )
}
]
} ) ;
// Construire l'InteractiveMessage complet
const interactiveMsg = proto . Message . InteractiveMessage . create ( {
header ,
body ,
footer : foot ,
nativeFlowMessage : nativeFlow
} ) ;
// Envelopper (ici dans viewOnceMessage, comme dans votre exemple)
const raw = {
viewOnceMessage : {
message : {
messageContextInfo : {
deviceListMetadata : { } ,
deviceListMetadataVersion : 2
} ,
interactiveMessage : interactiveMsg
}
}
} ;
// Générer et relayer
const jid = ` ${ phone } @s.whatsapp.net ` ;
const msg = generateWAMessageFromContent ( jid , raw , { } ) ;
await sock . relayMessage ( jid , msg . message , { messageId : msg . key . id } ) ;
return res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur /sendInteractiveImage :' , e ) ;
return res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-07 06:11:04 +00:00
app . post ( '/sendInteractiveImage2' , async ( req , res ) => {
const { phone , caption , title , subtitle , footer } = req . body ;
if ( ! sock || ! isConnected ) return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
try {
const imagePath = path . join ( _ _dirname , 'public' , 'logo-merlo-cs-FR.jpg' ) ;
const resizedBuffer = fs . readFileSync ( imagePath ) ;
await sock . sendMessage ( ` ${ phone } @s.whatsapp.net ` , {
image : resizedBuffer ,
caption : caption || 'Description par défaut' ,
title : title || 'Titre par défaut' ,
subtitle : subtitle || 'Sous-titre' ,
footer : footer || 'Pied de page' ,
media : true ,
interactiveButtons : [
{
name : 'cta_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : 'Proposition' ,
url : 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf'
} )
} ,
{
name : 'cta_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : 'Spec machine' ,
url : 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf'
} )
}
]
} ) ;
res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur interactive image :' , e ) ;
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-06 20:25:52 +00:00
app . post ( '/sendProductMessage' , async ( req , res ) => {
// On vérifie sock et isConnected, pas client
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté à WhatsApp' } ) ;
}
const {
phone ,
productImageUrl ,
productImageCount ,
productTitle ,
productDescription ,
priceAmount1000 ,
currencyCode ,
retailerId ,
productUrl ,
businessOwnerJid ,
caption ,
messageTitle ,
footer ,
interactiveButtons = [ ] ,
quoted
} = req . body ;
try {
const jid = ` ${ phone } @s.whatsapp.net ` ;
// Build product payload exactly comme avant
const productPayload = {
productImage : { url : productImageUrl } ,
productImageCount ,
title : productTitle , // ici productTitle
description : productDescription ,
priceAmount1000 : priceAmount1000 * 1000 , // ajustez si besoin
currencyCode ,
retailerId ,
url : productUrl
} ;
// Transformer les boutons
const buttons = interactiveButtons . map ( btn => {
const params = { } ;
if ( btn . id ) params . id = btn . id ;
if ( btn . url ) params . url = btn . url ;
if ( btn . display _text ) params . display _text = btn . display _text ;
return {
name : btn . name ,
buttonParamsJson : JSON . stringify ( params )
} ;
} ) ;
// **On utilise sock.sendMessage** et non client.sendMessage
await sock . sendMessage (
jid ,
{
product : productPayload ,
businessOwnerJid ,
caption ,
title : messageTitle ,
footer ,
media : true ,
interactiveButtons : buttons
} ,
quoted ? { quoted } : { }
) ;
return res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur /sendProductMessage :' , e ) ;
return res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
app . post ( '/testProductMessage' , async ( req , res ) => {
const { phone } = req . body ;
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté à WhatsApp' } ) ;
}
const jid = ` ${ phone } @s.whatsapp.net ` ;
try {
await sock . sendMessage (
jid ,
{
product : {
productImage : { url : "https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg" } , // image du produit
productImageCount : 1 ,
title : "Tracteur Merlo TF38.10" ,
description : "Charge maximale 3.8T, hauteur 10m" ,
priceAmount1000 : 49500 * 1000 , // 49 500 €
currencyCode : "EUR" ,
retailerId : "MERLO-FR-001" ,
url : "https://example.com/product/tf38-10"
} ,
businessOwnerJid : "1234@s.whatsapp.net" ,
caption : "🛒 Découvrez notre nouveau modèle Merlo TF38.10" ,
title : "Offre Spéciale Merlo" ,
footer : "MERLO France • Offre valable jusqu'au 30/06" ,
media : true ,
interactiveButtons : [
{
name : "quick_reply" ,
buttonParamsJson : JSON . stringify ( {
display _text : "📩 Demander un devis" ,
id : "request_quote"
} )
} ,
{
name : "cta_url" ,
buttonParamsJson : JSON . stringify ( {
display _text : "🌐 Voir la fiche produit" ,
url : "https://example.com/product/tf38-10"
} )
}
]
} ,
{
quoted : null // ou remplace par un message existant si tu veux répondre à un msg
}
) ;
res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur envoi produit :' , e ) ;
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
app . post ( '/testInteractiveImage' , async ( req , res ) => {
const { phone } = req . body ;
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté à WhatsApp' } ) ;
}
const content = {
viewOnceMessage : {
message : {
messageContextInfo : {
deviceListMetadata : { } ,
deviceListMetadataVersion : 2
} ,
interactiveMessage : proto . Message . InteractiveMessage . create ( {
header : {
hasMediaAttachment : true ,
imageMessage : { url : "https://canguidev.fr/static/logo-merlo-cs-FR.jpg" }
} ,
body : { text : "Bienvenue chez Merlo France 🇫🇷\nChoisissez une action ci-dessous." } ,
footer : { text : "MERLO - Support & Documentation" } ,
nativeFlowMessage : {
buttons : [
{
name : "cta_reply" ,
buttonParamsJson : JSON . stringify ( {
display _text : "📩 Contacter support" ,
id : "support_action"
} )
} ,
{
name : "cta_url" ,
buttonParamsJson : JSON . stringify ( {
display _text : "🌐 Voir la fiche produit" ,
url : "https://example.com/product"
} )
}
]
}
} )
}
}
} ;
const jid = ` ${ phone } @s.whatsapp.net ` ;
const msg = generateWAMessageFromContent ( jid , content , { } ) ;
await sock . relayMessage ( jid , msg . message , { messageId : msg . key . id } ) ;
} ) ;
2025-05-07 05:16:23 +00:00
app . post ( '/testButtons2' , async ( req , res ) => {
const { phone } = req . body ;
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
}
const jid = ` ${ phone } @s.whatsapp.net ` ;
try {
await sock . sendMessage ( jid , {
text : '📚 *Veuillez choisir le document à télécharger :*' ,
footer : '© Fizzxy Dev' ,
buttons : [
{
buttonId : 'doc_1' ,
buttonText : { displayText : 'Télécharger Document 1' } ,
type : 1 ,
} ,
{
buttonId : 'doc_2' ,
buttonText : { displayText : 'Télécharger Document 2' } ,
type : 1 ,
}
] ,
headerType : 1 , // Texte seulement
} ) ;
res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur testButtons :' , e ) ;
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-07 06:00:58 +00:00
app . post ( '/testButtons3' , async ( req , res ) => {
const { phone } = req . body ;
if ( ! sock || ! isConnected ) {
return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
}
const jid = ` ${ phone } @s.whatsapp.net ` ;
2025-05-07 06:06:19 +00:00
let msg = generateWAMessageFromContent ( m . chat , {
viewOnceMessage : {
message : {
"messageContextInfo" : {
"deviceListMetadata" : { } ,
"deviceListMetadataVersion" : 2
} ,
interactiveMessage : proto . Message . InteractiveMessage . create ( {
body : proto . Message . InteractiveMessage . Body . create ( {
text : "Fizzxy Dev"
} ) ,
footer : proto . Message . InteractiveMessage . Footer . create ( {
text : "Bot"
} ) ,
header : proto . Message . InteractiveMessage . Header . create ( {
title : "Igna" ,
subtitle : "test" ,
hasMediaAttachment : false
} ) ,
nativeFlowMessage : proto . Message . InteractiveMessage . NativeFlowMessage . create ( {
buttons : [
{
"name" : "single_select" ,
"buttonParamsJson" : "{\"title\":\"title\",\"sections\":[{\".menu\":\".play dj webito\",\"highlight_label\":\"label\",\"rows\":[{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"},{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"}]}]}"
} ,
{
"name" : "cta_reply" ,
"buttonParamsJson" : "{\"display_text\":\"quick_reply\",\"id\":\"message\"}"
} ,
{
"name" : "cta_url" ,
"buttonParamsJson" : "{\"display_text\":\"url\",\"url\":\"https://www.google.com\",\"merchant_url\":\"https://www.google.com\"}"
} ,
{
"name" : "cta_call" ,
"buttonParamsJson" : "{\"display_text\":\"call\",\"id\":\"message\"}"
} ,
{
"name" : "cta_copy" ,
"buttonParamsJson" : "{\"display_text\":\"copy\",\"id\":\"123456789\",\"copy_code\":\"message\"}"
} ,
{
"name" : "cta_reminder" ,
"buttonParamsJson" : "{\"display_text\":\"Recordatorio\",\"id\":\"message\"}"
} ,
{
"name" : "cta_cancel_reminder" ,
"buttonParamsJson" : "{\"display_text\":\"cta_cancel_reminder\",\"id\":\"message\"}"
} ,
{
"name" : "address_message" ,
"buttonParamsJson" : "{\"display_text\":\"address_message\",\"id\":\"message\"}"
} ,
{
"name" : "send_location" ,
"buttonParamsJson" : ""
}
] ,
} )
} )
}
}
} , { } )
2025-05-07 06:00:58 +00:00
try {
2025-05-07 06:06:19 +00:00
await sock . relayMessage ( msg . key . remoteJid , msg . message , { messageId : msg . key . id } )
2025-05-07 06:00:58 +00:00
res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur testButtons :' , e ) ;
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-07 05:16:23 +00:00
2025-05-06 20:25:52 +00:00
// 5) 404 et gestion des erreurs
app . use ( ( req , res ) => res . status ( 404 ) . json ( { error : 'Ressource introuvable' } ) ) ;
app . use ( ( err , req , res , next ) => {
console . error ( 'Middleware d’ erreur :' , err ) ;
res . status ( 500 ) . json ( { error : err . message } ) ;
2025-05-06 15:34:25 +00:00
} ) ;
2025-05-06 20:25:52 +00:00
app . listen ( 3001 , ( ) => console . log ( '🚀 Serveur Baileys démarré sur http://localhost:3001' ) ) ;