Make date parse from metadata a little more consistent
This commit is contained in:
@@ -222,13 +222,14 @@ pub async fn get_available_models_handler(
|
|||||||
let ollama_client = &app_state.ollama;
|
let ollama_client = &app_state.ollama;
|
||||||
|
|
||||||
// Fetch models with capabilities from primary server
|
// Fetch models with capabilities from primary server
|
||||||
let primary_models = match OllamaClient::list_models_with_capabilities(&ollama_client.primary_url).await {
|
let primary_models =
|
||||||
Ok(models) => models,
|
match OllamaClient::list_models_with_capabilities(&ollama_client.primary_url).await {
|
||||||
Err(e) => {
|
Ok(models) => models,
|
||||||
log::warn!("Failed to fetch models from primary server: {:?}", e);
|
Err(e) => {
|
||||||
vec![]
|
log::warn!("Failed to fetch models from primary server: {:?}", e);
|
||||||
}
|
vec![]
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let primary = ServerModels {
|
let primary = ServerModels {
|
||||||
url: ollama_client.primary_url.clone(),
|
url: ollama_client.primary_url.clone(),
|
||||||
|
|||||||
@@ -995,7 +995,10 @@ impl InsightGenerator {
|
|||||||
let image_base64 = if has_vision {
|
let image_base64 = if has_vision {
|
||||||
match self.load_image_as_base64(&file_path) {
|
match self.load_image_as_base64(&file_path) {
|
||||||
Ok(b64) => {
|
Ok(b64) => {
|
||||||
log::info!("Successfully loaded image for vision-capable model '{}'", model_to_check);
|
log::info!(
|
||||||
|
"Successfully loaded image for vision-capable model '{}'",
|
||||||
|
model_to_check
|
||||||
|
);
|
||||||
Some(b64)
|
Some(b64)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ impl OllamaClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a model has vision capabilities using the /api/show endpoint
|
/// Check if a model has vision capabilities using the /api/show endpoint
|
||||||
pub async fn check_model_capabilities(url: &str, model_name: &str) -> Result<ModelCapabilities> {
|
pub async fn check_model_capabilities(
|
||||||
|
url: &str,
|
||||||
|
model_name: &str,
|
||||||
|
) -> Result<ModelCapabilities> {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.connect_timeout(Duration::from_secs(5))
|
.connect_timeout(Duration::from_secs(5))
|
||||||
.timeout(Duration::from_secs(10))
|
.timeout(Duration::from_secs(10))
|
||||||
|
|||||||
57
src/files.rs
57
src/files.rs
@@ -1,3 +1,6 @@
|
|||||||
|
use ::anyhow;
|
||||||
|
use actix::{Handler, Message};
|
||||||
|
use anyhow::{Context, anyhow};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
@@ -5,10 +8,7 @@ use std::io;
|
|||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::time::SystemTime;
|
||||||
use ::anyhow;
|
|
||||||
use actix::{Handler, Message};
|
|
||||||
use anyhow::{Context, anyhow};
|
|
||||||
|
|
||||||
use crate::data::{Claims, FilesRequest, FilterMode, MediaType, PhotosResponse, SortType};
|
use crate::data::{Claims, FilesRequest, FilterMode, MediaType, PhotosResponse, SortType};
|
||||||
use crate::database::ExifDao;
|
use crate::database::ExifDao;
|
||||||
@@ -22,6 +22,7 @@ use actix_web::{
|
|||||||
HttpRequest, HttpResponse,
|
HttpRequest, HttpResponse,
|
||||||
web::{self, Query},
|
web::{self, Query},
|
||||||
};
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
use opentelemetry::KeyValue;
|
use opentelemetry::KeyValue;
|
||||||
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
||||||
@@ -73,18 +74,24 @@ fn apply_sorting_with_exif(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
// Try EXIF date first
|
// Try EXIF date first
|
||||||
let date_taken = exif_map.get(&f.file_name).copied().or_else(|| {
|
let date_taken = exif_map
|
||||||
// Fallback to filename extraction
|
.get(&f.file_name)
|
||||||
extract_date_from_filename(&f.file_name).map(|dt| dt.timestamp())
|
.copied()
|
||||||
}).or_else(|| {
|
.or_else(|| {
|
||||||
// Fallback to filesystem metadata creation date
|
// Fallback to filename extraction
|
||||||
let full_path = base_path.join(&f.file_name);
|
extract_date_from_filename(&f.file_name).map(|dt| dt.timestamp())
|
||||||
std::fs::metadata(full_path)
|
})
|
||||||
.and_then(|md| md.created())
|
.or_else(|| {
|
||||||
.ok()
|
// Fallback to filesystem metadata creation date
|
||||||
.and_then(|ct| ct.duration_since(std::time::UNIX_EPOCH).ok())
|
let full_path = base_path.join(&f.file_name);
|
||||||
.map(|d| d.as_secs() as i64)
|
std::fs::metadata(full_path)
|
||||||
});
|
.and_then(|md| md.created().or(md.modified()))
|
||||||
|
.ok()
|
||||||
|
.map(|system_time| {
|
||||||
|
<SystemTime as Into<DateTime<Utc>>>::into(system_time)
|
||||||
|
.timestamp()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
FileWithMetadata {
|
FileWithMetadata {
|
||||||
file_name: f.file_name,
|
file_name: f.file_name,
|
||||||
@@ -332,8 +339,13 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
|||||||
// Handle sorting - use helper function that supports EXIF date sorting
|
// Handle sorting - use helper function that supports EXIF date sorting
|
||||||
let sort_type = req.sort.unwrap_or(NameAsc);
|
let sort_type = req.sort.unwrap_or(NameAsc);
|
||||||
let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao");
|
let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao");
|
||||||
let result =
|
let result = apply_sorting_with_exif(
|
||||||
apply_sorting_with_exif(files, sort_type, &mut exif_dao_guard, &span_context, (&app_state.base_path).as_ref());
|
files,
|
||||||
|
sort_type,
|
||||||
|
&mut exif_dao_guard,
|
||||||
|
&span_context,
|
||||||
|
(&app_state.base_path).as_ref(),
|
||||||
|
);
|
||||||
drop(exif_dao_guard);
|
drop(exif_dao_guard);
|
||||||
result
|
result
|
||||||
})
|
})
|
||||||
@@ -476,8 +488,13 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
|||||||
// Handle sorting - use helper function that supports EXIF date sorting
|
// Handle sorting - use helper function that supports EXIF date sorting
|
||||||
let response_files = if let Some(sort_type) = req.sort {
|
let response_files = if let Some(sort_type) = req.sort {
|
||||||
let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao");
|
let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao");
|
||||||
let result =
|
let result = apply_sorting_with_exif(
|
||||||
apply_sorting_with_exif(photos, sort_type, &mut exif_dao_guard, &span_context, (&app_state.base_path).as_ref());
|
photos,
|
||||||
|
sort_type,
|
||||||
|
&mut exif_dao_guard,
|
||||||
|
&span_context,
|
||||||
|
(&app_state.base_path).as_ref(),
|
||||||
|
);
|
||||||
drop(exif_dao_guard);
|
drop(exif_dao_guard);
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ use actix_web::{
|
|||||||
web::{self, BufMut, BytesMut},
|
web::{self, BufMut, BytesMut},
|
||||||
};
|
};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use urlencoding::decode;
|
|
||||||
use diesel::sqlite::Sqlite;
|
use diesel::sqlite::Sqlite;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use urlencoding::decode;
|
||||||
|
|
||||||
use crate::ai::InsightGenerator;
|
use crate::ai::InsightGenerator;
|
||||||
use crate::auth::login;
|
use crate::auth::login;
|
||||||
|
|||||||
Reference in New Issue
Block a user