package api import ( "encoding/xml" "fmt" "time" "strconv" "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" ) type BaseAPIController struct{ beego.Controller } func (c *BaseAPIController) NewEmpty() responses.Subsonic { return responses.Subsonic{Status: "ok", Version: beego.AppConfig.String("apiVersion")} } func (c *BaseAPIController) RequiredParamString(param string, msg string) string { p := c.Input().Get(param) if p == "" { c.SendError(responses.ErrorMissingParameter, msg) } return p } func (c *BaseAPIController) RequiredParamStrings(param string, msg string) []string { ps := c.Input()[param] if len(ps) == 0 { c.SendError(responses.ErrorMissingParameter, msg) } return ps } func (c *BaseAPIController) ParamString(param string) string { return c.Input().Get(param) } func (c *BaseAPIController) ParamStrings(param string) []string { return c.Input()[param] } func (c *BaseAPIController) ParamTime(param string, def time.Time) time.Time { if c.Input().Get(param) == "" { return def } var value int64 c.Ctx.Input.Bind(&value, param) 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) RequiredParamInt(param string, msg string) int { p := c.Input().Get(param) if p == "" { c.SendError(responses.ErrorMissingParameter, msg) } return c.ParamInt(param, 0) } func (c *BaseAPIController) ParamInt(param string, def int) int { if c.Input().Get(param) == "" { return def } var value int c.Ctx.Input.Bind(&value, param) return value } func (c *BaseAPIController) ParamInts(param string) []int { pStr := c.Input()[param] ints := make([]int, 0, len(pStr)) for _, s := range pStr { i, err := strconv.ParseInt(s, 10, 32) if err == nil { ints = append(ints, int(i)) } } return ints } func (c *BaseAPIController) ParamBool(param string, def bool) bool { if c.Input().Get(param) == "" { return def } var value bool c.Ctx.Input.Bind(&value, param) return value } func (c *BaseAPIController) SendError(errorCode int, message ...interface{}) { response := responses.Subsonic{Version: beego.AppConfig.String("apiVersion"), Status: "fail"} var msg string if len(message) == 0 { msg = responses.ErrorMsg(errorCode) } else { msg = fmt.Sprintf(message[0].(string), message[1:]...) } response.Error = &responses.Error{Code: errorCode, Message: msg} xmlBody, _ := xml.Marshal(&response) c.CustomAbort(200, xml.Header+string(xmlBody)) } func (c *BaseAPIController) SendEmptyResponse() { c.SendResponse(c.NewEmpty()) } func (c *BaseAPIController) SendResponse(response responses.Subsonic) { f := c.GetString("f") switch f { case "json": w := &responses.JsonWrapper{Subsonic: response} c.Data["json"] = &w c.ServeJSON() case "jsonp": w := &responses.JsonWrapper{Subsonic: response} c.Data["jsonp"] = &w c.ServeJSONP() default: c.Data["xml"] = &response c.ServeXML() } } func (c *BaseAPIController) ToChildren(entries engine.Entries) []responses.Child { children := make([]responses.Child, len(entries)) for i, entry := range entries { children[i] = c.ToChild(entry) } return children } func (c *BaseAPIController) ToAlbums(entries engine.Entries) []responses.Child { children := make([]responses.Child, len(entries)) for i, entry := range entries { children[i] = c.ToAlbum(entry) } return children } func (c *BaseAPIController) ToAlbum(entry engine.Entry) responses.Child { album := c.ToChild(entry) album.Name = album.Title album.Title = "" album.Parent = "" album.Album = "" album.AlbumId = "" return album } func (c *BaseAPIController) ToChild(entry engine.Entry) responses.Child { child := responses.Child{} child.Id = entry.Id child.Title = entry.Title child.IsDir = entry.IsDir child.Parent = entry.Parent child.Album = entry.Album child.Year = entry.Year child.Artist = entry.Artist child.Genre = entry.Genre child.CoverArt = entry.CoverArt child.Track = entry.Track child.Duration = entry.Duration child.Size = entry.Size child.Suffix = entry.Suffix child.BitRate = entry.BitRate child.ContentType = entry.ContentType if !entry.Starred.IsZero() { child.Starred = &entry.Starred } child.Path = entry.Path child.PlayCount = entry.PlayCount child.DiscNumber = entry.DiscNumber if !entry.Created.IsZero() { child.Created = &entry.Created } child.AlbumId = entry.AlbumId child.ArtistId = entry.ArtistId child.Type = entry.Type child.UserRating = entry.UserRating child.SongCount = entry.SongCount return child }