Poll votes are encrypted by default and arrive through the messages.update event. You need to decrypt them using the original poll creation message to see the aggregated votes.
How Poll Votes Work
When someone votes on a poll:
- WhatsApp sends an encrypted vote update via
messages.update
- The update contains
pollUpdates with encrypted vote data
- You decrypt the votes using the original poll creation message
- You get aggregated vote counts per option
Basic Poll Vote Handling
Listen for messages.update
sock.ev.on('messages.update', (updates) => {
for (const { key, update } of updates) {
if (update.pollUpdates) {
// Handle poll votes
}
}
})
Get the original poll message
// You need to implement getMessage to retrieve stored messages
const pollCreation = await getMessage(key)
Decrypt the votes
import { getAggregateVotesInPollMessage } from '@whiskeysockets/baileys'
const aggregatedVotes = getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates
})
console.log('Poll votes:', aggregatedVotes)
Complete Example
import makeWASocket, { getAggregateVotesInPollMessage } from '@whiskeysockets/baileys'
const sock = makeWASocket({
// getMessage is required to decrypt poll votes
getMessage: async (key) => {
// Implement your storage retrieval logic here
return await getMessageFromStore(key)
}
})
sock.ev.on('messages.update', async (updates) => {
for (const { key, update } of updates) {
if (update.pollUpdates) {
// Get the original poll creation message
const pollCreation = await getMessage(key)
if (pollCreation) {
const aggregatedVotes = getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates
})
console.log('got poll update, aggregation:', aggregatedVotes)
}
}
}
})
You must configure getMessage in your socket config to decrypt poll votes. Without it, you cannot access vote data.
Implementing getMessage
You need to implement getMessage to retrieve stored messages. This is crucial for poll vote decryption:
import { proto, WAMessageKey, WAMessageContent } from '@whiskeysockets/baileys'
// Simple in-memory store (use a database in production)
const messageStore = new Map<string, proto.IMessage>()
// Store messages when they arrive
sock.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
const key = `${msg.key.remoteJid}_${msg.key.id}`
messageStore.set(key, msg.message!)
}
})
// Retrieve messages for poll decryption
async function getMessage(key: WAMessageKey): Promise<WAMessageContent | undefined> {
const messageKey = `${key.remoteJid}_${key.id}`
return messageStore.get(messageKey)
}
const sock = makeWASocket({
getMessage
})
In production, use a persistent database instead of an in-memory Map.
Understanding Poll Updates
The pollUpdates field contains an array of encrypted vote objects:
sock.ev.on('messages.update', (updates) => {
for (const { key, update } of updates) {
if (update.pollUpdates) {
console.log('Raw poll updates:', update.pollUpdates)
// These are encrypted and need the original message to decrypt
}
}
})
The getAggregateVotesInPollMessage function returns vote counts per option:
const aggregatedVotes = getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates
})
// aggregatedVotes structure:
// [
// {
// name: 'Option 1',
// voters: ['[email protected]']
// },
// {
// name: 'Option 2',
// voters: ['[email protected]', '[email protected]']
// }
// ]
console.log(`Option 1 has ${aggregatedVotes[0].voters.length} votes`)
Socket Configuration
To decrypt poll votes and improve retry handling, configure your socket with getMessage:
const sock = makeWASocket({
getMessage: async (key) => {
// Retrieve from your storage
return await getMessageFromStore(key)
}
})
The getMessage function is also used to improve message retry on encryption/decryption failures.
Complete Working Example
import makeWASocket, {
getAggregateVotesInPollMessage,
proto,
WAMessageKey,
WAMessageContent
} from '@whiskeysockets/baileys'
// Message store (use database in production)
const messages = new Map<string, proto.IMessage>()
function makeMessageKey(key: WAMessageKey): string {
return `${key.remoteJid}_${key.id}`
}
async function getMessage(key: WAMessageKey): Promise<WAMessageContent | undefined> {
return messages.get(makeMessageKey(key))
}
const sock = makeWASocket({
getMessage
})
// Store all incoming messages
sock.ev.on('messages.upsert', ({ messages: msgs }) => {
for (const msg of msgs) {
if (msg.message) {
messages.set(makeMessageKey(msg.key), msg.message)
}
}
})
// Handle poll votes
sock.ev.on('messages.update', async (updates) => {
for (const { key, update } of updates) {
if (update.pollUpdates) {
const pollCreation = await getMessage(key)
if (pollCreation) {
const aggregatedVotes = getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates
})
console.log('Poll Update Received:')
console.log('Poll ID:', key.id)
for (const option of aggregatedVotes) {
console.log(`- ${option.name}: ${option.voters.length} votes`)
console.log(` Voters: ${option.voters.join(', ')}`)
}
} else {
console.log('Could not find poll creation message for', key.id)
}
}
}
})