Skip to content

Humblemonk/dicemaiden-rs

Repository files navigation

DiceMaiden - Rust Edition

A powerful Discord dice rolling bot written in Rust using the Serenity framework. This is a complete rewrite of the original DiceMaiden Ruby bot, featuring all the same functionality with improved performance and memory safety.

Dice Maiden

Features

  • Comprehensive Dice Rolling: Support for complex dice expressions with modifiers
  • Game System Aliases: Built-in support for popular RPG systems
  • Slash Commands: Modern Discord integration with /roll and /r commands
  • Advanced Modifiers: Exploding dice, keep/drop, rerolls, success counting, and more
  • Multiple Roll Types: Single rolls, roll sets, and multi-roll expressions
  • Message Management: Purge command for cleaning up chat

Quick Install

Click here to add Dice Maiden to your server

This will authorize the bot for your server and you should see it in your default public channel. The bot will have permissions to read, send and manage messages.

Note: Users need the Use Application Commands permission to use slash commands. It is also recommended to review your app integration settings found under Server Settings > Integrations. From here you can restrict the bot slash commands to specific channels.

Commands

  • /roll <dice> - Roll dice using RPG notation
  • /r <dice> - Short alias for roll
  • /help [topic] - Show help (topics: basic, alias, system)
  • /purge <count> - Delete recent messages (requires permissions)

Dice Rolling Syntax

Example Dice Roll

readme

Supported dice rolls and game systems can be found here!

Local Instance Setup

  1. Clone the repository

    git clone https://github.com/Humblemonk/dicemaiden-rs.git
    cd dicemaiden-rs
  2. Set up environment

    cp env.example .env
    # Edit .env and add your Discord bot token. Review the other ENV variables found in this documentation
  3. Build and run

    cargo build --release
    cargo run

Discord Bot Setup

  1. Go to the Discord Developer Portal
  2. Create a new application and bot
  3. Copy the bot token to your .env file
  4. Invite the bot to your server with the following permissions:
    • Send Messages
    • Use Slash Commands
    • Manage Messages (for purge command)
    • Read Message History

Invite URL Template:

https://discord.com/api/oauth2/authorize?client_id=YOUR_BOT_ID&permissions=274878000128&scope=bot%20applications.commands

Configuration

Environment Variables

  • DISCORD_TOKEN - Your Discord bot token (required)
  • GUILD_ID - Guild ID for testing commands (optional)
  • DATABASE_URL - SQLite database path. Defaults to sqlite:main.db, resolved relative to the working directory. This database is automatically created if it doesn't exist (optional)
  • SHARD_COUNT - Manual number of shards to use. Defaults to 1 for small bots (optional)
  • USE_AUTOSHARDING - Set to true to use discord recommended shard count. Defaults to false (optional)
  • MAX_CONCURRENCY - Max concurrent shard connections. Discord will override this with your bots actual limit (optional)
  • RUST_LOG - Log level (default: info). Supports per-module filtering via EnvFilter syntax; recommended for production: RUST_LOG=warn,dicemaiden_rs=info,serenity::gateway=info
  • SHARD_START - Starting shard ID for the process (needed for multi-process sharding)
  • TOTAL_SHARDS - Total shards across all processes (needed for multi-process sharding)

You can customize the build further by modifying Cargo.toml dependencies.

Development

Requirements

  • Rust 1.90+ (see rust-version in Cargo.toml)
  • Discord bot token
  • SQLite database (automatically created for bot statistics)
  • Dependencies - For a detailed list, review Cargo.toml

Building

# Development build
cargo build

# Release build
cargo build --release

# Run tests
cargo test

# Run with logging
RUST_LOG=debug cargo run

Before submitting changes, make sure the full quality gate passes:

cargo clippy -- -D warnings && cargo fmt --check && cargo test

Project Structure

src/
├── main.rs             # Application entry point and Discord client setup
├── database.rs         # SQLite database management for shard statistics
├── help_text.rs        # Shared help text generation for all help commands
├── lib.rs              # Shared libraries required for unit tests
├── dice/
│   ├── mod.rs          # Dice module exports and core types (DiceRoll, RollResult, etc.)
│   ├── parser.rs       # Dice expression parsing and syntax validation
│   ├── roller.rs       # Dice rolling execution and modifier application
│   ├── rng.rs          # Enhanced cryptographically secure RNG with multiple entropy sources
│   └── aliases.rs      # Game system aliases and expression expansions
└── commands/
    ├── mod.rs          # Command module exports and CommandResponse type
    ├── roll.rs         # Roll command implementation with system info
    ├── help.rs         # Help command with topic-based help system
    └── purge.rs        # Message purge command with permission checking

