package database import ( "context" "fmt" "log" "strconv" "sync" "time" "git.yetaga.in/alazyreader/library/media" "github.com/irlndts/go-discogs" ) type DiscogsCache struct { authToken string m sync.Mutex cache []media.Record maxCacheAge time.Duration lastRefresh time.Time client discogs.Discogs username string } func NewDiscogsCache(token string, maxCacheAge time.Duration, username string) (*DiscogsCache, error) { client, err := discogs.New(&discogs.Options{ UserAgent: "library.yetaga.in personal collection cache", Token: token, }) if err != nil { return nil, err } return &DiscogsCache{ authToken: token, client: client, maxCacheAge: maxCacheAge, username: username, }, nil } func (c *DiscogsCache) FlushCache(ctx context.Context) error { c.m.Lock() defer c.m.Unlock() records, err := c.fetchRecords(ctx, nil) c.cache = records c.lastRefresh = time.Now() return err } func (c *DiscogsCache) GetAllRecords(ctx context.Context) ([]media.Record, error) { c.m.Lock() defer c.m.Unlock() if time.Now().After(c.lastRefresh.Add(c.maxCacheAge)) { records, err := c.fetchRecords(ctx, nil) c.cache = records c.lastRefresh = time.Now() return c.cache, err } return c.cache, nil } func (c *DiscogsCache) fetchRecords(ctx context.Context, pagination *discogs.Pagination) ([]media.Record, error) { records := []media.Record{} if pagination == nil { pagination = getPagination(0) } log.Printf("calling discogs API, page %v", pagination.Page) coll, err := c.client.CollectionItemsByFolder(c.username, 0, pagination) if err != nil { return records, fmt.Errorf("error loading collection: %w", err) } for i := range coll.Items { records = append(records, collectionItemToRecord(&coll.Items[i])) } // recurse down the list if coll.Pagination.URLs.Next != "" { coll, err := c.fetchRecords(ctx, getPagination(pagination.Page+1)) if err != nil { return records, err } records = append(records, coll...) } return records, nil } func getPagination(page int) *discogs.Pagination { return &discogs.Pagination{Page: page, Sort: "added", SortOrder: "asc", PerPage: 100} } func collectionItemToRecord(item *discogs.CollectionItemSource) media.Record { artists := []string{} for _, artist := range item.BasicInformation.Artists { artists = append(artists, artist.Name) } year := strconv.Itoa(item.BasicInformation.Year) if year == "0" { year = "" } return media.Record{ ID: item.ID, AlbumName: item.BasicInformation.Title, Artists: artists, Identifier: item.BasicInformation.Labels[0].Catno, Format: item.BasicInformation.Formats[0].Name, Genre: item.BasicInformation.Genres[0], Label: item.BasicInformation.Labels[0].Name, Year: year, CoverURL: item.BasicInformation.CoverImage, DiscogsURL: fmt.Sprintf("https://www.discogs.com/release/%v", item.ID), } }