feat: add sync schedule editing and improve Spotify rate limit handling

Renamed Active Playlists to Injected Playlists. Added sync schedule column with inline edit button. Added endpoint to update playlist sync schedules. Improved error handling for Spotify rate limits with user-friendly messages.
This commit is contained in:
2026-02-09 13:22:02 -05:00
parent 2b4cd35cf7
commit a37f7e0b1d
2 changed files with 113 additions and 6 deletions

View File

@@ -259,6 +259,7 @@ public class AdminController : ControllerBase
["id"] = config.Id,
["jellyfinId"] = config.JellyfinId,
["localTracksPosition"] = config.LocalTracksPosition.ToString(),
["syncSchedule"] = config.SyncSchedule ?? "0 8 * * 1",
["trackCount"] = 0,
["localTracks"] = 0,
["externalTracks"] = 0,
@@ -2311,6 +2312,60 @@ public class AdminController : ControllerBase
return await RemovePlaylist(decodedName);
}
/// <summary>
/// Update playlist sync schedule
/// </summary>
[HttpPut("playlists/{name}/schedule")]
public async Task<IActionResult> UpdatePlaylistSchedule(string name, [FromBody] UpdateScheduleRequest request)
{
var decodedName = Uri.UnescapeDataString(name);
if (string.IsNullOrWhiteSpace(request.SyncSchedule))
{
return BadRequest(new { error = "SyncSchedule is required" });
}
// Basic cron validation
var cronParts = request.SyncSchedule.Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (cronParts.Length != 5)
{
return BadRequest(new { error = "Invalid cron format. Expected: minute hour day month dayofweek" });
}
// Read current playlists
var currentPlaylists = await ReadPlaylistsFromEnvFile();
var playlist = currentPlaylists.FirstOrDefault(p => p.Name.Equals(decodedName, StringComparison.OrdinalIgnoreCase));
if (playlist == null)
{
return NotFound(new { error = $"Playlist '{decodedName}' not found" });
}
// Update the schedule
playlist.SyncSchedule = request.SyncSchedule.Trim();
// Save back to .env
var playlistsJson = JsonSerializer.Serialize(
currentPlaylists.Select(p => new[] {
p.Name,
p.Id,
p.JellyfinId,
p.LocalTracksPosition.ToString().ToLower(),
p.SyncSchedule ?? "0 8 * * 1"
}).ToArray()
);
var updateRequest = new ConfigUpdateRequest
{
Updates = new Dictionary<string, string>
{
["SPOTIFY_IMPORT_PLAYLISTS"] = playlistsJson
}
};
return await UpdateConfig(updateRequest);
}
private string GetJellyfinAuthHeader()
{
return $"MediaBrowser Client=\"Allstarr\", Device=\"Server\", DeviceId=\"allstarr-admin\", Version=\"1.0.0\", Token=\"{_jellyfinSettings.ApiKey}\"";
@@ -3417,6 +3472,11 @@ public class LinkPlaylistRequest
public string SyncSchedule { get; set; } = "0 8 * * 1"; // Default: 8 AM every Monday
}
public class UpdateScheduleRequest
{
public string SyncSchedule { get; set; } = string.Empty;
}
/// <summary>
/// GET /api/admin/downloads
/// Lists all downloaded files in the KEPT folder only (favorited tracks)