const venom = require('venom-bot'); const express = require('express'); const qrcode = require('qrcode'); const path = require('path'); const fs = require('fs'); const app = express(); app.use(express.json()); app.use(express.static('public')); let client; 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; }); } }); client.onStateChange((state) => { console.log('État de connexion:', state); isConnected = state === 'CONNECTED'; if (state === 'DISCONNECTED') { console.log('🔁 Tentative de reconnexion...'); setTimeout(initVenom, 5000); } }); }; initVenom(); // Routes Express app.use('/static', express.static(path.join(__dirname, 'public'))); app.get('/login', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'login.html')); }); app.get('/api/qrcode', (req, res) => { res.json({ qr: qrData, connected: isConnected }); }); app.post('/sendText', async (req, res) => { const { phone, message } = req.body; if (!client || !isConnected) return res.status(400).json({ error: 'Non connecté' }); try { await client.sendText(`${phone}@c.us`, message); res.json({ success: true }); } catch (e) { res.status(500).json({ error: e.message }); } }); app.post('/sendButtons', async (req, res) => { const { phone } = req.body; if (!client || !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 } ] } ); res.json({ success: true }); } catch (e) { console.error('❌ Erreur image interactive:', 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é' }); const { phone, productImageUrl, productTitle, productDescription, price, productUrl } = 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 caption = `*${productTitle}*\n\n${productDescription}\n\nPrix: ${price}`; await client.sendImage( `${phone}@c.us`, productImageUrl, 'product.jpg', caption, { buttons } ); res.json({ success: true }); } catch (e) { console.error('❌ Erreur produit:', e); res.status(500).json({ error: e.message }); } }); // Gestion des erreurs app.use((req, res) => res.status(404).json({ error: 'Ressource introuvable' })); app.use((err, req, res, next) => { console.error('Erreur:', err); res.status(500).json({ error: err.message }); }); app.listen(3001, () => console.log('🚀 Serveur Venom démarré sur http://localhost:3001'));