feature/shuffle-sort #30

Merged
cameron merged 21 commits from feature/shuffle-sort into master 2024-12-06 16:25:44 +00:00
3 changed files with 50 additions and 55 deletions
Showing only changes of commit 860e7a97fb - Show all commits

View File

@@ -24,7 +24,7 @@ use crate::tags::TagDao;
use crate::video::StreamActor; use crate::video::StreamActor;
use path_absolutize::*; use path_absolutize::*;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use rand::{thread_rng}; use rand::thread_rng;
use serde::Deserialize; use serde::Deserialize;
pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>( pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
@@ -51,54 +51,38 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
.filter_map(|t| t.parse().ok()) .filter_map(|t| t.parse().ok())
.collect::<Vec<i32>>(); .collect::<Vec<i32>>();
let exclude_tag_ids = req.exclude_tag_ids.clone() let exclude_tag_ids = req
.exclude_tag_ids
.clone()
.unwrap_or(String::new()) .unwrap_or(String::new())
.split(',') .split(',')
.filter_map(|t| t.parse().ok()) .filter_map(|t| t.parse().ok())
.collect::<Vec<i32>>(); .collect::<Vec<i32>>();
return dao match filter_mode {
.get_files_with_any_tag_ids(tag_ids.clone(), exclude_tag_ids.clone()) FilterMode::Any => dao.get_files_with_any_tag_ids(tag_ids.clone(), exclude_tag_ids),
.context(format!("Failed to get files with tag_ids: {:?}", tag_ids)) FilterMode::All => dao.get_files_with_all_tag_ids(tag_ids.clone(), exclude_tag_ids),
.map(|tagged_files| { }
return if let Some(sort_type) = req.sort { .context(format!(
debug!("Sorting files: {:?}", sort_type); "Failed to get files with tag_ids: {:?} with filter_mode: {:?}",
sort(tagged_files, sort_type) tag_ids, filter_mode
} else { ))
tagged_files .map(|files| {
}; files
}) .into_iter()
.map(|tagged_files| match filter_mode { .filter(|file_path| file_path.starts_with(search_path))
FilterMode::Any => tagged_files .collect()
.iter() })
.filter(|file| file.starts_with(search_path)) .map(|tagged_files| {
.cloned() trace!("Found tagged files: {:?}", tagged_files);
.collect(),
FilterMode::All => tagged_files
.iter()
.filter(|&file_path| {
if !file_path.starts_with(search_path) {
return false;
}
let file_tags = dao.get_tags_for_path(file_path).unwrap_or_default(); HttpResponse::Ok().json(PhotosResponse {
tag_ids photos: tagged_files,
.iter() dirs: vec![],
.all(|id| file_tags.iter().any(|tag| &tag.id == id))
})
.cloned()
.collect::<Vec<String>>(),
}) })
.map(|tagged_files| { })
trace!("Found tagged files: {:?}", tagged_files); .into_http_internal_err()
.unwrap_or_else(|e| e.error_response());
HttpResponse::Ok().json(PhotosResponse {
photos: tagged_files,
dirs: vec![],
})
})
.into_http_internal_err()
.unwrap_or_else(|e| e.error_response());
} }
} }

View File

