diff --git a/mediarepo-daemon/mediarepo-model/src/file.rs b/mediarepo-daemon/mediarepo-model/src/file.rs index 041b740..0062d00 100644 --- a/mediarepo-daemon/mediarepo-model/src/file.rs +++ b/mediarepo-daemon/mediarepo-model/src/file.rs @@ -1,5 +1,6 @@ use crate::file_type::FileType; use crate::storage::Storage; +use crate::tag::Tag; use crate::thumbnail::Thumbnail; use chrono::{Local, NaiveDateTime}; use mediarepo_core::error::{RepoError, RepoResult}; @@ -10,9 +11,12 @@ use mediarepo_core::image_processing::{ use mediarepo_database::entities::file; use mediarepo_database::entities::hash; use mediarepo_database::entities::hash_tag; +use mediarepo_database::entities::namespace; +use mediarepo_database::entities::tag; use mime::Mime; use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, Set}; +use sea_orm::{JoinType, QuerySelect}; use tokio::io::BufReader; #[derive(Clone)] @@ -167,6 +171,23 @@ impl File { Thumbnail::for_file_id(self.db.clone(), self.model.id).await } + /// Returns the list of tags of the file + pub async fn tags(&self) -> RepoResult> { + let tags: Vec<(tag::Model, Option)> = tag::Entity::find() + .find_also_related(namespace::Entity) + .join(JoinType::LeftJoin, hash_tag::Relation::Tag.def().rev()) + .join(JoinType::InnerJoin, hash_tag::Relation::Hash.def()) + .filter(hash::Column::Id.eq(self.hash.id)) + .all(&self.db) + .await?; + let tags = tags + .into_iter() + .map(|(tag, namespace)| Tag::new(self.db.clone(), tag, namespace)) + .collect(); + + Ok(tags) + } + /// Changes the name of the file pub async fn set_name(&mut self, name: S) -> RepoResult<()> { let mut active_file = self.get_active_model(); diff --git a/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs b/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs index 7c274e4..a5f3218 100644 --- a/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs +++ b/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs @@ -1,12 +1,8 @@ -use crate::types::requests::{ - AddFileRequest, FileIdentifier, GetFileThumbnailsRequest, ReadFileRequest, -}; +use crate::types::requests::{AddFileRequest, GetFileThumbnailsRequest, ReadFileRequest}; use crate::types::responses::{FileResponse, ThumbnailResponse}; -use crate::utils::get_repo_from_context; -use mediarepo_core::error::{RepoError, RepoResult}; +use crate::utils::{file_by_identifier, get_repo_from_context}; +use mediarepo_core::error::RepoError; use mediarepo_core::rmp_ipc::prelude::*; -use mediarepo_model::file::File; -use mediarepo_model::repo::Repo; use std::path::PathBuf; use tokio::io::AsyncReadExt; @@ -31,11 +27,10 @@ impl NamespaceProvider for FilesNamespace { impl FilesNamespace { /// Returns a list of all files async fn all_files(ctx: &Context, event: Event) -> IPCResult<()> { - let files = { - let repo = get_repo_from_context(ctx).await; - repo.files().await? - }; + let repo = get_repo_from_context(ctx).await; + let files = repo.files().await?; let responses: Vec = files.into_iter().map(FileResponse::from).collect(); + ctx.emitter .emit_response_to(event.id(), Self::name(), "all_files", responses) .await?; @@ -115,11 +110,3 @@ impl FilesNamespace { Ok(()) } } - -async fn file_by_identifier(identifier: FileIdentifier, repo: &Repo) -> RepoResult { - let file = match identifier { - FileIdentifier::ID(id) => repo.file_by_id(id).await, - FileIdentifier::Hash(hash) => repo.file_by_hash(hash).await, - }?; - file.ok_or_else(|| RepoError::from("Thumbnail not found")) -} diff --git a/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs b/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs index 42c2571..ddf6bba 100644 --- a/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs +++ b/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs @@ -1,5 +1,6 @@ +use crate::types::requests::GetFileTagsRequest; use crate::types::responses::TagResponse; -use crate::utils::get_repo_from_context; +use crate::utils::{file_by_identifier, get_repo_from_context}; use mediarepo_core::rmp_ipc::prelude::*; pub struct TagsNamespace; @@ -11,7 +12,8 @@ impl NamespaceProvider for TagsNamespace { fn register(handler: &mut EventHandler) { events!(handler, - "all_tags" => Self::all_tags + "all_tags" => Self::all_tags, + "tags_for_file" => Self::tags_for_file ); } } @@ -32,4 +34,19 @@ impl TagsNamespace { Ok(()) } + + /// Returns all tags for a single file + async fn tags_for_file(ctx: &Context, event: Event) -> IPCResult<()> { + let repo = get_repo_from_context(ctx).await; + let request = event.data::()?; + let file = file_by_identifier(request, &repo).await?; + let tags = file.tags().await?; + let responses: Vec = tags.into_iter().map(TagResponse::from).collect(); + + ctx.emitter + .emit_response_to(event.id(), Self::name(), "tags_for_file", responses) + .await?; + + Ok(()) + } } diff --git a/mediarepo-daemon/mediarepo-socket/src/types/requests.rs b/mediarepo-daemon/mediarepo-socket/src/types/requests.rs index 0806d39..6275703 100644 --- a/mediarepo-daemon/mediarepo-socket/src/types/requests.rs +++ b/mediarepo-daemon/mediarepo-socket/src/types/requests.rs @@ -13,3 +13,4 @@ pub enum FileIdentifier { pub type ReadFileRequest = FileIdentifier; pub type GetFileThumbnailsRequest = FileIdentifier; +pub type GetFileTagsRequest = FileIdentifier; diff --git a/mediarepo-daemon/mediarepo-socket/src/utils.rs b/mediarepo-daemon/mediarepo-socket/src/utils.rs index 7b29eaa..f65b62b 100644 --- a/mediarepo-daemon/mediarepo-socket/src/utils.rs +++ b/mediarepo-daemon/mediarepo-socket/src/utils.rs @@ -1,4 +1,7 @@ +use crate::types::requests::FileIdentifier; +use mediarepo_core::error::{RepoError, RepoResult}; use mediarepo_core::rmp_ipc::ipc::context::Context; +use mediarepo_model::file::File; use mediarepo_model::repo::Repo; use mediarepo_model::type_keys::RepoKey; use std::sync::Arc; @@ -8,3 +11,11 @@ pub async fn get_repo_from_context(ctx: &Context) -> Arc { let repo = data.get::().unwrap(); Arc::clone(repo) } + +pub async fn file_by_identifier(identifier: FileIdentifier, repo: &Repo) -> RepoResult { + let file = match identifier { + FileIdentifier::ID(id) => repo.file_by_id(id).await, + FileIdentifier::Hash(hash) => repo.file_by_hash(hash).await, + }?; + file.ok_or_else(|| RepoError::from("Thumbnail not found")) +}