ente/cli/pkg/remote_to_disk_album.go
2024-03-01 12:39:01 +05:30

138 lines
4.2 KiB
Go

package pkg
import (
"context"
"encoding/json"
"fmt"
"github.com/ente-io/cli/pkg/model"
"github.com/ente-io/cli/pkg/model/export"
"log"
"os"
"strings"
"path/filepath"
)
func (c *ClICtrl) createLocalFolderForRemoteAlbums(ctx context.Context, account model.Account) error {
path := account.ExportDir
albums, err := c.getRemoteAlbums(ctx)
if err != nil {
return err
}
userID := ctx.Value("user_id").(int64)
folderToMetaMap, albumIDToMetaMap, err := readFolderMetadata(path)
if err != nil {
return err
}
for _, album := range albums {
if album.IsDeleted {
if meta, ok := albumIDToMetaMap[album.ID]; ok {
log.Printf("Deleting album %s as it is deleted", meta.AlbumName)
if err = os.RemoveAll(filepath.Join(path, meta.FolderName)); err != nil {
return err
}
delete(folderToMetaMap, meta.FolderName)
delete(albumIDToMetaMap, meta.ID)
}
continue
}
metaByID := albumIDToMetaMap[album.ID]
if metaByID != nil {
if strings.EqualFold(metaByID.AlbumName, album.AlbumName) {
//log.Printf("Skipping album %s as it already exists", album.AlbumName)
continue
}
}
albumFolderName := filepath.Clean(album.AlbumName)
// replace : with _
albumFolderName = strings.ReplaceAll(albumFolderName, ":", "_")
albumFolderName = strings.ReplaceAll(albumFolderName, "/", "_")
albumFolderName = strings.TrimSpace(albumFolderName)
albumID := album.ID
if _, ok := folderToMetaMap[albumFolderName]; ok {
for i := 1; ; i++ {
newAlbumName := fmt.Sprintf("%s_%d", albumFolderName, i)
if _, ok := folderToMetaMap[newAlbumName]; !ok {
albumFolderName = newAlbumName
break
}
}
}
// Create album and meta folders if they don't exist
albumPath := filepath.Clean(filepath.Join(path, albumFolderName))
metaPath := filepath.Join(albumPath, ".meta")
if metaByID == nil {
log.Printf("Adding folder %s for album %s", albumFolderName, album.AlbumName)
for _, p := range []string{albumPath, metaPath} {
if _, err := os.Stat(p); os.IsNotExist(err) {
if err = os.Mkdir(p, 0755); err != nil {
return err
}
}
}
} else {
// rename meta.FolderName to albumFolderName
oldAlbumPath := filepath.Join(path, metaByID.FolderName)
log.Printf("Renaming path from %s to %s for album %s", oldAlbumPath, albumPath, album.AlbumName)
if err = os.Rename(oldAlbumPath, albumPath); err != nil {
return err
}
}
// Handle meta file
metaFilePath := filepath.Join(path, albumFolderName, albumMetaFolder, albumMetaFile)
metaData := export.AlbumMetadata{
ID: album.ID,
OwnerID: album.OwnerID,
AlbumName: album.AlbumName,
IsDeleted: album.IsDeleted,
AccountOwnerIDs: []int64{userID},
FolderName: albumFolderName,
}
if err = writeJSONToFile(metaFilePath, metaData); err != nil {
return err
}
folderToMetaMap[albumFolderName] = &metaData
albumIDToMetaMap[albumID] = &metaData
}
return nil
}
// readFolderMetadata returns a map of folder name to album metadata for all folders in the given path
// and a map of album ID to album metadata for all albums in the given path.
func readFolderMetadata(path string) (map[string]*export.AlbumMetadata, map[int64]*export.AlbumMetadata, error) {
result := make(map[string]*export.AlbumMetadata)
albumIdToMetadataMap := make(map[int64]*export.AlbumMetadata)
// Read the top-level directories in the given path
entries, err := os.ReadDir(path)
if err != nil {
return nil, nil, err
}
for _, entry := range entries {
if entry.IsDir() {
dirName := entry.Name()
metaFilePath := filepath.Join(path, dirName, albumMetaFolder, albumMetaFile)
// Initialize as nil, will remain nil if JSON file is not found or not readable
result[dirName] = nil
// Read the JSON file if it exists
if _, err := os.Stat(metaFilePath); err == nil {
var metaData export.AlbumMetadata
metaDataBytes, err := os.ReadFile(metaFilePath)
if err != nil {
continue // Skip this entry if reading fails
}
if err := json.Unmarshal(metaDataBytes, &metaData); err == nil {
metaData.FolderName = dirName
result[dirName] = &metaData
albumIdToMetadataMap[metaData.ID] = &metaData
}
}
}
}
return result, albumIdToMetadataMap, nil
}