2025-04-20 00:47:27 +08:00

9.5 KiB

Rust LavaLink Discord Music Bot Prototype

A prototype Discord music bot built with Rust, using the Serenity library for Discord interactions and the lavalink-rs crate to interface with a LavaLink audio server. This bot utilizes slash commands for user interaction and features a modular command structure using the inventory crate. It can be run natively or using Docker Compose for easier setup and deployment.

Features

  • Connects to Discord via the Gateway.
  • Connects to a LavaLink node for audio processing.
  • Slash command support for core music functions:
    • /join: Connect the bot to your voice channel.
    • /play: Play audio from a URL or search query (YouTube default). Handles single tracks and playlists.
    • /skip: Skip the currently playing track.
    • /leave: Disconnect the bot from the voice channel.
  • Basic queueing (handled internally by LavaLink).
  • Modular command system using inventory for easy addition of new commands.
  • Basic auto-leaving functionality when the bot is alone in a voice channel (with a short delay).
  • Asynchronous architecture using Tokio.
  • Logging using tracing.
  • Containerized setup using Docker and Docker Compose.

Prerequisites

For Native Execution

  1. Rust Toolchain: Install Rust using rustup. (rustup update recommended).
  2. LavaLink Server:
    • Download the latest Lavalink.jar from the LavaLink Releases.
    • A Java Runtime Environment (JRE) (Version 11 or higher, 17 recommended) to run the .jar file.
    • Configure the application.yml file for LavaLink.
  3. Discord Bot Application: (See details below)

For Docker Execution

  1. Docker & Docker Compose: Install Docker Desktop (which includes Compose) or Docker Engine and the Docker Compose plugin. See the official Docker installation guide.
  2. LavaLink Server Files: You still need to download Lavalink.jar and create/configure application.yml locally, as these will be mounted into the LavaLink container.
  3. Discord Bot Application: (See details below)

Discord Bot Application Details (Common)

  • Create a bot application on the Discord Developer Portal.
  • Retrieve the Bot Token.
  • Enable the Privileged Gateway Intents:
    • PRESENCE INTENT (Optional)
    • SERVER MEMBERS INTENT (Optional, not strictly required for prototype)
    • MESSAGE CONTENT INTENT (Optional, not strictly required for prototype)
    • GUILD_VOICE_STATES (Required for voice functionality)
  • Invite the bot to your Discord server with necessary permissions: Connect, Speak, Send Messages/Send Messages in Threads, Use Application Commands.

Setup

  1. Clone the Repository:

    git clone <repository-url>
    cd discord-music-bot-lavalink-rs
    
  2. Prepare LavaLink Files:

    • Download the latest Lavalink.jar from LavaLink Releases and place it in the project root directory.

    • Create or copy an application.yml file into the project root directory. Configure at least the lavalink.server.password. Example:

      # application.yml
      server:
        port: 2333
        address: 0.0.0.0
      lavalink:
        server:
          password: "youshallnotpass" # CHANGE THIS
          sources: # Enable desired sources
            youtube: true
            soundcloud: true
      # Add other configurations as needed
      
  3. Configure Environment Variables: Create a .env file in the project root:

    cp .env.example .env
    

    Edit .env with your credentials:

    # .env
    DISCORD_TOKEN=YOUR_BOT_TOKEN_HERE
    
    # --- IMPORTANT: Choose ONE Lavalink Host setting ---
    
    # == For Docker Compose Execution ==
    # Use the service name defined in docker-compose.yml
    LAVALINK_HOST=lavalink
    
    # == For Native Execution ==
    # Use the actual IP or hostname of your LavaLink server
    # LAVALINK_HOST=127.0.0.1 # Or e.g., other-machine-ip
    
    # --- Common Settings ---
    LAVALINK_PORT=2333
    LAVALINK_PASSWORD=youshallnotpass # Must match password in application.yml
    

    Note: Ensure the LAVALINK_PASSWORD here matches the one in application.yml.

Running the Bot

You can run the bot natively or using Docker Compose.

