Browse Source

adjust block unique constraint (#1634)

* upgrade dependencies

* allow blocks with same name in different groups

* code cleanup
pull/1636/head
Jason Dove 2 years ago committed by GitHub
parent
commit
087901d177
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      .config/dotnet-tools.json
  2. 3
      ErsatzTV.Application/Channels/Commands/CreateChannel.cs
  3. 40
      ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs
  4. 3
      ErsatzTV.Application/Channels/Commands/UpdateChannel.cs
  5. 4
      ErsatzTV.Application/Channels/Queries/GetChannelGuide.cs
  6. 16
      ErsatzTV.Application/Configuration/Commands/UpdateGeneralSettingsHandler.cs
  7. 3
      ErsatzTV.Application/Emby/Commands/UpdateEmbyLibraryPreferences.cs
  8. 3
      ErsatzTV.Application/Emby/Queries/GetEmbyPathReplacementsBySourceId.cs
  9. 4
      ErsatzTV.Application/ErsatzTV.Application.csproj
  10. 3
      ErsatzTV.Application/FFmpegProfiles/Commands/CopyFFmpegProfile.cs
  11. 3
      ErsatzTV.Application/Images/Queries/GetCachedImagePath.cs
  12. 4
      ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryById.cs
  13. 4
      ErsatzTV.Application/Jellyfin/Commands/UpdateJellyfinLibraryPreferences.cs
  14. 3
      ErsatzTV.Application/Jellyfin/Queries/GetJellyfinMediaSourceById.cs
  15. 4
      ErsatzTV.Application/Jellyfin/Queries/GetJellyfinPathReplacementsBySourceId.cs
  16. 5
      ErsatzTV.Application/Libraries/Commands/CallLibraryScannerHandler.cs
  17. 2
      ErsatzTV.Application/Libraries/Commands/CreateLocalLibraryHandler.cs
  18. 4
      ErsatzTV.Application/Libraries/Commands/CreateLocalLibraryPath.cs
  19. 2
      ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryHandler.cs
  20. 2
      ErsatzTV.Application/Libraries/Commands/MoveLocalLibraryPathHandler.cs
  21. 2
      ErsatzTV.Application/Libraries/Commands/UpdateLocalLibraryHandler.cs
  22. 3
      ErsatzTV.Application/MediaCards/ArtistCardViewModel.cs
  23. 3
      ErsatzTV.Application/MediaCards/ImageCardViewModel.cs
  24. 3
      ErsatzTV.Application/MediaCards/MovieCardViewModel.cs
  25. 3
      ErsatzTV.Application/MediaCards/MusicVideoCardViewModel.cs
  26. 3
      ErsatzTV.Application/MediaCards/OtherVideoCardViewModel.cs
  27. 3
      ErsatzTV.Application/MediaCards/Queries/GetMusicVideoCards.cs
  28. 4
      ErsatzTV.Application/MediaCards/Queries/GetTelevisionEpisodeCards.cs
  29. 4
      ErsatzTV.Application/MediaCards/Queries/GetTelevisionSeasonCards.cs
  30. 3
      ErsatzTV.Application/MediaCards/SongCardViewModel.cs
  31. 3
      ErsatzTV.Application/MediaCards/TelevisionEpisodeCardViewModel.cs
  32. 3
      ErsatzTV.Application/MediaCards/TelevisionSeasonCardViewModel.cs
  33. 3
      ErsatzTV.Application/MediaCards/TelevisionShowCardViewModel.cs
  34. 3
      ErsatzTV.Application/MediaCollections/Commands/AddArtistToCollection.cs
  35. 2
      ErsatzTV.Application/MediaCollections/Commands/AddArtistToCollectionHandler.cs
  36. 4
      ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs
  37. 3
      ErsatzTV.Application/MediaCollections/Commands/AddItemsToCollection.cs
  38. 2
      ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs
  39. 3
      ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollection.cs
  40. 4
      ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs
  41. 3
      ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollection.cs
  42. 4
      ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs
  43. 2
      ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs
  44. 2
      ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs
  45. 3
      ErsatzTV.Application/MediaCollections/Commands/AddSongToCollection.cs
  46. 2
      ErsatzTV.Application/MediaCollections/Commands/AddSongToCollectionHandler.cs
  47. 4
      ErsatzTV.Application/MediaCollections/Commands/CreateMultiCollection.cs
  48. 3
      ErsatzTV.Application/MediaCollections/Commands/CreateSmartCollection.cs
  49. 2
      ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs
  50. 2
      ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs
  51. 3
      ErsatzTV.Application/MediaCollections/Commands/UpdateCollection.cs
  52. 3
      ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionCustomOrder.cs
  53. 2
      ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionCustomOrderHandler.cs
  54. 2
      ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionHandler.cs
  55. 3
      ErsatzTV.Application/MediaCollections/Commands/UpdateMultiCollection.cs
  56. 4
      ErsatzTV.Application/MediaCollections/Commands/UpdateMultiCollectionHandler.cs
  57. 2
      ErsatzTV.Application/MediaCollections/Commands/UpdateSmartCollectionHandler.cs
  58. 7
      ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs
  59. 2
      ErsatzTV.Application/Playouts/Commands/CreateExternalJsonPlayoutHandler.cs
  60. 4
      ErsatzTV.Application/Playouts/Commands/CreateFloodPlayoutHandler.cs
  61. 4
      ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItems.cs
  62. 8
      ErsatzTV.Application/Playouts/Commands/UpdateExternalJsonPlayoutHandler.cs
  63. 4
      ErsatzTV.Application/Playouts/Commands/UpdatePlayout.cs
  64. 4
      ErsatzTV.Application/Playouts/Queries/GetFuturePlayoutItemsById.cs
  65. 3
      ErsatzTV.Application/Plex/Commands/UpdatePlexLibraryPreferences.cs
  66. 3
      ErsatzTV.Application/Plex/Commands/UpdatePlexPathReplacements.cs
  67. 4
      ErsatzTV.Application/Plex/Queries/GetPlexConnectionParameters.cs
  68. 3
      ErsatzTV.Application/Plex/Queries/GetPlexPathReplacementsBySourceId.cs
  69. 2
      ErsatzTV.Application/ProgramSchedules/Commands/AddProgramScheduleItemHandler.cs
  70. 4
      ErsatzTV.Application/ProgramSchedules/Commands/CopyProgramSchedule.cs
  71. 3
      ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItems.cs
  72. 3
      ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs
  73. 2
      ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs
  74. 4
      ErsatzTV.Application/Scheduling/Commands/CreateBlockGroupHandler.cs
  75. 29
      ErsatzTV.Application/Scheduling/Commands/CreateBlockHandler.cs
  76. 2
      ErsatzTV.Application/Scheduling/Commands/ReplacePlayoutTemplateItemsHandler.cs
  77. 3
      ErsatzTV.Application/Scheduling/Queries/GetTemplateItemsHandler.cs
  78. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexArtists.cs
  79. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexEpisodes.cs
  80. 3
      ErsatzTV.Application/Search/Queries/QuerySearchIndexImages.cs
  81. 3
      ErsatzTV.Application/Search/Queries/QuerySearchIndexMovies.cs
  82. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexMusicVideos.cs
  83. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexOtherVideos.cs
  84. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexSeasons.cs
  85. 4
      ErsatzTV.Application/Search/Queries/QuerySearchIndexShows.cs
  86. 3
      ErsatzTV.Application/Search/Queries/QuerySearchIndexSongs.cs
  87. 2
      ErsatzTV.Application/Streaming/HlsSessionWorker.cs
  88. 9
      ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs
  89. 3
      ErsatzTV.Application/Streaming/Queries/FFmpegProcessRequest.cs
  90. 4
      ErsatzTV.Application/Streaming/Queries/GetConcatPlaylistByChannelNumber.cs
  91. 4
      ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumber.cs
  92. 4
      ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs
  93. 2
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  94. 6
      ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs
  95. 3
      ErsatzTV.Application/Watermarks/Commands/CopyWatermark.cs
  96. 8
      ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
  97. 2
      ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs
  98. 68
      ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs
  99. 8
      ErsatzTV.Core/ErsatzTV.Core.csproj
  100. 43
      ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs
  101. Some files were not shown because too many files have changed in this diff Show More

2
.config/dotnet-tools.json

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"jetbrains.resharper.globaltools": {
"version": "2023.2.0",
"version": "2023.3.3",
"commands": [
"jb"
]

3
ErsatzTV.Application/Channels/Commands/CreateChannel.cs

@ -3,8 +3,7 @@ using ErsatzTV.Core.Domain; @@ -3,8 +3,7 @@ using ErsatzTV.Core.Domain;
namespace ErsatzTV.Application.Channels;
public record CreateChannel
(
public record CreateChannel(
string Name,
string Number,
string Group,

40
ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs

@ -22,9 +22,9 @@ namespace ErsatzTV.Application.Channels; @@ -22,9 +22,9 @@ namespace ErsatzTV.Application.Channels;
public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ILocalFileSystem _localFileSystem;
private readonly IConfigElementRepository _configElementRepository;
private readonly ILogger<RefreshChannelDataHandler> _logger;
private readonly RecyclableMemoryStreamManager _recyclableMemoryStreamManager;
@ -367,7 +367,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -367,7 +367,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
item,
start,
stop,
hasCustomTitle: false,
false,
templateContext,
movieTemplate,
episodeTemplate,
@ -491,9 +491,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -491,9 +491,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
ProgrammeStart = start,
ProgrammeStop = stop,
ChannelNumber = request.ChannelNumber,
request.ChannelNumber,
HasCustomTitle = hasCustomTitle,
CustomTitle = displayItem.CustomTitle,
displayItem.CustomTitle,
MovieTitle = title,
MovieHasPlot = !string.IsNullOrWhiteSpace(metadata.Plot),
MoviePlot = metadata.Plot,
@ -546,9 +546,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -546,9 +546,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
ProgrammeStart = start,
ProgrammeStop = stop,
ChannelNumber = request.ChannelNumber,
request.ChannelNumber,
HasCustomTitle = hasCustomTitle,
CustomTitle = displayItem.CustomTitle,
displayItem.CustomTitle,
ShowTitle = title,
EpisodeHasTitle = !string.IsNullOrWhiteSpace(subtitle),
EpisodeTitle = subtitle,
@ -560,7 +560,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -560,7 +560,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
EpisodeHasArtwork = !string.IsNullOrWhiteSpace(artworkPath),
EpisodeArtworkUrl = artworkPath,
SeasonNumber = templateEpisode.Season?.SeasonNumber ?? 0,
EpisodeNumber = metadata.EpisodeNumber,
metadata.EpisodeNumber,
ShowHasContentRating = !string.IsNullOrWhiteSpace(showMetadata.ContentRating),
ShowContentRating = showMetadata.ContentRating,
ShowGuids = showMetadata.Guids.Map(g => g.Guid),
@ -606,9 +606,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -606,9 +606,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
ProgrammeStart = start,
ProgrammeStop = stop,
ChannelNumber = request.ChannelNumber,
request.ChannelNumber,
HasCustomTitle = hasCustomTitle,
CustomTitle = displayItem.CustomTitle,
displayItem.CustomTitle,
ArtistTitle = title,
MusicVideoTitle = subtitle,
MusicVideoHasPlot = !string.IsNullOrWhiteSpace(metadata.Plot),
@ -663,9 +663,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -663,9 +663,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
ProgrammeStart = start,
ProgrammeStop = stop,
ChannelNumber = request.ChannelNumber,
request.ChannelNumber,
HasCustomTitle = hasCustomTitle,
CustomTitle = displayItem.CustomTitle,
displayItem.CustomTitle,
SongTitle = subtitle,
SongArtists = metadata.Artists,
SongAlbumArtists = metadata.AlbumArtists,
@ -682,7 +682,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -682,7 +682,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
SongAlbum = metadata.Album,
SongHasReleaseDate = metadata.ReleaseDate.HasValue,
SongReleaseDate = metadata.ReleaseDate,
SongStudios = metadata.Studios.Map(s => s.Name),
SongStudios = metadata.Studios.Map(s => s.Name)
};
var scriptObject = new ScriptObject();
@ -715,9 +715,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -715,9 +715,9 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
ProgrammeStart = start,
ProgrammeStop = stop,
ChannelNumber = request.ChannelNumber,
request.ChannelNumber,
HasCustomTitle = hasCustomTitle,
CustomTitle = displayItem.CustomTitle,
displayItem.CustomTitle,
OtherVideoTitle = title,
OtherVideoHasPlot = !string.IsNullOrWhiteSpace(metadata.Plot),
OtherVideoPlot = metadata.Plot,
@ -863,10 +863,12 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -863,10 +863,12 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
_ => 440
};
if (artworkPath.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || artworkPath.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
if (artworkPath.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
artworkPath.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return artworkPath;
}
if (artworkPath.StartsWith("jellyfin://", StringComparison.OrdinalIgnoreCase))
{
artworkPath = JellyfinUrl.PlaceholderProxyForArtwork(artworkPath, artworkKind, height);
@ -1077,7 +1079,8 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -1077,7 +1079,8 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
var artwork = new List<Artwork>();
if (!string.IsNullOrWhiteSpace(program.Icon))
{
artwork.Add(new Artwork
artwork.Add(
new Artwork
{
ArtworkKind = ArtworkKind.Thumbnail,
Path = program.Icon,
@ -1100,7 +1103,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -1100,7 +1103,7 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
{
EpisodeNumber = program.Episode,
Title = program.Title
},
}
],
Season = new Season
{
@ -1125,7 +1128,8 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData> @@ -1125,7 +1128,8 @@ public class RefreshChannelDataHandler : IRequestHandler<RefreshChannelData>
var artwork = new List<Artwork>();
if (!string.IsNullOrWhiteSpace(program.Icon))
{
artwork.Add(new Artwork
artwork.Add(
new Artwork
{
ArtworkKind = ArtworkKind.Poster,
Path = program.Icon,

3
ErsatzTV.Application/Channels/Commands/UpdateChannel.cs

@ -3,8 +3,7 @@ using ErsatzTV.Core.Domain; @@ -3,8 +3,7 @@ using ErsatzTV.Core.Domain;
namespace ErsatzTV.Application.Channels;
public record UpdateChannel
(
public record UpdateChannel(
int ChannelId,
string Name,
string Number,

4
ErsatzTV.Application/Channels/Queries/GetChannelGuide.cs

@ -3,5 +3,5 @@ using ErsatzTV.Core.Iptv; @@ -3,5 +3,5 @@ using ErsatzTV.Core.Iptv;
namespace ErsatzTV.Application.Channels;
public record GetChannelGuide
(string Scheme, string Host, string BaseUrl, string AccessToken) : IRequest<Either<BaseError, ChannelGuide>>;
public record GetChannelGuide(string Scheme, string Host, string BaseUrl, string AccessToken)
: IRequest<Either<BaseError, ChannelGuide>>;

16
ErsatzTV.Application/Configuration/Commands/UpdateGeneralSettingsHandler.cs

@ -26,16 +26,24 @@ public class UpdateGeneralSettingsHandler : IRequestHandler<UpdateGeneralSetting @@ -26,16 +26,24 @@ public class UpdateGeneralSettingsHandler : IRequestHandler<UpdateGeneralSetting
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevel, generalSettings.DefaultMinimumLogLevel);
_loggingLevelSwitches.DefaultLevelSwitch.MinimumLevel = generalSettings.DefaultMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelScanning, generalSettings.ScanningMinimumLogLevel);
await _configElementRepository.Upsert(
ConfigElementKey.MinimumLogLevelScanning,
generalSettings.ScanningMinimumLogLevel);
_loggingLevelSwitches.ScanningLevelSwitch.MinimumLevel = generalSettings.ScanningMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelScheduling, generalSettings.SchedulingMinimumLogLevel);
await _configElementRepository.Upsert(
ConfigElementKey.MinimumLogLevelScheduling,
generalSettings.SchedulingMinimumLogLevel);
_loggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = generalSettings.SchedulingMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelStreaming, generalSettings.StreamingMinimumLogLevel);
await _configElementRepository.Upsert(
ConfigElementKey.MinimumLogLevelStreaming,
generalSettings.StreamingMinimumLogLevel);
_loggingLevelSwitches.StreamingLevelSwitch.MinimumLevel = generalSettings.StreamingMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelHttp, generalSettings.HttpMinimumLogLevel);
await _configElementRepository.Upsert(
ConfigElementKey.MinimumLogLevelHttp,
generalSettings.HttpMinimumLogLevel);
_loggingLevelSwitches.HttpLevelSwitch.MinimumLevel = generalSettings.HttpMinimumLogLevel;
return Unit.Default;

3
ErsatzTV.Application/Emby/Commands/UpdateEmbyLibraryPreferences.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
namespace ErsatzTV.Application.Emby;
public record UpdateEmbyLibraryPreferences
(List<EmbyLibraryPreference> Preferences) : IRequest<Either<BaseError, Unit>>;
public record UpdateEmbyLibraryPreferences(List<EmbyLibraryPreference> Preferences) : IRequest<Either<BaseError, Unit>>;
public record EmbyLibraryPreference(int Id, bool ShouldSyncItems);

3
ErsatzTV.Application/Emby/Queries/GetEmbyPathReplacementsBySourceId.cs

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
namespace ErsatzTV.Application.Emby;
public record GetEmbyPathReplacementsBySourceId
(int EmbyMediaSourceId) : IRequest<List<EmbyPathReplacementViewModel>>;
public record GetEmbyPathReplacementsBySourceId(int EmbyMediaSourceId) : IRequest<List<EmbyPathReplacementViewModel>>;

4
ErsatzTV.Application/ErsatzTV.Application.csproj

@ -15,13 +15,13 @@ @@ -15,13 +15,13 @@
<PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog.Formatting.Compact.Reader" Version="3.0.0" />
<PackageReference Include="WebMarkupMin.Core" Version="2.14.0" />
<PackageReference Include="WebMarkupMin.Core" Version="2.16.0" />
<PackageReference Include="Winista.MimeDetect" Version="1.1.0" />
</ItemGroup>

3
ErsatzTV.Application/FFmpegProfiles/Commands/CopyFFmpegProfile.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.FFmpegProfiles;
public record CopyFFmpegProfile
(int FFmpegProfileId, string Name) : IRequest<Either<BaseError, FFmpegProfileViewModel>>;
public record CopyFFmpegProfile(int FFmpegProfileId, string Name) : IRequest<Either<BaseError, FFmpegProfileViewModel>>;

3
ErsatzTV.Application/Images/Queries/GetCachedImagePath.cs

@ -3,6 +3,5 @@ using ErsatzTV.Core.Domain; @@ -3,6 +3,5 @@ using ErsatzTV.Core.Domain;
namespace ErsatzTV.Application.Images;
public record GetCachedImagePath
(string FileName, ArtworkKind ArtworkKind, int? MaxHeight = null) : IRequest<
public record GetCachedImagePath(string FileName, ArtworkKind ArtworkKind, int? MaxHeight = null) : IRequest<
Either<BaseError, CachedImagePathViewModel>>;

4
ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryById.cs

@ -16,8 +16,8 @@ public record SynchronizeJellyfinLibraryByIdIfNeeded(int JellyfinLibraryId) : IS @@ -16,8 +16,8 @@ public record SynchronizeJellyfinLibraryByIdIfNeeded(int JellyfinLibraryId) : IS
public bool DeepScan => false;
}
public record ForceSynchronizeJellyfinLibraryById
(int JellyfinLibraryId, bool DeepScan) : ISynchronizeJellyfinLibraryById
public record ForceSynchronizeJellyfinLibraryById(int JellyfinLibraryId, bool DeepScan)
: ISynchronizeJellyfinLibraryById
{
public bool ForceScan => true;
}

4
ErsatzTV.Application/Jellyfin/Commands/UpdateJellyfinLibraryPreferences.cs

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
namespace ErsatzTV.Application.Jellyfin;
public record UpdateJellyfinLibraryPreferences
(List<JellyfinLibraryPreference> Preferences) : IRequest<Either<BaseError, Unit>>;
public record UpdateJellyfinLibraryPreferences(List<JellyfinLibraryPreference> Preferences)
: IRequest<Either<BaseError, Unit>>;
public record JellyfinLibraryPreference(int Id, bool ShouldSyncItems);

3
ErsatzTV.Application/Jellyfin/Queries/GetJellyfinMediaSourceById.cs

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
namespace ErsatzTV.Application.Jellyfin;
public record GetJellyfinMediaSourceById
(int JellyfinMediaSourceId) : IRequest<Option<JellyfinMediaSourceViewModel>>;
public record GetJellyfinMediaSourceById(int JellyfinMediaSourceId) : IRequest<Option<JellyfinMediaSourceViewModel>>;

4
ErsatzTV.Application/Jellyfin/Queries/GetJellyfinPathReplacementsBySourceId.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
namespace ErsatzTV.Application.Jellyfin;
public record GetJellyfinPathReplacementsBySourceId
(int JellyfinMediaSourceId) : IRequest<List<JellyfinPathReplacementViewModel>>;
public record GetJellyfinPathReplacementsBySourceId(int JellyfinMediaSourceId)
: IRequest<List<JellyfinPathReplacementViewModel>>;

5
ErsatzTV.Application/Libraries/Commands/CallLibraryScannerHandler.cs

@ -13,6 +13,7 @@ using ErsatzTV.Infrastructure.Data; @@ -13,6 +13,7 @@ using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Compact.Reader;
@ -20,6 +21,7 @@ namespace ErsatzTV.Application.Libraries; @@ -20,6 +21,7 @@ namespace ErsatzTV.Application.Libraries;
public abstract class CallLibraryScannerHandler<TRequest>
{
private readonly int _batchSize = 100;
private readonly ChannelWriter<ISearchIndexBackgroundServiceRequest> _channel;
private readonly IConfigElementRepository _configElementRepository;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
@ -27,7 +29,6 @@ public abstract class CallLibraryScannerHandler<TRequest> @@ -27,7 +29,6 @@ public abstract class CallLibraryScannerHandler<TRequest>
private readonly IRuntimeInfo _runtimeInfo;
private readonly List<int> _toReindex = [];
private readonly List<int> _toRemove = [];
private readonly int _batchSize = 100;
private string _libraryName;
protected CallLibraryScannerHandler(
@ -104,7 +105,7 @@ public abstract class CallLibraryScannerHandler<TRequest> @@ -104,7 +105,7 @@ public abstract class CallLibraryScannerHandler<TRequest>
if (logEvent.Properties.TryGetValue("SourceContext", out LogEventPropertyValue property))
{
log = log.ForContext(
Serilog.Core.Constants.SourceContextPropertyName,
Constants.SourceContextPropertyName,
property.ToString().Trim('"'));
}

2
ErsatzTV.Application/Libraries/Commands/CreateLocalLibraryHandler.cs

@ -32,7 +32,7 @@ public class CreateLocalLibraryHandler : LocalLibraryHandlerBase, @@ -32,7 +32,7 @@ public class CreateLocalLibraryHandler : LocalLibraryHandlerBase,
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, LocalLibrary> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, localLibrary => PersistLocalLibrary(dbContext, localLibrary));
return await validation.Apply(localLibrary => PersistLocalLibrary(dbContext, localLibrary));
}
private async Task<LocalLibraryViewModel> PersistLocalLibrary(

4
ErsatzTV.Application/Libraries/Commands/CreateLocalLibraryPath.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Libraries;
public record CreateLocalLibraryPath
(int LibraryId, string Path) : IRequest<Either<BaseError, LocalLibraryPathViewModel>>;
public record CreateLocalLibraryPath(int LibraryId, string Path)
: IRequest<Either<BaseError, LocalLibraryPathViewModel>>;

2
ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryHandler.cs

@ -28,7 +28,7 @@ public class DeleteLocalLibraryHandler : LocalLibraryHandlerBase, @@ -28,7 +28,7 @@ public class DeleteLocalLibraryHandler : LocalLibraryHandlerBase,
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, LocalLibrary> validation = await LocalLibraryMustExist(dbContext, request);
return await LanguageExtensions.Apply(validation, localLibrary => DoDeletion(dbContext, localLibrary));
return await validation.Apply(localLibrary => DoDeletion(dbContext, localLibrary));
}
private async Task<Unit> DoDeletion(TvContext dbContext, LocalLibrary localLibrary)

2
ErsatzTV.Application/Libraries/Commands/MoveLocalLibraryPathHandler.cs

@ -39,7 +39,7 @@ public class MoveLocalLibraryPathHandler : IRequestHandler<MoveLocalLibraryPath, @@ -39,7 +39,7 @@ public class MoveLocalLibraryPathHandler : IRequestHandler<MoveLocalLibraryPath,
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => MovePath(dbContext, parameters));
return await validation.Apply(parameters => MovePath(dbContext, parameters));
}
private async Task<Unit> MovePath(TvContext dbContext, Parameters parameters)

2
ErsatzTV.Application/Libraries/Commands/UpdateLocalLibraryHandler.cs

@ -37,7 +37,7 @@ public class UpdateLocalLibraryHandler : LocalLibraryHandlerBase, @@ -37,7 +37,7 @@ public class UpdateLocalLibraryHandler : LocalLibraryHandlerBase,
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => UpdateLocalLibrary(dbContext, parameters));
return await validation.Apply(parameters => UpdateLocalLibrary(dbContext, parameters));
}
private async Task<LocalLibraryViewModel> UpdateLocalLibrary(TvContext dbContext, Parameters parameters)

3
ErsatzTV.Application/MediaCards/ArtistCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record ArtistCardViewModel
(
public record ArtistCardViewModel(
int ArtistId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/ImageCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record ImageCardViewModel
(
public record ImageCardViewModel(
int ImageId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/MovieCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record MovieCardViewModel
(
public record MovieCardViewModel(
int MovieId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/MusicVideoCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record MusicVideoCardViewModel
(
public record MusicVideoCardViewModel(
int MusicVideoId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/OtherVideoCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record OtherVideoCardViewModel
(
public record OtherVideoCardViewModel(
int OtherVideoId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/Queries/GetMusicVideoCards.cs

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
namespace ErsatzTV.Application.MediaCards;
public record GetMusicVideoCards
(int ArtistId, int PageNumber, int PageSize) : IRequest<MusicVideoCardResultsViewModel>;
public record GetMusicVideoCards(int ArtistId, int PageNumber, int PageSize) : IRequest<MusicVideoCardResultsViewModel>;

4
ErsatzTV.Application/MediaCards/Queries/GetTelevisionEpisodeCards.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
namespace ErsatzTV.Application.MediaCards;
public record GetTelevisionEpisodeCards
(int TelevisionSeasonId, int PageNumber, int PageSize) : IRequest<TelevisionEpisodeCardResultsViewModel>;
public record GetTelevisionEpisodeCards(int TelevisionSeasonId, int PageNumber, int PageSize)
: IRequest<TelevisionEpisodeCardResultsViewModel>;

4
ErsatzTV.Application/MediaCards/Queries/GetTelevisionSeasonCards.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
namespace ErsatzTV.Application.MediaCards;
public record GetTelevisionSeasonCards
(int TelevisionShowId, int PageNumber, int PageSize) : IRequest<TelevisionSeasonCardResultsViewModel>;
public record GetTelevisionSeasonCards(int TelevisionShowId, int PageNumber, int PageSize)
: IRequest<TelevisionSeasonCardResultsViewModel>;

3
ErsatzTV.Application/MediaCards/SongCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record SongCardViewModel
(
public record SongCardViewModel(
int SongId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCards/TelevisionEpisodeCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record TelevisionEpisodeCardViewModel
(
public record TelevisionEpisodeCardViewModel(
int EpisodeId,
DateTime Aired,
string ShowTitle,

3
ErsatzTV.Application/MediaCards/TelevisionSeasonCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record TelevisionSeasonCardViewModel
(
public record TelevisionSeasonCardViewModel(
string ShowTitle,
int TelevisionSeasonId,
int TelevisionSeasonNumber,

3
ErsatzTV.Application/MediaCards/TelevisionShowCardViewModel.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCards;
public record TelevisionShowCardViewModel
(
public record TelevisionShowCardViewModel(
int TelevisionShowId,
string Title,
string Subtitle,

3
ErsatzTV.Application/MediaCollections/Commands/AddArtistToCollection.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.MediaCollections;
public record AddArtistToCollection
(int CollectionId, int ArtistId) : IRequest<Either<BaseError, Unit>>;
public record AddArtistToCollection(int CollectionId, int ArtistId) : IRequest<Either<BaseError, Unit>>;

2
ErsatzTV.Application/MediaCollections/Commands/AddArtistToCollectionHandler.cs

@ -33,7 +33,7 @@ public class AddArtistToCollectionHandler : @@ -33,7 +33,7 @@ public class AddArtistToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => ApplyAddArtistRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddArtistRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddArtistRequest(TvContext dbContext, Parameters parameters)

4
ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs

@ -33,9 +33,7 @@ public class AddEpisodeToCollectionHandler : @@ -33,9 +33,7 @@ public class AddEpisodeToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(
validation,
parameters => ApplyAddTelevisionEpisodeRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddTelevisionEpisodeRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddTelevisionEpisodeRequest(TvContext dbContext, Parameters parameters)

3
ErsatzTV.Application/MediaCollections/Commands/AddItemsToCollection.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCollections;
public record AddItemsToCollection
(
public record AddItemsToCollection(
int CollectionId,
List<int> MovieIds,
List<int> ShowIds,

2
ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs

@ -33,7 +33,7 @@ public class AddMovieToCollectionHandler : @@ -33,7 +33,7 @@ public class AddMovieToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => ApplyAddMovieRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddMovieRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddMovieRequest(TvContext dbContext, Parameters parameters)

3
ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollection.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.MediaCollections;
public record AddMusicVideoToCollection
(int CollectionId, int MusicVideoId) : IRequest<Either<BaseError, Unit>>;
public record AddMusicVideoToCollection(int CollectionId, int MusicVideoId) : IRequest<Either<BaseError, Unit>>;

4
ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs

@ -33,9 +33,7 @@ public class AddMusicVideoToCollectionHandler : @@ -33,9 +33,7 @@ public class AddMusicVideoToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(
validation,
parameters => ApplyAddMusicVideoRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddMusicVideoRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddMusicVideoRequest(TvContext dbContext, Parameters parameters)

3
ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollection.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.MediaCollections;
public record AddOtherVideoToCollection
(int CollectionId, int OtherVideoId) : IRequest<Either<BaseError, Unit>>;
public record AddOtherVideoToCollection(int CollectionId, int OtherVideoId) : IRequest<Either<BaseError, Unit>>;

4
ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs

@ -33,9 +33,7 @@ public class AddOtherVideoToCollectionHandler : @@ -33,9 +33,7 @@ public class AddOtherVideoToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(
validation,
parameters => ApplyAddOtherVideoRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddOtherVideoRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddOtherVideoRequest(TvContext dbContext, Parameters parameters)

2
ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs

@ -33,7 +33,7 @@ public class AddSeasonToCollectionHandler : @@ -33,7 +33,7 @@ public class AddSeasonToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => ApplyAddSeasonRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddSeasonRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddSeasonRequest(TvContext dbContext, Parameters parameters)

2
ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs

@ -33,7 +33,7 @@ public class AddShowToCollectionHandler : @@ -33,7 +33,7 @@ public class AddShowToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => ApplyAddShowRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddShowRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddShowRequest(TvContext dbContext, Parameters parameters)

3
ErsatzTV.Application/MediaCollections/Commands/AddSongToCollection.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.MediaCollections;
public record AddSongToCollection
(int CollectionId, int SongId) : IRequest<Either<BaseError, Unit>>;
public record AddSongToCollection(int CollectionId, int SongId) : IRequest<Either<BaseError, Unit>>;

2
ErsatzTV.Application/MediaCollections/Commands/AddSongToCollectionHandler.cs

@ -33,7 +33,7 @@ public class AddSongToCollectionHandler : @@ -33,7 +33,7 @@ public class AddSongToCollectionHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, parameters => ApplyAddSongRequest(dbContext, parameters));
return await validation.Apply(parameters => ApplyAddSongRequest(dbContext, parameters));
}
private async Task<Unit> ApplyAddSongRequest(TvContext dbContext, Parameters parameters)

4
ErsatzTV.Application/MediaCollections/Commands/CreateMultiCollection.cs

@ -9,5 +9,5 @@ public record CreateMultiCollectionItem( @@ -9,5 +9,5 @@ public record CreateMultiCollectionItem(
bool ScheduleAsGroup,
PlaybackOrder PlaybackOrder);
public record CreateMultiCollection
(string Name, List<CreateMultiCollectionItem> Items) : IRequest<Either<BaseError, MultiCollectionViewModel>>;
public record CreateMultiCollection(string Name, List<CreateMultiCollectionItem> Items)
: IRequest<Either<BaseError, MultiCollectionViewModel>>;

3
ErsatzTV.Application/MediaCollections/Commands/CreateSmartCollection.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.MediaCollections;
public record CreateSmartCollection
(string Query, string Name) : IRequest<Either<BaseError, SmartCollectionViewModel>>;
public record CreateSmartCollection(string Query, string Name) : IRequest<Either<BaseError, SmartCollectionViewModel>>;

2
ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs

@ -44,7 +44,7 @@ public class DeleteTraktListHandler : TraktCommandBase, IRequestHandler<DeleteTr @@ -44,7 +44,7 @@ public class DeleteTraktListHandler : TraktCommandBase, IRequestHandler<DeleteTr
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, TraktList> validation = await TraktListMustExist(dbContext, request.TraktListId);
return await LanguageExtensions.Apply(validation, c => DoDeletion(dbContext, c));
return await validation.Apply(c => DoDeletion(dbContext, c));
}
finally
{

2
ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs

@ -32,7 +32,7 @@ public class RemoveItemsFromCollectionHandler : IRequestHandler<RemoveItemsFromC @@ -32,7 +32,7 @@ public class RemoveItemsFromCollectionHandler : IRequestHandler<RemoveItemsFromC
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Collection> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, c => ApplyRemoveItemsRequest(dbContext, request, c));
return await validation.Apply(c => ApplyRemoveItemsRequest(dbContext, request, c));
}
private async Task<Unit> ApplyRemoveItemsRequest(

3
ErsatzTV.Application/MediaCollections/Commands/UpdateCollection.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCollections;
public record UpdateCollection
(int CollectionId, string Name) : IRequest<Either<BaseError, Unit>>
public record UpdateCollection(int CollectionId, string Name) : IRequest<Either<BaseError, Unit>>
{
public Option<bool> UseCustomPlaybackOrder { get; set; } = None;
}

3
ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionCustomOrder.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.MediaCollections;
public record UpdateCollectionCustomOrder
(
public record UpdateCollectionCustomOrder(
int CollectionId,
List<MediaItemCustomOrder> MediaItemCustomOrders) : IRequest<Either<BaseError, Unit>>;

2
ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionCustomOrderHandler.cs

@ -32,7 +32,7 @@ public class UpdateCollectionCustomOrderHandler : IRequestHandler<UpdateCollecti @@ -32,7 +32,7 @@ public class UpdateCollectionCustomOrderHandler : IRequestHandler<UpdateCollecti
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Collection> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, c => ApplyUpdateRequest(dbContext, c, request));
return await validation.Apply(c => ApplyUpdateRequest(dbContext, c, request));
}
private async Task<Unit> ApplyUpdateRequest(

2
ErsatzTV.Application/MediaCollections/Commands/UpdateCollectionHandler.cs

@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections; @@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections;
public class UpdateCollectionHandler : IRequestHandler<UpdateCollection, Either<BaseError, Unit>>
{
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
private readonly ISearchTargets _searchTargets;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly ISearchTargets _searchTargets;
public UpdateCollectionHandler(
IDbContextFactory<TvContext> dbContextFactory,

3
ErsatzTV.Application/MediaCollections/Commands/UpdateMultiCollection.cs

@ -9,8 +9,7 @@ public record UpdateMultiCollectionItem( @@ -9,8 +9,7 @@ public record UpdateMultiCollectionItem(
bool ScheduleAsGroup,
PlaybackOrder PlaybackOrder);
public record UpdateMultiCollection
(
public record UpdateMultiCollection(
int MultiCollectionId,
string Name,
List<UpdateMultiCollectionItem> Items) : IRequest<Either<BaseError, Unit>>;

4
ErsatzTV.Application/MediaCollections/Commands/UpdateMultiCollectionHandler.cs

@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections; @@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections;
public class UpdateMultiCollectionHandler : IRequestHandler<UpdateMultiCollection, Either<BaseError, Unit>>
{
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
private readonly ISearchTargets _searchTargets;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly ISearchTargets _searchTargets;
public UpdateMultiCollectionHandler(
IDbContextFactory<TvContext> dbContextFactory,
@ -36,7 +36,7 @@ public class UpdateMultiCollectionHandler : IRequestHandler<UpdateMultiCollectio @@ -36,7 +36,7 @@ public class UpdateMultiCollectionHandler : IRequestHandler<UpdateMultiCollectio
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, MultiCollection> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, c => ApplyUpdateRequest(dbContext, c, request));
return await validation.Apply(c => ApplyUpdateRequest(dbContext, c, request));
}
private async Task<Unit> ApplyUpdateRequest(TvContext dbContext, MultiCollection c, UpdateMultiCollection request)

2
ErsatzTV.Application/MediaCollections/Commands/UpdateSmartCollectionHandler.cs

@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections; @@ -14,9 +14,9 @@ namespace ErsatzTV.Application.MediaCollections;
public class UpdateSmartCollectionHandler : IRequestHandler<UpdateSmartCollection, Either<BaseError, Unit>>
{
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
private readonly ISearchTargets _searchTargets;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly ISearchTargets _searchTargets;
public UpdateSmartCollectionHandler(
IDbContextFactory<TvContext> dbContextFactory,

7
ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs

@ -17,13 +17,13 @@ namespace ErsatzTV.Application.Playouts; @@ -17,13 +17,13 @@ namespace ErsatzTV.Application.Playouts;
public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseError, Unit>>
{
private readonly IBlockPlayoutBuilder _blockPlayoutBuilder;
private readonly IClient _client;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly IEntityLocker _entityLocker;
private readonly IExternalJsonPlayoutBuilder _externalJsonPlayoutBuilder;
private readonly IFFmpegSegmenterService _ffmpegSegmenterService;
private readonly IPlayoutBuilder _playoutBuilder;
private readonly IBlockPlayoutBuilder _blockPlayoutBuilder;
private readonly IExternalJsonPlayoutBuilder _externalJsonPlayoutBuilder;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
public BuildPlayoutHandler(
@ -100,7 +100,8 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro @@ -100,7 +100,8 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
foreach (string channelNumber in maybeChannelNumber)
{
string fileName = Path.Combine(FileSystemLayout.ChannelGuideCacheFolder, $"{channelNumber}.xml");
if (hasChanges || !File.Exists(fileName) || playout.ProgramSchedulePlayoutType is ProgramSchedulePlayoutType.ExternalJson)
if (hasChanges || !File.Exists(fileName) ||
playout.ProgramSchedulePlayoutType is ProgramSchedulePlayoutType.ExternalJson)
{
await _workerChannel.WriteAsync(new RefreshChannelData(channelNumber), cancellationToken);
}

2
ErsatzTV.Application/Playouts/Commands/CreateExternalJsonPlayoutHandler.cs

@ -14,9 +14,9 @@ namespace ErsatzTV.Application.Playouts; @@ -14,9 +14,9 @@ namespace ErsatzTV.Application.Playouts;
public class CreateExternalJsonPlayoutHandler
: IRequestHandler<CreateExternalJsonPlayout, Either<BaseError, CreatePlayoutResponse>>
{
private readonly ILocalFileSystem _localFileSystem;
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ILocalFileSystem _localFileSystem;
public CreateExternalJsonPlayoutHandler(
ILocalFileSystem localFileSystem,

4
ErsatzTV.Application/Playouts/Commands/CreateFloodPlayoutHandler.cs

@ -41,7 +41,9 @@ public class CreateFloodPlayoutHandler : IRequestHandler<CreateFloodPlayout, Eit @@ -41,7 +41,9 @@ public class CreateFloodPlayoutHandler : IRequestHandler<CreateFloodPlayout, Eit
return new CreatePlayoutResponse(playout.Id);
}
private static async Task<Validation<BaseError, Playout>> Validate(TvContext dbContext, CreateFloodPlayout request) =>
private static async Task<Validation<BaseError, Playout>> Validate(
TvContext dbContext,
CreateFloodPlayout request) =>
(await ValidateChannel(dbContext, request), await ValidateProgramSchedule(dbContext, request),
ValidatePlayoutType(request))
.Apply(

4
ErsatzTV.Application/Playouts/Commands/ReplacePlayoutAlternateScheduleItems.cs

@ -2,5 +2,5 @@ using ErsatzTV.Core; @@ -2,5 +2,5 @@ using ErsatzTV.Core;
namespace ErsatzTV.Application.Playouts;
public record ReplacePlayoutAlternateScheduleItems
(int PlayoutId, List<ReplacePlayoutAlternateSchedule> Items) : IRequest<Either<BaseError, Unit>>;
public record ReplacePlayoutAlternateScheduleItems(int PlayoutId, List<ReplacePlayoutAlternateSchedule> Items)
: IRequest<Either<BaseError, Unit>>;

8
ErsatzTV.Application/Playouts/Commands/UpdateExternalJsonPlayoutHandler.cs

@ -8,7 +8,9 @@ using Microsoft.EntityFrameworkCore; @@ -8,7 +8,9 @@ using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.Playouts;
public class UpdateExternalJsonPlayoutHandler : IRequestHandler<UpdateExternalJsonPlayout, Either<BaseError, PlayoutNameViewModel>>
public class
UpdateExternalJsonPlayoutHandler : IRequestHandler<UpdateExternalJsonPlayout,
Either<BaseError, PlayoutNameViewModel>>
{
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
@ -52,7 +54,9 @@ public class UpdateExternalJsonPlayoutHandler : IRequestHandler<UpdateExternalJs @@ -52,7 +54,9 @@ public class UpdateExternalJsonPlayoutHandler : IRequestHandler<UpdateExternalJs
Optional(playout.DailyRebuildTime));
}
private static Task<Validation<BaseError, Playout>> Validate(TvContext dbContext, UpdateExternalJsonPlayout request) =>
private static Task<Validation<BaseError, Playout>> Validate(
TvContext dbContext,
UpdateExternalJsonPlayout request) =>
PlayoutMustExist(dbContext, request);
private static Task<Validation<BaseError, Playout>> PlayoutMustExist(

4
ErsatzTV.Application/Playouts/Commands/UpdatePlayout.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Playouts;
public record UpdatePlayout
(int PlayoutId, Option<TimeSpan> DailyRebuildTime) : IRequest<Either<BaseError, PlayoutNameViewModel>>;
public record UpdatePlayout(int PlayoutId, Option<TimeSpan> DailyRebuildTime)
: IRequest<Either<BaseError, PlayoutNameViewModel>>;

4
ErsatzTV.Application/Playouts/Queries/GetFuturePlayoutItemsById.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
namespace ErsatzTV.Application.Playouts;
public record GetFuturePlayoutItemsById
(int PlayoutId, bool ShowFiller, int PageNum, int PageSize) : IRequest<PagedPlayoutItemsViewModel>;
public record GetFuturePlayoutItemsById(int PlayoutId, bool ShowFiller, int PageNum, int PageSize)
: IRequest<PagedPlayoutItemsViewModel>;

3
ErsatzTV.Application/Plex/Commands/UpdatePlexLibraryPreferences.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
namespace ErsatzTV.Application.Plex;
public record UpdatePlexLibraryPreferences
(List<PlexLibraryPreference> Preferences) : IRequest<Either<BaseError, Unit>>;
public record UpdatePlexLibraryPreferences(List<PlexLibraryPreference> Preferences) : IRequest<Either<BaseError, Unit>>;
public record PlexLibraryPreference(int Id, bool ShouldSyncItems);

3
ErsatzTV.Application/Plex/Commands/UpdatePlexPathReplacements.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.Plex;
public record UpdatePlexPathReplacements
(
public record UpdatePlexPathReplacements(
int PlexMediaSourceId,
List<PlexPathReplacementItem> PathReplacements) : IRequest<Either<BaseError, Unit>>;

4
ErsatzTV.Application/Plex/Queries/GetPlexConnectionParameters.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Plex;
public record GetPlexConnectionParameters
(int PlexMediaSourceId) : IRequest<Either<BaseError, PlexConnectionParametersViewModel>>;
public record GetPlexConnectionParameters(int PlexMediaSourceId)
: IRequest<Either<BaseError, PlexConnectionParametersViewModel>>;

3
ErsatzTV.Application/Plex/Queries/GetPlexPathReplacementsBySourceId.cs

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
namespace ErsatzTV.Application.Plex;
public record GetPlexPathReplacementsBySourceId
(int PlexMediaSourceId) : IRequest<List<PlexPathReplacementViewModel>>;
public record GetPlexPathReplacementsBySourceId(int PlexMediaSourceId) : IRequest<List<PlexPathReplacementViewModel>>;

2
ErsatzTV.Application/ProgramSchedules/Commands/AddProgramScheduleItemHandler.cs

@ -29,7 +29,7 @@ public class AddProgramScheduleItemHandler : ProgramScheduleItemCommandBase, @@ -29,7 +29,7 @@ public class AddProgramScheduleItemHandler : ProgramScheduleItemCommandBase,
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, ProgramSchedule> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, ps => PersistItem(dbContext, request, ps));
return await validation.Apply(ps => PersistItem(dbContext, request, ps));
}
private async Task<ProgramScheduleItemViewModel> PersistItem(

4
ErsatzTV.Application/ProgramSchedules/Commands/CopyProgramSchedule.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.ProgramSchedules;
public record CopyProgramSchedule
(int ProgramScheduleId, string Name) : IRequest<Either<BaseError, ProgramScheduleViewModel>>;
public record CopyProgramSchedule(int ProgramScheduleId, string Name)
: IRequest<Either<BaseError, ProgramScheduleViewModel>>;

3
ErsatzTV.Application/ProgramSchedules/Commands/ReplaceProgramScheduleItems.cs

@ -32,6 +32,5 @@ public record ReplaceProgramScheduleItem( @@ -32,6 +32,5 @@ public record ReplaceProgramScheduleItem(
string PreferredSubtitleLanguageCode,
ChannelSubtitleMode? SubtitleMode) : IProgramScheduleItemRequest;
public record ReplaceProgramScheduleItems
(int ProgramScheduleId, List<ReplaceProgramScheduleItem> Items) : IRequest<
public record ReplaceProgramScheduleItems(int ProgramScheduleId, List<ReplaceProgramScheduleItem> Items) : IRequest<
Either<BaseError, IEnumerable<ProgramScheduleItemViewModel>>>;

3
ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.ProgramSchedules;
public record UpdateProgramSchedule
(
public record UpdateProgramSchedule(
int ProgramScheduleId,
string Name,
bool KeepMultiPartEpisodesTogether,

2
ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs

@ -29,7 +29,7 @@ public class UpdateProgramScheduleHandler : @@ -29,7 +29,7 @@ public class UpdateProgramScheduleHandler :
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, ProgramSchedule> validation = await Validate(dbContext, request);
return await LanguageExtensions.Apply(validation, ps => ApplyUpdateRequest(dbContext, ps, request));
return await validation.Apply(ps => ApplyUpdateRequest(dbContext, ps, request));
}
private async Task<UpdateProgramScheduleResult> ApplyUpdateRequest(

4
ErsatzTV.Application/Scheduling/Commands/CreateBlockGroupHandler.cs

@ -8,7 +8,9 @@ namespace ErsatzTV.Application.Scheduling; @@ -8,7 +8,9 @@ namespace ErsatzTV.Application.Scheduling;
public class CreateBlockGroupHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<CreateBlockGroup, Either<BaseError, BlockGroupViewModel>>
{
public async Task<Either<BaseError, BlockGroupViewModel>> Handle(CreateBlockGroup request, CancellationToken cancellationToken)
public async Task<Either<BaseError, BlockGroupViewModel>> Handle(
CreateBlockGroup request,
CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, BlockGroup> validation = await Validate(request);

29
ErsatzTV.Application/Scheduling/Commands/CreateBlockHandler.cs

@ -13,7 +13,7 @@ public class CreateBlockHandler(IDbContextFactory<TvContext> dbContextFactory) @@ -13,7 +13,7 @@ public class CreateBlockHandler(IDbContextFactory<TvContext> dbContextFactory)
CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Block> validation = await Validate(request);
Validation<BaseError, Block> validation = await Validate(dbContext, request);
return await validation.Apply(profile => PersistBlock(dbContext, profile));
}
@ -24,17 +24,30 @@ public class CreateBlockHandler(IDbContextFactory<TvContext> dbContextFactory) @@ -24,17 +24,30 @@ public class CreateBlockHandler(IDbContextFactory<TvContext> dbContextFactory)
return Mapper.ProjectToViewModel(block);
}
private static Task<Validation<BaseError, Block>> Validate(CreateBlock request) =>
Task.FromResult(
ValidateName(request).Map(
private static async Task<Validation<BaseError, Block>> Validate(TvContext dbContext, CreateBlock request) =>
await ValidateBlockName(dbContext, request).MapT(
name => new Block
{
BlockGroupId = request.BlockGroupId,
Name = name,
Minutes = 30
}));
});
private static Validation<BaseError, string> ValidateName(CreateBlock createBlock) =>
createBlock.NotEmpty(x => x.Name)
.Bind(_ => createBlock.NotLongerThan(50)(x => x.Name));
private static async Task<Validation<BaseError, string>> ValidateBlockName(
TvContext dbContext,
CreateBlock request)
{
if (request.Name.Length > 50)
{
return BaseError.New($"Block name \"{request.Name}\" is invalid");
}
Option<Block> maybeExisting = await dbContext.Blocks
.FirstOrDefaultAsync(r => r.BlockGroupId == request.BlockGroupId && r.Name == request.Name)
.Map(Optional);
return maybeExisting.IsSome
? BaseError.New($"A block named \"{request.Name}\" already exists in that block group")
: request.Name;
}
}

2
ErsatzTV.Application/Scheduling/Commands/ReplacePlayoutTemplateItemsHandler.cs

@ -42,7 +42,7 @@ public class ReplacePlayoutTemplateItemsHandler( @@ -42,7 +42,7 @@ public class ReplacePlayoutTemplateItemsHandler(
playout.Templates.Remove(remove);
}
var now = DateTime.UtcNow;
DateTime now = DateTime.UtcNow;
foreach (ReplacePlayoutTemplate add in toAdd)
{

3
ErsatzTV.Application/Scheduling/Queries/GetTemplateItemsHandler.cs

@ -3,7 +3,8 @@ using Microsoft.EntityFrameworkCore; @@ -3,7 +3,8 @@ using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.Scheduling;
public class GetTemplateItemsHandler(IDbContextFactory<TvContext> dbContextFactory) : IRequestHandler<GetTemplateItems, List<TemplateItemViewModel>>
public class GetTemplateItemsHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<GetTemplateItems, List<TemplateItemViewModel>>
{
public async Task<List<TemplateItemViewModel>> Handle(GetTemplateItems request, CancellationToken cancellationToken)
{

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexArtists.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexArtists
(string Query, int PageNumber, int PageSize) : IRequest<ArtistCardResultsViewModel>;
public record QuerySearchIndexArtists(string Query, int PageNumber, int PageSize)
: IRequest<ArtistCardResultsViewModel>;

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexEpisodes.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexEpisodes
(string Query, int PageNumber, int PageSize) : IRequest<TelevisionEpisodeCardResultsViewModel>;
public record QuerySearchIndexEpisodes(string Query, int PageNumber, int PageSize)
: IRequest<TelevisionEpisodeCardResultsViewModel>;

3
ErsatzTV.Application/Search/Queries/QuerySearchIndexImages.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexImages
(string Query, int PageNumber, int PageSize) : IRequest<ImageCardResultsViewModel>;
public record QuerySearchIndexImages(string Query, int PageNumber, int PageSize) : IRequest<ImageCardResultsViewModel>;

3
ErsatzTV.Application/Search/Queries/QuerySearchIndexMovies.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexMovies
(string Query, int PageNumber, int PageSize) : IRequest<MovieCardResultsViewModel>;
public record QuerySearchIndexMovies(string Query, int PageNumber, int PageSize) : IRequest<MovieCardResultsViewModel>;

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexMusicVideos.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexMusicVideos
(string Query, int PageNumber, int PageSize) : IRequest<MusicVideoCardResultsViewModel>;
public record QuerySearchIndexMusicVideos(string Query, int PageNumber, int PageSize)
: IRequest<MusicVideoCardResultsViewModel>;

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexOtherVideos.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexOtherVideos
(string Query, int PageNumber, int PageSize) : IRequest<OtherVideoCardResultsViewModel>;
public record QuerySearchIndexOtherVideos(string Query, int PageNumber, int PageSize)
: IRequest<OtherVideoCardResultsViewModel>;

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexSeasons.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexSeasons
(string Query, int PageNumber, int PageSize) : IRequest<TelevisionSeasonCardResultsViewModel>;
public record QuerySearchIndexSeasons(string Query, int PageNumber, int PageSize)
: IRequest<TelevisionSeasonCardResultsViewModel>;

4
ErsatzTV.Application/Search/Queries/QuerySearchIndexShows.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexShows
(string Query, int PageNumber, int PageSize) : IRequest<TelevisionShowCardResultsViewModel>;
public record QuerySearchIndexShows(string Query, int PageNumber, int PageSize)
: IRequest<TelevisionShowCardResultsViewModel>;

3
ErsatzTV.Application/Search/Queries/QuerySearchIndexSongs.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.Search;
public record QuerySearchIndexSongs
(string Query, int PageNumber, int PageSize) : IRequest<SongCardResultsViewModel>;
public record QuerySearchIndexSongs(string Query, int PageNumber, int PageSize) : IRequest<SongCardResultsViewModel>;

2
ErsatzTV.Application/Streaming/HlsSessionWorker.cs

@ -30,6 +30,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -30,6 +30,7 @@ public class HlsSessionWorker : IHlsSessionWorker
private readonly IMediator _mediator;
private readonly object _sync = new();
private readonly Option<int> _targetFramerate;
private CancellationTokenSource _cancellationTokenSource;
private string _channelNumber;
private bool _disposedValue;
private bool _hasWrittenSegments;
@ -39,7 +40,6 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -39,7 +40,6 @@ public class HlsSessionWorker : IHlsSessionWorker
private HlsSessionState _state;
private Timer _timer;
private DateTimeOffset _transcodedUntil;
private CancellationTokenSource _cancellationTokenSource;
public HlsSessionWorker(
IServiceScopeFactory serviceScopeFactory,

9
ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs

@ -19,6 +19,7 @@ namespace ErsatzTV.Application.Streaming; @@ -19,6 +19,7 @@ namespace ErsatzTV.Application.Streaming;
public class HlsSessionWorkerV2 : IHlsSessionWorker
{
private static readonly SemaphoreSlim Slim = new(1, 1);
//private static int _workAheadCount;
private readonly IConfigElementRepository _configElementRepository;
private readonly string _host;
@ -33,11 +34,11 @@ public class HlsSessionWorkerV2 : IHlsSessionWorker @@ -33,11 +34,11 @@ public class HlsSessionWorkerV2 : IHlsSessionWorker
private bool _disposedValue;
private bool _hasWrittenSegments;
private DateTimeOffset _lastAccess;
private Option<PlayoutItemProcessModel> _lastProcessModel;
private IServiceScope _serviceScope;
private HlsSessionState _state;
private Timer _timer;
private DateTimeOffset _transcodedUntil;
private Option<PlayoutItemProcessModel> _lastProcessModel;
public HlsSessionWorkerV2(
IServiceScopeFactory serviceScopeFactory,
@ -90,10 +91,8 @@ public class HlsSessionWorkerV2 : IHlsSessionWorker @@ -90,10 +91,8 @@ public class HlsSessionWorkerV2 : IHlsSessionWorker
public Task<Option<TrimPlaylistResult>> TrimPlaylist(
DateTimeOffset filterBefore,
CancellationToken cancellationToken)
{
return Task.FromResult(Option<TrimPlaylistResult>.None);
}
CancellationToken cancellationToken) =>
Task.FromResult(Option<TrimPlaylistResult>.None);
public void PlayoutUpdated() => _state = HlsSessionState.PlayoutUpdated;

3
ErsatzTV.Application/Streaming/Queries/FFmpegProcessRequest.cs

@ -2,8 +2,7 @@ @@ -2,8 +2,7 @@
namespace ErsatzTV.Application.Streaming;
public record FFmpegProcessRequest
(
public record FFmpegProcessRequest(
string ChannelNumber,
string Mode,
DateTimeOffset Now,

4
ErsatzTV.Application/Streaming/Queries/GetConcatPlaylistByChannelNumber.cs

@ -3,5 +3,5 @@ using ErsatzTV.Core.FFmpeg; @@ -3,5 +3,5 @@ using ErsatzTV.Core.FFmpeg;
namespace ErsatzTV.Application.Streaming;
public record GetConcatPlaylistByChannelNumber
(string Scheme, string Host, string ChannelNumber, string Mode) : IRequest<Either<BaseError, ConcatPlaylist>>;
public record GetConcatPlaylistByChannelNumber(string Scheme, string Host, string ChannelNumber, string Mode)
: IRequest<Either<BaseError, ConcatPlaylist>>;

4
ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumber.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Application.Streaming;
public record GetHlsPlaylistByChannelNumber
(string Scheme, string Host, string ChannelNumber, string Mode) : IRequest<Either<BaseError, string>>;
public record GetHlsPlaylistByChannelNumber(string Scheme, string Host, string ChannelNumber, string Mode)
: IRequest<Either<BaseError, string>>;

4
ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs

@ -28,9 +28,7 @@ public class GetHlsPlaylistByChannelNumberHandler : @@ -28,9 +28,7 @@ public class GetHlsPlaylistByChannelNumberHandler :
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
DateTimeOffset now = DateTimeOffset.Now;
Validation<BaseError, Parameters> validation = await Validate(dbContext, request, now);
return await LanguageExtensions.Apply(
validation,
parameters => GetPlaylist(dbContext, request, parameters, now));
return await validation.Apply(parameters => GetPlaylist(dbContext, request, parameters, now));
}
private Task<string> GetPlaylist(

2
ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs

@ -26,10 +26,10 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< @@ -26,10 +26,10 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
{
private readonly IArtistRepository _artistRepository;
private readonly IEmbyPathReplacementService _embyPathReplacementService;
private readonly IExternalJsonPlayoutItemProvider _externalJsonPlayoutItemProvider;
private readonly IFFmpegProcessService _ffmpegProcessService;
private readonly IJellyfinPathReplacementService _jellyfinPathReplacementService;
private readonly ILocalFileSystem _localFileSystem;
private readonly IExternalJsonPlayoutItemProvider _externalJsonPlayoutItemProvider;
private readonly ILogger<GetPlayoutItemProcessByChannelNumberHandler> _logger;
private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly IMusicVideoCreditsGenerator _musicVideoCreditsGenerator;

6
ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs

@ -23,9 +23,9 @@ namespace ErsatzTV.Application.Subtitles; @@ -23,9 +23,9 @@ namespace ErsatzTV.Application.Subtitles;
[SuppressMessage("Security", "CA5351:Do Not Use Broken Cryptographic Algorithms")]
public class ExtractEmbeddedSubtitlesHandler : IRequestHandler<ExtractEmbeddedSubtitles, Option<BaseError>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly IEntityLocker _entityLocker;
private readonly IConfigElementRepository _configElementRepository;
private readonly ILocalFileSystem _localFileSystem;
private readonly ILogger<ExtractEmbeddedSubtitlesHandler> _logger;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
@ -287,7 +287,9 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler<ExtractEmbeddedSu @@ -287,7 +287,9 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler<ExtractEmbeddedSu
.Filter(
s => s.Codec != "hdmv_pgs_subtitle" && s.Codec != "dvd_subtitle" && s.Codec != "dvdsub" &&
s.Codec != "vobsub" && s.Codec != "pgssub" && s.Codec != "pgs")
.Filter(s => s.IsExtracted == false || string.IsNullOrWhiteSpace(s.Path) || FileDoesntExist(mediaItem.Id, s));
.Filter(
s => s.IsExtracted == false || string.IsNullOrWhiteSpace(s.Path) ||
FileDoesntExist(mediaItem.Id, s));
// find cache paths for each subtitle
foreach (Subtitle subtitle in subtitles)

3
ErsatzTV.Application/Watermarks/Commands/CopyWatermark.cs

@ -2,5 +2,4 @@ @@ -2,5 +2,4 @@
namespace ErsatzTV.Application.Watermarks;
public record CopyWatermark
(int WatermarkId, string Name) : IRequest<Either<BaseError, WatermarkViewModel>>;
public record CopyWatermark(int WatermarkId, string Name) : IRequest<Either<BaseError, WatermarkViewModel>>;

8
ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj

@ -10,19 +10,19 @@ @@ -10,19 +10,19 @@
<PackageReference Include="Bugsnag" Version="3.1.0" />
<PackageReference Include="CliWrap" Version="3.6.6" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="LanguageExt.Core" Version="4.4.7" />
<PackageReference Include="LanguageExt.Core" Version="4.4.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="NUnit" Version="4.0.1" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />

2
ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs

@ -65,7 +65,7 @@ public static class BlockPlayoutChangeDetectionTests @@ -65,7 +65,7 @@ public static class BlockPlayoutChangeDetectionTests
List<EffectiveBlock> effectiveBlocks =
[
new EffectiveBlock(block1, blockKey1, GetLocalDate(2024, 1, 17).AddHours(9), 1),
new EffectiveBlock(block2, blockKey2, GetLocalDate(2024, 1, 17).AddHours(13), 2),
new EffectiveBlock(block2, blockKey2, GetLocalDate(2024, 1, 17).AddHours(13), 2)
];
Map<CollectionKey, string> collectionEtags = LanguageExt.Map<CollectionKey, string>.Empty;

68
ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs

@ -7,6 +7,38 @@ namespace ErsatzTV.Core.Tests.Scheduling.BlockScheduling; @@ -7,6 +7,38 @@ namespace ErsatzTV.Core.Tests.Scheduling.BlockScheduling;
public static class EffectiveBlockTests
{
private static DateTimeOffset GetLocalDate(int year, int month, int day) =>
new(year, month, day, 0, 0, 0, TimeSpan.FromHours(-6));
private static Template SingleBlockTemplate(DateTimeOffset dateUpdated)
{
var template = new Template
{
Id = 1,
Items =
[
new TemplateItem
{
Block = new Block
{
Id = 1,
DateUpdated = dateUpdated.UtcDateTime
},
StartTime = TimeSpan.FromHours(9)
}
],
DateUpdated = dateUpdated.UtcDateTime
};
// this is used for navigation
foreach (TemplateItem item in template.Items)
{
item.Template = template;
}
return template;
}
[TestFixture]
public class GetEffectiveBlocks
{
@ -30,7 +62,7 @@ public static class EffectiveBlockTests @@ -30,7 +62,7 @@ public static class EffectiveBlockTests
DateTimeOffset start = GetLocalDate(2024, 1, 15).AddHours(9);
List<EffectiveBlock> result = EffectiveBlock.GetEffectiveBlocks(templates, start, daysToBuild: 5);
List<EffectiveBlock> result = EffectiveBlock.GetEffectiveBlocks(templates, start, 5);
result.Should().HaveCount(0);
}
@ -55,7 +87,7 @@ public static class EffectiveBlockTests @@ -55,7 +87,7 @@ public static class EffectiveBlockTests
DateTimeOffset start = GetLocalDate(2024, 1, 15).AddHours(9);
List<EffectiveBlock> result = EffectiveBlock.GetEffectiveBlocks(templates, start, daysToBuild: 5);
List<EffectiveBlock> result = EffectiveBlock.GetEffectiveBlocks(templates, start, 5);
result.Should().HaveCount(3);
@ -74,36 +106,4 @@ public static class EffectiveBlockTests @@ -74,36 +106,4 @@ public static class EffectiveBlockTests
// TODO: offset may be incorrect on days with time change, since start offset is re-used
}
private static DateTimeOffset GetLocalDate(int year, int month, int day) =>
new(year, month, day, 0, 0, 0, TimeSpan.FromHours(-6));
private static Template SingleBlockTemplate(DateTimeOffset dateUpdated)
{
var template = new Template
{
Id = 1,
Items =
[
new TemplateItem
{
Block = new Block
{
Id = 1,
DateUpdated = dateUpdated.UtcDateTime
},
StartTime = TimeSpan.FromHours(9)
}
],
DateUpdated = dateUpdated.UtcDateTime
};
// this is used for navigation
foreach (TemplateItem item in template.Items)
{
item.Template = template;
}
return template;
}
}

8
ErsatzTV.Core/ErsatzTV.Core.csproj

@ -10,17 +10,17 @@ @@ -10,17 +10,17 @@
<ItemGroup>
<PackageReference Include="Bugsnag" Version="3.1.0" />
<PackageReference Include="Destructurama.Attributed" Version="3.2.0" />
<PackageReference Include="Destructurama.Attributed" Version="4.0.0" />
<PackageReference Include="Flurl" Version="4.0.0" />
<PackageReference Include="LanguageExt.Core" Version="4.4.7" />
<PackageReference Include="LanguageExt.Transformers" Version="4.4.7" />
<PackageReference Include="LanguageExt.Core" Version="4.4.8" />
<PackageReference Include="LanguageExt.Transformers" Version="4.4.8" />
<PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

43
ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs

@ -237,7 +237,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -237,7 +237,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
Option<SubtitleInputFile> subtitleInputFile = maybeSubtitle.Map<Option<SubtitleInputFile>>(
subtitle =>
{
if (!subtitle.IsImage && subtitle.SubtitleKind == SubtitleKind.Embedded && (!subtitle.IsExtracted || string.IsNullOrWhiteSpace(subtitle.Path)))
if (!subtitle.IsImage && subtitle.SubtitleKind == SubtitleKind.Embedded &&
(!subtitle.IsExtracted || string.IsNullOrWhiteSpace(subtitle.Path)))
{
_logger.LogWarning("Subtitles are not yet available for this item");
return None;
@ -622,20 +623,20 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -622,20 +623,20 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
};
var ffmpegVideoStream = new VideoStream(
Index: 0,
Codec: VideoFormat.Raw,
0,
VideoFormat.Raw,
Some(pixelFormat),
ColorParams.Default,
resolution,
MaybeSampleAspectRatio: "1:1",
DisplayAspectRatio: string.Empty,
FrameRate: Option<string>.None,
StillImage: false,
"1:1",
string.Empty,
Option<string>.None,
false,
ScanKind.Progressive);
var videoInputFile = new VideoInputFile(concatInputFile.Url, new List<VideoStream> { ffmpegVideoStream });
var ffmpegAudioStream = new AudioStream(Index: 1, Codec: string.Empty, channel.FFmpegProfile.AudioChannels);
var ffmpegAudioStream = new AudioStream(1, string.Empty, channel.FFmpegProfile.AudioChannels);
Option<AudioInputFile> audioInputFile = new AudioInputFile(
concatInputFile.Url,
new List<AudioStream> { ffmpegAudioStream },
@ -657,13 +658,13 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -657,13 +658,13 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
var desiredState = new FrameState(
playbackSettings.RealtimeOutput,
InfiniteLoop: true,
true,
videoFormat,
VideoProfile: Option<string>.None,
Option<string>.None,
Optional(playbackSettings.PixelFormat),
ScaledSize: resolution,
PaddedSize: resolution,
CroppedSize: Option<FrameSize>.None,
resolution,
resolution,
Option<FrameSize>.None,
false,
playbackSettings.FrameRate,
playbackSettings.VideoBitrate,
@ -676,22 +677,22 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -676,22 +677,22 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
var ffmpegState = new FFmpegState(
saveReports,
DecoderHardwareAccelerationMode: HardwareAccelerationMode.None,
EncoderHardwareAccelerationMode: hwAccel,
HardwareAccelerationMode.None,
hwAccel,
vaapiDriver,
vaapiDevice,
playbackSettings.StreamSeek,
Finish: Option<TimeSpan>.None,
Option<TimeSpan>.None,
channel.StreamingMode != StreamingMode.HttpLiveStreamingDirect,
"ErsatzTV",
channel.Name,
MetadataAudioLanguage: Option<string>.None,
MetadataSubtitleLanguage: Option<string>.None,
MetadataSubtitleTitle: Option<string>.None,
OutputFormat: OutputFormatKind.Hls,
Option<string>.None,
Option<string>.None,
Option<string>.None,
OutputFormatKind.Hls,
hlsPlaylistPath,
hlsSegmentTemplate,
PtsOffset: 0,
0,
playbackSettings.ThreadCount,
Optional(channel.FFmpegProfile.QsvExtraHardwareFrames));

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save