### Install chat-adapter-zaileys and dependencies Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/getting-started.mdx Install the main adapter, the chat SDK, and the memory state adapter. For durable message history, install a store backend like better-sqlite3. ```sh npm i chat-adapter-zaileys zaileys chat @chat-adapter/state-memory ``` ```sh npm i better-sqlite3 ``` -------------------------------- ### Configure Slash Commands and Handle Invocation Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/events.mdx Set up the adapter to recognize specific command prefixes and handle slash commands. The example shows how to define a '/deploy' command and extract text following it. ```typescript const whatsapp = createZaileysAdapter({ session: { sessionId: 'main', commandPrefix: ['/', '!'] }, slashCommands: true, }) bot.onSlashCommand('/deploy', async (event) => { await event.channel.post(`Deploying ${event.text}…`) // "/deploy prod" → text = "prod" }) ``` -------------------------------- ### Install Chat Adapter Zaileys Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Install the necessary packages for chat-adapter-zaileys and its peer dependencies. Supports npm, pnpm, yarn, and bun. ```bash npm i chat-adapter-zaileys zaileys chat @chat-adapter/state-memory # or: pnpm add • yarn add • bun add ``` -------------------------------- ### Install Durable Store Dependencies Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Install optional peer dependencies for durable message history that survives restarts. Choose based on your preferred database. ```bash npm i better-sqlite3 # sqlite • redis (redis) • pg (postgres) • convex (convex) ``` -------------------------------- ### Multi-account Setup Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/configuration.mdx Configure multiple Zaileys adapters with unique adapter names to run several WhatsApp accounts within a single Chat instance. Ensure unique adapter names to maintain distinct thread IDs. ```typescript const main = createZaileysAdapter({ session: { sessionId: 'main' }, adapterName: 'wa-main', }) const sales = createZaileysAdapter({ session: { sessionId: 'sales' }, adapterName: 'wa-sales', }) const bot = new Chat({ userName: 'mybot', adapters: { main, sales }, state: createMemoryState(), }) await bot.initialize() await Promise.all([main.connect(), sales.connect()]) ``` -------------------------------- ### Handle Button Clicks Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/cards-buttons.mdx This code handles actions triggered by button clicks. The 'deploy' action ID is used here as an example, extracting the 'value' from the event. ```typescript bot.onAction('deploy', async (event) => { await event.thread?.post(`Deploying ${event.value}…`) // value = "prod" }) ``` -------------------------------- ### Send Native WhatsApp Interactive Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/cards-buttons.mdx Utilize the adapter's native() method to send various interactive messages like buttons, URLs, and copyable code snippets. This example demonstrates sending buttons with different types. ```typescript const wa = requireZaileysAdapter(thread) await wa.native(thread.id).buttons( [ { id: 'yes', text: 'Yes' }, { type: 'url', text: 'Open docs', url: 'https://zeative.github.io/zaileys/' }, { type: 'copy', text: 'Copy code', code: 'ZAILEYS-2026' }, ], { title: 'Pick one', text: 'Tap a button below' }, ) whatsapp.client.on('button-click', (ctx) => console.log('tapped:', ctx.buttonId)) ``` -------------------------------- ### Handle Miscellaneous Zaileys Events Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/events.mdx Utilize the typed passthrough for events that do not have a direct Chat SDK handler. Examples include incoming calls, group updates, message deletions, and presence changes. ```typescript whatsapp.client.on('call-incoming', (call) => console.log('incoming call from', call.from)) whatsapp.client.on('group-update', (u) => console.log('group changed:', u.update)) whatsapp.client.on('delete', (d) => console.log('message deleted:', d.key.id)) whatsapp.client.on('presence', (p) => console.log(p)) ``` -------------------------------- ### Access Zaileys Context from Message Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/payload.mdx Use `zaileysContext` to get the decoded message context from an incoming message. Returns null for history or sent echoes. Access sender device, flags, and quoted messages. ```typescript import { zaileysContext } from 'chat-adapter-zaileys' bot.onSubscribedMessage(async (thread, message) => { const ctx = zaileysContext(message) if (!ctx) return // history fetches / sent echoes have no live context ctx.senderDevice // 'android' | 'ios' | 'web' | 'desktop' ctx.isForwarded / ctx.isViewOnce // 20+ decoded flags const quoted = await ctx.replied() // the full decoded quoted message await ctx.react('🔥') // zaileys shortcuts still work }) ``` -------------------------------- ### Initialize Chat SDK with WhatsApp Adapter Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/index.mdx This snippet shows how to set up the Chat SDK with the Zaileys WhatsApp adapter. It initializes the adapter, creates a bot instance, and sets up a handler for new mentions. ```typescript import { Chat } from 'chat' import { createMemoryState } from '@chat-adapter/state-memory' import { createZaileysAdapter } from 'chat-adapter-zaileys' const whatsapp = createZaileysAdapter({ session: { sessionId: 'main' } }) const bot = new Chat({ userName: 'mybot', adapters: { whatsapp }, state: createMemoryState() }) bot.onNewMention(async (thread, message) => { await thread.subscribe() await thread.post(`Hello, ${message.author.fullName}!`) }) await bot.initialize() await whatsapp.connect() ``` -------------------------------- ### Create a basic Chat SDK WhatsApp bot Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/getting-started.mdx Initialize the Zaileys adapter and the Chat SDK bot. Register event handlers before connecting the adapter to avoid losing initial messages. The bot responds to mentions and subscribed messages. ```typescript import { Chat } from 'chat' import { createMemoryState } from '@chat-adapter/state-memory' import { createZaileysAdapter } from 'chat-adapter-zaileys' const whatsapp = createZaileysAdapter({ session: { sessionId: 'main' }, }) const bot = new Chat({ userName: 'mybot', adapters: { whatsapp }, state: createMemoryState(), }) bot.onNewMention(async (thread, message) => { await thread.subscribe() await thread.post(`Hello, ${message.author.fullName}!`) }) bot.onSubscribedMessage(async (thread, message) => { await thread.post(`You said: ${message.text}`) }) await bot.initialize() await whatsapp.connect() ``` -------------------------------- ### Initialize Chat Adapter Zaileys with QR Code Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md This snippet shows how to initialize the Zaileys adapter for use with WhatsApp, printing a QR code to the terminal for authentication. It then sets up a Chat bot that responds to mentions. ```typescript import { Chat } from 'chat' import { createMemoryState } from '@chat-adapter/state-memory' import { createZaileysAdapter } from 'chat-adapter-zaileys' const whatsapp = createZaileysAdapter({ session: { sessionId: 'main' }, // QR prints to the terminal on first run }) const bot = new Chat({ userName: 'mybot', adapters: { whatsapp }, state: createMemoryState(), }) bot.onNewMention(async (thread, message) => { await thread.subscribe() await thread.post(`Hello, ${message.author.fullName}!`) }) await bot.initialize() await whatsapp.connect() // register handlers first, then connect ``` -------------------------------- ### Create Zaileys Adapter with Custom Client Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Instantiate a Zaileys client with a custom session ID and a durable message store, then create the Zaileys adapter. ```typescript import { Client, SqliteMessageStore } from 'zaileys' import { createZaileysAdapter } from 'chat-adapter-zaileys' const client = new Client({ sessionId: 'main', store: new SqliteMessageStore({ database: './wa.db' }), // durable fetchMessages history }) const whatsapp = createZaileysAdapter({ client }) ``` -------------------------------- ### Handle Reactions and Member Joins Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/events.mdx Listen for specific reactions like '🔥' and post a message in the thread. Also, welcome new members to a channel by posting a greeting message. ```typescript bot.onReaction('🔥', async (event) => { await event.thread.post(`${event.user.userName} reacted with fire!`) }) bot.onMemberJoinedChannel(async (event) => { const thread = await bot.getThread(event.channelId) await thread.post(`Welcome <@${event.userId}>!`) }) ``` -------------------------------- ### Initialize Client with SqliteMessageStore Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/history.mdx Initialize the Zaileys client with a SqliteMessageStore for persistent message history. This ensures messages are not lost on client restart. ```typescript import { Client, SqliteMessageStore } from 'zaileys' const client = new Client({ sessionId: 'main', store: new SqliteMessageStore({ database: './wa.db' }), }) const whatsapp = createZaileysAdapter({ client }) ``` -------------------------------- ### Construct Zaileys Client manually for advanced configuration Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/getting-started.mdx For full control over Zaileys configuration, including custom storage adapters for authentication and message history, construct the Client manually. Pass either 'client' or 'session' to the adapter factory, but not both. ```typescript import { Client, SqliteAuthStore, SqliteMessageStore } from 'zaileys' import { createZaileysAdapter } from 'chat-adapter-zaileys' const client = new Client({ sessionId: 'main', auth: new SqliteAuthStore({ database: './auth.db' }), store: new SqliteMessageStore({ database: './wa.db' }), // durable history for fetchMessages }) const whatsapp = createZaileysAdapter({ client }) ``` -------------------------------- ### Create Zaileys Adapter Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/configuration.mdx Instantiate a Zaileys adapter with essential configuration like session details, adapter name, and user name. Customize behavior with options like forwardPollVotes, autoMarkRead, richMessages, and slashCommands. ```typescript import { createZaileysAdapter } from 'chat-adapter-zaileys' const whatsapp = createZaileysAdapter({ session: { sessionId: 'main' }, // or: client: myZaileysClient adapterName: 'zaileys', userName: 'zaileys-bot', forwardPollVotes: true, autoMarkRead: false, richMessages: false, slashCommands: false, }) ``` -------------------------------- ### Post Files and Attachments Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Send files (PDFs, images, videos, audio) or URLs as attachments. The first file's text content becomes the caption. Other file types are routed based on MIME type. ```typescript await thread.post({ markdown: 'Here is the report', files: [{ data: pdfBuffer, filename: 'report.pdf', mimeType: 'application/pdf' }], }) ``` -------------------------------- ### Use the Native Message Builder Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Access the full Zaileys message builder via the `native()` method for advanced message types like images, albums, and lists. ```typescript await wa.native(thread.id).image(buffer, { viewOnce: true }) await wa.native(thread.id).album([{ type: 'image', src: img1 }, { type: 'image', src: img2 }]) await wa.native(thread.id).list({ title: 'Menu', buttonText: 'Open', sections }) await wa.native(thread.id).text('hey').mentionAll() ``` -------------------------------- ### Configure Chat with Zaileys Adapter and Queue Concurrency Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/history.mdx Configure a Chat instance with the Zaileys adapter and set concurrency to 'queue' to handle message attachments. Attachments will download after being dequeued. ```typescript const bot = new Chat({ adapters: { whatsapp }, state: myState, concurrency: 'queue', // attachments still download after dequeue /* … */ }) ``` -------------------------------- ### Schedule Media or Interactive Content Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/scheduling.mdx For scheduling media or interactive messages, use the Zaileys scheduler directly with the `client.scheduleAt` method and a builder pattern. ```typescript await whatsapp.client.scheduleAt(date, (b) => b.to(jid).image('./promo.jpg', { caption: 'Launching today!' }), ) ``` -------------------------------- ### Send WhatsApp Extension Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/extensions.mdx Demonstrates sending various WhatsApp-native messages using Zaileys adapter extensions, including read receipts, location, and voice notes. Also shows how to fetch group participants and filter for admins. ```typescript const wa = requireZaileysAdapter(thread) await wa.markRead(thread.id) await wa.sendLocation({ threadId: thread.id, latitude: -6.2, longitude: 106.8, name: 'Jakarta' }) await wa.sendVoiceNote(thread.id, oggBuffer) const admins = (await wa.fetchGroupParticipants(thread.id)).filter((p) => p.isAdmin) ``` -------------------------------- ### Reply to Messages with Quoting Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Utilize the adapter's `reply` extension to quote and respond to incoming messages. This feature supports media and provides a native WhatsApp reply experience. ```typescript import { requireZaileysAdapter } from 'chat-adapter-zaileys' bot.onSubscribedMessage(async (thread, message) => { const wa = requireZaileysAdapter(thread) await wa.reply(message, 'Got it!') // quotes the original, media supported }) ``` -------------------------------- ### Use WhatsApp-Native Extensions Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Extend thread functionality with WhatsApp-native actions like marking messages as read, sending specific message types, and managing group participants. ```typescript import { requireZaileysAdapter } from 'chat-adapter-zaileys' bot.onSubscribedMessage(async (thread, message) => { const wa = requireZaileysAdapter(thread) await wa.markRead(thread.id) // blue ticks await wa.reply(message, 'Got it!') // native quoted reply await wa.sendLocation({ threadId: thread.id, latitude: -6.2, longitude: 106.8 }) await wa.sendSticker(thread.id, stickerBuffer) // auto webp conversion, Lottie included await wa.sendVoiceNote(thread.id, oggBuffer) // push-to-talk bubble await wa.sendContact(thread.id, vcardString) await wa.startRecording(thread.id) // "recording audio…" indicator await wa.forwardMessage(thread.id, message.id, otherThreadId) await wa.pinMessage(thread.id, message.id) await wa.setPresence('available') await wa.setDisappearing(thread.id, 86_400) // disappearing messages (0 disables) const participants = await wa.fetchGroupParticipants(thread.id) const admins = participants.filter((p) => p.isAdmin) }) ``` -------------------------------- ### Configure Zaileys adapter for pairing code authentication Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/getting-started.mdx To use pairing code authentication, specify 'pairing' as the authType and provide the phone number in E.164 format. This is an alternative to scanning a QR code. ```typescript const whatsapp = createZaileysAdapter({ session: { sessionId: 'main', authType: 'pairing', phoneNumber: '6281234567890' }, }) ``` -------------------------------- ### Configure Durable Message Store Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/scheduling.mdx To ensure scheduled jobs persist through process restarts, configure the `Client` with a durable message store like `SqliteMessageStore`. The default in-memory store only keeps jobs for the duration of the process. ```typescript const client = new Client({ sessionId: 'main', store: new SqliteMessageStore({ database: './wa.db' }), }) ``` -------------------------------- ### Send a WhatsApp Poll Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/polls.mdx Use `wa.sendPoll` to send a poll with a question, options, and selection count. Ensure the Zaileys adapter is required. ```typescript import { requireZaileysAdapter } from 'chat-adapter-zaileys' const wa = requireZaileysAdapter(thread) const poll = await wa.sendPoll({ threadId: thread.id, question: 'What time works for the call?', options: ['10:00', '14:00', '17:00'], selectableCount: 1, // any other value allows multiple selections }) ``` -------------------------------- ### Send Advanced Messages with native() Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/extensions.mdx Utilize the `native()` method to access the full Zaileys message builder for complex message types like images with viewOnce, albums, lists, events, and templated text with mentions or disappearing options. ```typescript await wa.native(thread.id).image(buffer, { viewOnce: true }) await wa.native(thread.id).album([ { type: 'image', src: './a.jpg' }, { type: 'image', src: './b.jpg' }, ]) await wa.native(thread.id).list({ title: 'Menu', buttonText: 'Open', sections }) await wa.native(thread.id).event({ name: 'Standup', startTime }) await wa.native(thread.id).text('hey everyone').mentionAll() await wa.native(thread.id).text('secret').disappearing(86_400) ``` -------------------------------- ### Post a Card with Buttons Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/cards-buttons.mdx Use this snippet to post a card with interactive buttons to a thread. Ensure the 'chat' library is imported. ```tsx import { Card, Actions, Button } from 'chat' bot.onNewMention(async (thread) => { await thread.post( ) }) ``` -------------------------------- ### Post Plain Text and Markdown Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Send simple text messages or formatted markdown strings. Markdown is converted to WhatsApp's native markup. ```typescript await thread.post('plain text') ``` ```typescript await thread.post({ markdown: '**bold** _italic_ ~~strike~~ `code` [docs](https://example.com)' }) ``` -------------------------------- ### Send and Handle Polls Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Create polls with questions and options, and listen for vote events. Votes are natively decrypted and persist across restarts. ```typescript const poll = await wa.sendPoll({ threadId: thread.id, question: 'Lunch?', options: ['A', 'B'] }) wa.onPollVote(poll.id, (vote) => { console.log(vote.voter.userName, 'picked', vote.selectedOptions) }) ``` -------------------------------- ### Receive All Poll Votes Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/polls.mdx Listen for all poll votes sent by the current account using `wa.onPollVote`. This is useful for tracking votes across all polls sent by the adapter. ```typescript // every poll this account sent wa.onPollVote((vote) => { console.log(vote.voter.userName, '→', vote.selectedOptions) }) ``` -------------------------------- ### Access Zaileys Client for Full Control Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/extensions.mdx Interact with the complete Zaileys client API via `adapter.client` to manage groups, newsletters, privacy settings, broadcasts, and commands. This provides access to all Zaileys functionalities. ```typescript whatsapp.client.group.promote(groupJid, [userJid]) whatsapp.client.newsletter.create('My Channel', 'Updates') whatsapp.client.privacy.updateLastSeen('contacts') whatsapp.client.broadcast(jids, (b) => b.text('Announcement'), { rateLimitPerSec: 5 }) whatsapp.client.command('ping', (ctx) => ctx.reply('pong 🏓')) ``` -------------------------------- ### Post Rich Bubbles with Markdown Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Enable rich message rendering by setting `richMessages: true`. This allows markdown posts to be displayed as interactive AIRich bubbles, supporting code blocks, tables, and directives. ```typescript const whatsapp = createZaileysAdapter({ session: { sessionId: 'main' }, richMessages: true }) await thread.post({ markdown: ['## Daily brief', '', '```ts', 'const x = 1', '```'].join('\n'), }) ``` -------------------------------- ### Fetch Recent and Older Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/history.mdx Fetch recent messages with a limit and then fetch older messages using the cursor from the previous fetch. Pagination is backward (newest first). ```typescript const recent = await thread.fetchMessages({ limit: 50 }) // recent.messages — chronological (oldest → newest), full Message objects const older = await thread.fetchMessages({ limit: 50, cursor: recent.nextCursor }) ``` -------------------------------- ### Stream Text Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Implement message streaming using the SDK's fallback streaming mechanism, which leverages the adapter's `editMessage` capability. This allows for real-time text updates. ```typescript bot.onSubscribedMessage(async (thread) => { const stream = await ai.streamText({ /* … */ }) await thread.post(stream.textStream) }) ``` -------------------------------- ### Require Zaileys Adapter Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/extensions.mdx Use `requireZaileysAdapter` to safely access Zaileys-specific thread methods. This function throws an error if the provided thread is not from a Zaileys adapter. ```typescript import { isZaileysAdapter, requireZaileysAdapter } from 'chat-adapter-zaileys' bot.onSubscribedMessage(async (thread, message) => { const wa = requireZaileysAdapter(thread) // throws if not a zaileys thread // … }) ``` -------------------------------- ### Schedule a WhatsApp Message Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/scheduling.mdx Use `thread.schedule` to send a text message at a specified future time. The returned object contains the Zaileys job ID and the scheduled post time, and can be used to cancel the scheduled message. ```typescript const scheduled = await thread.schedule('Reminder: standup in 10 minutes!', { postAt: new Date(Date.now() + 3600_000), }) scheduled.scheduledMessageId // zaileys job id scheduled.postAt // Date await scheduled.cancel() // change of plans ``` -------------------------------- ### Fetch Lazy Media Data Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/payload.mdx Access attachment metadata immediately and download the media bytes on demand using `attachment.fetchData()` or `ctx.media.buffer()`. Handles image and file types. ```typescript const [attachment] = message.attachments if (attachment) { attachment.mimeType // 'image/jpeg' attachment.size // bytes, when known const buffer = await attachment.fetchData() // downloads now } // or through the zaileys context: const ctx = zaileysContext(message) if (ctx?.media && 'buffer' in ctx.media) { const buffer = await ctx.media.buffer() } ``` -------------------------------- ### Schedule and Cancel Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Schedule a message to be posted at a specific time. Scheduled jobs persist in the Zaileys store and survive restarts if a durable store is used. ```typescript const scheduled = await thread.schedule('Reminder!', { postAt: new Date(Date.now() + 3600_000) }) await scheduled.cancel() // if you change your mind ``` -------------------------------- ### Send Cards with Buttons Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Respond to new mentions by posting a card with actionable buttons. Handles button clicks via onAction. ```tsx bot.onNewMention(async (thread) => { await thread.post( ) }) bot.onAction('deploy', async (event) => { await event.thread?.post(`Deploying ${event.value}…`) }) ``` -------------------------------- ### Access Zaileys Client Methods Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/configuration.mdx Interact with the underlying Zaileys client directly to perform advanced operations such as fetching group metadata, updating privacy settings, sending broadcast messages, or handling incoming calls. ```typescript whatsapp.client.group.metadata(jid) whatsapp.client.privacy.updateLastSeen('contacts') whatsapp.client.broadcast(jids, (b) => b.text('Announcement')) whatsapp.client.on('call-incoming', (call) => { /* … */ }) ``` -------------------------------- ### Edit, Delete, React, and Typing Indicators Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/messages.mdx Manage sent messages by editing content, adding or removing reactions, deleting messages, or showing a typing indicator. These operations map to native WhatsApp functionalities. ```typescript const sent = await thread.post('Original') await sent.edit('Fixed') // → WhatsApp native edit await sent.addReaction('👍') // → native reaction await sent.removeReaction('👍') await sent.delete() // → delete for everyone await thread.startTyping() // "typing…" indicator ``` -------------------------------- ### Thread ID Management Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/configuration.mdx Utilities for encoding, decoding, and checking Direct Message (DM) status for thread IDs. The thread ID format is ':'. ```typescript adapter.encodeThreadId({ jid: '628123456789@s.whatsapp.net' }) // "zaileys:NjI4MTIzNDU2Nzg5QHMud2hhdHNhcHAubmV0" adapter.decodeThreadId(threadId) // { jid: "628123456789@s.whatsapp.net" } adapter.isDM(threadId) // true for DMs, false for groups/newsletters adapter.openDM('6281234567890') // → DM thread ID (accepts digits or a jid) ``` -------------------------------- ### Receive Votes for Specific Polls Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/polls.mdx Use `wa.onPollVote` with a poll ID or an array of poll IDs to receive votes for specific polls. This allows for targeted handling of vote events. ```typescript // scoped to one (or several) polls wa.onPollVote(poll.id, async (vote) => { await thread.post(`${vote.voter.userName} picked ${vote.selectedOptions[0]}`) }) wa.onPollVote([pollA.id, pollB.id], handler) ``` -------------------------------- ### Access Zaileys Context from Message Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/README.md Extract the full Zaileys MessageContext from a subscribed message to access flags, sender details, media, and quoted messages. ```typescript import { zaileysContext } from 'chat-adapter-zaileys' bot.onSubscribedMessage(async (thread, message) => { const ctx = zaileysContext(message) if (!ctx) return ctx.isGroup / ctx.isForwarded / ctx.isViewOnce / ctx.isEphemeral // 20+ flags ctx.senderDevice // 'android' | 'ios' | 'web' | … const media = ctx.media // lazy — nothing downloads until you ask const quoted = await ctx.replied() // full decoded quoted message await ctx.react('🔥') // zaileys shortcuts still work }) ``` -------------------------------- ### Forward Poll Votes as Messages Source: https://github.com/zeative/chat-adapter-zaileys/blob/main/docs/content/polls.mdx When `forwardPollVotes` is true (default), non-empty poll votes are forwarded as regular messages. Bots can then process these votes via `onSubscribedMessage`. ```typescript bot.onSubscribedMessage(async (thread, message) => { // a vote for "14:00" arrives as message.text === "14:00" }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.