Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update create time when remote does not have one #183

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cmd/upload/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ func (ai *AssetIndex) ReIndex() {
ai.byID = map[string]*immich.Asset{}

for _, a := range ai.assets {
ext := path.Ext(a.OriginalPath)
ID := fmt.Sprintf("%s-%d", strings.ToUpper(path.Base(a.OriginalFileName)+ext), a.ExifInfo.FileSizeInByte)
ID := fmt.Sprintf("%s-%d", strings.ToUpper(path.Base(a.OriginalFileName)), a.ExifInfo.FileSizeInByte)
l := ai.byHash[a.Checksum]
l = append(l, a)
ai.byHash[a.Checksum] = l

n := a.OriginalFileName + ext
n := a.OriginalFileName
l = ai.byName[n]
l = append(l, a)
ai.byName[n] = l
Expand Down
35 changes: 34 additions & 1 deletion cmd/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ func (app *UpCmd) handleAsset(ctx context.Context, a *browser.LocalAssetFile) er
app.journalAsset(a, logger.INFO, willBeAddedToAlbum+app.PartnerAlbum)
app.AddToAlbum(advice.ServerAsset.ID, app.PartnerAlbum)
}
case LocalMetadataBetter:
app.journalAsset(a, logger.LocalMetadataBetter, advice.Message)
app.UpdateAsset(ctx, advice.ServerAsset, a)
}

