Browse Source

refactor: enabled channel importing into playlists

Kristian Vos 2 years ago
parent
commit
aadca463dc

+ 34 - 13
backend/logic/actions/playlists.js

@@ -1280,20 +1280,41 @@ export default {
 		async.waterfall(
 			[
 				next => {
-					this.publishProgress({ status: "update", message: `Importing YouTube playlist (stage 1)` });
-					YouTubeModule.runJob("GET_PLAYLIST", { url, musicOnly }, this)
-						.then(res => {
-							if (res.filteredSongs) {
-								videosInPlaylistTotal = res.songs.length;
-								songsInPlaylistTotal = res.filteredSongs.length;
-							} else {
-								songsInPlaylistTotal = videosInPlaylistTotal = res.songs.length;
-							}
-							next(null, res.songs);
-						})
-						.catch(err => {
-							next(err);
+					DBModule.runJob("GET_MODEL", { modelName: "user" }, this).then(userModel => {
+						userModel.findOne({ _id: session.userId }, (err, user) => {
+							if (user && user.role === "admin") return next(null, true);
+							return next(null, false);
 						});
+					});
+				},
+
+				(isAdmin, next) => {
+					this.publishProgress({ status: "update", message: `Importing YouTube playlist (stage 1)` });
+					const playlistRegex = /[\\?&]list=([^&#]*)/;
+					const channelRegex =
+						/\.[\w]+\/(?:(?:channel\/(UC[0-9A-Za-z_-]{21}[AQgw]))|(?:user\/?([\w-]+))|(?:c\/?([\w-]+))|(?:\/?([\w-]+)))/;
+
+					if (playlistRegex.exec(url) || channelRegex.exec(url))
+						YouTubeModule.runJob(
+							playlistRegex.exec(url) ? "GET_PLAYLIST" : "GET_CHANNEL",
+							{
+								url,
+								musicOnly,
+								disableSearch: !isAdmin
+							},
+							this
+						)
+							.then(res => {
+								if (res.filteredSongs) {
+									videosInPlaylistTotal = res.songs.length;
+									songsInPlaylistTotal = res.filteredSongs.length;
+								} else {
+									songsInPlaylistTotal = videosInPlaylistTotal = res.songs.length;
+								}
+								next(null, res.songs);
+							})
+							.catch(next);
+					else next("Invalid YouTube URL.");
 				},
 				(youtubeIds, next) => {
 					this.publishProgress({ status: "update", message: `Importing YouTube playlist (stage 2)` });

+ 10 - 3
backend/logic/youtube.js

@@ -587,7 +587,7 @@ class _YouTubeModule extends CoreClass {
 				],
 				(err, channelId) => {
 					if (err) {
-						YouTubeModule.log("ERROR", "GET_CHANNEL_ID_FROM_CUSTOM_URL", `${err.message}`);
+						YouTubeModule.log("ERROR", "GET_CHANNEL_ID_FROM_CUSTOM_URL", `${err.message || err}`);
 						if (err.message === "Request failed with status code 404") {
 							return reject(new Error("Channel not found. Is the channel public/unlisted?"));
 						}
@@ -783,6 +783,7 @@ class _YouTubeModule extends CoreClass {
 	 *
 	 * @param {object} payload - object that contains the payload
 	 * @param {boolean} payload.musicOnly - whether to return music videos or all videos in the channel
+	 * @param {boolean} payload.disableSearch - whether to allow searching for custom url/username
 	 * @param {string} payload.url - the url of the YouTube channel
 	 * @returns {Promise} - returns promise (reject, resolve)
 	 */
@@ -807,6 +808,8 @@ class _YouTubeModule extends CoreClass {
 			console.log(`Channel custom URL: ${channelCustomUrl}`);
 			console.log(`Channel username or custom URL: ${channelUsernameOrCustomUrl}`);
 
+			const disableSearch = payload.disableSearch || false;
+
 			async.waterfall(
 				[
 					next => {
@@ -829,6 +832,10 @@ class _YouTubeModule extends CoreClass {
 					(getUsernameFromCustomUrl, playlistId, next) => {
 						if (!getUsernameFromCustomUrl) return next(null, playlistId);
 
+						if (disableSearch)
+							return next(
+								"Importing with this type of URL is disabled. Please provide a channel URL with the channel ID."
+							);
 						const payload = {};
 						if (channelCustomUrl) payload.customUrl = channelCustomUrl;
 						else if (channelUsernameOrCustomUrl) payload.customUrl = channelUsernameOrCustomUrl;
@@ -890,8 +897,8 @@ class _YouTubeModule extends CoreClass {
 				],
 				(err, response) => {
 					if (err && err !== true) {
-						YouTubeModule.log("ERROR", "GET_CHANNEL", "Some error has occurred.", err.message);
-						reject(new Error(err.message));
+						YouTubeModule.log("ERROR", "GET_CHANNEL", "Some error has occurred.", err.message || err);
+						reject(new Error(err.message || err));
 					} else {
 						resolve({ songs: response.filteredSongs ? response.filteredSongs.videoIds : response.songs });
 					}

+ 7 - 3
frontend/src/components/modals/EditPlaylist/Tabs/ImportPlaylists.vue

@@ -27,10 +27,14 @@ const importPlaylist = () => {
 	if (!youtubeSearch.value.playlist.query)
 		return new Toast("Please enter a YouTube playlist URL.");
 
-	const regex = /[\\?&]list=([^&#]*)/;
-	const splitQuery = regex.exec(youtubeSearch.value.playlist.query);
+	const playlistRegex = /[\\?&]list=([^&#]*)/;
+	const channelRegex =
+		/\.[\w]+\/(?:(?:channel\/(UC[0-9A-Za-z_-]{21}[AQgw]))|(?:user\/?([\w-]+))|(?:c\/?([\w-]+))|(?:\/?([\w-]+)))/;
 
-	if (!splitQuery) {
+	if (
+		!playlistRegex.exec(youtubeSearch.value.playlist.query) &&
+		!channelRegex.exec(youtubeSearch.value.playlist.query)
+	) {
 		return new Toast({
 			content: "Please enter a valid YouTube playlist URL.",
 			timeout: 4000