subsonic-tui/internal/client/client.go
Sagi Dayan a4d4c49de9
initial commit
Signed-off-by: Sagi Dayan <sagidayan@gmail.com>
2024-12-14 23:37:05 +02:00

163 lines
3.7 KiB
Go

package client
import (
"fmt"
"image"
"io"
"net/http"
"sync"
"git.dayanhub.com/sagi/subsonic-tui/internal/common"
"github.com/delucks/go-subsonic"
)
type Client struct {
client subsonic.Client
}
func NewClient(baseURL string) *Client {
var client subsonic.Client = subsonic.Client{
Client: &http.Client{},
ClientName: "subsonic-tui",
BaseUrl: baseURL,
PasswordAuth: true,
}
return &Client{
client: client,
}
}
func (c *Client) Authenticate(username, password string) error {
c.client.User = username
return c.client.Authenticate(password)
}
func (c *Client) GetUser() (*subsonic.User, error) {
return c.client.GetUser(c.client.User)
}
func (c *Client) GetPlaylists() ([]*subsonic.Playlist, error) {
return c.client.GetPlaylists(map[string]string{})
}
func (c *Client) GetPlaylist(ID string) (*subsonic.Playlist, error) {
return c.client.GetPlaylist(ID)
}
func (c *Client) GetArtists() ([]*subsonic.ArtistID3, error) {
indexes, err := c.client.GetArtists(map[string]string{})
if err != nil {
return nil, err
}
artists := []*subsonic.ArtistID3{}
for _, i := range indexes.Index {
artists = append(artists, i.Artist...)
}
return artists, nil
}
func (c *Client) GetAlbums() ([]*subsonic.AlbumID3, error) {
return c.client.GetAlbumList2("alphabeticalByName", map[string]string{
"size": "500",
})
}
func (c *Client) GetArtist(ID string) (*subsonic.ArtistID3, error) {
return c.client.GetArtist(ID)
}
func (c *Client) GetArtistInfo(ID string) (*subsonic.ArtistInfo2, error) {
return c.client.GetArtistInfo2(ID, map[string]string{
"count": "20",
})
}
func (c *Client) GetAlbum(ID string) (*subsonic.AlbumID3, error) {
return c.client.GetAlbum(ID)
}
func (c *Client) GetCoverArt(ID string) (image.Image, error) {
if img := ArtCache.GetImage(ID); img != nil {
return *img, nil
}
img, err := c.client.GetCoverArt(ID, map[string]string{
//"size": "64",
})
if err != nil {
return nil, err
}
ArtCache.saveArt(ID, img)
return img, err
}
func (c *Client) GetSimilarSongs(artistID string, maxSongs int) ([]*subsonic.Child, error) {
max := fmt.Sprintf("%d", maxSongs)
return c.client.GetSimilarSongs2(artistID, map[string]string{
"count": max,
})
}
func (c *Client) Stream(ID string) (io.Reader, error) {
return c.client.Stream(ID, map[string]string{
"format": "mp3",
})
}
func (c *Client) Scrobble(ID string) error {
return c.client.Scrobble(ID, map[string]string{})
}
func (c *Client) GetTopSongs(name string, max int) ([]*subsonic.Child, error) {
count := fmt.Sprintf("%d", max)
return c.client.GetTopSongs(name, map[string]string{
"count": count,
})
}
func (c *Client) Search(query string) (*subsonic.SearchResult3, error) {
return c.client.Search3(query, map[string]string{
"artistCount": "20",
"songCount": "20",
"albumCount": "20",
})
}
func (c *Client) GetExperimentalArtistRadio(artistId3 *subsonic.ArtistID3, info *subsonic.ArtistInfo2, max int) ([]*subsonic.Child, error) {
var wg sync.WaitGroup
ID := artistId3.ID
similarArtists := info.SimilarArtist
songs := []*subsonic.Child{}
similarArtistsSongs := 10
thisArtistFactor := 3
portion := len(info.SimilarArtist) * similarArtistsSongs * thisArtistFactor
wg.Add(2)
go func() {
s, _ := c.GetSimilarSongs(ID, portion)
songs = append(songs, s...)
wg.Done()
}()
go func() {
s, _ := c.GetTopSongs(artistId3.Name, similarArtistsSongs)
songs = append(songs, s...)
wg.Done()
}()
common.ShuffleSlice(similarArtists)
for _, a := range similarArtists {
wg.Add(1)
artist := a
go func() {
s, _ := c.GetSimilarSongs(artist.ID, similarArtistsSongs)
songs = append(songs, s...)
wg.Done()
}()
}
wg.Wait()
if max > len(songs) {
max = len(songs)
}
songs = songs[:max]
common.ShuffleSlice(songs)
return songs, nil
}