diff options
Diffstat (limited to 'src/commands/playback.rs')
| -rw-r--r-- | src/commands/playback.rs | 215 |
1 files changed, 55 insertions, 160 deletions
diff --git a/src/commands/playback.rs b/src/commands/playback.rs index 21393a2..7ecef47 100644 --- a/src/commands/playback.rs +++ b/src/commands/playback.rs @@ -1,7 +1,3 @@ -use either::{ - Left, - Right, -}; use log::{ debug, error, @@ -18,32 +14,43 @@ use serenity::{ CommandError, CommandResult, }, - futures::TryFutureExt, model::channel::Message, prelude::*, }; -use tap::{ - Conv, - Pipe, +use songbird::{ + input::YoutubeDl, + Call, + Songbird, }; +use std::sync::Arc; +use tap::Conv; use crate::{ - audio::{ - parse_times, - PlayArgs, - PlayQueue, - VoiceManager, - }, + bot::HttpKey, commands::sound_levels::*, util, CONFIG, }; #[group] -#[commands(skip, pause, resume, list, die, mute, unmute, play, volume)] +#[commands(skip, pause, resume, list, die, mute, unmute, play)] #[only_in(guild)] struct Playback; +pub async fn songbird( + ctx: &Context, + msg: &Message, +) -> Result<(Arc<Songbird>, Arc<Mutex<Call>>), CommandError> { + let Some(gid) = msg.guild_id else { + return Err(anyhow::anyhow!("no guild id").into()); + }; + + let sb = songbird::get(ctx).await.expect("acquiring songbird handle"); + let call = sb.get_or_insert(gid); + + Ok((sb, call)) +} + pub async fn _play(ctx: &Context, msg: &Message, url: &str) -> CommandResult { use url::{ Host, @@ -83,18 +90,20 @@ pub async fn _play(ctx: &Context, msg: &Message, url: &str) -> CommandResult { return Ok(()); } - let (start, end) = parse_times(&msg.content); + let (_sb, call) = songbird(ctx, msg).await?; + let mut call = call.lock().await; - let queue_lock = ctx.data.write().await.get::<PlayQueue>().cloned().unwrap(); - let mut play_queue = queue_lock.write().unwrap(); + if call.current_channel().is_none() { + call.join(CONFIG.discord.voice_channel()).await?; + } - play_queue.general_queue.push_back(PlayArgs { - initiator: msg.author.name.clone(), - data: Left(url.conv::<String>()), - sender_channel: msg.channel_id, - start, - end, - }); + let client = { + let data = ctx.data.read().await; + data.get::<HttpKey>().unwrap().clone() + }; + + let input = YoutubeDl::new_ytdl_like("yt-dlp", client.clone(), url.conv::<String>()); + call.enqueue_input(input.into()).await; Ok(()) } @@ -115,37 +124,15 @@ pub async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult }, }; - _play(ctx, msg, &url) + _play(ctx, msg, &url).await } #[command] pub async fn pause(ctx: &Context, msg: &Message, _: Args) -> CommandResult { - let queue_lock = ctx.data.write().await.get::<PlayQueue>().cloned().unwrap(); + let (_sb, call) = songbird(ctx, msg).await?; - let done = || util::send(ctx, msg.channel_id, "r u srs", msg.tts).map_err(CommandError::from); - let playing = { - let play_queue = queue_lock.read().unwrap(); - - let current_item = match play_queue.playing { - Some(ref x) => x, - None => return done().await, - }; - - let audio = current_item.audio.lock(); - audio.playing - }; - - if !playing { - return done().await; - } - - { - let queue = queue_lock.write().unwrap(); - let ref audio = queue.playing.clone().unwrap().audio; - audio.lock().pause(); - - info!("paused playback"); - } + let call = call.lock().await; + call.queue().pause()?; Ok(()) } @@ -157,58 +144,21 @@ pub async fn resume(ctx: &Context, msg: &Message, _: Args) -> CommandResult { } async fn _resume(ctx: &Context, msg: &Message) -> CommandResult { - let queue_lock = ctx.data.write().await.get::<PlayQueue>().cloned().unwrap(); + let (_sb, call) = songbird(ctx, msg).await?; - let done = || util::send(ctx, msg.channel_id, "r u srs", msg.tts).map_err(CommandError::from); - let playing = { - let play_queue = queue_lock.read().unwrap(); - - let current_item = match play_queue.playing { - Some(ref x) => x, - None => { - done().await?; - return Ok(()); - }, - }; - - let audio = current_item.audio.lock(); - audio.playing - }; - - if playing { - done().await?; - debug!("attempted to resume playback while sound was already playing"); - return Ok(()); - } - - { - let queue = queue_lock.write().unwrap(); - let ref audio = queue.playing.clone().unwrap().audio; - audio.lock().play(); - info!("playback resumed"); - } + let call = call.lock().await; + call.queue().resume()?; Ok(()) } #[command] #[aliases("next")] -pub async fn skip(ctx: &Context, _msg: &Message, _args: Args) -> CommandResult { - let data = ctx.data.write().await; - - let mgr_lock = data.get::<VoiceManager>().cloned().unwrap(); - let mut manager = mgr_lock.lock(); +pub async fn skip(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { + let (_sb, call) = songbird(ctx, msg).await?; - let queue_lock = data.get::<PlayQueue>().cloned().unwrap(); - - if let Some(handler) = manager.get_mut(CONFIG.discord.guild()) { - handler.stop(); - let mut play_queue = queue_lock.write().unwrap(); - play_queue.playing = None; - info!("skipped currently-playing audio"); - } else { - debug!("got skip with no handler attached"); - } + let call = call.lock().await; + call.queue().skip()?; Ok(()) } @@ -216,29 +166,10 @@ pub async fn skip(ctx: &Context, _msg: &Message, _args: Args) -> CommandResult { #[command] #[aliases("sudoku", "fuckoff", "stop")] pub async fn die(ctx: &Context, msg: &Message, _: Args) -> CommandResult { - let data = ctx.data.write().await; - - let mgr_lock = data.get::<VoiceManager>().cloned().unwrap(); - let mut manager = mgr_lock.lock(); + let (_sb, call) = songbird(ctx, msg).await?; - let queue_lock = data.get::<PlayQueue>().cloned().unwrap(); - - { - let mut play_queue = queue_lock.write().unwrap(); - - play_queue.playing = None; - play_queue.general_queue.clear(); - play_queue.meme_queue.clear(); - } - - if let Some(handler) = manager.get_mut(CONFIG.discord.guild()) { - info!("killing playback"); - handler.stop(); - handler.leave(); - } else { - util::send(ctx, msg.channel_id, "YOU die", msg.tts).await?; - debug!("got die with no handler attached"); - } + let call = call.lock().await; + call.queue().stop(); Ok(()) } @@ -246,55 +177,19 @@ pub async fn die(ctx: &Context, msg: &Message, _: Args) -> CommandResult { #[command] #[aliases("queue")] pub async fn list(ctx: &Context, msg: &Message, _: Args) -> CommandResult { - let queue_lock = ctx.data.write().await.get::<PlayQueue>().cloned().unwrap(); - let play_queue = queue_lock.read().unwrap(); + let (_sb, call) = songbird(ctx, msg).await?; - let channel = msg.channel(&ctx).await.unwrap().guild().unwrap(); + let call = call.lock().await; + let queue = call.queue(); - info!("listing queue"); - match play_queue.playing { - Some(ref info) => { - let audio = info.audio.lock(); - let status = if audio.playing { - "playing" - } else { - "paused:" - }; + util::send(ctx, msg.channel_id, "(command fix work-in-progress)", msg.tts).await?; - let playing_info = match info.init_args.data { - Left(ref url) => format!(" `{}`", url), - Right(_) => "memeing".to_owned(), - }; + for track in queue.current_queue().into_iter() { + let info = track.get_info().await?; - util::send( - ctx, - msg.channel_id, - &format!("Currently {} {} ({})", status, playing_info, info.init_args.initiator), - msg.tts, - ) + util::send(ctx, msg.channel_id, format!("track playing for {:?}", info.play_time), msg.tts) .await?; - }, - None => { - debug!("`list` called with no items in queue"); - util::send(ctx, msg.channel_id, "Nothing is playing you meme", msg.tts).await?; - return Ok(()); - }, } - play_queue - .meme_queue - .iter() - .chain(play_queue.general_queue.iter()) - .pipe(serenity::futures::stream::iter) - .for_each(|info| async move { - let playing_info = match info.data { - Left(ref url) => format!("`{}`", url), - Right(_) => "meme".to_owned(), - }; - - let _ = channel.say(&ctx, &format!("{} ({})", playing_info, info.initiator)).await; - }) - .await; - Ok(()) } |
