picox/src/model/image.rs

155 lines
3.9 KiB
Rust

use crate::api::models::{AlbumQuery, ImageQuery, ImageSort, PicOxError};
use crate::model::album::Album;
use chrono::{DateTime, Utc};
use j_db::database::Database;
use j_db::model::JdbModel;
use rand::prelude::SliceRandom;
use rand::thread_rng;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use url::Url;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum StorageLocation {
FileStore { path: PathBuf },
Link,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Image {
pub filename: String,
pub tags: Vec<String>,
pub create_date: DateTime<Utc>,
pub link: Url,
pub created_by: u64,
pub storage_location: StorageLocation,
pub album: u64,
id: Option<u64>,
}
impl Image {
pub fn new(
filename: &str,
tags: Vec<String>,
link: Url,
created_by: u64,
storage_location: StorageLocation,
album: u64,
) -> Self {
Self {
filename: filename.to_string(),
tags,
create_date: Utc::now(),
link,
created_by,
storage_location,
album,
id: None,
}
}
pub fn query_image(db: &Database, image_query: &ImageQuery) -> Result<Vec<Self>, PicOxError> {
let album_id = if let Some(album) = &image_query.album {
Some(
Album::find_album_by_query(
db,
AlbumQuery {
album_name: Some(album.to_string()),
},
)
.first()
.ok_or(PicOxError::AlbumNotFound)?
.id()
.unwrap(),
)
} else {
None
};
let mut images: Vec<Image> = db
.filter(|_, img: &Image| {
if let Some(album_id) = album_id {
if img.album != album_id {
return false;
}
}
if !image_query.image_type.is_empty() {
let path = img.link.to_file_path().unwrap();
let ext = path.extension().unwrap().to_str().unwrap();
if !image_query.image_type.contains(&ext.to_string())
{
return false;
}
}
if !image_query.tags.is_empty() {
let mut found = false;
for tag in &image_query.tags {
if img.tags.contains(tag) {
found = true;
break;
}
}
if !found {
return false;
}
}
true
})?
.collect();
match image_query.order {
ImageSort::Random => {
images.shuffle(&mut thread_rng());
}
ImageSort::DateAscending => {
images.sort_by(|img_a, img_b| img_a.create_date.cmp(&img_b.create_date))
}
ImageSort::DateDescending => {
images.sort_by(|img_a, img_b| img_b.create_date.cmp(&img_a.create_date))
}
ImageSort::None => {}
}
if images.len() > image_query.limit {
images.drain(image_query.limit..);
}
Ok(images)
}
}
impl j_db::model::JdbModel for Image {
fn id(&self) -> Option<u64> {
self.id
}
fn set_id(&mut self, id: u64) {
self.id = Some(id)
}
fn tree() -> String {
"Image".to_string()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ImageData {
Bytes(Vec<u8>),
Link(String),
}
impl ImageData {
pub fn size(&self) -> usize {
match self {
ImageData::Bytes(data) => data.len(),
ImageData::Link(_) => 0,
}
}
}