-
Notifications
You must be signed in to change notification settings - Fork 1
docs: unify README, setup guide, and description #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,129 +1,129 @@ | ||
| <img width="20%" src="assets/icon-no-bg.png" align="right" alt="Icon"> | ||
| <br> | ||
|
|
||
| # Project for PvR: Discord MusicBot in Rust | ||
| - Author: Pavel Mikula (MIK0486) | ||
| - Took approximately 40 hours | ||
|
|
||
| ## Project Theme | ||
| This project is a Discord bot developed in Rust, designed to play music in Discord voice channels. It uses libraries like `serenity` and `poise` for handling the Discord API, `songbird` for managing audio playback, `yt-dlp` for YouTube track streaming, and integrates with the Spotify Web API for Spotify URLs. The bot supports a full music queue, a local audio library, timed reminders, and several utility commands. | ||
|
|
||
| ## Project Requirements | ||
| - Rust: The primary programming language for bot logic | ||
| - Serenity + Poise: Discord API wrapper and command framework for Rust | ||
| - Songbird: Voice and audio playback library for Discord | ||
| - yt-dlp: For downloading and streaming audio from YouTube | ||
| - SQLite (via sqlx): Persistent storage for guild settings and reminders | ||
| - Spotify Web API: For resolving Spotify track / playlist URLs | ||
|
|
||
| ## Installation | ||
| ### Prerequisites | ||
| - Installed rust from [rust-lang.org](https://www.rust-lang.org/tools/install) | ||
| - Installed yt-dlp from [github.com/yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) | ||
| - `yt-dlp` should be in the system PATH | ||
| - Installed `ffmpeg` (in the system PATH) — used by yt-dlp for post-processing **and** by the bot's loudness analyzer to measure each track's integrated LUFS for cross-track volume normalization | ||
| - YouTube Data API token from [Google Cloud Console](https://developers.google.com/youtube/registering_an_application) | ||
| - Discord bot token from [Discord Developer Portal](https://discord.com/developers/applications) | ||
| - (Optional) Spotify Client ID & Secret from [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) — required for Spotify URL support | ||
| - Installed CMAKE. Required for the [audiopus_sys](https://github.com/Lakelezz/audiopus_sys) library | ||
|
|
||
| ### Installation | ||
| 1. Clone this repository | ||
| ```bash | ||
| git clone https://github.com/Firestone82/RustyTunes.git | ||
| cd RustyTunes | ||
| ``` | ||
| 2. Create a `.env` file in the root directory | ||
| ```bash | ||
| cp .env.example .env | ||
|
|
||
| # Edit the .env file with your Discord bot token, YouTube API key, | ||
| # and (optionally) Spotify client id and secret. | ||
| ``` | ||
| 3. Setup database | ||
| ```bash | ||
| cargo install sqlx-cli | ||
| sqlx database create | ||
| sqlx migrate run | ||
| ``` | ||
| 4. Install dependencies | ||
| ```bash | ||
| # yt-dlp | ||
| sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp | ||
| sudo chmod a+rx /usr/local/bin/yt-dlp | ||
|
|
||
| # ffmpeg (required by yt-dlp and by the loudness normalizer) | ||
| sudo apt-get install ffmpeg | ||
|
|
||
| # CMAKE | ||
| sudo apt-get install cmake | ||
| ``` | ||
| 5. Build and run the bot | ||
| ```bash | ||
| cargo build --release | ||
| cargo run | ||
| ``` | ||
|
|
||
| ## Usage | ||
| All commands are available as both **prefix commands** (default prefix `!`) and **slash commands** (`/`). Use `!help` or `/help` in Discord to list every command, or `!help <command>` for details on a specific one. | ||
| <img width="18%" src="assets/icon-no-bg.png" align="right" alt="Icon"> | ||
|
|
||
| # RustyTunes | ||
|
|
||
| > **VŠB-TUO** — School project · Programming in Rust (PvR) | ||
|
|
||
|   | ||
|
|
||
| A feature-rich Discord music bot written in Rust. Supports YouTube, Spotify, local audio files, and direct URLs. Includes a persistent queue, per-guild volume memory, loudness normalization, timed reminders, and various utility commands. | ||
|
|
||
| ## Features | ||
|
|
||
| ### Audio Sources | ||
| - Play tracks and playlists from **YouTube** (direct URL or text search) | ||
| - Play tracks and playlists from **Spotify** (URL — resolved to YouTube for playback) | ||
| - Play files from a **local audio library** stored on the bot host | ||
| - Stream user-uploaded **Discord attachments** (audio files) | ||
| - Stream audio from **arbitrary direct URLs** | ||
| - YouTube (direct URL or text search) | ||
| - Spotify (URL — resolved to YouTube for playback) | ||
| - Local audio library stored on the bot host | ||
| - Discord attachment uploads (audio files) | ||
| - Arbitrary direct URLs | ||
|
|
||
| ### Playback Controls | ||
| - `play <query|url>` — play a track or playlist from YouTube or Spotify (appends to queue) | ||
| - `playtop <query|url>` — same as `play` but inserts at the front of the queue | ||
| - `pause` / `resume` — pause and resume the current track | ||
| - `skip [amount]` — skip the current track (or multiple at once) | ||
| - `stop` — stop playback and clear the active track | ||
| - `playing` — show the currently playing track | ||
| - `volume [1-100]` — set the playback volume; append `!` (e.g. `volume 200!`) to opt into the extended 1–500 overdrive range | ||
| - `normalize [on|off]` — toggle session-only cross-track loudness normalization (off by default, applies to every source once enabled, resets on restart) | ||
| - `silent [on|off]` — suppress NowPlaying announcements for the session | ||
| - `join` / `leave` — manually summon or dismiss the bot from your voice channel | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `play <query\|url>` | Play a track or playlist, append to queue | | ||
| | `playtop <query\|url>` | Same, but insert at front of queue | | ||
| | `pause` / `resume` | Pause and resume the current track | | ||
| | `skip [amount]` | Skip current track (or N tracks) | | ||
| | `stop` | Stop playback and clear the active track | | ||
| | `playing` | Show the currently playing track | | ||
| | `volume [1-100]` | Set volume; append `!` for overdrive (1–500) | | ||
| | `normalize [on\|off]` | Toggle cross-track loudness normalization (EBU R128) | | ||
| | `silent [on\|off]` | Suppress Now Playing announcements | | ||
| | `join` / `leave` | Summon or dismiss from voice channel | | ||
|
|
||
| ### Queue Management | ||
| - `queue` — paginated queue listing (10 tracks per page) with navigation buttons | ||
| - `clear` — remove every track from the queue | ||
| - `remove <index>` — remove a specific track from the queue by its 1-based index | ||
| - `shuffle` — shuffle the current queue | ||
| - `history` — show the last 10 played tracks with buttons to instantly replay any of them | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `queue` | Paginated queue (10 tracks/page) with navigation | | ||
| | `clear` | Remove all tracks from the queue | | ||
| | `remove <index>` | Remove a specific track by 1-based index | | ||
| | `shuffle` | Shuffle the current queue | | ||
| | `history` | Last 10 played tracks with replay buttons | | ||
|
|
||
| ### Local Audio Library | ||
| The `local` command groups subcommands for managing audio files saved on the bot host: | ||
| - `local download <url> [name]` — download an audio file from a URL into the library | ||
| - `local upload [name]` — save an uploaded Discord attachment into the library | ||
| - `local list` — list all saved local tracks | ||
| - `local play [name]` — play a saved track by name (with autocomplete and an interactive picker) | ||
| - `local rename <track> <new name>` — rename a saved track | ||
| - `local remove <track>` — delete a saved track from the library | ||
|
|
||
| ### Reminders / Notifications | ||
| The `notify` command (alias `remind`) lets users schedule timed reminders persisted to the database: | ||
| - `notify me <when> <message>` — schedule a reminder for yourself | ||
| - `notify you <user> <when> <message>` — schedule a reminder for another user | ||
| - `notify list` — list your pending reminders | ||
| - `notify remove <id>` — cancel a pending reminder | ||
|
|
||
| ### Utility Commands | ||
| - `wakeup <user> [count]` — drags a user briefly between voice channels to grab their attention (also available as a right-click **WakeUp!** user context menu action) | ||
| - `rename <user> [new name]` — set another member's nickname (respects role hierarchy) | ||
| - `uwu <text>` — uwuify the given text | ||
| - `uwu_me <text>` — uwuify text and post it impersonating the author via webhook | ||
| - `help [command]` — built-in help listing and per-command detail | ||
|
|
||
| ### Quality-of-Life Behaviour | ||
| - **Auto-leave**: bot automatically leaves the voice channel when it's left alone | ||
| - **Auto-cleanup**: when the bot is kicked, dragged out, or otherwise loses its voice connection, playback state and the queue are cleaned up automatically | ||
| - **Per-guild volume persistence**: the last-set volume is remembered between sessions in SQLite | ||
| - **Cross-track loudness normalization**: opt-in via `!normalize`. When enabled, each cached track's integrated loudness is measured once (EBU R128 via ffmpeg) and a static gain is applied so songs sit at roughly the same perceived loudness without crushing in-song dynamics. Off by default, takes effect immediately on the current track, resets on restart. The target loudness (`NORMALIZE_TARGET_LUFS`, default -10) and gain clamps (`NORMALIZE_MIN_GAIN_DB`, `NORMALIZE_MAX_GAIN_DB`) are tunable via env vars — higher target = louder output | ||
| - **Per-source cache layout**: downloaded audio is filed under `cache/youtube/` or `cache/spotify/` (legacy flat-cached files still play) | ||
| - **Slash + prefix parity**: every command works both ways | ||
| - **Graceful shutdown**: handles SIGINT/SIGTERM (and Ctrl+C on Windows) to disconnect cleanly | ||
| - **Structured logging**: powered by `tracing` with environment-controlled filtering | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `local download <url> [name]` | Download audio from URL into library | | ||
| | `local upload [name]` | Save a Discord attachment into library | | ||
| | `local list` | List all saved tracks | | ||
| | `local play [name]` | Play a saved track (with autocomplete) | | ||
| | `local rename <track> <name>` | Rename a saved track | | ||
| | `local remove <track>` | Delete a saved track | | ||
|
|
||
| ### Reminders | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `notify me <when> <msg>` | Schedule a reminder for yourself | | ||
| | `notify you <user> <when> <msg>` | Schedule a reminder for another user | | ||
| | `notify list` | List your pending reminders | | ||
| | `notify remove <id>` | Cancel a pending reminder | | ||
|
|
||
| ### Utilities | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `wakeup <user> [count]` | Drag a user between voice channels to get attention | | ||
| | `rename <user> [name]` | Set a member's nickname | | ||
| | `uwu <text>` | Uwuify text | | ||
| | `help [command]` | Show command list or per-command help | | ||
|
|
||
| All commands are available as both prefix commands (default `!`) and slash commands (`/`). | ||
|
|
||
| ### Quality-of-Life | ||
| - Auto-leave when alone in channel | ||
| - Per-guild volume persistence (SQLite) | ||
| - Cross-track loudness normalization (opt-in, EBU R128 via ffmpeg) | ||
| - Slash + prefix parity | ||
| - Graceful SIGINT/SIGTERM shutdown | ||
| - Structured logging via `tracing` | ||
|
|
||
| ## Requirements | ||
|
|
||
| - Rust stable toolchain — [rustup.rs](https://rustup.rs/) | ||
| - [`yt-dlp`](https://github.com/yt-dlp/yt-dlp) in system PATH | ||
| - [`ffmpeg`](https://ffmpeg.org/) in system PATH | ||
| - CMake (required by `audiopus_sys`) | ||
| - Discord bot token — [discord.com/developers](https://discord.com/developers/applications) | ||
| - YouTube Data API v3 key — [Google Cloud Console](https://console.cloud.google.com/) | ||
| - *(Optional)* Spotify Client ID & Secret — [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. Install system dependencies: | ||
| ```bash | ||
| # Debian/Ubuntu | ||
| sudo apt-get install ffmpeg cmake | ||
| sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp \ | ||
| -o /usr/local/bin/yt-dlp && sudo chmod a+rx /usr/local/bin/yt-dlp | ||
| ``` | ||
|
|
||
| 2. Clone the repository: | ||
| ```bash | ||
| git clone https://github.com/Firestone82/RustyTunes.git | ||
| cd RustyTunes | ||
| ``` | ||
|
|
||
| 3. Copy `.env.example` to `.env` and fill in your Discord token, YouTube API key, and optional Spotify credentials. | ||
|
|
||
| 4. Set up the database: | ||
| ```bash | ||
| cargo install sqlx-cli | ||
| sqlx database create | ||
| sqlx migrate run | ||
| ``` | ||
|
|
||
| 5. Build and run: | ||
| ```bash | ||
| cargo build --release | ||
| cargo run --release | ||
| ``` | ||
|
|
||
| ### Discord bot setup | ||
|
|
||
| 1. Create an application at [discord.com/developers/applications](https://discord.com/developers/applications). | ||
| 2. Under **Bot**, enable **Message Content Intent** and **Server Members Intent**. | ||
| 3. Copy the bot token into `.env` as `DISCORD_TOKEN`. | ||
| 4. Invite the bot via the OAuth2 URL generator with `bot` + `applications.commands` scopes and `Connect`, `Speak`, and `Send Messages` permissions. | ||
|
|
||
| ## License | ||
|
|
||
| This project was created as a school assignment at VŠB-TUO. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setup step now calls
sqlx database createon a clean checkout without ever installing thesqlxCLI. A standard Rust install only provides Cargo/Rust tools, so users following the README hitsqlx: command not foundbefore they can create the SQLite database or run migrations; the previous instructions includedcargo install sqlx-clibefore these commands.Useful? React with 👍 / 👎.