|  | @@ -4,6 +4,7 @@ const db = require('../db');
 | 
	
		
			
				|  |  |  const io = require('../io');
 | 
	
		
			
				|  |  |  const cache = require('../cache');
 | 
	
		
			
				|  |  |  const utils = require('../utils');
 | 
	
		
			
				|  |  | +const logger = require('../logger');
 | 
	
		
			
				|  |  |  const hooks = require('./hooks');
 | 
	
		
			
				|  |  |  const async = require('async');
 | 
	
		
			
				|  |  |  const playlists = require('../playlists');
 | 
	
	
		
			
				|  | @@ -71,19 +72,61 @@ cache.sub('playlist.updateDisplayName', res => {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  let lib = {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Gets the first song from a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are getting the first song from
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	getFirstSong: hooks.loginRequired((session, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  | -		playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist'});
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found.');
 | 
	
		
			
				|  |  | +				next(null, playlist.songs[0]);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, song) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_GET_FIRST_SONG", "ERROR", `Getting the first song of playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: 'Something went wrong when getting the playlist'});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_GET_FIRST_SONG", "SUCCESS", `Successfully got the first song of playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  |  			cb({
 | 
	
		
			
				|  |  |  				status: 'success',
 | 
	
		
			
				|  |  | -				song: playlist.songs[0]
 | 
	
		
			
				|  |  | +				song: song
 | 
	
		
			
				|  |  |  			});
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Gets all playlists for the user requesting it
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	indexForUser: hooks.loginRequired((session, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.find({ createdBy: userId }, (err, playlists) => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'failure', message: 'Something went wrong when getting the playlists'});;
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.find({ createdBy: userId }, next);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlists) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_INDEX_FOR_USER", "ERROR", `Indexing playlists for user "${userId}" failed. "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_INDEX_FOR_USER", "SUCCESS", `Successfully indexed playlists for user "${userId}".`);
 | 
	
		
			
				|  |  |  			cb({
 | 
	
		
			
				|  |  |  				status: 'success',
 | 
	
		
			
				|  |  |  				data: playlists
 | 
	
	
		
			
				|  | @@ -91,6 +134,14 @@ let lib = {
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Creates a new private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {Object} data - the data for the new private playlist
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	create: hooks.loginRequired((session, data, cb, userId) => {
 | 
	
		
			
				|  |  |  		async.waterfall([
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -99,7 +150,7 @@ let lib = {
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			(next) => {
 | 
	
		
			
				|  |  | -				const { name, displayName, songs } = data;
 | 
	
		
			
				|  |  | +				const { displayName, songs } = data;
 | 
	
		
			
				|  |  |  				db.models.playlist.create({
 | 
	
		
			
				|  |  |  					_id: utils.generateRandomString(17),//TODO Check if exists
 | 
	
		
			
				|  |  |  					displayName,
 | 
	
	
		
			
				|  | @@ -110,17 +161,48 @@ let lib = {
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		], (err, playlist) => {
 | 
	
		
			
				|  |  | -			console.log(err, playlist);
 | 
	
		
			
				|  |  | -			if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong'});
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_CREATE", "ERROR", `Creating private playlist failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  |  			cache.pub('playlist.create', playlist._id);
 | 
	
		
			
				|  |  | -			return cb({ 'status': 'success', 'message': 'Successfully created playlist' });
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_CREATE", "SUCCESS", `Successfully created private playlist for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cb({ 'status': 'success', 'message': 'Successfully created playlist' });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	getPlaylist: hooks.loginRequired((session, id, cb, userId) => {
 | 
	
		
			
				|  |  | -		playlists.getPlaylist(id, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || playlist.createdBy !== userId) return cb({status: 'success', message: 'Playlist not found'});
 | 
	
		
			
				|  |  | -			if (err == null) return cb({
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Gets a playlist from id
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are getting
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	getPlaylist: hooks.loginRequired((session, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found');
 | 
	
		
			
				|  |  | +				next(null, playlist);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_GET", "ERROR", `Getting private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_GET", "SUCCESS", `Successfully got private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			console.log(playlist);
 | 
	
		
			
				|  |  | +			cb({
 | 
	
		
			
				|  |  |  				status: 'success',
 | 
	
		
			
				|  |  |  				data: playlist
 | 
	
		
			
				|  |  |  			});
 | 
	
	
		
			
				|  | @@ -128,29 +210,59 @@ let lib = {
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	//TODO Remove this
 | 
	
		
			
				|  |  | -	update: hooks.loginRequired((session, _id, playlist, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.update({ _id, createdBy: userId }, playlist, (err, data) => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'failure', message: 'Something went wrong.' });
 | 
	
		
			
				|  |  | -			playlists.updatePlaylist(_id, (err) => {
 | 
	
		
			
				|  |  | -				if (err) return cb({ status: 'failure', message: 'Something went wrong.' });
 | 
	
		
			
				|  |  | -				return cb({ status: 'success', message: 'Playlist has been successfully updated', data });
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Updates a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are updating
 | 
	
		
			
				|  |  | +	 * @param {Object} playlist - the new private playlist object
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	update: hooks.loginRequired((session, playlistId, playlist, cb, userId) => {
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.update({ _id: playlistId, createdBy: userId }, playlist, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(res, next) => {
 | 
	
		
			
				|  |  | +				playlists.updatePlaylist(playlistId, next)
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_UPDATE", "ERROR", `Updating private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_UPDATE", "SUCCESS", `Successfully updated private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cb({
 | 
	
		
			
				|  |  | +				status: 'success',
 | 
	
		
			
				|  |  | +				data: playlist
 | 
	
		
			
				|  |  |  			});
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Adds a song to a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} songId - the id of the song we are trying to add
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are adding the song to
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	addSongToPlaylist: hooks.loginRequired((session, songId, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  | -		console.log(songId);
 | 
	
		
			
				|  |  |  		async.waterfall([
 | 
	
		
			
				|  |  |  			(next) => {
 | 
	
		
			
				|  |  |  				playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  |  					if (err || !playlist || playlist.createdBy !== userId) return next('Something went wrong when trying to get the playlist');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					let found = false;
 | 
	
		
			
				|  |  | -					playlist.songs.forEach((song) => {
 | 
	
		
			
				|  |  | -						if (songId === song._id) found = true;
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | -					if (found) return next('That song is already in the playlist');
 | 
	
		
			
				|  |  | -					return next(null);
 | 
	
		
			
				|  |  | +					async.each(playlist.songs, (song, next) => {
 | 
	
		
			
				|  |  | +						if (song._id === songId) return next('That song is already in the playlist');
 | 
	
		
			
				|  |  | +						next();
 | 
	
		
			
				|  |  | +					}, next);
 | 
	
		
			
				|  |  |  				});
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			(next) => {
 | 
	
	
		
			
				|  | @@ -170,11 +282,7 @@ let lib = {
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			(newSong, next) => {
 | 
	
		
			
				|  |  |  				db.models.playlist.update({ _id: playlistId }, { $push: { songs: newSong } }, (err) => {
 | 
	
		
			
				|  |  | -					if (err) {
 | 
	
		
			
				|  |  | -						console.error(err);
 | 
	
		
			
				|  |  | -						return next('Failed to add song to playlist');
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +					if (err) return next(err);
 | 
	
		
			
				|  |  |  					playlists.updatePlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  |  						next(err, playlist, newSong);
 | 
	
		
			
				|  |  |  					});
 | 
	
	
		
			
				|  | @@ -182,14 +290,28 @@ let lib = {
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		],
 | 
	
		
			
				|  |  |  		(err, playlist, newSong) => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'error', message: err });
 | 
	
		
			
				|  |  | -			else if (playlist.songs) {
 | 
	
		
			
				|  |  | -				cache.pub('playlist.addSong', { playlistId: playlist._id, song: newSong, userId: userId });
 | 
	
		
			
				|  |  | -				return cb({ status: 'success', message: 'Song has been successfully added to the playlist', data: playlist.songs });
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_ADD_SONG", "ERROR", `Adding song "${songId}" to private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_ADD_SONG", "SUCCESS", `Successfully added song "${songId}" to private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.addSong', { playlistId: playlist._id, song: newSong, userId: userId });
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Song has been successfully added to the playlist', data: playlist.songs });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  | -	
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Adds a set of songs to a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} url - the url of the the YouTube playlist
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are adding the set of songs to
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	addSetToPlaylist: hooks.loginRequired((session, url, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  |  		async.waterfall([
 | 
	
		
			
				|  |  |  			(next) => {
 | 
	
	
		
			
				|  | @@ -210,178 +332,237 @@ let lib = {
 | 
	
		
			
				|  |  |  				}
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			(next) => {
 | 
	
		
			
				|  |  | -				playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -					if (err || !playlist || playlist.createdBy !== userId) return next('Something went wrong while trying to get the playlist');
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					next(null, playlist);
 | 
	
		
			
				|  |  | -				});
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found.');
 | 
	
		
			
				|  |  | +				next(null, playlist);
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -		],
 | 
	
		
			
				|  |  | -		(err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'failure', message: err });
 | 
	
		
			
				|  |  | -			else if (playlist.songs) return cb({ status: 'success', message: 'Playlist has been successfully imported.', data: playlist.songs });
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_IMPORT", "ERROR", `Importing a YouTube playlist to private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_IMPORT", "SUCCESS", `Successfully imported a YouTube playlist to private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cb({ status: 'success', message: 'Playlist has been successfully imported.', data: playlist.songs });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Removes a song from a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} songId - the id of the song we are removing from the private playlist
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are removing the song from
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	removeSongFromPlaylist: hooks.loginRequired((session, songId, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  | -		playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist'});
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			for (let z = 0; z < playlist.songs.length; z++) {
 | 
	
		
			
				|  |  | -				if (playlist.songs[z]._id == songId) playlist.songs.shift(playlist.songs[z]);
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found');
 | 
	
		
			
				|  |  | +				db.models.playlist.update({_id: playlistId}, {$pull: {songs: songId}}, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			db.models.playlist.update({_id: playlistId}, {$pull: {songs: {_id: songId}}}, (err) => {
 | 
	
		
			
				|  |  | -				if (err) {
 | 
	
		
			
				|  |  | -					console.error(err);
 | 
	
		
			
				|  |  | -					return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -				playlists.updatePlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -					cache.pub('playlist.removeSong', {playlistId: playlist._id, songId: songId, userId: userId});
 | 
	
		
			
				|  |  | -					return cb({ status: 'success', message: 'Song has been successfully removed from playlist', data: playlist.songs });
 | 
	
		
			
				|  |  | -				});
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +			(res, next) => {
 | 
	
		
			
				|  |  | +				playlists.updatePlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_REMOVE_SONG", "ERROR", `Removing song "${songId}" from private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_REMOVE_SONG", "SUCCESS", `Successfully removed song "${songId}" from private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.removeSong', {playlistId: playlist._id, songId: songId, userId: userId});
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Song has been successfully removed from playlist', data: playlist.songs });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	updateDisplayName: hooks.loginRequired((session, _id, displayName, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.update({ _id, createdBy: userId }, { displayName }, (err, res) => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -			playlists.updatePlaylist(_id, (err) => {
 | 
	
		
			
				|  |  | -				if (err) return cb({ status: 'failure', message: err});
 | 
	
		
			
				|  |  | -				cache.pub('playlist.updateDisplayName', {playlistId: _id, displayName: displayName, userId: userId});
 | 
	
		
			
				|  |  | -				return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  | -			})
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Updates the displayName of a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are updating the displayName for
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	updateDisplayName: hooks.loginRequired((session, playlistId, displayName, cb, userId) => {
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.update({ _id: playlistId, createdBy: userId }, { $set: { displayName } }, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(res, next) => {
 | 
	
		
			
				|  |  | +				playlists.updatePlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_UPDATE_DISPLAY_NAME", "ERROR", `Updating display name to "${displayName}" for private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_UPDATE_DISPLAY_NAME", "SUCCESS", `Successfully updated display name to "${displayName}" for private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.updateDisplayName', {playlistId: playlistId, displayName: displayName, userId: userId});
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Moves a song to the top of the list in a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are moving the song to the top from
 | 
	
		
			
				|  |  | +	 * @param {String} songId - the id of the song we are moving to the top of the list
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	moveSongToTop: hooks.loginRequired((session, playlistId, songId, cb, userId) => {
 | 
	
		
			
				|  |  | -		playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist'});
 | 
	
		
			
				|  |  | -			let found = false;
 | 
	
		
			
				|  |  | -			let foundSong;
 | 
	
		
			
				|  |  | -			playlist.songs.forEach((song) => {
 | 
	
		
			
				|  |  | -				if (song._id === songId) {
 | 
	
		
			
				|  |  | -					foundSong = song;
 | 
	
		
			
				|  |  | -					found = true;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			if (found) {
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found');
 | 
	
		
			
				|  |  | +				async.each(playlist.songs, (song, next) => {
 | 
	
		
			
				|  |  | +					if (song._id === songId) return next(song);
 | 
	
		
			
				|  |  | +					next();
 | 
	
		
			
				|  |  | +				}, (err) => {
 | 
	
		
			
				|  |  | +					if (err && err._id) return next(null, err);
 | 
	
		
			
				|  |  | +					next('Song not found');
 | 
	
		
			
				|  |  | +				});
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(song, next) => {
 | 
	
		
			
				|  |  |  				db.models.playlist.update({_id: playlistId}, {$pull: {songs: {_id: songId}}}, (err) => {
 | 
	
		
			
				|  |  | -					console.log(err);
 | 
	
		
			
				|  |  | -					if (err) return cb({status: 'failure', message: 'Something went wrong when moving the song'});
 | 
	
		
			
				|  |  | -					db.models.playlist.update({_id: playlistId}, {
 | 
	
		
			
				|  |  | -						$push: {
 | 
	
		
			
				|  |  | -							songs: {
 | 
	
		
			
				|  |  | -								$each: [foundSong],
 | 
	
		
			
				|  |  | -								$position: 0
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -					}, (err) => {
 | 
	
		
			
				|  |  | -						console.log(err);
 | 
	
		
			
				|  |  | -						if (err) return cb({status: 'failure', message: 'Something went wrong when moving the song'});
 | 
	
		
			
				|  |  | -						playlists.updatePlaylist(playlistId, (err) => {
 | 
	
		
			
				|  |  | -							if (err) return cb({ status: 'failure', message: err});
 | 
	
		
			
				|  |  | -							cache.pub('playlist.moveSongToTop', {playlistId, songId, userId: userId});
 | 
	
		
			
				|  |  | -							return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  | -						})
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | +					if (err) return next(err);
 | 
	
		
			
				|  |  | +					return next(null, song);
 | 
	
		
			
				|  |  |  				});
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | -				return cb({status: 'failure', message: 'Song not found.'});
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(song, next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.update({_id: playlistId}, {
 | 
	
		
			
				|  |  | +					$push: {
 | 
	
		
			
				|  |  | +						songs: {
 | 
	
		
			
				|  |  | +							$each: [song],
 | 
	
		
			
				|  |  | +							$position: 0
 | 
	
		
			
				|  |  | +						}
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				}, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(res, next) => {
 | 
	
		
			
				|  |  | +				playlists.updatePlaylist(playlistId, next);
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_MOVE_SONG_TO_TOP", "ERROR", `Moving song "${songId}" to the top for private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_MOVE_SONG_TO_TOP", "SUCCESS", `Successfully moved song "${songId}" to the top for private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.moveSongToTop', {playlistId, songId, userId: userId});
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Moves a song to the bottom of the list in a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are moving the song to the bottom from
 | 
	
		
			
				|  |  | +	 * @param {String} songId - the id of the song we are moving to the bottom of the list
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  |  	moveSongToBottom: hooks.loginRequired((session, playlistId, songId, cb, userId) => {
 | 
	
		
			
				|  |  | -		playlists.getPlaylist(playlistId, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist'});
 | 
	
		
			
				|  |  | -			let found = false;
 | 
	
		
			
				|  |  | -			let foundSong;
 | 
	
		
			
				|  |  | -			playlist.songs.forEach((song) => {
 | 
	
		
			
				|  |  | -				if (song._id === songId) {
 | 
	
		
			
				|  |  | -					foundSong = song;
 | 
	
		
			
				|  |  | -					found = true;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.getPlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			if (found) {
 | 
	
		
			
				|  |  | -				db.models.playlist.update({_id: playlistId}, {$pull: {songs: {_id: songId}}}, (err) => {
 | 
	
		
			
				|  |  | -					console.log(err);
 | 
	
		
			
				|  |  | -					if (err) return cb({status: 'failure', message: 'Something went wrong when moving the song'});
 | 
	
		
			
				|  |  | -					db.models.playlist.update({_id: playlistId}, {
 | 
	
		
			
				|  |  | -						$push: { songs: foundSong }
 | 
	
		
			
				|  |  | -					}, (err) => {
 | 
	
		
			
				|  |  | -						console.log(err);
 | 
	
		
			
				|  |  | -						if (err) return cb({status: 'failure', message: 'Something went wrong when moving the song'});
 | 
	
		
			
				|  |  | -						playlists.updatePlaylist(playlistId, (err) => {
 | 
	
		
			
				|  |  | -							if (err) return cb({ status: 'failure', message: err });
 | 
	
		
			
				|  |  | -							cache.pub('playlist.moveSongToBottom', { playlistId, songId, userId: userId });
 | 
	
		
			
				|  |  | -							return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  | -						})
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | +			(playlist, next) => {
 | 
	
		
			
				|  |  | +				if (!playlist || playlist.createdBy !== userId) return next('Playlist not found');
 | 
	
		
			
				|  |  | +				async.each(playlist.songs, (song, next) => {
 | 
	
		
			
				|  |  | +					if (song._id === songId) return next(song);
 | 
	
		
			
				|  |  | +					next();
 | 
	
		
			
				|  |  | +				}, (err) => {
 | 
	
		
			
				|  |  | +					if (err && err._id) return next(null, err);
 | 
	
		
			
				|  |  | +					next('Song not found');
 | 
	
		
			
				|  |  |  				});
 | 
	
		
			
				|  |  | -			} else return cb({status: 'failure', message: 'Song not found'});
 | 
	
		
			
				|  |  | -		});
 | 
	
		
			
				|  |  | -	}),
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	/*
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	promoteSong: hooks.loginRequired((session, playlistId, fromIndex, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist.'});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			let song = playlist.songs[fromIndex];
 | 
	
		
			
				|  |  | -			playlist.songs.splice(fromIndex, 1);
 | 
	
		
			
				|  |  | -			playlist.songs.splice((fromIndex + 1), 0, song);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			playlist.save(err => {
 | 
	
		
			
				|  |  | -				if (err) {
 | 
	
		
			
				|  |  | -					console.error(err);
 | 
	
		
			
				|  |  | -					return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -				playlists.updatePlaylist(playlistId, (err) => {
 | 
	
		
			
				|  |  | -					if (err) return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -					return cb({ status: 'success', data: playlist.songs });
 | 
	
		
			
				|  |  | +			(song, next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.update({_id: playlistId}, {$pull: {songs: {_id: songId}}}, (err) => {
 | 
	
		
			
				|  |  | +					if (err) return next(err);
 | 
	
		
			
				|  |  | +					return next(null, song);
 | 
	
		
			
				|  |  |  				});
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +			(song, next) => {
 | 
	
		
			
				|  |  | +				db.models.playlist.update({_id: playlistId}, {
 | 
	
		
			
				|  |  | +					$push: {
 | 
	
		
			
				|  |  | +						songs: song
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				}, next);
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			(res, next) => {
 | 
	
		
			
				|  |  | +				playlists.updatePlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err, playlist) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_MOVE_SONG_TO_BOTTOM", "ERROR", `Moving song "${songId}" to the bottom for private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_MOVE_SONG_TO_BOTTOM", "SUCCESS", `Successfully moved song "${songId}" to the bottom for private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.moveSongToBottom', {playlistId, songId, userId: userId});
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	}),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	demoteSong: hooks.loginRequired((session, playlistId, fromIndex, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
 | 
	
		
			
				|  |  | -			if (err || !playlist || playlist.createdBy !== userId) return cb({ status: 'failure', message: 'Something went wrong when getting the playlist.'});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			let song = playlist.songs[fromIndex];
 | 
	
		
			
				|  |  | -			playlist.songs.splice(fromIndex, 1);
 | 
	
		
			
				|  |  | -			playlist.songs.splice((fromIndex - 1), 0, song);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			playlist.save(err => {
 | 
	
		
			
				|  |  | -				if (err) {
 | 
	
		
			
				|  |  | -					console.error(err);
 | 
	
		
			
				|  |  | -					return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				playlists.updatePlaylist(playlistId, (err) => {
 | 
	
		
			
				|  |  | -					if (err) return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 | 
	
		
			
				|  |  | -					return cb({ status: 'success', data: playlist.songs });
 | 
	
		
			
				|  |  | -				});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | -		});
 | 
	
		
			
				|  |  | -	}),*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	remove: hooks.loginRequired((session, _id, cb, userId) => {
 | 
	
		
			
				|  |  | -		db.models.playlist.remove({ _id, createdBy: userId }).exec(err => {
 | 
	
		
			
				|  |  | -			if (err) return cb({ status: 'failure', message: 'Something went wrong when removing the playlist.'});
 | 
	
		
			
				|  |  | -			cache.hdel('playlists', _id, () => {
 | 
	
		
			
				|  |  | -				cache.pub('playlist.delete', {userId: userId, playlistId: _id});
 | 
	
		
			
				|  |  | -				return cb({ status: 'success', message: 'Playlist successfully removed' });
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * Removes a song from a private playlist
 | 
	
		
			
				|  |  | +	 *
 | 
	
		
			
				|  |  | +	 * @param {Object} session - the session object automatically added by socket.io
 | 
	
		
			
				|  |  | +	 * @param {String} playlistId - the id of the playlist we are moving the song to the top from
 | 
	
		
			
				|  |  | +	 * @param {Function} cb - gets called with the result
 | 
	
		
			
				|  |  | +	 * @param {String} userId - the userId automatically added by hooks
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	remove: hooks.loginRequired((session, playlistId, cb, userId) => {
 | 
	
		
			
				|  |  | +		async.waterfall([
 | 
	
		
			
				|  |  | +			(next) => {
 | 
	
		
			
				|  |  | +				playlists.deletePlaylist(playlistId, next);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		], (err) => {
 | 
	
		
			
				|  |  | +			if (err) {
 | 
	
		
			
				|  |  | +				let error = 'An error occurred.';
 | 
	
		
			
				|  |  | +				if (typeof err === "string") error = err;
 | 
	
		
			
				|  |  | +				else if (err.message) error = err.message;
 | 
	
		
			
				|  |  | +				logger.log("PLAYLIST_REMOVE", "ERROR", `Removing private playlist "${playlistId}" failed for user "${userId}". "${error}"`);
 | 
	
		
			
				|  |  | +				return cb({ status: 'failure', message: error});
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			logger.log("PLAYLIST_REMOVE", "SUCCESS", `Successfully removed private playlist "${playlistId}" for user "${userId}".`);
 | 
	
		
			
				|  |  | +			cache.pub('playlist.delete', {userId: userId, playlistId});
 | 
	
		
			
				|  |  | +			return cb({ status: 'success', message: 'Playlist successfully removed' });
 | 
	
		
			
				|  |  |  		});
 | 
	
		
			
				|  |  |  	})
 | 
	
		
			
				|  |  |  
 |