### Run Real-Flow Example Source: https://github.com/vinikjkkj/zapo/blob/master/README.md Execute the provided real-flow example to test the WhatsApp Web connection. ```bash npm run example ``` -------------------------------- ### Install Dependencies Source: https://github.com/vinikjkkj/zapo/blob/master/README.md Install the project dependencies using npm. ```bash npm install ``` -------------------------------- ### Initialize Zapo Client Source: https://github.com/vinikjkkj/zapo/blob/master/README.md Sets up the logger, store, and WaClient for Zapo JS. Ensure you have the necessary dependencies installed. ```typescript import { createPinoLogger, createStore, WaClient } from 'zapo-js' import { createSqliteStore } from '@zapo-js/store-sqlite' const logger = await createPinoLogger({ level: 'info', pretty: true }) const store = createStore({ backends: { sqlite: createSqliteStore({ path: '.auth/state.sqlite', driver: 'auto' }) }, providers: { auth: 'sqlite', signal: 'sqlite', preKey: 'sqlite', session: 'sqlite', identity: 'sqlite', senderKey: 'sqlite', appState: 'sqlite', messages: 'sqlite', threads: 'sqlite', contacts: 'sqlite' } }) const client = new WaClient( { store, sessionId: 'default', connectTimeoutMs: 15_000, nodeQueryTimeoutMs: 30_000, history: { enabled: true, requireFullSync: true } }, logger ) client.on('auth_qr', ({ qr, ttlMs }) => { console.log('qr', { qr, ttlMs }) }) client.on('message', (event) => { console.log('incoming', { chatJid: event.chatJid, senderJid: event.senderJid }) }) await client.connect() ``` -------------------------------- ### Sending Messages with WaClient.sendMessage() Source: https://context7.com/vinikjkkj/zapo/llms.txt Demonstrates various ways to send messages, including text, media, and structured messages, with examples for individual and group chats. ```APIDOC ## POST /api/messages ### Description Send text messages, media, or structured WhatsApp message types to individuals or groups. Returns a promise with the message ID and acknowledgment details. ### Method POST ### Endpoint /api/messages ### Parameters #### Query Parameters - **to** (string) - Required - The recipient's JID (e.g., '5511999999999@s.whatsapp.net' or '123456789-1234567890@g.us'). #### Request Body - **message** (object | string) - Required - The message content. Can be a string for plain text, or an object for structured messages (e.g., image, document, extended text). - **type** (string) - Optional - For media messages (e.g., 'image', 'document'). - **media** (Buffer) - Required for media messages - The media content. - **mimetype** (string) - Required for media messages - The MIME type of the media. - **caption** (string) - Optional - Caption for media messages. - **fileName** (string) - Optional - Filename for document messages. - **extendedTextMessage** (object) - Optional - For structured text messages. - **text** (string) - Required - The main text content. - **matchedText** (string) - Optional - Text that was matched to trigger this message. - **canonicalUrl** (string) - Optional - The canonical URL for a link preview. - **title** (string) - Optional - The title for a link preview. - **description** (string) - Optional - The description for a link preview. ### Request Example ```json { "to": "5511999999999@s.whatsapp.net", "message": { "type": "image", "media": "", "mimetype": "image/jpeg", "caption": "Check out this photo!" } } ``` ### Response #### Success Response (200) - **id** (string) - The unique ID of the sent message. - **ack** (number) - Acknowledgment status of the message. #### Response Example ```json { "id": "true_1234567890@broadcast.whatsapp.net", "ack": 1 } ``` ``` -------------------------------- ### Configure SQLite Store with createStore() Source: https://context7.com/vinikjkkj/zapo/llms.txt Set up a SQLite-backed store for persistence, recommended for single-instance deployments. Specify the database path and driver. All essential data providers are configured to use the SQLite backend. ```typescript import { createStore } from 'zapo-js' import { createSqliteStore } from '@zapo-js/store-sqlite' // SQLite-backed store (recommended for single-instance deployments) const sqliteStore = createStore({ backends: { sqlite: createSqliteStore({ path: './data/zapo.sqlite', driver: 'auto' // Uses better-sqlite3 if available }) }, providers: { auth: 'sqlite', signal: 'sqlite', senderKey: 'sqlite', appState: 'sqlite', messages: 'sqlite', threads: 'sqlite', contacts: 'sqlite', privacyToken: 'sqlite' } }) ``` -------------------------------- ### Configure PostgreSQL Store with createStore() Source: https://context7.com/vinikjkkj/zapo/llms.txt Configure a PostgreSQL-backed store for multi-instance deployments. Provide the connection string and specify which data providers should use the PostgreSQL backend. ```typescript import { createStore } from 'zapo-js' import { createPostgresStore } from '@zapo-js/store-postgres' // PostgreSQL-backed store (for multi-instance deployments) const pgStore = createStore({ backends: { postgres: createPostgresStore({ connectionString: 'postgres://user:pass@localhost:5432/zapo' }) }, providers: { auth: 'postgres', signal: 'postgres', senderKey: 'postgres', appState: 'postgres', messages: 'postgres', threads: 'postgres', contacts: 'postgres' } }) ``` -------------------------------- ### Create WaClient Instance with SQLite Store Source: https://context7.com/vinikjkkj/zapo/llms.txt Instantiate the WaClient with a persistent SQLite store and optional logger. Configure connection and query timeouts, and device details. ```typescript import { createPinoLogger, createStore, WaClient } from 'zapo-js' import { createSqliteStore } from '@zapo-js/store-sqlite' // Create a logger (optional but recommended) const logger = await createPinoLogger({ level: 'info', pretty: true }) // Create a SQLite-backed store for persistence const store = createStore({ backends: { sqlite: createSqliteStore({ path: '.auth/state.sqlite', driver: 'auto' }) }, providers: { auth: 'sqlite', signal: 'sqlite', senderKey: 'sqlite', appState: 'sqlite', messages: 'sqlite', threads: 'sqlite', contacts: 'sqlite', privacyToken: 'sqlite' } }) // Create the client const client = new WaClient( { store, sessionId: 'my-session', connectTimeoutMs: 15_000, nodeQueryTimeoutMs: 30_000, deviceBrowser: 'Chrome', deviceOsDisplayName: 'Windows', history: { enabled: true, requireFullSync: true } }, logger ) ``` -------------------------------- ### Configure Memory Store with createStore() Source: https://context7.com/vinikjkkj/zapo/llms.txt Set up a memory-only store for testing purposes. Note that data will be lost upon application restart. Authentication requires a persistent backend and will throw an error if configured for memory. ```typescript // Memory-only store (for testing, data lost on restart) const memoryStore = createStore({ backends: {}, providers: { auth: 'memory', // Will throw - auth requires persistent backend signal: 'memory', senderKey: 'memory', appState: 'memory' }, memory: { limits: { signalPreKeys: 100, signalSessions: 500, messages: 10000 } } }) ``` -------------------------------- ### createStore() - Storage Configuration Source: https://context7.com/vinikjkkj/zapo/llms.txt Creates a unified store instance for managing persistence needs with support for multiple backends and configurable providers. ```APIDOC ## createStore() - Storage Configuration The `createStore()` function creates a unified store instance that manages all persistence needs. It supports multiple backends (memory, SQLite, PostgreSQL, MySQL, MongoDB, Redis) with configurable providers for each data domain. ### SQLite-backed Store Recommended for single-instance deployments. **Method:** `createStore(options)` **Parameters:** - **backends.sqlite** (object) - Configuration for the SQLite backend. - **path** (string) - Path to the SQLite database file. - **driver** (string) - Database driver (e.g., 'auto'). - **providers** (object) - Mapping of data domains to backend providers. - **auth** (string) - Required - Authentication credentials provider. - **signal** (string) - Signal protocol keys provider. - **senderKey** (string) - Group encryption keys provider. - **appState** (string) - Chat state (archive, pin, mute) provider. - **messages** (string) - Message history provider. - **threads** (string) - Thread/conversation list provider. - **contacts** (string) - Contact information provider. - **privacyToken** (string) - Privacy tokens for trusted contacts provider. ### PostgreSQL-backed Store Suitable for multi-instance deployments. **Parameters:** - **backends.postgres** (object) - Configuration for the PostgreSQL backend. - **connectionString** (string) - PostgreSQL connection string. - **providers** (object) - Mapping of data domains to backend providers (e.g., 'postgres'). ### Memory-only Store For testing purposes; data is lost on restart. **Parameters:** - **backends** (object) - Should be empty `{}` for memory-only. - **providers** (object) - Mapping of data domains to 'memory' provider. - **auth** (string) - 'memory' (Note: Will throw an error as auth requires a persistent backend). - **signal** (string) - 'memory'. - **senderKey** (string) - 'memory'. - **appState** (string) - 'memory'. - **memory.limits** (object) - Optional - Limits for memory storage. - **signalPreKeys** (number) - Limit for signal pre-keys. - **signalSessions** (number) - Limit for signal sessions. - **messages** (number) - Limit for messages. ### Request Example (SQLite) ```typescript import { createStore } from 'zapo-js' import { createSqliteStore } from '@zapo-js/store-sqlite' const sqliteStore = createStore({ backends: { sqlite: createSqliteStore({ path: './data/zapo.sqlite', driver: 'auto' }) }, providers: { auth: 'sqlite', signal: 'sqlite', senderKey: 'sqlite', appState: 'sqlite', messages: 'sqlite', threads: 'sqlite', contacts: 'sqlite', privacyToken: 'sqlite' } }) ``` ### Request Example (PostgreSQL) ```typescript import { createStore } from 'zapo-js' import { createPostgresStore } from '@zapo-js/store-postgres' const pgStore = createStore({ backends: { postgres: createPostgresStore({ connectionString: 'postgres://user:pass@localhost:5432/zapo' }) }, providers: { auth: 'postgres', signal: 'postgres', senderKey: 'postgres', appState: 'postgres', messages: 'postgres', threads: 'postgres', contacts: 'postgres' } }) ``` ### Request Example (Memory) ```typescript import { createStore } from 'zapo-js' const memoryStore = createStore({ backends: {}, providers: { auth: 'memory', signal: 'memory', senderKey: 'memory', appState: 'memory' }, memory: { limits: { signalPreKeys: 100, signalSessions: 500, messages: 10000 } } }) ``` ``` -------------------------------- ### Logging Configuration Source: https://context7.com/vinikjkkj/zapo/llms.txt Configure structured logging using Pino or a simple console logger. ```APIDOC ## Logging Configuration ### Description Zapo supports structured logging via Pino or a simple console logger. Configure log levels to control verbosity. ### Method POST ### Endpoint /vinikjkkj/zapo/configureLogger ### Parameters #### Request Body - **loggerType** (string) - Required - Type of logger to use ('pino' or 'console'). - **options** (object) - Optional - Configuration options for the logger. - **level** (string) - Optional - Log level ('trace', 'debug', 'info', 'warn', 'error'). Defaults to 'info'. - **name** (string) - Optional - Name of the logger (for Pino). - **pretty** (boolean) - Optional - Enable pretty printing (for Pino). - **prettyOptions** (object) - Optional - Options for pretty printing (for Pino). - **pinoOptions** (object) - Optional - Additional Pino options. ### Request Example ```json { "loggerType": "pino", "options": { "level": "debug", "pretty": true, "prettyOptions": { "colorize": true, "translateTime": "HH:MM:ss" } } } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating logger configuration. #### Response Example ```json { "message": "Logger configured successfully" } ``` ``` -------------------------------- ### Connect to WhatsApp and Handle Authentication Events Source: https://context7.com/vinikjkkj/zapo/llms.txt Establish a WebSocket connection to WhatsApp servers and handle authentication events like QR code display and successful pairing. This method reuses existing sessions if available. ```typescript // Set up event listeners before connecting client.on('auth_qr', ({ qr, ttlMs }) => { // Display QR code for user to scan console.log(`Scan this QR code (expires in ${ttlMs}ms):`, qr) }) client.on('auth_paired', ({ credentials }) => { console.log(`Successfully paired! JID: ${credentials.meJid}`) }) client.on('connection', (event) => { if (event.status === 'open') { console.log('Connected to WhatsApp') } else if (event.status === 'close') { console.log(`Disconnected: ${event.reason}`) } }) // Connect (will reuse existing session if available) await client.connect() ``` -------------------------------- ### Configure Zapo Logging with Pino Source: https://context7.com/vinikjkkj/zapo/llms.txt Configures structured logging for Zapo using Pino, supporting different log levels and pretty output for development. Production logging should use JSON output. ```typescript import { createPinoLogger, ConsoleLogger } from 'zapo-js' // Production logging with Pino const pinoLogger = await createPinoLogger({ level: 'info', // 'trace', 'debug', 'info', 'warn', 'error' name: 'zapo-app', pretty: false, // JSON output for production pinoOptions: { // Any additional pino options } }) ``` ```typescript // Development logging with pretty output const devLogger = await createPinoLogger({ level: 'debug', pretty: true, prettyOptions: { colorize: true, translateTime: 'HH:MM:ss' } }) ``` ```typescript // Simple console logger (no dependencies) const consoleLogger = new ConsoleLogger('info') ``` ```typescript // Use with client const client = new WaClient({ store, sessionId: 'main' }, pinoLogger) ``` -------------------------------- ### WaClient.syncAppState() - App State Synchronization Source: https://context7.com/vinikjkkj/zapo/llms.txt Synchronize app state collections (archived chats, pinned chats, muted chats, starred messages) with WhatsApp servers. ```APIDOC ## WaClient.syncAppState() ### Description Synchronize app state collections (archived chats, pinned chats, muted chats, starred messages) with WhatsApp servers. ### Method POST ### Endpoint /vinikjkkj/zapo/syncAppState ### Parameters #### Query Parameters - **collections** (array) - Optional - Specify which collections to sync. If not provided, all collections are synced. ### Request Example ```json { "collections": ["regular", "regular_high"] } ``` ### Response #### Success Response (200) - **collections** (array) - An array of collection synchronization results. - **collection** (string) - The name of the collection. - **state** (string) - The synchronization state of the collection. - **mutations** (array) - An array of mutations applied to the collection (optional). #### Response Example ```json { "collections": [ { "collection": "regular", "state": "synced", "mutations": [ { "id": "12345", "type": "add" } ] } ] } ``` ## WaClient.exportAppState() ### Description Export the current app state, which can be useful for debugging purposes. ### Method GET ### Endpoint /vinikjkkj/zapo/exportAppState ### Response #### Success Response (200) - **keys** (array) - An array of synchronization keys. ### Response Example ```json { "keys": ["key1", "key2"] } ``` ``` -------------------------------- ### Receiving Messages and Events with WaClient Events Source: https://context7.com/vinikjkkj/zapo/llms.txt Details on how to subscribe to various client events to handle incoming messages, receipts, group updates, and more. ```APIDOC ## Events ### Description The client emits various events for incoming messages, receipts, presence updates, and more. Subscribe to these events to build reactive WhatsApp integrations. ### Method Event Subscription ### Endpoint N/A (Client-side event listeners) ### Event Listeners - **message**: Fired when an incoming message is received. - **event** (object) - Contains message details like `senderJid`, `chatJid`, and `message` content. - **message.conversation** (string) - Plain text content. - **message.extendedTextMessage.text** (string) - Text content from extended text messages. - **message.imageMessage** (object) - Indicates an image message was received. - **message_receipt**: Fired for message receipt updates (e.g., delivered, read). - **event** (object) - Contains `stanzaId` and `stanzaType`. - **group_event**: Fired for group-related events (e.g., participant join/leave, admin changes). - **event** (object) - Contains `action`, `groupJid`, and optional `participants`. - **chat_event**: Fired for chat-level events (e.g., archive, pin, mute). - **event** (object) - Contains `action` and `chatJid`. - **history_sync_chunk**: Fired during history synchronization. - **event** (object) - Contains `messagesCount` and `conversationsCount`. ### Request Example ```javascript client.on('message', async (event) => { console.log(`Message from ${event.senderJid} in ${event.chatJid}`); if (event.message?.conversation === 'ping') { await client.sendMessage(event.chatJid, 'pong!'); } }); ``` ### Response N/A (Events are handled via callbacks) ``` -------------------------------- ### Release Flow with Changesets Source: https://github.com/vinikjkkj/zapo/blob/master/README.md Manages project versioning and releases using Changesets. This sequence of commands is used for creating and publishing new versions. ```bash npm run changeset npm run changeset:status npm run version:packages npm run release:publish ``` -------------------------------- ### Download and Decrypt Media with WaClient Source: https://context7.com/vinikjkkj/zapo/llms.txt Use this to download and decrypt media files like images from messages. Ensure you have the directPath and mediaKey from the message object. For large files, use downloadAndDecryptStream. ```typescript const mediaClient = client.mediaTransfer // Download and decrypt media from a message const imageMessage = event.message?.imageMessage if (imageMessage?.directPath && imageMessage?.mediaKey) { const decrypted = await mediaClient.downloadAndDecrypt({ mediaType: 'image', directPath: imageMessage.directPath, mediaKey: imageMessage.mediaKey, fileSha256: imageMessage.fileSha256, fileEncSha256: imageMessage.fileEncSha256 }) // Save to file import { writeFileSync } from 'node:fs' writeFileSync('./downloaded-image.jpg', decrypted) } ``` ```typescript // Stream download for large files const videoMessage = event.message?.videoMessage if (videoMessage?.directPath && videoMessage?.mediaKey) { const stream = await mediaClient.downloadAndDecryptStream({ mediaType: 'video', directPath: videoMessage.directPath, mediaKey: videoMessage.mediaKey }) // Pipe to file import { createWriteStream } from 'node:fs' import { pipeline } from 'node:stream/promises' await pipeline(stream.plaintext, createWriteStream('./video.mp4')) } ``` -------------------------------- ### Sending Messages with WaClient Source: https://context7.com/vinikjkkj/zapo/llms.txt Use these methods to send text, media, or structured messages to individuals or groups. Ensure necessary imports like readFileSync are included when handling local media files. ```typescript // Send a simple text message const result = await client.sendMessage('5511999999999@s.whatsapp.net', 'Hello, World!') console.log(`Message sent with ID: ${result.id}`) // Send a text message with extended formatting await client.sendMessage('5511999999999@s.whatsapp.net', { extendedTextMessage: { text: 'Check out this link!', matchedText: 'https://example.com', canonicalUrl: 'https://example.com', title: 'Example Site', description: 'An example website' } }) // Send an image with caption import { readFileSync } from 'node:fs' await client.sendMessage('5511999999999@s.whatsapp.net', { type: 'image', media: readFileSync('./photo.jpg'), mimetype: 'image/jpeg', caption: 'Check out this photo!' }) // Send a document await client.sendMessage('5511999999999@s.whatsapp.net', { type: 'document', media: readFileSync('./document.pdf'), mimetype: 'application/pdf', fileName: 'report.pdf' }) // Send to a group await client.sendMessage('123456789-1234567890@g.us', 'Hello group!') ``` -------------------------------- ### Manage Profile Information with WaClient.profile Source: https://context7.com/vinikjkkj/zapo/llms.txt Retrieve and update profile pictures, status text, and batch profile data. ```typescript // Get profile picture URL const picture = await client.profile.getProfilePicture('5511999999999@s.whatsapp.net') if (picture.url) { console.log('Profile picture URL:', picture.url) } // Set your own profile picture import { readFileSync } from 'node:fs' const imageBytes = readFileSync('./profile.jpg') const pictureId = await client.profile.setProfilePicture(imageBytes) console.log('Profile picture updated, ID:', pictureId) // Delete your profile picture await client.profile.deleteProfilePicture() // Get user status (about) const status = await client.profile.getStatus('5511999999999@s.whatsapp.net') console.log('Status:', status.status) // Set your own status await client.profile.setStatus('Available') // Get multiple profiles at once const profiles = await client.profile.getProfiles([ '5511999999999@s.whatsapp.net', '5511888888888@s.whatsapp.net' ]) for (const profile of profiles) { console.log(`${profile.jid}: picture=${profile.pictureId}, status=${profile.status}`) } ``` -------------------------------- ### Request Pairing Code for Phone Number Authentication Source: https://context7.com/vinikjkkj/zapo/llms.txt Initiate phone number pairing by requesting a code for a given phone number. Ensure the client is connected and listen for the 'auth_pairing_code' event. ```typescript // First connect to get authentication state await client.connect() // Listen for the pairing code event client.on('auth_pairing_code', ({ code }) => { console.log(`Enter this code on your phone: ${code}`) }) // Request pairing code for a phone number (with country code, no + or spaces) const pairingCode = await client.requestPairingCode('15551234567') console.log(`Pairing code sent: ${pairingCode}`) ``` -------------------------------- ### Configure Privacy Settings with WaClient.privacy Source: https://context7.com/vinikjkkj/zapo/llms.txt Manage privacy visibility settings and blocklist operations. ```typescript // Get current privacy settings const settings = await client.privacy.getPrivacySettings() console.log('Last seen:', settings.lastSeen) console.log('Profile photo:', settings.profilePhoto) console.log('Status:', settings.status) console.log('Read receipts:', settings.readReceipts) // Update privacy settings // Values: 'all', 'contacts', 'contact_blacklist', 'none' await client.privacy.setPrivacySetting('lastSeen', 'contacts') await client.privacy.setPrivacySetting('profilePhoto', 'contacts') await client.privacy.setPrivacySetting('status', 'all') // Get blocked users const blocklist = await client.privacy.getBlocklist() console.log('Blocked users:', blocklist.jids) // Block/unblock users await client.privacy.blockUser('5511999999999@s.whatsapp.net') await client.privacy.unblockUser('5511999999999@s.whatsapp.net') ``` -------------------------------- ### WaClient.mediaTransfer - Media Handling Source: https://context7.com/vinikjkkj/zapo/llms.txt Handles encrypted upload and download of media files (images, videos, documents, audio, stickers). ```APIDOC ## WaClient.mediaTransfer - Media Handling The media transfer client handles encrypted upload and download of media files for images, videos, documents, audio, and stickers. ### Download and Decrypt Media This function downloads and decrypts media from a message. **Method:** `client.mediaTransfer.downloadAndDecrypt` **Parameters:** - **mediaType** (string) - Required - Type of media (e.g., 'image', 'video'). - **directPath** (string) - Required - Direct path to the media. - **mediaKey** (Buffer) - Required - The media key for decryption. - **fileSha256** (Buffer) - Optional - SHA256 hash of the file. - **fileEncSha256** (Buffer) - Optional - SHA256 hash of the encrypted file. ### Stream Download for Large Files This function streams and decrypts large media files. **Method:** `client.mediaTransfer.downloadAndDecryptStream` **Parameters:** - **mediaType** (string) - Required - Type of media (e.g., 'image', 'video'). - **directPath** (string) - Required - Direct path to the media. - **mediaKey** (Buffer) - Required - The media key for decryption. ### Request Example (Download) ```typescript const imageMessage = event.message?.imageMessage if (imageMessage?.directPath && imageMessage?.mediaKey) { const decrypted = await mediaClient.downloadAndDecrypt({ mediaType: 'image', directPath: imageMessage.directPath, mediaKey: imageMessage.mediaKey, fileSha256: imageMessage.fileSha256, fileEncSha256: imageMessage.fileEncSha256 }) // Save to file import { writeFileSync } from 'node:fs' writeFileSync('./downloaded-image.jpg', decrypted) } ``` ### Request Example (Stream) ```typescript const videoMessage = event.message?.videoMessage if (videoMessage?.directPath && videoMessage?.mediaKey) { const stream = await mediaClient.downloadAndDecryptStream({ mediaType: 'video', directPath: videoMessage.directPath, mediaKey: videoMessage.mediaKey }) // Pipe to file import { createWriteStream } from 'node:fs' import { pipeline } from 'node:stream/promises' await pipeline(stream.plaintext, createWriteStream('./video.mp4')) } ``` ``` -------------------------------- ### Managing Groups with WaClient Source: https://context7.com/vinikjkkj/zapo/llms.txt Perform administrative tasks such as querying metadata, managing participants, and updating group settings. Most methods require a valid group JID. ```typescript // Query metadata for a specific group const metadata = await client.group.queryGroupMetadata('123456789-1234567890@g.us') console.log(`Group: ${metadata.subject}`) console.log(`Participants: ${metadata.participants.length}`) console.log(`Admins: ${metadata.participants.filter(p => p.isAdmin).map(p => p.jid)}`) // List all groups you're a member of const allGroups = await client.group.queryAllGroups() for (const group of allGroups) { console.log(`${group.subject} (${group.jid}): ${group.size} members`) } // Create a new group const createResult = await client.group.createGroup( 'My New Group', ['5511999999999@s.whatsapp.net', '5511888888888@s.whatsapp.net'], { description: 'A group for testing' } ) // Add participants to a group await client.group.addParticipants('123456789-1234567890@g.us', [ '5511777777777@s.whatsapp.net' ]) // Remove participants await client.group.removeParticipants('123456789-1234567890@g.us', [ '5511777777777@s.whatsapp.net' ]) // Promote/demote admins await client.group.promoteParticipants('123456789-1234567890@g.us', ['5511999999999@s.whatsapp.net']) await client.group.demoteParticipants('123456789-1234567890@g.us', ['5511999999999@s.whatsapp.net']) // Update group settings await client.group.setSubject('123456789-1234567890@g.us', 'New Group Name') await client.group.setDescription('123456789-1234567890@g.us', 'Updated description') await client.group.setSetting('123456789-1234567890@g.us', 'announcement', true) // Only admins can send await client.group.setSetting('123456789-1234567890@g.us', 'restrict', true) // Only admins edit info // Leave a group await client.group.leaveGroup(['123456789-1234567890@g.us']) // Join via invite code await client.group.joinGroupViaInvite('AbCdEfGhIjKlMnOp') ``` -------------------------------- ### Group Management with WaClient.group Source: https://context7.com/vinikjkkj/zapo/llms.txt APIs for managing WhatsApp groups, including querying metadata, creating groups, managing participants, and updating settings. ```APIDOC ## Group Management API ### Description The group coordinator provides methods for creating groups, managing participants, and configuring group settings. ### Method Various (GET, POST, PUT, DELETE equivalents) ### Endpoints - `/group/metadata/{groupJid}` (Query Group Metadata) - `/group/all` (Query All Groups) - `/group/create` (Create Group) - `/group/participants/add` (Add Participants) - `/group/participants/remove` (Remove Participants) - `/group/participants/promote` (Promote Participants) - `/group/participants/demote` (Demote Participants) - `/group/subject` (Set Group Subject) - `/group/description` (Set Group Description) - `/group/setting` (Set Group Setting) - `/group/leave` (Leave Group) - `/group/join` (Join Group via Invite) ### Parameters #### Path Parameters - **groupJid** (string) - Required - The JID of the group (e.g., '123456789-1234567890@g.us'). #### Query Parameters - **inviteCode** (string) - Required for joining a group - The invite code for the group. #### Request Body - **createGroup**: - **subject** (string) - Required - The name of the new group. - **participants** (array of strings) - Required - JIDs of initial participants. - **description** (string) - Optional - Description for the new group. - **addParticipants**: - **participants** (array of strings) - Required - JIDs of participants to add. - **removeParticipants**: - **participants** (array of strings) - Required - JIDs of participants to remove. - **promoteParticipants**: - **participants** (array of strings) - Required - JIDs of participants to promote to admin. - **demoteParticipants**: - **participants** (array of strings) - Required - JIDs of participants to demote from admin. - **setSubject**: - **subject** (string) - Required - The new subject for the group. - **setDescription**: - **description** (string) - Required - The new description for the group. - **setSetting**: - **settingName** (string) - Required - The setting to change ('announcement' or 'restrict'). - **value** (boolean) - Required - The new value for the setting. - **leaveGroup**: - **groupJids** (array of strings) - Required - JIDs of groups to leave. ### Request Example ```javascript // Query group metadata const metadata = await client.group.queryGroupMetadata('123456789-1234567890@g.us'); // Create a new group await client.group.createGroup('My New Group', ['5511999999999@s.whatsapp.net']); // Add participants await client.group.addParticipants('123456789-1234567890@g.us', ['5511777777777@s.whatsapp.net']); ``` ### Response #### Success Response (200) - **queryGroupMetadata**: Returns group metadata object (subject, participants, admins, etc.). - **queryAllGroups**: Returns an array of group objects. - **createGroup**: Returns creation result details. - **addParticipants, removeParticipants, promoteParticipants, demoteParticipants, setSubject, setDescription, setSetting, leaveGroup, joinGroupViaInvite**: Typically return success status or void on success. #### Response Example ```json { "subject": "My New Group", "size": 3, "participants": [ { "jid": "5511999999999@s.whatsapp.net", "isAdmin": true }, { "jid": "5511888888888@s.whatsapp.net", "isAdmin": false }, { "jid": "5511777777777@s.whatsapp.net", "isAdmin": false } ] } ``` ``` -------------------------------- ### Handling WaClient Events Source: https://context7.com/vinikjkkj/zapo/llms.txt Subscribe to client events to process incoming messages, receipts, and group updates. These listeners enable the creation of reactive and automated WhatsApp integrations. ```typescript // Listen for incoming messages client.on('message', async (event) => { console.log(`Message from ${event.senderJid} in ${event.chatJid}`) // Access the message content if (event.message?.conversation) { console.log(`Text: ${event.message.conversation}`) } if (event.message?.extendedTextMessage?.text) { console.log(`Extended text: ${event.message.extendedTextMessage.text}`) } if (event.message?.imageMessage) { console.log('Received an image') } // Reply to a "ping" message const text = event.message?.conversation || event.message?.extendedTextMessage?.text if (text?.toLowerCase() === 'ping') { await client.sendMessage(event.chatJid!, { extendedTextMessage: { text: 'pong!' } }) } }) // Listen for message receipts (read, delivered, etc.) client.on('message_receipt', (event) => { console.log(`Receipt for ${event.stanzaId}: ${event.stanzaType}`) }) // Listen for group events client.on('group_event', (event) => { console.log(`Group ${event.action} in ${event.groupJid}`) if (event.participants) { console.log('Participants:', event.participants.map(p => p.jid)) } }) // Listen for chat state changes (archive, pin, mute) client.on('chat_event', (event) => { console.log(`Chat ${event.action} for ${event.chatJid}`) }) // Listen for history sync chunks client.on('history_sync_chunk', (event) => { console.log(`Synced ${event.messagesCount} messages, ${event.conversationsCount} conversations`) }) ``` -------------------------------- ### WaClient.disconnect() - Clean Disconnection Source: https://context7.com/vinikjkkj/zapo/llms.txt Properly disconnect from WhatsApp, flushing pending writes and cleaning up resources. ```APIDOC ## WaClient.disconnect() ### Description Properly disconnect from WhatsApp, flushing pending writes and cleaning up resources. ### Method POST ### Endpoint /vinikjkkj/zapo/disconnect ### Response #### Success Response (200) - **message** (string) - Confirmation message of disconnection. ### Response Example ```json { "message": "Disconnected cleanly" } ``` ## WaClient.flushWriteBehind(timeout) ### Description Flush any pending write-behind data to the server. ### Method POST ### Endpoint /vinikjkkj/zapo/flushWriteBehind ### Parameters #### Query Parameters - **timeout** (number) - Required - The maximum time in milliseconds to wait for pending writes. ### Response #### Success Response (200) - **remaining** (number) - The number of writes still pending after the flush attempt. ### Response Example ```json { "remaining": 0 } ``` ``` -------------------------------- ### Trigger GitHub Release Source: https://github.com/vinikjkkj/zapo/blob/master/README.md Pushes a Git tag to trigger an automated GitHub release. The format of the tag determines if the release is a prerelease. ```bash git tag v0.1.1 git push origin v0.1.1 ``` -------------------------------- ### Send Read Receipt with WaClient.sendReceipt() Source: https://context7.com/vinikjkkj/zapo/llms.txt Acknowledge message delivery or reading by sending a read receipt. This is crucial for maintaining correct WhatsApp protocol behavior. For group messages, the participant JID is required. ```typescript // Send a read receipt for an incoming message await client.sendReceipt({ to: event.chatJid!, id: event.stanzaId!, type: 'read', participant: event.senderJid // Required for group messages }) ``` ```typescript // Send a delivery receipt await client.sendReceipt({ to: event.chatJid!, id: event.stanzaId!, type: 'received' }) ``` ```typescript // Acknowledge multiple messages at once await client.sendReceipt({ to: '5511999999999@s.whatsapp.net', id: 'LAST_MESSAGE_ID', listIds: ['MESSAGE_ID_1', 'MESSAGE_ID_2', 'MESSAGE_ID_3'] }) ``` -------------------------------- ### WaClient.sendReceipt() - Sending Read Receipts Source: https://context7.com/vinikjkkj/zapo/llms.txt Sends read receipts to acknowledge message delivery or reading, crucial for WhatsApp protocol behavior. ```APIDOC ## WaClient.sendReceipt() - Sending Read Receipts Send read receipts to acknowledge message delivery or reading. This is important for proper WhatsApp protocol behavior. ### Method `client.sendReceipt(options)` ### Parameters - **to** (string) - Required - The recipient's JID. - **id** (string) - Required - The ID of the message to acknowledge. - **type** (string) - Required - Type of receipt ('read' or 'received'). - **participant** (string) - Optional - The sender's JID (required for group messages). - **listIds** (string[]) - Optional - An array of message IDs to acknowledge at once. ### Request Example (Read Receipt) ```typescript await client.sendReceipt({ to: event.chatJid!, id: event.stanzaId!, type: 'read', participant: event.senderJid // Required for group messages }) ``` ### Request Example (Delivery Receipt) ```typescript await client.sendReceipt({ to: event.chatJid!, id: event.stanzaId!, type: 'received' }) ``` ### Request Example (Multiple Messages) ```typescript await client.sendReceipt({ to: '5511999999999@s.whatsapp.net', id: 'LAST_MESSAGE_ID', listIds: ['MESSAGE_ID_1', 'MESSAGE_ID_2', 'MESSAGE_ID_3'] }) ``` ``` -------------------------------- ### Manage Chat State with WaClient.chat Source: https://context7.com/vinikjkkj/zapo/llms.txt Methods for archiving, pinning, muting, reading, and deleting chats or messages. ```typescript // Archive/unarchive a chat await client.chat.setChatArchive('5511999999999@s.whatsapp.net', true) await client.chat.setChatArchive('5511999999999@s.whatsapp.net', false) // Pin/unpin a chat await client.chat.setChatPin('5511999999999@s.whatsapp.net', true) await client.chat.setChatPin('5511999999999@s.whatsapp.net', false) // Mute a chat (requires end timestamp in milliseconds) const muteUntil = Date.now() + 8 * 60 * 60 * 1000 // 8 hours from now await client.chat.setChatMute('5511999999999@s.whatsapp.net', true, muteUntil) await client.chat.setChatMute('5511999999999@s.whatsapp.net', false) // Unmute // Mark chat as read/unread await client.chat.setChatRead('5511999999999@s.whatsapp.net', true) await client.chat.setChatRead('5511999999999@s.whatsapp.net', false) // Star/unstar a message await client.chat.setMessageStar({ chatJid: '5511999999999@s.whatsapp.net', id: 'MESSAGE_ID_HERE', fromMe: false, participantJid: '5511888888888@s.whatsapp.net' // Required for group messages }, true) // Delete a message for yourself await client.chat.deleteMessageForMe({ chatJid: '5511999999999@s.whatsapp.net', id: 'MESSAGE_ID_HERE', fromMe: true }) // Clear all messages in a chat await client.chat.clearChat('5511999999999@s.whatsapp.net', { deleteStarred: false, deleteMedia: true }) // Delete entire chat await client.chat.deleteChat('5511999999999@s.whatsapp.net', { deleteMedia: true }) ``` -------------------------------- ### Gracefully Disconnect from WhatsApp Source: https://context7.com/vinikjkkj/zapo/llms.txt Properly disconnects from WhatsApp, ensuring pending writes are flushed and resources are cleaned up. Handles process signals for graceful shutdown. ```typescript async function shutdown() { // Flush any pending write-behind data const flushResult = await client.flushWriteBehind(5000) if (flushResult.remaining > 0) { console.warn(`${flushResult.remaining} writes still pending`) } // Disconnect from WhatsApp await client.disconnect() console.log('Disconnected cleanly') } // Handle process signals process.on('SIGINT', () => shutdown().then(() => process.exit(0))) process.on('SIGTERM', () => shutdown().then(() => process.exit(0))) ``` -------------------------------- ### Synchronize WhatsApp App State Source: https://context7.com/vinikjkkj/zapo/llms.txt Synchronizes app state collections (archived, pinned, muted chats, starred messages) with WhatsApp servers. Can sync all collections or specific ones. ```typescript const syncResult = await client.syncAppState() for (const collection of syncResult.collections) { console.log(`Collection ${collection.collection}: ${collection.state}`) console.log(` Mutations: ${collection.mutations?.length ?? 0}`) } ``` ```typescript const partialSync = await client.syncAppState({ collections: ['regular', 'regular_high'] }) ``` ```typescript const exportedState = await client.exportAppState() console.log(`Sync keys: ${exportedState.keys.length}`) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.