diff --git a/allstarr/Controllers/AdminController.cs b/allstarr/Controllers/AdminController.cs index 84a262a..e15ec78 100644 --- a/allstarr/Controllers/AdminController.cs +++ b/allstarr/Controllers/AdminController.cs @@ -1738,30 +1738,6 @@ public class AdminController : ControllerBase }); } - /// - /// Clear all cached lyrics (LRCLIB only - Jellyfin and Spotify lyrics are not cached) - /// - [HttpPost("cache/clear-lyrics")] - public async Task ClearLyricsCache() - { - _logger.LogInformation("Lyrics cache clear requested from admin UI"); - - var clearedRedisKeys = 0; - - // Clear all lyrics cache keys (pattern-based deletion) - // This includes LRCLIB lyrics and manual mappings - var lyricsKeysDeleted = await _cache.DeleteByPatternAsync("lyrics:*"); - clearedRedisKeys += lyricsKeysDeleted; - - _logger.LogInformation("Lyrics cache cleared: {RedisKeys} Redis keys deleted", clearedRedisKeys); - - return Ok(new { - message = "Lyrics cache cleared successfully", - redisKeysDeleted = clearedRedisKeys, - note = "Only LRCLIB lyrics are cached. Jellyfin and Spotify lyrics are fetched on-demand (fast)." - }); - } - /// /// Restart the allstarr container to apply configuration changes /// @@ -3348,7 +3324,7 @@ public class LinkPlaylistRequest /// /// GET /api/admin/downloads - /// Lists all downloaded files in the downloads directory + /// Lists all downloaded files in the downloads directory AND kept folder /// [HttpGet("downloads")] public IActionResult GetDownloads() @@ -3356,46 +3332,84 @@ public class LinkPlaylistRequest try { var downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads"; - - if (!Directory.Exists(downloadPath)) - { - return Ok(new { files = new List(), totalSize = 0 }); - } + var keptPath = "/app/kept"; var files = new List(); long totalSize = 0; - // Recursively get all audio files + // Recursively get all audio files from both locations var audioExtensions = new[] { ".flac", ".mp3", ".m4a", ".opus" }; - var allFiles = Directory.GetFiles(downloadPath, "*.*", SearchOption.AllDirectories) - .Where(f => audioExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())) - .ToList(); - foreach (var filePath in allFiles) + // Get files from downloads folder (cache) + if (Directory.Exists(downloadPath)) { - var fileInfo = new FileInfo(filePath); - var relativePath = Path.GetRelativePath(downloadPath, filePath); + var downloadFiles = Directory.GetFiles(downloadPath, "*.*", SearchOption.AllDirectories) + .Where(f => audioExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())) + .ToList(); - // Parse artist/album/track from path structure - var parts = relativePath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - var artist = parts.Length > 0 ? parts[0] : ""; - var album = parts.Length > 1 ? parts[1] : ""; - var fileName = parts.Length > 2 ? parts[^1] : Path.GetFileName(filePath); - - files.Add(new + foreach (var filePath in downloadFiles) { - path = relativePath, - fullPath = filePath, - artist, - album, - fileName, - size = fileInfo.Length, - sizeFormatted = FormatFileSize(fileInfo.Length), - lastModified = fileInfo.LastWriteTimeUtc, - extension = fileInfo.Extension - }); + var fileInfo = new FileInfo(filePath); + var relativePath = Path.GetRelativePath(downloadPath, filePath); + + // Parse artist/album/track from path structure + var parts = relativePath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var artist = parts.Length > 0 ? parts[0] : ""; + var album = parts.Length > 1 ? parts[1] : ""; + var fileName = parts.Length > 2 ? parts[^1] : Path.GetFileName(filePath); + + files.Add(new + { + path = relativePath, + fullPath = filePath, + artist, + album, + fileName, + size = fileInfo.Length, + sizeFormatted = FormatFileSize(fileInfo.Length), + lastModified = fileInfo.LastWriteTimeUtc, + extension = fileInfo.Extension, + location = "cache" + }); + + totalSize += fileInfo.Length; + } + } + + // Get files from kept folder (favorited) + if (Directory.Exists(keptPath)) + { + var keptFiles = Directory.GetFiles(keptPath, "*.*", SearchOption.AllDirectories) + .Where(f => audioExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())) + .ToList(); - totalSize += fileInfo.Length; + foreach (var filePath in keptFiles) + { + var fileInfo = new FileInfo(filePath); + var relativePath = Path.GetRelativePath(keptPath, filePath); + + // Parse artist/album/track from path structure + var parts = relativePath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var artist = parts.Length > 0 ? parts[0] : ""; + var album = parts.Length > 1 ? parts[1] : ""; + var fileName = parts.Length > 2 ? parts[^1] : Path.GetFileName(filePath); + + files.Add(new + { + path = relativePath, + fullPath = filePath, + artist, + album, + fileName, + size = fileInfo.Length, + sizeFormatted = FormatFileSize(fileInfo.Length), + lastModified = fileInfo.LastWriteTimeUtc, + extension = fileInfo.Extension, + location = "kept" + }); + + totalSize += fileInfo.Length; + } } return Ok(new @@ -3403,7 +3417,9 @@ public class LinkPlaylistRequest files = files.OrderBy(f => ((dynamic)f).artist).ThenBy(f => ((dynamic)f).album).ThenBy(f => ((dynamic)f).fileName), totalSize, totalSizeFormatted = FormatFileSize(totalSize), - count = files.Count + count = files.Count, + cacheCount = files.Count(f => ((dynamic)f).location == "cache"), + keptCount = files.Count(f => ((dynamic)f).location == "kept") }); } catch (Exception ex)