Fix downloads endpoint to show kept files and remove lyrics cache endpoint

- Downloads endpoint now shows both /app/downloads (cache) and /app/kept (favorited)
- Added location field to distinguish between cache and kept files
- Added cacheCount and keptCount to response
- Removed lyrics cache clear endpoint (no longer needed)
This commit is contained in:
2026-02-06 23:53:36 -05:00
parent b99a199ef3
commit 2389b80733

View File

@@ -1738,30 +1738,6 @@ public class AdminController : ControllerBase
}); });
} }
/// <summary>
/// Clear all cached lyrics (LRCLIB only - Jellyfin and Spotify lyrics are not cached)
/// </summary>
[HttpPost("cache/clear-lyrics")]
public async Task<IActionResult> 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)."
});
}
/// <summary> /// <summary>
/// Restart the allstarr container to apply configuration changes /// Restart the allstarr container to apply configuration changes
/// </summary> /// </summary>
@@ -3348,7 +3324,7 @@ public class LinkPlaylistRequest
/// <summary> /// <summary>
/// GET /api/admin/downloads /// GET /api/admin/downloads
/// Lists all downloaded files in the downloads directory /// Lists all downloaded files in the downloads directory AND kept folder
/// </summary> /// </summary>
[HttpGet("downloads")] [HttpGet("downloads")]
public IActionResult GetDownloads() public IActionResult GetDownloads()
@@ -3356,46 +3332,84 @@ public class LinkPlaylistRequest
try try
{ {
var downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads"; var downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads";
var keptPath = "/app/kept";
if (!Directory.Exists(downloadPath))
{
return Ok(new { files = new List<object>(), totalSize = 0 });
}
var files = new List<object>(); var files = new List<object>();
long totalSize = 0; long totalSize = 0;
// Recursively get all audio files // Recursively get all audio files from both locations
var audioExtensions = new[] { ".flac", ".mp3", ".m4a", ".opus" }; 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 downloadFiles = Directory.GetFiles(downloadPath, "*.*", SearchOption.AllDirectories)
var relativePath = Path.GetRelativePath(downloadPath, filePath); .Where(f => audioExtensions.Contains(Path.GetExtension(f).ToLowerInvariant()))
.ToList();
// Parse artist/album/track from path structure foreach (var filePath in downloadFiles)
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, var fileInfo = new FileInfo(filePath);
fullPath = filePath, var relativePath = Path.GetRelativePath(downloadPath, filePath);
artist,
album,
fileName,
size = fileInfo.Length,
sizeFormatted = FormatFileSize(fileInfo.Length),
lastModified = fileInfo.LastWriteTimeUtc,
extension = fileInfo.Extension
});
totalSize += fileInfo.Length; // 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();
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 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), files = files.OrderBy(f => ((dynamic)f).artist).ThenBy(f => ((dynamic)f).album).ThenBy(f => ((dynamic)f).fileName),
totalSize, totalSize,
totalSizeFormatted = FormatFileSize(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) catch (Exception ex)