@simo777/whatsapp-baileys-plugin
v1.0.1
Published
Fastify plugin for WhatsApp messaging via Baileys — session management, message persistence, contact sync, media handling, and webhook events.
Readme
WhatsApp Baileys Plugin for Fastify
A powerful Fastify plugin to integrate WhatsApp messaging into your applications using Baileys. This plugin provides session management, message persistence (via Prisma), contact synchronization, media handling, and webhook event notifications.
Features
- Session Management: Create and manage multiple WhatsApp sessions.
- Message Persistence: Automatically stores inbound and outbound messages in a database.
- Reply & Mention Support: Native support for replying to specific messages and mentioning users.
- Channel (Newsletter) Support: Seamlessly send text and media to WhatsApp Channels.
- Contact Sync: Synchronizes WhatsApp contacts and groups.
- Advanced Media Handling:
- Cloudflare R2 Support: Upload media locally or to R2 buckets.
- Image Processing: Automatic conversion to WebP/JPEG/PNG with quality and resize controls via Sharp.
- Metadata Extraction: Automatically captures width, height, and duration.
- Webhooks & Filtering: Real-time event notifications with topic-based filtering.
- Interactive API Docs: Built-in Swagger support for easy testing.
Installation
pnpm add @simo777/whatsapp-baileys-pluginUsage
Register the plugin in your Fastify application. You can pass options directly or rely on your app's environment configuration.
import Fastify from 'fastify';
import whatsappPlugin from '@simo777/whatsapp-baileys-plugin';
const app = Fastify();
// Ensure Prisma is registered before the plugin if you don't pass it in options
// app.register(prismaPlugin);
await app.register(whatsappPlugin, {
prefix: '/api/v1', // Optional: Prefix for plugin routes
prisma: myPrismaClient, // Optional: Pass your Prisma instance
storage: {
provider: 'local', // or 'r2'
localPath: './uploads',
publicUrl: 'http://localhost:3002/uploads',
defaultPath: 'storage/whatsapp'
},
gatewayUrl: 'http://localhost:3000'
});
app.listen({ port: 3002 });Database & Prisma Setup
This plugin requires Prisma. You must include the following models and enums in your project's schema.prisma file.
1. Update your schema.prisma
model Session {
id String @id @default(uuid())
name String
webhookUrl String?
topics String[] @default([])
status SessionStatus @default(DISCONNECTED)
whatsappNumber String?
whatsappName String?
authData SessionAuth[]
contacts Contact[]
messages Message[]
media Media[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum SessionStatus {
DISCONNECTED
CONNECTING
QR
OPEN
LOGGED_OUT
}
model SessionAuth {
id String
sessionId String
data String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
updatedAt DateTime @default(now()) @updatedAt
@@id([sessionId, id])
@@index([sessionId, updatedAt])
}
model Contact {
id String @id @default(uuid())
sessionId String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
jid String
lid String?
phone String?
phoneType PhoneType @default(SECONDARY)
savedName String?
pushName String?
profilePicUrl String?
profilePicPath String?
profilePicUpdatedAt DateTime?
isGroup Boolean @default(false)
isBlocked Boolean @default(false)
isArchived Boolean @default(false)
messages Message[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([sessionId, jid])
@@index([sessionId])
@@index([sessionId, lid])
@@index([sessionId, isGroup])
@@index([phone])
}
enum PhoneType {
PRIMARY
SECONDARY
}
model Message {
id String @id @default(uuid())
sessionId String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
contactId String
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
waMessageId String
direction MessageDirection
status MessageStatus @default(SENT)
type String
body String?
mediaId String?
media Media? @relation(fields: [mediaId], references: [id])
reactions Reaction[]
quotedMessageId String?
waTimestamp BigInt
isGroup Boolean @default(false)
senderContactId String?
raw Bytes?
createdAt DateTime @default(now())
@@unique([sessionId, waMessageId])
@@index([sessionId, contactId])
@@index([contactId, waTimestamp])
@@index([sessionId, direction])
@@index([sessionId, createdAt])
@@index([sessionId, senderContactId])
}
model Reaction {
id String @id @default(uuid())
text String
senderJid String
createdAt DateTime @default(now())
message Message? @relation(fields: [messageId], references: [id], onDelete: Cascade)
messageId String?
@@unique([messageId, senderJid])
}
enum MessageDirection {
INBOUND
OUTBOUND
OUTBOUND_USER
}
enum MessageStatus {
SENT
DELIVERED
READ
PLAYED
FAILED
}
model Media {
id String @id @default(uuid())
sessionId String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
key String @unique
provider String
originalName String
message Message[]
type String
mimeType String?
path String
size Int?
url String
hash String @unique
width Int?
height Int?
duration Int?
createdAt DateTime @default(now())
@@index([sessionId])
@@index([type])
@@index([hash])
}Configuration Options
| Option | Type | Description |
| :--- | :--- | :--- |
| prisma | PrismaClient | Your Prisma client instance. |
| prefix | string | Route prefix (e.g., /api/v1). |
| storage.provider | 'local' \| 'r2' | Where to store media attachments. |
| storage.localPath | string | Local folder for uploads. |
| storage.publicUrl | string | Base URL for accessing media. |
| gatewayUrl | string | Public URL for media links in messages. |
| imageProcess | object | Options for Sharp image optimization. |
Webhook Topics
You can filter events by providing a topics list when creating a session or via the update route:
message.inboundmessage.outbound_usermessage.outbound_botmessage.deletedmessage.reactionreceipt.updatesession.statussession.migratedcontact.updatedcontact.presence
Created with ❤️ for the Fastify community.
