mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-30 05:37:05 +02:00
Code style: All uppercase acronyms URL, ISRC, ID, HTTP
This commit is contained in:
parent
39b31fc664
commit
d51c97c648
26 changed files with 137 additions and 137 deletions
|
@ -27,7 +27,7 @@ type OAuth2Authenticator interface {
|
|||
models.Backend
|
||||
|
||||
// Returns OAuth2 config suitable for this backend
|
||||
OAuth2Strategy(redirectUrl *url.URL) OAuth2Strategy
|
||||
OAuth2Strategy(redirectURL *url.URL) OAuth2Strategy
|
||||
|
||||
// Setup the OAuth2 client
|
||||
OAuth2Setup(token oauth2.TokenSource) error
|
||||
|
|
|
@ -24,14 +24,14 @@ import (
|
|||
type OAuth2Strategy interface {
|
||||
Config() oauth2.Config
|
||||
|
||||
AuthCodeURL(verifier string, state string) AuthUrl
|
||||
AuthCodeURL(verifier string, state string) AuthURL
|
||||
|
||||
ExchangeToken(code CodeResponse, verifier string) (*oauth2.Token, error)
|
||||
}
|
||||
|
||||
type AuthUrl struct {
|
||||
type AuthURL struct {
|
||||
// The URL the user must visit to approve access
|
||||
Url string
|
||||
URL string
|
||||
// Random state string passed on to the callback.
|
||||
// Leave empty if the service does not support state.
|
||||
State string
|
||||
|
@ -56,10 +56,10 @@ func (s StandardStrategy) Config() oauth2.Config {
|
|||
return s.conf
|
||||
}
|
||||
|
||||
func (s StandardStrategy) AuthCodeURL(verifier string, state string) AuthUrl {
|
||||
func (s StandardStrategy) AuthCodeURL(verifier string, state string) AuthURL {
|
||||
url := s.conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier))
|
||||
return AuthUrl{
|
||||
Url: url,
|
||||
return AuthURL{
|
||||
URL: url,
|
||||
State: state,
|
||||
Param: "code",
|
||||
}
|
||||
|
|
|
@ -33,10 +33,10 @@ func (s deezerStrategy) Config() oauth2.Config {
|
|||
return s.conf
|
||||
}
|
||||
|
||||
func (s deezerStrategy) AuthCodeURL(verifier string, state string) auth.AuthUrl {
|
||||
func (s deezerStrategy) AuthCodeURL(verifier string, state string) auth.AuthURL {
|
||||
url := s.conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier))
|
||||
return auth.AuthUrl{
|
||||
Url: url,
|
||||
return auth.AuthURL{
|
||||
URL: url,
|
||||
State: state,
|
||||
Param: "code",
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ const MaxItemsPerGet = 1000
|
|||
const DefaultRateLimitWaitSeconds = 5
|
||||
|
||||
type Client struct {
|
||||
HttpClient *resty.Client
|
||||
HTTPClient *resty.Client
|
||||
token oauth2.TokenSource
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func NewClient(token oauth2.TokenSource) Client {
|
|||
client.SetHeader("User-Agent", version.UserAgent())
|
||||
client.SetRetryCount(5)
|
||||
return Client{
|
||||
HttpClient: client,
|
||||
HTTPClient: client,
|
||||
token: token,
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func (c Client) setToken(req *resty.Request) error {
|
|||
}
|
||||
|
||||
func listRequest[T Result](c Client, path string, offset int, limit int) (result T, err error) {
|
||||
request := c.HttpClient.R().
|
||||
request := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"index": strconv.Itoa(offset),
|
||||
"limit": strconv.Itoa(limit),
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestGetUserHistory(t *testing.T) {
|
|||
|
||||
token := oauth2.StaticTokenSource(&oauth2.Token{})
|
||||
client := deezer.NewClient(token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.deezer.com/user/me/history",
|
||||
"testdata/user-history.json")
|
||||
|
||||
|
@ -65,7 +65,7 @@ func TestGetUserTracks(t *testing.T) {
|
|||
|
||||
token := oauth2.StaticTokenSource(&oauth2.Token{})
|
||||
client := deezer.NewClient(token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.deezer.com/user/me/tracks",
|
||||
"testdata/user-tracks.json")
|
||||
|
||||
|
@ -81,7 +81,7 @@ func TestGetUserTracks(t *testing.T) {
|
|||
assert.Equal("Outland", track1.Track.Album.Title)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
|
||||
type DeezerApiBackend struct {
|
||||
client Client
|
||||
clientId string
|
||||
clientID string
|
||||
clientSecret string
|
||||
}
|
||||
|
||||
|
@ -50,19 +50,19 @@ func (b *DeezerApiBackend) Options() []models.BackendOption {
|
|||
}
|
||||
|
||||
func (b *DeezerApiBackend) InitConfig(config *config.ServiceConfig) error {
|
||||
b.clientId = config.GetString("client-id")
|
||||
b.clientID = config.GetString("client-id")
|
||||
b.clientSecret = config.GetString("client-secret")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *DeezerApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy {
|
||||
func (b *DeezerApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy {
|
||||
conf := oauth2.Config{
|
||||
ClientID: b.clientId,
|
||||
ClientID: b.clientID,
|
||||
ClientSecret: b.clientSecret,
|
||||
Scopes: []string{
|
||||
"offline_access,basic_access,listening_history",
|
||||
},
|
||||
RedirectURL: redirectUrl.String(),
|
||||
RedirectURL: redirectURL.String(),
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: "https://connect.deezer.com/oauth/auth.php",
|
||||
TokenURL: "https://connect.deezer.com/oauth/access_token.php",
|
||||
|
@ -244,8 +244,8 @@ func (t Track) AsTrack() models.Track {
|
|||
info["music_service"] = "deezer.com"
|
||||
info["origin_url"] = t.Link
|
||||
info["deezer_id"] = t.Link
|
||||
info["deezer_album_id"] = fmt.Sprintf("https://www.deezer.com/album/%v", t.Album.Id)
|
||||
info["deezer_artist_id"] = fmt.Sprintf("https://www.deezer.com/artist/%v", t.Artist.Id)
|
||||
info["deezer_album_id"] = fmt.Sprintf("https://www.deezer.com/album/%v", t.Album.ID)
|
||||
info["deezer_artist_id"] = fmt.Sprintf("https://www.deezer.com/artist/%v", t.Artist.ID)
|
||||
|
||||
return track
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ type HistoryResult struct {
|
|||
}
|
||||
|
||||
type Track struct {
|
||||
Id int `json:"id"`
|
||||
ID int `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Link string `json:"link"`
|
||||
Title string `json:"title"`
|
||||
|
@ -75,7 +75,7 @@ type LovedTrack struct {
|
|||
}
|
||||
|
||||
type Album struct {
|
||||
Id int `json:"id"`
|
||||
ID int `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Link string `json:"link"`
|
||||
Title string `json:"title"`
|
||||
|
@ -83,7 +83,7 @@ type Album struct {
|
|||
}
|
||||
|
||||
type Artist struct {
|
||||
Id int `json:"id"`
|
||||
ID int `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Link string `json:"link"`
|
||||
Name string `json:"name"`
|
||||
|
|
|
@ -33,13 +33,13 @@ import (
|
|||
const MaxItemsPerGet = 50
|
||||
|
||||
type Client struct {
|
||||
HttpClient *resty.Client
|
||||
HTTPClient *resty.Client
|
||||
token string
|
||||
}
|
||||
|
||||
func NewClient(serverUrl string, token string) Client {
|
||||
func NewClient(serverURL string, token string) Client {
|
||||
client := resty.New()
|
||||
client.SetBaseURL(serverUrl)
|
||||
client.SetBaseURL(serverURL)
|
||||
client.SetAuthScheme("Bearer")
|
||||
client.SetAuthToken(token)
|
||||
client.SetHeader("Accept", "application/json")
|
||||
|
@ -49,14 +49,14 @@ func NewClient(serverUrl string, token string) Client {
|
|||
ratelimit.EnableHTTPHeaderRateLimit(client, "Retry-After")
|
||||
|
||||
return Client{
|
||||
HttpClient: client,
|
||||
HTTPClient: client,
|
||||
token: token,
|
||||
}
|
||||
}
|
||||
|
||||
func (c Client) GetHistoryListenings(user string, page int, perPage int) (result ListeningsResult, err error) {
|
||||
const path = "/api/v1/history/listenings"
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"username": user,
|
||||
"page": strconv.Itoa(page),
|
||||
|
@ -75,7 +75,7 @@ func (c Client) GetHistoryListenings(user string, page int, perPage int) (result
|
|||
|
||||
func (c Client) GetFavoriteTracks(page int, perPage int) (result FavoriteTracksResult, err error) {
|
||||
const path = "/api/v1/favorites/tracks"
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"page": strconv.Itoa(page),
|
||||
"page_size": strconv.Itoa(perPage),
|
||||
|
|
|
@ -32,20 +32,20 @@ import (
|
|||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
serverUrl := "https://funkwhale.example.com"
|
||||
serverURL := "https://funkwhale.example.com"
|
||||
token := "foobar123"
|
||||
client := funkwhale.NewClient(serverUrl, token)
|
||||
assert.Equal(t, serverUrl, client.HttpClient.BaseURL)
|
||||
assert.Equal(t, token, client.HttpClient.Token)
|
||||
client := funkwhale.NewClient(serverURL, token)
|
||||
assert.Equal(t, serverURL, client.HTTPClient.BaseURL)
|
||||
assert.Equal(t, token, client.HTTPClient.Token)
|
||||
}
|
||||
|
||||
func TestGetHistoryListenings(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
serverUrl := "https://funkwhale.example.com"
|
||||
serverURL := "https://funkwhale.example.com"
|
||||
token := "thetoken"
|
||||
client := funkwhale.NewClient(serverUrl, token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
client := funkwhale.NewClient(serverURL, token)
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://funkwhale.example.com/api/v1/history/listenings",
|
||||
"testdata/listenings.json")
|
||||
|
||||
|
@ -67,9 +67,9 @@ func TestGetFavoriteTracks(t *testing.T) {
|
|||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
token := "thetoken"
|
||||
serverUrl := "https://funkwhale.example.com"
|
||||
client := funkwhale.NewClient(serverUrl, token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
serverURL := "https://funkwhale.example.com"
|
||||
client := funkwhale.NewClient(serverURL, token)
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://funkwhale.example.com/api/v1/favorites/tracks",
|
||||
"testdata/favorite-tracks.json")
|
||||
|
||||
|
@ -87,7 +87,7 @@ func TestGetFavoriteTracks(t *testing.T) {
|
|||
assert.Equal("phw", fav1.User.UserName)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
|
||||
|
|
|
@ -31,7 +31,7 @@ type ListeningsResult struct {
|
|||
}
|
||||
|
||||
type Listening struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
User User `json:"user"`
|
||||
Track Track `json:"track"`
|
||||
CreationDate string `json:"creation_date"`
|
||||
|
@ -45,14 +45,14 @@ type FavoriteTracksResult struct {
|
|||
}
|
||||
|
||||
type FavoriteTrack struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
User User `json:"user"`
|
||||
Track Track `json:"track"`
|
||||
CreationDate string `json:"creation_date"`
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
Artist Artist `json:"artist"`
|
||||
Album Album `json:"album"`
|
||||
Title string `json:"title"`
|
||||
|
@ -64,13 +64,13 @@ type Track struct {
|
|||
}
|
||||
|
||||
type Artist struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
Name string `json:"name"`
|
||||
ArtistMBID mbtypes.MBID `json:"mbid"`
|
||||
}
|
||||
|
||||
type Album struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
Title string `json:"title"`
|
||||
AlbumArtist Artist `json:"artist"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
|
@ -79,7 +79,7 @@ type Album struct {
|
|||
}
|
||||
|
||||
type User struct {
|
||||
Id int `json:"int"`
|
||||
ID int `json:"int"`
|
||||
UserName string `json:"username"`
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ func (b *JSPFBackend) InitConfig(config *config.ServiceConfig) error {
|
|||
Identifier: config.GetString("identifier"),
|
||||
Tracks: make([]jspf.Track, 0),
|
||||
Extension: map[string]any{
|
||||
jspf.MusicBrainzPlaylistExtensionId: jspf.MusicBrainzPlaylistExtension{
|
||||
jspf.MusicBrainzPlaylistExtensionID: jspf.MusicBrainzPlaylistExtension{
|
||||
LastModifiedAt: time.Now(),
|
||||
Public: true,
|
||||
},
|
||||
|
@ -116,7 +116,7 @@ func listenAsTrack(l models.Listen) jspf.Track {
|
|||
extension := makeMusicBrainzExtension(l.Track)
|
||||
extension.AddedAt = l.ListenedAt
|
||||
extension.AddedBy = l.UserName
|
||||
track.Extension[jspf.MusicBrainzTrackExtensionId] = extension
|
||||
track.Extension[jspf.MusicBrainzTrackExtensionID] = extension
|
||||
|
||||
if l.RecordingMBID != "" {
|
||||
track.Identifier = append(track.Identifier, "https://musicbrainz.org/recording/"+string(l.RecordingMBID))
|
||||
|
@ -131,7 +131,7 @@ func loveAsTrack(l models.Love) jspf.Track {
|
|||
extension := makeMusicBrainzExtension(l.Track)
|
||||
extension.AddedAt = l.Created
|
||||
extension.AddedBy = l.UserName
|
||||
track.Extension[jspf.MusicBrainzTrackExtensionId] = extension
|
||||
track.Extension[jspf.MusicBrainzTrackExtensionID] = extension
|
||||
|
||||
recordingMBID := l.Track.RecordingMBID
|
||||
if l.RecordingMBID != "" {
|
||||
|
|
|
@ -25,21 +25,21 @@ import (
|
|||
|
||||
type lastfmStrategy struct {
|
||||
client *lastfm.Api
|
||||
redirectUrl *url.URL
|
||||
redirectURL *url.URL
|
||||
}
|
||||
|
||||
func (s lastfmStrategy) Config() oauth2.Config {
|
||||
return oauth2.Config{}
|
||||
}
|
||||
|
||||
func (s lastfmStrategy) AuthCodeURL(verifier string, state string) auth.AuthUrl {
|
||||
func (s lastfmStrategy) AuthCodeURL(verifier string, state string) auth.AuthURL {
|
||||
// Last.fm does not use OAuth2, but the provided authorization flow with
|
||||
// callback URL is close enough we can shoehorn it into the existing
|
||||
// authentication strategy.
|
||||
// TODO: Investigate and use callback-less flow with api.GetAuthTokenUrl(token)
|
||||
url := s.client.GetAuthRequestUrl(s.redirectUrl.String())
|
||||
return auth.AuthUrl{
|
||||
Url: url,
|
||||
url := s.client.GetAuthRequestUrl(s.redirectURL.String())
|
||||
return auth.AuthURL{
|
||||
URL: url,
|
||||
State: "", // last.fm does not use state
|
||||
Param: "token",
|
||||
}
|
||||
|
|
|
@ -62,9 +62,9 @@ func (b *LastfmApiBackend) Options() []models.BackendOption {
|
|||
}
|
||||
|
||||
func (b *LastfmApiBackend) InitConfig(config *config.ServiceConfig) error {
|
||||
clientId := config.GetString("client-id")
|
||||
clientID := config.GetString("client-id")
|
||||
clientSecret := config.GetString("client-secret")
|
||||
b.client = lastfm.New(clientId, clientSecret)
|
||||
b.client = lastfm.New(clientID, clientSecret)
|
||||
b.username = config.GetString("username")
|
||||
return nil
|
||||
}
|
||||
|
@ -72,10 +72,10 @@ func (b *LastfmApiBackend) InitConfig(config *config.ServiceConfig) error {
|
|||
func (b *LastfmApiBackend) StartImport() error { return nil }
|
||||
func (b *LastfmApiBackend) FinishImport() error { return nil }
|
||||
|
||||
func (b *LastfmApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy {
|
||||
func (b *LastfmApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy {
|
||||
return lastfmStrategy{
|
||||
client: b.client,
|
||||
redirectUrl: redirectUrl,
|
||||
redirectURL: redirectURL,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ const (
|
|||
)
|
||||
|
||||
type Client struct {
|
||||
HttpClient *resty.Client
|
||||
HTTPClient *resty.Client
|
||||
MaxResults int
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ func NewClient(token string) Client {
|
|||
ratelimit.EnableHTTPHeaderRateLimit(client, "X-RateLimit-Reset-In")
|
||||
|
||||
return Client{
|
||||
HttpClient: client,
|
||||
HTTPClient: client,
|
||||
MaxResults: DefaultItemsPerGet,
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func NewClient(token string) Client {
|
|||
func (c Client) GetListens(user string, maxTime time.Time, minTime time.Time) (result GetListensResult, err error) {
|
||||
const path = "/user/{username}/listens"
|
||||
errorResult := ErrorResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetPathParam("username", user).
|
||||
SetQueryParams(map[string]string{
|
||||
"max_ts": strconv.FormatInt(maxTime.Unix(), 10),
|
||||
|
@ -84,7 +84,7 @@ func (c Client) GetListens(user string, maxTime time.Time, minTime time.Time) (r
|
|||
func (c Client) SubmitListens(listens ListenSubmission) (result StatusResult, err error) {
|
||||
const path = "/submit-listens"
|
||||
errorResult := ErrorResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetBody(listens).
|
||||
SetResult(&result).
|
||||
SetError(&errorResult).
|
||||
|
@ -100,7 +100,7 @@ func (c Client) SubmitListens(listens ListenSubmission) (result StatusResult, er
|
|||
func (c Client) GetFeedback(user string, status int, offset int) (result GetFeedbackResult, err error) {
|
||||
const path = "/feedback/user/{username}/get-feedback"
|
||||
errorResult := ErrorResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetPathParam("username", user).
|
||||
SetQueryParams(map[string]string{
|
||||
"status": strconv.Itoa(status),
|
||||
|
@ -122,7 +122,7 @@ func (c Client) GetFeedback(user string, status int, offset int) (result GetFeed
|
|||
func (c Client) SendFeedback(feedback Feedback) (result StatusResult, err error) {
|
||||
const path = "/feedback/recording-feedback"
|
||||
errorResult := ErrorResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetBody(feedback).
|
||||
SetResult(&result).
|
||||
SetError(&errorResult).
|
||||
|
@ -138,7 +138,7 @@ func (c Client) SendFeedback(feedback Feedback) (result StatusResult, err error)
|
|||
func (c Client) Lookup(recordingName string, artistName string) (result LookupResult, err error) {
|
||||
const path = "/metadata/lookup"
|
||||
errorResult := ErrorResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"recording_name": recordingName,
|
||||
"artist_name": artistName,
|
||||
|
|
|
@ -36,7 +36,7 @@ import (
|
|||
func TestNewClient(t *testing.T) {
|
||||
token := "foobar123"
|
||||
client := listenbrainz.NewClient(token)
|
||||
assert.Equal(t, token, client.HttpClient.Token)
|
||||
assert.Equal(t, token, client.HTTPClient.Token)
|
||||
assert.Equal(t, listenbrainz.DefaultItemsPerGet, client.MaxResults)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ func TestGetListens(t *testing.T) {
|
|||
|
||||
client := listenbrainz.NewClient("thetoken")
|
||||
client.MaxResults = 2
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.listenbrainz.org/1/user/outsidecontext/listens",
|
||||
"testdata/listens.json")
|
||||
|
||||
|
@ -62,7 +62,7 @@ func TestGetListens(t *testing.T) {
|
|||
|
||||
func TestSubmitListens(t *testing.T) {
|
||||
client := listenbrainz.NewClient("thetoken")
|
||||
httpmock.ActivateNonDefault(client.HttpClient.GetClient())
|
||||
httpmock.ActivateNonDefault(client.HTTPClient.GetClient())
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, listenbrainz.StatusResult{
|
||||
Status: "ok",
|
||||
|
@ -103,7 +103,7 @@ func TestGetFeedback(t *testing.T) {
|
|||
|
||||
client := listenbrainz.NewClient("thetoken")
|
||||
client.MaxResults = 2
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.listenbrainz.org/1/feedback/user/outsidecontext/get-feedback",
|
||||
"testdata/feedback.json")
|
||||
|
||||
|
@ -120,7 +120,7 @@ func TestGetFeedback(t *testing.T) {
|
|||
|
||||
func TestSendFeedback(t *testing.T) {
|
||||
client := listenbrainz.NewClient("thetoken")
|
||||
httpmock.ActivateNonDefault(client.HttpClient.GetClient())
|
||||
httpmock.ActivateNonDefault(client.HTTPClient.GetClient())
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, listenbrainz.StatusResult{
|
||||
Status: "ok",
|
||||
|
@ -145,7 +145,7 @@ func TestLookup(t *testing.T) {
|
|||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
client := listenbrainz.NewClient("thetoken")
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.listenbrainz.org/1/metadata/lookup",
|
||||
"testdata/lookup.json")
|
||||
|
||||
|
@ -158,7 +158,7 @@ func TestLookup(t *testing.T) {
|
|||
assert.Equal(mbtypes.MBID("569436a1-234a-44bc-a370-8f4d252bef21"), result.RecordingMBID)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
|
||||
|
|
|
@ -131,7 +131,7 @@ func TestTrackTrackNumberString(t *testing.T) {
|
|||
assert.Equal(t, 12, track.TrackNumber())
|
||||
}
|
||||
|
||||
func TestTrackIsrc(t *testing.T) {
|
||||
func TestTrackISRC(t *testing.T) {
|
||||
expected := mbtypes.ISRC("TCAEJ1934417")
|
||||
track := listenbrainz.Track{
|
||||
AdditionalInfo: map[string]any{
|
||||
|
|
|
@ -32,25 +32,25 @@ import (
|
|||
const MaxItemsPerGet = 1000
|
||||
|
||||
type Client struct {
|
||||
HttpClient *resty.Client
|
||||
HTTPClient *resty.Client
|
||||
token string
|
||||
}
|
||||
|
||||
func NewClient(serverUrl string, token string) Client {
|
||||
func NewClient(serverURL string, token string) Client {
|
||||
client := resty.New()
|
||||
client.SetBaseURL(serverUrl)
|
||||
client.SetBaseURL(serverURL)
|
||||
client.SetHeader("Accept", "application/json")
|
||||
client.SetHeader("User-Agent", version.UserAgent())
|
||||
client.SetRetryCount(5)
|
||||
return Client{
|
||||
HttpClient: client,
|
||||
HTTPClient: client,
|
||||
token: token,
|
||||
}
|
||||
}
|
||||
|
||||
func (c Client) GetScrobbles(page int, perPage int) (result GetScrobblesResult, err error) {
|
||||
const path = "/apis/mlj_1/scrobbles"
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"page": strconv.Itoa(page),
|
||||
"perpage": strconv.Itoa(perPage),
|
||||
|
@ -68,7 +68,7 @@ func (c Client) GetScrobbles(page int, perPage int) (result GetScrobblesResult,
|
|||
func (c Client) NewScrobble(scrobble NewScrobble) (result NewScrobbleResult, err error) {
|
||||
const path = "/apis/mlj_1/newscrobble"
|
||||
scrobble.Key = c.token
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetBody(scrobble).
|
||||
SetResult(&result).
|
||||
Post(path)
|
||||
|
|
|
@ -32,19 +32,19 @@ import (
|
|||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
serverUrl := "https://maloja.example.com"
|
||||
serverURL := "https://maloja.example.com"
|
||||
token := "foobar123"
|
||||
client := maloja.NewClient(serverUrl, token)
|
||||
assert.Equal(t, serverUrl, client.HttpClient.BaseURL)
|
||||
client := maloja.NewClient(serverURL, token)
|
||||
assert.Equal(t, serverURL, client.HTTPClient.BaseURL)
|
||||
}
|
||||
|
||||
func TestGetScrobbles(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
serverUrl := "https://maloja.example.com"
|
||||
serverURL := "https://maloja.example.com"
|
||||
token := "thetoken"
|
||||
client := maloja.NewClient(serverUrl, token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
client := maloja.NewClient(serverURL, token)
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://maloja.example.com/apis/mlj_1/scrobbles",
|
||||
"testdata/scrobbles.json")
|
||||
|
||||
|
@ -60,7 +60,7 @@ func TestGetScrobbles(t *testing.T) {
|
|||
func TestNewScrobble(t *testing.T) {
|
||||
server := "https://maloja.example.com"
|
||||
client := maloja.NewClient(server, "thetoken")
|
||||
httpmock.ActivateNonDefault(client.HttpClient.GetClient())
|
||||
httpmock.ActivateNonDefault(client.HTTPClient.GetClient())
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File("testdata/newscrobble-result.json"))
|
||||
if err != nil {
|
||||
|
@ -80,7 +80,7 @@ func TestNewScrobble(t *testing.T) {
|
|||
assert.Equal(t, "success", result.Status)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
|
||||
|
|
|
@ -40,7 +40,7 @@ const (
|
|||
)
|
||||
|
||||
type Client struct {
|
||||
HttpClient *resty.Client
|
||||
HTTPClient *resty.Client
|
||||
}
|
||||
|
||||
func NewClient(token oauth2.TokenSource) Client {
|
||||
|
@ -55,7 +55,7 @@ func NewClient(token oauth2.TokenSource) Client {
|
|||
ratelimit.EnableHTTPHeaderRateLimit(client, "Retry-After")
|
||||
|
||||
return Client{
|
||||
HttpClient: client,
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ func (c Client) RecentlyPlayedBefore(before time.Time, limit int) (RecentlyPlaye
|
|||
|
||||
func (c Client) recentlyPlayed(after *time.Time, before *time.Time, limit int) (result RecentlyPlayedResult, err error) {
|
||||
const path = "/me/player/recently-played"
|
||||
request := c.HttpClient.R().
|
||||
request := c.HTTPClient.R().
|
||||
SetQueryParam("limit", strconv.Itoa(limit)).
|
||||
SetResult(&result)
|
||||
if after != nil {
|
||||
|
@ -87,7 +87,7 @@ func (c Client) recentlyPlayed(after *time.Time, before *time.Time, limit int) (
|
|||
|
||||
func (c Client) UserTracks(offset int, limit int) (result TracksResult, err error) {
|
||||
const path = "/me/tracks"
|
||||
response, err := c.HttpClient.R().
|
||||
response, err := c.HTTPClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"offset": strconv.Itoa(offset),
|
||||
"limit": strconv.Itoa(limit),
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestRecentlyPlayedAfter(t *testing.T) {
|
|||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
client := spotify.NewClient(nil)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.spotify.com/v1/me/player/recently-played",
|
||||
"testdata/recently-played.json")
|
||||
|
||||
|
@ -63,7 +63,7 @@ func TestGetUserTracks(t *testing.T) {
|
|||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
client := spotify.NewClient(nil)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
setupHTTPMock(t, client.HTTPClient.GetClient(),
|
||||
"https://api.spotify.com/v1/me/tracks",
|
||||
"testdata/user-tracks.json")
|
||||
|
||||
|
@ -79,7 +79,7 @@ func TestGetUserTracks(t *testing.T) {
|
|||
assert.Equal("Zeal & Ardor", track1.Track.Album.Name)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
|
||||
|
|
|
@ -58,7 +58,7 @@ type Listen struct {
|
|||
}
|
||||
|
||||
type Track struct {
|
||||
Id string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Href string `json:"href"`
|
||||
Uri string `json:"uri"`
|
||||
|
@ -69,14 +69,14 @@ type Track struct {
|
|||
Explicit bool `json:"explicit"`
|
||||
IsLocal bool `json:"is_local"`
|
||||
Popularity int `json:"popularity"`
|
||||
ExternalIds ExternalIds `json:"external_ids"`
|
||||
ExternalUrls ExternalUrls `json:"external_urls"`
|
||||
ExternalIDs ExternalIDs `json:"external_ids"`
|
||||
ExternalURLs ExternalURLs `json:"external_urls"`
|
||||
Album Album `json:"album"`
|
||||
Artists []Artist `json:"artists"`
|
||||
}
|
||||
|
||||
type Album struct {
|
||||
Id string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Href string `json:"href"`
|
||||
Uri string `json:"uri"`
|
||||
|
@ -85,32 +85,32 @@ type Album struct {
|
|||
ReleaseDate string `json:"release_date"`
|
||||
ReleaseDatePrecision string `json:"release_date_precision"`
|
||||
AlbumType string `json:"album_type"`
|
||||
ExternalUrls ExternalUrls `json:"external_urls"`
|
||||
ExternalURLs ExternalURLs `json:"external_urls"`
|
||||
Artists []Artist `json:"artists"`
|
||||
Images []Image `json:"images"`
|
||||
}
|
||||
|
||||
type Artist struct {
|
||||
Id string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Href string `json:"href"`
|
||||
Uri string `json:"uri"`
|
||||
Type string `json:"type"`
|
||||
ExternalUrls ExternalUrls `json:"external_urls"`
|
||||
ExternalURLs ExternalURLs `json:"external_urls"`
|
||||
}
|
||||
|
||||
type ExternalIds struct {
|
||||
type ExternalIDs struct {
|
||||
ISRC mbtypes.ISRC `json:"isrc"`
|
||||
EAN string `json:"ean"`
|
||||
UPC string `json:"upc"`
|
||||
}
|
||||
|
||||
type ExternalUrls struct {
|
||||
type ExternalURLs struct {
|
||||
Spotify string `json:"spotify"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Url string `json:"url"`
|
||||
URL string `json:"url"`
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
|
||||
type SpotifyApiBackend struct {
|
||||
client Client
|
||||
clientId string
|
||||
clientID string
|
||||
clientSecret string
|
||||
}
|
||||
|
||||
|
@ -53,14 +53,14 @@ func (b *SpotifyApiBackend) Options() []models.BackendOption {
|
|||
}
|
||||
|
||||
func (b *SpotifyApiBackend) InitConfig(config *config.ServiceConfig) error {
|
||||
b.clientId = config.GetString("client-id")
|
||||
b.clientID = config.GetString("client-id")
|
||||
b.clientSecret = config.GetString("client-secret")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *SpotifyApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy {
|
||||
func (b *SpotifyApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy {
|
||||
conf := oauth2.Config{
|
||||
ClientID: b.clientId,
|
||||
ClientID: b.clientID,
|
||||
ClientSecret: b.clientSecret,
|
||||
Scopes: []string{
|
||||
"user-read-currently-playing",
|
||||
|
@ -68,16 +68,16 @@ func (b *SpotifyApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Stra
|
|||
"user-library-read",
|
||||
"user-library-modify",
|
||||
},
|
||||
RedirectURL: redirectUrl.String(),
|
||||
RedirectURL: redirectURL.String(),
|
||||
Endpoint: spotify.Endpoint,
|
||||
}
|
||||
|
||||
return auth.NewStandardStrategy(conf)
|
||||
}
|
||||
|
||||
func (b *SpotifyApiBackend) OAuth2Config(redirectUrl *url.URL) oauth2.Config {
|
||||
func (b *SpotifyApiBackend) OAuth2Config(redirectURL *url.URL) oauth2.Config {
|
||||
return oauth2.Config{
|
||||
ClientID: b.clientId,
|
||||
ClientID: b.clientID,
|
||||
ClientSecret: b.clientSecret,
|
||||
Scopes: []string{
|
||||
"user-read-currently-playing",
|
||||
|
@ -85,7 +85,7 @@ func (b *SpotifyApiBackend) OAuth2Config(redirectUrl *url.URL) oauth2.Config {
|
|||
"user-library-read",
|
||||
"user-library-modify",
|
||||
},
|
||||
RedirectURL: redirectUrl.String(),
|
||||
RedirectURL: redirectURL.String(),
|
||||
Endpoint: spotify.Endpoint,
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ func (t Track) AsTrack() models.Track {
|
|||
Duration: time.Duration(t.DurationMs * int(time.Millisecond)),
|
||||
TrackNumber: t.TrackNumber,
|
||||
DiscNumber: t.DiscNumber,
|
||||
ISRC: t.ExternalIds.ISRC,
|
||||
ISRC: t.ExternalIDs.ISRC,
|
||||
AdditionalInfo: map[string]any{},
|
||||
}
|
||||
|
||||
|
@ -264,30 +264,30 @@ func (t Track) AsTrack() models.Track {
|
|||
info["music_service"] = "spotify.com"
|
||||
}
|
||||
|
||||
if t.ExternalUrls.Spotify != "" {
|
||||
info["origin_url"] = t.ExternalUrls.Spotify
|
||||
info["spotify_id"] = t.ExternalUrls.Spotify
|
||||
if t.ExternalURLs.Spotify != "" {
|
||||
info["origin_url"] = t.ExternalURLs.Spotify
|
||||
info["spotify_id"] = t.ExternalURLs.Spotify
|
||||
}
|
||||
|
||||
if t.Album.ExternalUrls.Spotify != "" {
|
||||
info["spotify_album_id"] = t.Album.ExternalUrls.Spotify
|
||||
if t.Album.ExternalURLs.Spotify != "" {
|
||||
info["spotify_album_id"] = t.Album.ExternalURLs.Spotify
|
||||
}
|
||||
|
||||
if len(t.Artists) > 0 {
|
||||
info["spotify_artist_ids"] = extractArtistIds(t.Artists)
|
||||
info["spotify_artist_ids"] = extractArtistIDs(t.Artists)
|
||||
}
|
||||
|
||||
if len(t.Album.Artists) > 0 {
|
||||
info["spotify_album_artist_ids"] = extractArtistIds(t.Album.Artists)
|
||||
info["spotify_album_artist_ids"] = extractArtistIDs(t.Album.Artists)
|
||||
}
|
||||
|
||||
return track
|
||||
}
|
||||
|
||||
func extractArtistIds(artists []Artist) []string {
|
||||
artistIds := make([]string, len(artists))
|
||||
func extractArtistIDs(artists []Artist) []string {
|
||||
artistIDs := make([]string, len(artists))
|
||||
for i, artist := range artists {
|
||||
artistIds[i] = artist.ExternalUrls.Spotify
|
||||
artistIDs[i] = artist.ExternalURLs.Spotify
|
||||
}
|
||||
return artistIds
|
||||
return artistIDs
|
||||
}
|
||||
|
|
|
@ -92,8 +92,8 @@ func (i HistoryItem) AsListen() models.Listen {
|
|||
PlaybackDuration: time.Duration(i.MillisecondsPlayed * int(time.Millisecond)),
|
||||
UserName: i.UserName,
|
||||
}
|
||||
if trackUrl, err := formatSpotifyUri(i.SpotifyTrackUri); err != nil {
|
||||
listen.AdditionalInfo["spotify_id"] = trackUrl
|
||||
if trackURL, err := formatSpotifyUri(i.SpotifyTrackUri); err != nil {
|
||||
listen.AdditionalInfo["spotify_id"] = trackURL
|
||||
}
|
||||
return listen
|
||||
}
|
||||
|
|
|
@ -43,20 +43,20 @@ func AuthenticationFlow(service config.ServiceConfig, backend auth.OAuth2Authent
|
|||
|
||||
state := auth.RandomState()
|
||||
// Redirect user to consent page to ask for permission specified scopes.
|
||||
authUrl := strategy.AuthCodeURL(verifier, state)
|
||||
authURL := strategy.AuthCodeURL(verifier, state)
|
||||
|
||||
// Start an HTTP server to listen for the response
|
||||
responseChan := make(chan auth.CodeResponse)
|
||||
auth.RunOauth2CallbackServer(*redirectURL, authUrl.Param, responseChan)
|
||||
auth.RunOauth2CallbackServer(*redirectURL, authURL.Param, responseChan)
|
||||
|
||||
// Open the URL
|
||||
fmt.Println(i18n.Tr("Visit the URL for authorization: %v", authUrl.Url))
|
||||
err = browser.OpenURL(authUrl.Url)
|
||||
fmt.Println(i18n.Tr("Visit the URL for authorization: %v", authURL.URL))
|
||||
err = browser.OpenURL(authURL.URL)
|
||||
cobra.CheckErr(err)
|
||||
|
||||
// Retrieve the code from the authentication callback
|
||||
code := <-responseChan
|
||||
if code.State != authUrl.State {
|
||||
if code.State != authURL.State {
|
||||
cobra.CompErrorln(i18n.Tr("Error: OAuth state mismatch"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue