server/lastfm: make a scrobbler interface and migrate lastfm to use it

This commit is contained in:
Alex McGrath
2021-01-08 13:09:42 +00:00
committed by Senan Kelly
parent cc93d61908
commit f4ff7e70f2
5 changed files with 38 additions and 12 deletions

View File

@@ -13,6 +13,7 @@ import (
"go.senan.xyz/gonic/server/ctrlsubsonic/params" "go.senan.xyz/gonic/server/ctrlsubsonic/params"
"go.senan.xyz/gonic/server/ctrlsubsonic/spec" "go.senan.xyz/gonic/server/ctrlsubsonic/spec"
"go.senan.xyz/gonic/server/jukebox" "go.senan.xyz/gonic/server/jukebox"
"go.senan.xyz/gonic/server/lastfm"
) )
type CtxKey int type CtxKey int
@@ -28,6 +29,7 @@ type Controller struct {
CachePath string CachePath string
CoverCachePath string CoverCachePath string
Jukebox *jukebox.Jukebox Jukebox *jukebox.Jukebox
Scrobblers []lastfm.Scrobbler
} }
type metaResponse struct { type metaResponse struct {

View File

@@ -61,14 +61,16 @@ func (c *Controller) ServeScrobble(r *http.Request) *spec.Response {
StampMili: params.GetOrInt("time", int(time.Now().UnixNano()/1e6)), StampMili: params.GetOrInt("time", int(time.Now().UnixNano()/1e6)),
Submission: params.GetOrBool("submission", true), Submission: params.GetOrBool("submission", true),
} }
err = lastfm.Scrobble( scrobbleErrs := []error{}
c.DB.GetSetting("lastfm_api_key"), for _, scrobbler := range c.Scrobblers {
c.DB.GetSetting("lastfm_secret"), if !scrobbler.Enabled(user) {
user.LastFMSession, continue
opts, }
) err = scrobbler.Scrobble(user, opts)
if err != nil { scrobbleErrs = append(scrobbleErrs, err)
return spec.NewError(0, "error when submitting: %v", err) }
if len(scrobbleErrs) != 0 {
return spec.NewError(0, "error when submitting: %v", scrobbleErrs)
} }
return spec.NewResponse() return spec.NewResponse()
} }

View File

@@ -15,7 +15,8 @@ import (
) )
const ( const (
baseURL = "https://ws.audioscrobbler.com/2.0/" lastfmBaseURL = "https://ws.audioscrobbler.com/2.0/"
lbBaseURL = "https://api.listenbrainz.org"
) )
var ( var (
@@ -42,7 +43,7 @@ func getParamSignature(params url.Values, secret string) string {
} }
func makeRequest(method string, params url.Values) (LastFM, error) { func makeRequest(method string, params url.Values) (LastFM, error) {
req, _ := http.NewRequest(method, baseURL, nil) req, _ := http.NewRequest(method, lastfmBaseURL, nil)
req.URL.RawQuery = params.Encode() req.URL.RawQuery = params.Encode()
resp, err := http.DefaultClient.Do(req) resp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
@@ -79,7 +80,18 @@ type ScrobbleOptions struct {
Submission bool Submission bool
} }
func Scrobble(apiKey, secret, session string, opts ScrobbleOptions) error { type LastfmScrobbler struct { //nolint
DB *db.DB
}
func (lfm *LastfmScrobbler) Scrobble(reqUser interface{}, opts ScrobbleOptions) error {
apiKey := lfm.DB.GetSetting("lastfm_api_key")
secret := lfm.DB.GetSetting("lastfm_secret")
// fetch user to get lastfm session
user := reqUser.(*db.User)
if user.LastFMSession == "" {
return fmt.Errorf("you don't have a last.fm session: %w", ErrLastFM)
}
params := url.Values{} params := url.Values{}
if opts.Submission { if opts.Submission {
params.Add("method", "track.Scrobble") params.Add("method", "track.Scrobble")
@@ -89,7 +101,7 @@ func Scrobble(apiKey, secret, session string, opts ScrobbleOptions) error {
params.Add("method", "track.updateNowPlaying") params.Add("method", "track.updateNowPlaying")
} }
params.Add("api_key", apiKey) params.Add("api_key", apiKey)
params.Add("sk", session) params.Add("sk", user.LastFMSession)
params.Add("artist", opts.Track.TagTrackArtist) params.Add("artist", opts.Track.TagTrackArtist)
params.Add("track", opts.Track.TagTitle) params.Add("track", opts.Track.TagTitle)
params.Add("trackNumber", strconv.Itoa(opts.Track.TagTrackNumber)) params.Add("trackNumber", strconv.Itoa(opts.Track.TagTrackNumber))

View File

@@ -4,6 +4,10 @@ import (
"encoding/xml" "encoding/xml"
) )
type Scrobbler interface {
Scrobble(interface{}, ScrobbleOptions) error
}
type LastFM struct { type LastFM struct {
XMLName xml.Name `xml:"lfm"` XMLName xml.Name `xml:"lfm"`
Status string `xml:"status,attr"` Status string `xml:"status,attr"`

View File

@@ -17,6 +17,7 @@ import (
"go.senan.xyz/gonic/server/ctrlsubsonic" "go.senan.xyz/gonic/server/ctrlsubsonic"
"go.senan.xyz/gonic/server/db" "go.senan.xyz/gonic/server/db"
"go.senan.xyz/gonic/server/jukebox" "go.senan.xyz/gonic/server/jukebox"
"go.senan.xyz/gonic/server/lastfm"
"go.senan.xyz/gonic/server/scanner" "go.senan.xyz/gonic/server/scanner"
) )
@@ -62,11 +63,16 @@ func New(opts Options) *Server {
sessDB.SessionOpts.SameSite = http.SameSiteLaxMode sessDB.SessionOpts.SameSite = http.SameSiteLaxMode
// //
ctrlAdmin := ctrladmin.New(base, sessDB) ctrlAdmin := ctrladmin.New(base, sessDB)
lastfmScrobbler := &lastfm.LastfmScrobbler{DB: opts.DB}
scrobblers := []lastfm.Scrobbler{
lastfmScrobbler,
}
ctrlSubsonic := &ctrlsubsonic.Controller{ ctrlSubsonic := &ctrlsubsonic.Controller{
Controller: base, Controller: base,
CachePath: opts.CachePath, CachePath: opts.CachePath,
CoverCachePath: opts.CoverCachePath, CoverCachePath: opts.CoverCachePath,
Jukebox: jukebox, Jukebox: jukebox,
Scrobblers: scrobblers,
} }
setupMisc(r, base) setupMisc(r, base)
setupAdmin(r.PathPrefix("/admin").Subrouter(), ctrlAdmin) setupAdmin(r.PathPrefix("/admin").Subrouter(), ctrlAdmin)