### 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.