
Security News
rv Is a New Rust-Powered Ruby Version Manager Inspired by Python's uv
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
wa-multi-mongodb
Advanced tools
This repository is a modified version of @mimamch/wa-multi-session with MongoDB session management integration. The original repository uses file-based session storage, while this version uses MongoDB for better scalability and session management.
Lightweight library for WhatsApp with MongoDB integration. No Selenium or browser required.
Built on Baileys Library.
Install package using npm:
npm install wa-multi-mongodb@latest
Then import into your code:
// Using ES modules
import * as whatsapp from "wa-multi-mongodb";
// Or using CommonJS
const whatsapp = require("wa-multi-mongodb");
For secure MongoDB URI management, we recommend using environment variables:
Create a .env
file in your project root (copy from .env.example
):
# MongoDB Configuration
MONGODB_URI=mongodb://username:password@hostname:port/database
# Optional database settings
WA_DB_NAME=wa_session
WA_COLLECTION_NAME=auth
Install and use the dotenv package:
// Load environment variables
require('dotenv').config();
// Use in your code
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
console.error('Error: MONGODB_URI not found in environment variables');
process.exit(1);
}
// Initialize WhatsApp with MongoDB
await whatsapp.setMongoURI(MONGODB_URI);
Make sure to add .env
to your .gitignore
file to prevent exposing sensitive credentials
Make sure MongoDB is running (local/cloud)
Configure the connection using one of these methods:
Using environment variables (recommended):
require('dotenv').config();
await whatsapp.setMongoURI(process.env.MONGODB_URI);
Directly in code (not recommended for production):
await whatsapp.setMongoURI("mongodb+srv://username:password@host/db?options");
Optionally customize the database and collection names:
// Default values are "wa_session" and "auth"
whatsapp.setMongoDBNames("custom_database_name", "custom_collection_name");
// Start a new session with QR Code
const session = await whatsapp.startSession("mysession");
// Start with options
await whatsapp.startSession("mysession2", {
printQR: true,
onConnected: () => console.log("Connected!"),
onDisconnected: () => console.log("Disconnected!"),
onQRUpdated: (qr) => {
console.log("New QR:", qr);
// QR data is raw and ready for frontend use
// You can display this in React, Vue, Angular, etc.
}
});
// Start session with Pairing Code (v3.9.6+)
await whatsapp.startSessionWithPairingCode("mysession3", {
mobile: "6281234567890", // your phone number with country code
onConnected: () => console.log("Pairing session connected!"),
onDisconnected: () => console.log("Pairing session disconnected!"),
onPairingCode: (code) => {
console.log("Pairing code:", code);
// Enter this code in your WhatsApp app: Settings > Linked Devices > Link a Device > Link with phone number
}
});
// Get all active sessions
const sessions = await whatsapp.getAllSession();
// Get data for a specific session
const sessionData = whatsapp.getSession("mysession");
// Load all saved sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Session Management Utilities (v3.9.6+)
// Get session status with detailed information
const status = await whatsapp.getSessionStatus("mysession");
console.log("Session status:", status);
// Returns: { exists: true, connected: true, sessionType: 'qr' | 'pairing' }
// Manual reconnection for any session
try {
const reconnected = await whatsapp.reconnect("mysession");
console.log("Reconnection successful:", reconnected);
} catch (error) {
console.error("Reconnection failed:", error);
}
// Get all pairing code sessions
const pairingSessions = whatsapp.getPairingCodeSessions();
console.log("Pairing code sessions:", pairingSessions);
// Bulk reconnect all pairing code sessions
await whatsapp.reconnectAllPairingCodeSessions();
// Send text message
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "6281234567890", // always include country code
text: "Hello from wa-multi-mongodb!"
// isGroup parameter is optional (v3.9.0+)
// The library will automatically detect if the destination is a group
});
// Send to a group (automatic detection in v3.9.0+)
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "120363152682073800", // group ID
text: "Hello group!"
// No need for isGroup: true parameter in v3.9.0+
});
// Send to a group (compatible with older versions)
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "120363152682073800", // group ID
text: "Hello group!",
isGroup: true // still works but optional in v3.9.0+
});
// Send media (unified function)
await whatsapp.sendMedia({
sessionId: "mysession",
to: "6281234567890",
type: "image", // options: image, video, pdf, doc, docx, xls, xlsx, zip, mp3
media: fs.readFileSync("./image.jpg"), // or URL string
caption: "Image caption",
fileName: "image.jpg", // required for documents
// isGroup parameter is optional (v3.9.0+)
});
// Send voice note
await whatsapp.sendVoiceNote({
sessionId: "mysession",
to: "6281234567890",
media: fs.readFileSync("./audio.mp3"),
// isGroup parameter is optional (v3.9.0+)
});
// Mark message as read
await whatsapp.readMessage({
sessionId: "mysession",
key: msg.key,
});
// Send typing indicator
await whatsapp.sendTyping({
sessionId: "mysession",
to: "6281234567890", // or group ID
duration: 3000, // milliseconds
// isGroup parameter is optional (v3.9.0+)
});
// Delete message (v3.9.5+)
// Delete own message for everyone
await whatsapp.deleteMessage({
sessionId: "mysession",
key: messageObject.key, // message key from received or sent message
});
// Delete someone else's message (requires admin permissions in groups)
await whatsapp.deleteMessage({
sessionId: "mysession",
key: {
remoteJid: "120363152682073800@g.us", // group ID with @g.us
fromMe: false,
id: "MESSAGE_ID",
participant: "SENDER_JID" // required for group messages
}
});
// Auto-delete message after delay (helper function example)
function autoDeleteMessage(sessionId, message, delayMs = 3000) {
setTimeout(async () => {
try {
await whatsapp.deleteMessage({
sessionId: sessionId,
key: message.key
});
} catch (error) {
console.error("Error auto-deleting message:", error);
}
}, delayMs);
}
// Send text message with mention (v3.9.8+)
// Mention one user in a group
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890@g.us", // group JID
text: "Halo @6281234567890, selamat datang di grup!",
mentions: ["6281234567890@s.whatsapp.net"], // JID to mention
isGroup: true
});
// Mention multiple users in a group
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890@g.us",
text: "Halo @6281234567890 dan @6289876543210, ada yang bisa saya bantu?",
mentions: [
"6281234567890@s.whatsapp.net",
"6289876543210@s.whatsapp.net"
],
isGroup: true
});
// Mention in private chat (less common but supported)
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890",
text: "Halo @6281234567890, ini adalah pesan pribadi dengan mention",
mentions: ["6281234567890@s.whatsapp.net"]
});
// Alternative: Use sendTextMessage with mentions property
// You can also use the regular sendTextMessage with mentions
const session = whatsapp.getSession("mysession");
if (session) {
await session.sendMessage(
"6281234567890@g.us",
{
text: "Halo @6281234567890, ini pesan dengan mention!",
mentions: ["6281234567890@s.whatsapp.net"]
},
{
quoted: null // or message to quote
}
);
}
// Incoming messages
whatsapp.onMessageReceived((msg) => {
console.log(`Message from ${msg.key.remoteJid}:`, msg);
});
// QR code updates
whatsapp.onQRUpdated(({ sessionId, qr }) => {
console.log(`QR Code for ${sessionId}:`, qr);
// You can display this QR in a UI or save it to a file
});
// Connection events
whatsapp.onConnected((sessionId) => {
console.log(`Session ${sessionId} connected`);
});
whatsapp.onDisconnected((sessionId) => {
console.log(`Session ${sessionId} disconnected`);
});
whatsapp.onMessageReceived(async (msg) => {
if (msg.message?.imageMessage) {
await msg.saveImage("./saved-image.jpg");
}
if (msg.message?.videoMessage) {
await msg.saveVideo("./saved-video.mp4");
}
if (msg.message?.documentMessage) {
await msg.saveDocument("./saved-document"); // extension will be added automatically
}
if (msg.message?.audioMessage) {
await msg.saveAudio("./saved-audio.mp3");
}
});
The library now implements a hybrid caching system for group metadata using both in-memory (NodeCache) and persistent storage (MongoDB). This significantly improves performance for applications that frequently use group metadata information.
// Configure cache settings (optional, has default values)
whatsapp.setGroupCacheConfig({
stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
checkperiod: 120 // Check for expired keys every 2 minutes
});
// Get group metadata (automatically uses cache if available)
const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
console.log(`Group name: ${metadata.subject}`);
console.log(`Participants: ${metadata.participants.length}`);
console.log(`Created on: ${new Date(metadata.creation * 1000).toLocaleString()}`);
// Force fetch fresh data from server and update cache
const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
// Clear cache for specific group in a specific session
await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
// Clear all group metadata cache for a specific session
await whatsapp.clearSessionGroupMetadataCache(sessionId);
// Clear all cached group metadata for all sessions
whatsapp.clearAllGroupMetadataCache();
Benefits of the hybrid caching system:
The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
This approach ensures that in multi-session environments:
// Create a delay
import { createDelay } from "wa-multi-mongodb";
await createDelay(2000); // wait 2 seconds
// Execute with timeout
import { withTimeout } from "wa-multi-mongodb";
try {
const result = await withTimeout(
functionThatMightTakeTooLong(),
10000, // timeout in ms
"Operation timed out" // error message if timeout occurs
);
} catch (error) {
console.error(error.message);
}
// Attempt to reconnect a session
import { reconnect } from "wa-multi-mongodb";
try {
const reconnected = await reconnect("mysession");
console.log("Reconnect successful:", reconnected);
} catch (error) {
console.error("Reconnect failed:", error);
}
import * as whatsapp from "wa-multi-mongodb";
import { withTimeout } from "wa-multi-mongodb";
require('dotenv').config();
// Store connection status
const sessionStatus = {};
// Function to check and reconnect if disconnected
async function checkAndReconnect(sessionId) {
if (sessionStatus[sessionId] === 'disconnected') {
try {
const reconnected = await whatsapp.reconnect(sessionId);
if (reconnected) {
sessionStatus[sessionId] = 'connected';
console.log(`Session ${sessionId} reconnected`);
}
} catch (error) {
console.error(`Error during reconnect: ${error.message}`);
}
}
}
async function startApp() {
// MongoDB Configuration
await whatsapp.setMongoURI(process.env.MONGODB_URI);
// Event listeners
whatsapp.onQRUpdated(({ sessionId, qr }) => {
console.log(`QR Code for session ${sessionId}:`, qr);
});
whatsapp.onConnected((sessionId) => {
console.log(`Session ${sessionId} connected!`);
sessionStatus[sessionId] = 'connected';
});
whatsapp.onDisconnected((sessionId) => {
console.log(`Session ${sessionId} disconnected!`);
sessionStatus[sessionId] = 'disconnected';
// Try to reconnect after a few seconds
setTimeout(() => checkAndReconnect(sessionId), 10000);
});
// Message handler with error handling and group detection
whatsapp.onMessageReceived(async (msg) => {
try {
if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
const messageContent = msg.message?.conversation ||
msg.message?.extendedTextMessage?.text ||
"";
// Detect if message is from a group
const isGroup = msg.key.remoteJid.endsWith('@g.us');
// Using group metadata cache (v3.9.4+)
if (isGroup) {
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
console.log(`Message from group: ${metadata.subject} with ${metadata.participants.length} members`);
}
// Mark message as read
try {
await whatsapp.readMessage({
sessionId: msg.sessionId,
key: msg.key,
});
} catch (error) {
if (error.message.includes('Connection Closed')) {
sessionStatus[msg.sessionId] = 'disconnected';
setTimeout(() => checkAndReconnect(msg.sessionId), 5000);
}
}
// Reply to messages containing "hello"
if (messageContent.toLowerCase().includes("hello")) {
// Show typing indicator (works in both private and group chats since v3.9.1+)
await whatsapp.sendTyping({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
duration: 2000,
});
// Use different timeouts for groups vs private chats
const timeoutMs = isGroup ? 60000 : 30000;
try {
await withTimeout(
whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: "Hello! How can I help you?",
answering: msg,
}),
timeoutMs,
"Message sending timed out"
);
} catch (error) {
console.error("Error sending message:", error.message);
}
}
// Example command to get group info
if (messageContent === "!groupinfo" && isGroup) {
try {
// Force fetch fresh data
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
const adminList = metadata.participants
.filter(p => p.admin)
.map(p => p.id.split('@')[0])
.join(", ");
const infoText = `*Group Info*\n` +
`Name: ${metadata.subject}\n` +
`Description: ${metadata.desc || 'None'}\n` +
`Members: ${metadata.participants.length}\n` +
`Admins: ${adminList}\n` +
`Created: ${new Date(metadata.creation * 1000).toLocaleString()}`;
await whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: infoText
});
} catch (error) {
console.error("Error getting group info:", error.message);
}
}
} catch (error) {
// Prevent application crash
console.error("Error processing message:", error.message);
}
});
// Load all sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Create a main session if it doesn't exist
const mainSession = "main_session";
const existingSessions = await whatsapp.getAllSession();
if (!existingSessions.includes(mainSession)) {
await whatsapp.startSession(mainSession);
} else {
sessionStatus[mainSession] = 'connected';
}
// Check connections periodically
setInterval(() => {
Object.keys(sessionStatus).forEach(sid => {
checkAndReconnect(sid);
});
}, 5 * 60 * 1000); // check every 5 minutes
}
startApp().catch(err => {
console.error("Failed to start application:", err);
process.exit(1);
});
import * as whatsapp from "wa-multi-mongodb";
require('dotenv').config();
// Store connection status
const sessionStatus = {};
async function startPairingApp() {
// MongoDB Configuration
await whatsapp.setMongoURI(process.env.MONGODB_URI);
// Event listeners for pairing code sessions
whatsapp.onConnected((sessionId) => {
console.log(`Pairing session ${sessionId} connected!`);
sessionStatus[sessionId] = 'connected';
});
whatsapp.onDisconnected(async (sessionId) => {
console.log(`Pairing session ${sessionId} disconnected!`);
sessionStatus[sessionId] = 'disconnected';
// Check if it's a pairing code session
const status = await whatsapp.getSessionStatus(sessionId);
if (status.sessionType === 'pairing') {
console.log(`Attempting to reconnect pairing session ${sessionId}...`);
// Auto-reconnect after 5 seconds
setTimeout(async () => {
try {
const reconnected = await whatsapp.reconnect(sessionId);
if (reconnected) {
console.log(`Pairing session ${sessionId} reconnected successfully!`);
sessionStatus[sessionId] = 'connected';
}
} catch (error) {
console.error(`Failed to reconnect pairing session ${sessionId}:`, error);
}
}, 5000);
}
});
// Message handler
whatsapp.onMessageReceived(async (msg) => {
if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
const messageContent = msg.message?.conversation ||
msg.message?.extendedTextMessage?.text ||
"";
console.log(`Message from ${msg.key.remoteJid}: ${messageContent}`);
// Auto-reply example
if (messageContent.toLowerCase().includes("ping")) {
await whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: "Pong! Message received from pairing session.",
answering: msg
});
}
});
// Load existing sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Start a new pairing code session
const pairingSessionId = "pairing_session_1";
const yourPhoneNumber = "6281234567890"; // Replace with your phone number
try {
await whatsapp.startSessionWithPairingCode(pairingSessionId, {
mobile: yourPhoneNumber,
onConnected: () => {
console.log("Pairing session connected successfully!");
sessionStatus[pairingSessionId] = 'connected';
},
onDisconnected: () => {
console.log("Pairing session disconnected!");
sessionStatus[pairingSessionId] = 'disconnected';
},
onPairingCode: (code) => {
console.log("\n" + "=".repeat(50));
console.log("📱 PAIRING CODE:", code);
console.log("=".repeat(50));
console.log("1. Open WhatsApp on your phone");
console.log("2. Go to Settings > Linked Devices");
console.log("3. Tap 'Link a Device'");
console.log("4. Tap 'Link with phone number instead'");
console.log("5. Enter the pairing code above");
console.log("=".repeat(50) + "\n");
}
});
sessionStatus[pairingSessionId] = 'connecting';
} catch (error) {
console.error("Error starting pairing session:", error);
}
// Periodic health check for pairing sessions
setInterval(async () => {
const pairingSessions = whatsapp.getPairingCodeSessions();
console.log(`Active pairing sessions: ${pairingSessions.length}`);
// Check each pairing session status
for (const sessionId of pairingSessions) {
const status = await whatsapp.getSessionStatus(sessionId);
console.log(`Session ${sessionId}: ${status.connected ? 'Connected' : 'Disconnected'}`);
if (!status.connected && sessionStatus[sessionId] === 'connected') {
console.log(`Detected disconnection for ${sessionId}, attempting reconnect...`);
try {
await whatsapp.reconnect(sessionId);
} catch (error) {
console.error(`Reconnect failed for ${sessionId}:`, error);
}
}
}
}, 30000); // Check every 30 seconds
// Bulk reconnect utility
setInterval(async () => {
try {
await whatsapp.reconnectAllPairingCodeSessions();
console.log("Bulk reconnect completed for all pairing sessions");
} catch (error) {
console.error("Bulk reconnect failed:", error);
}
}, 10 * 60 * 1000); // Every 10 minutes
console.log("Pairing code application started!");
}
startPairingApp().catch(err => {
console.error("Failed to start pairing application:", err);
process.exit(1);
});
// React.js example for QR code display
import React, { useState, useEffect } from 'react';
import QRCode from 'qrcode';
import * as whatsapp from "wa-multi-mongodb";
function WhatsAppQRComponent() {
const [qrDataURL, setQrDataURL] = useState('');
const [sessionStatus, setSessionStatus] = useState('disconnected');
useEffect(() => {
// Initialize WhatsApp connection
const initWhatsApp = async () => {
await whatsapp.setMongoURI(process.env.REACT_APP_MONGODB_URI);
// Start session with simplified QR callback
await whatsapp.startSession("frontend_session", {
printQR: false, // Don't print in terminal
onQRUpdated: async (qr) => {
// QR data is raw and ready for frontend use
try {
const qrDataURL = await QRCode.toDataURL(qr);
setQrDataURL(qrDataURL);
} catch (error) {
console.error('Error generating QR code:', error);
}
},
onConnected: () => {
setSessionStatus('connected');
setQrDataURL(''); // Clear QR when connected
},
onDisconnected: () => {
setSessionStatus('disconnected');
}
});
};
initWhatsApp().catch(console.error);
}, []);
return (
<div className="whatsapp-qr">
<h2>WhatsApp Connection</h2>
<div className="status">
Status: <span className={sessionStatus}>{sessionStatus}</span>
</div>
{qrDataURL && (
<div className="qr-container">
<p>Scan this QR code with WhatsApp:</p>
<img src={qrDataURL} alt="WhatsApp QR Code" />
</div>
)}
{sessionStatus === 'connected' && (
<div className="connected">
<p>✅ WhatsApp connected successfully!</p>
</div>
)}
</div>
);
}
export default WhatsAppQRComponent;
MessageCounterError
(handled automatically in v3.9.1+)sendTextMessageWithMention
Function: Comprehensive mention functionality for WhatsApp messages (v3.9.8+)sendTextMessageWithMention
Function: Comprehensive mention functionality for WhatsApp messages
messages.upsert
now processes all messages in array instead of only the first messagestartSessionWithPairingCode()
function for creating sessions using pairing codesreconnect(sessionId)
- Manual reconnection for any session typereconnectAllPairingCodeSessions()
- Bulk reconnection for all tracked pairing code sessionsgetPairingCodeSessions()
- Get list of all pairing code session IDsgetSessionStatus(sessionId)
- Get detailed session status information including session typeprintQR
optiononQRUpdated
callback signature: removed qrString
parameter, now only provides raw QR dataonQRUpdated
option simplified from (qr, qrString)
to (qr)
onlydeleteMessage()
function for deleting messagesgetGroupMetadata()
- Get metadata with automatic cachingsetGroupCacheConfig()
- Configure cache TTL and check periodsclearGroupMetadataCache()
- Clear specific group metadataclearAllGroupMetadataCache()
- Clear all cached group metadataprintQRInTerminal
option with qrcode
library implementationMessageCounterError
in group chats with announcement channelsisGroup: true
parameterISC
FAQs
Multi Session Whatsapp Library with MongoDB Integration
We found that wa-multi-mongodb demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.
Security News
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.