scotty/internal/backends/spotifyhistory/archive.go
2025-05-25 12:51:36 +02:00

82 lines
2 KiB
Go

/*
Copyright © 2025 Philipp Wolfer <phw@uploadedlobster.com>
This file is part of Scotty.
Scotty is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.
Scotty is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Scotty. If not, see <https://www.gnu.org/licenses/>.
*/
package spotifyhistory
import (
"errors"
"sort"
"go.uploadedlobster.com/scotty/pkg/archive"
)
var historyFileGlobs = []string{
"Spotify Extended Streaming History/Streaming_History_Audio_*.json",
"Streaming_History_Audio_*.json",
}
// Access a Spotify history archive.
// This can be either the ZIP file as provided by Spotify
// or a directory where this was extracted to.
type HistoryArchive struct {
backend archive.ArchiveReader
}
// Open a Spotify history archive from file path.
func OpenHistoryArchive(path string) (*HistoryArchive, error) {
backend, err := archive.OpenArchive(path)
if err != nil {
return nil, err
}
return &HistoryArchive{backend: backend}, nil
}
func (h *HistoryArchive) GetHistoryFiles() ([]archive.FileInfo, error) {
for _, glob := range historyFileGlobs {
files, err := h.backend.Glob(glob)
if err != nil {
return nil, err
}
if len(files) > 0 {
sort.Slice(files, func(i, j int) bool {
return files[i].Name < files[j].Name
})
return files, nil
}
}
// Found no files, fail
return nil, errors.New("found no history files in archive")
}
func readHistoryFile(f archive.OpenableFile) (StreamingHistory, error) {
file, err := f.Open()
if err != nil {
return nil, err
}
defer file.Close()
history := StreamingHistory{}
err = history.Read(file)
if err != nil {
return nil, err
}
return history, nil
}