2024-01-16 15:21:35 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
2024-12-18 15:29:16 +00:00
|
|
|
"strconv"
|
2024-01-16 15:21:35 +00:00
|
|
|
"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 {
|
2024-12-18 15:29:16 +00:00
|
|
|
client := subsonic.Client{
|
2024-01-16 15:21:35 +00:00
|
|
|
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
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
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{})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetPlaylist(id string) (*subsonic.Playlist, error) {
|
|
|
|
return c.client.GetPlaylist(id)
|
2024-01-16 15:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) GetArtists() ([]*subsonic.ArtistID3, error) {
|
|
|
|
indexes, err := c.client.GetArtists(map[string]string{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
artists := []*subsonic.ArtistID3{}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
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",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetArtist(id string) (*subsonic.ArtistID3, error) {
|
|
|
|
return c.client.GetArtist(id)
|
2024-01-16 15:21:35 +00:00
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetArtistInfo(id string) (*subsonic.ArtistInfo2, error) {
|
|
|
|
return c.client.GetArtistInfo2(id, map[string]string{
|
2024-01-16 15:21:35 +00:00
|
|
|
"count": "20",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetAlbum(id string) (*subsonic.AlbumID3, error) {
|
|
|
|
return c.client.GetAlbum(id)
|
2024-01-16 15:21:35 +00:00
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetCoverArt(id string) (image.Image, error) {
|
|
|
|
if img := ArtCache.GetImage(id); img != nil {
|
2024-01-16 15:21:35 +00:00
|
|
|
return *img, nil
|
|
|
|
}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
img, err := c.client.GetCoverArt(id, map[string]string{
|
|
|
|
// "size": "64",
|
2024-01-16 15:21:35 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
ArtCache.saveArt(id, img)
|
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
return img, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) GetSimilarSongs(artistID string, maxSongs int) ([]*subsonic.Child, error) {
|
2024-12-18 15:29:16 +00:00
|
|
|
count := strconv.Itoa(maxSongs)
|
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
return c.client.GetSimilarSongs2(artistID, map[string]string{
|
2024-12-18 15:29:16 +00:00
|
|
|
"count": count,
|
2024-01-16 15:21:35 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) Stream(id string) (io.Reader, error) {
|
|
|
|
return c.client.Stream(id, map[string]string{
|
2024-01-16 15:21:35 +00:00
|
|
|
"format": "mp3",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) Scrobble(id string) error {
|
|
|
|
return c.client.Scrobble(id, map[string]string{})
|
2024-01-16 15:21:35 +00:00
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetTopSongs(name string, maxSongs int) ([]*subsonic.Child, error) {
|
|
|
|
count := strconv.Itoa(maxSongs)
|
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
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",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:29:16 +00:00
|
|
|
func (c *Client) GetExperimentalArtistRadio(artistID3 *subsonic.ArtistID3,
|
|
|
|
info *subsonic.ArtistInfo2, maxSongs int,
|
|
|
|
) ([]*subsonic.Child, error) {
|
2024-01-16 15:21:35 +00:00
|
|
|
var wg sync.WaitGroup
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
ID := artistID3.ID
|
2024-01-16 15:21:35 +00:00
|
|
|
similarArtists := info.SimilarArtist
|
|
|
|
songs := []*subsonic.Child{}
|
|
|
|
similarArtistsSongs := 10
|
|
|
|
thisArtistFactor := 3
|
|
|
|
portion := len(info.SimilarArtist) * similarArtistsSongs * thisArtistFactor
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
go func() {
|
|
|
|
s, _ := c.GetSimilarSongs(ID, portion)
|
|
|
|
songs = append(songs, s...)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
wg.Done()
|
|
|
|
}()
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
go func() {
|
2024-12-18 15:29:16 +00:00
|
|
|
s, _ := c.GetTopSongs(artistID3.Name, similarArtistsSongs)
|
2024-01-16 15:21:35 +00:00
|
|
|
songs = append(songs, s...)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
wg.Done()
|
|
|
|
}()
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
common.ShuffleSlice(similarArtists)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
for _, a := range similarArtists {
|
|
|
|
wg.Add(1)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
artist := a
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
go func() {
|
|
|
|
s, _ := c.GetSimilarSongs(artist.ID, similarArtistsSongs)
|
|
|
|
songs = append(songs, s...)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
wg.Done()
|
|
|
|
}()
|
|
|
|
}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
wg.Wait()
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
if maxSongs > len(songs) {
|
|
|
|
maxSongs = len(songs)
|
2024-01-16 15:21:35 +00:00
|
|
|
}
|
2024-12-18 15:29:16 +00:00
|
|
|
|
|
|
|
songs = songs[:maxSongs]
|
2024-01-16 15:21:35 +00:00
|
|
|
common.ShuffleSlice(songs)
|
2024-12-18 15:29:16 +00:00
|
|
|
|
2024-01-16 15:21:35 +00:00
|
|
|
return songs, nil
|
|
|
|
}
|