diff --git a/Cargo.toml b/Cargo.toml index eb12b65..950486a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "siren" version = "0.2.8" edition = "2021" -authors = ["Ben Sherriff "] +authors = ["Ben Sherriff "] description = "A Discord bot for playing music" repository = "https://github.com/bensherriff/siren" readme = "README.md" diff --git a/docker-compose.yml b/docker-compose.yml index 23842f7..317fbd0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,23 +52,10 @@ services: - backend restart: unless-stopped - redis: - image: redis:latest - container_name: siren-redis - volumes: - - redis:/data - ports: - - ${REDIS_PORT:-6379}:6379 - networks: - - backend - profiles: - - backend - restart: unless-stopped volumes: postgres: postgres_logs: - redis: networks: frontend: diff --git a/generate_keys.sh b/generate_keys.sh deleted file mode 100755 index 7653c32..0000000 --- a/generate_keys.sh +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/bash - -DIR="./keys" - -if [ "$#" -eq 1 ]; then - DIR=$1 -fi - -# Create the keys directory (if it doesn't exist) -echo "Generating public/private keys in: $DIR" -mkdir -p "$DIR" - -# Remove any existing keys -rm -f $DIR/*_private_key.pem -rm -f $DIR/*_public_key.pem - -# Generate Keys -openssl genrsa -out $DIR/access_private_key.pem 4096 -openssl rsa -in $DIR/access_private_key.pem -pubout -outform PEM -out $DIR/access_public_key.pem -chmod 600 $DIR/access_private_key.pem -chmod 644 $DIR/access_public_key.pem - -openssl genrsa -out $DIR/refresh_private_key.pem 4096 -openssl rsa -in $DIR/refresh_private_key.pem -pubout -outform PEM -out $DIR/refresh_public_key.pem -chmod 600 $DIR/refresh_private_key.pem -chmod 644 $DIR/refresh_public_key.pem diff --git a/src/bot/commands/audio/pause.rs b/src/bot/commands/audio/pause.rs index 22cd9ec..17b64ab 100644 --- a/src/bot/commands/audio/pause.rs +++ b/src/bot/commands/audio/pause.rs @@ -31,7 +31,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { let handler = handler_lock.lock().await; match handler.queue().pause() { Ok(_) => { - log::debug!("Paused the track"); + log::debug!("<{guild_id}> Paused the track"); edit_response(&ctx, &command, format!("Pausing the track")).await; } Err(err) => { diff --git a/src/bot/commands/audio/play.rs b/src/bot/commands/audio/play.rs index f97895a..89ff571 100644 --- a/src/bot/commands/audio/play.rs +++ b/src/bot/commands/audio/play.rs @@ -3,19 +3,17 @@ use std::sync::Arc; use serenity::all::{CommandInteraction, CommandOptionType, CreateCommand, CreateCommandOption}; use serenity::model::prelude::GuildId; use serenity::{prelude::*, async_trait}; -use songbird::input::{AuxMetadata, Input, YoutubeDl}; +use songbird::input::{Input, YoutubeDl}; use songbird::tracks::TrackHandle; -use songbird::{Call, Event, EventHandler, Songbird, TrackEvent}; +use songbird::{Event, EventHandler, Songbird, TrackEvent}; -use crate::database::guilds::GuildCache; +use crate::bot::commands::audio::leave_voice_channel; +use crate::data::guilds::GuildCache; use crate::bot::ytdlp::{PlaylistItem, YtDlp}; use crate::error::{SirenResult, Error as SirenError}; use crate::HttpKey; -use super::{ - create_response, edit_response, get_songbird, is_valid_url, join_voice_channel, - leave_voice_channel, -}; +use super::{create_response, edit_response, get_songbird, is_valid_url, join_voice_channel}; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Process the command options @@ -87,10 +85,7 @@ pub async fn play_track( ) -> SirenResult { let mut track_count = 0; if let Some(handler_lock) = manager.get(guild_id) { - let is_queue_empty = { - let call_handler = handler_lock.lock().await; - call_handler.queue().is_empty() - }; + let mut handler = handler_lock.lock().await; let guild = GuildCache::get_by_id(guild_id.get() as i64).await?.unwrap(); let valid = is_valid_url(&track_url); // Check if the URL is valid @@ -123,71 +118,49 @@ pub async fn play_track( } // Add each track to the queue for item in playlist_items { - match add_song( - ctx, - handler_lock.clone(), - &item.url, - is_queue_empty, - guild.volume as f32 / 100.0, - ) - .await - { - Ok(metadata) => { - let track_title = metadata.title.unwrap(); - log::debug!("Added track: {}", track_title); - let mut handler = handler_lock.lock().await; - // handler.remove_all_global_events(); - handler.add_global_event( - Event::Track(TrackEvent::End), - TrackEndNotifier { - guild_id, - call: manager.clone(), - }, - ); - track_count += 1; - } + let volume = guild.volume as f32 / 100.0; + let http_client = { + let data = ctx.data.read().await; + data + .get::() + .cloned() + .expect("Guaranteed to exist in the typemap.") + }; + let source = YoutubeDl::new(http_client, item.url.to_owned()); + let mut input: Input = source.into(); + let metadata = match input.aux_metadata().await { + Ok(metadata) => metadata, Err(err) => { - log::warn!("Failed to add song: {}", err); - if let Err(why) = leave_voice_channel(&manager, &guild_id).await { - log::error!("Failed to leave voice channel: {}", why); - } + log::warn!("Failed to get metadata for track: {err}"); + let _ = leave_voice_channel(&manager, &guild_id).await; return Err(SirenError::new(422, err.to_string())); } + }; + let track_handle: TrackHandle; + let is_queue_empty = handler.queue().is_empty(); + if is_queue_empty { + track_handle = handler.play_input(input); + } else { + track_handle = handler.enqueue_input(input).await; } + // Set the volume + let _ = track_handle.set_volume(volume); + let track_title = metadata.title.unwrap(); + log::debug!("<{guild_id}> Added track: {}", track_title); + handler.remove_all_global_events(); + handler.add_global_event( + Event::Track(TrackEvent::End), + TrackEndNotifier { + guild_id, + call: manager.clone(), + }, + ); + track_count += 1; } } Ok(track_count) } -async fn add_song( - ctx: &Context, - call: Arc>, - url: &str, - lazy: bool, - volume: f32, -) -> SirenResult { - let http_client = { - let data = ctx.data.read().await; - data - .get::() - .cloned() - .expect("Guaranteed to exist in the typemap.") - }; - let source = YoutubeDl::new(http_client, url.to_owned()); - let mut handler = call.lock().await; - let mut input: Input = source.into(); - let metadata = input.aux_metadata().await.unwrap(); - let track_handle: TrackHandle; - if lazy { - track_handle = handler.play_input(input); - } else { - track_handle = handler.enqueue_input(input).await; - } - // Set the volume - let _ = track_handle.set_volume(volume); - Ok(metadata) -} - pub fn get_playlist_urls(url: &str) -> SirenResult> { let output = YtDlp::new() .arg("--flat-playlist") diff --git a/src/bot/commands/audio/resume.rs b/src/bot/commands/audio/resume.rs index 3391dab..de9982a 100644 --- a/src/bot/commands/audio/resume.rs +++ b/src/bot/commands/audio/resume.rs @@ -31,7 +31,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { let handler = handler_lock.lock().await; match handler.queue().resume() { Ok(_) => { - log::debug!("Resumed the track"); + log::debug!("<{guild_id}> Resumed the track"); edit_response(&ctx, &command, format!("Resuming the track")).await; } Err(err) => { diff --git a/src/bot/commands/audio/skip.rs b/src/bot/commands/audio/skip.rs index c5bd8fc..4a07f7e 100644 --- a/src/bot/commands/audio/skip.rs +++ b/src/bot/commands/audio/skip.rs @@ -31,7 +31,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { let handler = handler_lock.lock().await; match handler.queue().skip() { Ok(_) => { - log::debug!("Skipped the track"); + log::debug!("<{guild_id}> Skipped the track"); edit_response(&ctx, &command, format!("Skipping the track")).await; } Err(err) => { diff --git a/src/bot/commands/audio/stop.rs b/src/bot/commands/audio/stop.rs index a28e77c..b50c610 100644 --- a/src/bot/commands/audio/stop.rs +++ b/src/bot/commands/audio/stop.rs @@ -30,7 +30,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { if let Some(handler_lock) = manager.get(guild_id) { let handler = handler_lock.lock().await; handler.queue().stop(); - log::debug!("Stopped the track"); + log::debug!("<{guild_id}> Stopped the track"); edit_response(&ctx, &command, format!("Stopping the tracks")).await; } } diff --git a/src/bot/commands/audio/volume.rs b/src/bot/commands/audio/volume.rs index 266234d..184cd3d 100644 --- a/src/bot/commands/audio/volume.rs +++ b/src/bot/commands/audio/volume.rs @@ -7,7 +7,7 @@ use serenity::{ }; use songbird::Songbird; -use crate::database::guilds::GuildCache; +use crate::data::guilds::GuildCache; use super::{get_songbird, create_response, edit_response}; @@ -47,7 +47,12 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { // Set the volume set_volume(&manager, guild_id, volume).await; - edit_response(&ctx, &command, format!("Setting the volume to {}", volume)).await; + edit_response( + &ctx, + &command, + format!("<{guild_id}> Setting the volume to {}", volume), + ) + .await; } pub async fn set_volume(manager: &Arc, guild_id: &GuildId, volume: i32) { diff --git a/src/bot/commands/chat.rs b/src/bot/commands/chat.rs index 9d02cfc..3a3a3d7 100644 --- a/src/bot/commands/chat.rs +++ b/src/bot/commands/chat.rs @@ -4,7 +4,7 @@ use serenity::model::channel::Message; use serenity::model::prelude::{ChannelType, PermissionOverwrite, PermissionOverwriteType}; use serenity::prelude::*; -use crate::database::messages::MessageCache; +use crate::data::messages::MessageCache; use crate::bot::oai::{ChatCompletionMessage, ChatCompletionRequest, GPTRole, OAI}; pub async fn generate_response(ctx: &Context, msg: &Message, oai: &OAI) { diff --git a/src/bot/commands/event/schedule.rs b/src/bot/commands/event/schedule.rs index cda67e4..d168011 100644 --- a/src/bot/commands/event/schedule.rs +++ b/src/bot/commands/event/schedule.rs @@ -2,10 +2,10 @@ use chrono::{DateTime, NaiveDate, TimeZone, Utc}; use regex::Regex; use serenity::all::{ Color, CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption, - CreateEmbed, CreateEmbedFooter, CreateScheduledEvent, EditInteractionResponse, Timestamp, + CreateEmbed, CreateEmbedFooter, EditInteractionResponse, Timestamp, }; -use crate::{bot::commands::audio::create_response, database::events::Event}; +use crate::{bot::commands::audio::create_response, data::events::Event}; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response diff --git a/src/bot/handler.rs b/src/bot/handler.rs index 9c83027..c93abc6 100644 --- a/src/bot/handler.rs +++ b/src/bot/handler.rs @@ -5,7 +5,7 @@ use serenity::model::gateway::Ready; use serenity::model::channel::Message; use serenity::prelude::*; -use crate::database::guilds::GuildCache; +use crate::data::guilds::GuildCache; use super::{commands, oai}; use super::commands::audio::create_response; diff --git a/src/dnd/backgrounds/mod.rs b/src/data/dnd/backgrounds/mod.rs similarity index 100% rename from src/dnd/backgrounds/mod.rs rename to src/data/dnd/backgrounds/mod.rs diff --git a/src/dnd/bestiary/mod.rs b/src/data/dnd/bestiary/mod.rs similarity index 100% rename from src/dnd/bestiary/mod.rs rename to src/data/dnd/bestiary/mod.rs diff --git a/src/dnd/campaigns/mod.rs b/src/data/dnd/campaigns/mod.rs similarity index 100% rename from src/dnd/campaigns/mod.rs rename to src/data/dnd/campaigns/mod.rs diff --git a/src/dnd/characters/mod.rs b/src/data/dnd/characters/mod.rs similarity index 100% rename from src/dnd/characters/mod.rs rename to src/data/dnd/characters/mod.rs diff --git a/src/database/events/mod.rs b/src/data/dnd/classes/mod.rs similarity index 100% rename from src/database/events/mod.rs rename to src/data/dnd/classes/mod.rs diff --git a/src/dnd/classes/model.rs b/src/data/dnd/classes/model.rs similarity index 100% rename from src/dnd/classes/model.rs rename to src/data/dnd/classes/model.rs diff --git a/src/dnd/conditions/mod.rs b/src/data/dnd/conditions/mod.rs similarity index 100% rename from src/dnd/conditions/mod.rs rename to src/data/dnd/conditions/mod.rs diff --git a/src/dnd/feats/mod.rs b/src/data/dnd/feats/mod.rs similarity index 100% rename from src/dnd/feats/mod.rs rename to src/data/dnd/feats/mod.rs diff --git a/src/dnd/items/mod.rs b/src/data/dnd/items/mod.rs similarity index 100% rename from src/dnd/items/mod.rs rename to src/data/dnd/items/mod.rs diff --git a/src/dnd/mod.rs b/src/data/dnd/mod.rs similarity index 100% rename from src/dnd/mod.rs rename to src/data/dnd/mod.rs diff --git a/src/dnd/options/mod.rs b/src/data/dnd/options/mod.rs similarity index 100% rename from src/dnd/options/mod.rs rename to src/data/dnd/options/mod.rs diff --git a/src/dnd/races/mod.rs b/src/data/dnd/races/mod.rs similarity index 100% rename from src/dnd/races/mod.rs rename to src/data/dnd/races/mod.rs diff --git a/src/dnd/spells/mod.rs b/src/data/dnd/spells/mod.rs similarity index 100% rename from src/dnd/spells/mod.rs rename to src/data/dnd/spells/mod.rs diff --git a/src/dnd/spells/model.rs b/src/data/dnd/spells/model.rs similarity index 100% rename from src/dnd/spells/model.rs rename to src/data/dnd/spells/model.rs diff --git a/src/dnd/spells/types.rs b/src/data/dnd/spells/types.rs similarity index 100% rename from src/dnd/spells/types.rs rename to src/data/dnd/spells/types.rs diff --git a/src/database/guilds/mod.rs b/src/data/events/mod.rs similarity index 100% rename from src/database/guilds/mod.rs rename to src/data/events/mod.rs diff --git a/src/database/events/model.rs b/src/data/events/model.rs similarity index 93% rename from src/database/events/model.rs rename to src/data/events/model.rs index 00002ef..db5bbdb 100644 --- a/src/database/events/model.rs +++ b/src/data/events/model.rs @@ -19,7 +19,7 @@ pub struct Event { impl Event { pub async fn insert(&self) -> SirenResult<()> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); sqlx::query(&format!( "INSERT INTO {} ( id, @@ -47,7 +47,7 @@ impl Event { } pub async fn get_by_id(id: i64) -> SirenResult> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); let item = sqlx::query_as::<_, Self>(&format!("SELECT * FROM {} WHERE id = $1", TABLE_NAME)) .bind(id) .fetch_optional(pool) diff --git a/src/database/messages/mod.rs b/src/data/guilds/mod.rs similarity index 100% rename from src/database/messages/mod.rs rename to src/data/guilds/mod.rs diff --git a/src/database/guilds/model.rs b/src/data/guilds/model.rs similarity index 90% rename from src/database/guilds/model.rs rename to src/data/guilds/model.rs index 30fb111..8d7f06e 100644 --- a/src/database/guilds/model.rs +++ b/src/data/guilds/model.rs @@ -12,7 +12,7 @@ pub struct GuildCache { impl GuildCache { pub async fn insert(&self) -> SirenResult<()> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); sqlx::query(&format!( "INSERT INTO {} ( id, @@ -32,7 +32,7 @@ impl GuildCache { } pub async fn get_by_id(id: i64) -> SirenResult> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); let item = sqlx::query_as::<_, Self>(&format!("SELECT * FROM {} WHERE id = $1", TABLE_NAME)) .bind(id) .fetch_optional(pool) @@ -42,7 +42,7 @@ impl GuildCache { } pub async fn update(&self) -> SirenResult<()> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); sqlx::query(&format!( "UPDATE {} SET bot_id = $2, diff --git a/src/dnd/classes/mod.rs b/src/data/messages/mod.rs similarity index 100% rename from src/dnd/classes/mod.rs rename to src/data/messages/mod.rs diff --git a/src/database/messages/model.rs b/src/data/messages/model.rs similarity index 92% rename from src/database/messages/model.rs rename to src/data/messages/model.rs index 99e148f..7d42428 100644 --- a/src/database/messages/model.rs +++ b/src/data/messages/model.rs @@ -19,7 +19,7 @@ pub struct MessageCache { impl MessageCache { pub async fn insert(&self) -> SirenResult<()> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); sqlx::query(&format!( "INSERT INTO {} ( id, @@ -58,9 +58,9 @@ impl MessageCache { author_id: i64, limit: i64, ) -> SirenResult> { - let pool = crate::database::pool(); + let pool = crate::data::pool(); let messages = sqlx::query_as::<_, MessageCache>(&format!( - "SELECT * FROM {} WHERE guild_id = $1 AND channel_id = $2 AND author_id = $3 ORDER BY created DESC LIMIT $4", + "SELECT * FROM {} WHERE guild_id = $1 AND channel_id = $2 AND author_id = $3 ORDER BY created ASC LIMIT $4", TABLE_NAME )) .bind(guild_id) diff --git a/src/database/mod.rs b/src/data/mod.rs similarity index 100% rename from src/database/mod.rs rename to src/data/mod.rs diff --git a/src/main.rs b/src/main.rs index 51f0d68..673892b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ use reqwest::Client as HttpClient; use crate::bot::handler::Handler; mod bot; -mod database; +mod data; mod dnd; mod error; @@ -23,7 +23,7 @@ impl TypeMapKey for HttpKey { async fn main() { dotenv::dotenv().ok(); env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", "warn,siren=info")); - if let Err(err) = database::initialize().await { + if let Err(err) = data::initialize().await { log::error!("Failed to initialize database: {err}"); return; };