Browse Source

feat: added experimental way to use weights for songs when autofilling station

Kristian Vos 1 year ago
parent
commit
135726a693
1 changed files with 50 additions and 3 deletions
  1. 50 3
      backend/logic/stations.js

+ 50 - 3
backend/logic/stations.js

@@ -1,4 +1,5 @@
 import async from "async";
+import config from "config";
 
 import CoreClass from "../core";
 
@@ -12,6 +13,7 @@ let WSModule;
 let PlaylistsModule;
 let NotificationsModule;
 let MediaModule;
+let SongsModule;
 
 class _StationsModule extends CoreClass {
 	// eslint-disable-next-line require-jsdoc
@@ -34,6 +36,7 @@ class _StationsModule extends CoreClass {
 		PlaylistsModule = this.moduleManager.modules.playlists;
 		NotificationsModule = this.moduleManager.modules.notifications;
 		MediaModule = this.moduleManager.modules.media;
+		SongsModule = this.moduleManager.modules.songs;
 
 		this.userList = {};
 		this.usersPerStation = {};
@@ -533,7 +536,7 @@ class _StationsModule extends CoreClass {
 						} else next(null, playlist.songs, station);
 					},
 
-					(_playlistSongs, station, next) => {
+					async (_playlistSongs, station) => {
 						let playlistSongs = JSON.parse(JSON.stringify(_playlistSongs));
 						if (station.autofill.mode === "sequential") {
 							if (station.currentSongIndex <= playlistSongs.length) {
@@ -551,6 +554,50 @@ class _StationsModule extends CoreClass {
 						if (station.currentSong && station.currentSong.youtubeId)
 							currentYoutubeIds.push(station.currentSong.youtubeId);
 
+						if (
+							config.has("experimental.weight_stations") &&
+							config.get("experimental.weight_stations").indexOf(stationId) !== -1
+						) {
+							const weightMap = {};
+							const getYoutubeIds = playlistSongs
+								.map(playlistSong => playlistSong.youtubeId)
+								.filter(youtubeId => currentYoutubeIds.indexOf(youtubeId) === -1);
+
+							const { songs } = await SongsModule.runJob("GET_SONGS", { youtubeIds: getYoutubeIds });
+
+							songs.forEach(song => {
+								let weight = 1;
+
+								song.tags.forEach(tag => {
+									const regexResponse = /weight\[(\d+)\]/.exec(tag);
+									if (regexResponse) weight = Number(regexResponse[1]);
+								});
+
+								if (Number.isNaN(weight)) weight = 1;
+								weight = Math.round(weight);
+								weight = Math.max(1, weight);
+								weight = Math.min(10000, weight);
+
+								weightMap[song.youtubeId] = weight;
+							});
+
+							const adjustedPlaylistSongs = [];
+
+							playlistSongs.forEach(playlistSong => {
+								Array.from({ length: weightMap[playlistSong.youtubeId] }).forEach(() => {
+									adjustedPlaylistSongs.push(playlistSong);
+								});
+							});
+
+							const { array } = await UtilsModule.runJob(
+								"SHUFFLE",
+								{ array: adjustedPlaylistSongs },
+								this
+							);
+
+							playlistSongs = array;
+						}
+
 						playlistSongs.every(song => {
 							if (
 								songsToAdd.length < songsStillNeeded &&
@@ -574,10 +621,10 @@ class _StationsModule extends CoreClass {
 							if (indexOfLastSong !== -1) currentSongIndex = indexOfLastSong;
 						}
 
-						next(null, currentSongs, songsToAdd, currentSongIndex);
+						return { currentSongs, songsToAdd, currentSongIndex };
 					},
 
-					(currentSongs, songsToAdd, currentSongIndex, next) => {
+					({ currentSongs, songsToAdd, currentSongIndex }, next) => {
 						const songs = [];
 						async.eachLimit(
 							songsToAdd.map(song => song.youtubeId),