From 34c6d56aff6beb9ed0c8fc04ee90df5d8c321a51 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:37:58 +0200 Subject: [PATCH 01/40] ddd --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 7b251ca..0535879 100644 --- a/index.js +++ b/index.js @@ -136,7 +136,7 @@ app.post('/sendInteractiveImage', async (req, res) => { const header = proto.Message.InteractiveMessage.Header.create({ title, // 'Igna' ou envoyé par le client subtitle, // 'test' ou envoyé par le client - hasMediaAttachment: true, // ← impératif pour afficher un media + hasMediaAttachment: false, // ← impératif pour afficher un media imageMessage: { url: imageUrl, // URL publique de l'image mimetype: 'image/jpeg' // type MIME From 45bbf9d3e46e80b9586cb9257b77f3588e094c80 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:38:55 +0200 Subject: [PATCH 02/40] ddd --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index 0535879..b7967ae 100644 --- a/index.js +++ b/index.js @@ -141,7 +141,6 @@ app.post('/sendInteractiveImage', async (req, res) => { url: imageUrl, // URL publique de l'image mimetype: 'image/jpeg' // type MIME }, - media: 'imageMessage' // ← sélectionne le bon union field }); // Body et Footer From 5d50cf96f0db66143725157bd59844b10c10488d Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:42:15 +0200 Subject: [PATCH 03/40] dsdsdsds --- index.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index b7967ae..e318691 100644 --- a/index.js +++ b/index.js @@ -133,16 +133,15 @@ app.post('/sendInteractiveImage', async (req, res) => { const imageUrl = `${BASE_URL}/static/logo-merlo-cs-FR.jpg`; // Construire le Header correct - const header = proto.Message.InteractiveMessage.Header.create({ - title, // 'Igna' ou envoyé par le client - subtitle, // 'test' ou envoyé par le client - hasMediaAttachment: false, // ← impératif pour afficher un media - imageMessage: { - url: imageUrl, // URL publique de l'image - mimetype: 'image/jpeg' // type MIME - }, + 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({ + type: proto.Message.InteractiveMessage.HeaderType.IMAGE, + imageMessage: { url: imageUrl }, + title: 'Igna', + subtitle: 'test' + }) }); - // Body et Footer const body = proto.Message.InteractiveMessage.Body.create({ text: caption || 'Description par défaut' From 33e6203d363d46d6d5f0b7444424394b58556349 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:43:08 +0200 Subject: [PATCH 04/40] ezezez --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index e318691..f0d5a55 100644 --- a/index.js +++ b/index.js @@ -136,7 +136,7 @@ app.post('/sendInteractiveImage', async (req, res) => { 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({ - type: proto.Message.InteractiveMessage.HeaderType.IMAGE, + type: "image", imageMessage: { url: imageUrl }, title: 'Igna', subtitle: 'test' From 6dc36a2039d124c1b401d9acc6b58c85dfffab47 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:49:13 +0200 Subject: [PATCH 05/40] DDDDD --- index.js | 102 +++++++++++++++++++++++-------------------------------- 1 file changed, 43 insertions(+), 59 deletions(-) diff --git a/index.js b/index.js index f0d5a55..6e08a07 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,9 @@ const initBaileys = async () => { sock = makeWASocket({ version, auth: state, - printQRInTerminal: false + printQRInTerminal: false, + logger: { level: 'trace' } // Active les logs détaillés + }); sock.ev.on('connection.update', async (update) => { @@ -129,73 +131,55 @@ app.post('/sendInteractiveImage', async (req, res) => { } try { - const BASE_URL = process.env.BASE_URL || 'https://wa.canguidev.fr'; - const imageUrl = `${BASE_URL}/static/logo-merlo-cs-FR.jpg`; + const imagePath = path.join(__dirname, 'public', 'logo-merlo-cs-FR.jpg'); + const imageBuffer = fs.readFileSync(imagePath); + + // Upload the image first + const uploadedImage = await prepareWAMessageMedia( + { image: imageBuffer }, + { upload: sock.waUploadToServer } + ); - // 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({ - type: "image", - imageMessage: { url: imageUrl }, - 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({ + const interactiveMessage = { + imageMessage: uploadedImage.imageMessage, + caption: caption || 'Description par défaut', + footer: footer || 'Pied de page', 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' - }) + buttonId: 'btn1', + buttonText: { displayText: '📄 Voir proposition' }, + type: 1 // URL button }, { - name: 'cta_url', - buttonParamsJson: JSON.stringify({ - display_text: '🔧 Spécifications', - url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf' - }) + buttonId: 'btn2', + buttonText: { displayText: '🔧 Spécifications' }, + type: 1 // URL button + } + ] + }; + + await sock.sendMessage(`${phone}@s.whatsapp.net`, { + image: imageBuffer, + caption: caption, + footer: footer, + templateButtons: [ + { + index: 1, + urlButton: { + displayText: '📄 Voir proposition', + url: 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf' + } + }, + { + index: 2, + urlButton: { + displayText: '🔧 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); From 6e9634267d1ed8d1a55b8ddf19fa5853039f0c5a Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:49:49 +0200 Subject: [PATCH 06/40] DFFDF --- index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.js b/index.js index 6e08a07..93577dc 100644 --- a/index.js +++ b/index.js @@ -21,8 +21,6 @@ const initBaileys = async () => { version, auth: state, printQRInTerminal: false, - logger: { level: 'trace' } // Active les logs détaillés - }); sock.ev.on('connection.update', async (update) => { From 0e2b03391fc2d13671130376cef2c9a8bbd6a627 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 19:58:53 +0200 Subject: [PATCH 07/40] jlmjl --- index.js | 319 +++++++++++++++------------------------------------ package.json | 60 ++++++++-- 2 files changed, 138 insertions(+), 241 deletions(-) diff --git a/index.js b/index.js index 93577dc..e62d585 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ -const { default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, proto, generateWAMessageFromContent, generateWAMessageContent ,prepareWAMessageMedia} = require('@fizzxydev/baileys-pro'); +const venom = require('venom-bot'); const express = require('express'); -const { Boom } = require('@hapi/boom'); const qrcode = require('qrcode'); const path = require('path'); const fs = require('fs'); @@ -9,44 +8,42 @@ const app = express(); app.use(express.json()); app.use(express.static('public')); -let sock; +let client; 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; +// Initialisation Venom-bot +const initVenom = async () => { + client = await venom.create({ + session: 'whatsapp-session', + disableSpins: true, + logQR: false, + catchQR: (base64Qrimg) => { + qrcode.toDataURL(base64Qrimg, (err, url) => { + if (err) { + console.error('Erreur QR code:', err); + return; + } + qrData = url; + isConnected = false; + }); } }); - sock.ev.on('creds.update', saveCreds); + client.onStateChange((state) => { + console.log('État de connexion:', state); + isConnected = state === 'CONNECTED'; + + if (state === 'DISCONNECTED') { + console.log('🔁 Tentative de reconnexion...'); + setTimeout(initVenom, 5000); + } + }); }; -initBaileys(); +initVenom(); + +// Routes Express app.use('/static', express.static(path.join(__dirname, 'public'))); app.get('/login', (req, res) => { @@ -59,9 +56,10 @@ app.get('/api/qrcode', (req, res) => { app.post('/sendText', async (req, res) => { const { phone, message } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + try { - await sock.sendMessage(`${phone}@s.whatsapp.net`, { text: message }); + await client.sendText(`${phone}@c.us`, message); res.json({ success: true }); } catch (e) { res.status(500).json({ error: e.message }); @@ -70,237 +68,100 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + if (!client || !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 }); - + const buttons = [ + { body: "📩 Contacter support" }, + { body: "🌐 Voir notre site" }, + { body: "📞 Appeler le support" } + ]; + + await client.sendButtons( + `${phone}@c.us`, + "Bienvenue sur notre service !", + buttons, + "Choisis une action ci-dessous" + ); + res.json({ success: true }); } catch (e) { - console.error('❌ Erreur bouton actif :', e); + console.error('❌ Erreur boutons:', e); res.status(500).json({ error: e.message }); } }); -// 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' }); - } + const { phone, caption, footer } = req.body; + if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); try { const imagePath = path.join(__dirname, 'public', 'logo-merlo-cs-FR.jpg'); const imageBuffer = fs.readFileSync(imagePath); - // Upload the image first - const uploadedImage = await prepareWAMessageMedia( - { image: imageBuffer }, - { upload: sock.waUploadToServer } + await client.sendImage( + `${phone}@c.us`, + imageBuffer, + 'logo.jpg', + caption || 'Description par défaut', + { + footer: footer || 'Pied de page', + buttons: [ + { buttonId: 'id1', buttonText: { displayText: '📄 Voir proposition' }, type: 1 }, + { buttonId: 'id2', buttonText: { displayText: '🔧 Spécifications' }, type: 1 } + ] + } ); - - const interactiveMessage = { - imageMessage: uploadedImage.imageMessage, - caption: caption || 'Description par défaut', - footer: footer || 'Pied de page', - buttons: [ - { - buttonId: 'btn1', - buttonText: { displayText: '📄 Voir proposition' }, - type: 1 // URL button - }, - { - buttonId: 'btn2', - buttonText: { displayText: '🔧 Spécifications' }, - type: 1 // URL button - } - ] - }; - - await sock.sendMessage(`${phone}@s.whatsapp.net`, { - image: imageBuffer, - caption: caption, - footer: footer, - templateButtons: [ - { - index: 1, - urlButton: { - displayText: '📄 Voir proposition', - url: 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf' - } - }, - { - index: 2, - urlButton: { - displayText: '🔧 Spécifications', - url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf' - } - } - ] - }); - - return res.json({ success: true }); + + res.json({ success: true }); } catch (e) { - console.error('❌ Erreur /sendInteractiveImage :', e); - return res.status(500).json({ error: e.message }); + console.error('❌ Erreur image interactive:', e); + 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.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' }); - } + if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); const { phone, productImageUrl, - productImageCount, productTitle, productDescription, - priceAmount1000, - currencyCode, - retailerId, - productUrl, - businessOwnerJid, - caption, - messageTitle, - footer, - interactiveButtons = [], - quoted + price, + productUrl } = req.body; try { - const jid = `${phone}@s.whatsapp.net`; + // Venom-bot n'a pas de méthode native pour les produits + // On simule avec une image et des boutons + const buttons = [ + { buttonId: 'buy', buttonText: { displayText: '🛒 Acheter' }, type: 1 }, + { buttonId: 'details', buttonText: { displayText: 'ℹ️ Détails' }, type: 1 } + ]; - // 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 - }; + const caption = `*${productTitle}*\n\n${productDescription}\n\nPrix: ${price}`; - // 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 } : {} + await client.sendImage( + `${phone}@c.us`, + productImageUrl, + 'product.jpg', + caption, + { buttons } ); - - return res.json({ success: true }); + + res.json({ success: true }); } catch (e) { - console.error('❌ Erreur /sendProductMessage :', e); - return res.status(500).json({ error: e.message }); + console.error('❌ Erreur produit:', e); + res.status(500).json({ error: e.message }); } }); - -// 5) 404 et gestion des erreurs +// 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); + console.error('Erreur:', err); res.status(500).json({ error: err.message }); }); -app.listen(3001, () => console.log('🚀 Serveur Baileys démarré sur http://localhost:3001')); + +app.listen(3001, () => console.log('🚀 Serveur Venom démarré sur http://localhost:3001')); \ No newline at end of file diff --git a/package.json b/package.json index 9a7c66b..dc1ab39 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,53 @@ { - "name": "baileys-whatsapp-api", - "version": "1.0.0", - "description": "API WhatsApp avec Baileys Pro", - "main": "index.js", + "name": "whatsapp-api-venom", + "version": "2.0.0", + "description": "API WhatsApp avec Venom-bot - Solution complète de messagerie", + "main": "server.js", "scripts": { - "start": "node index.js" + "start": "node server.js", + "dev": "nodemon server.js", + "test": "jest --coverage", + "lint": "eslint .", + "format": "prettier --write .", + "postinstall": "node node_modules/venom-bot/install-chromium.js" }, "dependencies": { - "@fizzxydev/baileys-pro": "latest", - "@hapi/boom": "^10.0.1", - "axios": "^1.4.0", - "express": "^4.18.4", - "qrcode": "^1.5.1", - "sharp": "^0.33.0" + "venom-bot": "^4.3.7", + "express": "^4.18.2", + "express-rate-limit": "^6.8.1", + "helmet": "^7.1.0", + "morgan": "^1.10.0", + "qrcode": "^1.5.3", + "sharp": "^0.33.2", + "winston": "^3.11.0", + "axios": "^1.6.2" + }, + "devDependencies": { + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "jest": "^29.7.0", + "nodemon": "^3.0.2", + "prettier": "^3.1.1", + "supertest": "^6.3.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "keywords": [ + "whatsapp", + "api", + "venom", + "bot", + "messaging", + "automation" + ], + "repository": { + "type": "git", + "url": "https://github.com/votre-utilisateur/whatsapp-api-venom.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/votre-utilisateur/whatsapp-api-venom/issues" } -} +} \ No newline at end of file From eea45a62b580c8a986dc464f7094ab0decc95168 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:04:10 +0200 Subject: [PATCH 08/40] jjjj --- package.json | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index dc1ab39..b45a530 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "whatsapp-api-venom", - "version": "2.0.0", + "version": "2.0.1", "description": "API WhatsApp avec Venom-bot - Solution complète de messagerie", "main": "server.js", "scripts": { @@ -9,7 +9,7 @@ "test": "jest --coverage", "lint": "eslint .", "format": "prettier --write .", - "postinstall": "node node_modules/venom-bot/install-chromium.js" + "postinstall": "node node_modules/venom-bot/dist/install/install-chromium.js" }, "dependencies": { "venom-bot": "^4.3.7", @@ -18,9 +18,9 @@ "helmet": "^7.1.0", "morgan": "^1.10.0", "qrcode": "^1.5.3", - "sharp": "^0.33.2", "winston": "^3.11.0", - "axios": "^1.6.2" + "axios": "^1.6.2", + "puppeteer": "^21.9.0" }, "devDependencies": { "eslint": "^8.56.0", @@ -33,21 +33,5 @@ "engines": { "node": ">=16.0.0", "npm": ">=8.0.0" - }, - "keywords": [ - "whatsapp", - "api", - "venom", - "bot", - "messaging", - "automation" - ], - "repository": { - "type": "git", - "url": "https://github.com/votre-utilisateur/whatsapp-api-venom.git" - }, - "license": "MIT", - "bugs": { - "url": "https://github.com/votre-utilisateur/whatsapp-api-venom/issues" } } \ No newline at end of file From 8be64a0f8130c5c0fd89d8f845c69051803585e1 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:13:06 +0200 Subject: [PATCH 09/40] =?UTF-8?q?dsm=C3=B9;se=C3=B9d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index b45a530..a45a2e7 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,10 @@ { - "name": "whatsapp-api-venom", - "version": "2.0.1", - "description": "API WhatsApp avec Venom-bot - Solution complète de messagerie", - "main": "server.js", + "name": "baileys-whatsapp-api", + "version": "1.0.0", + "description": "API WhatsApp avec Baileys Pro", + "main": "index.js", "scripts": { - "start": "node server.js", - "dev": "nodemon server.js", - "test": "jest --coverage", - "lint": "eslint .", - "format": "prettier --write .", - "postinstall": "node node_modules/venom-bot/dist/install/install-chromium.js" + "start": "node index.js" }, "dependencies": { "venom-bot": "^4.3.7", @@ -21,17 +16,5 @@ "winston": "^3.11.0", "axios": "^1.6.2", "puppeteer": "^21.9.0" - }, - "devDependencies": { - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "jest": "^29.7.0", - "nodemon": "^3.0.2", - "prettier": "^3.1.1", - "supertest": "^6.3.3" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" } -} \ No newline at end of file +} From d77d5724c3e8ddb0f55cd647c31d43add5d5271e Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:16:52 +0200 Subject: [PATCH 10/40] kdsksdk --- Dockerfile | 56 ++++++++++++++++++++++++++++++++++------------------ package.json | 29 +++++++++++++++++++++------ 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index f2e1b24..8406d98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,46 @@ -FROM node:20 +FROM node:20-slim -# Installation des dépendances système nécessaires à sharp (et puppeteer) +# Install system dependencies for Venom-bot, Puppeteer and Sharp RUN apt-get update && apt-get install -y \ - libvips-dev \ - libnss3 \ - libatk-bridge2.0-0 \ - libxss1 \ - libasound2 \ - libgtk-3-0 \ - libgbm1 \ - libx11-xcb1 \ - libxcomposite1 \ - libxdamage1 \ - libxrandr2 \ - xdg-utils \ - --no-install-recommends && \ - apt-get clean && rm -rf /var/lib/apt/lists/* + libvips-dev \ + libnss3 \ + libatk-bridge2.0-0 \ + libxss1 \ + libasound2 \ + libgtk-3-0 \ + libgbm1 \ + libx11-xcb1 \ + libxcomposite1 \ + libxdamage1 \ + libxrandr2 \ + xdg-utils \ + fonts-liberation \ + libappindicator3-1 \ + libnspr4 \ + lsb-release \ + wget \ + # Clean up + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +# Set working directory WORKDIR /app -COPY package.json yarn.lock ./ -RUN yarn install +# Install Chromium manually (recommended approach for Venom-bot) +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium +# Copy package files first for better layer caching +COPY package.json yarn.lock ./ + +# Install project dependencies +RUN yarn install --frozen-lockfile --production=false + +# Copy application files COPY . . +# Expose the application port EXPOSE 3001 -CMD ["yarn", "start"] + +# Start command +CMD ["yarn", "start"] \ No newline at end of file diff --git a/package.json b/package.json index a45a2e7..b45a530 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,15 @@ { - "name": "baileys-whatsapp-api", - "version": "1.0.0", - "description": "API WhatsApp avec Baileys Pro", - "main": "index.js", + "name": "whatsapp-api-venom", + "version": "2.0.1", + "description": "API WhatsApp avec Venom-bot - Solution complète de messagerie", + "main": "server.js", "scripts": { - "start": "node index.js" + "start": "node server.js", + "dev": "nodemon server.js", + "test": "jest --coverage", + "lint": "eslint .", + "format": "prettier --write .", + "postinstall": "node node_modules/venom-bot/dist/install/install-chromium.js" }, "dependencies": { "venom-bot": "^4.3.7", @@ -16,5 +21,17 @@ "winston": "^3.11.0", "axios": "^1.6.2", "puppeteer": "^21.9.0" + }, + "devDependencies": { + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "jest": "^29.7.0", + "nodemon": "^3.0.2", + "prettier": "^3.1.1", + "supertest": "^6.3.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" } -} +} \ No newline at end of file From 30a6f2171d1fafc825084926b43fafc15e87e85d Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:21:47 +0200 Subject: [PATCH 11/40] dsdsdds --- Dockerfile | 54 +++----- index.js | 355 +++++++++++++++++++++++++++++++++++++-------------- package.json | 44 ++----- 3 files changed, 286 insertions(+), 167 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8406d98..f2e1b24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,46 +1,28 @@ -FROM node:20-slim +FROM node:20 -# Install system dependencies for Venom-bot, Puppeteer and Sharp +# Installation des dépendances système nécessaires à sharp (et puppeteer) RUN apt-get update && apt-get install -y \ - libvips-dev \ - libnss3 \ - libatk-bridge2.0-0 \ - libxss1 \ - libasound2 \ - libgtk-3-0 \ - libgbm1 \ - libx11-xcb1 \ - libxcomposite1 \ - libxdamage1 \ - libxrandr2 \ - xdg-utils \ - fonts-liberation \ - libappindicator3-1 \ - libnspr4 \ - lsb-release \ - wget \ - # Clean up - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + libvips-dev \ + libnss3 \ + libatk-bridge2.0-0 \ + libxss1 \ + libasound2 \ + libgtk-3-0 \ + libgbm1 \ + libx11-xcb1 \ + libxcomposite1 \ + libxdamage1 \ + libxrandr2 \ + xdg-utils \ + --no-install-recommends && \ + apt-get clean && rm -rf /var/lib/apt/lists/* -# Set working directory WORKDIR /app -# Install Chromium manually (recommended approach for Venom-bot) -ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true -ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium - -# Copy package files first for better layer caching COPY package.json yarn.lock ./ +RUN yarn install -# Install project dependencies -RUN yarn install --frozen-lockfile --production=false - -# Copy application files COPY . . -# Expose the application port EXPOSE 3001 - -# Start command -CMD ["yarn", "start"] \ No newline at end of file +CMD ["yarn", "start"] diff --git a/index.js b/index.js index e62d585..cdafa74 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ -const venom = require('venom-bot'); +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'); @@ -8,42 +9,44 @@ const app = express(); app.use(express.json()); app.use(express.static('public')); -let client; +let sock; let qrData = null; let isConnected = false; -// Initialisation Venom-bot -const initVenom = async () => { - client = await venom.create({ - session: 'whatsapp-session', - disableSpins: true, - logQR: false, - catchQR: (base64Qrimg) => { - qrcode.toDataURL(base64Qrimg, (err, url) => { - if (err) { - console.error('Erreur QR code:', err); - return; - } - qrData = url; - 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; } }); - client.onStateChange((state) => { - console.log('État de connexion:', state); - isConnected = state === 'CONNECTED'; - - if (state === 'DISCONNECTED') { - console.log('🔁 Tentative de reconnexion...'); - setTimeout(initVenom, 5000); - } - }); + sock.ev.on('creds.update', saveCreds); }; -initVenom(); - -// Routes Express +initBaileys(); app.use('/static', express.static(path.join(__dirname, 'public'))); app.get('/login', (req, res) => { @@ -56,10 +59,9 @@ app.get('/api/qrcode', (req, res) => { app.post('/sendText', async (req, res) => { const { phone, message } = req.body; - if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); - + if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); try { - await client.sendText(`${phone}@c.us`, message); + await sock.sendMessage(`${phone}@s.whatsapp.net`, { text: message }); res.json({ success: true }); } catch (e) { res.status(500).json({ error: e.message }); @@ -68,100 +70,255 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; - if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); try { - const buttons = [ - { body: "📩 Contacter support" }, - { body: "🌐 Voir notre site" }, - { body: "📞 Appeler le support" } - ]; - - await client.sendButtons( - `${phone}@c.us`, - "Bienvenue sur notre service !", - buttons, - "Choisis une action ci-dessous" - ); - - res.json({ success: true }); - } catch (e) { - console.error('❌ Erreur boutons:', e); - res.status(500).json({ error: e.message }); - } -}); - -app.post('/sendInteractiveImage', async (req, res) => { - const { phone, caption, footer } = req.body; - if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); - - try { - const imagePath = path.join(__dirname, 'public', 'logo-merlo-cs-FR.jpg'); - const imageBuffer = fs.readFileSync(imagePath); - - await client.sendImage( - `${phone}@c.us`, - imageBuffer, - 'logo.jpg', - caption || 'Description par défaut', - { - footer: footer || 'Pied de page', - buttons: [ - { buttonId: 'id1', buttonText: { displayText: '📄 Voir proposition' }, type: 1 }, - { buttonId: 'id2', buttonText: { displayText: '🔧 Spécifications' }, type: 1 } - ] + 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 image interactive:', 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, 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({ + type: proto.Message.InteractiveMessage.HeaderType.IMAGE, + imageMessage: { url: imageUrl }, + 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 }); + } +}); + +// 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.post('/sendProductMessage', async (req, res) => { - if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + // 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, - price, - productUrl + priceAmount1000, + currencyCode, + retailerId, + productUrl, + businessOwnerJid, + caption, + messageTitle, + footer, + interactiveButtons = [], + quoted } = req.body; try { - // Venom-bot n'a pas de méthode native pour les produits - // On simule avec une image et des boutons - const buttons = [ - { buttonId: 'buy', buttonText: { displayText: '🛒 Acheter' }, type: 1 }, - { buttonId: 'details', buttonText: { displayText: 'ℹ️ Détails' }, type: 1 } - ]; + const jid = `${phone}@s.whatsapp.net`; - const caption = `*${productTitle}*\n\n${productDescription}\n\nPrix: ${price}`; + // 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 + }; - await client.sendImage( - `${phone}@c.us`, - productImageUrl, - 'product.jpg', - caption, - { buttons } + // 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 } : {} ); - - res.json({ success: true }); + + return res.json({ success: true }); } catch (e) { - console.error('❌ Erreur produit:', e); - res.status(500).json({ error: e.message }); + console.error('❌ Erreur /sendProductMessage :', e); + return res.status(500).json({ error: e.message }); } }); -// Gestion des erreurs + +// 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('Erreur:', err); + console.error('Middleware d’erreur :', err); res.status(500).json({ error: err.message }); }); - -app.listen(3001, () => console.log('🚀 Serveur Venom démarré sur http://localhost:3001')); \ No newline at end of file +app.listen(3001, () => console.log('🚀 Serveur Baileys démarré sur http://localhost:3001')); diff --git a/package.json b/package.json index b45a530..9a7c66b 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,17 @@ { - "name": "whatsapp-api-venom", - "version": "2.0.1", - "description": "API WhatsApp avec Venom-bot - Solution complète de messagerie", - "main": "server.js", + "name": "baileys-whatsapp-api", + "version": "1.0.0", + "description": "API WhatsApp avec Baileys Pro", + "main": "index.js", "scripts": { - "start": "node server.js", - "dev": "nodemon server.js", - "test": "jest --coverage", - "lint": "eslint .", - "format": "prettier --write .", - "postinstall": "node node_modules/venom-bot/dist/install/install-chromium.js" + "start": "node index.js" }, "dependencies": { - "venom-bot": "^4.3.7", - "express": "^4.18.2", - "express-rate-limit": "^6.8.1", - "helmet": "^7.1.0", - "morgan": "^1.10.0", - "qrcode": "^1.5.3", - "winston": "^3.11.0", - "axios": "^1.6.2", - "puppeteer": "^21.9.0" - }, - "devDependencies": { - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "jest": "^29.7.0", - "nodemon": "^3.0.2", - "prettier": "^3.1.1", - "supertest": "^6.3.3" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" + "@fizzxydev/baileys-pro": "latest", + "@hapi/boom": "^10.0.1", + "axios": "^1.4.0", + "express": "^4.18.4", + "qrcode": "^1.5.1", + "sharp": "^0.33.0" } -} \ No newline at end of file +} From c6b6d4663555f54300d499de7f967021cacd1784 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:28:55 +0200 Subject: [PATCH 12/40] kkkk --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index cdafa74..6572d7e 100644 --- a/index.js +++ b/index.js @@ -136,7 +136,6 @@ app.post('/sendInteractiveImage', async (req, res) => { 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({ - type: proto.Message.InteractiveMessage.HeaderType.IMAGE, imageMessage: { url: imageUrl }, title: 'Igna', subtitle: 'test' From a71c859d83528c1db5a20a09994109680d6cb3ac Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 20:31:05 +0200 Subject: [PATCH 13/40] jjjj --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index 6572d7e..1906567 100644 --- a/index.js +++ b/index.js @@ -136,7 +136,6 @@ app.post('/sendInteractiveImage', async (req, res) => { 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({ - imageMessage: { url: imageUrl }, title: 'Igna', subtitle: 'test' }), From 3b248cc9437e75ea95ade361edb8163ddfa5bed5 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:11:12 +0200 Subject: [PATCH 14/40] DKDKDK --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 1906567..1fd9db3 100644 --- a/index.js +++ b/index.js @@ -71,11 +71,13 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; 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`; try { const content = { message: { interactiveMessage: proto.Message.InteractiveMessage.create({ + image: { url : imageUrl }, // Can buffer body: { text: "Bienvenue sur notre service !" }, footer: { text: "Choisis une action ci-dessous" }, header: { From d2353f9b5b9605125e2d648e88c3f188ca029b6c Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:14:46 +0200 Subject: [PATCH 15/40] JJJJJJ --- index.js | 88 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/index.js b/index.js index 1fd9db3..cd9fbcc 100644 --- a/index.js +++ b/index.js @@ -70,52 +70,53 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + + if (!client || !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`; - try { - const content = { - message: { - interactiveMessage: proto.Message.InteractiveMessage.create({ - image: { url : imageUrl }, // Can buffer - 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 jid = `${phone}@s.whatsapp.net`; - const msg = generateWAMessageFromContent(`${phone}@s.whatsapp.net`, content, {}); - await sock.relayMessage(`${phone}@s.whatsapp.net`, msg.message, { messageId: msg.key.id }); + try { + await client.sendMessage( + jid, + { + image: { url: imageUrl }, + caption: "Bienvenue sur notre service !", + title: "Menu principal", + subtitle: "Choisis une action ci-dessous", + footer: "MERLO FRANCE", + media: true, + interactiveButtons: [ + { + name: "quick_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" + }) + }, + { + name: "cta_call", + buttonParamsJson: JSON.stringify({ + display_text: "📞 Appeler le support", + id: "+33612345678" + }) + } + ] + }, + { + quoted: null // tu peux remplacer `null` par un message existant si besoin + } + ); res.json({ success: true }); } catch (e) { @@ -123,6 +124,7 @@ app.post('/sendButtons', async (req, res) => { res.status(500).json({ error: e.message }); } }); + // Votre route POST app.post('/sendInteractiveImage', async (req, res) => { const { phone, caption, title, subtitle, footer } = req.body; From 1bc18fbbaff18df6d5f68ce67ed92a87d3dae130 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:16:39 +0200 Subject: [PATCH 16/40] KKKK --- index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index cd9fbcc..bcd872e 100644 --- a/index.js +++ b/index.js @@ -71,9 +71,8 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; - if (!client || !isConnected) { - return res.status(400).json({ error: 'Non connecté' }); - } + 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`; From 758cba09b6d0d36e4cafbead183ec2f13b54fca6 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:18:49 +0200 Subject: [PATCH 17/40] DSDSDS --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index bcd872e..3a0f8ce 100644 --- a/index.js +++ b/index.js @@ -73,13 +73,12 @@ app.post('/sendButtons', async (req, res) => { 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`; try { - await client.sendMessage( + await sock.sendMessage( jid, { image: { url: imageUrl }, @@ -113,7 +112,7 @@ app.post('/sendButtons', async (req, res) => { ] }, { - quoted: null // tu peux remplacer `null` par un message existant si besoin + quoted: null // ou un message existant si tu veux répondre à un message } ); @@ -124,6 +123,7 @@ app.post('/sendButtons', async (req, res) => { } }); + // Votre route POST app.post('/sendInteractiveImage', async (req, res) => { const { phone, caption, title, subtitle, footer } = req.body; From 3d832169786f9aabbd96814bc621ae665d5d44c9 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:25:43 +0200 Subject: [PATCH 18/40] KJOJP --- index.js | 56 +++++++++++++++++++++++++++++++++++++++++----------- package.json | 4 +++- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 3a0f8ce..b08e2c2 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,16 @@ -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 NodeCache = require('node-cache'); +const { + default: makeWASocket, + useMultiFileAuthState, + DisconnectReason, + fetchLatestBaileysVersion, + proto, + generateWAMessageFromContent +} = require('@fizzxydev/baileys-pro'); const app = express(); app.use(express.json()); @@ -13,6 +20,15 @@ let sock; let qrData = null; let isConnected = false; +// 💾 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 () => { const { version } = await fetchLatestBaileysVersion(); const { state, saveCreds } = await useMultiFileAuthState('auth'); @@ -20,23 +36,21 @@ const initBaileys = async () => { sock = makeWASocket({ version, auth: state, - printQRInTerminal: false + markOnlineOnConnect: false, + getMessage: async (key) => await getMessageFromStore(key), + cachedGroupMetadata: async (jid) => groupCache.get(jid) }); - sock.ev.on('connection.update', async (update) => { - const { connection, lastDisconnect, qr } = update; + sock.ev.on('connection.update', async ({ connection, lastDisconnect, qr }) => { 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é.'); - } + console.log(shouldReconnect ? '🔁 Reconnexion...' : '❌ Déconnecté.'); + if (shouldReconnect) initBaileys(); } else if (connection === 'open') { console.log('✅ Connecté à WhatsApp'); isConnected = true; @@ -44,9 +58,29 @@ const initBaileys = async () => { }); sock.ev.on('creds.update', saveCreds); + + // 📌 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]; + if (!msg.key.fromMe && msg.message?.conversation) { + console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); + } + }); }; initBaileys(); + app.use('/static', express.static(path.join(__dirname, 'public'))); app.get('/login', (req, res) => { diff --git a/package.json b/package.json index 9a7c66b..e9d8771 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "axios": "^1.4.0", "express": "^4.18.4", "qrcode": "^1.5.1", - "sharp": "^0.33.0" + "sharp": "^0.33.0", + "node-cache": "^5.1.2" + } } From 221d98a541359a1f8a2ed62627dc7d4bddafc8b4 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:31:03 +0200 Subject: [PATCH 19/40] lJLJ --- index.js | 83 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/index.js b/index.js index b08e2c2..6b27ffc 100644 --- a/index.js +++ b/index.js @@ -105,50 +105,61 @@ app.post('/sendText', async (req, res) => { app.post('/sendButtons', async (req, res) => { const { phone } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + 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`; try { - await sock.sendMessage( - jid, - { - image: { url: imageUrl }, - caption: "Bienvenue sur notre service !", - title: "Menu principal", - subtitle: "Choisis une action ci-dessous", - footer: "MERLO FRANCE", - media: true, - interactiveButtons: [ - { - name: "quick_reply", - buttonParamsJson: JSON.stringify({ - display_text: "📩 Contacter support", - id: "support_action" - }) + const content = { + viewOnceMessage: { + message: { + messageContextInfo: { + deviceListMetadata: {}, + deviceListMetadataVersion: 2 }, - { - name: "cta_url", - buttonParamsJson: JSON.stringify({ - display_text: "🌐 Voir notre site", - url: "https://canguidev.fr" - }) - }, - { - name: "cta_call", - buttonParamsJson: JSON.stringify({ - display_text: "📞 Appeler le support", - id: "+33612345678" - }) - } - ] - }, - { - quoted: null // ou un message existant si tu veux répondre à un message + interactiveMessage: proto.Message.InteractiveMessage.create({ + body: { text: "Bienvenue sur notre service !" }, + footer: { text: "Choisis une action ci-dessous" }, + header: { + hasMediaAttachment: true, + imageMessage: { url: imageUrl } + }, + 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" + }) + }, + { + name: "cta_call", + buttonParamsJson: JSON.stringify({ + display_text: "📞 Appeler le support", + id: "+33612345678" + }) + } + ] + } + }) + } } - ); + }; + + const msg = generateWAMessageFromContent(jid, content, {}); + await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); res.json({ success: true }); } catch (e) { From be382454857f5d284973b91ddb7b1defac1c8702 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:36:08 +0200 Subject: [PATCH 20/40] DSKSDOK --- index.js | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/index.js b/index.js index 6b27ffc..0607366 100644 --- a/index.js +++ b/index.js @@ -101,6 +101,80 @@ app.post('/sendText', async (req, res) => { res.status(500).json({ error: e.message }); } }); +app.post('/testButtons', 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: "Hello Wolrd !;", + footer: "© Fizzxy Dev", + 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 + }); + + res.json({ success: true }); + } catch (e) { + console.error('❌ Erreur testButtons :', e); + res.status(500).json({ error: e.message }); + } +}); app.post('/sendButtons', async (req, res) => { const { phone } = req.body; From 4e8d795adb7d9270c3542bd11b49882f01aedee6 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:40:12 +0200 Subject: [PATCH 21/40] SDML,DSL,MDS --- index.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/index.js b/index.js index 0607366..bf7b7f4 100644 --- a/index.js +++ b/index.js @@ -322,6 +322,98 @@ app.post('/sendInteractiveImage', async (req, res) => { return res.status(500).json({ error: e.message }); } }); +app.post('/sendFullInteractive', async (req, res) => { + const { phone } = req.body; + + 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`; + + try { + const content = { + viewOnceMessage: { + message: { + messageContextInfo: { + deviceListMetadata: {}, + deviceListMetadataVersion: 2 + }, + interactiveMessage: proto.Message.InteractiveMessage.create({ + header: { + hasMediaAttachment: true, + imageMessage: { url: imageUrl } + }, + 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 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" + }) + }, + { + name: "single_select", + buttonParamsJson: JSON.stringify({ + title: "📚 Choisir une brochure", + sections: [ + { + title: "Documentation PDF", + highlight_label: "Merlo Docs", + rows: [ + { + id: "brochure_1", + title: "Catalogue Général", + description: "Voir le PDF du catalogue", + header: "Catalogue" + }, + { + id: "brochure_2", + title: "Fiche technique", + description: "Voir le PDF de la fiche technique", + header: "Fiche" + } + ] + } + ] + }) + } + ] + } + }) + } + } + }; + + const msg = generateWAMessageFromContent(jid, content, {}); + await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); + + res.json({ success: true }); + } catch (e) { + console.error('❌ Erreur sendFullInteractive :', e); + res.status(500).json({ error: e.message }); + } +}); + // app.post('/sendInteractiveImage', async (req, res) => { // const { phone, caption, title, subtitle, footer } = req.body; From ad3b2c33c89f73c7e50a972966004c44bc6bbbe9 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:42:13 +0200 Subject: [PATCH 22/40] klnklnkl --- index.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index bf7b7f4..f060aca 100644 --- a/index.js +++ b/index.js @@ -71,12 +71,58 @@ const initBaileys = async () => { }); // (Facultatif) Gestion des messages reçus - sock.ev.on('messages.upsert', async ({ messages }) => { + sock.ev.on('messages.upsert', async ({ messages, type }) => { const msg = messages[0]; - if (!msg.key.fromMe && msg.message?.conversation) { - console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); + + // Ignore les messages venant de toi + if (!msg.message || msg.key.fromMe) return; + + const from = msg.key.remoteJid; + console.log('📩 Message reçu de', from); + + // 💬 Gérer les réponses à un bouton `cta_reply` + if (msg.message?.buttonReplyMessage) { + const id = msg.message.buttonReplyMessage.selectedDisplayText; + console.log('🟢 Réponse bouton :', id); + + // Exemple de réponse simple + await sock.sendMessage(from, { text: `Vous avez sélectionné : ${id}` }); + return; + } + + // 🧵 Gérer les sélections dans un menu `single_select` + if (msg.message?.interactiveResponseMessage?.nativeFlowResponseMessage) { + const native = msg.message.interactiveResponseMessage.nativeFlowResponseMessage; + const params = JSON.parse(native.paramsJson); + const selectedRowId = params?.selected_row_id; + + console.log('📂 ID sélectionné dans le menu :', selectedRowId); + + if (selectedRowId === 'brochure_1') { + await sock.sendMessage(from, { + document: { url: "https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf" }, + mimetype: "application/pdf", + fileName: "Catalogue_Merlo.pdf" + }); + } else if (selectedRowId === 'brochure_2') { + await sock.sendMessage(from, { + document: { url: "https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf" }, + mimetype: "application/pdf", + fileName: "Fiche_Technique_Merlo.pdf" + }); + } else { + await sock.sendMessage(from, { text: "Option non reconnue." }); + } + + return; + } + + // Optionnel : fallback pour tout autre message + if (msg.message?.conversation) { + await sock.sendMessage(from, { text: "Merci pour votre message ! 😊" }); } }); + }; initBaileys(); From 2c7bbb8c50c712d8952968ae64982b91de239d4d Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:45:38 +0200 Subject: [PATCH 23/40] dsdsds --- index.js | 147 +++---------------------------------------------------- 1 file changed, 6 insertions(+), 141 deletions(-) diff --git a/index.js b/index.js index f060aca..b654e55 100644 --- a/index.js +++ b/index.js @@ -71,58 +71,12 @@ const initBaileys = async () => { }); // (Facultatif) Gestion des messages reçus - sock.ev.on('messages.upsert', async ({ messages, type }) => { + sock.ev.on('messages.upsert', async ({ messages }) => { const msg = messages[0]; - - // Ignore les messages venant de toi - if (!msg.message || msg.key.fromMe) return; - - const from = msg.key.remoteJid; - console.log('📩 Message reçu de', from); - - // 💬 Gérer les réponses à un bouton `cta_reply` - if (msg.message?.buttonReplyMessage) { - const id = msg.message.buttonReplyMessage.selectedDisplayText; - console.log('🟢 Réponse bouton :', id); - - // Exemple de réponse simple - await sock.sendMessage(from, { text: `Vous avez sélectionné : ${id}` }); - return; - } - - // 🧵 Gérer les sélections dans un menu `single_select` - if (msg.message?.interactiveResponseMessage?.nativeFlowResponseMessage) { - const native = msg.message.interactiveResponseMessage.nativeFlowResponseMessage; - const params = JSON.parse(native.paramsJson); - const selectedRowId = params?.selected_row_id; - - console.log('📂 ID sélectionné dans le menu :', selectedRowId); - - if (selectedRowId === 'brochure_1') { - await sock.sendMessage(from, { - document: { url: "https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf" }, - mimetype: "application/pdf", - fileName: "Catalogue_Merlo.pdf" - }); - } else if (selectedRowId === 'brochure_2') { - await sock.sendMessage(from, { - document: { url: "https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf" }, - mimetype: "application/pdf", - fileName: "Fiche_Technique_Merlo.pdf" - }); - } else { - await sock.sendMessage(from, { text: "Option non reconnue." }); - } - - return; - } - - // Optionnel : fallback pour tout autre message - if (msg.message?.conversation) { - await sock.sendMessage(from, { text: "Merci pour votre message ! 😊" }); + if (!msg.key.fromMe && msg.message?.conversation) { + console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); } }); - }; initBaileys(); @@ -158,8 +112,11 @@ app.post('/testButtons', async (req, res) => { try { 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, buttons: [ { buttonId: '.tes', @@ -368,98 +325,6 @@ app.post('/sendInteractiveImage', async (req, res) => { return res.status(500).json({ error: e.message }); } }); -app.post('/sendFullInteractive', async (req, res) => { - const { phone } = req.body; - - 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`; - - try { - const content = { - viewOnceMessage: { - message: { - messageContextInfo: { - deviceListMetadata: {}, - deviceListMetadataVersion: 2 - }, - interactiveMessage: proto.Message.InteractiveMessage.create({ - header: { - hasMediaAttachment: true, - imageMessage: { url: imageUrl } - }, - 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 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" - }) - }, - { - name: "single_select", - buttonParamsJson: JSON.stringify({ - title: "📚 Choisir une brochure", - sections: [ - { - title: "Documentation PDF", - highlight_label: "Merlo Docs", - rows: [ - { - id: "brochure_1", - title: "Catalogue Général", - description: "Voir le PDF du catalogue", - header: "Catalogue" - }, - { - id: "brochure_2", - title: "Fiche technique", - description: "Voir le PDF de la fiche technique", - header: "Fiche" - } - ] - } - ] - }) - } - ] - } - }) - } - } - }; - - const msg = generateWAMessageFromContent(jid, content, {}); - await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); - - res.json({ success: true }); - } catch (e) { - console.error('❌ Erreur sendFullInteractive :', e); - res.status(500).json({ error: e.message }); - } -}); - // app.post('/sendInteractiveImage', async (req, res) => { // const { phone, caption, title, subtitle, footer } = req.body; From 2deec5e15893e16f889cfbc9fcc20503b41f39a4 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:48:31 +0200 Subject: [PATCH 24/40] kjh=jkh=k --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index b654e55..dbc2bb7 100644 --- a/index.js +++ b/index.js @@ -117,6 +117,9 @@ app.post('/testButtons', async (req, res) => { 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', From b6dbd6849150364d9cc57c8af727f044dc30d577 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:51:17 +0200 Subject: [PATCH 25/40] lknslkn --- index.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/index.js b/index.js index dbc2bb7..4f22dbb 100644 --- a/index.js +++ b/index.js @@ -439,6 +439,62 @@ app.post('/sendProductMessage', async (req, res) => { 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 }); + } +}); // 5) 404 et gestion des erreurs From e9c51cdebcd11e45bf4ec7038626bec69e47523b Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:54:47 +0200 Subject: [PATCH 26/40] ml,ML, --- index.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/index.js b/index.js index 4f22dbb..05007eb 100644 --- a/index.js +++ b/index.js @@ -496,6 +496,53 @@ app.post('/testProductMessage', async (req, res) => { } }); +app.post('/testInteractiveImage', 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, + { + image: { url: "https://example.com/image.jpg" }, // remplace par une vraie image en HTTPS + caption: "📌 Découvrez notre service interactif !", + title: "Merlo Interactive Demo", + subtitle: "Choisissez une action", + footer: "MERLO France © 2025", + media: true, + interactiveButtons: [ + { + name: "quick_reply", + buttonParamsJson: JSON.stringify({ + display_text: "📩 Contacter un conseiller", + id: "contact_support" + }) + }, + { + name: "cta_url", + buttonParamsJson: JSON.stringify({ + display_text: "🌐 Voir notre site", + url: "https://canguidev.fr" + }) + } + ] + }, + { + quoted: null // tu peux y mettre un message si tu veux répondre à un msg précédent + } + ); + + res.json({ success: true }); + } catch (e) { + console.error("❌ Erreur interactive image :", e); + res.status(500).json({ error: e.message }); + } +}); // 5) 404 et gestion des erreurs app.use((req, res) => res.status(404).json({ error: 'Ressource introuvable' })); From fdece82ee596d2550e46b4ce4c06f8ee75518c32 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 21:55:39 +0200 Subject: [PATCH 27/40] dddd --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 05007eb..d722cd6 100644 --- a/index.js +++ b/index.js @@ -509,7 +509,7 @@ app.post('/testInteractiveImage', async (req, res) => { await sock.sendMessage( jid, { - image: { url: "https://example.com/image.jpg" }, // remplace par une vraie image en HTTPS + image: { url: "https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg" }, // remplace par une vraie image en HTTPS caption: "📌 Découvrez notre service interactif !", title: "Merlo Interactive Demo", subtitle: "Choisissez une action", From 4a3cd2ee187f1d70c610520e786baf5d20d926c4 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:00:51 +0200 Subject: [PATCH 28/40] ONKLNL --- index.js | 74 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/index.js b/index.js index d722cd6..ce64dd7 100644 --- a/index.js +++ b/index.js @@ -503,45 +503,47 @@ app.post('/testInteractiveImage', async (req, res) => { return res.status(400).json({ error: 'Non connecté à WhatsApp' }); } - const jid = `${phone}@s.whatsapp.net`; - - try { - await sock.sendMessage( - jid, - { - image: { url: "https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg" }, // remplace par une vraie image en HTTPS - caption: "📌 Découvrez notre service interactif !", - title: "Merlo Interactive Demo", - subtitle: "Choisissez une action", - footer: "MERLO France © 2025", - media: true, - interactiveButtons: [ - { - name: "quick_reply", - buttonParamsJson: JSON.stringify({ - display_text: "📩 Contacter un conseiller", - id: "contact_support" - }) + 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" } }, - { - name: "cta_url", - buttonParamsJson: JSON.stringify({ - display_text: "🌐 Voir notre site", - url: "https://canguidev.fr" - }) + 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" + }) + } + ] } - ] - }, - { - quoted: null // tu peux y mettre un message si tu veux répondre à un msg précédent + }) } - ); - - res.json({ success: true }); - } catch (e) { - console.error("❌ Erreur interactive image :", e); - res.status(500).json({ error: e.message }); - } + } + }; + + const jid = `${phone}@s.whatsapp.net`; + const msg = generateWAMessageFromContent(jid, content, {}); + await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); + }); // 5) 404 et gestion des erreurs From 1d893a1c21dc8802e4462096d991e39d71de531a Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:12:39 +0200 Subject: [PATCH 29/40] khkhl= --- index.js | 14 ++++++++------ package.json | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index ce64dd7..134decf 100644 --- a/index.js +++ b/index.js @@ -4,13 +4,14 @@ const path = require('path'); const fs = require('fs'); const NodeCache = require('node-cache'); const { - default: makeWASocket, + makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, proto, generateWAMessageFromContent -} = require('@fizzxydev/baileys-pro'); +} = require('@whiskeysockets/baileys'); + const app = express(); app.use(express.json()); @@ -186,7 +187,7 @@ app.post('/sendButtons', async (req, res) => { const { phone } = req.body; if (!sock || !isConnected) { - return res.status(400).json({ error: 'Non connecté' }); + return res.status(400).json({ error: 'Non connecté à WhatsApp' }); } const BASE_URL = process.env.BASE_URL || 'https://wa.canguidev.fr'; @@ -202,12 +203,12 @@ app.post('/sendButtons', async (req, res) => { deviceListMetadataVersion: 2 }, interactiveMessage: proto.Message.InteractiveMessage.create({ - body: { text: "Bienvenue sur notre service !" }, - footer: { text: "Choisis une action ci-dessous" }, header: { hasMediaAttachment: true, imageMessage: { url: imageUrl } }, + body: { text: "Bienvenue sur notre service !" }, + footer: { text: "Choisis une action ci-dessous" }, nativeFlowMessage: { buttons: [ { @@ -243,12 +244,13 @@ app.post('/sendButtons', async (req, res) => { res.json({ success: true }); } catch (e) { - console.error('❌ Erreur bouton actif :', e); + console.error('❌ Erreur /sendButtons :', e); res.status(500).json({ error: e.message }); } }); + // Votre route POST app.post('/sendInteractiveImage', async (req, res) => { const { phone, caption, title, subtitle, footer } = req.body; diff --git a/package.json b/package.json index e9d8771..93d2423 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "start": "node index.js" }, "dependencies": { - "@fizzxydev/baileys-pro": "latest", + "@whiskeysockets/baileys": "^6.7.16", "@hapi/boom": "^10.0.1", "axios": "^1.4.0", "express": "^4.18.4", "qrcode": "^1.5.1", "sharp": "^0.33.0", - "node-cache": "^5.1.2" + "node-cache": "^5.1.2" } } From 3aca1bbbe2a0fee3f5ca146ffb57ce33bdda76dd Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:16:28 +0200 Subject: [PATCH 30/40] JIOPJO --- index.js | 507 ++++++++----------------------------------------------- 1 file changed, 68 insertions(+), 439 deletions(-) diff --git a/index.js b/index.js index 134decf..fc39eda 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ + const express = require('express'); const qrcode = require('qrcode'); const path = require('path'); @@ -8,11 +9,10 @@ const { useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, - proto, - generateWAMessageFromContent + generateWAMessageFromContent, + proto } = require('@whiskeysockets/baileys'); - const app = express(); app.use(express.json()); app.use(express.static('public')); @@ -21,12 +21,9 @@ let sock; let qrData = null; let isConnected = false; -// 💾 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" }; } @@ -60,18 +57,6 @@ const initBaileys = async () => { sock.ev.on('creds.update', saveCreds); - // 📌 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]; if (!msg.key.fromMe && msg.message?.conversation) { @@ -82,8 +67,6 @@ const initBaileys = async () => { initBaileys(); -app.use('/static', express.static(path.join(__dirname, 'public'))); - app.get('/login', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'login.html')); }); @@ -102,408 +85,12 @@ app.post('/sendText', async (req, res) => { res.status(500).json({ error: e.message }); } }); -app.post('/testButtons', 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, { - 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 - }); - - res.json({ success: true }); - } catch (e) { - console.error('❌ Erreur testButtons :', 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é à WhatsApp' }); - } - - const BASE_URL = process.env.BASE_URL || 'https://wa.canguidev.fr'; - const imageUrl = `${BASE_URL}/static/logo-merlo-cs-FR.jpg`; + if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); const jid = `${phone}@s.whatsapp.net`; - - try { - const content = { - viewOnceMessage: { - message: { - messageContextInfo: { - deviceListMetadata: {}, - deviceListMetadataVersion: 2 - }, - interactiveMessage: proto.Message.InteractiveMessage.create({ - header: { - hasMediaAttachment: true, - imageMessage: { url: imageUrl } - }, - body: { text: "Bienvenue sur notre service !" }, - footer: { text: "Choisis une action ci-dessous" }, - 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" - }) - }, - { - name: "cta_call", - buttonParamsJson: JSON.stringify({ - display_text: "📞 Appeler le support", - id: "+33612345678" - }) - } - ] - } - }) - } - } - }; - - const msg = generateWAMessageFromContent(jid, content, {}); - await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); - - res.json({ success: true }); - } catch (e) { - console.error('❌ Erreur /sendButtons :', e); - res.status(500).json({ error: e.message }); - } -}); - - - -// 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 }); - } -}); - -// 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.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 imageUrl = 'https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg'; const content = { viewOnceMessage: { @@ -515,25 +102,19 @@ app.post('/testInteractiveImage', async (req, res) => { interactiveMessage: proto.Message.InteractiveMessage.create({ header: { hasMediaAttachment: true, - imageMessage: { url: "https://canguidev.fr/static/logo-merlo-cs-FR.jpg" } + imageMessage: { url: imageUrl } }, - body: { text: "Bienvenue chez Merlo France 🇫🇷\nChoisissez une action ci-dessous." }, - footer: { text: "MERLO - Support & Documentation" }, + body: { text: 'Bienvenue !' }, + footer: { text: 'Choisissez une action :' }, nativeFlowMessage: { buttons: [ { - name: "cta_reply", - buttonParamsJson: JSON.stringify({ - display_text: "📩 Contacter support", - id: "support_action" - }) + name: 'cta_reply', + buttonParamsJson: JSON.stringify({ display_text: 'Répondre', id: 'reply_id' }) }, { - name: "cta_url", - buttonParamsJson: JSON.stringify({ - display_text: "🌐 Voir la fiche produit", - url: "https://example.com/product" - }) + name: 'cta_url', + buttonParamsJson: JSON.stringify({ display_text: 'Site Web', url: 'https://canguidev.fr' }) } ] } @@ -541,17 +122,65 @@ app.post('/testInteractiveImage', async (req, res) => { } } }; - - const jid = `${phone}@s.whatsapp.net`; - const msg = generateWAMessageFromContent(jid, content, {}); - await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); - + + try { + const msg = generateWAMessageFromContent(jid, content, {}); + await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); + res.json({ success: true }); + } catch (e) { + console.error('❌ Erreur sendButtons :', e); + res.status(500).json({ error: e.message }); + } +}); + +app.post('/sendInteractiveImage', 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`; + const imageUrl = 'https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg'; + + const content = { + viewOnceMessage: { + message: { + messageContextInfo: { + deviceListMetadata: {}, + deviceListMetadataVersion: 2 + }, + interactiveMessage: proto.Message.InteractiveMessage.create({ + header: { + hasMediaAttachment: true, + imageMessage: { url: imageUrl } + }, + body: { text: '📄 Document interactif' }, + footer: { text: 'Sélectionne une option :' }, + nativeFlowMessage: { + buttons: [ + { + name: 'cta_url', + buttonParamsJson: JSON.stringify({ display_text: 'Voir PDF', url: 'https://example.com/doc.pdf' }) + } + ] + } + }) + } + } + }; + + try { + const msg = generateWAMessageFromContent(jid, content, {}); + await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); + res.json({ success: true }); + } catch (e) { + console.error('❌ Erreur interactive image :', e); + res.status(500).json({ error: e.message }); + } }); -// 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); + console.error('❌ Middleware erreur :', err); res.status(500).json({ error: err.message }); }); -app.listen(3001, () => console.log('🚀 Serveur Baileys démarré sur http://localhost:3001')); + +app.listen(3001, () => console.log('🚀 Serveur Baileys opérationnel sur http://localhost:3001')); From dcb36bf05904f75686adda7af8dcc0dfeeae4097 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:21:45 +0200 Subject: [PATCH 31/40] sddssdsd --- index.js | 209 ++++++++++++++++++++++--------------------------------- 1 file changed, 85 insertions(+), 124 deletions(-) diff --git a/index.js b/index.js index fc39eda..44096bb 100644 --- a/index.js +++ b/index.js @@ -1,54 +1,42 @@ - const express = require('express'); const qrcode = require('qrcode'); -const path = require('path'); -const fs = require('fs'); -const NodeCache = require('node-cache'); const { - makeWASocket, + default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, generateWAMessageFromContent, proto } = require('@whiskeysockets/baileys'); +const { Boom } = require('@hapi/boom'); const app = express(); app.use(express.json()); -app.use(express.static('public')); let sock; -let qrData = null; +let qrCodeData = null; let isConnected = false; -const groupCache = new NodeCache({ stdTTL: 300, useClones: false }); - -async function getMessageFromStore(key) { - return { conversation: "Message temporaire pour retry" }; -} - -const initBaileys = async () => { +async function startSock() { + const { state, saveCreds } = await useMultiFileAuthState('auth_info'); const { version } = await fetchLatestBaileysVersion(); - const { state, saveCreds } = await useMultiFileAuthState('auth'); sock = makeWASocket({ version, auth: state, - markOnlineOnConnect: false, - getMessage: async (key) => await getMessageFromStore(key), - cachedGroupMetadata: async (jid) => groupCache.get(jid) + printQRInTerminal: true }); sock.ev.on('connection.update', async ({ connection, lastDisconnect, qr }) => { if (qr) { - qrData = await qrcode.toDataURL(qr); - isConnected = false; + qrCodeData = await qrcode.toDataURL(qr); } if (connection === 'close') { - const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut; - console.log(shouldReconnect ? '🔁 Reconnexion...' : '❌ Déconnecté.'); - if (shouldReconnect) initBaileys(); + const shouldReconnect = (lastDisconnect?.error instanceof Boom) + && lastDisconnect.error.output.statusCode !== DisconnectReason.loggedOut; + console.log('❌ Déconnecté. Reconnexion :', shouldReconnect); + if (shouldReconnect) startSock(); } else if (connection === 'open') { console.log('✅ Connecté à WhatsApp'); isConnected = true; @@ -56,28 +44,17 @@ const initBaileys = async () => { }); sock.ev.on('creds.update', saveCreds); +} - sock.ev.on('messages.upsert', async ({ messages }) => { - const msg = messages[0]; - if (!msg.key.fromMe && msg.message?.conversation) { - console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); - } - }); -}; - -initBaileys(); - -app.get('/login', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'login.html')); -}); - +startSock(); app.get('/api/qrcode', (req, res) => { - res.json({ qr: qrData, connected: isConnected }); + res.json({ qr: qrCodeData, 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 }); @@ -86,101 +63,85 @@ app.post('/sendText', async (req, res) => { } }); -app.post('/sendButtons', async (req, res) => { +app.post('/sendImage', async (req, res) => { + const { phone, imageUrl, caption } = req.body; + if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + + try { + await sock.sendMessage(`${phone}@s.whatsapp.net`, { + image: { url: imageUrl }, + caption: caption || '' + }); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.post('/sendDocument', async (req, res) => { + const { phone, documentUrl, fileName, mimetype } = req.body; + if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + + try { + await sock.sendMessage(`${phone}@s.whatsapp.net`, { + document: { url: documentUrl }, + fileName: fileName || 'fichier.pdf', + mimetype: mimetype || 'application/pdf' + }); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); +app.post('/sendInteractive', async (req, res) => { const { phone } = req.body; if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); - const jid = `${phone}@s.whatsapp.net`; - const imageUrl = 'https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg'; - - const content = { - viewOnceMessage: { - message: { - messageContextInfo: { - deviceListMetadata: {}, - deviceListMetadataVersion: 2 - }, - interactiveMessage: proto.Message.InteractiveMessage.create({ - header: { - hasMediaAttachment: true, - imageMessage: { url: imageUrl } - }, - body: { text: 'Bienvenue !' }, - footer: { text: 'Choisissez une action :' }, - nativeFlowMessage: { - buttons: [ - { - name: 'cta_reply', - buttonParamsJson: JSON.stringify({ display_text: 'Répondre', id: 'reply_id' }) - }, - { - name: 'cta_url', - buttonParamsJson: JSON.stringify({ display_text: 'Site Web', url: 'https://canguidev.fr' }) - } - ] - } - }) - } - } - }; try { + const jid = `${phone}@s.whatsapp.net`; + const content = { + viewOnceMessage: { + message: { + messageContextInfo: { + deviceListMetadata: {}, + deviceListMetadataVersion: 2 + }, + interactiveMessage: proto.Message.InteractiveMessage.create({ + body: { text: 'Bienvenue ! Choisissez une action :' }, + footer: { text: 'Service WhatsApp' }, + nativeFlowMessage: { + buttons: [ + { + name: 'cta_reply', + buttonParamsJson: JSON.stringify({ + display_text: '✅ Confirmer', + id: 'confirm_action' + }) + }, + { + name: 'cta_url', + buttonParamsJson: JSON.stringify({ + display_text: '🌐 Site Web', + url: 'https://canguidev.fr' + }) + } + ] + } + }) + } + } + }; + const msg = generateWAMessageFromContent(jid, content, {}); await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); + res.json({ success: true }); } catch (e) { - console.error('❌ Erreur sendButtons :', e); + console.error('❌ Erreur interactive :', e); res.status(500).json({ error: e.message }); } }); - -app.post('/sendInteractiveImage', 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`; - const imageUrl = 'https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg'; - - const content = { - viewOnceMessage: { - message: { - messageContextInfo: { - deviceListMetadata: {}, - deviceListMetadataVersion: 2 - }, - interactiveMessage: proto.Message.InteractiveMessage.create({ - header: { - hasMediaAttachment: true, - imageMessage: { url: imageUrl } - }, - body: { text: '📄 Document interactif' }, - footer: { text: 'Sélectionne une option :' }, - nativeFlowMessage: { - buttons: [ - { - name: 'cta_url', - buttonParamsJson: JSON.stringify({ display_text: 'Voir PDF', url: 'https://example.com/doc.pdf' }) - } - ] - } - }) - } - } - }; - - try { - const msg = generateWAMessageFromContent(jid, content, {}); - await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); - res.json({ success: true }); - } catch (e) { - console.error('❌ Erreur interactive image :', e); - res.status(500).json({ error: e.message }); - } +const PORT = process.env.PORT || 3001; +app.listen(PORT, () => { + console.log(`🚀 Serveur prêt sur http://localhost:${PORT}`); }); - -app.use((req, res) => res.status(404).json({ error: 'Ressource introuvable' })); -app.use((err, req, res, next) => { - console.error('❌ Middleware erreur :', err); - res.status(500).json({ error: err.message }); -}); - -app.listen(3001, () => console.log('🚀 Serveur Baileys opérationnel sur http://localhost:3001')); From a23a3e064a23c13e2b4e6d72c215945d5302ddcc Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:23:06 +0200 Subject: [PATCH 32/40] xwwxxw --- public/login.html | 144 +++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 97 deletions(-) diff --git a/public/login.html b/public/login.html index 44fad60..50ccbf2 100644 --- a/public/login.html +++ b/public/login.html @@ -2,116 +2,66 @@ - Connexion WhatsApp & Envoi Interactif + Connexion WhatsApp -

Scanne le QR Code WhatsApp

-
Chargement...
+

Connexion WhatsApp

+

Scannez le QR Code avec votre application WhatsApp

-
- -

Envoyer du message interactif avec image

-
- - - - - - - - -
-
+
+ QR Code WhatsApp +
Chargement du QR code...
+
From 0028c5080c0543802caa72ac4b5dc5531d03e37a Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:24:10 +0200 Subject: [PATCH 33/40] jjj --- index.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/index.js b/index.js index 44096bb..9b078a4 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,15 @@ const { Boom } = require('@hapi/boom'); const app = express(); app.use(express.json()); +const path = require('path'); // à ajouter en haut si pas encore importé + +// Sert les fichiers statiques depuis le dossier "public" +app.use(express.static('public')); + +// Route pour afficher la page de login avec QR code +app.get('/login', (req, res) => { + res.sendFile(path.join(__dirname, 'public', 'login.html')); +}); let sock; let qrCodeData = null; From db94c8a111745f3a11aa1b03a55692bfbcf21241 Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 22:25:52 +0200 Subject: [PATCH 34/40] ghghg --- index.js | 541 ++++++++++++++++++++++++++++++++++++++++++++------- package.json | 4 +- 2 files changed, 472 insertions(+), 73 deletions(-) diff --git a/index.js b/index.js index 9b078a4..9393e2f 100644 --- a/index.js +++ b/index.js @@ -1,51 +1,56 @@ const express = require('express'); const qrcode = require('qrcode'); +const path = require('path'); +const fs = require('fs'); +const NodeCache = require('node-cache'); const { default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, - generateWAMessageFromContent, - proto -} = require('@whiskeysockets/baileys'); -const { Boom } = require('@hapi/boom'); + proto, + generateWAMessageFromContent +} = require('@fizzxydev/baileys-pro'); const app = express(); app.use(express.json()); -const path = require('path'); // à ajouter en haut si pas encore importé - -// Sert les fichiers statiques depuis le dossier "public" app.use(express.static('public')); -// Route pour afficher la page de login avec QR code -app.get('/login', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'login.html')); -}); - let sock; -let qrCodeData = null; +let qrData = null; let isConnected = false; -async function startSock() { - const { state, saveCreds } = await useMultiFileAuthState('auth_info'); +// 💾 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 () => { const { version } = await fetchLatestBaileysVersion(); + const { state, saveCreds } = await useMultiFileAuthState('auth'); sock = makeWASocket({ version, auth: state, - printQRInTerminal: true + markOnlineOnConnect: false, + getMessage: async (key) => await getMessageFromStore(key), + cachedGroupMetadata: async (jid) => groupCache.get(jid) }); sock.ev.on('connection.update', async ({ connection, lastDisconnect, qr }) => { if (qr) { - qrCodeData = await qrcode.toDataURL(qr); + qrData = await qrcode.toDataURL(qr); + isConnected = false; } if (connection === 'close') { - const shouldReconnect = (lastDisconnect?.error instanceof Boom) - && lastDisconnect.error.output.statusCode !== DisconnectReason.loggedOut; - console.log('❌ Déconnecté. Reconnexion :', shouldReconnect); - if (shouldReconnect) startSock(); + const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut; + console.log(shouldReconnect ? '🔁 Reconnexion...' : '❌ Déconnecté.'); + if (shouldReconnect) initBaileys(); } else if (connection === 'open') { console.log('✅ Connecté à WhatsApp'); isConnected = true; @@ -53,17 +58,42 @@ async function startSock() { }); sock.ev.on('creds.update', saveCreds); -} -startSock(); + // 📌 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]; + if (!msg.key.fromMe && msg.message?.conversation) { + console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); + } + }); +}; + +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: qrCodeData, connected: isConnected }); + 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 }); @@ -71,43 +101,99 @@ app.post('/sendText', async (req, res) => { res.status(500).json({ error: e.message }); } }); - -app.post('/sendImage', async (req, res) => { - const { phone, imageUrl, caption } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); - - try { - await sock.sendMessage(`${phone}@s.whatsapp.net`, { - image: { url: imageUrl }, - caption: caption || '' - }); - res.json({ success: true }); - } catch (e) { - res.status(500).json({ error: e.message }); - } -}); - -app.post('/sendDocument', async (req, res) => { - const { phone, documentUrl, fileName, mimetype } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); - - try { - await sock.sendMessage(`${phone}@s.whatsapp.net`, { - document: { url: documentUrl }, - fileName: fileName || 'fichier.pdf', - mimetype: mimetype || 'application/pdf' - }); - res.json({ success: true }); - } catch (e) { - res.status(500).json({ error: e.message }); - } -}); -app.post('/sendInteractive', async (req, res) => { +app.post('/testButtons', async (req, res) => { const { phone } = req.body; - if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' }); + + if (!sock || !isConnected) { + return res.status(400).json({ error: 'Non connecté' }); + } + + const jid = `${phone}@s.whatsapp.net`; + + try { + 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 + }); + + res.json({ success: true }); + } catch (e) { + console.error('❌ Erreur testButtons :', 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é' }); + } + + 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`; try { - const jid = `${phone}@s.whatsapp.net`; const content = { viewOnceMessage: { message: { @@ -116,22 +202,33 @@ app.post('/sendInteractive', async (req, res) => { deviceListMetadataVersion: 2 }, interactiveMessage: proto.Message.InteractiveMessage.create({ - body: { text: 'Bienvenue ! Choisissez une action :' }, - footer: { text: 'Service WhatsApp' }, + body: { text: "Bienvenue sur notre service !" }, + footer: { text: "Choisis une action ci-dessous" }, + header: { + hasMediaAttachment: true, + imageMessage: { url: imageUrl } + }, nativeFlowMessage: { buttons: [ { - name: 'cta_reply', + name: "cta_reply", buttonParamsJson: JSON.stringify({ - display_text: '✅ Confirmer', - id: 'confirm_action' + display_text: "📩 Contacter support", + id: "support_action" }) }, { - name: 'cta_url', + name: "cta_url", buttonParamsJson: JSON.stringify({ - display_text: '🌐 Site Web', - url: 'https://canguidev.fr' + display_text: "🌐 Voir notre site", + url: "https://canguidev.fr" + }) + }, + { + name: "cta_call", + buttonParamsJson: JSON.stringify({ + display_text: "📞 Appeler le support", + id: "+33612345678" }) } ] @@ -146,11 +243,313 @@ app.post('/sendInteractive', async (req, res) => { res.json({ success: true }); } catch (e) { - console.error('❌ Erreur interactive :', e); + console.error('❌ Erreur bouton actif :', e); res.status(500).json({ error: e.message }); } }); -const PORT = process.env.PORT || 3001; -app.listen(PORT, () => { - console.log(`🚀 Serveur prêt sur http://localhost:${PORT}`); + + +// 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 }); + } }); + +// 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.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 }); + +}); + +// 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 }); +}); +app.listen(3001, () => console.log('🚀 Serveur Baileys démarré sur http://localhost:3001')); diff --git a/package.json b/package.json index 93d2423..e9d8771 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "start": "node index.js" }, "dependencies": { - "@whiskeysockets/baileys": "^6.7.16", + "@fizzxydev/baileys-pro": "latest", "@hapi/boom": "^10.0.1", "axios": "^1.4.0", "express": "^4.18.4", "qrcode": "^1.5.1", "sharp": "^0.33.0", - "node-cache": "^5.1.2" + "node-cache": "^5.1.2" } } From ddcda51e1d3d6c67f110607b9f3d19e206d81140 Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 07:16:23 +0200 Subject: [PATCH 35/40] DFDFFDFD --- index.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/index.js b/index.js index 9393e2f..d0fa998 100644 --- a/index.js +++ b/index.js @@ -76,6 +76,27 @@ const initBaileys = async () => { if (!msg.key.fromMe && msg.message?.conversation) { console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); } + if (buttonId === 'doc_1') { + await sock.sendMessage(jid, { + document: { + url: 'hhttps://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf', + }, + 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: { + url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf', + }, + mimetype: 'application/pdf', + fileName: 'Document_2.pdf', + caption: 'Voici votre *Document 2* 📄', + footer: '© Fizzxy Dev', + }); + } }); }; @@ -545,6 +566,42 @@ const msg = generateWAMessageFromContent(jid, content, {}); await sock.relayMessage(jid, msg.message, { messageId: msg.key.id }); }); +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 }); + } +}); + // 5) 404 et gestion des erreurs app.use((req, res) => res.status(404).json({ error: 'Ressource introuvable' })); From 609d2f076d825c39b0161e44ea01e52bd030f905 Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 07:19:18 +0200 Subject: [PATCH 36/40] lkkkklkl --- index.js | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index d0fa998..8bc1ffe 100644 --- a/index.js +++ b/index.js @@ -73,29 +73,35 @@ const initBaileys = async () => { // (Facultatif) Gestion des messages reçus sock.ev.on('messages.upsert', async ({ messages }) => { const msg = messages[0]; + if (!msg.key.fromMe && msg.message?.conversation) { console.log('💬 Message reçu de', msg.key.remoteJid, ':', msg.message.conversation); } - if (buttonId === 'doc_1') { - await sock.sendMessage(jid, { - document: { - url: 'hhttps://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf', - }, - 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: { - url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf', - }, - mimetype: 'application/pdf', - fileName: 'Document_2.pdf', - caption: 'Voici votre *Document 2* 📄', - footer: '© Fizzxy Dev', - }); + 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: { + url: 'https://wa.canguidev.fr/static/document1.pdf', + }, + 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: { + url: 'https://wa.canguidev.fr/static/document2.pdf', + }, + mimetype: 'application/pdf', + fileName: 'Document_2.pdf', + caption: 'Voici votre *Document 2* 📄', + footer: '© Fizzxy Dev', + }); + } } }); }; From a1b111abea837212bf9ed41f27759e9fabc8e573 Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 07:34:09 +0200 Subject: [PATCH 37/40] ffddfdf --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 8bc1ffe..85589b1 100644 --- a/index.js +++ b/index.js @@ -84,7 +84,7 @@ const initBaileys = async () => { if (buttonId === 'doc_1') { await sock.sendMessage(jid, { document: { - url: 'https://wa.canguidev.fr/static/document1.pdf', + url: 'https://merlo-ch.com/uploads/proposition/f_p_250505_0000136_00008_EB00001909.pdf', }, mimetype: 'application/pdf', fileName: 'Document_1.pdf', @@ -94,7 +94,7 @@ const initBaileys = async () => { } else if (buttonId === 'doc_2') { await sock.sendMessage(jid, { document: { - url: 'https://wa.canguidev.fr/static/document2.pdf', + url: 'https://merlo-ch.com/uploads/proposition/d_p_250505_0000136_00008_EB00001909.pdf', }, mimetype: 'application/pdf', fileName: 'Document_2.pdf', From 60f0425f38c8f6637d38949c20b12b4baaa9e529 Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 08:00:58 +0200 Subject: [PATCH 38/40] PEPEPPEPEPE --- index.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/index.js b/index.js index 85589b1..0850d46 100644 --- a/index.js +++ b/index.js @@ -607,6 +607,47 @@ app.post('/testButtons2', async (req, res) => { res.status(500).json({ error: e.message }); } }); +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`; + + try { + await sock.sendMessage(jid, { + text: 'Hello World!', + footer: '© Fizzxy Dev', + templateButtons: [ + { + index: 0, + urlButton: { + displayText: 'Visiter Site', + url: 'https://google.fr' + } + }, + { + index: 1, + urlButton: { + displayText: 'Voir logo', + url: 'https://google.fr' + } + } + ] + }, { + quoted: null + }); + + + res.json({ success: true }); + + } catch (e) { + console.error('❌ Erreur testButtons :', e); + res.status(500).json({ error: e.message }); + } +}); // 5) 404 et gestion des erreurs From 412e6b888c6f7c9349e82755c6406b1cd3a06b2a Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 08:06:19 +0200 Subject: [PATCH 39/40] EDSDSDSDS --- index.js | 86 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/index.js b/index.js index 0850d46..7e4f0ae 100644 --- a/index.js +++ b/index.js @@ -615,30 +615,72 @@ app.post('/testButtons3', async (req, res) => { } const jid = `${phone}@s.whatsapp.net`; + 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": "" + } + ], + }) + }) + } + } + }, {}) try { - await sock.sendMessage(jid, { - text: 'Hello World!', - footer: '© Fizzxy Dev', - templateButtons: [ - { - index: 0, - urlButton: { - displayText: 'Visiter Site', - url: 'https://google.fr' - } - }, - { - index: 1, - urlButton: { - displayText: 'Voir logo', - url: 'https://google.fr' - } - } - ] - }, { - quoted: null - }); + await sock.relayMessage(msg.key.remoteJid, msg.message, { messageId: msg.key.id }) res.json({ success: true }); From 15e5852440e045e5e8529d63206d79288ac62dab Mon Sep 17 00:00:00 2001 From: cangui Date: Wed, 7 May 2025 08:11:04 +0200 Subject: [PATCH 40/40] SQSQSQSQ --- index.js | 72 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/index.js b/index.js index 7e4f0ae..cfb60ea 100644 --- a/index.js +++ b/index.js @@ -356,44 +356,44 @@ app.post('/sendInteractiveImage', async (req, res) => { } }); -// 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é' }); +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); + 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 }); -// } -// }); + 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.post('/sendProductMessage', async (req, res) => { // On vérifie sock et isConnected, pas client if (!sock || !isConnected) {