Skip to content

feat: add polls feature - #148

Open
ap-1 wants to merge 25 commits into
mainfrom
polls
Open

feat: add polls feature#148
ap-1 wants to merge 25 commits into
mainfrom
polls

Conversation

@ap-1

@ap-1 ap-1 commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Adds /poll command with six subcommands:

  • setup (configure guild polls channel)
  • create (create a poll with up to 10 options, optional multi-select)
  • results (view vote counts)
  • delete (for admins or poll authors to remove polls)
  • close (to manually close the poll before expiry)
  • myvote (check your own vote on an anonymous poll)

Closes https://github.com/ScottyLabs/dalmatian/issues/48

@ap-1
ap-1 requested review from TenType and maybe-yiyi as code owners April 10, 2026 18:44
@ap-1
ap-1 marked this pull request as draft April 10, 2026 18:52
@ap-1 ap-1 self-assigned this Apr 10, 2026
@ap-1
ap-1 marked this pull request as ready for review April 10, 2026 19:35
@maybe-yiyi

maybe-yiyi commented Apr 13, 2026

Copy link
Copy Markdown
Member

just some things, not sure if some are feasible at all

  • Should we have polls autoclose? What if people just want the polls to be open indefinitely?
  • I think the results page should reference the original poll perhaps
    • is there a way to make it so you can see your own vote on anonymous polls? obviously we wouldn't be able to use ephemeral messages for that
  • For me the polls are saying Poll by <@649388957007609879>•Today at 16:21 instead of mentioning the user
  • i think we should put at least rolling counts on the ongoing polls
  • does the poll embed builder just add every single voter to the voting list? it feels like you might hit embed limits on massive polls, and/or it crowds the answer choices
  • what if i want to unvote from a poll

@ap-1

ap-1 commented Apr 13, 2026

Copy link
Copy Markdown
Contributor Author

just some things, not sure if some are feasible at all

* Should we have polls autoclose? What if people just want the polls to be open indefinitely?

* I think the results page should reference the original poll perhaps
  
  * is there a way to make it so you can see your own vote on anonymous polls? obviously we wouldn't be able to use ephemeral messages for that

* For me the polls are saying `Poll by <@649388957007609879>•Today at 16:21` instead of mentioning the user

* i think we should put at least rolling counts on the ongoing polls

* does the poll embed builder just add every single voter to the voting list? it feels like you might hit embed limits on massive polls, and/or it crowds the answer choices

* what if i want to unvote from a poll
  • made duration optional so there's no expiry by default
  • results embed links to the original poll message
  • /poll myvote to check your vote on anonymous polls
  • "Poll by" moved from footer to description
  • rolling vote counts shown on ongoing poll embeds now
  • voter list capped at 10 with "+ X more"
  • allows unvoting now by removing the minimum selected values

@maybe-yiyi

Copy link
Copy Markdown
Member

wait how do you unvote
it doesn't seem like i'm able to send a selection with 0 options selected or anything

@ap-1

ap-1 commented Apr 13, 2026

Copy link
Copy Markdown
Contributor Author

nevermind seems like that's not a thing, i just added an unvote button instead

@maybe-yiyi maybe-yiyi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

besides these things lgtm

didn't test attempting to delete polls without being the author, but the code looks correct.

  • perhaps eventually we can whitelist/blacklist multiple roles
  • maybe we consider whether it's necessary to enumerate the poll options, since we aren't voting using the enumeration nor does it really matter for poll results?

Comment thread src/commands/poll.ts Outdated
Comment thread src/commands/poll.ts Outdated
Comment thread src/commands/poll.ts Outdated
@ap-1
ap-1 requested a review from maybe-yiyi April 13, 2026 21:59

@maybe-yiyi maybe-yiyi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, thanks!

perhaps @TenType will want to review in terms of design, but it looks good to me.

@TenType TenType left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check this as well tonight, thanks yiyoung!

