const { default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, proto, generateWAMessageFromContent, generateWAMessageContent ,prepareWAMessageMedia} = require('@fizzxydev/baileys-pro'); const express = require('express'); const { Boom } = require('@hapi/boom'); const qrcode = require('qrcode'); const path = require('path'); const fs = require('fs'); const app = express(); app.use(express.json()); app.use(express.static('public')); let sock; let qrData = null; let isConnected = false; const initBaileys = async () => { const { version } = await fetchLatestBaileysVersion(); const { state, saveCreds } = await useMultiFileAuthState('auth'); sock = makeWASocket({ version, auth: state, printQRInTerminal: false }); 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); }; initBaileys(); app.use('/static', express.static(path.join(__dirname, 'public'))); app.get('/login', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'login.html')); }); app.get('/api/qrcode', (req, res) => { res.json({ qr: qrData, connected: isConnected }); }); app.post('/sendText', async (req, res) => { const { phone, message } = req.body; if (!sock || !isConnected) return res.status(400).json({ error: 'Non connectĂ©' }); try { await sock.sendMessage(`${phone}@s.whatsapp.net`, { text: message }); res.json({ success: true }); } catch (e) { res.status(500).json({ error: e.message }); } }); app.post('/sendButtons', async (req, res) => { const { phone } = req.body; if (!sock || !isConnected) return res.status(400).json({ error: 'Non connectĂ©' }); try { const content = { message: { 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: [ { name: "cta_reply", buttonParamsJson: JSON.stringify({ display_text: "đŸ“© Contacter support", id: "support_action" }) }, { name: "cta_url", buttonParamsJson: JSON.stringify({ display_text: "🌐 Voir notre site", url: "https://canguidev.fr", merchant_url: "https://canguidev.fr" }) }, { name: "cta_call", buttonParamsJson: JSON.stringify({ display_text: "📞 Appeler le support", id: "+33612345678" }) } ] } }) } }; const msg = generateWAMessageFromContent(`${phone}@s.whatsapp.net`, content, {}); await sock.relayMessage(`${phone}@s.whatsapp.net`, msg.message, { messageId: msg.key.id }); res.json({ success: true }); } catch (e) { console.error('❌ Erreur bouton actif :', e); res.status(500).json({ error: e.message }); } }); // Votre route POST app.post('/sendInteractiveImage', async (req, res) => { const { phone, caption, footer } = req.body; if (!sock || !isConnected) { return res.status(400).json({ error: 'Non connectĂ© Ă  WhatsApp' }); } try { // 1) URL publique de votre image const BASE_URL = process.env.BASE_URL || 'https://wa.canguidev.fr'; const imageUrl = `${BASE_URL}/static/logo-merlo-cs-FR.jpg`; console.log(imageUrl); // 2) Contenu brut du message interactif const rawMessage = { viewOnceMessage: { message: { messageContextInfo: { deviceListMetadata: {}, deviceListMetadataVersion: 2 }, interactiveMessage: proto.Message.InteractiveMessage.create({ header: proto.Message.InteractiveMessage.Header.create({ // On donne simplement l'URL, Baileys s'en charge imageMessage: { url: imageUrl }, title: 'Igna', // facultatif subtitle: 'test' , // facultatif }), body: proto.Message.InteractiveMessage.Body.create({ text: caption || 'Description par dĂ©faut' }), footer: proto.Message.InteractiveMessage.Footer.create({ text: footer || 'Pied de page' }), // Ici on utilise nativeFlowMessage plutĂŽt que `action` ou `buttons` nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({ buttons: [ // bouton URL “Proposition” { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: '📄 Voir proposition', url: 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf' }) }, // bouton URL “SpĂ©cifications” { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: '🔧 SpĂ©cifications', url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf' }) } ] }) }) } } }; // 3) GĂ©nĂ©rer et envoyer const jid = `${phone}@s.whatsapp.net`; const msg = generateWAMessageFromContent(jid, rawMessage, {}); 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 }); } }); // 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Ă©' }); // 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 }); // } // }); app.listen(3001, () => console.log('🚀 Serveur Baileys dĂ©marrĂ© sur http://localhost:3001'));