whatsapp/index.js
2025-05-07 17:15:56 +02:00

217 lines
6.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const qrcode = require('qrcode');
const path = require('path');
const fs = require('fs');
const NodeCache = require('node-cache');
const mime = require('mime-types');
const fetch = require('node-fetch'); // en haut si pas encore ajouté
const {
default: makeWASocket,
useMultiFileAuthState,
DisconnectReason,
fetchLatestBaileysVersion,
proto,
generateWAMessageFromContent,
prepareWAMessageMedia,
generateWAMessageContent
} = require('@fizzxydev/baileys-pro');
const app = express();
const http = require('http');
const WebSocket = require('ws');
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
function broadcastToClients(data) {
const message = JSON.stringify(data);
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
}
app.use(express.json());
app.use(express.static('public'));
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" };
}
app.post('/webhook/status', (req, res) => {
console.log('📩 Webhook reçu :', req.body);
res.sendStatus(200);
});
const initBaileys = async () => {
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)
});
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;
console.log(shouldReconnect ? '🔁 Reconnexion...' : '❌ Déconnecté.');
if (shouldReconnect) initBaileys();
} else if (connection === 'open') {
console.log('✅ Connecté à WhatsApp');
isConnected = true;
}
});
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);
}
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://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',
});
}
}
});
sock.ev.on('messages.update', async (updates) => {
broadcastToClients({
messageId,
status,
jid
});
});
};
initBaileys();
app.use('/static', express.static(path.join(__dirname, 'public')));
app.get('/login', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'login.html'));
});
app.get('/api/qrcode', (req, res) => {
res.json({ qr: qrData, connected: isConnected });
});
app.post('/sendText', async (req, res) => {
const { phone, message } = req.body;
if (!sock || !isConnected) return res.status(400).json({ error: 'Non connecté' });
try {
await sock.sendMessage(`${phone}@s.whatsapp.net`, { text: message });
res.json({ success: true });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
//// ***** bonne route ****** ///
/* exemple de json
*{
"phone": "33617452235",
"imageUrl": "https://wa.canguidev.fr/static/logo-merlo-cs-FR.jpg",
"caption": "🟢 Offre spéciale !\n📅 Merlo2025\n\nBonjour M. Jérôme VANDEMEULEBROUCK,\n\nSuite à nos échanges, je vous transmets l'offre que je vous propose.\nVous trouverez ci-joint votre offre au format PDF.\n\n📄 Proposition : https://pvmel.fr/V5Pi\n🛠 Descriptif machine : \n\n—\nCanguilième Julien\n📎 Votre offre en PDF ci-joint."
}
*
*/
app.post('/sendImageWithBaileysPro', async (req, res) => {
if (!sock || !isConnected) {
return res.status(400).json({ error: 'Non connecté à WhatsApp' });
}
const {
phone,
imageUrl,
caption,
quoted,
} = req.body;
if (!phone || !imageUrl) {
return res.status(400).json({ error: 'Paramètres requis manquants (phone, imageUrl)' });
}
const jid = `${phone}@s.whatsapp.net`;
try {
await sock.sendMessage(
jid,
{
image: { url: imageUrl },
caption: caption || '',
},
quoted ? { quoted } : {}
);
res.json({ success: true, to: jid });
} catch (e) {
console.error('❌ Erreur /sendImageWithBaileysPro :', e);
res.status(500).json({ error: e.message });
}
});
app.use((req, res) => res.status(404).json({ error: 'Ressource introuvable' }));
app.use((err, req, res, next) => {
console.error('Middleware derreur :', err);
res.status(500).json({ error: err.message });
});
app.listen(3001, () => console.log('🚀 Serveur Baileys démarré sur http://localhost:3001'));