A comprehensive Discord poll bot with advanced scheduling, admin-only access, and a beautiful web interface for poll management.
- Only server administrators can create polls
- Discord OAuth authentication with permission verification
- Secure JWT-based web sessions
- Named polls with custom options (up to 10)
- Full-size image uploads (not tiny thumbnails)
- Rich Discord embeds with real-time vote counts
- Emoji-based voting system (🇦 🇧 🇨 🇩 🇪 🇫 🇬 🇭 🇮 🇯)
- User preferences system - remembers last used server, channel, and timezone
- Anonymous polls option to hide results until poll ends
- Calendar and time picker for precise scheduling
- Automatic poll opening and closing
- Timezone-aware scheduling system
- Background job processing with APScheduler
- Beautiful Bootstrap-based interface with HTMX (NO JavaScript)
- Create and manage polls from the web
- Live updates without page refreshes
- View poll history and results
- Responsive design for mobile and desktop
- US/Eastern timezone as default
- Poll messages display times in selected timezone
- Timezone-aware scheduling system
- Support for major world timezones
- Built with modern Python stack (FastAPI + discord.py)
- HTMX for dynamic UI without JavaScript
- SQLite database for zero-configuration setup
- Single application deployment
- Managed with
uvfor blazing fast package management
- Python 3.11+
- Discord Bot Token
- Discord Application Client ID & Secret
-
Clone the repository
git clone <repository-url> cd polly
-
Install dependencies with uv
uv sync
-
Configure environment
cp .env.example .env # Edit .env with your Discord bot credentials -
Run the application
uv run python -m polly.main
-
Access the web interface
- Open http://localhost:8000
- Login with Discord
- Start creating polls!
-
Create Discord Application
- Go to https://discord.com/developers/applications
- Click "New Application"
- Give it a name (e.g., "Polly")
-
Create Bot
- Go to "Bot" section
- Click "Add Bot"
- Copy the bot token to your
.envfile
-
Configure OAuth2
- Go to "OAuth2" section
- Add redirect URI:
http://localhost:8000/auth/callback - Copy Client ID and Client Secret to your
.envfile
-
Invite Bot to Server
- Go to "OAuth2" > "URL Generator"
- Select scopes:
bot,applications.commands - Select permissions:
Send Messages,Add Reactions,Use Slash Commands - Use generated URL to invite bot
Create a .env file with the following variables:
# Discord Bot Configuration
DISCORD_TOKEN=your_discord_bot_token_here
DISCORD_CLIENT_ID=your_discord_client_id_here
DISCORD_CLIENT_SECRET=your_discord_client_secret_here
# Web Application Configuration
DISCORD_REDIRECT_URI=http://localhost:8000/auth/callback
SECRET_KEY=your-secret-key-for-jwt-tokens-change-this
BASE_URL=http://localhost:8000/poll- Create a quick poll with up to 5 options- Example:
/poll question:"What's your favorite color?" option1:"Red" option2:"Blue" option3:"Green"
- Example:
- Login - Authenticate with Discord OAuth
- Dashboard - View and manage your polls with live statistics
- Create Poll - Use the web form for advanced options:
- Named polls with custom scheduling
- Image uploads (up to 8MB)
- Server and channel selection
- Anonymous poll option
- Timezone selection
- Poll Management - Full CRUD operations:
- Edit scheduled polls before they start
- View detailed poll results and analytics
- Manually close active polls
- Delete polls (with automatic image cleanup)
- Live Vote Updates - Poll embeds update in real-time as users vote
- Smart User Preferences - Remembers your last used server, channel, and timezone
- Automatic Messaging - Sends completion message to the same channel when polls end
- Comprehensive Logging - Full audit trail of all poll operations
- Image Management - Automatic cleanup of uploaded images when polls are deleted
- Status-Based Actions - Different management options based on poll status (scheduled/active/closed)
- Admin Only - Only server administrators can create and manage polls
- Backend: Python 3.11+, FastAPI, discord.py
- Database: SQLite with SQLAlchemy ORM
- Frontend: Bootstrap 5, HTMX (NO JavaScript)
- Scheduling: APScheduler
- Authentication: Discord OAuth2 + JWT
- Package Management: uv
polly/
├── polly/ # Main package
│ ├── __init__.py
│ ├── main.py # Application entry point
│ ├── database.py # Database models
│ ├── auth.py # Authentication logic
│ └── discord_utils.py # Discord bot utilities
├── templates/ # HTML templates
│ ├── index.html # Landing page
│ ├── dashboard.html # Admin dashboard (legacy)
│ ├── dashboard_htmx.html # HTMX-powered dashboard
│ └── htmx/ # HTMX partial templates
│ ├── polls.html # Poll listing
│ ├── stats.html # Dashboard stats
│ ├── create_form.html # Poll creation form
│ └── servers.html # Server selection
├── static/uploads/ # Image storage
├── cline_docs/ # Project documentation
├── pyproject.toml # Dependencies and config
├── .env.example # Environment template
└── README.md # This file
This project uses uv for blazing fast Python package management. Here are the essential commands:
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install all dependencies (creates virtual environment automatically)
uv sync
# Add a new dependency
uv add package-name
# Add a development dependency
uv add --dev package-name
# Remove a dependency
uv remove package-name
# Update all dependencies
uv sync --upgrade
# Run commands in the virtual environment
uv run python -m polly.main
uv run uvicorn polly.main:app --reload
# Activate the virtual environment manually (optional)
source .venv/bin/activate # Linux/Mac
# or
.venv\Scripts\activate # Windows# Install dependencies
uv sync
# Run with auto-reload
uv run uvicorn polly.main:app --reload --host 0.0.0.0 --port 8000
# Or run the main module directly
uv run python -m polly.mainThe SQLite database is automatically created and initialized on first run. No migrations needed for the MVP.
- Update database models in
polly/database.py - Add API endpoints in
polly/main.py - Update web interface in
templates/ - Test with Discord bot commands
# Start development server
uv run uvicorn polly.main:app --reload
# Run tests (when available)
uv run pytest
# Format code
uv run black polly/
uv run isort polly/
# Type checking
uv run mypy polly/-
Clone and Configure
git clone <repository-url> cd polly cp .env.example .env # Edit .env with your Discord bot credentials
-
Build and Run with Docker Compose
docker-compose up -d
-
Access the Application
- Web interface: http://localhost:8000
- With nginx proxy: http://localhost (port 80)
The Docker setup includes:
- Polly application container
- Nginx reverse proxy (optional)
- Automatic restarts
- Health checks
- Volume mounts for data persistence
-
Setup Environment
# On your server git clone <repository-url> cd polly uv sync cp .env.example .env # Configure .env with production values
-
Create Systemd Service
# /etc/systemd/system/polly.service [Unit] Description=Polly Discord Poll Bot After=network.target [Service] Type=simple User=polly WorkingDirectory=/path/to/polly ExecStart=/path/to/polly/.venv/bin/python -m polly.main Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
-
Start Service
sudo systemctl enable polly sudo systemctl start polly
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /path/to/polly/static/;
}
}- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please:
- Check the documentation
- Search existing issues
- Create a new issue with detailed information
Built with ❤️ for the Discord community