2025-05-06 11:49:45 +00:00
const { default : makeWASocket , useMultiFileAuthState , DisconnectReason , fetchLatestBaileysVersion , proto , generateWAMessageFromContent , generateWAMessageContent } = require ( '@fizzxydev/baileys-pro' ) ;
2025-05-06 10:19:47 +00:00
const express = require ( 'express' ) ;
const { Boom } = require ( '@hapi/boom' ) ;
const qrcode = require ( 'qrcode' ) ;
const path = require ( 'path' ) ;
const fs = require ( 'fs' ) ;
2025-05-06 10:12:55 +00:00
2025-05-06 08:51:13 +00:00
const app = express ( ) ;
app . use ( express . json ( ) ) ;
2025-05-06 10:12:55 +00:00
app . use ( express . static ( 'public' ) ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 10:12:55 +00:00
let sock ;
let qrData = null ;
let isConnected = false ;
2025-05-06 08:51:13 +00:00
2025-05-06 10:12:55 +00:00
const initBaileys = async ( ) => {
const { version } = await fetchLatestBaileysVersion ( ) ;
const { state , saveCreds } = await useMultiFileAuthState ( 'auth' ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 10:12:55 +00:00
sock = makeWASocket ( {
version ,
auth : state ,
printQRInTerminal : false
} ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 10:12:55 +00:00
sock . ev . on ( 'connection.update' , async ( update ) => {
const { connection , lastDisconnect , qr } = update ;
if ( qr ) {
qrData = await qrcode . toDataURL ( qr ) ;
isConnected = false ;
}
if ( connection === 'close' ) {
const shouldReconnect = lastDisconnect ? . error ? . output ? . statusCode !== DisconnectReason . loggedOut ;
if ( shouldReconnect ) {
console . log ( '🔁 Reconnexion...' ) ;
initBaileys ( ) ;
} else {
console . log ( '❌ Déconnecté.' ) ;
}
} else if ( connection === 'open' ) {
console . log ( '✅ Connecté à WhatsApp' ) ;
isConnected = true ;
}
} ) ;
sock . ev . on ( 'creds.update' , saveCreds ) ;
} ;
2025-05-06 08:51:13 +00:00
2025-05-06 10:35:09 +00:00
async function generateMediaMessage ( sock , type , url ) {
const generated = await generateWAMessageContent (
{ [ type ] : { url } } ,
{ upload : sock . waUploadToServer }
) ;
return generated [ ` ${ type } Message ` ] ;
}
async function sendInteractive ( sock , jid , imageUrl ) {
const imageMsg = await generateMediaMessage ( sock , 'image' , imageUrl ) ;
const content = {
viewOnceMessage : {
message : {
messageContextInfo : {
deviceListMetadata : { } ,
deviceListMetadataVersion : 2 ,
} ,
interactiveMessage : proto . Message . InteractiveMessage . create ( {
body : { text : 'Quel produit vous intéresse ?' } ,
footer : { text : 'Répondez via un bouton' } ,
header : {
title : 'Menu produits' ,
hasMediaAttachment : true ,
imageMessage : imageMsg ,
} ,
nativeFlowMessage : {
buttons : [
{
name : 'quick_reply' ,
buttonParamsJson : JSON . stringify ( {
display _text : '📦 Voir produits' ,
id : '.produits' ,
} ) ,
} ,
{
name : 'ctl_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : '🛒 Visiter boutique' ,
url : 'https://canguidev.fr' ,
merchant _url : 'https://canguidev.fr' ,
} ) ,
} ,
] ,
} ,
} ) ,
} ,
} ,
} ;
const msg = generateWAMessageFromContent ( jid , content , { } ) ;
await sock . relayMessage ( jid , msg . message , { messageId : msg . key . id } ) ;
}
2025-05-06 10:12:55 +00:00
initBaileys ( ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 09:54:23 +00:00
app . get ( '/login' , ( req , res ) => {
res . sendFile ( path . join ( _ _dirname , 'public' , 'login.html' ) ) ;
} ) ;
2025-05-06 10:12:55 +00:00
2025-05-06 09:54:23 +00:00
app . get ( '/api/qrcode' , ( req , res ) => {
2025-05-06 10:12:55 +00:00
res . json ( { qr : qrData , connected : isConnected } ) ;
2025-05-06 08:51:13 +00:00
} ) ;
2025-05-06 09:38:23 +00:00
app . post ( '/sendText' , async ( req , res ) => {
const { phone , message } = req . body ;
2025-05-06 10:12:55 +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 10:12:55 +00:00
await sock . sendMessage ( ` ${ phone } @s.whatsapp.net ` , { text : message } ) ;
2025-05-06 09:38:23 +00:00
res . json ( { success : true } ) ;
2025-05-06 09:54:23 +00:00
} catch ( e ) {
res . status ( 500 ) . json ( { error : e . message } ) ;
2025-05-06 09:38:23 +00:00
}
} ) ;
2025-05-06 09:43:48 +00:00
2025-05-06 09:54:23 +00:00
app . post ( '/sendButtons' , async ( req , res ) => {
2025-05-06 11:53:28 +00:00
const { phone } = req . body ;
if ( ! sock || ! isConnected ) return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
2025-05-06 12:00:21 +00:00
2025-05-06 11:53:28 +00:00
try {
2025-05-06 12:00:21 +00:00
const content = {
2025-05-06 12:08:18 +00:00
viewOnceMessage : {
message : {
messageContextInfo : {
deviceListMetadata : { } ,
deviceListMetadataVersion : 2
2025-05-06 11:53:28 +00:00
} ,
2025-05-06 12:08:18 +00:00
interactiveMessage : proto . Message . InteractiveMessage . create ( {
body : { text : "Bienvenue sur notre service !" } ,
footer : { text : "Choisis une action ci-dessous" } ,
header : {
title : "Menu principal" ,
hasMediaAttachment : false
} ,
nativeFlowMessage : {
buttons : [
{
2025-05-06 12:09:49 +00:00
"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\"}]}]}"
2025-05-06 12:08:18 +00:00
} ,
{
2025-05-06 12:09:49 +00:00
"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\"}"
} ,
2025-05-06 12:08:18 +00:00
{
2025-05-06 12:09:49 +00:00
"name" : "send_location" ,
"buttonParamsJson" : ""
2025-05-06 12:08:18 +00:00
}
2025-05-06 12:09:49 +00:00
] ,
2025-05-06 12:08:18 +00:00
}
} )
}
2025-05-06 12:00:21 +00:00
}
} ;
2025-05-06 12:08:18 +00:00
2025-05-06 12:00:21 +00:00
const msg = generateWAMessageFromContent ( ` ${ phone } @s.whatsapp.net ` , content , { } ) ;
await sock . relayMessage ( ` ${ phone } @s.whatsapp.net ` , msg . message , { messageId : msg . key . id } ) ;
2025-05-06 11:53:28 +00:00
res . json ( { success : true } ) ;
} catch ( e ) {
2025-05-06 12:02:30 +00:00
console . error ( '❌ Erreur bouton actif :' , e ) ;
2025-05-06 11:53:28 +00:00
res . status ( 500 ) . json ( { error : e . message } ) ;
}
2025-05-06 09:43:48 +00:00
} ) ;
2025-05-06 08:51:13 +00:00
2025-05-06 12:17:18 +00:00
app . post ( '/sendInteractiveImage' , async ( req , res ) => {
const { phone } = req . body ;
if ( ! sock || ! isConnected ) return res . status ( 400 ) . json ( { error : 'Non connecté' } ) ;
try {
await sock . sendMessage ( ` ${ phone } @s.whatsapp.net ` , {
2025-05-06 12:18:54 +00:00
image : { url : 'https://merlo-ch.com/assets/images/site/logo-fond-blanc.svg' } ,
2025-05-06 12:17:18 +00:00
caption : 'Description Of Messages' ,
title : 'Title Of Messages' ,
subtitle : 'Subtile Message' ,
footer : 'Footer Messages' ,
media : true ,
interactiveButtons : [
{
name : 'quick_reply' ,
buttonParamsJson : JSON . stringify ( {
display _text : 'Display Button' ,
id : 'ID'
} )
} ,
{
name : 'cta_url' ,
buttonParamsJson : JSON . stringify ( {
display _text : 'Display Button' ,
url : 'https://www.google.com'
} )
}
]
} ) ;
res . json ( { success : true } ) ;
} catch ( e ) {
console . error ( '❌ Erreur interactive image :' , e ) ;
res . status ( 500 ) . json ( { error : e . message } ) ;
}
} ) ;
2025-05-06 10:16:50 +00:00
app . listen ( 3001 , ( ) => console . log ( '🚀 Serveur Baileys démarré sur http://localhost:3001' ) ) ;