Compare commits
2 Commits
6fd2478359
...
e833af1ecc
Author | SHA1 | Date | |
---|---|---|---|
|
e833af1ecc | ||
|
bd62068e09 |
12
internal/common/strings.go
Normal file
12
internal/common/strings.go
Normal file
@ -0,0 +1,12 @@
|
||||
package common
|
||||
|
||||
import "strings"
|
||||
|
||||
func Unify(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
s = strings.ToLower(s)
|
||||
for strings.Contains(s, " ") {
|
||||
s = strings.ReplaceAll(s, " ", " ")
|
||||
}
|
||||
return s
|
||||
}
|
@ -1,6 +1,62 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitea.elara.ws/Hazel/music-kraken/internal/common"
|
||||
"github.com/gohugoio/hugo/common"
|
||||
)
|
||||
|
||||
type MusicObject interface {
|
||||
Compile() MusicObject
|
||||
GetIndices() []string
|
||||
Merge(other MusicObject) MusicObject
|
||||
}
|
||||
|
||||
func dedupeMusicObjects[T MusicObject](inputMusicObjects []T) []T {
|
||||
indexMapping := map[string]int{}
|
||||
deduped := []T{}
|
||||
|
||||
for _, musicObject := range inputMusicObjects {
|
||||
musicObject = musicObject.Compile().(T)
|
||||
indices := musicObject.GetIndices()
|
||||
|
||||
// Check if we've seen any of these indices before
|
||||
found := false
|
||||
var existingIndex int
|
||||
|
||||
for _, index := range indices {
|
||||
if idx, exists := indexMapping[index]; exists {
|
||||
found = true
|
||||
existingIndex = idx
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
// Merge with existing object
|
||||
existing := deduped[existingIndex]
|
||||
merged := existing.Merge(musicObject).(T)
|
||||
deduped[existingIndex] = merged
|
||||
|
||||
// Update indices for the merged object
|
||||
newIndices := merged.GetIndices()
|
||||
for _, index := range newIndices {
|
||||
indexMapping[index] = existingIndex
|
||||
}
|
||||
} else {
|
||||
// Add new object
|
||||
deduped = append(deduped, musicObject)
|
||||
newIndex := len(deduped) - 1
|
||||
|
||||
// Register all indices for this object
|
||||
for _, index := range indices {
|
||||
indexMapping[index] = newIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deduped
|
||||
}
|
||||
|
||||
type Song struct {
|
||||
@ -15,6 +71,45 @@ type Song struct {
|
||||
Sources []Source
|
||||
}
|
||||
|
||||
func (m Song) GetIndices() []string {
|
||||
res := sourceIndices(m.Sources)
|
||||
if m.UnifiedName != "" {
|
||||
res = append(res, "name"+m.UnifiedName)
|
||||
}
|
||||
if m.Id != 0 {
|
||||
res = append(res, "id"+strconv.Itoa(m.Id))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m Song) Merge(other MusicObject) MusicObject {
|
||||
otherSong, ok := other.(Song)
|
||||
if !ok {
|
||||
return m
|
||||
}
|
||||
|
||||
if m.Id == 0 && otherSong.Id != 0 {
|
||||
m.Id = otherSong.Id
|
||||
}
|
||||
|
||||
if m.Name == "" && otherSong.Name != "" {
|
||||
m.Name = otherSong.Name
|
||||
m.UnifiedName = otherSong.UnifiedName
|
||||
}
|
||||
|
||||
m.Album = m.Album.Merge(otherSong.Album).(Album)
|
||||
m.Sources = dedupeSources(append(m.Sources, otherSong.Sources...))
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Song) Compile() MusicObject {
|
||||
m.Sources = dedupeSources(m.Sources)
|
||||
m.UnifiedName = common.Unify(m.Name)
|
||||
m.Artists = dedupeMusicObjects(m.Artists)
|
||||
return m
|
||||
}
|
||||
|
||||
type Album struct {
|
||||
Id int
|
||||
|
||||
@ -27,6 +122,47 @@ type Album struct {
|
||||
Sources []Source
|
||||
}
|
||||
|
||||
func (m Album) GetIndices() []string {
|
||||
res := sourceIndices(m.Sources)
|
||||
if m.UnifiedName != "" {
|
||||
res = append(res, "name"+m.UnifiedName)
|
||||
}
|
||||
if m.Id != 0 {
|
||||
res = append(res, "id"+strconv.Itoa(m.Id))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m Album) Merge(other MusicObject) MusicObject {
|
||||
otherAlbum, ok := other.(Album)
|
||||
if !ok {
|
||||
return m
|
||||
}
|
||||
|
||||
if m.Id == 0 && otherAlbum.Id != 0 {
|
||||
m.Id = otherAlbum.Id
|
||||
}
|
||||
|
||||
if m.Name == "" && otherAlbum.Name != "" {
|
||||
m.Name = otherAlbum.Name
|
||||
m.UnifiedName = otherAlbum.UnifiedName
|
||||
}
|
||||
|
||||
m.Songs = dedupeMusicObjects(append(m.Songs, otherAlbum.Songs...))
|
||||
m.Artists = dedupeMusicObjects(append(m.Artists, otherAlbum.Artists...))
|
||||
m.Sources = dedupeSources(append(m.Sources, otherAlbum.Sources...))
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Album) Compile() MusicObject {
|
||||
m.Sources = dedupeSources(m.Sources)
|
||||
m.UnifiedName = common.Unify(m.Name)
|
||||
m.Songs = dedupeMusicObjects(m.Songs)
|
||||
m.Artists = dedupeMusicObjects(m.Artists)
|
||||
return m
|
||||
}
|
||||
|
||||
type Artist struct {
|
||||
Id int
|
||||
|
||||
@ -37,3 +173,41 @@ type Artist struct {
|
||||
|
||||
Sources []Source
|
||||
}
|
||||
|
||||
func (m Artist) Merge(other MusicObject) MusicObject {
|
||||
otherArtist, ok := other.(Artist)
|
||||
if !ok {
|
||||
return m
|
||||
}
|
||||
|
||||
if m.Id == 0 && otherArtist.Id != 0 {
|
||||
m.Id = otherArtist.Id
|
||||
}
|
||||
if m.Name == "" && otherArtist.Name != "" {
|
||||
m.Name = otherArtist.Name
|
||||
m.UnifiedName = otherArtist.UnifiedName
|
||||
}
|
||||
|
||||
m.Albums = dedupeMusicObjects(append(m.Albums, otherArtist.Albums...))
|
||||
m.Sources = dedupeSources(append(m.Sources, otherArtist.Sources...))
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Artist) GetIndices() []string {
|
||||
res := sourceIndices(m.Sources)
|
||||
if m.UnifiedName != "" {
|
||||
res = append(res, "name"+m.UnifiedName)
|
||||
}
|
||||
if m.Id != 0 {
|
||||
res = append(res, "id"+strconv.Itoa(m.Id))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m Artist) Compile() MusicObject {
|
||||
m.Sources = dedupeSources(m.Sources)
|
||||
m.UnifiedName = common.Unify(m.Name)
|
||||
m.Albums = dedupeMusicObjects(m.Albums)
|
||||
return m
|
||||
}
|
||||
|
@ -37,3 +37,38 @@ type Source struct {
|
||||
SourceType *SourceType
|
||||
ObjectType ObjectType
|
||||
}
|
||||
|
||||
func dedupeSources(inputSources []Source) []Source {
|
||||
urlMapping := map[string]int{}
|
||||
|
||||
deduped := []Source{}
|
||||
|
||||
for _, source := range inputSources {
|
||||
if mergeWithIndex, ok := urlMapping[source.Url]; ok {
|
||||
// has to merge current source with source at index
|
||||
if source.ObjectType != "" {
|
||||
deduped[mergeWithIndex].ObjectType = source.ObjectType
|
||||
}
|
||||
if source.SourceType != nil {
|
||||
deduped[mergeWithIndex].SourceType = source.SourceType
|
||||
}
|
||||
|
||||
} else {
|
||||
// just appending
|
||||
urlMapping[source.Url] = len(deduped)
|
||||
deduped = append(deduped, source)
|
||||
}
|
||||
}
|
||||
|
||||
return deduped
|
||||
}
|
||||
|
||||
func sourceIndices(sources []Source) []string {
|
||||
res := []string{}
|
||||
|
||||
for _, source := range sources {
|
||||
res = append(res, "url"+source.Url)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -60,6 +60,10 @@ func compileSource(source data.Source) (data.Source, error) {
|
||||
}
|
||||
|
||||
// find what object this source corresponds to
|
||||
if source.ObjectType != "" {
|
||||
return source, nil
|
||||
}
|
||||
|
||||
sourceType := source.SourceType
|
||||
|
||||
if sourceType.RegexSong.MatchString(source.Url) {
|
||||
@ -80,7 +84,24 @@ func compileSource(source data.Source) (data.Source, error) {
|
||||
return source, errors.New("couldn't find corresponding object source on " + sourceType.Name + " for " + source.Url)
|
||||
}
|
||||
|
||||
func dedupeSources(sources []data.Source) []data.Source {
|
||||
urls := map[string]interface{}{}
|
||||
deduped := []data.Source{}
|
||||
|
||||
for _, raw := range sources {
|
||||
parsed, _ := compileSource(raw)
|
||||
|
||||
if _, u := urls[parsed.Url]; !u {
|
||||
urls[parsed.Url] = true
|
||||
deduped = append(deduped, parsed)
|
||||
}
|
||||
}
|
||||
|
||||
return deduped
|
||||
}
|
||||
|
||||
func Fetch(source data.Source) (data.MusicObject, error) {
|
||||
// the fetch function without the post processing of the music objects
|
||||
source, err := compileSource(source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -92,15 +113,33 @@ func Fetch(source data.Source) (data.MusicObject, error) {
|
||||
}
|
||||
|
||||
if source.ObjectType == data.SongSource {
|
||||
return plugin.FetchSong(source)
|
||||
song, err := plugin.FetchSong(source)
|
||||
|
||||
if err != nil {
|
||||
return song, err
|
||||
}
|
||||
song.Sources = dedupeSources(append(song.Sources, source))
|
||||
return song, nil
|
||||
}
|
||||
|
||||
if source.ObjectType == data.AlbumSource {
|
||||
return plugin.FetchAlbum(source)
|
||||
album, err := plugin.FetchAlbum(source)
|
||||
|
||||
if err != nil {
|
||||
return album, err
|
||||
}
|
||||
album.Sources = dedupeSources(append(album.Sources, source))
|
||||
return album, nil
|
||||
}
|
||||
|
||||
if source.ObjectType == data.ArtistSource {
|
||||
return plugin.FetchArtist(source)
|
||||
artist, err := plugin.FetchArtist(source)
|
||||
|
||||
if err != nil {
|
||||
return artist, err
|
||||
}
|
||||
artist.Sources = dedupeSources(append(artist.Sources, source))
|
||||
return artist, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user