diff --git a/src/audio/mod.rs b/src/audio/mod.rs index d0cdd40..7b82086 100644 --- a/src/audio/mod.rs +++ b/src/audio/mod.rs @@ -53,7 +53,9 @@ impl Sink for StreamSink { fn write(&mut self, packet: AudioPacket, converter: &mut Converter) -> SinkResult<()> { use zerocopy::AsBytes; - let AudioPacket::Samples(samples) = packet else { return Ok(()); }; + let AudioPacket::Samples(samples) = packet else { + return Ok(()); + }; let samples_f32: &[f32] = &converter.f64_to_f32(&samples); let resampled = samplerate::convert( @@ -65,10 +67,10 @@ impl Sink for StreamSink { ) .expect("to succeed"); - let samples_i16 = - &converter.f64_to_s16(&resampled.iter().map(|v| *v as f64).collect::>()); + // let samples_i16 = + // &converter.f64_to_s16(&resampled.iter().map(|v| *v as f64).collect::>()); - self.write_bytes(samples_i16.as_bytes())?; + self.write_bytes(resampled.as_bytes())?; Ok(()) } diff --git a/src/audio/stream.rs b/src/audio/stream.rs index 1f38215..f8d2468 100644 --- a/src/audio/stream.rs +++ b/src/audio/stream.rs @@ -38,6 +38,7 @@ impl Read for Stream { } let max_read = usize::min(buf.len(), buffer.len()); + buf[0..max_read].copy_from_slice(&buffer[0..max_read]); buffer.drain(0..max_read); condvar.notify_all(); diff --git a/src/bot/commands/music/join.rs b/src/bot/commands/music/join.rs index 2816779..fcb5fcc 100644 --- a/src/bot/commands/music/join.rs +++ b/src/bot/commands/music/join.rs @@ -231,49 +231,74 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO } } - if let Some(session) = session_opt.as_mut() { - if let Err(why) = session.update_owner(&ctx, command.user.id).await { - // Need to link first - if let SessionCreateError::NoSpotify = why { - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("You need to link your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to get started.") - .status(Status::Error) - .build(), - ) - .await; + macro_rules! report_error { + ($why:ident) => { + match $why { + // User has not linked their account + SessionCreateError::NoSpotify => { + update_message( + &ctx, + &command, + EmbedBuilder::new() + .title("Cannot join voice channel") + .description("You need to link your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to get started.") + .status(Status::Error) + .build(), + ) + .await; + } - return; - } else if let SessionCreateError::SpotifyExpired = why { - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("Spoticord no longer has access to your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to relink your Spotify account.") - .status(Status::Error) - .build(), - ).await; + // Spotify credentials have expired or are invalid + SessionCreateError::SpotifyExpired => { + update_message( + &ctx, + &command, + EmbedBuilder::new() + .title("Cannot join voice channel") + .description("Spoticord no longer has access to your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to relink your Spotify account.") + .status(Status::Error) + .build(), + ).await; + } - return; + // Songbird error + SessionCreateError::JoinError(why) => { + update_message( + &ctx, + &command, + EmbedBuilder::new() + .title("Cannot join voice channel") + .description(format!( + "An error occured while joining the channel. Please try running again.\n\nError details: `{why}`" + )) + .status(Status::Error) + .build(), + ) + .await; + } + + // Any other error + _ => { + update_message( + &ctx, + &command, + EmbedBuilder::new() + .title("Cannot join voice channel") + .description("An error occured while joining the channel. Please try again later.") + .status(Status::Error) + .build(), + ) + .await; + } } - // Any other error - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("An error occured while joining the channel. Please try again later.") - .status(Status::Error) - .build(), - ) - .await; - return; + }; + } + + if let Some(session) = session_opt.as_mut() { + if let Err(why) = session.update_owner(&ctx, command.user.id).await { + report_error!(why); } } else { // Create the session, and handle potential errors @@ -287,47 +312,7 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO ) .await { - // Need to link first - if let SessionCreateError::NoSpotify = why { - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("You need to link your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to get started.") - .status(Status::Error) - .build(), - ) - .await; - - return; - } else if let SessionCreateError::SpotifyExpired = why { - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("Spoticord no longer has access to your Spotify account. Use or go to [the accounts website](https://account.spoticord.com/) to relink your Spotify account.") - .status(Status::Error) - .build(), - ).await; - - return; - } - - // Any other error - update_message( - &ctx, - &command, - EmbedBuilder::new() - .title("Cannot join voice channel") - .description("An error occured while joining the channel. Please try again later.") - .status(Status::Error) - .build(), - ) - .await; - - return; + report_error!(why); }; } diff --git a/src/session/manager.rs b/src/session/manager.rs index 4639bc3..5d3d186 100644 --- a/src/session/manager.rs +++ b/src/session/manager.rs @@ -4,6 +4,7 @@ use serenity::{ model::prelude::{ChannelId, GuildId, UserId}, prelude::{Context, TypeMapKey}, }; +use songbird::error::JoinError; use thiserror::Error; use super::SpoticordSession; @@ -22,8 +23,8 @@ pub enum SessionCreateError { #[error("An error has occured while communicating with the database")] DatabaseError, - #[error("Failed to join voice channel {0} ({1})")] - JoinError(ChannelId, GuildId), + #[error("Failed to join voice channel")] + JoinError(JoinError), #[error("Failed to start the player")] PlayerStartError, diff --git a/src/session/mod.rs b/src/session/mod.rs index c52221b..5a00063 100644 --- a/src/session/mod.rs +++ b/src/session/mod.rs @@ -13,6 +13,7 @@ use crate::{ utils::embed::Status, }; use log::*; +use reqwest::StatusCode; use serenity::{ async_trait, http::Http, @@ -78,7 +79,7 @@ impl SpoticordSession { if let Err(why) = result { error!("Error joining voice channel: {:?}", why); - return Err(SessionCreateError::JoinError(channel_id, guild_id)); + return Err(SessionCreateError::JoinError(why)); } let inner = InnerSpoticordSession { @@ -182,15 +183,15 @@ impl SpoticordSession { let token = match database.get_access_token(owner_id.to_string()).await { Ok(token) => token, Err(why) => { - if let DatabaseError::InvalidStatusCode(code) = why { - if code == 404 { - return Err(SessionCreateError::NoSpotify); - } else if code == 400 { - return Err(SessionCreateError::SpotifyExpired); + return match why { + DatabaseError::InvalidStatusCode(StatusCode::NOT_FOUND) => { + Err(SessionCreateError::NoSpotify) } - } - - return Err(SessionCreateError::DatabaseError); + DatabaseError::InvalidStatusCode(StatusCode::BAD_REQUEST) => { + Err(SessionCreateError::SpotifyExpired) + } + _ => Err(SessionCreateError::DatabaseError), + }; } }; @@ -209,7 +210,7 @@ impl SpoticordSession { let (mut track, track_handle) = create_player(Input::new( true, Reader::Extension(Box::new(stream.clone())), - Codec::Pcm, + Codec::FloatPcm, Container::Raw, None, ));