diff --git a/src/bot/commands/music/join.rs b/src/bot/commands/music/join.rs index 5605c4a..55ddfbb 100644 --- a/src/bot/commands/music/join.rs +++ b/src/bot/commands/music/join.rs @@ -242,6 +242,18 @@ pub fn run(ctx: Context, command: ApplicationCommandInteraction) -> CommandOutpu ) .await; + return; + } else if let SessionCreateError::NoLongerSpotifyError = 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; } @@ -284,6 +296,18 @@ pub fn run(ctx: Context, command: ApplicationCommandInteraction) -> CommandOutpu ) .await; + return; + } else if let SessionCreateError::NoLongerSpotifyError = 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; } diff --git a/src/session/manager.rs b/src/session/manager.rs index 41ce67e..fa4c265 100644 --- a/src/session/manager.rs +++ b/src/session/manager.rs @@ -16,6 +16,9 @@ pub enum SessionCreateError { #[error("The user has not linked their Spotify account")] NoSpotifyError, + #[error("The application no longer has access to the user's Spotify account")] + NoLongerSpotifyError, + #[error("An error has occured while communicating with the database")] DatabaseError, @@ -66,11 +69,10 @@ impl InnerSessionManager { } /// Remove a session - pub async fn remove_session(&mut self, guild_id: GuildId) { - if let Some(session) = self.sessions.get(&guild_id) { - if let Some(owner) = session.owner().await { - self.owner_map.remove(&owner); - } + pub async fn remove_session(&mut self, guild_id: GuildId, owner: Option) { + // Remove the owner from the owner map (if it exists) + if let Some(owner) = owner { + self.owner_map.remove(&owner); } self.sessions.remove(&guild_id); @@ -146,8 +148,8 @@ impl SessionManager { } /// Remove a session - pub async fn remove_session(&self, guild_id: GuildId) { - self.0.write().await.remove_session(guild_id).await; + pub async fn remove_session(&self, guild_id: GuildId, owner: Option) { + self.0.write().await.remove_session(guild_id, owner).await; } /// Remove owner from owner map. diff --git a/src/session/mod.rs b/src/session/mod.rs index 119f07a..e03c2b4 100644 --- a/src/session/mod.rs +++ b/src/session/mod.rs @@ -54,6 +54,10 @@ struct InnerSpoticordSession { disconnect_handle: Option>, client: Option, + + /// Whether the session has been disconnected + /// If this is true then this instance should no longer be used and dropped + disconnected: bool, } impl SpoticordSession { @@ -90,6 +94,7 @@ impl SpoticordSession { playback_info: None, disconnect_handle: None, client: None, + disconnected: false, }; let mut instance = Self(Arc::new(RwLock::new(inner))); @@ -153,6 +158,8 @@ impl SpoticordSession { if let DatabaseError::InvalidStatusCode(code) = why { if code == 404 { return Err(SessionCreateError::NoSpotifyError); + } else if code == 400 { + return Err(SessionCreateError::NoLongerSpotifyError); } } @@ -276,6 +283,7 @@ impl SpoticordSession { message.embed(|embed| { embed.title("Failed to connect to Spotify"); embed.description(why); + embed.footer(|footer| footer.text("Please try again")); embed.color(Status::Error as u64); embed @@ -288,9 +296,6 @@ impl SpoticordSession { error!("Failed to send error message: {:?}", why); } - // Clean up session - instance.player_stopped().await; - break; } @@ -380,6 +385,11 @@ impl SpoticordSession { _ => {} } } + + // Clean up session + if !inner.read().await.disconnected { + instance.player_stopped().await; + } } }); @@ -513,7 +523,7 @@ impl SpoticordSession { // read lock to read the current owner. // This would deadlock if we have an active write lock { - let inner = self.0.read().await; + let mut inner = self.0.write().await; inner.disconnect_no_abort().await; } @@ -597,7 +607,7 @@ impl SpoticordSession { pub async fn disconnect_with_message(&self, content: &str) { { - let inner = self.0.read().await; + let mut inner = self.0.write().await; // Firstly we disconnect inner.disconnect_no_abort().await; @@ -672,8 +682,12 @@ impl SpoticordSession { impl InnerSpoticordSession { /// Internal version of disconnect, which does not abort the disconnect timer - async fn disconnect_no_abort(&self) { - self.session_manager.remove_session(self.guild_id).await; + async fn disconnect_no_abort(&mut self) { + self.disconnected = true; + self + .session_manager + .remove_session(self.guild_id, self.owner) + .await; let mut call = self.call.lock().await;