mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Fix Spotify missing tracks search order: forward 12h then backward 12h
This commit is contained in:
@@ -146,12 +146,13 @@ public class SpotifyMissingTracksFetcher : BackgroundService
|
|||||||
.AddMinutes(settings.SyncStartMinute);
|
.AddMinutes(settings.SyncStartMinute);
|
||||||
var syncEnd = syncStart.AddHours(settings.SyncWindowHours);
|
var syncEnd = syncStart.AddHours(settings.SyncWindowHours);
|
||||||
|
|
||||||
if (now < syncStart || now > syncEnd)
|
// Only run after the sync window has passed
|
||||||
|
if (now < syncEnd)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Within sync window, fetching missing tracks...");
|
_logger.LogInformation("Sync window passed, searching last 24 hours for missing tracks...");
|
||||||
|
|
||||||
foreach (var kvp in _playlistIdToName)
|
foreach (var kvp in _playlistIdToName)
|
||||||
{
|
{
|
||||||
@@ -175,46 +176,106 @@ public class SpotifyMissingTracksFetcher : BackgroundService
|
|||||||
var jellyfinUrl = _jellyfinSettings.Value.Url;
|
var jellyfinUrl = _jellyfinSettings.Value.Url;
|
||||||
var apiKey = _jellyfinSettings.Value.ApiKey;
|
var apiKey = _jellyfinSettings.Value.ApiKey;
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
var today = DateTime.UtcNow.Date;
|
|
||||||
var syncStart = today
|
// Start from the configured sync time (most likely time)
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
var todaySync = now.Date
|
||||||
.AddHours(settings.SyncStartHour)
|
.AddHours(settings.SyncStartHour)
|
||||||
.AddMinutes(settings.SyncStartMinute);
|
.AddMinutes(settings.SyncStartMinute);
|
||||||
var syncEnd = syncStart.AddHours(settings.SyncWindowHours);
|
|
||||||
|
// If we haven't reached today's sync time yet, start from yesterday's sync time
|
||||||
|
var syncTime = now >= todaySync ? todaySync : todaySync.AddDays(-1);
|
||||||
|
|
||||||
_logger.LogInformation("Searching for missing tracks file for {Playlist}", playlistName);
|
_logger.LogInformation("Searching ±12 hours around {SyncTime} for {Playlist}",
|
||||||
|
syncTime, playlistName);
|
||||||
|
|
||||||
for (var time = syncStart; time <= syncEnd; time = time.AddMinutes(5))
|
var found = false;
|
||||||
|
|
||||||
|
// Search forward 12 hours from sync time
|
||||||
|
for (var minutesAhead = 0; minutesAhead <= 720; minutesAhead++) // 720 minutes = 12 hours
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) break;
|
if (cancellationToken.IsCancellationRequested) break;
|
||||||
|
|
||||||
var filename = $"{playlistName}_missing_{time:yyyy-MM-dd_HH-mm}.json";
|
var time = syncTime.AddMinutes(minutesAhead);
|
||||||
var url = $"{jellyfinUrl}/Viperinius.Plugin.SpotifyImport/MissingTracksFile" +
|
if (await TryFetchMissingTracksFile(playlistName, time, jellyfinUrl, apiKey, httpClient, cancellationToken))
|
||||||
$"?name={Uri.EscapeDataString(filename)}&api_key={apiKey}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Trying {Filename}", filename);
|
found = true;
|
||||||
var response = await httpClient.GetAsync(url, cancellationToken);
|
break;
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var json = await response.Content.ReadAsStringAsync(cancellationToken);
|
|
||||||
var tracks = ParseMissingTracks(json);
|
|
||||||
|
|
||||||
if (tracks.Count > 0)
|
|
||||||
{
|
|
||||||
await _cache.SetAsync(cacheKey, tracks, TimeSpan.FromHours(24));
|
|
||||||
_logger.LogInformation(
|
|
||||||
"✓ Cached {Count} missing tracks for {Playlist} from {Filename}",
|
|
||||||
tracks.Count, playlistName, filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
// Small delay every 60 requests
|
||||||
|
if (minutesAhead > 0 && minutesAhead % 60 == 0)
|
||||||
{
|
{
|
||||||
_logger.LogDebug(ex, "Failed to fetch {Filename}", filename);
|
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Then search backwards 12 hours from sync time
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
for (var minutesBehind = 1; minutesBehind <= 720; minutesBehind++)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested) break;
|
||||||
|
|
||||||
|
var time = syncTime.AddMinutes(-minutesBehind);
|
||||||
|
if (await TryFetchMissingTracksFile(playlistName, time, jellyfinUrl, apiKey, httpClient, cancellationToken))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small delay every 60 requests
|
||||||
|
if (minutesBehind % 60 == 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Could not find missing tracks file for {Playlist} in ±12 hour window", playlistName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> TryFetchMissingTracksFile(
|
||||||
|
string playlistName,
|
||||||
|
DateTime time,
|
||||||
|
string jellyfinUrl,
|
||||||
|
string apiKey,
|
||||||
|
HttpClient httpClient,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var filename = $"{playlistName}_missing_{time:yyyy-MM-dd_HH-mm}.json";
|
||||||
|
var url = $"{jellyfinUrl}/Viperinius.Plugin.SpotifyImport/MissingTracksFile" +
|
||||||
|
$"?name={Uri.EscapeDataString(filename)}&api_key={apiKey}";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogDebug("Trying {Filename}", filename);
|
||||||
|
var response = await httpClient.GetAsync(url, cancellationToken);
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var json = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||||
|
var tracks = ParseMissingTracks(json);
|
||||||
|
|
||||||
|
if (tracks.Count > 0)
|
||||||
|
{
|
||||||
|
var cacheKey = $"spotify:missing:{playlistName}";
|
||||||
|
await _cache.SetAsync(cacheKey, tracks, TimeSpan.FromHours(24));
|
||||||
|
_logger.LogInformation(
|
||||||
|
"✓ Cached {Count} missing tracks for {Playlist} from {Filename}",
|
||||||
|
tracks.Count, playlistName, filename);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogDebug(ex, "Failed to fetch {Filename}", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MissingTrack> ParseMissingTracks(string json)
|
private List<MissingTrack> ParseMissingTracks(string json)
|
||||||
|
|||||||
Reference in New Issue
Block a user