lastfm: loves import

This commit is contained in:
Philipp Wolfer 2023-11-26 12:56:27 +01:00
parent 1249238d3a
commit 406e150987
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B
5 changed files with 57 additions and 6 deletions

View file

@ -44,7 +44,7 @@ deezer | ✓ | | ✓ | -
dump | | ✓ | | ✓
funkwhale | ✓ | | ✓ | -
jspf | - | ✓ | - | ✓
lastfm | - | - | - | -
lastfm | - | - | ✓ | ✓
listenbrainz | ✓ | ✓ | ✓ | ✓
maloja | ✓ | ✓ | |
scrobbler-log | ✓ | ✓ | |

View file

@ -49,7 +49,10 @@ func Authenticate(service string, backend models.Backend, db storage.Database, c
}
conf := authenticator.OAuth2Strategy(redirectURL).Config()
tokenSource := auth.NewDatabaseTokenSource(db, service, &conf, token)
authenticator.OAuth2Setup(tokenSource)
err = authenticator.OAuth2Setup(tokenSource)
if err != nil {
return needAuth, err
}
}
return needAuth, nil
}

View file

@ -24,12 +24,15 @@ import (
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"go.uploadedlobster.com/scotty/internal/backends"
"go.uploadedlobster.com/scotty/internal/backends/deezer"
"go.uploadedlobster.com/scotty/internal/backends/dump"
"go.uploadedlobster.com/scotty/internal/backends/funkwhale"
"go.uploadedlobster.com/scotty/internal/backends/jspf"
"go.uploadedlobster.com/scotty/internal/backends/lastfm"
"go.uploadedlobster.com/scotty/internal/backends/listenbrainz"
"go.uploadedlobster.com/scotty/internal/backends/maloja"
"go.uploadedlobster.com/scotty/internal/backends/scrobblerlog"
"go.uploadedlobster.com/scotty/internal/backends/spotify"
"go.uploadedlobster.com/scotty/internal/backends/subsonic"
"go.uploadedlobster.com/scotty/internal/models"
)
@ -73,6 +76,10 @@ func TestGetBackends(t *testing.T) {
}
func TestImplementsInterfaces(t *testing.T) {
expectInterface[models.ListensExport](t, &deezer.DeezerApiBackend{})
expectInterface[models.LovesExport](t, &deezer.DeezerApiBackend{})
// expectInterface[models.LovesImport](t, &deezer.DeezerApiBackend{})
expectInterface[models.ListensImport](t, &dump.DumpBackend{})
expectInterface[models.LovesImport](t, &dump.DumpBackend{})
@ -82,18 +89,27 @@ func TestImplementsInterfaces(t *testing.T) {
// expectInterface[models.LovesImport](t, &funkwhale.FunkwhaleApiBackend{})
// expectInterface[models.ListensExport](t, &jspf.JSPFBackend{})
// expectInterface[models.ListensImport](t, &jspf.JSPFBackend{})
expectInterface[models.ListensImport](t, &jspf.JSPFBackend{})
// expectInterface[models.LovesExport](t, &jspf.JSPFBackend{})
expectInterface[models.LovesImport](t, &jspf.JSPFBackend{})
// expectInterface[models.ListensExport](t, &lastfm.LastfmApiBackend{})
// expectInterface[models.ListensImport](t, &lastfm.LastfmApiBackend{})
expectInterface[models.LovesExport](t, &lastfm.LastfmApiBackend{})
expectInterface[models.LovesImport](t, &lastfm.LastfmApiBackend{})
expectInterface[models.ListensExport](t, &listenbrainz.ListenBrainzApiBackend{})
// expectInterface[models.ListensImport](t, &listenbrainz.ListenBrainzApiBackend{})
expectInterface[models.ListensImport](t, &listenbrainz.ListenBrainzApiBackend{})
expectInterface[models.LovesExport](t, &listenbrainz.ListenBrainzApiBackend{})
expectInterface[models.LovesImport](t, &listenbrainz.ListenBrainzApiBackend{})
expectInterface[models.ListensExport](t, &maloja.MalojaApiBackend{})
expectInterface[models.ListensImport](t, &maloja.MalojaApiBackend{})
expectInterface[models.ListensExport](t, &spotify.SpotifyApiBackend{})
expectInterface[models.LovesExport](t, &spotify.SpotifyApiBackend{})
// expectInterface[models.LovesImport](t, &spotify.SpotifyApiBackend{})
expectInterface[models.ListensExport](t, &scrobblerlog.ScrobblerLogBackend{})
expectInterface[models.ListensImport](t, &scrobblerlog.ScrobblerLogBackend{})

View file

@ -47,5 +47,10 @@ func (s lastfmStrategy) AuthCodeURL(verifier string, state string) auth.AuthUrl
func (s lastfmStrategy) ExchangeToken(code auth.CodeResponse, verifier string) (*oauth2.Token, error) {
// The token is directly valid
return &oauth2.Token{AccessToken: code.Code}, nil
err := s.client.LoginWithToken(code.Code)
if err != nil {
return nil, err
}
sk := s.client.GetSessionKey()
return &oauth2.Token{AccessToken: sk}, nil
}

View file

@ -16,6 +16,7 @@ Scotty. If not, see <https://www.gnu.org/licenses/>.
package lastfm
import (
"fmt"
"net/url"
"sort"
"strconv"
@ -45,6 +46,9 @@ func (b *LastfmApiBackend) FromConfig(config *viper.Viper) models.Backend {
return b
}
func (b *LastfmApiBackend) StartImport() error { return nil }
func (b *LastfmApiBackend) FinishImport() error { return nil }
func (b *LastfmApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy {
return lastfmStrategy{
client: b.client,
@ -57,7 +61,8 @@ func (b *LastfmApiBackend) OAuth2Setup(token oauth2.TokenSource) error {
if err != nil {
return err
}
return b.client.LoginWithToken(t.AccessToken)
b.client.SetSession(t.AccessToken)
return nil
}
func (b *LastfmApiBackend) ExportLoves(oldestTimestamp time.Time, results chan models.LovesResult, progress chan models.Progress) {
@ -130,3 +135,25 @@ out:
results <- models.LovesResult{Loves: loves, Total: totalCount}
progress <- p.Complete()
}
func (b *LastfmApiBackend) ImportLoves(export models.LovesResult, importResult models.ImportResult, progress chan models.Progress) (models.ImportResult, error) {
for _, love := range export.Loves {
err := b.client.Track.Love(lastfm.P{
"track": love.TrackName,
"artist": love.ArtistName(),
})
if err == nil {
importResult.UpdateTimestamp(love.Created)
importResult.ImportCount += 1
} else {
msg := fmt.Sprintf("Failed import of \"%s\" by %s: %v",
love.TrackName, love.ArtistName(), err.Error())
importResult.ImportErrors = append(importResult.ImportErrors, msg)
}
progress <- models.Progress{}.FromImportResult(importResult)
}
return importResult, nil
}