GitHub - kedarv/votey: a tiny voting app for slack

GitHub

4 min read Original article ↗

a simple slack polling slash command - because paying for polls is kind of stupid

User Guide

Votey is a surprisingly complex application because it has a variety of options that can allow you to customize how your poll looks and behaves. A Votey poll is composed of three components, a poll title, options, and voters. The first quoted string after the /votey command is used as the poll title, and following text is used to form "options" (ie. items that can be voted upon) and poll configuration options.

Run /votey with no arguments to open a creation modal with form fields for the question, options, per-option emoji, channel, vote limit, and anonymous/secret toggles. Use the Add option button to add up to 10 rows. The inline syntax below is still supported and posts the poll immediately.

Simple poll example:

/votey "some title" "some option A" "some option B"

Votey allows you to define "emoji vote icons" for each option. To enable this for a vote option, prepend the emoji you'd like to use:

/votey "some title" :thumbsup: "yes" :thumbsdown: "no"

To hide the names of voters, append --anonymous at the end of your poll creation text. To use an emoji other than the default :thumbsup: icon, use --anonymous=:emojiName:.

To hide the name of the poll creator and names of voters, append --secret at the end of your poll creation text.

To limit the number of votes per poll, append --limit=N at the end of your poll creation text. Note that N must be equal to lesser than the number of vote options provided.

Slack setup

Create a Slack app, add the chat:write and commands bot scopes under OAuth & Permissions, and create a /votey slash command. Enable Interactivity & Shortcuts so poll buttons and the creation modal work.

Votey supports two connection modes. SLACK_MODE=http is the default and is suited to a public deployment and multiple workspace installations. SLACK_MODE=socket maintains an outbound WebSocket connection and needs no public request URL.

HTTP webhooks

Configure these environment variables:

SLACK_MODE=http
CLIENT_ID=your-slack-client-id
CLIENT_SECRET=your-slack-client-secret
SIGNING_SECRET=your-slack-signing-secret
DATABASE_URL=postgresql://...

Use https://your-app.example/slack as both the slash command request URL and the Interactivity & Shortcuts request URL. Add https://your-app.example/oauth as an OAuth redirect URL, then install or distribute the app through Slack. The OAuth callback stores each workspace's bot token in the database.

HTTP mode runs under Gunicorn in the supplied Docker image.

Socket Mode

Enable Socket Mode in the Slack app settings. Create an app-level token with the connections:write scope, then install the app to the workspace and copy its bot token from OAuth & Permissions. Configure:

SLACK_MODE=socket
SLACK_APP_TOKEN=xapp-...
SLACK_BOT_TOKEN=xoxb-...
DATABASE_URL=postgresql://...

Do not configure request URLs for the slash command or interactivity. Start Votey with make start, or run the supplied Docker image; its entrypoint selects the socket process when SLACK_MODE=socket. On startup Votey validates the bot token and registers that workspace in the same database used by HTTP mode.

Socket Mode does not listen on an HTTP port. When deploying it to a platform such as Fly.io, remove HTTP services and TCP health checks from the deployment configuration for that process.

Development

Installation

Votey runs on Python 3.14. Install uv

Run the following in the source directory:

uv sync --all-groups
cp .env.example .env

Modify your .env file to look something like this:

SLACK_MODE=socket
SLACK_APP_TOKEN=xapp-your-app-token
SLACK_BOT_TOKEN=xoxb-your-bot-token

SQLite at data/votey.db is used when DATABASE_URL is omitted. To use HTTP mode during development, configure the HTTP variables described above and use a tunnel such as ngrok for the two Slack request URLs. Start either mode with make start.

While developing, you can use make <lint|pre-commit> to run linters or run the whole pre-commit suite over all files (which will both format and lint).

Before committing, don't forget to run make install-hooks.

Happy Developing!