tests/
├── unit_tests.rs           # Core dice logic, parsing, rolling
├── game_systems_tests.rs   # All game system tests (consolidated)
├── integration_tests.rs    # End-to-end functionality
└── performance_tests.rs    # Performance and limit testing

Deployment

Docker

FROM rust:1.90-slim-bookworm AS builder

# Install build dependencies
RUN apt-get update && apt-get install -y \
    pkg-config \
    libssl-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy manifest files first for better layer caching
COPY Cargo.toml Cargo.lock ./

# Create dummy source to build dependencies
RUN mkdir src \
    && echo "fn main() {}" > src/main.rs \
    && touch src/lib.rs
RUN cargo build --release && rm -rf src

# Copy actual source code
COPY . .
# Force rebuild of our code but reuse dependencies
RUN touch src/main.rs src/lib.rs && cargo build --release

FROM debian:bookworm-slim

# Install runtime dependencies
RUN apt-get update && apt-get install -y \
    ca-certificates \
    sqlite3 \
    && rm -rf /var/lib/apt/lists/* \
    && useradd -m -u 1000 dicebot

COPY --from=builder /app/target/release/dicemaiden-rs /usr/local/bin/

# Create data directory for SQLite database
RUN mkdir -p /data && chown dicebot:dicebot /data

USER dicebot
WORKDIR /data

CMD ["dicemaiden-rs"]

Build and run:

docker build -t dicemaiden-rs .

# .env must contain at least DISCORD_TOKEN; the named volume persists the SQLite database
docker run -d \
  --name dicemaiden \
  --restart unless-stopped \
  --env-file .env \
  -v dicemaiden-data:/data \
  dicemaiden-rs

Systemd Service

[Unit]
Description=Dice Maiden
After=network-online.target
Wants=network-online.target
# Rate-limit restarts: an unbounded restart loop during a network outage can
# exhaust Discord's daily session start budget and invalidate your token.
StartLimitIntervalSec=1800
StartLimitBurst=5

[Service]
Type=simple
User=dicebot
Group=dicebot
# Working directory must be writable: the default DATABASE_URL (sqlite:main.db)
# resolves relative to it, and ProtectSystem=strict blocks writes elsewhere.
WorkingDirectory=/opt/dicemaiden-rs/data
Environment=RUST_LOG=warn,dicemaiden_rs=info,serenity::gateway=info
EnvironmentFile=/opt/dicemaiden-rs/.env
ExecStart=/opt/dicemaiden-rs/target/release/dicemaiden-rs
Restart=always
RestartSec=60
TimeoutStartSec=300
TimeoutStopSec=120

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/dicemaiden-rs/data
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Multi-Process Sharding

# Example: 3 processes handling 64 shards total
# Process 1: shards 0-20
SHARD_COUNT=21 SHARD_START=0 TOTAL_SHARDS=64 ./dicemaiden-rs &

# Process 2: shards 21-41  
SHARD_COUNT=21 SHARD_START=21 TOTAL_SHARDS=64 ./dicemaiden-rs &

# Process 3: shards 42-63
SHARD_COUNT=22 SHARD_START=42 TOTAL_SHARDS=64 ./dicemaiden-rs &

Differences from Original

This Rust implementation maintains full compatibility with the original DiceMaiden's dice syntax while offering:

  • Better Performance: Rust's zero-cost abstractions and memory safety plus low memory utilization
  • Modern Discord API: Native slash command support
  • Type Safety: Compile-time guarantees prevent runtime errors
  • Easier Deployment: Single binary with no runtime dependencies
  • Better Error Handling: Comprehensive error messages and recovery

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Verify the quality gate passes: cargo clippy -- -D warnings && cargo fmt --check && cargo test
  6. Submit a pull request

See CONTRIBUTING.md for the full contributor workflow.

License

This project is licensed under the GPLv3 License

Acknowledgments

  • Original DiceMaiden by Humblemonk and many awesome contributors!
  • Serenity Discord library
  • The Rust community for excellent crates and documentation

Support

  • Create an issue for bugs or feature requests
  • Check the documentation for dice syntax questions
  • Join the Discord community for help and discussion

Releases

No releases published

Sponsor this project

  •  

Packages

 
 
 

Contributors

Languages