From 18a3bcc5141c97e25dc46fd125ea072152e3c42a Mon Sep 17 00:00:00 2001 From: chyroc Date: Fri, 29 Dec 2023 14:41:48 +0800 Subject: [PATCH] Fix: Use AssetDate as photo created time --- icloud-photo-cli/command/command_download.go | 19 ++++++++++++++++++- internal/photo_asset.go | 20 +++++++++++++++++--- internal/photo_asset_download.go | 4 ++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/icloud-photo-cli/command/command_download.go b/icloud-photo-cli/command/command_download.go index 6b07488..e79940b 100644 --- a/icloud-photo-cli/command/command_download.go +++ b/icloud-photo-cli/command/command_download.go @@ -361,11 +361,28 @@ func (r *downloadCommand) downloadPhotoAssetInternal(photo *icloudgo.PhotoAsset, tmpPath := photo.LocalPath(filepath.Join(r.Output, ".tmp"), icloudgo.PhotoVersionOriginal, r.FileStructure, livePhoto) path := photo.LocalPath(outputDir, icloudgo.PhotoVersionOriginal, r.FileStructure, livePhoto) name := path[len(r.Output):] + + oldOutputDir := photo.OldOutputDir(r.Output, r.FolderStructure) + oldPath := photo.LocalPath(oldOutputDir, icloudgo.PhotoVersionOriginal, r.FileStructure, livePhoto) + if err := os.MkdirAll(outputDir, os.ModePerm); err != nil { fmt.Printf("[icloudgo] [download] [%s] mkdir '%s' output dir: '%s' failed: %s\n", pickReason, photo.Filename(livePhoto), outputDir, err) return false, err } + // 如果 old 存在, 直接移动到新目录 + if oldPath != path { + if f, _ := os.Stat(oldPath); f != nil { + if err := os.Rename(oldPath, path); err != nil { + fmt.Printf("[icloudgo] [download] [%s] compatible with wrong photo time for '%s' failed: %s\n", pickReason, name, err) + return false, err + } else { + fmt.Printf("[icloudgo] [download] [%s] compatible with wrong photo time for '%s' success\n", pickReason, name) + fmt.Printf("%s -> %s\n", oldPath, path) + } + } + } + if f, _ := os.Stat(path); f != nil { if photo.Size() != int(f.Size()) { return false, r.downloadTo(pickReason, photo, livePhoto, tmpPath, path, name) @@ -502,7 +519,7 @@ func newAssertQueue(data []*icloudgo.PhotoAsset) *assertQueue { recentAssets := []*icloudgo.PhotoAsset{} oldAssets := []*icloudgo.PhotoAsset{} for _, v := range data { - if v.Created().Before(twoDaysAge) { + if v.AssetDate().Before(twoDaysAge) { oldAssets = append(oldAssets, v) } else { recentAssets = append(recentAssets, v) diff --git a/internal/photo_asset.go b/internal/photo_asset.go index b1a4c93..464f70e 100644 --- a/internal/photo_asset.go +++ b/internal/photo_asset.go @@ -103,17 +103,31 @@ func (r *PhotoAsset) FormatSize() string { return formatSize(r.Size()) } -func (r *PhotoAsset) Created() time.Time { +func (r *PhotoAsset) AddDate() time.Time { return time.UnixMilli(r._masterRecord.Created.Timestamp) } +func (r *PhotoAsset) AssetDate() time.Time { + return time.UnixMilli(r._assetRecord.Fields.AssetDate.Value) +} + func (r *PhotoAsset) OutputDir(output, folderStructure string) string { if folderStructure == "" || folderStructure == "/" { return output } - createdFolderName := r.Created().Format(folderStructure) - return filepath.Join(output, createdFolderName) + assetDate := r.AssetDate().Format(folderStructure) + return filepath.Join(output, assetDate) +} + +// 仅为兼容性 +func (r *PhotoAsset) OldOutputDir(output, folderStructure string) string { + if folderStructure == "" || folderStructure == "/" { + return output + } + + assetDate := r.AddDate().Format(folderStructure) + return filepath.Join(output, assetDate) } func formatSize(size int) string { diff --git a/internal/photo_asset_download.go b/internal/photo_asset_download.go index de243f8..38d03c4 100644 --- a/internal/photo_asset_download.go +++ b/internal/photo_asset_download.go @@ -40,8 +40,8 @@ func (r *PhotoAsset) DownloadTo(version PhotoVersion, livePhoto bool, target str } // 1676381385791 to time.time - created := r.Created() - if err := os.Chtimes(target, created, created); err != nil { + assetDate := r.AssetDate() + if err := os.Chtimes(target, assetDate, assetDate); err != nil { return fmt.Errorf("change file time error: %v", err) }