func (db *DB) list(ctx core.CommandContext) core.Result { //TODO args := ctx.Args var err error text, err := util.GetArg(args, "text", false, err) query, err := util.GetArg(args, "query", false, err) tags, err := util.GetArg(args, "tags", false, err) if text != nil { return core.ResultByError(core.ErrorNotImplemented) } if query != nil { res, err := db.ListQuery(*query) if err != nil { return core.ResultByError(errrs.New(err.Error())) } return core.Result{core.StatusOK, ItemToInterfaceSlice(res), err, false} } if tags != nil { return core.ResultByError(core.ErrorNotImplemented) } res, err := db.ListAll() if err != nil { return core.ResultByError(errrs.New(err.Error())) } return core.Result{core.StatusOK, ItemToInterfaceSlice(res), err, false} }
func (s *Sync) Start(c core.Core, db *db.DB) { s.core = c s.db = db s.config = config.Current.Plugins[PluginName].(*Config) c.RegisterCommand(core.Command{[]string{"sync", "s"}, "Syncs media with a device or folder. By default, lossles files are converted to MP3 V0.", map[string]string{ "path": "Target path", "convert": "boolean, default is true"}, core.AuthAdmin, func(ctx core.CommandContext) core.Result { args := ctx.Args var err error pathS, err := util.GetArg(args, "path", true, err) convertS, err := util.GetArg(args, "convert", true, err) doConvert, err := util.CastBool(convertS, err) if err != nil { return core.ResultByError(err) } convert := true if doConvert != nil { convert = *doConvert } return core.ResultByError(s.Sync(*pathS, convert)) }}) }
func (db *DB) GetItem(args core.ArgMap) ([]Item, error) { // check if necessary args are there var err error title, err := util.GetArg(args, "title", true, err) artist, err := util.GetArg(args, "artist", true, err) album, err := util.GetArg(args, "album", false, err) album_artist, err := util.GetArg(args, "album_artist", false, err) //musicbrainz_id, err := util.GetArg(args, "musicbrainz_id", false, err) if err != nil { return nil, err } limit := map[string]interface{}{"title": title, "artist": artist} if album != nil { limit["album"] = album } if album_artist != nil && false { //TODO album-artists are not implemented yet limit["album_artist"] = album_artist } //TODO mbid is not implemented. If given, only search mbid. /*if musicbrainz_id != nil { limit["musicbrainz_id"] = musicbrainz_id }*/ tracks := make([]Item, 0) err = db.db.Where(limit).Find(tracks).Error if err != nil { return nil, err } return tracks, nil }
func (db *DB) TrackPlayed(ctx core.CommandContext) core.Result { args := ctx.Args tracks, err := db.GetItem(args) lengthS, err := util.GetArg(args, "length", true, err) length_playedS, err := util.GetArg(args, "length_played", true, err) scrobbledS, err := util.GetArg(args, "scrobbled", true, err) length, err := util.CastFloat(lengthS, err) length_played, err := util.CastFloat(length_playedS, err) scrobbled, err := util.CastBool(scrobbledS, err) if err != nil { return core.Result{Status: core.StatusError, Error: err} } if len(tracks) == 0 { //TODO insert track return core.Result{Status: core.StatusItemNotFound} } if len(tracks) > 1 { return core.Result{Status: core.StatusQueryNotUnique, Result: tracks} } track := tracks[0] // update stats x := float64(*length_played / *length) tu := float64(config.Current.ListenedUpperThreshold) tl := float64(config.Current.ListenedLowerThreshold) scoreAdd := float32(math.Min(1, math.Max(0, (x-tl)/(tu-tl)))) //TODO test this track.PlayCount++ if scoreAdd > 0 { track.PlayScore += scoreAdd track.ScoredCount++ } if *scrobbled { track.ScrobbleCount++ } err = db.db.Save(track).Error if err != nil { return core.Result{Status: core.StatusError, Error: err} } return core.Result{Status: core.StatusOK, Result: tracks} }
func (a *AS) LoginAS(ctx core.CommandContext) core.Result { var err error args := ctx.Args handshakeS, err := util.GetArg(args, "hs", true, err) handshake, err := util.CastBool(handshakeS, err) pVer, err := util.GetArg(args, "p", true, err) _, err = util.GetArg(args, "c", true, err) _, err = util.GetArg(args, "v", true, err) userS, err := util.GetArg(args, "u", true, err) timestampS, err := util.GetArg(args, "t", true, err) timestamp, err := util.CastInt64(timestampS, err) authMsg, err := util.GetArg(args, "a", true, err) if err != nil { return errorAS(StatusFailed, err) } if !*handshake { return errorAS(StatusFailed, errrs.New("this URL is only for handshake"+ " requests, hs must be true")) } if *pVer != "1.2.1" { return errorAS(StatusFailed, errrs.New("Protocol version must be 1.2.1")) } //TODO maybe check audioscrobbler client id and version // check timestamp timestampReal := time.Now().Unix() if util.Abs(timestampReal-*timestamp) > 120 { return errorAS(StatusBadTime, nil) } // get user user, err := a.db.GetUserByName(*userS) if user == nil { logger.Log.Println("incorrect auth from unknown user ", *userS) return errorAS(StatusBadAuth, nil) } // check auth // md5(md5(auth_token) + timestamp) md5Token := fmt.Sprintf("%x", md5.Sum([]byte(user.AuthToken))) correctStr := fmt.Sprintf("%s%d", md5Token, *timestamp) correctAuthMsg := fmt.Sprintf("%x", md5.Sum([]byte(correctStr))) if correctAuthMsg != *authMsg { logger.Log.Println("incorrect auth from", user.Name, "with", *authMsg, "instead of", correctAuthMsg) return errorAS(StatusBadAuth, nil) } return core.Result{StatusOK, []interface{}{user.AuthToken, a.nowPlayingURL, a.submissionURL}, nil, true} }
func (p *IPod) Start(c core.Core, db *db.DB, s *sync.Sync) { p.core = c p.db = db p.sync = s p.config = config.Current.Plugins[PluginName].(*Config) c.RegisterCommand(core.Command{[]string{"ipod"}, "Syncs media with an iPod device. By default, Lossles files are converted to MP3 V0.", map[string]string{"mountpoint": "mountpoint of the iPod"}, core.AuthAdmin, func(ctx core.CommandContext) core.Result { path, err := util.GetArg(ctx.Args, "mountpoint", true, nil) if err != nil { return core.ResultByError(err) } return core.ResultByError(p.Sync(*path)) }}) }
func (c *impl) registerBaseCommands() { c.RegisterCommand(core.Command{ []string{"quit", "q", "close", "exit"}, "Shuts down and exits.", map[string]string{}, core.AuthRoot, func(_ core.CommandContext) core.Result { return core.ResultByError(c.Shutdown()) }}) c.RegisterCommand(core.Command{ []string{"help", "h", "?"}, "Prints help.", map[string]string{"c": "(Optional) the command to get help for"}, core.AuthGuest, func(ctx core.CommandContext) core.Result { res := make(map[string]interface{}) mk := func(k string, v core.Command) { if ctx.AuthLevel >= v.MinAuthLevel { res[k] = CmdHelp{v.MinAuthLevel, v.Verbs, v.Description, v.ArgsHelp} } } var err error cmdArg, err := util.GetArg(ctx.Args, "c", false, err) if err != nil { return core.ResultByError(err) } if cmdArg != nil { cmd, ok := c.commandMap[*cmdArg] if !ok { return core.ResultByError(core.ErrorCmdNotFound) } mk(*cmdArg, cmd) } else { for k, v := range c.commandSet { mk(k, v) } } return core.Result{Status: core.StatusOK, Result: res} }}) }
func (n *NetCmdLine) authenticate(c martini.Context, ctx *core.CommandContext, w http.ResponseWriter) { // check auth token token, err := util.GetArg(ctx.Args, "auth_token", false, nil) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintln(w, "bad request:", err) return } ctx.AuthLevel = core.AuthGuest if token != nil { ctx.AuthLevel, ctx.UserId, err = n.db.Authenticate(*token) if err != nil { w.WriteHeader(http.StatusUnauthorized) fmt.Fprintln(w, "bad request:", err) return } } }
func (db *DB) initLogin(c core.Core) { c.RegisterCommand(core.Command{ []string{"create_user"}, "Creates a user in the database", map[string]string{ "name": "Username", "email": "E-Mail", "auth_level": fmt.Sprintf("User Rank: Guest(%d), User(%d), "+ "Admin(%d), Root(%d)", core.AuthGuest, core.AuthUser, core.AuthAdmin, core.AuthRoot), "password": "******"}, core.AuthAdmin, func(ctx core.CommandContext) core.Result { args := ctx.Args var err error name, err := util.GetArg(args, "name", true, err) email, err := util.GetArg(args, "email", true, err) authLevelS, err := util.GetArg(args, "auth_level", true, err) password, err := util.GetArg(args, "password", true, err) authLevelI, err := util.CastUint(authLevelS, err) if err != nil { return core.Result{Status: core.StatusError, Error: err} } authLevel := core.AuthLevel(*authLevelI) if authLevel >= ctx.AuthLevel { return core.ResultByError(errrs.New("You cannot create a user" + " with that level!")) } user, err := db.CreateUser(*name, *email, authLevel, *password) if err == nil { return core.Result{Status: core.StatusOK, Result: user} } return core.Result{Status: core.StatusError, Error: err} }}) c.RegisterCommand(core.Command{ []string{"login"}, "Logs in with user/password and returns the auth token", map[string]string{ "name": "Username", "password": "******"}, core.AuthGuest, func(ctx core.CommandContext) core.Result { args := ctx.Args var err error name, err := util.GetArg(args, "name", true, err) password, err := util.GetArg(args, "password", true, err) if err != nil { return core.ResultByError(err) } success, authToken, err := db.Login(*name, *password) if err == nil && success { return core.Result{Status: core.StatusOK, Result: map[string]string{"auth_token": authToken}} } if err == nil { return core.Result{Status: core.StatusError, Error: errrs.New("Wrong username or password")} } return core.Result{Status: core.StatusError, Error: err} }}) c.RegisterCommand(core.Command{ []string{"change_authtoken", "logout"}, `Changes the authentication token of the user, thereby logging out all clients`, map[string]string{ "name": `(Optional) username of the user to log out. Leave empty to use current user`, }, core.AuthUser, func(ctx core.CommandContext) core.Result { args := ctx.Args var err error name, err := util.GetArg(args, "name", false, err) if err != nil { return core.ResultByError(err) } var user *User if name != nil { if ctx.AuthLevel < core.AuthAdmin { return core.ResultByError(core.ErrorNotAllowed) } user, err = db.GetUserByName(*name) } else { if ctx.UserId == nil { return core.ResultByError(core.ErrorNotLoggedIn) } user, err = db.GetUser(*ctx.UserId) } if user == nil { return core.ResultByError(core.ErrorUserNotFound) } _, err = db.ChangeAuthToken(user) return core.ResultByError(err) }}) }