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.
Koito/internal/importer/koito.go

176 lines
5.0 KiB

package importer
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"path"
"strings"
"github.com/gabehf/koito/internal/cfg"
"github.com/gabehf/koito/internal/db"
"github.com/gabehf/koito/internal/export"
"github.com/gabehf/koito/internal/logger"
"github.com/gabehf/koito/internal/models"
"github.com/gabehf/koito/internal/utils"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
)
func ImportKoitoFile(ctx context.Context, store db.DB, filename string) error {
l := logger.FromContext(ctx)
l.Info().Msgf("Beginning Koito import on file: %s", filename)
data := new(export.KoitoExport)
f, err := os.Open(path.Join(cfg.ConfigDir(), "import", filename))
if err != nil {
return fmt.Errorf("ImportKoitoFile: os.Open: %w", err)
}
defer f.Close()
err = json.NewDecoder(f).Decode(data)
if err != nil {
return fmt.Errorf("ImportKoitoFile: Decode: %w", err)
}
if data.Version != "1" {
return fmt.Errorf("ImportKoitoFile: unupported version: %s", data.Version)
}
l.Info().Msgf("Beginning data import for user: %s", data.User)
count := 0
for i := range data.Listens {
// use this for save/get mbid for all artist/album/track
var mbid uuid.UUID
artistIds := make([]int32, 0)
for _, ia := range data.Listens[i].Artists {
mbid = uuid.Nil
if ia.MBID != nil {
mbid = *ia.MBID
}
artist, err := store.GetArtist(ctx, db.GetArtistOpts{
MusicBrainzID: mbid,
Name: getPrimaryAliasFromAliasSlice(ia.Aliases),
})
if errors.Is(err, pgx.ErrNoRows) {
var imgid = uuid.Nil
// not a perfect way to check if the image url is an actual source vs manual upload but
// im like 99% sure it will work perfectly
if strings.HasPrefix(ia.ImageUrl, "http") {
imgid = uuid.New()
}
// save artist
artist, err := store.SaveArtist(ctx, db.SaveArtistOpts{
Name: getPrimaryAliasFromAliasSlice(ia.Aliases),
Image: imgid,
ImageSrc: ia.ImageUrl,
MusicBrainzID: mbid,
Aliases: utils.FlattenAliases(ia.Aliases),
})
if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
artistIds = append(artistIds, artist.ID)
} else if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
} else {
artistIds = append(artistIds, artist.ID)
}
}
// call associate album
albumId := int32(0)
mbid = uuid.Nil
if data.Listens[i].Album.MBID != nil {
mbid = *data.Listens[i].Album.MBID
}
album, err := store.GetAlbum(ctx, db.GetAlbumOpts{
MusicBrainzID: mbid,
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Album.Aliases),
ArtistID: artistIds[0],
})
if errors.Is(err, pgx.ErrNoRows) {
var imgid = uuid.Nil
// not a perfect way to check if the image url is an actual source vs manual upload but
// im like 99% sure it will work perfectly
if strings.HasPrefix(data.Listens[i].Album.ImageUrl, "http") {
imgid = uuid.New()
}
// save album
album, err = store.SaveAlbum(ctx, db.SaveAlbumOpts{
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Album.Aliases),
Image: imgid,
ImageSrc: data.Listens[i].Album.ImageUrl,
MusicBrainzID: mbid,
Aliases: utils.FlattenAliases(data.Listens[i].Album.Aliases),
ArtistIDs: artistIds,
VariousArtists: data.Listens[i].Album.VariousArtists,
})
if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
albumId = album.ID
} else if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
} else {
albumId = album.ID
}
// call associate track
mbid = uuid.Nil
if data.Listens[i].Track.MBID != nil {
mbid = *data.Listens[i].Track.MBID
}
track, err := store.GetTrack(ctx, db.GetTrackOpts{
MusicBrainzID: mbid,
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Track.Aliases),
ArtistIDs: artistIds,
})
if errors.Is(err, pgx.ErrNoRows) {
// save track
track, err = store.SaveTrack(ctx, db.SaveTrackOpts{
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Track.Aliases),
RecordingMbzID: mbid,
Duration: int32(data.Listens[i].Track.Duration),
ArtistIDs: artistIds,
AlbumID: albumId,
})
if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
// save track aliases
err = store.SaveTrackAliases(ctx, track.ID, utils.FlattenAliases(data.Listens[i].Track.Aliases), "Import")
if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
} else if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
// save listen
err = store.SaveListen(ctx, db.SaveListenOpts{
TrackID: track.ID,
Time: data.Listens[i].ListenedAt,
UserID: 1,
})
if err != nil {
return fmt.Errorf("ImportKoitoFile: %w", err)
}
l.Info().Msgf("ImportKoitoFile: Imported listen for track %s", track.Title)
count++
}
return finishImport(ctx, filename, count)
}
func getPrimaryAliasFromAliasSlice(aliases []models.Alias) string {
for _, a := range aliases {
if a.Primary {
return a.Alias
}
}
return ""
}