You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mediarepo/mediarepo-daemon/mediarepo-model/src/thumbnail.rs

129 lines
3.7 KiB
Rust

use crate::storage::Storage;
use mediarepo_core::error::RepoResult;
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,
model: thumbnail::Model,
hash: hash::Model,
}
impl Thumbnail {
pub(crate) fn new(db: DatabaseConnection, model: thumbnail::Model, hash: hash::Model) -> Self {
Self { db, model, hash }
}
/// Returns the thumbnail by id
pub async fn by_id(db: DatabaseConnection, id: i64) -> RepoResult<Option<Self>> {
let model: Option<(thumbnail::Model, Option<hash::Model>)> =
thumbnail::Entity::find_by_id(id)
.find_also_related(hash::Entity)
.one(&db)
.await?;
if let Some((model, Some(hash))) = model {
Ok(Some(Self::new(db, model, hash)))
} else {
Ok(None)
}
}
/// Returns a thumbnail by hash
pub async fn by_hash<S: AsRef<str>>(
db: DatabaseConnection,
hash: S,
) -> RepoResult<Option<Self>> {
let result: Option<(hash::Model, Option<thumbnail::Model>)> = 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,
hash_id: i64,
file_id: i64,
storage_id: i64,
height: i32,
width: i32,
mime: Option<String>,
) -> RepoResult<Self> {
let active_model = thumbnail::ActiveModel {
storage_id: Set(storage_id),
hash_id: Set(hash_id),
file_id: Set(file_id),
height: Set(height),
width: Set(width),
mime: Set(mime),
..Default::default()
};
let active_model: thumbnail::ActiveModel = active_model.insert(&db).await?;
let thumbnail = Self::by_id(db, active_model.id.unwrap())
.await?
.expect("Inserted thumbnail does not exist");
Ok(thumbnail)
}
/// Returns all thumbnails for a given file
pub async fn for_file_id(db: DatabaseConnection, file_id: i64) -> RepoResult<Vec<Self>> {
let thumb_models: Vec<(thumbnail::Model, Option<hash::Model>)> = thumbnail::Entity::find()
.filter(thumbnail::Column::FileId.eq(file_id))
.find_also_related(hash::Entity)
.all(&db)
.await?;
Ok(thumb_models
.into_iter()
.filter_map(|(m, h)| Some(Self::new(db.clone(), m, h?)))
.collect())
}
pub fn id(&self) -> i64 {
self.model.id
}
pub fn hash(&self) -> &String {
&self.hash.value
}
pub fn height(&self) -> i32 {
self.model.height
}
pub fn width(&self) -> i32 {
self.model.width
}
pub fn mime_type(&self) -> &Option<String> {
&self.model.mime
}
/// Returns the storage for the thumbnail
pub async fn storage(&self) -> RepoResult<Storage> {
let storage = Storage::by_id(self.db.clone(), self.model.storage_id)
.await?
.expect("The FK storage_id doesn't exist?!");
Ok(storage)
}
/// Returns the reader of the thumbnail file
pub async fn get_reader(&self) -> RepoResult<BufReader<File>> {
let storage = self.storage().await?;
storage.get_file_reader(self.hash()).await
}
}