Polls Commands

Updated 3/28/2026

What the Poll system provides (short)

  • Create simple multi-choice polls (2–4 choices) or default Yes/No polls.

  • Optionally run timed polls that update an embed with a countdown and automatically close.

  • Store active polls on disk (data/polls.json) and store poll defaults in pollSettings.json.

  • Reacts to the poll message with letter emojis (🇦 🇧 🇨 🇩) so members vote by reacting.

  • Administrative controls to end, view results, delete, list, pin polls, and toggle anonymous voting.


Commands & examples

Note: the /poll command is a slash command with the following subcommands implemented in the bot. See each subsection for examples and notes.

/poll create <question> [choice1 choice2 choice3 choice4] [channel:#channel] [duration:1h30m]

Purpose — Create a new poll and post it to the specified channel (or current channel). By default, if you only provide a question, the poll will be a Yes/No poll (Yes / No). You may provide up to 4 choices. Optionally supply a duration (e.g., “1h30m”, “10m20s”) to make a timed poll that auto-closes.

Key behavior

  • Defaults: choice1Yes, choice2No if not supplied. The command maps choices to emojis 🇦/🇧/🇨/🇩 and reacts to the created message so users can vote. A poll object is saved to data/polls.json. If a duration is provided the bot runs a countdown that edits the embed periodically and closes the poll when time expires.

Example

/poll create question:"Favorite color?" choice1:"Red" choice2:"Blue" choice3:"Green" channel:#polls duration:"10m"
/poll create question:"Do you want the event on Friday?" # creates a Yes/No poll in current channel

Notes

  • Duration parsing accepts patterns like 1h, 30m, 45s and combinations (1h30m). The implementation parses H/M/S and converts to seconds. If invalid the poll will be created without a timer.

  • Timed polls edit the embed periodically (the implementation updates every 5 seconds for performance) and remove the poll from active storage when time expires.


/poll end <message_id>

Purpose — Manually end a poll early. Removes the poll entry from active storage so it’s no longer considered active.

Example

/poll end message_id:123456789012345678

Notes

  • The command deletes the poll record from polls.json and acknowledges success. Ending a poll does not automatically delete the message — it simply marks the poll closed on the server side.


/poll results <message_id>

Purpose — Show the current results for an active poll.

Example

/poll results message_id:123456789012345678

Notes & limitation

  • The command returns an embed with the poll question and the list of choices. The current implementation does not compute and display per-choice vote counts — it provides a results summary placeholder (staff can extend this if you need precise counts). If you need vote counts immediately, you can fetch the poll message and inspect reactions, or add a short extension to the bot to aggregate reaction counts on demand.


/poll delete <message_id>

Purpose — Remove the poll entry from storage. This will forget the poll (it does not necessarily delete the message from Discord).

Example

/poll delete message_id:123456789012345678

Notes

  • Deleting simply removes the poll from polls.json and replies with confirmation. If you want the message removed too, delete it in Discord.


/poll list

Purpose — Show all active poll IDs the bot currently tracks.

Example

/poll list

Behavior

  • Returns an ephemeral (staff-only) embed that lists active poll message IDs, or No active polls. if none. Useful to find the message IDs you need for results, end, or delete.


/poll pin <message_id>

Purpose — Pin the poll message to the channel (makes it easier for members to find).

Example

/poll pin message_id:123456789012345678

Notes

  • The implementation attempts to fetch the message from the current channel and pin it. If the message is in a different channel, the pin will fail — supply the message ID from the channel where the poll was posted, or pin manually in Discord. The command responds ephemerally with success/failure.


/poll anonymous on|off

Purpose — Toggle anonymous voting as a global poll setting (affects the footer on newly created polls and how the bot records polls). This is a server-wide default stored in pollSettings.json.

Examples

/poll anonymous mode:on
/poll anonymous mode:off

Notes

  • The command updates pollSettings.json and replies with a confirmation. When anonymous mode is enabled, poll embeds show a “🔒 Anonymous Voting” footer. This is a global default — you might want per-poll anonymous control in the future, but today this code toggles the server default.


/poll settings

Purpose — Show current poll defaults such as whether anonymous voting is on and the default duration.

Example

/poll settings

Notes

  • Returns an ephemeral embed that reads pollSettings.json and displays Anonymous Voting and Default Duration. Use this to audit server defaults.


Implementation notes & details

  • Where data is stored — Active polls are persisted to data/polls.json and defaults are stored in data/pollSettings.json. This makes polls survive restarts.

  • Choice/emoji mapping — The bot maps up to 4 choices to emojis 🇦, 🇧, 🇨, 🇩 and reacts with those on the poll message so members vote with reactions. Keep your choice count ≤ 4.

  • Timed polls & countdown — Durations are parsed into seconds (supports h, m, s), and if a duration is given the poll displays a countdown. The timed logic updates the embed (every ~5s) and removes the poll record when the countdown ends. The timer loop uses setInterval and will clear itself when finished.

  • Anonymous mode — The server-wide anonymous setting influences the embed footer and the poll’s anonymous flag stored with each poll. It does not automatically hide reaction voters (Discord reactions always show who reacted unless you implement a more advanced collection method). The current implementation’s “anonymous” is primarily a UI flag.


Best practices

  • Pick short, clear choices so the label plus the emoji fits the embed nicely. Use no more than 4 options.

  • Test a timed poll in a staff channel before using it with a long-running audience — the embed updates frequently and long durations may create many edits. Timed polls update the embed every 5 seconds when the remaining time is divisible by 5.

  • Use /poll list to find poll message IDs for results, end, delete, or pin. The list command is ephemeral, making it safe for staff use.

  • Pin only from the poll’s channel or manually pin in the channel owner’s UI — the /poll pin command fetches from the interaction channel. If pinning a poll from another channel, do it in Discord or run the command in that channel.


Troubleshooting checklist

  • Poll not posting — confirm the bot has Send Messages, Add Reactions, and Embed Links permissions in the target channel. The bot reacts to the message immediately after posting, so Add Reactions is required.

  • Countdown not updating — timed polls rely on an in-process interval. If the bot restarts, the stored endsAt is persisted, but the in-memory interval would be lost; currently the code does not rehydrate running timers on restart. For long-lived production polls you may want to extend the code to re-spawn timers from stored endsAt on boot. (At present the code persists endsAt, but only the in-process interval performs the live countdown edits.)

  • Results do not show vote counts — the results subcommand currently returns the question and choices but does not calculate reaction counts. To get counts now, fetch the poll message and inspect reaction counts or update the bot to aggregate reaction counts for the poll.

  • Pin fails/poll pin fetches the message from the command’s current channel; ensure you run the command in the same channel the poll message was posted or pin manually.


Quick cheatsheet

/poll create question:"Favorite map?" choice1:"Map A" choice2:"Map B" choice3:"Map C" channel:#polls duration:"10m"
/poll create question:"Do you want voice chat?" # Yes/No (defaults)
/poll end message_id:123456789012345678
/poll results message_id:123456789012345678
/poll delete message_id:123456789012345678
/poll list
/poll pin message_id:123456789012345678
/poll anonymous mode:on|off
/poll settings