80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use async_trait::async_trait;
|
|
use std::path::PathBuf;
|
|
|
|
use libertas_core::{
|
|
error::{CoreError, CoreResult},
|
|
models::Media,
|
|
plugins::{MediaProcessorPlugin, PluginContext, PluginData},
|
|
};
|
|
use nom_exif::{AsyncMediaParser, AsyncMediaSource, Exif, ExifIter, ExifTag};
|
|
|
|
pub struct ExifReaderPlugin;
|
|
|
|
#[async_trait]
|
|
impl MediaProcessorPlugin for ExifReaderPlugin {
|
|
fn name(&self) -> &'static str {
|
|
"exif_reader"
|
|
}
|
|
|
|
async fn process(&self, media: &Media, context: &PluginContext) -> CoreResult<PluginData> {
|
|
let file_path = PathBuf::from(&context.media_library_path).join(&media.storage_path);
|
|
|
|
let ms = match AsyncMediaSource::file_path(file_path).await {
|
|
Ok(ms) => ms,
|
|
Err(e) => return Err(CoreError::Unknown(format!("Failed to open a file: {}", e))),
|
|
};
|
|
|
|
if !ms.has_exif() {
|
|
return Ok(PluginData {
|
|
message: "No EXIF data found in file.".to_string(),
|
|
});
|
|
}
|
|
|
|
let mut parser = AsyncMediaParser::new();
|
|
let iter: ExifIter = match parser.parse(ms).await {
|
|
Ok(iter) => iter,
|
|
Err(e) => {
|
|
// It's not a fatal error, just means parsing failed (e.g., corrupt data)
|
|
return Ok(PluginData {
|
|
message: format!("Could not parse EXIF: {}", e),
|
|
});
|
|
}
|
|
};
|
|
|
|
let location: Option<String> = match iter.parse_gps_info() {
|
|
Ok(Some(gps_info)) => Some(gps_info.format_iso6709()),
|
|
Ok(None) => None,
|
|
Err(_) => None,
|
|
};
|
|
|
|
let exif: Exif = iter.into();
|
|
|
|
let width = exif
|
|
.get(ExifTag::ExifImageWidth)
|
|
.and_then(|f| f.as_u32())
|
|
.map(|v| v as i32);
|
|
|
|
let height = exif
|
|
.get(ExifTag::ExifImageHeight)
|
|
.and_then(|f| f.as_u32())
|
|
.map(|v| v as i32);
|
|
|
|
if width.is_some() || height.is_some() || location.is_some() {
|
|
context
|
|
.media_repo
|
|
.update_metadata(media.id, width, height, location.clone())
|
|
.await?;
|
|
|
|
let message = format!(
|
|
"Extracted EXIF: width={:?}, height={:?}, location={:?}",
|
|
width, height, location
|
|
);
|
|
Ok(PluginData { message })
|
|
} else {
|
|
Ok(PluginData {
|
|
message: "No EXIF width/height or GPS location found.".to_string(),
|
|
})
|
|
}
|
|
}
|
|
}
|