diff --git a/Cargo.toml b/Cargo.toml index c59f5d9..86760d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,10 @@ edition = "2018" tracing = "0.1" tracing-subscriber = "0.2" tracing-futures = "0.2" -songbird = "0.2" + +[dependencies.songbird] +version = "0.2" +features = ["builtin-queue"] [dependencies.serenity] version = "0.10" diff --git a/src/commands.rs b/src/commands.rs index 35af40c..0098dc2 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -131,6 +131,109 @@ pub async fn play(ctx: &mut Context, command: &ApplicationCommandInteraction) -> } } +pub async fn queue(ctx: &mut Context, command: &ApplicationCommandInteraction) -> String { + let options = command + .data + .options + .get(0) + .expect("Expected url option") + .resolved + .as_ref() + .expect("Expected url object"); + + let url = match options { + ApplicationCommandInteractionDataOptionValue::String(url) => url, + _ => { + return "You didn't tell me what to play.".to_string(); + } + }; + + if !url.starts_with("http") { + return "That's not a real URL. I'm onto you.".to_string(); + } + + let guild_id = command.guild_id.unwrap(); + + let manager = songbird::get(ctx) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + // Try to join the caller's channel + if manager.get(guild_id).is_none() { + join(ctx, command).await; + } + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let source = match songbird::input::Restartable::ytdl(url.clone(), false).await { + Ok(source) => source, + Err(why) => { + println!("Err starting source: {:?}", why); + + return "Something went horribly wrong. Go yell at Valter.".to_string(); + } + }; + + let source_input: Input = source.into(); + + let message = { + if let Some(title) = &source_input.metadata.title { + let mut msg = MessageBuilder::new(); + msg.push_line(format!( + "Queueing this up at position {}:", + handler.queue().len() + )); + msg.push_named_link(title, url); + msg.build() + } else { + format!( + "Queueing something up at position {}, I dunno what.", + handler.queue().len() + ) + .to_string() + } + }; + + let (mut audio, track_handle) = create_player(source_input); + + let mut data = ctx.data.write().await; + + let current_track = data.get_mut::().unwrap(); + *current_track = Some(track_handle); + + let volume = data.get::().unwrap(); + + audio.set_volume(*volume); + handler.enqueue(audio); + + message + } else { + "Somehow neither of us are in a voice channel to begin with.".to_string() + } +} + +pub async fn skip(ctx: &Context, command: &ApplicationCommandInteraction) -> String { + let guild_id = command.guild_id.unwrap(); + + let manager = songbird::get(ctx) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + if let Some(handler_lock) = manager.get(guild_id) { + let handler = handler_lock.lock().await; + + let queue = handler.queue(); + let _ = queue.skip(); + + format!("Yeah, I didn't like this one very much anyway. Skip! Now we're at number {} in the queue.", queue.len()) + } else { + "I'm not even in a channel to begin with. Silly.".to_string() + } +} + pub async fn stop(ctx: &Context, command: &ApplicationCommandInteraction) -> String { let guild_id = command.guild_id.unwrap(); diff --git a/src/main.rs b/src/main.rs index 8bdd942..6b87ae1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,8 @@ impl EventHandler for Handler { "join" => commands::join(&ctx, &command).await, "leave" => commands::leave(&ctx, &command).await, "play" => commands::play(&mut ctx, &command).await, + "queue" => commands::queue(&mut ctx, &command).await, + "skip" => commands::skip(&mut ctx, &command).await, "stop" => commands::stop(&ctx, &command).await, "volume" => commands::set_volume(&mut ctx, &command).await, "loop" => commands::set_loop(&mut ctx, &command).await, @@ -89,6 +91,25 @@ impl EventHandler for Handler { }) .default_permission(false) }) + .create_application_command(|command| { + command + .name("queue") + .description("Queue up a song") + .create_option(|option| { + option + .name("url") + .description("The URL of the song to queue") + .kind(ApplicationCommandOptionType::String) + .required(true) + }) + .default_permission(false) + }) + .create_application_command(|command| { + command + .name("skip") + .description("Skip the currently playing queued song") + .default_permission(false) + }) .create_application_command(|command| { command .name("stop") @@ -111,7 +132,9 @@ impl EventHandler for Handler { .create_application_command(|command| { command .name("loop") - .description("Enable or disable looping the currently playing track") + .description( + "Enable or disable looping the currently playing track", + ) .create_option(|option| { option .name("loop")