> ## Documentation Index
> Fetch the complete documentation index at: https://zapo.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Enquetes, reações e edições

> Envie enquetes e votos, reaja a mensagens, fixe e edite conteúdo, revogue mensagens enviadas e trate os eventos de cada — tudo pela union tipada de content.

Além de texto e mídia, o `client.message.send` aceita uma família de objetos de conteúdo interativo tipados. Cada um é discriminado pelo seu campo `type`.

<h2 id="targeting-a-message">
  Apontando para uma mensagem
</h2>

Reply / reaction / revoke / pin / keep / event-response aceitam um `WaMessageTargetInput`: um evento `message` recebido passado **literalmente** (sua `key` é usada) ou uma `WaMessageKey` explícita:

```ts theme={null}
interface WaMessageKey {
  remoteJid: string     // o chat onde o alvo está
  id: string            // o id (stanza) do alvo
  fromMe: boolean       // o alvo foi enviado por você?
  participant?: string  // o autor — obrigatório em grupos ao mirar a mensagem de outra pessoa
}
```

O caminho mais fácil é passar o próprio evento — `event.key` já é uma `WaMessageKey`:

```ts theme={null}
client.on('message', async (event) => {
  // Usa o próprio evento como target — sua key é lida para você.
  await client.message.send(event.key.remoteJid, {
    type: 'reaction',
    emoji: '👍',
    target: event
  })
})
```

<h2 id="reactions">
  Reações
</h2>

```ts theme={null}
// Passe o evento literalmente, ou uma WaMessageKey explícita
await client.message.send(jid, {
  type: 'reaction',
  emoji: '👍',
  target: event
})
```

Passe uma **string vazia** como `emoji` para remover uma reação anterior:

```ts theme={null}
await client.message.send(jid, { type: 'reaction', emoji: '', target: event })
```

<h2 id="polls">
  Enquetes
</h2>

```ts theme={null}
const result = await client.message.send(jid, {
  type: 'poll',
  name: 'Lunch?',
  options: ['Pizza', 'Sushi', 'Salad'],
  selectableCount: 1,        // quantas opções um votante pode escolher
  allowAddOption: false
})
```

As opções podem ser strings simples ou objetos `{ name }`. **A ordem importa** — ela é usada no hashing dos votos.

<h3 id="voting-on-a-poll">
  Votando em uma enquete
</h3>

Votar requer a identidade da enquete original e seu `messageSecret` (32 bytes do `messageContextInfo.messageSecret` da enquete):

```ts theme={null}
await client.message.send(jid, {
  type: 'poll-vote',
  poll: {
    id: pollStanzaId,                  // o id (stanza) da enquete
    fromMe: false,
    authorJid: pollAuthorJid,
    messageSecret: pollMessageSecret,  // Uint8Array, 32 bytes
    participant: pollAuthorJid         // obrigatório fora de conversas 1:1
  },
  selectedOptionNames: ['Pizza']       // exatamente como apareceram na enquete
})
```

<Note>
  Os votos recebidos chegam como eventos [`message_addon`](/pt-br/guides/receiving-messages#addons) depois de descriptografados.
</Note>

<h2 id="editing-a-message">
  Editando uma mensagem
</h2>

Para editar, envie o conteúdo **novo** e passe `editKey` nas opções. A original deve ser `fromMe`. Você pode passar o evento `message` recebido literalmente, sua `key`, ou uma `WaSendEditKey` explícita (`{ id, participant?, timestampMs? }`):

```ts theme={null}
// Mais fácil: encaminhe o evento original
await client.message.send(jid, 'Corrected text', { editKey: originalEvent })

// Ou monte um explicitamente
await client.message.send(jid, 'Corrected text', {
  editKey: {
    id: originalStanzaId,
    // participant obrigatório em grupos para originais endereçadas via lid/pn
    participant: undefined
  }
})
```

O novo payload é empacotado em uma mensagem de protocolo `MESSAGE_EDIT` que mira o `editKey.id`.

<h2 id="revoking-delete-for-everyone">
  Revogando (apagar para todos)
</h2>

```ts theme={null}
// Mais fácil: passe o evento que você quer revogar
await client.message.send(jid, { type: 'revoke', target: event })

// Ou construa o target explicitamente
await client.message.send(jid, {
  type: 'revoke',
  target: {
    remoteJid: jid,
    id: targetStanzaId,
    fromMe: true,
    // participant obrigatório quando um admin revoga a mensagem de outra pessoa em um grupo
    participant: undefined
  }
})
```

Sender vs admin revoke é auto-detectado a partir de `target.fromMe`: `false` dispara um admin revoke. Não há opção `subtype` para passar.

<h2 id="pinning">
  Fixando
</h2>

```ts theme={null}
await client.message.send(jid, { type: 'pin', target: event })   // fixar
await client.message.send(jid, { type: 'unpin', target: event }) // desafixar
```

Pins expiram — passe `durationSecs` para sobrescrever o default. O wa-web oferece três presets:

```ts theme={null}
await client.message.send(jid, { type: 'pin', target: event, durationSecs: 604_800 })   // 7 dias
await client.message.send(jid, { type: 'pin', target: event, durationSecs: 2_592_000 }) // 30 dias
```

O default é **`86_400`** (24h). O TTL viaja com o pin via `messageContextInfo.messageAddOnDurationInSecs`; sem ele os clients receptores dropam o pin silenciosamente, então a lib sempre carimba o default se você omitir. `durationSecs` é ignorado em `unpin`.

<h2 id="keep-in-chat">
  Manter no chat
</h2>

Para chats com mensagens temporárias, mantenha (ou desfaça a manutenção de) uma mensagem específica:

```ts theme={null}
await client.message.send(jid, { type: 'keep', target: event })
await client.message.send(jid, { type: 'unkeep', target: event })
```

<h2 id="events">
  Eventos
</h2>

Crie uma mensagem de evento no estilo calendário:

```ts theme={null}
await client.message.send(groupJid, {
  type: 'event',
  name: 'Team sync',
  description: 'Weekly catch-up',
  startTime: Math.floor(Date.now() / 1000) + 3600, // segundos unix
  location: { latitude: -23.5, longitude: -46.6, name: 'HQ' },
  joinLink: 'https://meet.example.com/abc',
  hasReminder: true,
  reminderOffsetSec: 600
})
```

<h3 id="responding-to-an-event">
  Respondendo a um evento
</h3>

```ts theme={null}
await client.message.send(jid, {
  type: 'event-response',
  event: {
    id: eventStanzaId,                 // o id (stanza) do evento
    fromMe: false,
    authorJid: eventAuthorJid,
    messageSecret: eventMessageSecret  // 32 bytes
  },
  response: 'going' // 'going' | 'not_going' | 'maybe'
})
```

<h2 id="locations--contacts">
  Localizações e contatos
</h2>

Ainda não existe um builder dedicado para localizações estáticas ou cartões de contato — envie-os como um `Proto.IMessage` bruto:

```ts theme={null}
await client.message.send(jid, {
  locationMessage: { degreesLatitude: -23.5, degreesLongitude: -46.6 }
})

await client.message.send(jid, {
  contactMessage: { displayName: 'Jane', vcard: 'BEGIN:VCARD\n...\nEND:VCARD' }
})
```
