Browse Source

refactor: Continued experimental config work

Owen Diffey 2 years ago
parent
commit
361a0e959a

+ 2 - 1
backend/config/default.json

@@ -30,7 +30,8 @@
 					"title": "Queries Per 100 Seconds",
 					"limit": 3000000
 				}
-			]
+			],
+			"maxPlaylistPages": 20
 		},
 		"spotify": {
 			"enabled": false,

+ 17 - 18
backend/index.js

@@ -4,6 +4,7 @@ import util from "util";
 import config from "config";
 import fs from "fs";
 
+import * as readline from "node:readline";
 import package_json from "./package.json" assert { type: "json" };
 
 const REQUIRED_CONFIG_VERSION = 12;
@@ -60,10 +61,7 @@ const printVersion = () => {
 
 printVersion();
 
-if (
-	(!config.has("configVersion") || config.get("configVersion") !== REQUIRED_CONFIG_VERSION) &&
-	!(config.has("skipConfigVersionCheck") && config.get("skipConfigVersionCheck"))
-) {
+if (config.get("configVersion") !== REQUIRED_CONFIG_VERSION && !config.get("skipConfigVersionCheck")) {
 	console.log(
 		"CONFIG VERSION IS WRONG. PLEASE UPDATE YOUR CONFIG WITH THE HELP OF THE TEMPLATE FILE AND THE README FILE."
 	);
@@ -268,10 +266,12 @@ if (!config.get("migration")) {
 	moduleManager.addModule("tasks");
 	moduleManager.addModule("utils");
 	moduleManager.addModule("youtube");
-	moduleManager.addModule("soundcloud");
-	moduleManager.addModule("spotify");
-	moduleManager.addModule("musicbrainz");
-	moduleManager.addModule("wikidata");
+	if (config.get("experimental.soundcloud")) moduleManager.addModule("soundcloud");
+	if (config.get("experimental.spotify")) {
+		moduleManager.addModule("spotify");
+		moduleManager.addModule("musicbrainz");
+		moduleManager.addModule("wikidata");
+	}
 } else {
 	moduleManager.addModule("migration");
 }
@@ -308,12 +308,10 @@ function printTask(task, layer) {
 	});
 }
 
-import * as readline from "node:readline";
-
-var rl = readline.createInterface({
+const rl = readline.createInterface({
 	input: process.stdin,
 	output: process.stdout,
-	completer: function (command) {
+	completer(command) {
 		const parts = command.split(" ");
 		const commands = [
 			"version",
@@ -330,17 +328,18 @@ var rl = readline.createInterface({
 		if (parts.length === 1) {
 			const hits = commands.filter(c => c.startsWith(parts[0]));
 			return [hits.length ? hits : commands, command];
-		} else if (parts.length === 2) {
+		}
+		if (parts.length === 2) {
 			if (["queued", "running", "paused", "runjob", "stats"].indexOf(parts[0]) !== -1) {
 				const modules = Object.keys(moduleManager.modules);
 				const hits = modules
 					.filter(module => module.startsWith(parts[1]))
 					.map(module => `${parts[0]} ${module}${parts[0] === "runjob" ? " " : ""}`);
 				return [hits.length ? hits : modules, command];
-			} else {
-				return [];
 			}
-		} else if (parts.length === 3) {
+			return [];
+		}
+		if (parts.length === 3) {
 			if (parts[0] === "runjob") {
 				const modules = Object.keys(moduleManager.modules);
 				if (modules.indexOf(parts[1]) !== -1) {
@@ -359,7 +358,7 @@ var rl = readline.createInterface({
 	}
 });
 
-rl.on("line", function (command) {
+rl.on("line", command => {
 	if (command === "version") {
 		printVersion();
 	}
@@ -451,7 +450,7 @@ rl.on("line", function (command) {
 		console.log(`Eval response: `, response);
 	}
 	if (command.startsWith("debug")) {
-		moduleManager.modules["youtube"].apiCalls.forEach(apiCall => {
+		moduleManager.modules.youtube.apiCalls.forEach(apiCall => {
 			// console.log(`${apiCall.date.toISOString()} - ${apiCall.url} - ${apiCall.quotaCost} - ${JSON.stringify(apiCall.params)}`);
 			console.log(apiCall);
 		});

+ 1 - 2
backend/logic/actions/apis.js

@@ -769,8 +769,7 @@ export default {
 			page === "youtube" ||
 			page === "youtubeVideos" ||
 			page === "youtubeChannels" ||
-			page === "soundcloud" ||
-			page === "soundcloudTracks" ||
+			(config.get("experimental.soundcloud") && (page === "soundcloud" || page === "soundcloudTracks")) ||
 			page === "import" ||
 			page === "dataRequests"
 		) {

+ 4 - 5
backend/logic/actions/playlists.js

@@ -2124,7 +2124,7 @@ export default {
 		playlistId,
 		cb
 	) {
-		if (!(config.has("experimental.soundcloud") && !!config.get("experimental.soundcloud")))
+		if (!config.get("experimental.soundcloud"))
 			return cb({ status: "error", message: "SoundCloud is not enabled" });
 
 		let songsInPlaylistTotal = 0;
@@ -2149,7 +2149,7 @@ export default {
 			this
 		);
 
-		async.waterfall(
+		return async.waterfall(
 			[
 				next => {
 					DBModule.runJob("GET_MODEL", { modelName: "user" }, this).then(userModel => {
@@ -2315,8 +2315,7 @@ export default {
 	 * @param {Function} cb - gets called with the result
 	 */
 	addSpotifySetToPlaylist: isLoginRequired(async function addSpotifySetToPlaylist(session, url, playlistId, cb) {
-		if (!(config.has("experimental.spotify") && !!config.get("experimental.spotify")))
-			return cb({ status: "error", message: "Spotify is not enabled" });
+		if (!config.get("experimental.spotify")) return cb({ status: "error", message: "Spotify is not enabled" });
 
 		let songsInPlaylistTotal = 0;
 		let addSongsStats = null;
@@ -2340,7 +2339,7 @@ export default {
 			this
 		);
 
-		async.waterfall(
+		return async.waterfall(
 			[
 				next => {
 					DBModule.runJob("GET_MODEL", { modelName: "user" }, this).then(userModel => {

+ 2 - 4
backend/logic/actions/stations.js

@@ -1007,8 +1007,7 @@ export default {
 		async.waterfall(
 			[
 				next => {
-					if (!(config.has("experimental.station_history") && !!config.get("experimental.station_history")))
-						return next("Station history is not enabled");
+					if (!config.get("experimental.station_history")) return next("Station history is not enabled");
 					return next();
 				},
 
@@ -1777,8 +1776,7 @@ export default {
 			"station"
 		];
 
-		if (data.type === "community" && config.has("blacklistedCommunityStationNames"))
-			blacklist = [...blacklist, ...config.get("blacklistedCommunityStationNames")];
+		if (data.type === "community") blacklist = [...blacklist, ...config.get("blacklistedCommunityStationNames")];
 
 		async.waterfall(
 			[

+ 1 - 4
backend/logic/actions/users.js

@@ -881,10 +881,7 @@ export default {
 				next => {
 					if (config.get("registrationDisabled") === true)
 						return next("Registration is not allowed at this time.");
-					if (
-						config.has("experimental.registration_email_whitelist") &&
-						config.get("experimental.registration_email_whitelist")
-					) {
+					if (config.get("experimental.registration_email_whitelist")) {
 						const experimentalRegistrationEmailWhitelist = config.get(
 							"experimental.registration_email_whitelist"
 						);

+ 2 - 3
backend/logic/hooks/hasPermission.js

@@ -99,13 +99,12 @@ permissions.admin = {
 	"youtube.removeVideos": true
 };
 
-if (config.has("experimental.soundcloud") && !!config.get("experimental.soundcloud")) {
+if (config.get("experimental.soundcloud")) {
 	permissions.moderator["admin.view.soundcloudTracks"] = true;
 	permissions.admin["admin.view.soundcloudTracks"] = true;
 	permissions.admin["admin.view.soundcloud"] = true;
 }
-if (config.has("experimental.spotify") && !!config.get("experimental.spotify"))
-	permissions.admin["admin.view.spotify"] = true;
+if (config.get("experimental.spotify")) permissions.admin["admin.view.spotify"] = true;
 
 export const hasPermission = async (permission, session, stationId) => {
 	const CacheModule = moduleManager.modules.cache;

+ 69 - 65
backend/logic/media.js

@@ -1,4 +1,5 @@
 import async from "async";
+import config from "config";
 import CoreClass from "../core";
 
 let MediaModule;
@@ -396,47 +397,49 @@ class _MediaModule extends CoreClass {
 								.catch(next);
 						}
 
-						if (payload.mediaSource.startsWith("soundcloud:")) {
-							const trackId = payload.mediaSource.split(":")[1];
-
-							return SoundCloudModule.runJob(
-								"GET_TRACK",
-								{ identifier: trackId, createMissing: true },
-								this
-							)
-								.then(response => {
-									const { trackId, title, username, artworkUrl, duration } = response.track;
-									next(null, song, {
-										mediaSource: `soundcloud:${trackId}`,
-										title,
-										artists: [username],
-										thumbnail: artworkUrl,
-										duration
-									});
-								})
-								.catch(next);
-						}
+						if (config.get("experimental.soundcloud")) {
+							if (payload.mediaSource.startsWith("soundcloud:")) {
+								const trackId = payload.mediaSource.split(":")[1];
+
+								return SoundCloudModule.runJob(
+									"GET_TRACK",
+									{ identifier: trackId, createMissing: true },
+									this
+								)
+									.then(response => {
+										const { trackId, title, username, artworkUrl, duration } = response.track;
+										next(null, song, {
+											mediaSource: `soundcloud:${trackId}`,
+											title,
+											artists: [username],
+											thumbnail: artworkUrl,
+											duration
+										});
+									})
+									.catch(next);
+							}
 
-						if (payload.mediaSource.indexOf("soundcloud.com") !== -1) {
-							return SoundCloudModule.runJob(
-								"GET_TRACK_FROM_URL",
-								{ identifier: payload.mediaSource, createMissing: true },
-								this
-							)
-								.then(response => {
-									const { trackId, title, username, artworkUrl, duration } = response.track;
-									next(null, song, {
-										mediaSource: `soundcloud:${trackId}`,
-										title,
-										artists: [username],
-										thumbnail: artworkUrl,
-										duration
-									});
-								})
-								.catch(next);
+							if (payload.mediaSource.indexOf("soundcloud.com") !== -1) {
+								return SoundCloudModule.runJob(
+									"GET_TRACK_FROM_URL",
+									{ identifier: payload.mediaSource, createMissing: true },
+									this
+								)
+									.then(response => {
+										const { trackId, title, username, artworkUrl, duration } = response.track;
+										next(null, song, {
+											mediaSource: `soundcloud:${trackId}`,
+											title,
+											artists: [username],
+											thumbnail: artworkUrl,
+											duration
+										});
+									})
+									.catch(next);
+							}
 						}
 
-						if (payload.mediaSource.startsWith("spotify:")) {
+						if (config.get("experimental.spotify") && payload.mediaSource.startsWith("spotify:")) {
 							const trackId = payload.mediaSource.split(":")[1];
 
 							return SpotifyModule.runJob("GET_TRACK", { identifier: trackId, createMissing: true }, this)
@@ -530,34 +533,35 @@ class _MediaModule extends CoreClass {
 							allPromises.push(promise);
 						});
 
-						soundcloudMediaSources.forEach(mediaSource => {
-							const trackId = mediaSource.split(":")[1];
-
-							const promise = SoundCloudModule.runJob(
-								"GET_TRACK",
-								{ identifier: trackId, createMissing: true },
-								this
-							)
-								.then(response => {
-									const { trackId, title, username, artworkUrl, duration } = response.track;
-									songMap[mediaSource] = {
-										mediaSource: `soundcloud:${trackId}`,
-										title,
-										artists: [username],
-										thumbnail: artworkUrl,
-										duration
-									};
-								})
-								.catch(err => {
-									MediaModule.log(
-										"ERROR",
-										`Failed to get media in GET_MEDIA_FROM_MEDIA_SOURCES with mediaSource ${mediaSource} and error`,
-										typeof err === "string" ? err : err.message
-									);
-								});
+						if (config.get("experimental.soundcloud"))
+							soundcloudMediaSources.forEach(mediaSource => {
+								const trackId = mediaSource.split(":")[1];
+
+								const promise = SoundCloudModule.runJob(
+									"GET_TRACK",
+									{ identifier: trackId, createMissing: true },
+									this
+								)
+									.then(response => {
+										const { trackId, title, username, artworkUrl, duration } = response.track;
+										songMap[mediaSource] = {
+											mediaSource: `soundcloud:${trackId}`,
+											title,
+											artists: [username],
+											thumbnail: artworkUrl,
+											duration
+										};
+									})
+									.catch(err => {
+										MediaModule.log(
+											"ERROR",
+											`Failed to get media in GET_MEDIA_FROM_MEDIA_SOURCES with mediaSource ${mediaSource} and error`,
+											typeof err === "string" ? err : err.message
+										);
+									});
 
-							allPromises.push(promise);
-						});
+								allPromises.push(promise);
+							});
 
 						Promise.allSettled(allPromises).then(() => {
 							next();

+ 15 - 3
backend/logic/songs.js

@@ -1,4 +1,5 @@
 import async from "async";
+import config from "config";
 import mongoose from "mongoose";
 import CoreClass from "../core";
 
@@ -245,7 +246,7 @@ class _SongsModule extends CoreClass {
 								}
 							);
 
-						if (mediaSourceType === "soundcloud")
+						if (config.get("experimental.soundcloud") && mediaSourceType === "soundcloud")
 							return SoundCloudModule.soundcloudTrackModel.find(
 								{
 									trackId: {
@@ -1028,11 +1029,22 @@ class _SongsModule extends CoreClass {
 						const page = payload.page ? payload.page : 1;
 						const pageSize = 15;
 						const skipAmount = pageSize * (page - 1);
+						const query = { $or: filterArray };
 
-						SongsModule.SongModel.find({ $or: filterArray }).count((err, count) => {
+						const mediaSources = [];
+						if (!config.get("experimental.soundcloud")) {
+							mediaSources.push(/^soundcloud:/);
+							mediaSources.push(/.*soundcloud.com.*/);
+						}
+						if (!config.get("experimental.spotify")) {
+							mediaSources.push(/^spotify:/);
+						}
+						if (mediaSources.length > 0) query.mediaSource = { $nin: mediaSources };
+
+						SongsModule.SongModel.find(query).count((err, count) => {
 							if (err) next(err);
 							else {
-								SongsModule.SongModel.find({ $or: filterArray })
+								SongsModule.SongModel.find(query)
 									.skip(skipAmount)
 									.limit(pageSize)
 									.exec((err, songs) => {

+ 2 - 2
backend/logic/spotify.js

@@ -102,7 +102,7 @@ class _SpotifyModule extends CoreClass {
 		});
 
 		return new Promise((resolve, reject) => {
-			if (!config.has("apis.spotify") || !config.get("apis.spotify.enabled")) {
+			if (!config.get("apis.spotify.enabled")) {
 				reject(new Error("Spotify is not enabled."));
 				return;
 			}
@@ -1067,7 +1067,7 @@ class _SpotifyModule extends CoreClass {
 						// relation["type-id"] === "7e41ef12-a124-4324-afdb-fdbae687a89c"
 						const { resource } = relation.url;
 
-						if (resource.indexOf("soundcloud.com") !== -1) {
+						if (config.get("experimental.soundcloud") && resource.indexOf("soundcloud.com") !== -1) {
 							// throw new Error(`Unable to parse SoundCloud resource ${resource}.`);
 
 							const promise = new Promise(resolve => {

+ 56 - 36
backend/logic/stations.js

@@ -176,11 +176,33 @@ class _StationsModule extends CoreClass {
 
 					next => {
 						this.setStage(4);
+						const mediaSources = [];
+						if (!config.get("experimental.soundcloud")) {
+							mediaSources.push(/^soundcloud:/);
+							mediaSources.push(/.*soundcloud.com.*/);
+						}
+						if (!config.get("experimental.spotify")) {
+							mediaSources.push(/^spotify:/);
+						}
+						if (mediaSources.length > 0)
+							stationModel.updateMany(
+								{},
+								{ $pull: { queue: { mediaSource: { $in: mediaSources } } } },
+								err => {
+									if (err) next(err);
+									else next();
+								}
+							);
+						else next();
+					},
+
+					next => {
+						this.setStage(5);
 						stationModel.find({}, next);
 					},
 
 					(stations, next) => {
-						this.setStage(5);
+						this.setStage(6);
 						async.each(
 							stations,
 							(station, next2) => {
@@ -291,7 +313,14 @@ class _StationsModule extends CoreClass {
 							});
 					},
 					(station, next) => {
-						if (!station.currentSong) {
+						if (
+							!station.currentSong ||
+							(!config.get("experimental.soundcloud") &&
+								(station.currentSong.mediaSource.startsWith("soundcloud:") ||
+									station.currentSong.mediaSource.indexOf("soundcloud.com") !== -1)) ||
+							(!config.get("experimental.spotify") &&
+								station.currentSong.mediaSource.startsWith("spotify:"))
+						) {
 							return StationsModule.runJob(
 								"SKIP_STATION",
 								{
@@ -956,8 +985,7 @@ class _StationsModule extends CoreClass {
 	 * @param {*} payload
 	 */
 	async ADD_STATION_HISTORY_ITEM(payload) {
-		if (!(config.has("experimental.station_history") && !!config.get("experimental.station_history")))
-			throw new Error("Station history is not enabled");
+		if (!config.get("experimental.station_history")) throw new Error("Station history is not enabled");
 
 		const { stationId, currentSong, skipReason, skippedAt } = payload;
 
@@ -1033,13 +1061,7 @@ class _StationsModule extends CoreClass {
 					(station, next) => {
 						if (!station) return next("Station not found.");
 
-						if (
-							!(
-								config.has("experimental.station_history") &&
-								!!config.get("experimental.station_history")
-							)
-						)
-							return next(null, station);
+						if (!config.get("experimental.station_history")) return next(null, station);
 
 						const { currentSong } = station;
 						if (!currentSong || !currentSong.mediaSource) return next(null, station);
@@ -2063,36 +2085,34 @@ class _StationsModule extends CoreClass {
 					// },
 
 					(song, station, next) => {
-						if (config.has(`experimental.queue_add_before_autofilled`)) {
-							const queueAddBeforeAutofilled = config.get(`experimental.queue_add_before_autofilled`);
+						const queueAddBeforeAutofilled = config.get(`experimental.queue_add_before_autofilled`);
 
-							if (
-								queueAddBeforeAutofilled === true ||
-								(Array.isArray(queueAddBeforeAutofilled) &&
-									queueAddBeforeAutofilled.indexOf(stationId) !== -1)
-							) {
-								let position = station.queue.length;
+						if (
+							queueAddBeforeAutofilled === true ||
+							(Array.isArray(queueAddBeforeAutofilled) &&
+								queueAddBeforeAutofilled.indexOf(stationId) !== -1)
+						) {
+							let position = station.queue.length;
 
-								if (station.autofill.enabled && station.queue.length >= station.autofill.limit) {
-									position = -station.autofill.limit;
-								}
+							if (station.autofill.enabled && station.queue.length >= station.autofill.limit) {
+								position = -station.autofill.limit;
+							}
 
-								StationsModule.stationModel.updateOne(
-									{ _id: stationId },
-									{
-										$push: {
-											queue: {
-												$each: [song],
-												$position: position
-											}
+							StationsModule.stationModel.updateOne(
+								{ _id: stationId },
+								{
+									$push: {
+										queue: {
+											$each: [song],
+											$position: position
 										}
-									},
-									{ runValidators: true },
-									next
-								);
+									}
+								},
+								{ runValidators: true },
+								next
+							);
 
-								return;
-							}
+							return;
 						}
 
 						StationsModule.stationModel.updateOne(

+ 2 - 7
backend/logic/youtube.js

@@ -624,9 +624,7 @@ class _YouTubeModule extends CoreClass {
 				return;
 			}
 			const playlistId = splitQuery[1];
-			const maxPages = config.has("apis.youtube.maxPlaylistPages")
-				? Number.parseInt(config.get("apis.youtube.maxPlaylistPages"))
-				: 20;
+			const maxPages = Number.parseInt(config.get("apis.youtube.maxPlaylistPages"));
 
 			let currentPage = 0;
 
@@ -1024,10 +1022,7 @@ class _YouTubeModule extends CoreClass {
 		return new Promise((resolve, reject) => {
 			const { params } = payload;
 
-			if (
-				config.has("experimental.disable_youtube_search") &&
-				config.get("experimental.disable_youtube_search")
-			) {
+			if (config.get("experimental.disable_youtube_search")) {
 				reject(new Error("Searching with YouTube is disabled."));
 				return;
 			}