From 440ef9850f1249774c6b928891de40dc5f1f5c4d Mon Sep 17 00:00:00 2001 From: Josh Patra Date: Sat, 7 Feb 2026 00:35:12 -0500 Subject: [PATCH] Make kept path configurable via web UI - Added Library:KeptPath to appsettings.json (default: /app/kept) - Added Library Settings card to web UI with DownloadPath and KeptPath - Updated GetDownloads and DeleteDownload endpoints to use configured path - Updated JellyfinController to use configured kept path - Injected IConfiguration into JellyfinController - Users can now customize where favorited tracks are stored --- allstarr/Controllers/AdminController.cs | 9 +++++++-- allstarr/Controllers/JellyfinController.cs | 9 ++++++--- allstarr/appsettings.json | 3 ++- allstarr/wwwroot/index.html | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/allstarr/Controllers/AdminController.cs b/allstarr/Controllers/AdminController.cs index e8c3a4b..c54ca0c 100644 --- a/allstarr/Controllers/AdminController.cs +++ b/allstarr/Controllers/AdminController.cs @@ -1450,6 +1450,11 @@ public class AdminController : ControllerBase userId = _jellyfinSettings.UserId ?? "(not set)", libraryId = _jellyfinSettings.LibraryId }, + library = new + { + downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads", + keptPath = _configuration["Library:KeptPath"] ?? "/app/kept" + }, deezer = new { arl = MaskValue(_deezerSettings.Arl, showLast: 8), @@ -3331,7 +3336,7 @@ public class LinkPlaylistRequest { try { - var keptPath = "/app/kept"; + var keptPath = _configuration["Library:KeptPath"] ?? "/app/kept"; _logger.LogInformation("📂 Checking kept folder: {Path}", keptPath); _logger.LogInformation("📂 Directory exists: {Exists}", Directory.Exists(keptPath)); @@ -3414,7 +3419,7 @@ public class LinkPlaylistRequest return BadRequest(new { error = "Path is required" }); } - var keptPath = "/app/kept"; + var keptPath = _configuration["Library:KeptPath"] ?? "/app/kept"; var fullPath = Path.Combine(keptPath, path); _logger.LogInformation("🗑️ Delete request for: {Path}", fullPath); diff --git a/allstarr/Controllers/JellyfinController.cs b/allstarr/Controllers/JellyfinController.cs index 83d2590..1a3656a 100644 --- a/allstarr/Controllers/JellyfinController.cs +++ b/allstarr/Controllers/JellyfinController.cs @@ -41,6 +41,7 @@ public class JellyfinController : ControllerBase private readonly SpotifyLyricsService? _spotifyLyricsService; private readonly LrclibService? _lrclibService; private readonly RedisCacheService _cache; + private readonly IConfiguration _configuration; private readonly ILogger _logger; public JellyfinController( @@ -55,6 +56,7 @@ public class JellyfinController : ControllerBase JellyfinProxyService proxyService, JellyfinSessionManager sessionManager, RedisCacheService cache, + IConfiguration configuration, ILogger logger, ParallelMetadataService? parallelMetadataService = null, PlaylistSyncService? playlistSyncService = null, @@ -78,6 +80,7 @@ public class JellyfinController : ControllerBase _spotifyLyricsService = spotifyLyricsService; _lrclibService = lrclibService; _cache = cache; + _configuration = configuration; _logger = logger; if (string.IsNullOrWhiteSpace(_settings.Url)) @@ -3787,8 +3790,8 @@ public class JellyfinController : ControllerBase return; } - // Build kept folder path: /app/kept/Artist/Album/ - var keptBasePath = "/app/kept"; + // Build kept folder path: Artist/Album/ + var keptBasePath = _configuration["Library:KeptPath"] ?? "/app/kept"; var keptArtistPath = Path.Combine(keptBasePath, PathHelper.SanitizeFileName(song.Artist)); var keptAlbumPath = Path.Combine(keptArtistPath, PathHelper.SanitizeFileName(song.Album)); @@ -4084,7 +4087,7 @@ public class JellyfinController : ControllerBase var song = await _metadataService.GetSongAsync(provider!, externalId!); if (song == null) return; - var keptBasePath = "/app/kept"; + var keptBasePath = _configuration["Library:KeptPath"] ?? "/app/kept"; var keptArtistPath = Path.Combine(keptBasePath, PathHelper.SanitizeFileName(song.Artist)); var keptAlbumPath = Path.Combine(keptArtistPath, PathHelper.SanitizeFileName(song.Album)); diff --git a/allstarr/appsettings.json b/allstarr/appsettings.json index f5e6fa6..771d34a 100644 --- a/allstarr/appsettings.json +++ b/allstarr/appsettings.json @@ -32,7 +32,8 @@ "EnableExternalPlaylists": true }, "Library": { - "DownloadPath": "./downloads" + "DownloadPath": "./downloads", + "KeptPath": "/app/kept" }, "Qobuz": { "UserAuthToken": "your-qobuz-token", diff --git a/allstarr/wwwroot/index.html b/allstarr/wwwroot/index.html index 5820ac5..7cc913c 100644 --- a/allstarr/wwwroot/index.html +++ b/allstarr/wwwroot/index.html @@ -920,6 +920,22 @@ +
+

Library Settings

+
+
+ Download Path (Cache) + - + +
+
+ Kept Path (Favorited) + - + +
+
+
+

Sync Schedule

@@ -1687,6 +1703,10 @@ document.getElementById('config-jellyfin-user-id').textContent = data.jellyfin.userId || '(not set)'; document.getElementById('config-jellyfin-library-id').textContent = data.jellyfin.libraryId || '-'; + // Library settings + document.getElementById('config-download-path').textContent = data.library?.downloadPath || './downloads'; + document.getElementById('config-kept-path').textContent = data.library?.keptPath || '/app/kept'; + // Sync settings const syncHour = data.spotifyImport.syncStartHour; const syncMin = data.spotifyImport.syncStartMinute;