diff --git a/src/commands/audio/pause.rs b/src/commands/audio/pause.rs index e69de29..4423f67 100644 --- a/src/commands/audio/pause.rs +++ b/src/commands/audio/pause.rs @@ -0,0 +1,43 @@ +use log::{debug, error}; + +use serenity::prelude::*; +use serenity::builder::CreateApplicationCommand; +use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; + +use super::{get_songbird, create_response, edit_response}; + +pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { + // Create the initial response + if let Err(why) = create_response(&ctx, &command, "Processing command...".to_string()).await { + error!("Failed to create response message: {}", why); + return; + } + + let guild_id = match command.guild_id { + Some(g) => g, + None => { + if let Err(why) = edit_response(&ctx, &command, "Unable to join voice channel".to_string()).await { + error!("Failed to edit response message: {}", why); + } + return; + } + }; + let manager = get_songbird(ctx).await; + if let Some(handler_lock) = manager.get(guild_id) { + let handler = handler_lock.lock().await; + if let Err(err) = handler.queue().pause() { + if let Err(why) = edit_response(&ctx, &command, format!("Failed to pause: {}", err)).await { + error!("Failed to edit response message: {}", why); + } + } else { + debug!("Paused the track"); + if let Err(why) = edit_response(&ctx, &command, format!("Pausing the track")).await { + error!("Failed to edit response message: {}", why); + } + } + } +} + +pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command.name("pause").description("Pause the current track") +} \ No newline at end of file diff --git a/src/commands/audio/play.rs b/src/commands/audio/play.rs index 0bef488..e98da00 100644 --- a/src/commands/audio/play.rs +++ b/src/commands/audio/play.rs @@ -74,7 +74,7 @@ pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { } let mut handler = handler_lock.lock().await; handler.remove_all_global_events(); - handler.add_global_event(songbird::Event::Track(songbird::TrackEvent::End), InactiveHandler { guild_id, call: manager }) + handler.add_global_event(songbird::Event::Track(songbird::TrackEvent::End), TrackEndNotifier { guild_id, call: manager }) } Err(why) => { warn!("Failed to add song: {}", why); @@ -107,19 +107,19 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio }) } -struct InactiveHandler { +struct TrackEndNotifier { pub call: std::sync::Arc, pub guild_id: serenity::model::id::GuildId } #[async_trait] -impl EventHandler for InactiveHandler { +impl EventHandler for TrackEndNotifier { async fn act(&self, ctx: &songbird::events::EventContext<'_>) -> Option { - if let songbird::EventContext::Track(track_list) = ctx { - if track_list.is_empty() { - if let Some(call) = self.call.get(self.guild_id) { - debug!("Track list is empty; leaving voice channel"); - let mut handler = call.lock().await; + if let songbird::EventContext::Track(_track_list) = ctx { + if let Some(call) = self.call.get(self.guild_id) { + let mut handler = call.lock().await; + if handler.queue().is_empty() { + debug!("Queue is empty, leaving voice channel"); handler.leave().await.unwrap(); } } diff --git a/src/commands/audio/resume.rs b/src/commands/audio/resume.rs index e69de29..d97a592 100644 --- a/src/commands/audio/resume.rs +++ b/src/commands/audio/resume.rs @@ -0,0 +1,43 @@ +use log::{debug, error}; + +use serenity::prelude::*; +use serenity::builder::CreateApplicationCommand; +use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; + +use super::{get_songbird, create_response, edit_response}; + +pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { + // Create the initial response + if let Err(why) = create_response(&ctx, &command, "Processing command...".to_string()).await { + error!("Failed to create response message: {}", why); + return; + } + + let guild_id = match command.guild_id { + Some(g) => g, + None => { + if let Err(why) = edit_response(&ctx, &command, "Unable to join voice channel".to_string()).await { + error!("Failed to edit response message: {}", why); + } + return; + } + }; + let manager = get_songbird(ctx).await; + if let Some(handler_lock) = manager.get(guild_id) { + let handler = handler_lock.lock().await; + if let Err(err) = handler.queue().resume() { + if let Err(why) = edit_response(&ctx, &command, format!("Failed to resume: {}", err)).await { + error!("Failed to edit response message: {}", why); + } + } else { + debug!("Resumed the track"); + if let Err(why) = edit_response(&ctx, &command, format!("Resuming the track")).await { + error!("Failed to edit response message: {}", why); + } + } + } +} + +pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command.name("resume").description("Resume the current track") +} \ No newline at end of file diff --git a/src/commands/audio/skip.rs b/src/commands/audio/skip.rs index e69de29..cd95d91 100644 --- a/src/commands/audio/skip.rs +++ b/src/commands/audio/skip.rs @@ -0,0 +1,43 @@ +use log::{debug, error}; + +use serenity::prelude::*; +use serenity::builder::CreateApplicationCommand; +use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; + +use super::{get_songbird, create_response, edit_response}; + +pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { + // Create the initial response + if let Err(why) = create_response(&ctx, &command, "Processing command...".to_string()).await { + error!("Failed to create response message: {}", why); + return; + } + + let guild_id = match command.guild_id { + Some(g) => g, + None => { + if let Err(why) = edit_response(&ctx, &command, "Unable to join voice channel".to_string()).await { + error!("Failed to edit response message: {}", why); + } + return; + } + }; + let manager = get_songbird(ctx).await; + if let Some(handler_lock) = manager.get(guild_id) { + let handler = handler_lock.lock().await; + if let Err(err) = handler.queue().skip() { + if let Err(why) = edit_response(&ctx, &command, format!("Failed to skip: {}", err)).await { + error!("Failed to edit response message: {}", why); + } + } else { + debug!("Skipped the track"); + if let Err(why) = edit_response(&ctx, &command, format!("Skipping the track")).await { + error!("Failed to edit response message: {}", why); + } + } + } +} + +pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command.name("skip").description("Skip the current track") +} \ No newline at end of file diff --git a/src/commands/audio/stop.rs b/src/commands/audio/stop.rs index e69de29..32dec6f 100644 --- a/src/commands/audio/stop.rs +++ b/src/commands/audio/stop.rs @@ -0,0 +1,38 @@ +use log::{debug, error}; + +use serenity::prelude::*; +use serenity::builder::CreateApplicationCommand; +use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; + +use super::{get_songbird, create_response, edit_response}; + +pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { + // Create the initial response + if let Err(why) = create_response(&ctx, &command, "Processing command...".to_string()).await { + error!("Failed to create response message: {}", why); + return; + } + + let guild_id = match command.guild_id { + Some(g) => g, + None => { + if let Err(why) = edit_response(&ctx, &command, "Unable to join voice channel".to_string()).await { + error!("Failed to edit response message: {}", why); + } + return; + } + }; + let manager = get_songbird(ctx).await; + if let Some(handler_lock) = manager.get(guild_id) { + let handler = handler_lock.lock().await; + handler.queue().stop(); + debug!("Stopped the track"); + if let Err(why) = edit_response(&ctx, &command, format!("Stopping the tracks")).await { + error!("Failed to edit response message: {}", why); + } + } +} + +pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command.name("stop").description("Stop the current track and clear the queue") +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index afec996..e4b814f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,10 @@ impl EventHandler for Handler { if let Interaction::ApplicationCommand(command) = interaction { match command.data.name.as_str() { "play" => commands::audio::play::run(&ctx, &command).await, + "stop" => commands::audio::stop::run(&ctx, &command).await, + "pause" => commands::audio::pause::run(&ctx, &command).await, + "resume" => commands::audio::resume::run(&ctx, &command).await, + "skip" => commands::audio::skip::run(&ctx, &command).await, _ => { let content: String = match command.data.name.as_str() { "ping" => commands::ping::run(&command.data.options), @@ -43,6 +47,10 @@ impl EventHandler for Handler { let commands = guild.id.set_application_commands(&ctx.http, |commands| { commands.create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::ping::register(command) }) .create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::audio::play::register(command) }) + .create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::audio::stop::register(command) }) + .create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::audio::pause::register(command) }) + .create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::audio::resume::register(command) }) + .create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::audio::skip::register(command) }) }).await; match commands { Ok(c) => info!("Registered {} commands for guild {}", c.len(), guild.id.0),