From 8e1736703dabf844e1b1ba2d18949183c0fcb788 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 21 Mar 2016 19:35:40 -0400 Subject: [PATCH] Scrobble accepts multiple ids --- api/base_api_controller.go | 24 ++++++++++++++- api/media_annotation.go | 62 ++++++++++++++++++++++---------------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/api/base_api_controller.go b/api/base_api_controller.go index 9225b7206..a02df6ff7 100644 --- a/api/base_api_controller.go +++ b/api/base_api_controller.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "strconv" + "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" "github.com/deluan/gosonic/engine" @@ -25,6 +27,14 @@ func (c *BaseAPIController) RequiredParamString(param string, msg string) string return p } +func (c *BaseAPIController) RequiredParamStrings(param string, msg string) []string { + ps := c.Input()[param] + if len(ps) == 0 { + c.SendError(responses.ERROR_MISSING_PARAMETER, msg) + } + return ps +} + func (c *BaseAPIController) ParamString(param string) string { return c.Input().Get(param) } @@ -38,6 +48,18 @@ func (c *BaseAPIController) ParamTime(param string, def time.Time) time.Time { return utils.ToTime(value) } +func (c *BaseAPIController) ParamTimes(param string) []time.Time { + pStr := c.Input()[param] + times := make([]time.Time, len(pStr)) + for i, t := range pStr { + ti, err := strconv.ParseInt(t, 10, 64) + if err == nil { + times[i] = utils.ToTime(ti) + } + } + return times +} + func (c *BaseAPIController) ParamInt(param string, def int) int { value := def c.Ctx.Input.Bind(&value, param) @@ -59,7 +81,7 @@ func (c *BaseAPIController) SendError(errorCode int, message ...interface{}) { if len(message) == 0 { msg = responses.ErrorMsg(errorCode) } else { - msg = fmt.Sprintf(message[0].(string), message[1:len(message)]...) + msg = fmt.Sprintf(message[0].(string), message[1:]...) } response.Error = &responses.Error{Code: errorCode, Message: msg} diff --git a/api/media_annotation.go b/api/media_annotation.go index 7c94ee5f0..c5ebe7d4b 100644 --- a/api/media_annotation.go +++ b/api/media_annotation.go @@ -20,38 +20,48 @@ func (c *MediaAnnotationController) Prepare() { } func (c *MediaAnnotationController) Scrobble() { - id := c.RequiredParamString("id", "Required id parameter is missing") - time := c.ParamTime("time", time.Now()) - submission := c.ParamBool("submission", false) - + ids := c.RequiredParamStrings("id", "Required id parameter is missing") + times := c.ParamTimes("time") + if len(times) > 0 && len(times) != len(ids) { + c.SendError(responses.ERROR_GENERIC, fmt.Sprintf("Wrong number of timestamps: %d", len(times))) + } + submission := c.ParamBool("submission", true) playerId := 1 // TODO Multiple players, based on playerName/username/clientIP(?) playerName := c.ParamString("c") username := c.ParamString("u") - skip, err := c.scrobbler.DetectSkipped(playerId, id, submission) - if err != nil { - beego.Error("Error detecting skip:", err) - } - if skip { - beego.Info("Skipped previous song") - } - - if submission { - mf, err := c.scrobbler.Register(playerId, id, time) - if err != nil { - beego.Error("Error scrobbling:", err) - c.SendError(responses.ERROR_GENERIC, "Internal error") + for i := range ids { + var t time.Time + if len(times) > 0 { + t = times[i] + } else { + t = time.Now() } - beego.Info(fmt.Sprintf(`Scrobbled (%s) "%s" at %v`, id, mf.Title, time)) - } else { - mf, err := c.scrobbler.NowPlaying(playerId, id, username, playerName) - if err != nil { - beego.Error("Error setting", id, "as current song:", err) - c.SendError(responses.ERROR_GENERIC, "Internal error") - } - beego.Info(fmt.Sprintf(`Current Song (%s) "%s" at %v`, id, mf.Title, time)) - } + // TODO Fix skipped songs + //skip, err := c.scrobbler.DetectSkipped(playerId, id, submission) + //if err != nil { + // beego.Error("Error detecting skip:", err) + //} + //if skip { + // beego.Info("Skipped previous song") + //} + if submission { + mf, err := c.scrobbler.Register(playerId, ids[i], t) + if err != nil { + beego.Error("Error scrobbling:", err) + c.SendError(responses.ERROR_GENERIC, "Internal error") + } + beego.Info(fmt.Sprintf(`Scrobbled (%s) "%s" at %v`, ids[i], mf.Title, t)) + } else { + mf, err := c.scrobbler.NowPlaying(playerId, ids[i], username, playerName) + if err != nil { + beego.Error("Error setting", ids[i], "as current song:", err) + c.SendError(responses.ERROR_GENERIC, "Internal error") + } + beego.Info(fmt.Sprintf(`Current Song (%s) "%s" at %v`, ids[i], mf.Title, t)) + } + } response := c.NewEmpty() c.SendResponse(response) }