# Rust LavaLink Discord Music Bot Prototype A prototype Discord music bot built with Rust, using the [Serenity](https://github.com/serenity-rs/serenity) library for Discord interactions and the [lavalink-rs](https://github.com/adamsoutar/lavalink-rs) crate to interface with a [LavaLink](https://github.com/lavalink-devs/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](https://rustup.rs/). (`rustup update` recommended). 2. **LavaLink Server:** * Download the latest `Lavalink.jar` from the [LavaLink Releases](https://github.com/lavalink-devs/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](https://docs.docker.com/engine/install/). 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](https://discord.com/developers/applications). * 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:** ```bash git clone cd discord-music-bot-lavalink-rs ``` 2. **Prepare LavaLink Files:** * Download the latest `Lavalink.jar` from [LavaLink Releases](https://github.com/lavalink-devs/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: ```yaml # 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: ```bash cp .env.example .env ``` Edit `.env` with your credentials: ```env # .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. ### Option 1: Running with Docker Compose (Recommended) 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: ```bash 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):** ```bash docker compose logs -f app # View bot logs docker compose logs -f lavalink # View LavaLink logs ``` Press `Ctrl+C` to stop following. 4. **Stopping:** ```bash 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: ```bash java -jar Lavalink.jar ``` Keep this terminal open. 2. **Build the Bot (if needed):** ```bash 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: ```bash # 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:` : 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](https://github.com/serenity-rs/serenity): Discord API library for Rust. * [lavalink-rs](https://github.com/adamsoutar/lavalink-rs): Client implementation for the LavaLink protocol. * [Tokio](https://tokio.rs/): Asynchronous runtime. * [Inventory](https://github.com/dtolnay/inventory): Type-driven dependency injection / global struct collection (used for command registration). * [Anyhow](https://github.com/dtolnay/anyhow): Flexible error handling. * [Tracing](https://github.com/tokio-rs/tracing): Application-level tracing and logging framework. * [Url](https://crates.io/crates/url): URL parsing. * [Dotenv](https://crates.io/crates/dotenv): Loading environment variables from `.env` files. * [Docker](https://www.docker.com/): 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.