diff --git a/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs b/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs index fb43cb66f..771a05964 100644 --- a/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs +++ b/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs @@ -1189,10 +1189,18 @@ public class RefreshChannelDataHandler : IRequestHandler // must deserialize channel from json foreach (ExternalJsonChannel channel in maybeChannel) { - // TODO: null start time should log and throw + if (string.IsNullOrWhiteSpace(channel.StartTime)) + { + _logger.LogError( + "External json channel in file {File} has no start time; unable to refresh channel data", + path); + + throw new InvalidOperationException( + $"External json channel in file {path} has no start time"); + } DateTimeOffset startTime = DateTimeOffset.Parse( - channel.StartTime ?? string.Empty, + channel.StartTime, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime(); diff --git a/ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItemsHandler.cs b/ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItemsHandler.cs index 0cf6490a6..580558159 100644 --- a/ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItemsHandler.cs +++ b/ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItemsHandler.cs @@ -20,7 +20,10 @@ public class ReplacePlayoutAlternateScheduleItemsHandler( ReplacePlayoutAlternateScheduleItems request, CancellationToken cancellationToken) { - // TODO: validate that items is not empty + if (request.Items.Count == 0) + { + return BaseError.New("Playout alternate schedule items must not be empty"); + } try { diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index d95f60a09..c5eea25ee 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -1488,7 +1488,10 @@ public class PlayoutBuilder : IPlayoutBuilder goto default; default: - // TODO: handle this error case differently? + _logger.LogWarning( + "Unsupported playback order {PlaybackOrder}; falling back to random", + playbackOrder); + return new RandomizedMediaCollectionEnumerator(mediaItems, state); } } diff --git a/ErsatzTV.Infrastructure/Streaming/ExternalJsonPlayoutItemProvider.cs b/ErsatzTV.Infrastructure/Streaming/ExternalJsonPlayoutItemProvider.cs index 7e73234c4..28c7a216b 100644 --- a/ErsatzTV.Infrastructure/Streaming/ExternalJsonPlayoutItemProvider.cs +++ b/ErsatzTV.Infrastructure/Streaming/ExternalJsonPlayoutItemProvider.cs @@ -92,10 +92,18 @@ public class ExternalJsonPlayoutItemProvider : IExternalJsonPlayoutItemProvider // must deserialize channel from json foreach (ExternalJsonChannel channel in maybeChannel) { - // TODO: null start time should log and throw + if (string.IsNullOrWhiteSpace(channel.StartTime)) + { + _logger.LogError( + "External json channel in file {File} has no start time; unable to locate playout item", + playout.ScheduleFile); + + throw new InvalidOperationException( + $"External json channel in file {playout.ScheduleFile} has no start time"); + } DateTimeOffset startTime = DateTimeOffset.Parse( - channel.StartTime ?? string.Empty, + channel.StartTime, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime(); @@ -207,14 +215,35 @@ public class ExternalJsonPlayoutItemProvider : IExternalJsonPlayoutItemProvider .Include(pms => pms.Connections) .SelectOneAsync(pms => pms.ServerName, pms => pms.ServerName == program.ServerKey, cancellationToken); + if (maybeServer.IsNone) + { + _logger.LogWarning( + "Unable to stream remotely; no Plex server found with server name {ServerName}", + program.ServerKey); + } + foreach (PlexMediaSource server in maybeServer) { Option maybeConnection = server.Connections.SingleOrDefault(c => c.IsActive); + if (maybeConnection.IsNone) + { + _logger.LogWarning( + "Unable to stream remotely; Plex server {ServerName} has no active connection", + server.ServerName); + } + foreach (PlexConnection connection in maybeConnection) { Option maybeToken = await _plexSecretStore.GetServerAuthToken(server.ClientIdentifier); + if (maybeToken.IsNone) + { + _logger.LogWarning( + "Unable to stream remotely; Plex server {ServerName} has no auth token", + server.ServerName); + } + foreach (PlexServerAuthToken token in maybeToken) { MediaItem mediaItem = program.Type switch @@ -230,7 +259,6 @@ public class ExternalJsonPlayoutItemProvider : IExternalJsonPlayoutItemProvider } } - // TODO: log errors? return new UnableToLocatePlayoutItem(); }