use std::sync::Arc;
use super::types::DownloadEvent;
type FilterPredicate = Arc<dyn Fn(&DownloadEvent) -> bool + Send + Sync>;
#[derive(Clone)]
pub struct EventFilter {
predicates: Vec<FilterPredicate>,
}
impl EventFilter {
pub fn all() -> Self {
tracing::debug!("⚙️ Creating EventFilter that accepts all events");
Self { predicates: Vec::new() }
}
pub fn download_id(id: u64) -> Self {
tracing::debug!(download_id = id, "⚙️ Creating EventFilter for download ID");
let mut filter = Self::all();
filter
.predicates
.push(Arc::new(move |event| event.download_id() == Some(id)));
filter
}
pub fn only_terminal() -> Self {
tracing::debug!("⚙️ Creating EventFilter for terminal events");
let mut filter = Self::all();
filter.predicates.push(Arc::new(|event| event.is_terminal()));
filter
}
pub fn only_completed() -> Self {
tracing::debug!("⚙️ Creating EventFilter for completed downloads");
let mut filter = Self::all();
filter.predicates.push(Arc::new(|event| {
matches!(event, DownloadEvent::DownloadCompleted { .. })
}));
filter
}
pub fn only_failed() -> Self {
tracing::debug!("⚙️ Creating EventFilter for failed downloads");
let mut filter = Self::all();
filter
.predicates
.push(Arc::new(|event| matches!(event, DownloadEvent::DownloadFailed { .. })));
filter
}
pub fn only_progress() -> Self {
tracing::debug!("⚙️ Creating EventFilter for progress events");
let mut filter = Self::all();
filter.predicates.push(Arc::new(|event| event.is_progress()));
filter
}
pub fn event_types(types: Vec<&'static str>) -> Self {
tracing::debug!(
type_count = types.len(),
"⚙️ Creating EventFilter for specific event types"
);
let mut filter = Self::all();
filter
.predicates
.push(Arc::new(move |event| types.contains(&event.event_type())));
filter
}
pub fn and_then<F>(mut self, predicate: F) -> Self
where
F: Fn(&DownloadEvent) -> bool + Send + Sync + 'static,
{
self.predicates.push(Arc::new(predicate));
self
}
pub fn matches(&self, event: &DownloadEvent) -> bool {
let result = self.predicates.iter().all(|predicate| predicate(event));
tracing::trace!(
event_type = event.event_type(),
download_id = event.download_id(),
matches = result,
predicate_count = self.predicates.len(),
"🔔 Event filter match test"
);
result
}
pub fn exclude_progress(self) -> Self {
self.and_then(|event| !event.is_progress())
}
pub fn only_downloads(self) -> Self {
self.and_then(|event| event.download_id().is_some())
}
pub fn any_of(types: &[&'static str]) -> Self {
let types_vec: Vec<&'static str> = types.to_vec();
Self::all().and_then(move |event| types_vec.contains(&event.event_type()))
}
pub fn only_playlist() -> Self {
Self::any_of(&[
"playlist_fetched",
"playlist_item_started",
"playlist_item_completed",
"playlist_item_failed",
"playlist_completed",
])
}
pub fn only_metadata() -> Self {
Self::any_of(&["metadata_applied", "chapters_embedded"])
}
pub fn only_post_process() -> Self {
Self::any_of(&["post_process_started", "post_process_completed", "post_process_failed"])
}
#[cfg(feature = "live-recording")]
pub fn only_live_recording() -> Self {
Self::any_of(&[
"live_recording_started",
"live_recording_progress",
"live_recording_stopped",
"live_recording_failed",
])
}
#[cfg(feature = "live-recording")]
pub fn live_recording(video_id: impl Into<String>) -> Self {
let id = video_id.into();
Self::only_live_recording().and_then(move |event| match event {
DownloadEvent::LiveRecordingStarted { video_id, .. }
| DownloadEvent::LiveRecordingProgress { video_id, .. }
| DownloadEvent::LiveRecordingStopped { video_id, .. }
| DownloadEvent::LiveRecordingFailed { video_id, .. } => video_id == &id,
_ => false,
})
}
#[cfg(feature = "live-streaming")]
pub fn only_live_streaming() -> Self {
Self::any_of(&[
"live_stream_started",
"live_stream_progress",
"live_stream_stopped",
"live_stream_failed",
])
}
}
impl Default for EventFilter {
fn default() -> Self {
Self::all()
}
}
impl std::fmt::Debug for EventFilter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventFilter")
.field("predicate_count", &self.predicates.len())
.finish()
}
}
impl std::fmt::Display for EventFilter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "EventFilter(predicates={})", self.predicates.len())
}
}