diff --git a/.env.example b/.env.example index ed98ecc..4730c3c 100644 --- a/.env.example +++ b/.env.example @@ -126,13 +126,26 @@ SPOTIFY_IMPORT_SYNC_START_MINUTE=15 # Example: If plugin runs at 4:15 PM and window is 2 hours, checks from 4:00 PM to 6:00 PM SPOTIFY_IMPORT_SYNC_WINDOW_HOURS=2 -# Playlists configuration (JSON array format - combines name, ID, and local track position) +# Playlists configuration (SIMPLE FORMAT - recommended for .env files) +# Comma-separated lists - all three must have the same number of items +# +# 1. Playlist IDs (get from Jellyfin playlist URL: https://jellyfin.example.com/web/#/details?id=PLAYLIST_ID) +SPOTIFY_IMPORT_PLAYLIST_IDS= +# +# 2. Playlist names (as they appear in Jellyfin) +SPOTIFY_IMPORT_PLAYLIST_NAMES= +# +# 3. Local track positions (optional - defaults to "first" if not specified) +# - "first": Local tracks appear first, external tracks at the end +# - "last": External tracks appear first, local tracks at the end +SPOTIFY_IMPORT_PLAYLIST_LOCAL_TRACKS_POSITIONS= +# +# Example with 4 playlists: +# SPOTIFY_IMPORT_PLAYLIST_IDS=4383a46d8bcac3be2ef9385053ea18df,ba50e26c867ec9d57ab2f7bf24cfd6b0,8203ce3be9b0053b122190eb23bac7ea,7c2b218bd69b00e24c986363ba71852f +# SPOTIFY_IMPORT_PLAYLIST_NAMES=Discover Weekly,Release Radar,Today's Top Hits,On Repeat +# SPOTIFY_IMPORT_PLAYLIST_LOCAL_TRACKS_POSITIONS=first,first,last,first +# +# Advanced: JSON array format (use only if you can't use the simple format above) # Format: [["PlaylistName","JellyfinPlaylistId","first|last"],...] -# - PlaylistName: Name as it appears in Jellyfin (e.g., "Discover Weekly", "Release Radar") -# - JellyfinPlaylistId: Get from playlist URL: https://jellyfin.example.com/web/#/details?id=PLAYLIST_ID -# - first|last: Where to position local tracks relative to external tracks -# - "first": Local tracks appear first, external tracks at the end (default) -# - "last": External tracks appear first, local tracks at the end -# Example with 2 playlists: +# Note: This format may not work in .env files due to Docker Compose limitations # SPOTIFY_IMPORT_PLAYLISTS=[["Discover Weekly","4383a46d8bcac3be2ef9385053ea18df","first"],["Release Radar","ba50e26c867ec9d57ab2f7bf24cfd6b0","last"]] -SPOTIFY_IMPORT_PLAYLISTS= diff --git a/allstarr/Models/Settings/SpotifyImportSettings.cs b/allstarr/Models/Settings/SpotifyImportSettings.cs index 5cddd8f..ab15df9 100644 --- a/allstarr/Models/Settings/SpotifyImportSettings.cs +++ b/allstarr/Models/Settings/SpotifyImportSettings.cs @@ -93,6 +93,14 @@ public class SpotifyImportSettings [Obsolete("Use Playlists instead")] public List PlaylistNames { get; set; } = new(); + /// + /// Legacy: Comma-separated list of local track positions ("first" or "last") + /// Deprecated: Use Playlists instead + /// Example: "first,last,first,first" (one per playlist) + /// + [Obsolete("Use Playlists instead")] + public List PlaylistLocalTracksPositions { get; set; } = new(); + /// /// Gets the playlist configuration by Jellyfin playlist ID. /// diff --git a/allstarr/Program.cs b/allstarr/Program.cs index f2fe58a..ee841db 100644 --- a/allstarr/Program.cs +++ b/allstarr/Program.cs @@ -178,15 +178,37 @@ builder.Services.Configure(options => .ToList(); } + var playlistPositionsEnv = builder.Configuration.GetValue("SpotifyImport:PlaylistLocalTracksPositions"); + if (!string.IsNullOrWhiteSpace(playlistPositionsEnv) && options.PlaylistLocalTracksPositions.Count == 0) + { + options.PlaylistLocalTracksPositions = playlistPositionsEnv + .Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(pos => pos.Trim()) + .Where(pos => !string.IsNullOrEmpty(pos)) + .ToList(); + } + // Convert legacy format to new Playlists array for (int i = 0; i < options.PlaylistIds.Count; i++) { var name = i < options.PlaylistNames.Count ? options.PlaylistNames[i] : options.PlaylistIds[i]; + var position = LocalTracksPosition.First; // Default + + // Parse position if provided + if (i < options.PlaylistLocalTracksPositions.Count) + { + var posStr = options.PlaylistLocalTracksPositions[i]; + if (posStr.Equals("last", StringComparison.OrdinalIgnoreCase)) + { + position = LocalTracksPosition.Last; + } + } + options.Playlists.Add(new SpotifyPlaylistConfig { Name = name, Id = options.PlaylistIds[i], - LocalTracksPosition = LocalTracksPosition.First // Default for legacy + LocalTracksPosition = position }); } #pragma warning restore CS0618 diff --git a/docker-compose.yml b/docker-compose.yml index 3812688..c6a5a70 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,6 +82,9 @@ services: - SpotifyImport__SyncStartMinute=${SPOTIFY_IMPORT_SYNC_START_MINUTE:-15} - SpotifyImport__SyncWindowHours=${SPOTIFY_IMPORT_SYNC_WINDOW_HOURS:-2} - SpotifyImport__Playlists=${SPOTIFY_IMPORT_PLAYLISTS:-} + - SpotifyImport__PlaylistIds=${SPOTIFY_IMPORT_PLAYLIST_IDS:-} + - SpotifyImport__PlaylistNames=${SPOTIFY_IMPORT_PLAYLIST_NAMES:-} + - SpotifyImport__PlaylistLocalTracksPositions=${SPOTIFY_IMPORT_PLAYLIST_LOCAL_TRACKS_POSITIONS:-} # ===== SHARED ===== - Library__DownloadPath=/app/downloads