package library import ( "fmt" "os" "path/filepath" "github.com/arnef/toni-sync/internal/tonieapi" ) // ScaffoldClient is the subset of tonieapi.Client needed to scaffold a library folder tree. type ScaffoldClient interface { GetHouseholds() ([]tonieapi.Household, error) GetCreativeTonies(householdID string) ([]tonieapi.CreativeTonie, error) } // ScaffoldResult reports what Scaffold did for a single tonie. type ScaffoldResult struct { HouseholdID string TonieID string Name string Folder string Created bool // false if a matching folder already existed and was left untouched } // Scaffold creates the "// [id=]" folder // structure for every household and Kreativ-Tonie on the account. Existing // tonie folders (matched by id, regardless of the current display name) are // left untouched so local audio files are never affected. func Scaffold(client ScaffoldClient, root string) ([]ScaffoldResult, error) { households, err := client.GetHouseholds() if err != nil { return nil, err } var results []ScaffoldResult for _, h := range households { householdPath := filepath.Join(root, h.ID) if err := os.MkdirAll(householdPath, 0o755); err != nil { return nil, fmt.Errorf("creating household folder %s: %w", householdPath, err) } existingByID, err := existingTonieFoldersByID(householdPath) if err != nil { return nil, err } tonies, err := client.GetCreativeTonies(h.ID) if err != nil { return nil, err } for _, t := range tonies { if existingDir, ok := existingByID[t.ID]; ok { results = append(results, ScaffoldResult{ HouseholdID: h.ID, TonieID: t.ID, Name: t.Name, Folder: filepath.Join(householdPath, existingDir), Created: false, }) continue } dirName := DirName(t.Name, t.ID) tonieFolder := filepath.Join(householdPath, dirName) if err := os.MkdirAll(tonieFolder, 0o755); err != nil { return nil, fmt.Errorf("creating tonie folder %s: %w", tonieFolder, err) } results = append(results, ScaffoldResult{ HouseholdID: h.ID, TonieID: t.ID, Name: t.Name, Folder: tonieFolder, Created: true, }) } } return results, nil } // existingTonieFoldersByID maps tonie id -> existing folder name within a household folder. func existingTonieFoldersByID(householdPath string) (map[string]string, error) { entries, err := os.ReadDir(householdPath) if err != nil { return nil, fmt.Errorf("reading household folder %s: %w", householdPath, err) } byID := make(map[string]string) for _, e := range entries { if !e.IsDir() { continue } if _, id, ok := ParseTonieDir(e.Name()); ok { byID[id] = e.Name() } } return byID, nil }