Beispiel #1
0
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}
}
Beispiel #2
0
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))
		}})
}
Beispiel #3
0
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
}
Beispiel #4
0
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}
}
Beispiel #5
0
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}
}
Beispiel #6
0
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))
		}})
}
Beispiel #7
0
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}
		}})
}
Beispiel #8
0
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
		}
	}
}
Beispiel #9
0
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)
		}})
}