mirror of https://github.com/gabehf/Koito.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.8 KiB
121 lines
3.8 KiB
package catalog
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/gabehf/koito/internal/db"
|
|
"github.com/gabehf/koito/internal/logger"
|
|
"github.com/gabehf/koito/internal/mbz"
|
|
"github.com/gabehf/koito/internal/models"
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
type AssociateTrackOpts struct {
|
|
ArtistIDs []int32
|
|
AlbumID int32
|
|
TrackMbzID uuid.UUID
|
|
TrackName string
|
|
Duration int32
|
|
Mbzc mbz.MusicBrainzCaller
|
|
}
|
|
|
|
func AssociateTrack(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*models.Track, error) {
|
|
l := logger.FromContext(ctx)
|
|
if opts.TrackName == "" {
|
|
return nil, errors.New("AssociateTrack: missing required parameter 'opts.TrackName'")
|
|
}
|
|
if len(opts.ArtistIDs) < 1 {
|
|
return nil, errors.New("AssociateTrack: at least one artist id must be specified")
|
|
}
|
|
if opts.AlbumID == 0 {
|
|
return nil, errors.New("AssociateTrack: release group id must be specified")
|
|
}
|
|
// first, try to match track Mbz ID
|
|
if opts.TrackMbzID != uuid.Nil {
|
|
l.Debug().Msgf("Associating track '%s' by MusicBrainz recording ID", opts.TrackName)
|
|
return matchTrackByMbzID(ctx, d, opts)
|
|
} else {
|
|
l.Debug().Msgf("Associating track '%s' by title and artist", opts.TrackName)
|
|
return matchTrackByTitleAndArtist(ctx, d, opts)
|
|
}
|
|
}
|
|
|
|
// If no match is found, will call matchTrackByTitleAndArtist and associate the Mbz ID with the result
|
|
func matchTrackByMbzID(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*models.Track, error) {
|
|
l := logger.FromContext(ctx)
|
|
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
|
MusicBrainzID: opts.TrackMbzID,
|
|
})
|
|
if err == nil {
|
|
l.Debug().Msgf("Found track '%s' by MusicBrainz ID", track.Title)
|
|
return track, nil
|
|
} else if !errors.Is(err, pgx.ErrNoRows) {
|
|
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
|
} else {
|
|
l.Debug().Msgf("Track '%s' could not be found by MusicBrainz ID", opts.TrackName)
|
|
track, err := matchTrackByTitleAndArtist(ctx, d, opts)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
|
}
|
|
l.Debug().Msgf("Updating track '%s' with MusicBrainz ID %s", opts.TrackName, opts.TrackMbzID)
|
|
err = d.UpdateTrack(ctx, db.UpdateTrackOpts{
|
|
ID: track.ID,
|
|
MusicBrainzID: opts.TrackMbzID,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
|
}
|
|
track.MbzID = &opts.TrackMbzID
|
|
return track, nil
|
|
}
|
|
}
|
|
|
|
func matchTrackByTitleAndArtist(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*models.Track, error) {
|
|
l := logger.FromContext(ctx)
|
|
// try provided track title
|
|
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
|
Title: opts.TrackName,
|
|
ArtistIDs: opts.ArtistIDs,
|
|
})
|
|
if err == nil {
|
|
l.Debug().Msgf("Track '%s' found by title and artist match", track.Title)
|
|
return track, nil
|
|
} else if !errors.Is(err, pgx.ErrNoRows) {
|
|
return nil, fmt.Errorf("matchTrackByTitleAndArtist: %w", err)
|
|
} else {
|
|
if opts.TrackMbzID != uuid.Nil {
|
|
mbzTrack, err := opts.Mbzc.GetTrack(ctx, opts.TrackMbzID)
|
|
if err == nil {
|
|
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
|
Title: mbzTrack.Title,
|
|
ArtistIDs: opts.ArtistIDs,
|
|
})
|
|
if err == nil {
|
|
l.Debug().Msgf("Track '%s' found by MusicBrainz title and artist match", opts.TrackName)
|
|
return track, nil
|
|
}
|
|
}
|
|
}
|
|
l.Debug().Msgf("Track '%s' could not be found by title and artist match", opts.TrackName)
|
|
t, err := d.SaveTrack(ctx, db.SaveTrackOpts{
|
|
RecordingMbzID: opts.TrackMbzID,
|
|
AlbumID: opts.AlbumID,
|
|
Title: opts.TrackName,
|
|
ArtistIDs: opts.ArtistIDs,
|
|
Duration: opts.Duration,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("matchTrackByTitleAndArtist: %w", err)
|
|
}
|
|
if opts.TrackMbzID == uuid.Nil {
|
|
l.Info().Msgf("Created track '%s' with title and artist", opts.TrackName)
|
|
} else {
|
|
l.Info().Msgf("Created track '%s' with MusicBrainz Recording ID", opts.TrackName)
|
|
}
|
|
return t, nil
|
|
}
|
|
}
|