diff --git a/src/command/render.rs b/src/command/render.rs index 937da35..359d854 100644 --- a/src/command/render.rs +++ b/src/command/render.rs @@ -1,3 +1,4 @@ +use futures::TryStreamExt as _; use snafu::{OptionExt as _, Report, ResultExt as _, Snafu}; use std::{collections::BTreeMap, sync::LazyLock}; use time::{UtcDateTime, format_description::well_known::Rfc3339}; @@ -85,7 +86,7 @@ pub static COMMAND: LazyLock = LazyLock::new(|| { }); struct Options { - voice_channel: Id, + voice_channel_id: Id, start: UtcDateTime, end: UtcDateTime, } @@ -152,15 +153,15 @@ fn parse_options(interaction: &Interaction) -> Result Result Result Result + Unpin, ListError> -// { -// todo!(); -// } -// } +impl RecordingDataManager { + pub fn between( + &self, + start: UtcDateTime, + end: UtcDateTime, + ) -> impl TryStream + Unpin { + let this = self.clone(); -// impl RecordingDataManager { -// pub async fn between_in_vc( -// &self, -// start: UtcDateTime, -// end: UtcDateTime, -// guild_id: Id, -// voice_channel_id: Id, -// ) -> Result + Unpin, ListError> -// { -// todo!(); -// Ok(self.between(start, end)?) -// } -// } + let (mut sink, stream) = futures::channel::mpsc::channel(BUFFER_SIZE); + + tokio::spawn(async move { + let year_start = start.year(); + let year_end = end.year(); + + let years = year_start..=year_end; + + for year in years { + let mut month_start = start.month(); + let mut month_end = end.month(); + + if year > year_start { + month_start = Month::January; + } + + if year < year_end { + month_end = Month::December; + } + + let months = month_start as u8..=month_end as u8; + let months = months.map(|month| Month::try_from(month).unwrap()); + + for month in months { + let mut day_start = start.day(); + let mut day_end = end.day(); + + if month > month_start { + day_start = 1; + } + + if month < month_end { + day_end = 31; + } + + let days = day_start..=day_end; + + for day in days { + let mut hour_start = start.hour(); + let mut hour_end = end.hour(); + + if day > day_start { + hour_start = 0; + } + + if day < day_end { + hour_end = 23; + } + + let hours = hour_start..=hour_end; + + for hour in hours { + let mut minute_start = start.minute(); + let mut minute_end = end.minute(); + + if hour > hour_start { + minute_start = 0; + } + + if hour < hour_end { + minute_end = 59; + } + + let minutes = minute_start..=minute_end; + + for minute in minutes { + match this.clips(year, month, day, hour, minute).await { + Err(list_error) => { + let _ = sink + .send(Err(RecordingEntryError::ListClipsError { + source: list_error, + })) + .await; + } + Ok(clips) => { + let mut clips = clips.into_stream(); + while let Some(clip_result) = clips.next().await { + match clip_result { + Err(entry_error) => { + let _ = sink + .send(Err( + RecordingEntryError::ClipEntryError { + source: entry_error, + }, + )) + .await; + } + Ok(clip) => { + let recording = Recording { + year, + month, + day, + hour, + minute, + clip, + }; + + let _ = sink.send(Ok(recording)).await; + } + } + } + } + } + } + } + } + } + } + }); + + stream + } +} + +impl RecordingDataManager { + pub fn between_in_vc( + &self, + start: UtcDateTime, + end: UtcDateTime, + guild_id: Id, + voice_channel_id: Id, + ) -> impl TryStream + Unpin { + self.between(start, end).try_filter(move |recording| { + std::future::ready( + recording.clip.guild == guild_id + && recording.clip.voice_channel == voice_channel_id, + ) + }) + } +} diff --git a/src/recording_data/mod.rs b/src/recording_data/mod.rs index 22e69aa..63cafbe 100644 --- a/src/recording_data/mod.rs +++ b/src/recording_data/mod.rs @@ -18,7 +18,8 @@ mod user; mod voice_channel; mod year; -pub use clip::Clip; +pub use between::RecordingEntryError; +pub use clip::{Clip, ClipEntryError}; use day::Day; use guild::Guild; use hour::Hour;