@TenType TenType left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, some things I think we should change:

  • I'd prefer if we don't show who votes for what by default as it clutters the embed. maybe we can have a button "See voters" that replies with an ephemeral message of voters for each choice
  • for anonymous polls, the number of people who voted for each choice is missing - can we also add the running count there as well?
  • for time-limited polls, let's also show the time remaining via a discord timestamp
  • I think it would be better to use components v2 for creating a poll (similar to how we do reaction redirect setup) than to accept the options via arguments, but this is okay to do in a separate PR

@maybe-yiyi

Copy link
Copy Markdown
Member

Wait does this have ranked choice implemented

@TenType TenType left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the earlier comment

@Gostmeaper Gostmeaper self-assigned this May 3, 2026
@Gostmeaper Gostmeaper removed their assignment May 20, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c3afe16b-5809-4bcc-9f05-dbc347d6522b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch polls

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Adds show_progress_bars and option_marker_style columns to both
poll_config (guild-wide defaults) and polls (per-poll snapshot so
behavior doesn't change retroactively if guild settings change later).
Moves poll configuration out of the generic SetupForm wizard into a
dedicated buttons-in-a-container flow matching PollCreateForm's style,
since a subcommand can't carry .setDefaultMemberPermissions() (only
top-level slash commands can), and the new flow needs plain toggle
buttons alongside a channel select rather than a form wizard.

Lets admins configure: the polls channel, whether progress bars are
shown, and whether option markers use letters or numbers.
- message_id options were passed straight into a bigint DB column;
  non-numeric input (e.g. 'a') threw a raw Postgres cast error instead
  of a clean reply. Added a snowflake regex check on every subcommand
  that takes a message_id.
- Closing/deleting a poll required Administrator; weakened to
  ManageMessages, which better fits the action.
- Added .orderBy(asc(pollOptions.id)) to option queries so option
  order is deterministic (Postgres doesn't guarantee row order without
  an ORDER BY).
- Removed the /poll setup subcommand (moved to the standalone
  /pollsetup command) and pointed the "no polls channel configured"
  message at it.
pollCreateForm.ts:
- Scale to 20 max options (was 10).
- Replace push/pop-only option editing (Add option / Remove last)
  with a dedicated options sub-view where each option gets its own
  remove button, since Discord's 40-component-per-message cap rules
  out giving every option its own button alongside the rest of the
  form on the main view.
- Fix Multi-select/Ranked choice toggle asymmetry: picking either one
  now always clears the other, instead of only one direction doing so.
- Replace unconventional symbols (×, —, ·) with plain ASCII.
- Guard each option-add modal with a per-call nonce in its customId so
  a double-triggered modal can't have two awaitModalSubmit listeners
  both resolve on the same submission (was double-adding options).
- Scope the component collector to the reply message (not the whole
  channel) and track one active session per user per guild, canceling
  a user's previous /poll create session when they start a new one -
  concurrent sessions were cross-talking since the old channel-scoped
  collector reacted to interactions from either session.
- Suppress notification pings from the poll message's mentions.
- Wire up the new showProgressBars/optionMarkerStyle poll-setup
  options end to end.

pollVotes.ts:
- Convert the live/closed poll message from an embed to a Components
  V2 container so it can have a real separator (embeds have no native
  horizontal rule), restoring the divider under the title the reviewer
  asked for.
- Add letter/number marker emoji beside each option and in the voting
  dropdown, stable regardless of vote-percentage sort order.
- Render the options/bars as a monospaced table; labels are padded,
  never truncated. Labels longer than a cap move their bar/percentage
  to an indented line underneath instead of trailing inline, so a long
  option can't soft-wrap mid-row and strand the bar/percentage.
- Bold the whitelist/blacklist line and move it out of the embed
  footer (footers can't render markdown), combined onto one small-text
  line with the timestamp.
- Suppress notification pings on every send/edit/reply that can
  contain a mention.
- .orderBy(asc(...)) on every option/vote query for deterministic
  ordering.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants