212 lines
6.3 KiB
Go
212 lines
6.3 KiB
Go
package metadata
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
metadataPb "homelab.lan/music-agregator/gen/metadata/v1"
|
|
"homelab.lan/music-agregator/internal/database"
|
|
)
|
|
|
|
type MetadataService struct {
|
|
client metadataPb.MetadataServiceClient
|
|
artists *database.ArtistRepository
|
|
albums *database.AlbumRepository
|
|
tracks *database.TrackRepository
|
|
}
|
|
|
|
func NewMetadataService(client metadataPb.MetadataServiceClient, db *database.DB) *MetadataService {
|
|
return &MetadataService{
|
|
client: client,
|
|
artists: database.NewArtistRepository(db.Pool),
|
|
albums: database.NewAlbumRepository(db.Pool),
|
|
tracks: database.NewTrackRepository(db.Pool),
|
|
}
|
|
}
|
|
|
|
func (s *MetadataService) GetAlbum(ctx context.Context, albumID string) (*metadataPb.Album, error) {
|
|
resp, err := s.client.GetAlbum(ctx, &metadataPb.GetAlbumRequest{
|
|
Identifier: &metadataPb.GetAlbumRequest_Id{Id: albumID},
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetching album: %w", err)
|
|
}
|
|
|
|
album := resp.GetAlbum()
|
|
|
|
if _, err := s.albums.GetByExternalID(ctx, album.GetId()); err != nil {
|
|
s.PersistArtist(ctx, album, database.Monitored)
|
|
s.PersistAlbum(ctx, album, database.Monitored)
|
|
}
|
|
|
|
return album, nil
|
|
}
|
|
|
|
func (s *MetadataService) GetArtistAlbums(ctx context.Context, artistExternalID string) ([]*metadataPb.Album, error) {
|
|
resp, err := s.client.GetArtistAlbums(ctx, &metadataPb.GetArtistAlbumsRequest{
|
|
ArtistId: artistExternalID,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetching artist albums: %w", err)
|
|
}
|
|
return resp.GetAlbums(), nil
|
|
}
|
|
|
|
func (s *MetadataService) GetAlbumTracks(ctx context.Context, albumExternalID string) ([]*metadataPb.Track, error) {
|
|
resp, err := s.client.GetAlbumTracks(ctx, &metadataPb.GetAlbumTracksRequest{
|
|
AlbumId: albumExternalID,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetching album tracks: %w", err)
|
|
}
|
|
return resp.GetTracks(), nil
|
|
}
|
|
|
|
func (s *MetadataService) GetArtistByExternalID(ctx context.Context, externalID string) (*database.Artist, error) {
|
|
return s.artists.GetByExternalID(ctx, externalID)
|
|
}
|
|
|
|
func (s *MetadataService) GetAlbumByID(ctx context.Context, id string) (*database.Album, error) {
|
|
return s.albums.GetByID(ctx, id)
|
|
}
|
|
|
|
func (s *MetadataService) GetAlbumByExternalID(ctx context.Context, externalID string) (*database.Album, error) {
|
|
return s.albums.GetByExternalID(ctx, externalID)
|
|
}
|
|
|
|
func (s *MetadataService) GetAlbumsByArtistID(ctx context.Context, artistID string) ([]*database.Album, error) {
|
|
return s.albums.GetByArtistID(ctx, artistID)
|
|
}
|
|
|
|
func (s *MetadataService) GetTracksByAlbumID(ctx context.Context, albumID string) ([]*database.Track, error) {
|
|
return s.tracks.GetByAlbumID(ctx, albumID)
|
|
}
|
|
|
|
func (s *MetadataService) SetAlbumMonitorState(ctx context.Context, id string, state database.MonitorState) error {
|
|
return s.albums.SetMonitorState(ctx, id, state)
|
|
}
|
|
|
|
func (s *MetadataService) PersistArtist(ctx context.Context, album *metadataPb.Album, state database.MonitorState) {
|
|
if len(album.GetArtists()) == 0 {
|
|
return
|
|
}
|
|
|
|
artist := album.GetArtists()[0].GetArtist()
|
|
var genres []string
|
|
for _, g := range artist.GetGenres() {
|
|
genres = append(genres, g.GetName())
|
|
}
|
|
|
|
err := s.artists.Create(ctx, &database.Artist{
|
|
ExternalID: artist.GetId(),
|
|
Name: artist.GetName(),
|
|
ArtistType: artist.GetArtistType(),
|
|
Country: artist.GetCountry(),
|
|
Genres: genres,
|
|
ImageURL: artist.GetImageUrl(),
|
|
MonitorState: state,
|
|
})
|
|
if err != nil {
|
|
log.Warn().Err(err).Str("name", artist.GetName()).Msg("failed to persist artist")
|
|
}
|
|
}
|
|
|
|
func (s *MetadataService) PersistAlbum(ctx context.Context, album *metadataPb.Album, state database.MonitorState) {
|
|
s.PersistAlbumForArtist(ctx, album, "", state)
|
|
}
|
|
|
|
func (s *MetadataService) PersistAlbumsForArtist(ctx context.Context, metadataAlbums []*metadataPb.Album, artistDBID string, state database.MonitorState) {
|
|
if len(metadataAlbums) == 0 || artistDBID == "" {
|
|
return
|
|
}
|
|
|
|
dbAlbums := make([]*database.Album, 0, len(metadataAlbums))
|
|
for _, album := range metadataAlbums {
|
|
var genres []string
|
|
for _, g := range album.GetGenres() {
|
|
genres = append(genres, g.GetName())
|
|
}
|
|
labelName := ""
|
|
if album.GetLabel() != nil {
|
|
labelName = album.GetLabel().GetName()
|
|
}
|
|
dbAlbums = append(dbAlbums, &database.Album{
|
|
ExternalID: album.GetId(),
|
|
ArtistID: artistDBID,
|
|
Title: album.GetTitle(),
|
|
AlbumType: album.GetAlbumType(),
|
|
TotalTracks: int(album.GetTotalTracks()),
|
|
TotalDiscs: int(album.GetTotalDiscs()),
|
|
Label: labelName,
|
|
Genres: genres,
|
|
CoverURL: album.GetCoverUrl(),
|
|
MonitorState: state,
|
|
})
|
|
}
|
|
|
|
if err := s.albums.CreateBatch(ctx, dbAlbums); err != nil {
|
|
log.Warn().Err(err).Int("count", len(dbAlbums)).Msg("failed to batch persist albums")
|
|
}
|
|
}
|
|
|
|
func (s *MetadataService) PersistAlbumForArtist(ctx context.Context, album *metadataPb.Album, artistDBID string, state database.MonitorState) {
|
|
if artistDBID == "" {
|
|
if len(album.GetArtists()) > 0 {
|
|
a, err := s.artists.GetByExternalID(ctx, album.GetArtists()[0].GetArtist().GetId())
|
|
if err == nil {
|
|
artistDBID = a.ID
|
|
}
|
|
}
|
|
}
|
|
|
|
if artistDBID == "" {
|
|
log.Trace().Str("album", album.GetTitle()).Msg("skipping album persist, no artist in DB")
|
|
return
|
|
}
|
|
|
|
var genres []string
|
|
for _, g := range album.GetGenres() {
|
|
genres = append(genres, g.GetName())
|
|
}
|
|
|
|
labelName := ""
|
|
if album.GetLabel() != nil {
|
|
labelName = album.GetLabel().GetName()
|
|
}
|
|
|
|
err := s.albums.Create(ctx, &database.Album{
|
|
ExternalID: album.GetId(),
|
|
ArtistID: artistDBID,
|
|
Title: album.GetTitle(),
|
|
AlbumType: album.GetAlbumType(),
|
|
TotalTracks: int(album.GetTotalTracks()),
|
|
TotalDiscs: int(album.GetTotalDiscs()),
|
|
Label: labelName,
|
|
Genres: genres,
|
|
CoverURL: album.GetCoverUrl(),
|
|
MonitorState: state,
|
|
})
|
|
if err != nil {
|
|
log.Warn().Err(err).Str("title", album.GetTitle()).Msg("failed to persist album")
|
|
}
|
|
}
|
|
|
|
func (s *MetadataService) PersistTracks(ctx context.Context, albumDBID string, tracks []*metadataPb.Track) {
|
|
for _, t := range tracks {
|
|
err := s.tracks.Create(ctx, &database.Track{
|
|
ExternalID: t.GetId(),
|
|
AlbumID: albumDBID,
|
|
Title: t.GetTitle(),
|
|
DurationMS: int(t.GetDurationMs()),
|
|
ISRC: t.GetIsrc(),
|
|
DiscNumber: int(t.GetDiscNumber()),
|
|
TrackNumber: int(t.GetTrackNumber()),
|
|
})
|
|
if err != nil {
|
|
log.Warn().Err(err).Str("title", t.GetTitle()).Msg("failed to persist track")
|
|
}
|
|
}
|
|
}
|