@@ -282,7 +282,7 @@ async fn favorites(
.expect("Unable to get FavoritesDao") .expect("Unable to get FavoritesDao")
.get_favorites(claims.sub.parse::<i32>().unwrap()) .get_favorites(claims.sub.parse::<i32>().unwrap())
}) })
.await .await
{ {
Ok(Ok(favorites)) => { Ok(Ok(favorites)) => {
let favorites = favorites let favorites = favorites
@@ -317,7 +317,7 @@ async fn put_add_favorite(
.expect("Unable to get FavoritesDao") .expect("Unable to get FavoritesDao")
.add_favorite(user_id, &path) .add_favorite(user_id, &path)
}) })
.await .await
{ {
Ok(Err(e)) if e.kind == DbErrorKind::AlreadyExists => { Ok(Err(e)) if e.kind == DbErrorKind::AlreadyExists => {
debug!("Favorite: {} exists for user: {}", &body.path, user_id); debug!("Favorite: {} exists for user: {}", &body.path, user_id);
@@ -356,8 +356,8 @@ async fn delete_favorite(
.expect("Unable to get favorites dao") .expect("Unable to get favorites dao")
.remove_favorite(user_id, path); .remove_favorite(user_id, path);
}) })
.await .await
.unwrap(); .unwrap();
info!( info!(
"Removing favorite \"{}\" for userid: {}", "Removing favorite \"{}\" for userid: {}",
@@ -391,7 +391,7 @@ fn create_thumbnails() {
.parent() .parent()
.unwrap_or_else(|| panic!("Thumbnail {:?} has no parent?", thumb_path)), .unwrap_or_else(|| panic!("Thumbnail {:?} has no parent?", thumb_path)),
) )
.expect("Error creating directory"); .expect("Error creating directory");
debug!("Generating video thumbnail: {:?}", thumb_path); debug!("Generating video thumbnail: {:?}", thumb_path);
generate_video_thumbnail(entry.path(), &thumb_path); generate_video_thumbnail(entry.path(), &thumb_path);
@@ -526,10 +526,10 @@ fn main() -> std::io::Result<()> {
.app_data::<Data<Mutex<SqliteTagDao>>>(Data::new(Mutex::new(tag_dao))) .app_data::<Data<Mutex<SqliteTagDao>>>(Data::new(Mutex::new(tag_dao)))
.wrap(prometheus.clone()) .wrap(prometheus.clone())
}) })
.bind(dotenv::var("BIND_URL").unwrap())? .bind(dotenv::var("BIND_URL").unwrap())?
.bind("localhost:8088")? .bind("localhost:8088")?
.run() .run()
.await .await
}) })
} }
@@ -548,7 +548,8 @@ fn watch_files() {
let base_str = dotenv::var("BASE_PATH").unwrap(); let base_str = dotenv::var("BASE_PATH").unwrap();
let base_path = Path::new(&base_str); let base_path = Path::new(&base_str);
watcher.watch(base_path, RecursiveMode::Recursive) watcher
.watch(base_path, RecursiveMode::Recursive)
.context(format!("Unable to watch BASE_PATH: '{}'", base_str)) .context(format!("Unable to watch BASE_PATH: '{}'", base_str))
.unwrap(); .unwrap();

View File

@@ -198,7 +198,11 @@ pub trait TagDao {
fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>; fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>;
fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>; fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>;
fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>; fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>;
fn get_files_with_all_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>>; fn get_files_with_all_tag_ids(
&mut self,
tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>>;
fn get_files_with_any_tag_ids( fn get_files_with_any_tag_ids(
&mut self, &mut self,
tag_ids: Vec<i32>, tag_ids: Vec<i32>,
@@ -345,11 +349,16 @@ impl TagDao for SqliteTagDao {
}) })
} }
fn get_files_with_all_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>> { fn get_files_with_all_tag_ids(
&mut self,
tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>> {
use diesel::dsl::*; use diesel::dsl::*;
tagged_photo::table tagged_photo::table
.filter(tagged_photo::tag_id.eq_any(tag_ids.clone())) .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) .group_by(tagged_photo::photo_name)
.select((tagged_photo::photo_name, count(tagged_photo::tag_id))) .select((tagged_photo::photo_name, count(tagged_photo::tag_id)))
.having(count_distinct(tagged_photo::tag_id).eq(tag_ids.len() as i64)) .having(count_distinct(tagged_photo::tag_id).eq(tag_ids.len() as i64))
@@ -496,7 +505,8 @@ mod tests {
fn get_files_with_all_tag_ids( fn get_files_with_all_tag_ids(
&mut self, &mut self,
_tag_ids: Vec<i32>, tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>> { ) -> anyhow::Result<Vec<String>> {
todo!() todo!()
} }