Przeglądaj źródła

Worked on switching community stations playlist mode to new playlist system

Kristian Vos 4 lat temu
rodzic
commit
6364b4914b

+ 42 - 76
backend/logic/actions/stations.js

@@ -754,6 +754,8 @@ export default {
 						partyMode: station.partyMode,
 						owner: station.owner,
 						privatePlaylist: station.privatePlaylist,
+						includedPlaylists: station.includedPlaylists,
+						excludedPlaylists: station.excludedPlaylists,
 						genres: station.genres,
 						blacklistedGenres: station.blacklistedGenres,
 						theme: station.theme
@@ -2512,6 +2514,7 @@ export default {
 					if (type === "community") {
 						if (blacklist.indexOf(name) !== -1)
 							return next("That name is blacklisted. Please use a different name.");
+						console.log(12121212, stationId);
 						return playlistModel.create(
 							{
 								isUserModifiable: false,
@@ -2528,6 +2531,7 @@ export default {
 								else {
 									stationModel.create(
 										{
+											_id: stationId,
 											name,
 											displayName,
 											description,
@@ -2989,9 +2993,6 @@ export default {
 	 * @param cb
 	 */
 	selectPrivatePlaylist: isOwnerRequired(async function selectPrivatePlaylist(session, stationId, playlistId, cb) {
-		const stationModel = await DBModule.runJob("GET_MODEL", { modelName: "station" }, this);
-		const playlistModel = await DBModule.runJob("GET_MODEL", { modelName: "playlist" }, this);
-
 		async.waterfall(
 			[
 				next => {
@@ -3003,34 +3004,20 @@ export default {
 				(station, next) => {
 					if (!station) return next("Station not found.");
 					if (station.type !== "community") return next("Station is not a community station.");
-					if (station.privatePlaylist === playlistId)
-						return next("That private playlist is already selected.");
-					return playlistModel.findOne({ _id: playlistId }, next);
-				},
-
-				(playlist, next) => {
-					if (!playlist) return next("Playlist not found.");
-					const currentSongIndex = playlist.songs.length > 0 ? playlist.songs.length - 1 : 0;
-					return stationModel.updateOne(
-						{ _id: stationId },
-						{
-							$set: {
-								privatePlaylist: playlistId,
-								currentSongIndex
-							}
-						},
-						{ runValidators: true },
-						next
-					);
+					if (station.includedPlaylists.indexOf(playlistId) !== -1)
+						return next("That playlist is already included.");
+					return next();
 				},
 
-				(res, next) => {
-					StationsModule.runJob("UPDATE_STATION", { stationId }, this)
-						.then(station => next(null, station))
+				next => {
+					StationsModule.runJob("INCLUDE_PLAYLIST", { stationId, playlistId }, this)
+						.then(() => {
+							next();
+						})
 						.catch(next);
 				}
 			],
-			async (err, station) => {
+			async err => {
 				if (err) {
 					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
 					this.log(
@@ -3047,19 +3034,15 @@ export default {
 					`Selected private playlist "${playlistId}" for station "${stationId}" successfully.`
 				);
 
-				NotificationsModule.runJob("UNSCHEDULE", {
-					name: `stations.nextSong?id${stationId}`
-				});
+				PlaylistsModule.runJob("AUTOFILL_STATION_PLAYLIST", { stationId }).then().catch();
 
-				if (!station.partyMode) StationsModule.runJob("SKIP_STATION", { stationId });
-
-				CacheModule.runJob("PUB", {
-					channel: "privatePlaylist.selected",
-					value: {
-						playlistId,
-						stationId
-					}
-				});
+				// CacheModule.runJob("PUB", {
+				// 	channel: "privatePlaylist.selected",
+				// 	value: {
+				// 		playlistId,
+				// 		stationId
+				// 	}
+				// });
 
 				return cb({
 					status: "success",
@@ -3076,15 +3059,12 @@ export default {
 	 * @param stationId - the station id
 	 * @param cb
 	 */
-	deselectPrivatePlaylist: isOwnerRequired(async function deselectPrivatePlaylist(session, stationId, cb) {
-		const stationModel = await DBModule.runJob(
-			"GET_MODEL",
-			{
-				modelName: "station"
-			},
-			this
-		);
-
+	deselectPrivatePlaylist: isOwnerRequired(async function deselectPrivatePlaylist(
+		session,
+		stationId,
+		playlistId,
+		cb
+	) {
 		async.waterfall(
 			[
 				next => {
@@ -3098,30 +3078,20 @@ export default {
 				(station, next) => {
 					if (!station) return next("Station not found.");
 					if (station.type !== "community") return next("Station is not a community station.");
-					if (!station.privatePlaylist) return next("No private playlist is currently selected.");
-
-					return stationModel.updateOne(
-						{ _id: stationId },
-						{
-							$set: {
-								privatePlaylist: null,
-								currentSongIndex: 0
-							}
-						},
-						{ runValidators: true },
-						next
-					);
+					if (station.includedPlaylists.indexOf(playlistId) === -1)
+						return next("That playlist is not included.");
+					return next();
 				},
 
-				(res, next) => {
-					StationsModule.runJob("UPDATE_STATION", { stationId }, this)
-						.then(station => {
-							next(null, station);
+				next => {
+					StationsModule.runJob("REMOVE_INCLUDED_PLAYLIST", { stationId, playlistId }, this)
+						.then(() => {
+							next();
 						})
 						.catch(next);
 				}
 			],
-			async (err, station) => {
+			async err => {
 				if (err) {
 					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
 					this.log(
@@ -3138,18 +3108,14 @@ export default {
 					`Deselected private playlist for station "${stationId}" successfully.`
 				);
 
-				NotificationsModule.runJob("UNSCHEDULE", {
-					name: `stations.nextSong?id${stationId}`
-				});
+				PlaylistsModule.runJob("AUTOFILL_STATION_PLAYLIST", { stationId }).then().catch();
 
-				if (!station.partyMode) StationsModule.runJob("SKIP_STATION", { stationId });
-
-				CacheModule.runJob("PUB", {
-					channel: "privatePlaylist.deselected",
-					value: {
-						stationId
-					}
-				});
+				// CacheModule.runJob("PUB", {
+				// 	channel: "privatePlaylist.deselected",
+				// 	value: {
+				// 		stationId
+				// 	}
+				// });
 
 				return cb({
 					status: "success",

+ 8 - 0
backend/logic/playlists.js

@@ -679,6 +679,14 @@ class _PlaylistsModule extends CoreClass {
 						);
 					},
 
+					(includedSongs, next) => {
+						PlaylistsModule.runJob("UPDATE_PLAYLIST", { playlistId: originalPlaylist._id }, this)
+							.then(() => {
+								next(null, includedSongs);
+							})
+							.catch(next);
+					},
+
 					(includedSongs, next) => {
 						if (originalPlaylist.songs.length === 0 && includedSongs.length > 0)
 							StationsModule.runJob("SKIP_STATION", { stationId: payload.stationId });

+ 112 - 78
backend/logic/stations.js

@@ -498,21 +498,20 @@ class _StationsModule extends CoreClass {
 					(playlistSongs, station, next) => {
 						const songsStillNeeded = 50 - station.playlist.length;
 						const currentSongs = station.playlist;
-						const currentSongIds = station.playlist.map(song => song._id);
+						const currentSongIds = station.playlist.map(song => song.songId);
 						const songsToAdd = [];
 						playlistSongs
 							.map(song => song._doc)
 							.every(song => {
 								if (
 									songsToAdd.length < songsStillNeeded &&
-									currentSongIds.indexOf(song._id.toString()) === -1
+									currentSongIds.indexOf(song.songId) === -1
 								) {
 									songsToAdd.push(song);
 									return false;
 								}
 								return true;
 							});
-
 						next(null, [...currentSongs, ...songsToAdd]);
 					},
 
@@ -546,13 +545,13 @@ class _StationsModule extends CoreClass {
 	}
 
 	/**
-	 * Gets next official station song
+	 * Gets next station song
 	 *
 	 * @param {object} payload - object that contains the payload
 	 * @param {string} payload.stationId - the id of the station
 	 * @returns {Promise} - returns a promise (resolve, reject)
 	 */
-	GET_NEXT_OFFICIAL_STATION_SONG(payload) {
+	GET_NEXT_STATION_SONG(payload) {
 		return new Promise((resolve, reject) => {
 			const { stationId } = payload;
 
@@ -574,26 +573,27 @@ class _StationsModule extends CoreClass {
 					},
 
 					(song, next) => {
-						console.log(44444, song, song._id);
-						SongsModule.runJob("GET_SONG", { id: song._id }, this)
-							.then(response => {
-								const { song } = response;
-								if (song) {
-									const newSong = {
-										_id: song._id,
-										songId: song.songId,
-										title: song.title,
-										artists: song.artists,
-										duration: song.duration,
-										thumbnail: song.thumbnail,
-										requestedAt: song.requestedAt
-									};
-									next(null, newSong);
-								} else {
-									next(null, song);
-								}
-							})
-							.catch(next);
+						if (!song._id) next(null, song);
+						else
+							SongsModule.runJob("GET_SONG", { id: song._id }, this)
+								.then(response => {
+									const { song } = response;
+									if (song) {
+										const newSong = {
+											_id: song._id,
+											songId: song.songId,
+											title: song.title,
+											artists: song.artists,
+											duration: song.duration,
+											thumbnail: song.thumbnail,
+											requestedAt: song.requestedAt
+										};
+										next(null, newSong);
+									} else {
+										next(null, song);
+									}
+								})
+								.catch(next);
 					}
 				],
 				(err, song) => {
@@ -664,6 +664,7 @@ class _StationsModule extends CoreClass {
 
 			async.waterfall(
 				[
+					// Clears up any existing timers that would skip the station if the song ends
 					next => {
 						NotificationsModule.runJob("UNSCHEDULE", {
 							name: `stations.nextSong?id=${payload.stationId}`
@@ -674,6 +675,7 @@ class _StationsModule extends CoreClass {
 							.catch(next);
 					},
 
+					// Gets the station object
 					next => {
 						StationsModule.runJob(
 							"GET_STATION",
@@ -687,6 +689,7 @@ class _StationsModule extends CoreClass {
 							})
 							.catch(() => {});
 					},
+
 					// eslint-disable-next-line consistent-return
 					(station, next) => {
 						if (!station) return next("Station not found.");
@@ -715,63 +718,94 @@ class _StationsModule extends CoreClass {
 						}
 
 						if (station.type === "community" && !station.partyMode) {
-							return DBModule.runJob("GET_MODEL", { modelName: "playlist" }, this).then(playlistModel =>
-								playlistModel.findOne({ _id: station.privatePlaylist }, (err, playlist) => {
-									if (err) return next(err);
-
-									if (!playlist) return next(null, null, -13, station);
-
-									playlist = playlist.songs;
-
-									if (playlist.length > 0) {
-										let currentSongIndex;
-
-										if (station.currentSongIndex < playlist.length - 1)
-											currentSongIndex = station.currentSongIndex + 1;
-										else currentSongIndex = 0;
-
-										const callback = (err, song) => {
-											if (err) return next(err);
-											if (song) return next(null, song, currentSongIndex, station);
-
-											const currentSong = {
-												songId: playlist[currentSongIndex].songId,
-												title: playlist[currentSongIndex].title,
-												duration: playlist[currentSongIndex].duration,
-												likes: -1,
-												dislikes: -1,
-												requestedAt: playlist[currentSongIndex].requestedAt
-											};
-
-											return next(null, currentSong, currentSongIndex, station);
-										};
-
-										if (mongoose.Types.ObjectId.isValid(playlist[currentSongIndex]._id))
-											return SongsModule.runJob(
-												"GET_SONG",
-												{
-													id: playlist[currentSongIndex]._id
-												},
+							StationsModule.runJob(
+								"REMOVE_FIRST_OFFICIAL_PLAYLIST_QUEUE_SONG",
+								{ stationId: station._id },
+								this
+							)
+								.then(() => {
+									StationsModule.runJob(
+										"FILL_UP_OFFICIAL_STATION_PLAYLIST_QUEUE",
+										{ stationId: station._id },
+										this
+									)
+										.then(() => {
+											StationsModule.runJob(
+												"GET_NEXT_STATION_SONG",
+												{ stationId: station._id },
 												this
 											)
-												.then(response => callback(null, response.song))
-												.catch(callback);
-										return SongsModule.runJob(
-											"GET_SONG_FROM_ID",
-											{
-												songId: playlist[currentSongIndex].songId
-											},
-											this
-										)
-											.then(response => callback(null, response.song))
-											.catch(callback);
-									}
-
-									return next(null, null, -14, station);
+												.then(response => {
+													next(null, response.song, 0, station);
+												})
+												.catch(err => {
+													if (err === "No songs available.") next(null, null, 0, station);
+													else next(err);
+												});
+										})
+										.catch(next);
 								})
-							);
+								.catch(next);
 						}
 
+						// if (station.type === "community" && !station.partyMode) {
+						// 	return DBModule.runJob("GET_MODEL", { modelName: "playlist" }, this).then(playlistModel =>
+						// 		playlistModel.findOne({ _id: station.privatePlaylist }, (err, playlist) => {
+						// 			if (err) return next(err);
+
+						// 			if (!playlist) return next(null, null, -13, station);
+
+						// 			playlist = playlist.songs;
+
+						// 			if (playlist.length > 0) {
+						// 				let currentSongIndex;
+
+						// 				if (station.currentSongIndex < playlist.length - 1)
+						// 					currentSongIndex = station.currentSongIndex + 1;
+						// 				else currentSongIndex = 0;
+
+						// 				const callback = (err, song) => {
+						// 					if (err) return next(err);
+						// 					if (song) return next(null, song, currentSongIndex, station);
+
+						// 					const currentSong = {
+						// 						songId: playlist[currentSongIndex].songId,
+						// 						title: playlist[currentSongIndex].title,
+						// 						duration: playlist[currentSongIndex].duration,
+						// 						likes: -1,
+						// 						dislikes: -1,
+						// 						requestedAt: playlist[currentSongIndex].requestedAt
+						// 					};
+
+						// 					return next(null, currentSong, currentSongIndex, station);
+						// 				};
+
+						// 				if (mongoose.Types.ObjectId.isValid(playlist[currentSongIndex]._id))
+						// 					return SongsModule.runJob(
+						// 						"GET_SONG",
+						// 						{
+						// 							id: playlist[currentSongIndex]._id
+						// 						},
+						// 						this
+						// 					)
+						// 						.then(response => callback(null, response.song))
+						// 						.catch(callback);
+						// 				return SongsModule.runJob(
+						// 					"GET_SONG_FROM_ID",
+						// 					{
+						// 						songId: playlist[currentSongIndex].songId
+						// 					},
+						// 					this
+						// 				)
+						// 					.then(response => callback(null, response.song))
+						// 					.catch(callback);
+						// 			}
+
+						// 			return next(null, null, -14, station);
+						// 		})
+						// 	);
+						// }
+
 						if (station.type === "official") {
 							StationsModule.runJob(
 								"REMOVE_FIRST_OFFICIAL_PLAYLIST_QUEUE_SONG",
@@ -786,7 +820,7 @@ class _StationsModule extends CoreClass {
 									)
 										.then(() => {
 											StationsModule.runJob(
-												"GET_NEXT_OFFICIAL_STATION_SONG",
+												"GET_NEXT_STATION_SONG",
 												{ stationId: station._id },
 												this
 											)

+ 7 - 3
frontend/src/pages/Station/components/Sidebar/MyPlaylists.vue

@@ -36,7 +36,7 @@
 									!isNotSelected(playlist._id) &&
 									!station.partyMode
 							"
-							@click="deselectPlaylist()"
+							@click="deselectPlaylist(playlist._id)"
 							class="material-icons stop-icon"
 							>stop</i
 						>
@@ -178,10 +178,11 @@ export default {
 				}
 			);
 		},
-		deselectPlaylist() {
+		deselectPlaylist(id) {
 			this.socket.dispatch(
 				"stations.deselectPrivatePlaylist",
 				this.station._id,
+				id,
 				res => {
 					if (res.status === "failure")
 						return new Toast({
@@ -194,7 +195,10 @@ export default {
 		},
 		isNotSelected(id) {
 			// TODO Also change this once it changes for a station
-			if (this.station && this.station.privatePlaylist === id)
+			if (
+				this.station &&
+				this.station.includedPlaylists.indexOf(id) !== -1
+			)
 				return false;
 			return true;
 		},

+ 4 - 0
frontend/src/pages/Station/index.vue

@@ -1480,6 +1480,8 @@ export default {
 							partyMode,
 							owner,
 							privatePlaylist,
+							includedPlaylists,
+							excludedPlaylists,
 							type,
 							genres,
 							blacklistedGenres,
@@ -1503,6 +1505,8 @@ export default {
 							partyMode,
 							owner,
 							privatePlaylist,
+							includedPlaylists,
+							excludedPlaylists,
 							type,
 							genres,
 							blacklistedGenres,