From 5a85987476cad45d4e092620fc6544a28061fe79 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 14 Nov 2023 08:41:53 +0100 Subject: [PATCH] Maloja listens import --- backends/maloja/client.go | 15 +++++++ backends/maloja/client_test.go | 23 +++++++++++ backends/maloja/maloja.go | 39 +++++++++++++++++++ backends/maloja/models.go | 32 ++++++++++++++- .../maloja/testdata/newscrobble-result.json | 10 +++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 backends/maloja/testdata/newscrobble-result.json diff --git a/backends/maloja/client.go b/backends/maloja/client.go index 46020fe..0c502ff 100644 --- a/backends/maloja/client.go +++ b/backends/maloja/client.go @@ -61,3 +61,18 @@ func (c Client) GetScrobbles(page int, perPage int) (result GetScrobblesResult, } return } + +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(). + SetBody(scrobble). + SetResult(&result). + Post(path) + + if response.StatusCode() != 200 { + err = errors.New(response.String()) + return + } + return +} diff --git a/backends/maloja/client_test.go b/backends/maloja/client_test.go index f7f7298..b4caaf4 100644 --- a/backends/maloja/client_test.go +++ b/backends/maloja/client_test.go @@ -57,6 +57,29 @@ func TestGetScrobbles(t *testing.T) { assert.Equal(int64(558), result.List[0].Duration) } +func TestNewScrobble(t *testing.T) { + server := "https://maloja.example.com" + client := maloja.NewClient(server, "thetoken") + httpmock.ActivateNonDefault(client.HttpClient.GetClient()) + + responder, err := httpmock.NewJsonResponder(200, httpmock.File("testdata/newscrobble-result.json")) + if err != nil { + t.Fatal(err) + } + url := server + "/apis/mlj_1/newscrobble" + httpmock.RegisterResponder("POST", url, responder) + + scrobble := maloja.NewScrobble{ + Title: "Oweynagat", + Artist: "Dool", + Time: 1699574369, + } + result, err := client.NewScrobble(scrobble) + require.NoError(t, err) + + assert.Equal(t, "success", result.Status) +} + func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) diff --git a/backends/maloja/maloja.go b/backends/maloja/maloja.go index c42b765..e82adda 100644 --- a/backends/maloja/maloja.go +++ b/backends/maloja/maloja.go @@ -22,6 +22,7 @@ THE SOFTWARE. package maloja import ( + "errors" "slices" "strings" "time" @@ -32,6 +33,7 @@ import ( type MalojaApiBackend struct { client Client + nofix bool } func (b MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend { @@ -39,6 +41,7 @@ func (b MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend { config.GetString("server-url"), config.GetString("token"), ) + b.nofix = config.GetBool("nofix") return b } @@ -75,6 +78,42 @@ out: return listens, nil } +func (b MalojaApiBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (models.ImportResult, error) { + result := models.ImportResult{ + TotalCount: len(listens), + ImportCount: 0, + LastTimestamp: oldestTimestamp, + } + for _, listen := range listens { + if listen.ListenedAt.Unix() <= oldestTimestamp.Unix() { + continue + } + + scrobble := NewScrobble{ + Title: listen.TrackName, + Artists: listen.ArtistNames, + Album: listen.ReleaseName, + Duration: int64(listen.PlaybackDuration.Seconds()), + Length: int64(listen.Duration.Seconds()), + Time: listen.ListenedAt.Unix(), + Nofix: b.nofix, + } + + resp, err := b.client.NewScrobble(scrobble) + if err != nil { + return result, err + } else if resp.Status != "success" { + return result, errors.New(resp.Error.Description) + } + + if listen.ListenedAt.Unix() > result.LastTimestamp.Unix() { + result.LastTimestamp = listen.ListenedAt + } + result.ImportCount += 1 + } + return result, nil +} + func (s Scrobble) ToListen() models.Listen { track := s.Track listen := models.Listen{ diff --git a/backends/maloja/models.go b/backends/maloja/models.go index e6da57b..1957370 100644 --- a/backends/maloja/models.go +++ b/backends/maloja/models.go @@ -21,12 +21,23 @@ THE SOFTWARE. */ package maloja +type GenericResult struct { + Status string `json:"status"` +} + type GetScrobblesResult struct { - Status string `json:"status"` + GenericResult List []Scrobble `json:"list"` Pagination Pagination `json:"pagination"` } +type NewScrobbleResult struct { + GenericResult + Track Track `json:"track"` + Description string `json:"desc"` + Error Error `json:"error"` +} + type Scrobble struct { ListenedAt int64 `json:"time"` Duration int64 `json:"duration"` @@ -36,6 +47,19 @@ type Scrobble struct { Track Track `json:"track"` } +type NewScrobble struct { + Key string `json:"key"` + Artist string `json:"artist,omitempty"` + Artists []string `json:"artists,omitempty"` + Title string `json:"title"` + Album string `json:"album,omitempty"` + AlbumArtists []string `json:"albumartists,omitempty"` + Duration int64 `json:"duration,omitempty"` + Length int64 `json:"length,omitempty"` + Time int64 `json:"time,omitempty"` + Nofix bool `json:"nofix,omitempty"` +} + type Track struct { Title string `json:"title"` Artists []string `json:"artists"` @@ -54,3 +78,9 @@ type Pagination struct { NextPage string `json:"next_page"` PrevPage string `json:"prev_page"` } + +type Error struct { + Type string `json:"type"` + Value string `json:"value"` + Description string `json:"desc"` +} diff --git a/backends/maloja/testdata/newscrobble-result.json b/backends/maloja/testdata/newscrobble-result.json new file mode 100644 index 0000000..f282d78 --- /dev/null +++ b/backends/maloja/testdata/newscrobble-result.json @@ -0,0 +1,10 @@ +{ + "status": "success", + "track": { + "artists": [ + "Dool" + ], + "title": "Oweynagat" + }, + "desc": "Scrobbled Oweynagat by Dool" +}