fix(rust): Match Go CLI's album-based export directory structure

Switch from date-based (YYYY/MM-Month) to album-based directory structure
to ensure compatibility with Go CLI. Files now export to AlbumName/ folders
with "Uncategorized" for files without albums.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Manav Rathi
2025-08-27 17:06:40 +05:30
parent 8e3f6e56d2
commit 35ded7bc59

View File

@@ -440,43 +440,23 @@ fn generate_export_path(
metadata: Option<&FileMetadata>,
pub_magic_metadata: Option<&serde_json::Value>,
) -> Result<PathBuf> {
use chrono::{TimeZone, Utc};
// Start with export directory
let mut path = export_dir.to_path_buf();
// Add date-based directory structure (YYYY/MM-MonthName)
// Use updation_time as creation time proxy
let datetime = Utc
.timestamp_micros(file.updation_time)
.single()
.ok_or_else(|| crate::Error::Generic("Invalid timestamp".into()))?;
let year = datetime.format("%Y").to_string();
let month = datetime.format("%m-%B").to_string(); // e.g., "01-January"
path.push(year);
path.push(month);
// Add collection name if available
if let Some(col) = collection
// Match Go CLI structure: export_dir/AlbumName/filename
// Use collection/album name as folder, or "Uncategorized" if none
let album_folder = if let Some(col) = collection
&& let Some(ref name) = col.name
&& !name.is_empty()
&& name != "Uncategorized"
{
// Sanitize collection name for filesystem
let safe_name: String = name
.chars()
.map(|c| match c {
'/' | '\\' | ':' | '*' | '?' | '"' | '<' | '>' | '|' => '_',
c if c.is_control() => '_',
c => c,
})
.collect::<String>()
.trim()
.to_string();
path.push(safe_name);
}
// Sanitize collection name for filesystem (matching Go's approach)
sanitize_album_name(name)
} else {
// Files without a collection go to "Uncategorized" (matching Go CLI)
"Uncategorized".to_string()
};
path.push(album_folder);
// Use filename from public magic metadata (edited name) or regular metadata
let filename = {
@@ -565,6 +545,19 @@ fn sanitize_filename(name: &str) -> String {
.to_string()
}
/// Sanitize an album/collection name for filesystem (matching Go CLI's logic)
fn sanitize_album_name(name: &str) -> String {
// Go CLI replaces : and / with _ in album names
name.chars()
.map(|c| match c {
':' | '/' => '_',
c => c,
})
.collect::<String>()
.trim()
.to_string()
}
/// Decrypt file metadata
fn decrypt_file_metadata(
file: &crate::api::models::File,