Guides
Vote announcements
Realtime vote posts to Discord webhooks - text, embed or Components V2.
The VoteAnnouncer broadcasts every incoming vote to Discord channel webhooks (and any external https endpoint) in realtime. It is DISABLED by default - nothing leaves your process until you pass `enabled: true`. It is built directly on the Discord execute-webhook REST endpoint with plain fetch: no discord.js, no Eris, works inside any framework or none.
wire it up
const lists = new Botlists({
client,
announcer: {
enabled: true, // required - off by default
format: 'embed-v2', // 'text' | 'embed' | 'embed-v2'
webhooks: [process.env.VOTE_WEBHOOK_URL!], // Discord channel webhooks
external: ['https://api.example.com/hooks/votes'], // JSON { source, event, list, vote }
username: 'Vote Alerts', // optional webhook identity overrides
color: 0x5865f2,
links: [{ label: 'Vote Again', url: 'https://top.gg/bot/YOUR_BOT/vote', emoji: '🗳️' }],
announceTestVotes: false, // dashboard test deliveries: ignore by default
},
});three render formats
// 'text' - plain message content from a {placeholder} template
{ format: 'text', template: '🗳️ {voter} voted on {list}!' }
// 'embed' - classic rich embed (title, description, color, timestamp, thumbnail)
{ format: 'embed' }
// 'embed-v2' - Components V2: section + avatar accessory, separator,
// link buttons; the IS_COMPONENTS_V2 flag is set for you
{ format: 'embed-v2' }| Option | Default | What it does |
|---|---|---|
enabled | false | master switch for wiring inside Botlists (standalone instances are always active) |
format | 'embed' | render style: text / embed / embed-v2 |
webhooks | [] | Discord channel webhook urls (discord.com, discordapp.com, canary, ptb) |
external | [] | any https endpoint - receives { source, event, list, vote } JSON |
username / avatarUrl | webhook default | override the posting identity |
botToken | undefined | read-only: resolves username/avatar via GET /users/@me so posts use the bot’s identity |
template | see below | {placeholder} text: {voter} {voterId} {list} {listId} {bot} {botId} {weight} {weekend} |
links | [] | link buttons appended to embed-v2 (max 5) |
customize | undefined | (vote, payload) => payload - full control, mutate or replace before sending |
announceTestVotes | false | also announce dashboard test deliveries |
minIntervalMs | 1000 | spacing between two sends to the SAME target (rate-limit safety) |
maxQueueSize | 500 | per-target queue bound; the oldest vote is dropped when full |
standalone use
import { Botlists, VoteAnnouncer } from '@potenfyrstudios/discord-botlists';
const announcer = new VoteAnnouncer({ format: 'embed-v2', webhooks: [url] });
announcer.on('delivered', (d) => console.log('sent to', d.target, d.status));
const lists = new Botlists({ client });
lists.on('vote', (vote) => announcer.announce(vote));TipRate-limit safety is on by default: sends to the same target are spaced ≥ 1 s apart, a 429 with a small Retry-After is waited out exactly once, queues are bounded so a webhook outage can never grow memory, and scheduler timers are unref'd - zero idle resource usage.