feat: Add listenbrainz base url configuration (#1774)

* feat: Add listenbrainz base url configuration

- ListenBrainz.BaseURL config value

* Don't need to store baseUrl

* Use `url.JoinPath` to concatenate url paths

* Replace url.JoinPath (Go 1.19 only) with custom function

Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Andy Klimczak 2022-09-27 21:06:28 -04:00 committed by GitHub
parent cb3ba23fce
commit 2f7a3c5eda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 34 additions and 17 deletions

View File

@ -98,6 +98,7 @@ type spotifyOptions struct {
type listenBrainzOptions struct {
Enabled bool
BaseURL string
}
var (
@ -254,6 +255,7 @@ func init() {
viper.SetDefault("spotify.id", "")
viper.SetDefault("spotify.secret", "")
viper.SetDefault("listenbrainz.enabled", true)
viper.SetDefault("listenbrainz.baseurl", "https://api.listenbrainz.org/1/")
// DevFlags. These are used to enable/disable debugging and incomplete features
viper.SetDefault("devlogsourceline", false)

View File

@ -21,6 +21,7 @@ const (
type listenBrainzAgent struct {
ds model.DataStore
sessionKeys *agents.SessionKeys
baseURL string
client *Client
}
@ -28,12 +29,13 @@ func listenBrainzConstructor(ds model.DataStore) *listenBrainzAgent {
l := &listenBrainzAgent{
ds: ds,
sessionKeys: &agents.SessionKeys{DataStore: ds, KeyName: sessionKeyProperty},
baseURL: conf.Server.ListenBrainz.BaseURL,
}
hc := &http.Client{
Timeout: consts.DefaultHttpClientTimeOut,
}
chc := utils.NewCachedHTTPClient(hc, consts.DefaultHttpClientTimeOut)
l.client = NewClient(chc)
l.client = NewClient(l.baseURL, chc)
return l
}

View File

@ -29,7 +29,7 @@ var _ = Describe("listenBrainzAgent", func() {
_ = ds.UserProps(ctx).Put("user-1", sessionKeyProperty, "SK-1")
httpClient = &tests.FakeHttpClient{}
agent = listenBrainzConstructor(ds)
agent.client = NewClient(httpClient)
agent.client = NewClient("http://localhost:8080", httpClient)
track = &model.MediaFile{
ID: "123",
Title: "Track Title",

View File

@ -8,6 +8,7 @@ import (
"github.com/deluan/rest"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/core/agents"
"github.com/navidrome/navidrome/log"
@ -38,7 +39,7 @@ func NewRouter(ds model.DataStore) *Router {
hc := &http.Client{
Timeout: consts.DefaultHttpClientTimeOut,
}
r.client = NewClient(hc)
r.client = NewClient(conf.Server.ListenBrainz.BaseURL, hc)
return r
}

View File

@ -24,7 +24,7 @@ var _ = Describe("ListenBrainz Auth Router", func() {
BeforeEach(func() {
sk = &fakeSessionKeys{KeyName: sessionKeyProperty}
httpClient = &tests.FakeHttpClient{}
cl := NewClient(httpClient)
cl := NewClient("http://localhost/", httpClient)
r = Router{
sessionKeys: sk,
client: cl,

View File

@ -6,14 +6,12 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"path"
"github.com/navidrome/navidrome/log"
)
const (
apiBaseUrl = "https://api.listenbrainz.org/1/"
)
type listenBrainzError struct {
Code int
Message string
@ -27,12 +25,13 @@ type httpDoer interface {
Do(req *http.Request) (*http.Response, error)
}
func NewClient(hc httpDoer) *Client {
return &Client{hc}
func NewClient(baseURL string, hc httpDoer) *Client {
return &Client{baseURL, hc}
}
type Client struct {
hc httpDoer
baseURL string
hc httpDoer
}
type listenBrainzResponse struct {
@ -128,9 +127,22 @@ func (c *Client) Scrobble(ctx context.Context, apiKey string, li listenInfo) err
return nil
}
func (c *Client) path(endpoint string) (string, error) {
u, err := url.Parse(c.baseURL)
if err != nil {
return "", err
}
u.Path = path.Join(u.Path, endpoint)
return u.String(), nil
}
func (c *Client) makeRequest(method string, endpoint string, r *listenBrainzRequest) (*listenBrainzResponse, error) {
b, _ := json.Marshal(r.Body)
req, _ := http.NewRequest(method, apiBaseUrl+endpoint, bytes.NewBuffer(b))
uri, err := c.path(endpoint)
if err != nil {
return nil, err
}
req, _ := http.NewRequest(method, uri, bytes.NewBuffer(b))
if r.ApiKey != "" {
req.Header.Add("Authorization", fmt.Sprintf("Token %s", r.ApiKey))

View File

@ -18,7 +18,7 @@ var _ = Describe("Client", func() {
var client *Client
BeforeEach(func() {
httpClient = &tests.FakeHttpClient{}
client = NewClient(httpClient)
client = NewClient("BASE_URL/", httpClient)
})
Describe("listenBrainzResponse", func() {
@ -48,7 +48,7 @@ var _ = Describe("Client", func() {
_, err := client.ValidateToken(context.Background(), "LB-TOKEN")
Expect(err).ToNot(HaveOccurred())
Expect(httpClient.SavedRequest.Method).To(Equal(http.MethodGet))
Expect(httpClient.SavedRequest.URL.String()).To(Equal(apiBaseUrl + "validate-token"))
Expect(httpClient.SavedRequest.URL.String()).To(Equal("BASE_URL/validate-token"))
Expect(httpClient.SavedRequest.Header.Get("Authorization")).To(Equal("Token LB-TOKEN"))
})
@ -86,7 +86,7 @@ var _ = Describe("Client", func() {
It("formats the request properly", func() {
Expect(client.UpdateNowPlaying(context.Background(), "LB-TOKEN", li)).To(Succeed())
Expect(httpClient.SavedRequest.Method).To(Equal(http.MethodPost))
Expect(httpClient.SavedRequest.URL.String()).To(Equal(apiBaseUrl + "submit-listens"))
Expect(httpClient.SavedRequest.URL.String()).To(Equal("BASE_URL/submit-listens"))
Expect(httpClient.SavedRequest.Header.Get("Authorization")).To(Equal("Token LB-TOKEN"))
body, _ := io.ReadAll(httpClient.SavedRequest.Body)
@ -103,7 +103,7 @@ var _ = Describe("Client", func() {
It("formats the request properly", func() {
Expect(client.Scrobble(context.Background(), "LB-TOKEN", li)).To(Succeed())
Expect(httpClient.SavedRequest.Method).To(Equal(http.MethodPost))
Expect(httpClient.SavedRequest.URL.String()).To(Equal(apiBaseUrl + "submit-listens"))
Expect(httpClient.SavedRequest.URL.String()).To(Equal("BASE_URL/submit-listens"))
Expect(httpClient.SavedRequest.Header.Get("Authorization")).To(Equal("Token LB-TOKEN"))
body, _ := io.ReadAll(httpClient.SavedRequest.Body)

View File

@ -100,7 +100,7 @@ func checkExternalCredentials() {
if !conf.Server.ListenBrainz.Enabled {
log.Info("ListenBrainz integration is DISABLED")
} else {
log.Debug("ListenBrainz integration is ENABLED")
log.Debug("ListenBrainz integration is ENABLED", "ListenBrainz.BaseURL", conf.Server.ListenBrainz.BaseURL)
}
if conf.Server.Spotify.ID == "" || conf.Server.Spotify.Secret == "" {