if err != nil {
Expand Down Expand Up @@ -560,6 +563,19 @@ func (app *UpCmd) UploadAsset(ctx context.Context, a *browser.LocalAssetFile) (s
return resp.ID, nil
}

func (app *UpCmd) UpdateAsset(ctx context.Context, s *immich.Asset, l *browser.LocalAssetFile) error {
var err error = nil
if !app.DryRun {
_, err = app.Immich.UpdateAsset(ctx, s.ID, l)
}

if err != nil {
app.journalAsset(l, logger.ServerError, err.Error())
}

return err
}

func (app *UpCmd) albumName(al browser.LocalAlbum) string {
Name := al.Name
if app.GooglePhotos {
Expand Down Expand Up @@ -689,6 +705,7 @@ const (
IDontKnow AdviceCode = iota
SmallerOnServer
BetterOnServer
LocalMetadataBetter
SameOnServer
NotOnServer
)
Expand Down Expand Up @@ -747,6 +764,14 @@ func (ai *AssetIndex) adviceNotOnServer() *Advice {
}
}

func (ai *AssetIndex) adviceLocalMetadataBetter(sa *immich.Asset, la *browser.LocalAssetFile) *Advice {
return &Advice{
Advice: LocalMetadataBetter,
Message: fmt.Sprintf("An asset with the same name:%q exists, but local metadata is better (local date: %q, server date: %q)", sa.OriginalFileName, la.DateTaken.Format(time.DateTime), sa.ExifInfo.DateTimeOriginal.Format(time.DateTime)),
ServerAsset: sa,
}
}

// ShouldUpload check if the server has this asset
//
// The server may have different assets with the same name. This happens with photos produced by digital cameras.
Expand All @@ -761,9 +786,17 @@ func (ai *AssetIndex) ShouldUpload(la *browser.LocalAssetFile) (*Advice, error)
ID := la.DeviceAssetID()

sa := ai.byID[ID]

if sa != nil {
// the same ID exist on the server
return ai.adviceSameOnServer(sa), nil
// logic here is *older* is almost certinally better than newer timestamps, because
// if a file is missing a timestamp, it will be replaced with the download timestamp
// (in the case of Photos Takeout) or upload timestamp (otherwise), which has to be after the take date
if compareDate(la.DateTaken, sa.ExifInfo.DateTimeOriginal.Time) < 0 {
return ai.adviceLocalMetadataBetter(sa, la), nil
} else {
return ai.adviceSameOnServer(sa), nil
}
}

var l []*immich.Asset
Expand Down
26 changes: 15 additions & 11 deletions immich/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,21 +226,25 @@ func (ic *ImmichClient) UpdateAssets(ctx context.Context, ids []string,

func (ic *ImmichClient) UpdateAsset(ctx context.Context, id string, a *browser.LocalAssetFile) (*Asset, error) {
type updAsset struct {
IsArchived bool `json:"isArchived"`
IsFavorite bool `json:"isFavorite"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Description string `json:"description,omitempty"`
DateTimeOriginal string `json:"dateTimeOriginal"`
IDs []string `json:"ids"`
IsArchived bool `json:"isArchived"`
IsFavorite bool `json:"isFavorite"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Description string `json:"description,omitempty"`
}
param := updAsset{
Description: a.Description,
IsArchived: a.Archived,
IsFavorite: a.Favorite,
Latitude: a.Latitude,
Longitude: a.Longitude,
DateTimeOriginal: a.DateTaken.Format(time.RFC3339),
IDs: []string{id},
Description: a.Description,
IsArchived: a.Archived,
IsFavorite: a.Favorite,
Latitude: a.Latitude,
Longitude: a.Longitude,
}
r := Asset{}
err := ic.newServerCall(ctx, "updateAsset").do(put("/asset/"+id, setJSONBody(param)), responseJSON(&r))
err := ic.newServerCall(ctx, "updateAsset").do(put("/asset/", setJSONBody(param)), responseJSON(&r))
return &r, err
}

Expand Down
42 changes: 22 additions & 20 deletions logger/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,27 @@ type Journal struct {
type Action string

const (
DiscoveredFile Action = "File"
ScannedImage Action = "Scanned image"
ScannedVideo Action = "Scanned video"
Discarded Action = "Discarded"
Uploaded Action = "Uploaded"
Upgraded Action = "Server's asset upgraded"
ERROR Action = "Error"
LocalDuplicate Action = "Local duplicate"
ServerDuplicate Action = "Server has photo"
Stacked Action = "Stacked"
ServerBetter Action = "Server's asset is better"
Album Action = "Added to an album"
LivePhoto Action = "Live photo"
FailedVideo Action = "Failed video"
Unsupported Action = "File type not supported"
Metadata Action = "Metadata files"
AssociatedMetadata Action = "Associated with metadata"
INFO Action = "Info"
NotSelected Action = "Not selected because options"
ServerError Action = "Server error"
DiscoveredFile Action = "File"
ScannedImage Action = "Scanned image"
ScannedVideo Action = "Scanned video"
Discarded Action = "Discarded"
Uploaded Action = "Uploaded"
Upgraded Action = "Server's asset upgraded"
ERROR Action = "Error"
LocalDuplicate Action = "Local duplicate"
ServerDuplicate Action = "Server has photo"
Stacked Action = "Stacked"
ServerBetter Action = "Server's asset is better"
LocalMetadataBetter Action = "Server's asset is identical, but better local metadata"
Album Action = "Added to an album"
LivePhoto Action = "Live photo"
FailedVideo Action = "Failed video"
Unsupported Action = "File type not supported"
Metadata Action = "Metadata files"
AssociatedMetadata Action = "Associated with metadata"
INFO Action = "Info"
NotSelected Action = "Not selected because options"
ServerError Action = "Server error"
)

func NewJournal(log Logger) *Journal {
Expand Down Expand Up @@ -89,6 +90,7 @@ func (j *Journal) Report() {
j.Log.OK("%6d uploaded files on the server", j.counts[Uploaded])
j.Log.OK("%6d upgraded files on the server", j.counts[Upgraded])
j.Log.OK("%6d files already on the server", j.counts[ServerDuplicate])
j.Log.OK("%6d files adready on the server, but updated create time", j.counts[LocalMetadataBetter])
j.Log.OK("%6d discarded files because of options", j.counts[NotSelected])
j.Log.OK("%6d discarded files because duplicated in the input", j.counts[LocalDuplicate])
j.Log.OK("%6d discarded files because server has a better image", j.counts[ServerBetter])
Expand Down