diff --git a/CHANGES.md b/CHANGES.md
index cda0d79..7324f77 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,6 @@
# Scotty Changelog
-## 0.5.0 - (not yet released)
+## 0.5.0 - 2025-04-29
- ListenBrainz: handle missing loves metadata in case of merged recordings
- ListenBrainz: fix loves import loading all existing loves
- ListenBrainz: fixed progress for loves import
diff --git a/internal/auth/auth.go b/internal/auth/auth.go
index 5ba05af..84c85b6 100644
--- a/internal/auth/auth.go
+++ b/internal/auth/auth.go
@@ -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
diff --git a/internal/auth/strategy.go b/internal/auth/strategy.go
index 3d03fa4..7e3c265 100644
--- a/internal/auth/strategy.go
+++ b/internal/auth/strategy.go
@@ -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",
}
diff --git a/internal/backends/deezer/auth.go b/internal/backends/deezer/auth.go
index aa30b04..0304dec 100644
--- a/internal/backends/deezer/auth.go
+++ b/internal/backends/deezer/auth.go
@@ -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",
}
diff --git a/internal/backends/deezer/client.go b/internal/backends/deezer/client.go
index 3c3b740..05264ae 100644
--- a/internal/backends/deezer/client.go
+++ b/internal/backends/deezer/client.go
@@ -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),
diff --git a/internal/backends/deezer/client_test.go b/internal/backends/deezer/client_test.go
index f8240f8..c90b01a 100644
--- a/internal/backends/deezer/client_test.go
+++ b/internal/backends/deezer/client_test.go
@@ -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))
diff --git a/internal/backends/deezer/deezer.go b/internal/backends/deezer/deezer.go
index e7d9762..7b6e1ad 100644
--- a/internal/backends/deezer/deezer.go
+++ b/internal/backends/deezer/deezer.go
@@ -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
}
diff --git a/internal/backends/deezer/models.go b/internal/backends/deezer/models.go
index 712cd73..85b569c 100644
--- a/internal/backends/deezer/models.go
+++ b/internal/backends/deezer/models.go
@@ -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"`
diff --git a/internal/backends/funkwhale/client.go b/internal/backends/funkwhale/client.go
index 8f2848b..c231c94 100644
--- a/internal/backends/funkwhale/client.go
+++ b/internal/backends/funkwhale/client.go
@@ -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),
diff --git a/internal/backends/funkwhale/client_test.go b/internal/backends/funkwhale/client_test.go
index 89325cd..e850a4d 100644
--- a/internal/backends/funkwhale/client_test.go
+++ b/internal/backends/funkwhale/client_test.go
@@ -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))
diff --git a/internal/backends/funkwhale/models.go b/internal/backends/funkwhale/models.go
index 10d57d0..faaae12 100644
--- a/internal/backends/funkwhale/models.go
+++ b/internal/backends/funkwhale/models.go
@@ -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"`
}
diff --git a/internal/backends/jspf/jspf.go b/internal/backends/jspf/jspf.go
index 152c810..3e6866d 100644
--- a/internal/backends/jspf/jspf.go
+++ b/internal/backends/jspf/jspf.go
@@ -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 != "" {
diff --git a/internal/backends/lastfm/auth.go b/internal/backends/lastfm/auth.go
index bbc65bc..9d43e0c 100644
--- a/internal/backends/lastfm/auth.go
+++ b/internal/backends/lastfm/auth.go
@@ -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",
}
diff --git a/internal/backends/lastfm/lastfm.go b/internal/backends/lastfm/lastfm.go
index 2d4a9d5..76fe9c7 100644
--- a/internal/backends/lastfm/lastfm.go
+++ b/internal/backends/lastfm/lastfm.go
@@ -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,
}
}
diff --git a/internal/backends/listenbrainz/client.go b/internal/backends/listenbrainz/client.go
index 1917bd4..fff476c 100644
--- a/internal/backends/listenbrainz/client.go
+++ b/internal/backends/listenbrainz/client.go
@@ -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,
diff --git a/internal/backends/listenbrainz/client_test.go b/internal/backends/listenbrainz/client_test.go
index 4e72756..2e841ae 100644
--- a/internal/backends/listenbrainz/client_test.go
+++ b/internal/backends/listenbrainz/client_test.go
@@ -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))
diff --git a/internal/backends/listenbrainz/models_test.go b/internal/backends/listenbrainz/models_test.go
index 9f5b14a..02cbe98 100644
--- a/internal/backends/listenbrainz/models_test.go
+++ b/internal/backends/listenbrainz/models_test.go
@@ -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{
diff --git a/internal/backends/maloja/client.go b/internal/backends/maloja/client.go
index f373f93..249819a 100644
--- a/internal/backends/maloja/client.go
+++ b/internal/backends/maloja/client.go
@@ -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)
diff --git a/internal/backends/maloja/client_test.go b/internal/backends/maloja/client_test.go
index 6a07adb..54316a8 100644
--- a/internal/backends/maloja/client_test.go
+++ b/internal/backends/maloja/client_test.go
@@ -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))
diff --git a/internal/backends/scrobblerlog/scrobblerlog.go b/internal/backends/scrobblerlog/scrobblerlog.go
index 26d417a..19ed30b 100644
--- a/internal/backends/scrobblerlog/scrobblerlog.go
+++ b/internal/backends/scrobblerlog/scrobblerlog.go
@@ -76,7 +76,7 @@ func (b *ScrobblerLogBackend) InitConfig(config *config.ServiceConfig) error {
b.log.FallbackTimezone = location
}
b.log = scrobblerlog.ScrobblerLog{
- TZ: scrobblerlog.TZ_UTC,
+ TZ: scrobblerlog.TimezoneUTC,
Client: "Rockbox unknown $Revision$",
}
return nil
@@ -197,7 +197,7 @@ func listenToRecord(listen models.Listen) scrobblerlog.Record {
var rating scrobblerlog.Rating
rockboxRating, ok := listen.AdditionalInfo["rockbox_rating"].(string)
if !ok || rockboxRating == "" {
- rating = scrobblerlog.RATING_LISTENED
+ rating = scrobblerlog.RatingListened
} else {
rating = scrobblerlog.Rating(rating)
}
diff --git a/internal/backends/spotify/client.go b/internal/backends/spotify/client.go
index 1c002c0..ff2b0a3 100644
--- a/internal/backends/spotify/client.go
+++ b/internal/backends/spotify/client.go
@@ -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),
diff --git a/internal/backends/spotify/client_test.go b/internal/backends/spotify/client_test.go
index 7d738bf..78ff063 100644
--- a/internal/backends/spotify/client_test.go
+++ b/internal/backends/spotify/client_test.go
@@ -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))
diff --git a/internal/backends/spotify/models.go b/internal/backends/spotify/models.go
index a22de21..e279e15 100644
--- a/internal/backends/spotify/models.go
+++ b/internal/backends/spotify/models.go
@@ -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"`
}
diff --git a/internal/backends/spotify/spotify.go b/internal/backends/spotify/spotify.go
index ae2fc25..1827769 100644
--- a/internal/backends/spotify/spotify.go
+++ b/internal/backends/spotify/spotify.go
@@ -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
}
diff --git a/internal/backends/spotifyhistory/models.go b/internal/backends/spotifyhistory/models.go
index fad4fb1..a2eba23 100644
--- a/internal/backends/spotifyhistory/models.go
+++ b/internal/backends/spotifyhistory/models.go
@@ -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
}
diff --git a/internal/cli/auth.go b/internal/cli/auth.go
index 828651a..ff14573 100644
--- a/internal/cli/auth.go
+++ b/internal/cli/auth.go
@@ -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)
}
diff --git a/internal/cli/transfer.go b/internal/cli/transfer.go
index 427af06..ade7ece 100644
--- a/internal/cli/transfer.go
+++ b/internal/cli/transfer.go
@@ -88,7 +88,7 @@ func (c *TransferCmd[E, I, R]) resolveBackends(source string, target string) err
}
func (c *TransferCmd[E, I, R]) Transfer(exp backends.ExportProcessor[R], imp backends.ImportProcessor[R]) error {
- fmt.Println(i18n.Tr("Transferring %s from %s to %s...", c.entity, c.sourceName, c.targetName))
+ fmt.Println(i18n.Tr("Transferring %s from %s to %s…", c.entity, c.sourceName, c.targetName))
// Authenticate backends, if needed
config := viper.GetViper()
diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go
index cbfd516..a910ca0 100644
--- a/internal/i18n/i18n.go
+++ b/internal/i18n/i18n.go
@@ -16,11 +16,10 @@ Scotty. If not, see .
package i18n
import (
- "log"
-
"github.com/Xuanwo/go-locale"
_ "go.uploadedlobster.com/scotty/internal/translations"
+ "golang.org/x/text/language"
"golang.org/x/text/message"
)
@@ -29,7 +28,7 @@ var localizer Localizer
func init() {
tag, err := locale.Detect()
if err != nil {
- log.Fatal(err)
+ tag = language.English
}
localizer = New(tag)
}
diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go
index 987612a..3eb2f7e 100644
--- a/internal/translations/catalog.go
+++ b/internal/translations/catalog.go
@@ -42,56 +42,56 @@ var messageKeyToIndex = map[string]int{
"\tbackend: %v": 11,
"\texport: %s": 0,
"\timport: %s\n": 1,
- "%v: %v": 47,
+ "%v: %v": 48,
"Aborted": 8,
"Access token": 19,
- "Access token received, you can use %v now.\n": 33,
+ "Access token received, you can use %v now.\n": 34,
"Append to file": 21,
- "Backend": 41,
+ "Backend": 42,
"Check for duplicate listens on import (slower)": 24,
"Client ID": 15,
"Client secret": 16,
"Delete the service configuration \"%v\"?": 7,
- "Directory path": 27,
- "Disable auto correction of submitted listens": 25,
- "Error: OAuth state mismatch": 32,
+ "Directory path": 29,
+ "Disable auto correction of submitted listens": 26,
+ "Error: OAuth state mismatch": 33,
"Failed reading config: %v": 2,
"File path": 20,
- "From timestamp: %v (%v)": 43,
- "Ignore listens in incognito mode": 28,
- "Ignore skipped listens": 29,
- "Ignored duplicate listen %v: \"%v\" by %v (%v)": 53,
- "Import failed, last reported timestamp was %v (%s)": 44,
- "Import log:": 46,
- "Imported %v of %v %s into %v.": 45,
- "Include skipped listens": 26,
- "Latest timestamp: %v (%v)": 49,
- "Minimum playback duration for skipped tracks (seconds)": 30,
- "No": 38,
+ "From timestamp: %v (%v)": 44,
+ "Ignore listens in incognito mode": 30,
+ "Ignore skipped listens": 27,
+ "Ignored duplicate listen %v: \"%v\" by %v (%v)": 25,
+ "Import failed, last reported timestamp was %v (%s)": 45,
+ "Import log:": 47,
+ "Imported %v of %v %s into %v.": 46,
+ "Latest timestamp: %v (%v)": 50,
+ "Minimum playback duration for skipped tracks (seconds)": 31,
+ "No": 39,
"Playlist title": 22,
"Saved service %v using backend %v": 5,
"Server URL": 17,
- "Service": 40,
+ "Service": 41,
"Service \"%v\" deleted\n": 9,
"Service name": 3,
+ "Specify a time zone for the listen timestamps": 28,
"The backend %v requires authentication. Authenticate now?": 6,
"Token received, you can close this window now.": 12,
- "Transferring %s from %s to %s...": 42,
+ "Transferring %s from %s to %s…": 43,
"Unique playlist identifier": 23,
"Updated service %v using backend %v\n": 10,
"User name": 18,
- "Visit the URL for authorization: %v": 31,
- "Yes": 37,
+ "Visit the URL for authorization: %v": 32,
+ "Yes": 38,
"a service with this name already exists": 4,
"backend %s does not implement %s": 13,
- "done": 36,
- "exporting": 34,
- "importing": 35,
- "invalid timestamp string \"%v\"": 48,
- "key must only consist of A-Za-z0-9_-": 51,
- "no configuration file defined, cannot write config": 50,
- "no existing service configurations": 39,
- "no service configuration \"%v\"": 52,
+ "done": 37,
+ "exporting": 35,
+ "importing": 36,
+ "invalid timestamp string \"%v\"": 49,
+ "key must only consist of A-Za-z0-9_-": 52,
+ "no configuration file defined, cannot write config": 51,
+ "no existing service configurations": 40,
+ "no service configuration \"%v\"": 53,
"unknown backend \"%s\"": 14,
}
@@ -103,18 +103,18 @@ var deIndex = []uint32{ // 55 elements
0x000001ac, 0x000001e7, 0x00000213, 0x00000233,
0x0000023d, 0x0000024b, 0x00000256, 0x00000263,
0x00000271, 0x0000027b, 0x0000028e, 0x000002a1,
- 0x000002b8, 0x000002ed, 0x00000321, 0x00000342,
- 0x00000352, 0x00000378, 0x0000039a, 0x000003d8,
+ 0x000002b8, 0x000002ed, 0x00000328, 0x0000035c,
+ 0x0000037e, 0x000003a4, 0x000003b4, 0x000003da,
// Entry 20 - 3F
- 0x000003fe, 0x00000428, 0x00000468, 0x00000473,
- 0x0000047e, 0x00000485, 0x00000488, 0x0000048d,
- 0x000004b6, 0x000004be, 0x000004c6, 0x000004ef,
- 0x0000050d, 0x0000054a, 0x00000575, 0x00000580,
- 0x0000058d, 0x000005b1, 0x000005d4, 0x00000625,
- 0x0000065c, 0x00000683, 0x00000683,
+ 0x00000418, 0x00000443, 0x0000046d, 0x000004ad,
+ 0x000004b8, 0x000004c3, 0x000004ca, 0x000004cd,
+ 0x000004d2, 0x000004fb, 0x00000503, 0x0000050b,
+ 0x00000534, 0x00000552, 0x0000058f, 0x000005ba,
+ 0x000005c5, 0x000005d2, 0x000005f6, 0x00000619,
+ 0x0000066a, 0x000006a1, 0x000006c8,
} // Size: 244 bytes
-const deData string = "" + // Size: 1667 bytes
+const deData string = "" + // Size: 1736 bytes
"\x04\x01\x09\x00\x0e\x02Export: %[1]s\x04\x01\x09\x01\x0a\x0e\x02Import:" +
" %[1]s\x02Fehler beim Lesen der Konfiguration: %[1]v\x02Servicename\x02e" +
"in Service mit diesem Namen existiert bereits\x02Service %[1]v mit dem B" +
@@ -123,25 +123,26 @@ const deData string = "" + // Size: 1667 bytes
"\x02Abgebrochen\x04\x00\x01\x0a\x1e\x02Service „%[1]v“ gelöscht\x04\x00" +
"\x01\x0a1\x02Service %[1]v mit dem Backend %[2]v aktualisiert\x04\x01" +
"\x09\x00\x0f\x02Backend: %[1]v\x02Token erhalten, das Fenster kann jetzt" +
- " geschlossen werden.\x02das backend %[1]s implementiert %[2]s nicht\x02u" +
+ " geschlossen werden.\x02das Backend %[1]s implementiert %[2]s nicht\x02u" +
"nbekanntes Backend „%[1]s“\x02Client-ID\x02Client-Secret\x02Server-URL" +
"\x02Benutzername\x02Zugriffstoken\x02Dateipfad\x02An Datei anhängen\x02T" +
"itel der Playlist\x02Eindeutige Playlist-ID\x02Beim Import auf Listen-Du" +
- "plikate prüfen (langsamer)\x02Autokorrektur für übermittelte Titel deakt" +
- "ivieren\x02Übersprungene Titel einbeziehen\x02Verzeichnispfad\x02Listens" +
- " im Inkognito-Modus ignorieren\x02Übersprungene Listens ignorieren\x02Mi" +
- "nimale Wiedergabedauer für übersprungene Titel (Sekunden)\x02URL für Aut" +
- "orisierung öffnen: %[1]v\x02Fehler: OAuth-State stimmt nicht überein\x04" +
- "\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwendet werd" +
- "en.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine bestehe" +
- "nden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %[1]s von" +
- " %[2]s nach %[3]s...\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fehlgesc" +
- "hlagen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %[3]s i" +
- "n %[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Zeitstem" +
- "pel „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfiguration" +
- "sdatei definiert, Konfiguration kann nicht geschrieben werden\x02Schlüss" +
- "el darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekonfigura" +
- "tion „%[1]v“"
+ "plikate prüfen (langsamer)\x02Listen-Duplikat ignoriert %[1]v: \x22%[2]v" +
+ "\x22 von %[3]v (%[4]v)\x02Autokorrektur für übermittelte Titel deaktivie" +
+ "ren\x02Übersprungene Listens ignorieren\x02Zeitzone für den Abspiel-Zeit" +
+ "stempel\x02Verzeichnispfad\x02Listens im Inkognito-Modus ignorieren\x02M" +
+ "inimale Wiedergabedauer für übersprungene Titel (Sekunden)\x02Zur Anmeld" +
+ "ung folgende URL aufrufen: %[1]v\x02Fehler: OAuth-State stimmt nicht übe" +
+ "rein\x04\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwen" +
+ "det werden.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine" +
+ " bestehenden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %" +
+ "[1]s von %[2]s nach %[3]s…\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fe" +
+ "hlgeschlagen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %" +
+ "[3]s in %[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Ze" +
+ "itstempel „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfigu" +
+ "rationsdatei definiert, Konfiguration kann nicht geschrieben werden\x02S" +
+ "chlüssel darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekon" +
+ "figuration „%[1]v“"
var enIndex = []uint32{ // 55 elements
// Entry 0 - 1F
@@ -151,18 +152,18 @@ var enIndex = []uint32{ // 55 elements
0x00000170, 0x0000019f, 0x000001c6, 0x000001de,
0x000001e8, 0x000001f6, 0x00000201, 0x0000020b,
0x00000218, 0x00000222, 0x00000231, 0x00000240,
- 0x0000025b, 0x0000028a, 0x000002b7, 0x000002cf,
- 0x000002de, 0x000002ff, 0x00000316, 0x0000034d,
+ 0x0000025b, 0x0000028a, 0x000002c3, 0x000002f0,
+ 0x00000307, 0x00000335, 0x00000344, 0x00000365,
// Entry 20 - 3F
- 0x00000374, 0x00000390, 0x000003c3, 0x000003cd,
- 0x000003d7, 0x000003dc, 0x000003e0, 0x000003e3,
- 0x00000406, 0x0000040e, 0x00000416, 0x00000440,
- 0x0000045e, 0x00000497, 0x000004c1, 0x000004cd,
- 0x000004da, 0x000004fb, 0x0000051b, 0x0000054e,
- 0x00000573, 0x00000594, 0x000005cd,
+ 0x0000039c, 0x000003c3, 0x000003df, 0x00000412,
+ 0x0000041c, 0x00000426, 0x0000042b, 0x0000042f,
+ 0x00000432, 0x00000455, 0x0000045d, 0x00000465,
+ 0x0000048f, 0x000004ad, 0x000004e6, 0x00000510,
+ 0x0000051c, 0x00000529, 0x0000054a, 0x0000056a,
+ 0x0000059d, 0x000005c2, 0x000005e3,
} // Size: 244 bytes
-const enData string = "" + // Size: 1485 bytes
+const enData string = "" + // Size: 1507 bytes
"\x04\x01\x09\x00\x0e\x02export: %[1]s\x04\x01\x09\x01\x0a\x0e\x02import:" +
" %[1]s\x02Failed reading config: %[1]v\x02Service name\x02a service with" +
" this name already exists\x02Saved service %[1]v using backend %[2]v\x02" +
@@ -174,19 +175,19 @@ const enData string = "" + // Size: 1485 bytes
"ent %[2]s\x02unknown backend \x22%[1]s\x22\x02Client ID\x02Client secret" +
"\x02Server URL\x02User name\x02Access token\x02File path\x02Append to fi" +
"le\x02Playlist title\x02Unique playlist identifier\x02Check for duplicat" +
- "e listens on import (slower)\x02Disable auto correction of submitted lis" +
- "tens\x02Include skipped listens\x02Directory path\x02Ignore listens in i" +
- "ncognito mode\x02Ignore skipped listens\x02Minimum playback duration for" +
- " skipped tracks (seconds)\x02Visit the URL for authorization: %[1]v\x02E" +
- "rror: OAuth state mismatch\x04\x00\x01\x0a.\x02Access token received, yo" +
- "u can use %[1]v now.\x02exporting\x02importing\x02done\x02Yes\x02No\x02n" +
- "o existing service configurations\x02Service\x02Backend\x02Transferring " +
- "%[1]s from %[2]s to %[3]s...\x02From timestamp: %[1]v (%[2]v)\x02Import " +
- "failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v of %" +
- "[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid timesta" +
- "mp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no configu" +
- "ration file defined, cannot write config\x02key must only consist of A-Z" +
- "a-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored duplicate " +
- "listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)"
+ "e listens on import (slower)\x02Ignored duplicate listen %[1]v: \x22%[2]" +
+ "v\x22 by %[3]v (%[4]v)\x02Disable auto correction of submitted listens" +
+ "\x02Ignore skipped listens\x02Specify a time zone for the listen timesta" +
+ "mps\x02Directory path\x02Ignore listens in incognito mode\x02Minimum pla" +
+ "yback duration for skipped tracks (seconds)\x02Visit the URL for authori" +
+ "zation: %[1]v\x02Error: OAuth state mismatch\x04\x00\x01\x0a.\x02Access " +
+ "token received, you can use %[1]v now.\x02exporting\x02importing\x02done" +
+ "\x02Yes\x02No\x02no existing service configurations\x02Service\x02Backen" +
+ "d\x02Transferring %[1]s from %[2]s to %[3]s…\x02From timestamp: %[1]v (%" +
+ "[2]v)\x02Import failed, last reported timestamp was %[1]v (%[2]s)\x02Imp" +
+ "orted %[1]v of %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v" +
+ "\x02invalid timestamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%" +
+ "[2]v)\x02no configuration file defined, cannot write config\x02key must " +
+ "only consist of A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22"
- // Total table size 3640 bytes (3KiB); checksum: 719A868A
+ // Total table size 3731 bytes (3KiB); checksum: F7951710
diff --git a/internal/translations/locales/de/messages.gotext.json b/internal/translations/locales/de/messages.gotext.json
index afa4129..8cbe44a 100644
--- a/internal/translations/locales/de/messages.gotext.json
+++ b/internal/translations/locales/de/messages.gotext.json
@@ -175,7 +175,7 @@
{
"id": "backend {Backend} does not implement {InterfaceName}",
"message": "backend {Backend} does not implement {InterfaceName}",
- "translation": "das backend {Backend} implementiert {InterfaceName} nicht",
+ "translation": "das Backend {Backend} implementiert {InterfaceName} nicht",
"placeholders": [
{
"id": "Backend",
@@ -261,9 +261,9 @@
"translation": "Beim Import auf Listen-Duplikate prüfen (langsamer)"
},
{
- "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})",
- "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})",
- "translation": "Listen-Duplikat ignoriert {ListenedAt}: „{TrackName}“ von {ArtistName} ({RecordingMbid})",
+ "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
+ "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
+ "translation": "Listen-Duplikat ignoriert {ListenedAt}: \"{TrackName}\" von {ArtistName} ({RecordingMBID})",
"placeholders": [
{
"id": "ListenedAt",
@@ -290,12 +290,12 @@
"expr": "l.ArtistName()"
},
{
- "id": "RecordingMbid",
+ "id": "RecordingMBID",
"string": "%[4]v",
- "type": "go.uploadedlobster.com/scotty/internal/models.MBID",
+ "type": "go.uploadedlobster.com/mbtypes.MBID",
"underlyingType": "string",
"argNum": 4,
- "expr": "l.RecordingMbid"
+ "expr": "l.RecordingMBID"
}
]
},
@@ -305,9 +305,14 @@
"translation": "Autokorrektur für übermittelte Titel deaktivieren"
},
{
- "id": "Include skipped listens",
- "message": "Include skipped listens",
- "translation": "Übersprungene Titel einbeziehen"
+ "id": "Ignore skipped listens",
+ "message": "Ignore skipped listens",
+ "translation": "Übersprungene Listens ignorieren"
+ },
+ {
+ "id": "Specify a time zone for the listen timestamps",
+ "message": "Specify a time zone for the listen timestamps",
+ "translation": "Zeitzone für den Abspiel-Zeitstempel"
},
{
"id": "Directory path",
@@ -319,28 +324,23 @@
"message": "Ignore listens in incognito mode",
"translation": "Listens im Inkognito-Modus ignorieren"
},
- {
- "id": "Ignore skipped listens",
- "message": "Ignore skipped listens",
- "translation": "Übersprungene Listens ignorieren"
- },
{
"id": "Minimum playback duration for skipped tracks (seconds)",
"message": "Minimum playback duration for skipped tracks (seconds)",
"translation": "Minimale Wiedergabedauer für übersprungene Titel (Sekunden)"
},
{
- "id": "Visit the URL for authorization: {Url}",
- "message": "Visit the URL for authorization: {Url}",
- "translation": "URL für Autorisierung öffnen: {Url}",
+ "id": "Visit the URL for authorization: {URL}",
+ "message": "Visit the URL for authorization: {URL}",
+ "translation": "Zur Anmeldung folgende URL aufrufen: {URL}",
"placeholders": [
{
- "id": "Url",
+ "id": "URL",
"string": "%[1]v",
"type": "string",
"underlyingType": "string",
"argNum": 1,
- "expr": "authUrl.Url"
+ "expr": "authURL.URL"
}
]
},
@@ -411,9 +411,9 @@
"translation": "Backend"
},
{
- "id": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "message": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}...",
+ "id": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "message": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}…",
"placeholders": [
{
"id": "Entity",
diff --git a/internal/translations/locales/de/out.gotext.json b/internal/translations/locales/de/out.gotext.json
index 18333c6..680505e 100644
--- a/internal/translations/locales/de/out.gotext.json
+++ b/internal/translations/locales/de/out.gotext.json
@@ -175,7 +175,7 @@
{
"id": "backend {Backend} does not implement {InterfaceName}",
"message": "backend {Backend} does not implement {InterfaceName}",
- "translation": "das backend {Backend} implementiert {InterfaceName} nicht",
+ "translation": "das Backend {Backend} implementiert {InterfaceName} nicht",
"placeholders": [
{
"id": "Backend",
@@ -263,7 +263,7 @@
{
"id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
"message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
- "translation": "",
+ "translation": "Listen-Duplikat ignoriert {ListenedAt}: \"{TrackName}\" von {ArtistName} ({RecordingMBID})",
"placeholders": [
{
"id": "ListenedAt",
@@ -305,9 +305,14 @@
"translation": "Autokorrektur für übermittelte Titel deaktivieren"
},
{
- "id": "Include skipped listens",
- "message": "Include skipped listens",
- "translation": "Übersprungene Titel einbeziehen"
+ "id": "Ignore skipped listens",
+ "message": "Ignore skipped listens",
+ "translation": "Übersprungene Listens ignorieren"
+ },
+ {
+ "id": "Specify a time zone for the listen timestamps",
+ "message": "Specify a time zone for the listen timestamps",
+ "translation": "Zeitzone für den Abspiel-Zeitstempel"
},
{
"id": "Directory path",
@@ -319,28 +324,23 @@
"message": "Ignore listens in incognito mode",
"translation": "Listens im Inkognito-Modus ignorieren"
},
- {
- "id": "Ignore skipped listens",
- "message": "Ignore skipped listens",
- "translation": "Übersprungene Listens ignorieren"
- },
{
"id": "Minimum playback duration for skipped tracks (seconds)",
"message": "Minimum playback duration for skipped tracks (seconds)",
"translation": "Minimale Wiedergabedauer für übersprungene Titel (Sekunden)"
},
{
- "id": "Visit the URL for authorization: {Url}",
- "message": "Visit the URL for authorization: {Url}",
- "translation": "URL für Autorisierung öffnen: {Url}",
+ "id": "Visit the URL for authorization: {URL}",
+ "message": "Visit the URL for authorization: {URL}",
+ "translation": "Zur Anmeldung folgende URL aufrufen: {URL}",
"placeholders": [
{
- "id": "Url",
+ "id": "URL",
"string": "%[1]v",
"type": "string",
"underlyingType": "string",
"argNum": 1,
- "expr": "authUrl.Url"
+ "expr": "authURL.URL"
}
]
},
@@ -411,9 +411,9 @@
"translation": "Backend"
},
{
- "id": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "message": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}...",
+ "id": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "message": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}…",
"placeholders": [
{
"id": "Entity",
diff --git a/internal/translations/locales/en/messages.gotext.json b/internal/translations/locales/en/messages.gotext.json
index 7687276..ed62636 100644
--- a/internal/translations/locales/en/messages.gotext.json
+++ b/internal/translations/locales/en/messages.gotext.json
@@ -311,9 +311,9 @@
"fuzzy": true
},
{
- "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})",
- "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})",
- "translation": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})",
+ "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
+ "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
+ "translation": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -341,12 +341,12 @@
"expr": "l.ArtistName()"
},
{
- "id": "RecordingMbid",
+ "id": "RecordingMBID",
"string": "%[4]v",
- "type": "go.uploadedlobster.com/scotty/internal/models.MBID",
+ "type": "go.uploadedlobster.com/mbtypes.MBID",
"underlyingType": "string",
"argNum": 4,
- "expr": "l.RecordingMbid"
+ "expr": "l.RecordingMBID"
}
],
"fuzzy": true
@@ -359,9 +359,16 @@
"fuzzy": true
},
{
- "id": "Include skipped listens",
- "message": "Include skipped listens",
- "translation": "Include skipped listens",
+ "id": "Ignore skipped listens",
+ "message": "Ignore skipped listens",
+ "translation": "Ignore skipped listens",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Specify a time zone for the listen timestamps",
+ "message": "Specify a time zone for the listen timestamps",
+ "translation": "Specify a time zone for the listen timestamps",
"translatorComment": "Copied from source.",
"fuzzy": true
},
@@ -379,13 +386,6 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
- {
- "id": "Ignore skipped listens",
- "message": "Ignore skipped listens",
- "translation": "Ignore skipped listens",
- "translatorComment": "Copied from source.",
- "fuzzy": true
- },
{
"id": "Minimum playback duration for skipped tracks (seconds)",
"message": "Minimum playback duration for skipped tracks (seconds)",
@@ -394,18 +394,18 @@
"fuzzy": true
},
{
- "id": "Visit the URL for authorization: {Url}",
- "message": "Visit the URL for authorization: {Url}",
- "translation": "Visit the URL for authorization: {Url}",
+ "id": "Visit the URL for authorization: {URL}",
+ "message": "Visit the URL for authorization: {URL}",
+ "translation": "Visit the URL for authorization: {URL}",
"translatorComment": "Copied from source.",
"placeholders": [
{
- "id": "Url",
+ "id": "URL",
"string": "%[1]v",
"type": "string",
"underlyingType": "string",
"argNum": 1,
- "expr": "authUrl.Url"
+ "expr": "authURL.URL"
}
],
"fuzzy": true
@@ -491,9 +491,9 @@
"fuzzy": true
},
{
- "id": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "message": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "translation": "Transferring {Entity} from {SourceName} to {TargetName}...",
+ "id": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "message": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "translation": "Transferring {Entity} from {SourceName} to {TargetName}…",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -714,4 +714,4 @@
"fuzzy": true
}
]
-}
\ No newline at end of file
+}
diff --git a/internal/translations/locales/en/out.gotext.json b/internal/translations/locales/en/out.gotext.json
index 54c6719..eecf359 100644
--- a/internal/translations/locales/en/out.gotext.json
+++ b/internal/translations/locales/en/out.gotext.json
@@ -359,9 +359,16 @@
"fuzzy": true
},
{
- "id": "Include skipped listens",
- "message": "Include skipped listens",
- "translation": "Include skipped listens",
+ "id": "Ignore skipped listens",
+ "message": "Ignore skipped listens",
+ "translation": "Ignore skipped listens",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Specify a time zone for the listen timestamps",
+ "message": "Specify a time zone for the listen timestamps",
+ "translation": "Specify a time zone for the listen timestamps",
"translatorComment": "Copied from source.",
"fuzzy": true
},
@@ -379,13 +386,6 @@
"translatorComment": "Copied from source.",
"fuzzy": true
},
- {
- "id": "Ignore skipped listens",
- "message": "Ignore skipped listens",
- "translation": "Ignore skipped listens",
- "translatorComment": "Copied from source.",
- "fuzzy": true
- },
{
"id": "Minimum playback duration for skipped tracks (seconds)",
"message": "Minimum playback duration for skipped tracks (seconds)",
@@ -394,18 +394,18 @@
"fuzzy": true
},
{
- "id": "Visit the URL for authorization: {Url}",
- "message": "Visit the URL for authorization: {Url}",
- "translation": "Visit the URL for authorization: {Url}",
+ "id": "Visit the URL for authorization: {URL}",
+ "message": "Visit the URL for authorization: {URL}",
+ "translation": "Visit the URL for authorization: {URL}",
"translatorComment": "Copied from source.",
"placeholders": [
{
- "id": "Url",
+ "id": "URL",
"string": "%[1]v",
"type": "string",
"underlyingType": "string",
"argNum": 1,
- "expr": "authUrl.Url"
+ "expr": "authURL.URL"
}
],
"fuzzy": true
@@ -491,9 +491,9 @@
"fuzzy": true
},
{
- "id": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "message": "Transferring {Entity} from {SourceName} to {TargetName}...",
- "translation": "Transferring {Entity} from {SourceName} to {TargetName}...",
+ "id": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "message": "Transferring {Entity} from {SourceName} to {TargetName}…",
+ "translation": "Transferring {Entity} from {SourceName} to {TargetName}…",
"translatorComment": "Copied from source.",
"placeholders": [
{
diff --git a/internal/version/version.go b/internal/version/version.go
index 818bec1..07d1569 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -1,5 +1,5 @@
/*
-Copyright © 2023-2024 Philipp Wolfer
+Copyright © 2023-2025 Philipp Wolfer
Scotty is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -17,7 +17,7 @@ package version
const (
AppName = "scotty"
- AppVersion = "0.4.1"
+ AppVersion = "0.5.0"
AppURL = "https://git.sr.ht/~phw/scotty/"
)
diff --git a/pkg/jspf/extensions.go b/pkg/jspf/extensions.go
index 07cd3c1..0f521c4 100644
--- a/pkg/jspf/extensions.go
+++ b/pkg/jspf/extensions.go
@@ -26,9 +26,9 @@ import "time"
const (
// The identifier for the MusicBrainz / ListenBrainz JSPF playlist extension
- MusicBrainzPlaylistExtensionId = "https://musicbrainz.org/doc/jspf#playlist"
+ MusicBrainzPlaylistExtensionID = "https://musicbrainz.org/doc/jspf#playlist"
// The identifier for the MusicBrainz / ListenBrainz JSPF track extension
- MusicBrainzTrackExtensionId = "https://musicbrainz.org/doc/jspf#track"
+ MusicBrainzTrackExtensionID = "https://musicbrainz.org/doc/jspf#track"
)
// MusicBrainz / ListenBrainz JSPF track extension
diff --git a/pkg/jspf/extensions_test.go b/pkg/jspf/extensions_test.go
index 8d8653d..883301d 100644
--- a/pkg/jspf/extensions_test.go
+++ b/pkg/jspf/extensions_test.go
@@ -39,7 +39,7 @@ func ExampleMusicBrainzTrackExtension() {
{
Title: "Oweynagat",
Extension: map[string]any{
- jspf.MusicBrainzTrackExtensionId: jspf.MusicBrainzTrackExtension{
+ jspf.MusicBrainzTrackExtensionID: jspf.MusicBrainzTrackExtension{
AddedAt: time.Date(2023, 11, 24, 07, 47, 50, 0, time.UTC),
AddedBy: "scotty",
},
diff --git a/pkg/scrobblerlog/parser.go b/pkg/scrobblerlog/parser.go
index 892f6e8..9c6471c 100644
--- a/pkg/scrobblerlog/parser.go
+++ b/pkg/scrobblerlog/parser.go
@@ -45,16 +45,16 @@ import (
type TZInfo string
const (
- TZ_UNKNOWN TZInfo = "UNKNOWN"
- TZ_UTC TZInfo = "UTC"
+ TimezoneUnknown TZInfo = "UNKNOWN"
+ TimezoneUTC TZInfo = "UTC"
)
// L if listened at least 50% or S if skipped
type Rating string
const (
- RATING_LISTENED Rating = "L"
- RATING_SKIPPED Rating = "S"
+ RatingListened Rating = "L"
+ RatingSkipped Rating = "S"
)
// A single entry of a track in the scrobbler log file.
@@ -75,7 +75,7 @@ type ScrobblerLog struct {
Client string
Records []Record
// Timezone to be used for timestamps in the log file,
- // if TZ is set to [TZ_UNKNOWN].
+ // if TZ is set to [TimezoneUnknown].
FallbackTimezone *time.Location
}
@@ -116,7 +116,7 @@ func (l *ScrobblerLog) Parse(data io.Reader, ignoreSkipped bool) error {
return err
}
- if ignoreSkipped && record.Rating == RATING_SKIPPED {
+ if ignoreSkipped && record.Rating == RatingSkipped {
continue
}
@@ -224,7 +224,7 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) {
}
var timezone *time.Location = nil
- if l.TZ == TZ_UNKNOWN {
+ if l.TZ == TimezoneUnknown {
timezone = l.FallbackTimezone
}
diff --git a/pkg/scrobblerlog/parser_test.go b/pkg/scrobblerlog/parser_test.go
index 7fd57c3..f4527cc 100644
--- a/pkg/scrobblerlog/parser_test.go
+++ b/pkg/scrobblerlog/parser_test.go
@@ -50,7 +50,7 @@ func TestParser(t *testing.T) {
result := scrobblerlog.ScrobblerLog{}
err := result.Parse(data, false)
require.NoError(t, err)
- assert.Equal(scrobblerlog.TZ_UNKNOWN, result.TZ)
+ assert.Equal(scrobblerlog.TimezoneUnknown, result.TZ)
assert.Equal("Rockbox sansaclipplus $Revision$", result.Client)
assert.Len(result.Records, 5)
record1 := result.Records[0]
@@ -59,11 +59,11 @@ func TestParser(t *testing.T) {
assert.Equal("Sevdanin rengi (sipacik) byMrTurkey", record1.TrackName)
assert.Equal(5, record1.TrackNumber)
assert.Equal(time.Duration(306*time.Second), record1.Duration)
- assert.Equal(scrobblerlog.RATING_LISTENED, record1.Rating)
+ assert.Equal(scrobblerlog.RatingListened, record1.Rating)
assert.Equal(time.Unix(1260342084, 0), record1.Timestamp)
assert.Equal(mbtypes.MBID(""), record1.MusicBrainzRecordingID)
record4 := result.Records[3]
- assert.Equal(scrobblerlog.RATING_SKIPPED, record4.Rating)
+ assert.Equal(scrobblerlog.RatingSkipped, record4.Rating)
assert.Equal(mbtypes.MBID("385ba9e9-626d-4750-a607-58e541dca78e"),
record4.MusicBrainzRecordingID)
}
@@ -76,7 +76,7 @@ func TestParserIgnoreSkipped(t *testing.T) {
require.NoError(t, err)
assert.Len(result.Records, 4)
record4 := result.Records[3]
- assert.Equal(scrobblerlog.RATING_LISTENED, record4.Rating)
+ assert.Equal(scrobblerlog.RatingListened, record4.Rating)
assert.Equal(mbtypes.MBID("1262beaf-19f8-4534-b9ed-7eef9ca8e83f"),
record4.MusicBrainzRecordingID)
}
@@ -101,7 +101,7 @@ func TestAppend(t *testing.T) {
data := make([]byte, 0, 10)
buffer := bytes.NewBuffer(data)
log := scrobblerlog.ScrobblerLog{
- TZ: scrobblerlog.TZ_UNKNOWN,
+ TZ: scrobblerlog.TimezoneUnknown,
Client: "Rockbox foo $Revision$",
}
records := []scrobblerlog.Record{
@@ -111,7 +111,7 @@ func TestAppend(t *testing.T) {
TrackName: "Reign",
TrackNumber: 1,
Duration: 271 * time.Second,
- Rating: scrobblerlog.RATING_LISTENED,
+ Rating: scrobblerlog.RatingListened,
Timestamp: time.Unix(1699572072, 0),
MusicBrainzRecordingID: mbtypes.MBID("b59cf4e7-caee-4019-a844-79d2c58d4dff"),
},
@@ -139,7 +139,7 @@ func TestReadHeader(t *testing.T) {
log := scrobblerlog.ScrobblerLog{}
err := log.ReadHeader(reader)
assert.NoError(t, err)
- assert.Equal(t, log.TZ, scrobblerlog.TZ_UNKNOWN)
+ assert.Equal(t, log.TZ, scrobblerlog.TimezoneUnknown)
assert.Equal(t, log.Client, "Rockbox sansaclipplus $Revision$")
assert.Empty(t, log.Records)
}