use chrono::Duration; use grate::tracing; use lazy_static::lazy_static; use rand::{ seq::SliceRandom, thread_rng, }; use songbird::input::{ Compose, YoutubeDl, }; use tap::Conv; use crate::{ bot::{ HttpKey, PlaybackKey, }, commands::{ playback, playback::{ songbird, InvokeInfo, }, }, util, PoiseContext, }; mod prelude; mod nov_5; mod sept_21; mod france; mod halloween; mod putin; mod shrek; mod ussr; mod thursday; mod tomorrow; mod wednesday; mod pianoman; pub type TodayIter = Box>; #[derive(Clone, Debug, Hash, Default)] pub struct TodayArgs { pub url: &'static str, pub start: Option, pub end: Option, } lazy_static! { static ref ALL: Vec TodayIter> = vec![ sept_21::sept_21, nov_5::nov_5, halloween::halloween, ussr::ussr, france::france, shrek::shrek, putin::putin, wednesday::wednesday, thursday::thursday, tomorrow::tomorrow, pianoman::pianoman, ]; } #[poise::command(prefix_command, guild_only)] pub async fn today(ctx: PoiseContext<'_>, #[rest] _rest: Option) -> anyhow::Result<()> { let today = { #[allow(unused_mut)] let mut result = chrono::Local::now().naive_local(); #[cfg(debug_assertions)] { if let Some(rest) = _rest { let dt = rest.parse::().or_else(|_| { rest.parse::().map(|date| { let time = chrono::NaiveTime::from_hms_opt(12, 0, 0).unwrap(); date.and_time(time) }) }); match dt { Ok(dt) => { tracing::debug!("overriding with datetime: {dt}"); result = dt; }, Err(e) => { tracing::debug!("parsing datetime: {e:?}"); }, }; } } result }; let options: Vec = ALL.iter().flat_map(|f| f(today)).collect(); tracing::debug!(option_count = options.len(), %today); let play_args = options.choose(&mut thread_rng()); if let Some(play_args) = play_args { let Some(voice_channel) = util::best_voice_channel(ctx) else { tracing::error!(?ctx, "couldn't find a relevant voice channel"); util::react(ctx, '🔇').await?; return Ok(()); }; let volume = util::volume(ctx).await; tracing::debug!(volume); let (_sb, call) = songbird(ctx).await?; let mut call = call.lock().await; if call.current_channel().is_none() { call.join(voice_channel).await?; } let client = { let data = ctx.serenity_context().data.read().await; data.get::().unwrap().clone() }; let mut input = YoutubeDl::new_ytdl_like("yt-dlp", client.clone(), play_args.url.conv::()); 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::().unwrap().clone() }; playback.insert(handle.uuid(), playback::Metadata { invoker: ctx.author().id, invoke_info: InvokeInfo::Ytdl { metadata: meta, }, }); let q = call.queue(); q.pause()?; q.modify_queue(move |q| { let last = q.pop_back(); if let Some(last) = last { q.push_front(last); } }); q.resume()?; } else { util::reply(ctx, "no").await?; util::reply(ctx, ":angry:").await?; } Ok(()) }