diff --git a/Dockerfile b/Dockerfile
index f35033b..ac3bfe1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
# =========
# Builder
# =========
-FROM rust:bookworm as builder
+FROM rust:bookworm AS builder
WORKDIR /builder
COPY migrations ./migrations
@@ -14,7 +14,7 @@ RUN cargo build --release
# ==========
# Packages
# ==========
-FROM debian:bookworm-slim as packages
+FROM debian:bookworm-slim AS packages
WORKDIR /packages
ARG TARGETPLATFORM
@@ -36,7 +36,7 @@ RUN apt-get update && apt-get install -y python3 curl tar xz-utils && \
# =========
# Runtime
# =========
-FROM debian:bookworm-slim as runtime
+FROM debian:bookworm-slim AS runtime
WORKDIR /siren
USER root
diff --git a/Makefile b/Makefile
index bdc9244..9a4834a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,57 +1,56 @@
#!make
SHELL := /bin/bash
-
-include .env
--include .env.local
-export
+ENV := ./scripts/apply_env.sh
.PHONY: help
+export VERSION=$(if $(v),$(v),latest)
+
help: ## Help command
@echo
@cat Makefile | grep -E '^[a-zA-Z\/_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@echo
backend-up: ## Start the backend containers
- @docker compose --profile backend up -d
+ @$(ENV) docker compose --profile backend up -d
up-backend: backend-up
backend-down: ## Stop the backend containers
- @docker compose --profile backend down
+ @$(ENV) docker compose --profile backend down
down-backend: backend-down
run: ## Run the project
@echo "Running project..."
- @cargo run
+ @$(ENV) cargo run
@echo "Run complete"
format: ## Format code
@echo "Formatting code..."
- @cargo fmt
+ @$(ENV) cargo fmt
@echo "Format complete"
clean: ## Clean the project
@echo "Cleaning project..."
- @cargo clean
+ @$(ENV) cargo clean
@echo "Clean complete"
docker-up: ## Start the app
- @docker compose --profile backend --profile bot up -d
+ @$(ENV) docker compose --profile backend --profile bot up -d
docker-down: ## Stop the app
- @docker compose --profile backend --profile bot down
+ @$(ENV) docker compose --profile backend --profile bot down
docker-build: ## Build the docker image
- @docker compose build
+ @$(ENV) docker build -f Dockerfile -t siren:${VERSION} .
docker-clean: ## Stop the docker containers and remove volumes
@echo "Stopping docker container and removing volumes..."
- @docker compose --profile backend --profile bot down -v
+ @$(ENV) docker compose --profile backend --profile bot down -v
@echo "Docker container stopped and volumes removed"
docker-refresh: docker-clean backend-up ## Refresh the docker containers
psql: ## Connect to the database
- @docker exec -it siren-postgres psql -U ${DATABASE_USER} -P pager=off
\ No newline at end of file
+ @$(ENV) docker exec -it siren-postgres psql -U ${DATABASE_USER} -P pager=off
\ No newline at end of file
diff --git a/README.md b/README.md
index eb42a8b..b80ec05 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,10 @@
Siren is a D&D Bot built for Discord, written in Rust. Features include:
-- Play tracks from Youtube or locally hosted files
-- Assistant DM tools to be defined later
+- Music commands from Youtube and locally hosted files
+- Database for D&D 5e content
+- Session scheduling
+- Backend API
- ChatGPT integration
## Requirements
@@ -80,6 +82,7 @@ Siren utilizes Discord slash commands. To view the commands, run `/help` in a se
| `/resume` | Resume the current track |
| `/skip` | Skip the current track |
| `/stop` | Stop the current track |
+| `/mute` | Mute the current track |
| `/queue` | ***TODO*** - Display the current queue |
| `/clear` | ***TODO*** - Clear the current queue |
| `/shuffle` | ***TODO*** - Shuffle the current queue |
@@ -111,48 +114,16 @@ Siren utilizes Discord slash commands. To view the commands, run `/help` in a se
| `/help` | ***TODO*** - Display a list of commands |
## Contributing
-[Rust](https://www.rust-lang.org/) must be installed to run locally. See [serenity-rs/serenity](https://github.com/serenity-rs/serenity) for more information about Rust Discord API Library.
-
-The following packages must be installed for [serenity-rs/songbird](https://github.com/serenity-rs/songbird). View the repository for additional installation and setup information on other operating systems.
-
- Unix Installation
- Notes:
-
- - [yt-dlp](https://github.com/yt-dlp/yt-dlp/releases) is preferred over youtube-dl.
-
- ```
- sudo apt install libopus-dev
- sudo apt install ffmpeg
- sudo apt apt install youtube-dl # See notes above
- # PostgreSQL Headers
- sudo apt install libpq5
- sudo apt install libpq-dev
- ```
-
- - Potentially requires [yt-dlp](https://github.com/yt-dlp/yt-dlp#installation) and [yt-dlp FFmpeg Static Auto-Builds](https://github.com/yt-dlp/FFmpeg-Builds).
-
-
-
- Mac Installation
- Notes:
-
- - [Homebrew](https://brew.sh/) must be installed to run the following commands.
- - [youtube-dl](https://formulae.brew.sh/formula/youtube-dl#default) is deprecated, [yt-dlp](https://formulae.brew.sh/formula/yt-dlp) is preferred
-
- ```
- brew install opus
- brew install ffmpeg
- brew install yt-dlp # See notes above
- brew install postgresql
- ```
-
+ - [Rust](https://www.rust-lang.org/)
+ - [yt-dlp](https://github.com/yt-dlp/yt-dlp)
+ - [ffmpeg](https://github.com/yt-dlp/FFmpeg-Builds)
### Running Locally
-1. Start the backend containers with `make docker-refresh`
-2. Start the application with `make run`
+1. Start the backend containers with `make backend-up`
+2. Run the application locally with `make run`
The application can also be tested from within a Docker container:
```
-docker build -t siren:latest .
-docker run --env-file .env -it --rm --name siren siren:latest
+make docker-build
+make docker-up
```
diff --git a/docker-compose.yml b/docker-compose.yml
index f497a72..6245902 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,13 +7,8 @@ x-env_file: &env
name: siren
services:
bot:
- image: siren-service:${SIREN_VERSION:-latest}
- container_name: siren-bot
- build:
- context: .
- dockerfile: ./Dockerfile
- args:
- - VERSION=${SIREN_VERSION:-latest}
+ image: siren:${SIREN_VERSION:-latest}
+ container_name: siren
env_file: *env
environment:
DATABASE_HOST: postgres
@@ -34,7 +29,7 @@ services:
postgres:
image: postgres:latest
- container_name: siren-postgres
+ container_name: postgres
env_file: *env
environment:
POSTGRES_USER: ${DATABASE_USER}
diff --git a/scripts/apply_env.sh b/scripts/apply_env.sh
new file mode 100755
index 0000000..990fab9
--- /dev/null
+++ b/scripts/apply_env.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Enable exporting variables
+set -a
+
+# Source the default env variables
+echo "Sourcing build environment"
+source .env
+
+# If there is a .env.local present, source it
+echo "Sourcing custom environment"
+if [ -f .env.local ]; then
+ source ./.env.local
+fi
+
+# Disable exporting variables
+set +a
+
+# Run the given command
+exec "$@"
diff --git a/src/bot/commands/audio/pause.rs b/src/bot/commands/audio/pause.rs
index cf566a2..79cbb3d 100644
--- a/src/bot/commands/audio/pause.rs
+++ b/src/bot/commands/audio/pause.rs
@@ -3,7 +3,7 @@ use serenity::{
prelude::*,
};
-use super::{create_response, edit_response, get_songbird, process_message};
+use super::{edit_response, get_songbird, process_message};
pub async fn run(ctx: &Context, command: &CommandInteraction) {
// Create the initial response
diff --git a/src/bot/commands/audio/play.rs b/src/bot/commands/audio/play.rs
index 83f2729..56feae4 100644
--- a/src/bot/commands/audio/play.rs
+++ b/src/bot/commands/audio/play.rs
@@ -56,7 +56,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) {
Ok(channel_id) => {
log::debug!("<{guild_id}> Play command executed on {channel_id} with track: {track_url:?}");
// Handle the track url
- match enqueue_track(ctx, manager, guild_id.to_owned(), track_url, true).await {
+ match enqueue_track(ctx, manager, guild_id.to_owned(), track_url).await {
Ok(count) => {
let mut message = format!("Playing {} tracks", count);
if count == 0 {
@@ -84,7 +84,6 @@ pub async fn enqueue_track(
manager: Arc,
guild_id: GuildId,
track_url: &str,
- play_now: bool,
) -> SirenResult {
let mut track_count = 0;
if let Some(handler_lock) = manager.get(guild_id) {
@@ -140,7 +139,6 @@ pub async fn enqueue_track(
}
};
let track_handle: TrackHandle;
- let is_queue_empty = handler.queue().is_empty();
track_handle = handler.enqueue_input(input).await;
// Set the volume
let _ = track_handle.set_volume(volume);
@@ -156,8 +154,8 @@ pub async fn enqueue_track(
);
track_count += 1;
}
- if play_now && !handler.queue().is_empty() {
- handler.queue().resume();
+ if handler.queue().is_empty() {
+ let _ = handler.queue().resume();
}
}
Ok(track_count)
diff --git a/src/bot/commands/audio/resume.rs b/src/bot/commands/audio/resume.rs
index 5b6a1e4..51b4206 100644
--- a/src/bot/commands/audio/resume.rs
+++ b/src/bot/commands/audio/resume.rs
@@ -3,7 +3,7 @@ use serenity::{
prelude::*,
};
-use super::{create_response, edit_response, get_songbird, process_message};
+use super::{edit_response, get_songbird, process_message};
pub async fn run(ctx: &Context, command: &CommandInteraction) {
// Create the initial response
diff --git a/src/bot/commands/audio/skip.rs b/src/bot/commands/audio/skip.rs
index 5ac5337..8b22713 100644
--- a/src/bot/commands/audio/skip.rs
+++ b/src/bot/commands/audio/skip.rs
@@ -3,7 +3,7 @@ use serenity::{
prelude::*,
};
-use super::{get_songbird, create_response, edit_response};
+use super::{edit_response, get_songbird, process_message};
pub async fn run(ctx: &Context, command: &CommandInteraction) {
// Create the initial response
diff --git a/src/bot/commands/audio/stop.rs b/src/bot/commands/audio/stop.rs
index 71b08a2..7897144 100644
--- a/src/bot/commands/audio/stop.rs
+++ b/src/bot/commands/audio/stop.rs
@@ -3,7 +3,7 @@ use serenity::{
prelude::*,
};
-use super::{get_songbird, create_response, edit_response};
+use super::{edit_response, get_songbird, process_message};
pub async fn run(ctx: &Context, command: &CommandInteraction) {
// Create the initial response
diff --git a/src/bot/commands/audio/volume.rs b/src/bot/commands/audio/volume.rs
index 774364c..fe7e911 100644
--- a/src/bot/commands/audio/volume.rs
+++ b/src/bot/commands/audio/volume.rs
@@ -48,12 +48,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) {
// Set the volume
set_volume(&manager, guild_id, volume).await;
log::debug!("<{guild_id}> Setting the volume to {}", volume);
- edit_response(
- &ctx,
- &command,
- format!("Setting the volume to {}", volume),
- )
- .await;
+ edit_response(&ctx, &command, format!("Setting the volume to {}", volume)).await;
}
pub async fn set_volume(manager: &Arc, guild_id: &GuildId, volume: i32) {
diff --git a/src/bot/handler.rs b/src/bot/handler.rs
index dd9a293..b22ef5e 100644
--- a/src/bot/handler.rs
+++ b/src/bot/handler.rs
@@ -1,4 +1,3 @@
-use log::{warn, info, error};
use serenity::all::Interaction;
use serenity::async_trait;
use serenity::model::gateway::Ready;
@@ -36,7 +35,7 @@ impl EventHandler for Handler {
commands::chat::generate_response(&ctx, &msg, oai).await;
}
}
- Err(why) => warn!("Could not check mentions: {:?}", why),
+ Err(why) => log::warn!("Could not check mentions: {:?}", why),
};
}
None => {}
@@ -71,8 +70,9 @@ impl EventHandler for Handler {
async fn ready(&self, ctx: Context, ready: Ready) {
if ready.guilds.is_empty() {
- warn!("No ready guilds found");
+ log::warn!("No ready guilds found");
}
+ log::trace!("Handling {} guilds", ready.guilds.len());
for guild in ready.guilds {
// Check if guild exists in database
let guild_id = guild.id.get() as i64;
@@ -103,12 +103,12 @@ impl EventHandler for Handler {
)
.await;
match commands {
- Ok(c) => info!(
+ Ok(c) => log::info!(
"Registered {} commands for guild {}",
c.len(),
guild.id.get()
),
- Err(why) => error!(
+ Err(why) => log::error!(
"Could not register commands for guild {}: {:?}",
guild.id.get(),
why