This method runs both the bot and the LavaLink server in isolated containers.

  1. Ensure Prerequisites: Docker, Docker Compose, Lavalink.jar, application.yml, configured .env (with LAVALINK_HOST=lavalink).

  2. Build and Start: In the project root, run:

    docker compose up --build -d
    
    • --build: Builds the bot image. Needed the first time or after code changes.
    • -d: Runs containers in the background.
  3. Check Logs (Optional):

    docker compose logs -f app      # View bot logs
    docker compose logs -f lavalink   # View LavaLink logs
    

    Press Ctrl+C to stop following.

  4. Stopping:

    docker compose down
    

Option 2: Running Natively

This method requires you to run LavaLink separately.

  1. Start LavaLink: Navigate to the directory containing Lavalink.jar and application.yml. Run:

    java -jar Lavalink.jar
    

    Keep this terminal open.

  2. Build the Bot (if needed):

    cargo build --release
    
  3. Configure .env: Ensure LAVALINK_HOST in your .env file points to the correct IP/hostname where LavaLink is running (e.g., 127.0.0.1 if running on the same machine).

  4. Run the Bot: In a new terminal, navigate to the project root and run:

    # Using cargo
    cargo run
    # Or using the compiled release binary
    # target/release/discord-music-bot-lavalink-rs
    

Available Commands

Use these commands in your Discord server where the bot is present:

  • /join : Makes the bot join the voice channel you are currently in.
  • /play query:<url or search term> : Plays a song from a URL (direct link or playlist) or searches YouTube for the term and plays the first result. Queues subsequent tracks/playlists.
  • /skip : Skips the song currently playing.
  • /leave : Disconnects the bot from the voice channel.

Project Structure

discord-music-bot-lavalink-rs/
├── .env                  # Local environment variables (ignored by git)
├── .env.example          # Example environment file
├── .dockerignore         # Files ignored by Docker context
├── Dockerfile            # Instructions to build the bot's Docker image
├── docker-compose.yml    # Defines bot and LavaLink services for Docker Compose
├── Lavalink.jar          # LavaLink server executable (add locally)
├── application.yml       # LavaLink configuration (add locally)
├── Cargo.toml            # Rust project manifest, dependencies
└── src/
    ├── main.rs           # Entry point, client setup, task spawning
    ├── state.rs          # Definition of the shared BotState struct
    ├── handler.rs        # Serenity event handler (ready, interaction_create, voice_state_update)
    ├── lavalink_handler.rs # lavalink-rs event handler (track start/end, etc.)
    ├── utils.rs          # Utility functions (e.g., get_voice_state)
    └── commands/         # Directory for slash command implementations
        ├── mod.rs        # Command registration setup (inventory, traits)
        ├── join.rs       # /join command implementation & registration
        ├── leave.rs      # /leave command implementation & registration
        ├── play.rs       # /play command implementation & registration
        └── skip.rs       # /skip command implementation & registration

Key Dependencies

  • Serenity: Discord API library for Rust.
  • lavalink-rs: Client implementation for the LavaLink protocol.
  • Tokio: Asynchronous runtime.
  • Inventory: Type-driven dependency injection / global struct collection (used for command registration).
  • Anyhow: Flexible error handling.
  • Tracing: Application-level tracing and logging framework.
  • Url: URL parsing.
  • Dotenv: Loading environment variables from .env files.
  • Docker: Containerization platform.

Future Improvements

This is a prototype, and many features could be added or improved:

  • [] More Commands: /queue, /pause, /resume, /nowplaying, /volume, /remove, /loop, /shuffle, etc.
  • [] Robust Error Handling: More specific error types and user-friendly feedback.
  • [] Queue Management: Displaying the queue, allowing users to remove specific tracks.
  • [] Permissions: Restricting commands based on user roles or voice channel status.
  • [] Configuration: Per-guild settings (e.g., announcement channels, DJ roles).
  • [] Player Persistence: Saving/loading player state across bot restarts (more complex).
  • [] Multi-Node Support: Utilizing multiple LavaLink nodes for scalability.
  • [] Tests: Adding unit and integration tests.