This commit is contained in:
Tomas Dvorak
2026-01-26 08:13:18 +01:00
parent aa036b6550
commit dfc079288f
505 changed files with 95755 additions and 5712 deletions
+86 -5
View File
@@ -8,6 +8,7 @@ import (
"net/url"
"os"
"path/filepath"
"sort"
"strings"
"time"
@@ -208,16 +209,57 @@ func (gc *GalleryController) FetchAlbum(c *gin.Context) {
var albums []ZoneramaAlbum
if data, err := os.ReadFile(albumsFile); err == nil {
_ = json.Unmarshal(data, &albums)
// Primary: try parsing as a plain array (expected format)
if err := json.Unmarshal(data, &albums); err != nil || len(albums) == 0 {
// Fallback: some older/miswritten caches might be an object {"albums": [...]}
var alt struct {
Albums []ZoneramaAlbum `json:"albums"`
}
if err2 := json.Unmarshal(data, &alt); err2 == nil && len(alt.Albums) > 0 {
albums = alt.Albums
} else if err != nil {
// If we failed to parse completely, refuse to overwrite to prevent data loss
logger.Error("Failed to parse existing zonerama_albums.json: %v", err)
c.JSON(http.StatusConflict, gin.H{"error": "Albums cache is invalid; refusing to overwrite to prevent data loss"})
return
}
}
}
// Check if album already exists and update it, or add new
found := false
for i, a := range albums {
if a.ID == albumData.ID {
albums[i] = albumData
// Reuse existing album if it already has more photos (avoid shrinking due to low photo_limit)
if len(a.Photos) >= len(albumData.Photos) {
logger.Info("Reusing existing album (kept %d photos vs fetched %d): %s", len(a.Photos), len(albumData.Photos), albumData.ID)
// Optionally refresh fetched timestamp
if strings.TrimSpace(a.FetchedAt) == "" {
a.FetchedAt = albumData.FetchedAt
}
albums[i] = a
} else {
// Merge: prefer non-empty fields from new data
merged := a
if strings.TrimSpace(albumData.Title) != "" {
merged.Title = albumData.Title
}
if strings.TrimSpace(albumData.URL) != "" {
merged.URL = albumData.URL
}
if strings.TrimSpace(albumData.Date) != "" {
merged.Date = albumData.Date
}
if albumData.ViewsCount > 0 {
merged.ViewsCount = albumData.ViewsCount
}
merged.PhotosCount = albumData.PhotosCount
merged.Photos = albumData.Photos
merged.FetchedAt = albumData.FetchedAt
albums[i] = merged
logger.Info("Updated existing album with more photos: %s (now %d)", albumData.ID, len(merged.Photos))
}
found = true
logger.Info("Updated existing album: %s", albumData.ID)
break
}
}
@@ -227,7 +269,41 @@ func (gc *GalleryController) FetchAlbum(c *gin.Context) {
logger.Info("Added new album: %s", albumData.ID)
}
// Save back to file
// Keep albums ordered by album date (desc), fallback to fetched_at
parseDate := func(s string) time.Time {
s = strings.TrimSpace(s)
if s == "" {
return time.Time{}
}
if t, err := time.Parse("2006-01-02", s); err == nil {
return t
}
if t, err := time.Parse("02.01.2006", s); err == nil {
return t
}
return time.Time{}
}
sort.Slice(albums, func(i, j int) bool {
di := parseDate(albums[i].Date)
dj := parseDate(albums[j].Date)
if !di.Equal(dj) {
return di.After(dj)
}
// Fallback to fetched_at if dates are equal/unavailable
var fi, fj time.Time
if t, err := time.Parse(time.RFC3339, strings.TrimSpace(albums[i].FetchedAt)); err == nil {
fi = t
}
if t, err := time.Parse(time.RFC3339, strings.TrimSpace(albums[j].FetchedAt)); err == nil {
fj = t
}
if !fi.Equal(fj) {
return fi.After(fj)
}
return strings.Compare(albums[i].ID, albums[j].ID) > 0
})
// Save back to file (atomic write)
if err := os.MkdirAll(filepath.Dir(albumsFile), 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create cache directory"})
return
@@ -239,10 +315,15 @@ func (gc *GalleryController) FetchAlbum(c *gin.Context) {
return
}
if err := os.WriteFile(albumsFile, albumsJSON, 0644); err != nil {
tmp := albumsFile + ".tmp"
if err := os.WriteFile(tmp, albumsJSON, 0644); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save albums"})
return
}
if err := os.Rename(tmp, albumsFile); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to finalize album save"})
return
}
logger.Info("Album %s saved successfully with %d photos", albumData.ID, len(albumData.Photos))