Files
supersonic/backend/mediaprovider/jellyfin/searchall.go
T

148 lines
3.7 KiB
Go

package jellyfin
import (
"strings"
"sync"
"github.com/deluan/sanitize"
"github.com/dweymouth/go-jellyfin"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/backend/mediaprovider/helpers"
"github.com/dweymouth/supersonic/sharedutil"
)
func (j *jellyfinMediaProvider) SearchAll(searchQuery string, maxResults int) ([]*mediaprovider.SearchResult, error) {
limit := maxResults / 3
var wg sync.WaitGroup
var albums []*jellyfin.Album
var artists []*jellyfin.Artist
var songs []*jellyfin.Song
var genres []jellyfin.NameID
var playlists []*jellyfin.Playlist
var opts jellyfin.QueryOpts
opts.Paging.Limit = limit
opts.Filter.ParentID = j.currentLibraryID
wg.Add(1)
go func() {
albumResult, _ := j.client.Search(searchQuery, jellyfin.TypeAlbum, opts)
albums = albumResult.Albums
wg.Done()
}()
wg.Add(1)
go func() {
artistResult, _ := j.client.Search(searchQuery, jellyfin.TypeArtist, opts)
artists = artistResult.Artists
wg.Done()
}()
wg.Add(1)
go func() {
songResult, _ := j.client.Search(searchQuery, jellyfin.TypeSong, opts)
songs = songResult.Songs
wg.Done()
}()
querySanitized := strings.ToLower(sanitize.Accents(searchQuery))
queryLowerWords := strings.Fields(querySanitized)
wg.Add(1)
go func() {
p, e := j.client.GetPlaylists()
if e == nil {
playlists = sharedutil.FilterSlice(p, func(p *jellyfin.Playlist) bool {
return helpers.AllTermsMatch(strings.ToLower(sanitize.Accents(p.Name)), queryLowerWords)
})
}
wg.Done()
}()
wg.Add(1)
go func() {
g, e := j.client.GetGenres(jellyfin.Paging{}, "")
if e == nil {
genres = sharedutil.FilterSlice(g, func(g jellyfin.NameID) bool {
return helpers.AllTermsMatch(strings.ToLower(sanitize.Accents(g.Name)), queryLowerWords)
})
}
wg.Done()
}()
wg.Wait()
results := j.mergeResults(albums, artists, songs, playlists, genres)
helpers.RankSearchResults(results, searchQuery, queryLowerWords)
return results, nil
}
func (j *jellyfinMediaProvider) mergeResults(
albums []*jellyfin.Album,
artists []*jellyfin.Artist,
songs []*jellyfin.Song,
matchingPlaylists []*jellyfin.Playlist,
matchingGenres []jellyfin.NameID,
) []*mediaprovider.SearchResult {
var results []*mediaprovider.SearchResult
getArtistNames := func(artist jellyfin.NameID) string {
return artist.Name
}
for _, al := range albums {
results = append(results, &mediaprovider.SearchResult{
Type: mediaprovider.ContentTypeAlbum,
ID: al.ID,
CoverID: al.ID,
Name: al.Name,
ArtistName: strings.Join(sharedutil.MapSlice(al.Artists, getArtistNames), ","),
Size: al.ChildCount,
Item: toAlbum(al),
})
}
for _, ar := range artists {
results = append(results, &mediaprovider.SearchResult{
Type: mediaprovider.ContentTypeArtist,
ID: ar.ID,
CoverID: ar.ID,
Name: ar.Name,
Size: ar.AlbumCount,
Item: toArtist(ar),
})
}
for _, tr := range songs {
results = append(results, &mediaprovider.SearchResult{
Type: mediaprovider.ContentTypeTrack,
ID: tr.Id,
CoverID: tr.Id,
Name: tr.Name,
ArtistName: strings.Join(sharedutil.MapSlice(tr.Artists, getArtistNames), ","),
Size: int(tr.RunTimeTicks / 10_000_000),
Item: toTrack(tr),
})
}
for _, pl := range matchingPlaylists {
results = append(results, &mediaprovider.SearchResult{
Type: mediaprovider.ContentTypePlaylist,
ID: pl.ID,
CoverID: pl.ID,
Name: pl.Name,
Size: pl.SongCount,
Item: j.toPlaylist(pl),
})
}
for _, g := range matchingGenres {
results = append(results, &mediaprovider.SearchResult{
Type: mediaprovider.ContentTypeGenre,
ID: g.Name,
Name: g.Name,
Size: -1,
})
}
return results
}