mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 15:45:10 -05:00
Add lyrics prefetch endpoint and UI button: prefetch lyrics for individual playlists with progress feedback
This commit is contained in:
@@ -38,6 +38,7 @@ public class AdminController : ControllerBase
|
||||
private readonly RedisCacheService _cache;
|
||||
private readonly HttpClient _jellyfinHttpClient;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly string _envFilePath;
|
||||
private const string CacheDirectory = "/app/cache/spotify";
|
||||
|
||||
@@ -56,6 +57,7 @@ public class AdminController : ControllerBase
|
||||
SpotifyPlaylistFetcher playlistFetcher,
|
||||
RedisCacheService cache,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IServiceProvider serviceProvider,
|
||||
SpotifyTrackMatchingService? matchingService = null)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -73,6 +75,7 @@ public class AdminController : ControllerBase
|
||||
_matchingService = matchingService;
|
||||
_cache = cache;
|
||||
_jellyfinHttpClient = httpClientFactory.CreateClient();
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// .env file path is always /app/.env in Docker (mounted from host)
|
||||
// In development, it's in the parent directory of ContentRootPath
|
||||
@@ -2621,6 +2624,46 @@ public class AdminController : ControllerBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prefetch lyrics for a specific playlist
|
||||
/// </summary>
|
||||
[HttpPost("playlists/{name}/prefetch-lyrics")]
|
||||
public async Task<IActionResult> PrefetchPlaylistLyrics(string name)
|
||||
{
|
||||
var decodedName = Uri.UnescapeDataString(name);
|
||||
|
||||
try
|
||||
{
|
||||
var lyricsPrefetchService = _serviceProvider.GetService<allstarr.Services.Lyrics.LyricsPrefetchService>();
|
||||
|
||||
if (lyricsPrefetchService == null)
|
||||
{
|
||||
return StatusCode(500, new { error = "Lyrics prefetch service not available" });
|
||||
}
|
||||
|
||||
_logger.LogInformation("Starting lyrics prefetch for playlist: {Playlist}", decodedName);
|
||||
|
||||
var (fetched, cached, missing) = await lyricsPrefetchService.PrefetchPlaylistLyricsAsync(
|
||||
decodedName,
|
||||
HttpContext.RequestAborted);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
message = "Lyrics prefetch complete",
|
||||
playlist = decodedName,
|
||||
fetched,
|
||||
cached,
|
||||
missing,
|
||||
total = fetched + cached + missing
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to prefetch lyrics for playlist {Playlist}", decodedName);
|
||||
return StatusCode(500, new { error = $"Failed to prefetch lyrics: {ex.Message}" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ public class LyricsPrefetchService : BackgroundService
|
||||
totalFetched, totalCached, totalMissing);
|
||||
}
|
||||
|
||||
private async Task<(int Fetched, int Cached, int Missing)> PrefetchPlaylistLyricsAsync(
|
||||
public async Task<(int Fetched, int Cached, int Missing)> PrefetchPlaylistLyricsAsync(
|
||||
string playlistName,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
@@ -1274,6 +1274,7 @@
|
||||
<td class="cache-age">${p.cacheAge || '-'}</td>
|
||||
<td>
|
||||
<button onclick="matchPlaylistTracks('${escapeJs(p.name)}')">Match Tracks</button>
|
||||
<button onclick="prefetchLyrics('${escapeJs(p.name)}')">Prefetch Lyrics</button>
|
||||
<button onclick="viewTracks('${escapeJs(p.name)}')">View</button>
|
||||
<button class="danger" onclick="removePlaylist('${escapeJs(p.name)}')">Remove</button>
|
||||
</td>
|
||||
@@ -1568,6 +1569,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function prefetchLyrics(name) {
|
||||
try {
|
||||
showToast(`Prefetching lyrics for ${name}...`, 'info', 5000);
|
||||
const res = await fetch(`/api/admin/playlists/${encodeURIComponent(name)}/prefetch-lyrics`, { method: 'POST' });
|
||||
const data = await res.json();
|
||||
|
||||
if (res.ok) {
|
||||
const summary = `Fetched: ${data.fetched}, Cached: ${data.cached}, Missing: ${data.missing}`;
|
||||
showToast(`✓ Lyrics prefetch complete for ${name}. ${summary}`, 'success', 8000);
|
||||
} else {
|
||||
showToast(data.error || 'Failed to prefetch lyrics', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
showToast('Failed to prefetch lyrics', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function searchProvider(query, provider) {
|
||||
// Provider-specific search URLs
|
||||
const searchUrls = {
|
||||
|
||||
Reference in New Issue
Block a user