Add Exif storing and update to Metadata endpoint

This commit is contained in:
Cameron
2025-12-17 16:55:48 -05:00
parent 4851f64229
commit 4082f1fdb8
13 changed files with 851 additions and 8 deletions

View File

@@ -4,7 +4,7 @@ use diesel::sqlite::SqliteConnection;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use crate::database::models::{Favorite, InsertFavorite, InsertUser, User};
use crate::database::models::{Favorite, ImageExif, InsertFavorite, InsertImageExif, InsertUser, User};
pub mod models;
pub mod schema;
@@ -181,3 +181,96 @@ impl FavoriteDao for SqliteFavoriteDao {
.map_err(|_| DbError::new(DbErrorKind::QueryError))
}
}
pub trait ExifDao: Sync + Send {
fn store_exif(&mut self, exif_data: InsertImageExif) -> Result<ImageExif, DbError>;
fn get_exif(&mut self, file_path: &str) -> Result<Option<ImageExif>, DbError>;
fn update_exif(&mut self, exif_data: InsertImageExif) -> Result<ImageExif, DbError>;
fn delete_exif(&mut self, file_path: &str) -> Result<(), DbError>;
}
pub struct SqliteExifDao {
connection: Arc<Mutex<SqliteConnection>>,
}
impl SqliteExifDao {
pub fn new() -> Self {
SqliteExifDao {
connection: Arc::new(Mutex::new(connect())),
}
}
}
impl ExifDao for SqliteExifDao {
fn store_exif(&mut self, exif_data: InsertImageExif) -> Result<ImageExif, DbError> {
use schema::image_exif::dsl::*;
let mut connection = self.connection.lock().expect("Unable to get ExifDao");
diesel::insert_into(image_exif)
.values(&exif_data)
.execute(connection.deref_mut())
.map_err(|_| DbError::new(DbErrorKind::InsertError))?;
image_exif
.filter(file_path.eq(&exif_data.file_path))
.first::<ImageExif>(connection.deref_mut())
.map_err(|_| DbError::new(DbErrorKind::QueryError))
}
fn get_exif(&mut self, path: &str) -> Result<Option<ImageExif>, DbError> {
use schema::image_exif::dsl::*;
let mut connection = self.connection.lock().expect("Unable to get ExifDao");
match image_exif
.filter(file_path.eq(path))
.first::<ImageExif>(connection.deref_mut())
{
Ok(exif) => Ok(Some(exif)),
Err(diesel::result::Error::NotFound) => Ok(None),
Err(_) => Err(DbError::new(DbErrorKind::QueryError)),
}
}
fn update_exif(&mut self, exif_data: InsertImageExif) -> Result<ImageExif, DbError> {
use schema::image_exif::dsl::*;
let mut connection = self.connection.lock().expect("Unable to get ExifDao");
diesel::update(image_exif.filter(file_path.eq(&exif_data.file_path)))
.set((
camera_make.eq(&exif_data.camera_make),
camera_model.eq(&exif_data.camera_model),
lens_model.eq(&exif_data.lens_model),
width.eq(&exif_data.width),
height.eq(&exif_data.height),
orientation.eq(&exif_data.orientation),
gps_latitude.eq(&exif_data.gps_latitude),
gps_longitude.eq(&exif_data.gps_longitude),
gps_altitude.eq(&exif_data.gps_altitude),
focal_length.eq(&exif_data.focal_length),
aperture.eq(&exif_data.aperture),
shutter_speed.eq(&exif_data.shutter_speed),
iso.eq(&exif_data.iso),
date_taken.eq(&exif_data.date_taken),
last_modified.eq(&exif_data.last_modified),
))
.execute(connection.deref_mut())
.map_err(|_| DbError::new(DbErrorKind::InsertError))?;
image_exif
.filter(file_path.eq(&exif_data.file_path))
.first::<ImageExif>(connection.deref_mut())
.map_err(|_| DbError::new(DbErrorKind::QueryError))
}
fn delete_exif(&mut self, path: &str) -> Result<(), DbError> {
use schema::image_exif::dsl::*;
diesel::delete(image_exif.filter(file_path.eq(path)))
.execute(self.connection.lock().unwrap().deref_mut())
.map(|_| ())
.map_err(|_| DbError::new(DbErrorKind::QueryError))
}
}

View File

@@ -1,4 +1,4 @@
use crate::database::schema::{favorites, users};
use crate::database::schema::{favorites, image_exif, users};
use serde::Serialize;
#[derive(Insertable)]
@@ -29,3 +29,47 @@ pub struct Favorite {
pub userid: i32,
pub path: String,
}
#[derive(Insertable)]
#[diesel(table_name = image_exif)]
pub struct InsertImageExif {
pub file_path: String,
pub camera_make: Option<String>,
pub camera_model: Option<String>,
pub lens_model: Option<String>,
pub width: Option<i32>,
pub height: Option<i32>,
pub orientation: Option<i32>,
pub gps_latitude: Option<f64>,
pub gps_longitude: Option<f64>,
pub gps_altitude: Option<f64>,
pub focal_length: Option<f64>,
pub aperture: Option<f64>,
pub shutter_speed: Option<String>,
pub iso: Option<i32>,
pub date_taken: Option<i64>,
pub created_time: i64,
pub last_modified: i64,
}
#[derive(Serialize, Queryable, Clone, Debug)]
pub struct ImageExif {
pub id: i32,
pub file_path: String,
pub camera_make: Option<String>,
pub camera_model: Option<String>,
pub lens_model: Option<String>,
pub width: Option<i32>,
pub height: Option<i32>,
pub orientation: Option<i32>,
pub gps_latitude: Option<f64>,
pub gps_longitude: Option<f64>,
pub gps_altitude: Option<f64>,
pub focal_length: Option<f64>,
pub aperture: Option<f64>,
pub shutter_speed: Option<String>,
pub iso: Option<i32>,
pub date_taken: Option<i64>,
pub created_time: i64,
pub last_modified: i64,
}

View File

@@ -6,6 +6,29 @@ table! {
}
}
table! {
image_exif (id) {
id -> Integer,
file_path -> Text,
camera_make -> Nullable<Text>,
camera_model -> Nullable<Text>,
lens_model -> Nullable<Text>,
width -> Nullable<Integer>,
height -> Nullable<Integer>,
orientation -> Nullable<Integer>,
gps_latitude -> Nullable<Double>,
gps_longitude -> Nullable<Double>,
gps_altitude -> Nullable<Double>,
focal_length -> Nullable<Double>,
aperture -> Nullable<Double>,
shutter_speed -> Nullable<Text>,
iso -> Nullable<Integer>,
date_taken -> Nullable<BigInt>,
created_time -> BigInt,
last_modified -> BigInt,
}
}
table! {
tagged_photo (id) {
id -> Integer,
@@ -33,4 +56,4 @@ table! {
joinable!(tagged_photo -> tags (tag_id));
allow_tables_to_appear_in_same_query!(favorites, tagged_photo, tags, users,);
allow_tables_to_appear_in_same_query!(favorites, image_exif, tagged_photo, tags, users,);