From 9a32a1cfe728f865dd7e6ba2c334f55dcb88d4cb Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 23 Nov 2024 20:21:19 -0500 Subject: [PATCH] Allow for excluding certain tags from a file search --- src/data/mod.rs | 1 + src/files.rs | 14 ++++++++++---- src/tags.rs | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/data/mod.rs b/src/data/mod.rs index 7ac194a..acb322e 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -113,6 +113,7 @@ pub struct FilesRequest { pub path: String, // comma separated numbers pub tag_ids: Option, + pub exclude_tag_ids: Option, pub tag_filter_mode: Option, pub recursive: Option, pub sort: Option, diff --git a/src/files.rs b/src/files.rs index 40ba3c3..7416bc9 100644 --- a/src/files.rs +++ b/src/files.rs @@ -24,7 +24,7 @@ use crate::tags::TagDao; use crate::video::StreamActor; use path_absolutize::*; use rand::prelude::SliceRandom; -use rand::{random, thread_rng}; +use rand::{thread_rng}; use serde::Deserialize; pub async fn list_photos( @@ -39,7 +39,7 @@ pub async fn list_photos( let search_recursively = req.recursive.unwrap_or(false); if let Some(tag_ids) = &req.tag_ids { if search_recursively { - let filter_mode = req.tag_filter_mode.unwrap_or(FilterMode::Any); + let filter_mode = &req.tag_filter_mode.unwrap_or(FilterMode::Any); debug!( "Searching for tags: {}. With path: '{}' and filter mode: {:?}", tag_ids, search_path, filter_mode @@ -51,10 +51,16 @@ pub async fn list_photos( .filter_map(|t| t.parse().ok()) .collect::>(); + let exclude_tag_ids = req.exclude_tag_ids.clone() + .unwrap_or(String::new()) + .split(',') + .filter_map(|t| t.parse().ok()) + .collect::>(); + return dao - .get_files_with_any_tag_ids(tag_ids.clone()) + .get_files_with_any_tag_ids(tag_ids.clone(), exclude_tag_ids.clone()) .context(format!("Failed to get files with tag_ids: {:?}", tag_ids)) - .map(|mut tagged_files| { + .map(|tagged_files| { return if let Some(sort_type) = req.sort { debug!("Sorting files: {:?}", sort_type); sort(tagged_files, sort_type) diff --git a/src/tags.rs b/src/tags.rs index 741834d..a1a22ee 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -199,7 +199,11 @@ pub trait TagDao { fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result>; fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result; fn get_files_with_all_tag_ids(&mut self, tag_ids: Vec) -> anyhow::Result>; - fn get_files_with_any_tag_ids(&mut self, tag_ids: Vec) -> anyhow::Result>; + fn get_files_with_any_tag_ids( + &mut self, + tag_ids: Vec, + exclude_tag_ids: Vec, + ) -> anyhow::Result>; } pub struct SqliteTagDao { @@ -348,17 +352,22 @@ impl TagDao for SqliteTagDao { .filter(tagged_photo::tag_id.eq_any(tag_ids.clone())) .group_by(tagged_photo::photo_name) .select((tagged_photo::photo_name, count(tagged_photo::tag_id))) - .having(count(tagged_photo::tag_id).eq(tag_ids.len() as i64)) + .having(count_distinct(tagged_photo::tag_id).eq(tag_ids.len() as i64)) .select(tagged_photo::photo_name) .get_results::(&mut self.connection) .with_context(|| format!("Unable to get Tagged photos with ids: {:?}", tag_ids)) } - fn get_files_with_any_tag_ids(&mut self, tag_ids: Vec) -> anyhow::Result> { + fn get_files_with_any_tag_ids( + &mut self, + tag_ids: Vec, + exclude_tag_ids: Vec, + ) -> anyhow::Result> { use diesel::dsl::*; tagged_photo::table .filter(tagged_photo::tag_id.eq_any(tag_ids.clone())) + .filter(tagged_photo::tag_id.ne_all(exclude_tag_ids)) .group_by(tagged_photo::photo_name) .select((tagged_photo::photo_name, count(tagged_photo::tag_id))) .select(tagged_photo::photo_name)