package client import ( "image" "io" "net/http" "strconv" "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 { 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) { count := strconv.Itoa(maxSongs) return c.client.GetSimilarSongs2(artistID, map[string]string{ "count": count, }) } 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, maxSongs int) ([]*subsonic.Child, error) { count := strconv.Itoa(maxSongs) 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, maxSongs 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(1) go func() { s, _ := c.GetSimilarSongs(ID, portion) songs = append(songs, s...) wg.Done() }() wg.Add(1) 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 maxSongs > len(songs) { maxSongs = len(songs) } songs = songs[:maxSongs] common.ShuffleSlice(songs) return songs, nil }