diff options
| author | Nathan Perry <np@nathanperry.dev> | 2024-08-16 23:09:41 -0400 |
|---|---|---|
| committer | Nathan Perry <np@nathanperry.dev> | 2024-08-16 23:09:43 -0400 |
| commit | 584f0ebc6e33ddc2905d82f44e7b42faea122668 (patch) | |
| tree | e4a2bbc3d801086649c29a1de741dd49fc466b96 /src | |
| parent | e0a9b18f45858829f88cbe20611aaf696fc5bf6a (diff) | |
fill in queued playback info
Diffstat (limited to 'src')
| -rw-r--r-- | src/bot.rs | 8 | ||||
| -rw-r--r-- | src/commands/playback.rs | 58 | ||||
| -rw-r--r-- | src/commands/today/mod.rs | 21 |
3 files changed, 73 insertions, 14 deletions
@@ -69,6 +69,12 @@ impl TypeMapKey for VolumeKey { type Value = DashMap<GuildId, f64>; } +pub struct PlaybackKey; + +impl TypeMapKey for PlaybackKey { + type Value = Arc<DashMap<uuid::Uuid, songbird::input::AuxMetadata>>; +} + #[cfg(debug_assertions)] const BOTNAME: &str = "thulani (dev)"; @@ -127,6 +133,7 @@ struct SongbirdHandler(Arc<Mutex<Call>>); impl songbird::events::EventHandler for SongbirdHandler { async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> { let mut call = self.0.lock().await; + if call.queue().is_empty() { let _ = call.leave().await; } @@ -416,6 +423,7 @@ pub async fn run() -> anyhow::Result<()> { .register_songbird_from_config(sb_config) .type_map_insert::<HttpKey>(reqwest::Client::new()) .type_map_insert::<VolumeKey>(DashMap::new()) + .type_map_insert::<PlaybackKey>(Arc::new(DashMap::new())) .framework(framework().await) .await?; diff --git a/src/commands/playback.rs b/src/commands/playback.rs index 4d6d0be..e7bf830 100644 --- a/src/commands/playback.rs +++ b/src/commands/playback.rs @@ -1,4 +1,7 @@ -use std::sync::Arc; +use std::{ + fmt::Debug, + sync::Arc, +}; use grate::tracing; use serenity::prelude::*; @@ -10,7 +13,10 @@ use songbird::{ use tap::Conv; use crate::{ - bot::HttpKey, + bot::{ + HttpKey, + PlaybackKey, + }, util, PoiseContext, PoiseData, @@ -21,9 +27,7 @@ pub fn commands() -> impl IntoIterator<Item = poise::Command<PoiseData, anyhow:: } pub async fn songbird(ctx: PoiseContext<'_>) -> anyhow::Result<(Arc<Songbird>, Arc<Mutex<Call>>)> { - let Some(gid) = ctx.guild_id() else { - return Err(anyhow::anyhow!("no guild id").into()); - }; + let gid = util::guild_id(ctx)?; let sb = songbird::get(ctx.serenity_context()).await.expect("acquiring songbird handle"); let call = sb.get_or_insert(gid); @@ -196,19 +200,51 @@ pub async fn die(ctx: PoiseContext<'_>) -> anyhow::Result<()> { /// List queued audio. #[poise::command(prefix_command, guild_only, category = "playback", aliases("queue"))] pub async fn list(ctx: PoiseContext<'_>) -> anyhow::Result<()> { - let (_sb, call) = songbird(ctx).await?; + let current_queue = { + let (_sb, call) = songbird(ctx).await?; - let call = call.lock().await; - let queue = call.queue(); + let call = call.lock().await; + let queue = call.queue(); - if queue.current_queue().is_empty() { + queue.current_queue() + }; + + let playback_data = { + let data = ctx.serenity_context().data.read().await; + data.get::<PlaybackKey>().cloned().unwrap() + }; + + if current_queue.is_empty() { util::reply(ctx, "nothing queued").await?; } - for track in queue.current_queue().into_iter() { + fn fmt_option<T>(name: &str, opt: Option<T>) -> String + where + T: std::fmt::Display, + { + if let Some(opt) = opt { + format!("{opt}") + } else { + format!("<no {name}>") + } + } + + for track in current_queue.into_iter() { let info = track.get_info().await?; - let fmt = format!("track playing for {:?}", info.play_time); + let meta = playback_data.get(&track.uuid()).map(|x| x.clone()); + let meta = meta.as_ref(); + + let fmt = format!( + "{}: {:?} / {}", + fmt_option("title", meta.and_then(|x| x.title.as_ref())), + humantime::format_duration(info.position), + fmt_option( + "duration", + meta.and_then(|x| x.duration.as_ref().map(|&dur| humantime::format_duration(dur))) + ) + ); + util::reply(ctx, fmt).await?; } diff --git a/src/commands/today/mod.rs b/src/commands/today/mod.rs index f8f38c7..2c47e83 100644 --- a/src/commands/today/mod.rs +++ b/src/commands/today/mod.rs @@ -5,11 +5,17 @@ use rand::{ seq::SliceRandom, thread_rng, }; -use songbird::input::YoutubeDl; +use songbird::input::{ + Compose, + YoutubeDl, +}; use tap::Conv; use crate::{ - bot::HttpKey, + bot::{ + HttpKey, + PlaybackKey, + }, commands::playback::songbird, util, PoiseContext, @@ -117,12 +123,21 @@ pub async fn today(ctx: PoiseContext<'_>, #[rest] _rest: Option<String>) -> anyh data.get::<HttpKey>().unwrap().clone() }; - let input = + let mut input = YoutubeDl::new_ytdl_like("yt-dlp", client.clone(), play_args.url.conv::<String>()); + let meta = input.aux_metadata().await?; + let handle = call.enqueue_input(input.into()).await; handle.set_volume(volume as _)?; + let playback = { + let data = ctx.serenity_context().data.read().await; + data.get::<PlaybackKey>().unwrap().clone() + }; + + playback.insert(handle.uuid(), meta); + let q = call.queue(); q.pause()?; q.modify_queue(move |q| { |
