224 lines
9.5 KiB
Markdown
224 lines
9.5 KiB
Markdown
# 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 <repository-url>
|
|
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:<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](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. |