feat: add per-playlist cron sync schedules

Each playlist now has its own cron schedule for syncing with Spotify. Default is 0 8 * * 1 (Monday 8 AM). Removed global MatchingIntervalHours in favor of per-playlist scheduling.
This commit is contained in:
2026-02-09 13:15:04 -05:00
parent faa07c2791
commit 2b4cd35cf7
3 changed files with 51 additions and 6 deletions

View File

@@ -1254,6 +1254,17 @@
</small>
</div>
<!-- Sync Schedule -->
<div class="form-group">
<label>Sync Schedule (Cron)</label>
<input type="text" id="link-sync-schedule" placeholder="0 8 * * 1" value="0 8 * * 1" style="font-family: monospace;">
<small style="color: var(--text-secondary); display: block; margin-top: 4px;">
Cron format: <code>minute hour day month dayofweek</code><br>
Default: <code>0 8 * * 1</code> = 8 AM every Monday<br>
Examples: <code>0 6 * * *</code> = daily at 6 AM, <code>0 20 * * 5</code> = Fridays at 8 PM
</small>
</div>
<div class="modal-actions">
<button onclick="closeModal('link-playlist-modal')">Cancel</button>
<button class="primary" onclick="linkPlaylist()">Link Playlist</button>
@@ -2080,6 +2091,19 @@
async function linkPlaylist() {
const jellyfinId = document.getElementById('link-jellyfin-id').value;
const name = document.getElementById('link-jellyfin-name').value;
const syncSchedule = document.getElementById('link-sync-schedule').value.trim();
// Validate sync schedule (basic cron format check)
if (!syncSchedule) {
showToast('Sync schedule is required', 'error');
return;
}
const cronParts = syncSchedule.split(/\s+/);
if (cronParts.length !== 5) {
showToast('Invalid cron format. Expected: minute hour day month dayofweek', 'error');
return;
}
// Get Spotify ID based on current mode
let spotifyId = '';
@@ -2119,7 +2143,11 @@
const res = await fetch(`/api/admin/jellyfin/playlists/${encodeURIComponent(jellyfinId)}/link`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, spotifyPlaylistId: cleanSpotifyId })
body: JSON.stringify({
name,
spotifyPlaylistId: cleanSpotifyId,
syncSchedule: syncSchedule
})
});
const data = await res.json();