commit 7b1c28bca7ac5a4083df641565eac1286ba83f9f
parent 4968e0af9a9c9c601e6e674adb1ad3d6074019ce
Author: AMIT DUTTA <amitdutta4255@gmail.com>
Date: Mon, 16 Feb 2026 18:28:48 +0530
Refactor Firestore message saving for idempotency
Updated Firestore message saving to use .set() for idempotency. Changed document ID to use WhatsApp message ID to prevent duplicates.
Diffstat:
| M | index.js | | | 28 | +++++++++++++++------------- |
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/index.js b/index.js
@@ -115,14 +115,21 @@ async function startWhatsApp() {
// Determine name: Use "Me" for outgoing, otherwise pushName or Unknown
const senderName = isFromMe ? "Me" : (msg.pushName || "Unknown");
- await db.collection('Chats').doc(remoteJid).collection('Messages').add({
- text: textContent,
- senderId: remoteJid,
- senderName: senderName,
- timestamp: timestamp,
- fromMe: isFromMe,
- id: msg.key.id
- });
+ // --- SAVE TO FIRESTORE ---
+ // UPDATE: Using .doc(msg.key.id).set(...) instead of .add(...)
+ // This ensures IDEMPOTENCY. If the same message arrives twice, it won't duplicate.
+ await db.collection('Chats')
+ .doc(remoteJid)
+ .collection('Messages')
+ .doc(msg.key.id) // <--- CRITICAL CHANGE: Use WhatsApp ID as Doc ID
+ .set({
+ text: textContent,
+ senderId: remoteJid,
+ senderName: senderName,
+ timestamp: timestamp,
+ fromMe: isFromMe,
+ id: msg.key.id
+ }, { merge: true }); // Merge ensures we don't accidentally wipe fields if we add more later
} catch (err) {
// Silent error handling
@@ -134,15 +141,12 @@ async function startWhatsApp() {
// --- EXPRESS ROUTES ---
// 1. PUBLIC ROUTE: Ping (Must be before Auth middleware)
-// This allows UptimeRobot to keep the server alive without needing a password.
app.get('/ping', (req, res) => {
res.status(200).send('Pong');
});
// --- MIDDLEWARE: BASIC AUTH ---
-// All routes defined BELOW this point will require a password.
const checkAuth = (req, res, next) => {
- // If vars aren't set in Render, allow access (fallback)
if (!AUTH_USER || !AUTH_PASS) return next();
const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
@@ -159,12 +163,10 @@ const checkAuth = (req, res, next) => {
app.use(checkAuth);
// 2. PROTECTED ROUTE: Serve Static Frontend
-// If you put index.html in a 'public' folder, it will be served here.
app.use(express.static(path.join(__dirname, 'public')));
// 3. PROTECTED ROUTE: Main Page (QR Code or Status)
app.get('/', async (req, res) => {
- // Check isConnected variable
if (isConnected) {
return res.send(`
<html>