diff --git a/mediarepo-daemon/mediarepo-model/src/repo.rs b/mediarepo-daemon/mediarepo-model/src/repo.rs index fab2fcc..441d5d0 100644 --- a/mediarepo-daemon/mediarepo-model/src/repo.rs +++ b/mediarepo-daemon/mediarepo-model/src/repo.rs @@ -102,6 +102,11 @@ impl Repo { .await } + /// Returns a thumbnail by its hash + pub async fn thumbnail_by_hash>(&self, hash: S) -> RepoResult> { + Thumbnail::by_hash(self.db.clone(), hash).await + } + /// Creates thumbnails of all sizes for a file pub async fn create_thumbnails_for_file(&self, file: File) -> RepoResult<()> { let thumb_storage = self.get_thumbnail_storage()?; diff --git a/mediarepo-daemon/mediarepo-model/src/thumbnail.rs b/mediarepo-daemon/mediarepo-model/src/thumbnail.rs index 8f632e7..d8a7d12 100644 --- a/mediarepo-daemon/mediarepo-model/src/thumbnail.rs +++ b/mediarepo-daemon/mediarepo-model/src/thumbnail.rs @@ -4,6 +4,8 @@ use mediarepo_database::entities::hash; use mediarepo_database::entities::thumbnail; use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, Set}; +use tokio::fs::File; +use tokio::io::BufReader; pub struct Thumbnail { db: DatabaseConnection, @@ -31,6 +33,23 @@ impl Thumbnail { } } + /// Returns a thumbnail by hash + pub async fn by_hash>( + db: DatabaseConnection, + hash: S, + ) -> RepoResult> { + let result: Option<(hash::Model, Option)> = hash::Entity::find() + .filter(hash::Column::Value.eq(hash.as_ref())) + .find_also_related(thumbnail::Entity) + .one(&db) + .await?; + if let Some((hash, Some(model))) = result { + Ok(Some(Self::new(db, model, hash))) + } else { + Ok(None) + } + } + /// Inserts a thumbnail into the database pub async fn add( db: DatabaseConnection, @@ -100,4 +119,10 @@ impl Thumbnail { Ok(storage) } + + /// Returns the reader of the thumbnail file + pub async fn get_reader(&self) -> RepoResult> { + let storage = self.storage().await?; + storage.get_file_reader(self.hash()).await + } } diff --git a/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs b/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs index ca0769e..b8a945f 100644 --- a/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs +++ b/mediarepo-daemon/mediarepo-socket/src/namespaces/files.rs @@ -20,6 +20,7 @@ pub fn build(builder: NamespaceBuilder) -> NamespaceBuilder { .on("add_file", |c, e| Box::pin(add_file(c, e))) .on("read_file", |c, e| Box::pin(read_file(c, e))) .on("get_thumbnails", |c, e| Box::pin(get_file_thumbnails(c, e))) + .on("read_thumbnail", |c, e| Box::pin(read_thumbnail(c, e))) } /// Returns a list of all files @@ -98,6 +99,27 @@ async fn get_file_thumbnails(ctx: &Context, event: Event) -> Result<()> { Ok(()) } +/// Reads a thumbnail for the given thumbnail hash +async fn read_thumbnail(ctx: &Context, event: Event) -> Result<()> { + let hash = event.data::()?; + let mut reader = { + let data = ctx.data.read().await; + let repo = data.get::().unwrap(); + let thumbnail = repo + .thumbnail_by_hash(&hash) + .await? + .ok_or_else(|| RepoError::from("Thumbnail not found"))?; + thumbnail.get_reader().await? + }; + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await?; + ctx.emitter + .emit_response_to(event.id(), FILES_NAMESPACE, "read_thumbnail", buf) + .await?; + + Ok(()) +} + async fn file_by_identifier(identifier: FileIdentifier, repo: &Repo) -> RepoResult> { match identifier { FileIdentifier::ID(id) => repo.file_by_id(id).await,