diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..53234a1 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "1.3.0", + "commands": [ + "csharpier" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 406d96e..82c170c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,6 +120,10 @@ Backend (из `backend/`): ```bash dotnet build +# Форматирование — csharpier, версия закреплена в .config/dotnet-tools.json (один раз: dotnet tool restore). +# Глобально установленный csharpier может быть другой версии — вызывать только через dotnet: +dotnet csharpier format . +dotnet csharpier check . # Юнит-тесты (по одному проекту за вызов — MSBuild не принимает несколько): dotnet test tests/TeleWave.Domain.Tests dotnet test tests/TeleWave.Application.Tests diff --git a/backend/src/TeleWave.Api/Common/SegmentFiles.cs b/backend/src/TeleWave.Api/Common/SegmentFiles.cs index f026d19..2d84739 100644 --- a/backend/src/TeleWave.Api/Common/SegmentFiles.cs +++ b/backend/src/TeleWave.Api/Common/SegmentFiles.cs @@ -17,11 +17,7 @@ internal static partial class SegmentFiles public static bool IsSegmentName(string file) => SegmentName().IsMatch(file); /// Путь к существующему файлу нарезки, либо null — если имя опасно или файла нет. - public static string? TryResolveExisting( - MediaPathResolver paths, - Guid assetId, - string fileName - ) + public static string? TryResolveExisting(MediaPathResolver paths, Guid assetId, string fileName) { string path; try diff --git a/backend/src/TeleWave.Api/Common/UploadLimits.cs b/backend/src/TeleWave.Api/Common/UploadLimits.cs index b954225..3bb9bad 100644 --- a/backend/src/TeleWave.Api/Common/UploadLimits.cs +++ b/backend/src/TeleWave.Api/Common/UploadLimits.cs @@ -8,10 +8,7 @@ namespace TeleWave.Api.Common; /// (Media и Storage), но проверяются всегда вместе и только на входе загрузки — /// хендлеру незачем знать про обе секции и тащить два в сигнатуре. /// -public sealed class UploadLimits( - IOptions media, - IOptions storage -) +public sealed class UploadLimits(IOptions media, IOptions storage) { /// Потолок размера загружаемого файла. public long MaxUploadBytes { get; } = media.Value.MaxUploadBytes; diff --git a/backend/src/TeleWave.Api/Endpoints/ChannelEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/ChannelEndpoints.cs index 6a3376c..a244360 100644 --- a/backend/src/TeleWave.Api/Endpoints/ChannelEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/ChannelEndpoints.cs @@ -7,10 +7,10 @@ using TeleWave.Application.Broadcast.GetSchedule; using TeleWave.Application.Broadcast.ListChannels; using TeleWave.Application.Broadcast.UpdateChannelSettings; using TeleWave.Application.Broadcast.UpdateChannelTime; -using TeleWave.Domain.Broadcast; -using TeleWave.Infrastructure.Identity; using TeleWave.Application.Broadcast.UpdateViewerSettings; using TeleWave.Application.Programming.Planning.Trace; +using TeleWave.Domain.Broadcast; +using TeleWave.Infrastructure.Identity; namespace TeleWave.Api.Endpoints; @@ -177,12 +177,7 @@ public static partial class ChannelEndpoints ) { var result = await sender.Send( - new UpdateChannelTimeCommand( - id, - body.Number, - body.UtcOffsetMinutes, - body.DayStartTime - ), + new UpdateChannelTimeCommand(id, body.Number, body.UtcOffsetMinutes, body.DayStartTime), cancellationToken ); return result.ToHttpResult(); @@ -209,7 +204,6 @@ public static partial class ChannelEndpoints return result.ToHttpResult(); } - private static async Task GetSchedule( Guid id, DateTimeOffset? from, diff --git a/backend/src/TeleWave.Api/Endpoints/GroupEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/GroupEndpoints.cs index 3ade5bb..441a5ae 100644 --- a/backend/src/TeleWave.Api/Endpoints/GroupEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/GroupEndpoints.cs @@ -30,7 +30,8 @@ public static class GroupEndpoints admin.MapDelete("/{id:guid}", DeleteGroup).Produces(StatusCodes.Status204NoContent); // Подбор по правилу набора: правило можно передать в теле, чтобы крутить его до сохранения. - admin.MapPost("/{id:guid}/candidates", FindCandidates) + admin + .MapPost("/{id:guid}/candidates", FindCandidates) .Produces>(); admin.MapPost("/{id:guid}/items", AddElements).Produces(); @@ -45,7 +46,10 @@ public static class GroupEndpoints return app; } - private static async Task ListGroups(ISender sender, CancellationToken cancellationToken) + private static async Task ListGroups( + ISender sender, + CancellationToken cancellationToken + ) { var result = await sender.Send(new ListGroupsQuery(), cancellationToken); return Results.Ok(result); diff --git a/backend/src/TeleWave.Api/Endpoints/JunctionEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/JunctionEndpoints.cs index d5ed8dd..e5a643f 100644 --- a/backend/src/TeleWave.Api/Endpoints/JunctionEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/JunctionEndpoints.cs @@ -24,7 +24,9 @@ public static class JunctionEndpoints admin .MapPost("/channels/{channelId:guid}/junctions", Create) .Produces(StatusCodes.Status201Created); - admin.MapPut("/junctions/{junctionId:guid}", Rename).Produces(StatusCodes.Status204NoContent); + admin + .MapPut("/junctions/{junctionId:guid}", Rename) + .Produces(StatusCodes.Status204NoContent); admin .MapDelete("/junctions/{junctionId:guid}", Delete) .Produces(StatusCodes.Status204NoContent); diff --git a/backend/src/TeleWave.Api/Endpoints/MediaEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/MediaEndpoints.cs index 52bde5e..4a40d50 100644 --- a/backend/src/TeleWave.Api/Endpoints/MediaEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/MediaEndpoints.cs @@ -141,7 +141,10 @@ public static class MediaEndpoints return result.ToHttpResult(); } - private static async Task ListManual(ISender sender, CancellationToken cancellationToken) + private static async Task ListManual( + ISender sender, + CancellationToken cancellationToken + ) { var result = await sender.Send(new ListManualInboxQuery(), cancellationToken); return Results.Ok(result); diff --git a/backend/src/TeleWave.Api/Endpoints/ShowEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/ShowEndpoints.cs index afa1115..b676c59 100644 --- a/backend/src/TeleWave.Api/Endpoints/ShowEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/ShowEndpoints.cs @@ -66,7 +66,10 @@ public static class ShowEndpoints bool interstitials = false ) { - var result = await sender.Send(new ListShowsQuery(genreId, interstitials), cancellationToken); + var result = await sender.Send( + new ListShowsQuery(genreId, interstitials), + cancellationToken + ); return Results.Ok(result); } diff --git a/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs index c9af4c9..7cb55cd 100644 --- a/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs @@ -48,7 +48,9 @@ public static class StreamingEndpoints CancellationToken cancellationToken ) => Results.Ok( - new ViewerFeaturesDto(await siteSettings.AreChannelNumbersEnabledAsync(cancellationToken)) + new ViewerFeaturesDto( + await siteSettings.AreChannelNumbersEnabledAsync(cancellationToken) + ) ); /// diff --git a/backend/src/TeleWave.Api/Endpoints/TemplateEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/TemplateEndpoints.cs index eb62ea2..ece21f8 100644 --- a/backend/src/TeleWave.Api/Endpoints/TemplateEndpoints.cs +++ b/backend/src/TeleWave.Api/Endpoints/TemplateEndpoints.cs @@ -56,13 +56,18 @@ public static class TemplateEndpoints .MapGet("/channels/{channelId:guid}/template/diff", DiffTemplate) .Produces(); admin - .MapPost("/channels/{channelId:guid}/template/copy-to/{targetChannelId:guid}", CopyTemplate) + .MapPost( + "/channels/{channelId:guid}/template/copy-to/{targetChannelId:guid}", + CopyTemplate + ) .Produces(); admin .MapPost("/templates/{templateId:guid}/layers", CreateLayer) .Produces(StatusCodes.Status201Created); - admin.MapPut("/layers/{layerId:guid}", UpdateLayer).Produces(StatusCodes.Status204NoContent); + admin + .MapPut("/layers/{layerId:guid}", UpdateLayer) + .Produces(StatusCodes.Status204NoContent); admin .MapDelete("/layers/{layerId:guid}", DeleteLayer) .Produces(StatusCodes.Status204NoContent); @@ -71,7 +76,9 @@ public static class TemplateEndpoints .MapPost("/layers/{layerId:guid}/slots", CreateSlot) .Produces(StatusCodes.Status201Created); admin.MapPut("/slots/{slotId:guid}", UpdateSlot).Produces(StatusCodes.Status204NoContent); - admin.MapDelete("/slots/{slotId:guid}", DeleteSlot).Produces(StatusCodes.Status204NoContent); + admin + .MapDelete("/slots/{slotId:guid}", DeleteSlot) + .Produces(StatusCodes.Status204NoContent); return app; } @@ -197,7 +204,10 @@ public static class TemplateEndpoints cancellationToken ); return result.IsSuccess - ? Results.Created($"/api/admin/layers/{result.Value}", new CreatedIdResponse(result.Value)) + ? Results.Created( + $"/api/admin/layers/{result.Value}", + new CreatedIdResponse(result.Value) + ) : result.ToHttpResult(); } @@ -240,7 +250,10 @@ public static class TemplateEndpoints { var result = await sender.Send(new CreateSlotCommand(layerId, input), cancellationToken); return result.IsSuccess - ? Results.Created($"/api/admin/slots/{result.Value}", new CreatedIdResponse(result.Value)) + ? Results.Created( + $"/api/admin/slots/{result.Value}", + new CreatedIdResponse(result.Value) + ) : result.ToHttpResult(); } diff --git a/backend/src/TeleWave.Application/Broadcast/Bumpers/RenderBumperPreviewCommandHandler.cs b/backend/src/TeleWave.Application/Broadcast/Bumpers/RenderBumperPreviewCommandHandler.cs index fd06250..e4dc762 100644 --- a/backend/src/TeleWave.Application/Broadcast/Bumpers/RenderBumperPreviewCommandHandler.cs +++ b/backend/src/TeleWave.Application/Broadcast/Bumpers/RenderBumperPreviewCommandHandler.cs @@ -108,11 +108,10 @@ public sealed class RenderBumperPreviewCommandHandler( var names = await ( from slot in dbContext.Slots.AsNoTracking() join layer in dbContext.GridLayers.AsNoTracking() on slot.LayerId equals layer.Id - join item in dbContext.GroupItems.AsNoTracking() - on slot.GroupId equals item.GroupId + join item in dbContext.GroupItems.AsNoTracking() on slot.GroupId equals item.GroupId join show in dbContext.Shows.AsNoTracking() on item.ElementId equals show.Id - where layer.TemplateId == channel.TemplateId - && item.ElementKind == GroupElementKind.Show + where + layer.TemplateId == channel.TemplateId && item.ElementKind == GroupElementKind.Show select show.Name ) .Distinct() diff --git a/backend/src/TeleWave.Application/Broadcast/ChannelErrors.cs b/backend/src/TeleWave.Application/Broadcast/ChannelErrors.cs index 7ac083c..1239272 100644 --- a/backend/src/TeleWave.Application/Broadcast/ChannelErrors.cs +++ b/backend/src/TeleWave.Application/Broadcast/ChannelErrors.cs @@ -50,5 +50,4 @@ public static class ChannelErrors "Channels.InvalidBumperFile", "Недопустимый файл заставки (формат или размер)." ); - } diff --git a/backend/src/TeleWave.Application/Library/Collections/ListCollections/ListCollectionsQueryHandler.cs b/backend/src/TeleWave.Application/Library/Collections/ListCollections/ListCollectionsQueryHandler.cs index 24b3fef..dbaaff6 100644 --- a/backend/src/TeleWave.Application/Library/Collections/ListCollections/ListCollectionsQueryHandler.cs +++ b/backend/src/TeleWave.Application/Library/Collections/ListCollections/ListCollectionsQueryHandler.cs @@ -20,7 +20,10 @@ public sealed class ListCollectionsQueryHandler(IAppDbContext dbContext) // Единиц воспроизведения может быть больше, чем частей: сериал внутри коллекции // разворачивается в свои серии. - var showIds = collections.SelectMany(c => c.Items.Select(i => i.ShowId)).Distinct().ToList(); + var showIds = collections + .SelectMany(c => c.Items.Select(i => i.ShowId)) + .Distinct() + .ToList(); var episodeCounts = await dbContext .Shows.AsNoTracking() .Where(s => showIds.Contains(s.Id)) diff --git a/backend/src/TeleWave.Application/Library/Collections/SetCollectionPoster/SetCollectionPosterCommand.cs b/backend/src/TeleWave.Application/Library/Collections/SetCollectionPoster/SetCollectionPosterCommand.cs index b2fd3b0..3519a52 100644 --- a/backend/src/TeleWave.Application/Library/Collections/SetCollectionPoster/SetCollectionPosterCommand.cs +++ b/backend/src/TeleWave.Application/Library/Collections/SetCollectionPoster/SetCollectionPosterCommand.cs @@ -4,4 +4,5 @@ using TeleWave.Application.Common.Models; namespace TeleWave.Application.Library.Collections.SetCollectionPoster; /// Привязать/снять постер коллекции ( = null — отвязать). -public sealed record SetCollectionPosterCommand(Guid CollectionId, Guid? ImageId) : ICommand; +public sealed record SetCollectionPosterCommand(Guid CollectionId, Guid? ImageId) + : ICommand; diff --git a/backend/src/TeleWave.Application/Library/GetShow/GetShowQueryHandler.cs b/backend/src/TeleWave.Application/Library/GetShow/GetShowQueryHandler.cs index ee8261c..7b33ebd 100644 --- a/backend/src/TeleWave.Application/Library/GetShow/GetShowQueryHandler.cs +++ b/backend/src/TeleWave.Application/Library/GetShow/GetShowQueryHandler.cs @@ -28,7 +28,12 @@ public sealed class GetShowQueryHandler(IAppDbContext dbContext) var genreNames = await dbContext .Genres.AsNoTracking() .Where(g => genreIds.Contains(g.Id)) - .Select(g => new { g.Id, g.Name, g.SortOrder }) + .Select(g => new + { + g.Id, + g.Name, + g.SortOrder, + }) .ToListAsync(cancellationToken); var genreDtos = genreNames diff --git a/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitialBlocks/ListInterstitialBlocksQueryHandler.cs b/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitialBlocks/ListInterstitialBlocksQueryHandler.cs index c89d3e3..569938c 100644 --- a/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitialBlocks/ListInterstitialBlocksQueryHandler.cs +++ b/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitialBlocks/ListInterstitialBlocksQueryHandler.cs @@ -21,15 +21,14 @@ public sealed class ListInterstitialBlocksQueryHandler(IAppDbContext dbContext) // «Блок» — не отдельная сущность, а признак состава: коллекция целиком из роликов. Смешанные // коллекции (франшизы) остаются на своём экране и сюда не попадают. - var showIds = collections.SelectMany(c => c.Items.Select(i => i.ShowId)).Distinct().ToList(); + var showIds = collections + .SelectMany(c => c.Items.Select(i => i.ShowId)) + .Distinct() + .ToList(); var clips = await dbContext .Shows.AsNoTracking() .Where(s => showIds.Contains(s.Id) && s.Kind == ShowKind.Interstitial) - .Select(s => new - { - s.Id, - AssetIds = s.Episodes.Select(e => e.MediaAssetId).ToList(), - }) + .Select(s => new { s.Id, AssetIds = s.Episodes.Select(e => e.MediaAssetId).ToList() }) .ToDictionaryAsync(s => s.Id, s => s.AssetIds, cancellationToken); var assetIds = clips.Values.SelectMany(ids => ids).Distinct().ToList(); diff --git a/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitials/ListInterstitialsQueryHandler.cs b/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitials/ListInterstitialsQueryHandler.cs index b420a52..e062b53 100644 --- a/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitials/ListInterstitialsQueryHandler.cs +++ b/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitials/ListInterstitialsQueryHandler.cs @@ -22,7 +22,9 @@ public sealed class ListInterstitialsQueryHandler(IAppDbContext dbContext) // У ролика ровно одна «серия» — берём её ассет, чтобы показать длительность и статус обработки. var assetIds = shows - .Select(s => s.Episodes.OrderBy(e => e.Position).Select(e => e.MediaAssetId).FirstOrDefault()) + .Select(s => + s.Episodes.OrderBy(e => e.Position).Select(e => e.MediaAssetId).FirstOrDefault() + ) .Where(id => id != Guid.Empty) .Distinct() .ToList(); @@ -44,8 +46,7 @@ public sealed class ListInterstitialsQueryHandler(IAppDbContext dbContext) .Episodes.OrderBy(e => e.Position) .Select(e => (Guid?)e.MediaAssetId) .FirstOrDefault(); - var asset = - assetId is { } id && assets.TryGetValue(id, out var a) ? a : null; + var asset = assetId is { } id && assets.TryGetValue(id, out var a) ? a : null; return new InterstitialDto( s.Id, s.Name, diff --git a/backend/src/TeleWave.Application/Library/ListShows/ListShowsQueryHandler.cs b/backend/src/TeleWave.Application/Library/ListShows/ListShowsQueryHandler.cs index 142421b..da0b7d7 100644 --- a/backend/src/TeleWave.Application/Library/ListShows/ListShowsQueryHandler.cs +++ b/backend/src/TeleWave.Application/Library/ListShows/ListShowsQueryHandler.cs @@ -78,7 +78,8 @@ public sealed class ListShowsQueryHandler(IAppDbContext dbContext) s.Year, s.PosterImageId is not null, s.CreatedAt, - s.PrimaryGenreId is { } primaryId && genreNames.TryGetValue(primaryId, out var g) + s.PrimaryGenreId is { } primaryId + && genreNames.TryGetValue(primaryId, out var g) ? g : null ); diff --git a/backend/src/TeleWave.Application/Media/ManualInbox/ImportManualInboxCommand.cs b/backend/src/TeleWave.Application/Media/ManualInbox/ImportManualInboxCommand.cs index a7df188..212dfaa 100644 --- a/backend/src/TeleWave.Application/Media/ManualInbox/ImportManualInboxCommand.cs +++ b/backend/src/TeleWave.Application/Media/ManualInbox/ImportManualInboxCommand.cs @@ -28,8 +28,7 @@ public sealed record ImportManualInboxResultDto( public sealed record ImportFailureDto(string RelativePath, string Reason); -public sealed class ImportManualInboxCommandValidator - : AbstractValidator +public sealed class ImportManualInboxCommandValidator : AbstractValidator { public ImportManualInboxCommandValidator() { diff --git a/backend/src/TeleWave.Application/Programming/Groups/AddGroupElements/AddGroupElementsCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/AddGroupElements/AddGroupElementsCommandHandler.cs index 9ba415a..fa03a0a 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/AddGroupElements/AddGroupElementsCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/AddGroupElements/AddGroupElementsCommandHandler.cs @@ -6,10 +6,8 @@ using TeleWave.Domain.Programming; namespace TeleWave.Application.Programming.Groups.AddGroupElements; -public sealed class AddGroupElementsCommandHandler( - IAppDbContext dbContext, - GroupStatsService stats -) : ICommandHandler> +public sealed class AddGroupElementsCommandHandler(IAppDbContext dbContext, GroupStatsService stats) + : ICommandHandler> { public async Task> Handle( AddGroupElementsCommand command, diff --git a/backend/src/TeleWave.Application/Programming/Groups/CreateGroup/CreateGroupCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/CreateGroup/CreateGroupCommandHandler.cs index e7381b5..3a3aff5 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/CreateGroup/CreateGroupCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/CreateGroup/CreateGroupCommandHandler.cs @@ -8,7 +8,10 @@ namespace TeleWave.Application.Programming.Groups.CreateGroup; public sealed class CreateGroupCommandHandler(IAppDbContext dbContext) : ICommandHandler> { - public Task> Handle(CreateGroupCommand command, CancellationToken cancellationToken) + public Task> Handle( + CreateGroupCommand command, + CancellationToken cancellationToken + ) { var group = Group.Create(command.Name, command.Description); dbContext.Groups.Add(group); diff --git a/backend/src/TeleWave.Application/Programming/Groups/DeleteGroup/DeleteGroupCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/DeleteGroup/DeleteGroupCommandHandler.cs index 6eea134..a1bd8f9 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/DeleteGroup/DeleteGroupCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/DeleteGroup/DeleteGroupCommandHandler.cs @@ -8,7 +8,10 @@ namespace TeleWave.Application.Programming.Groups.DeleteGroup; public sealed class DeleteGroupCommandHandler(IAppDbContext dbContext) : ICommandHandler { - public async Task Handle(DeleteGroupCommand command, CancellationToken cancellationToken) + public async Task Handle( + DeleteGroupCommand command, + CancellationToken cancellationToken + ) { var group = await dbContext.Groups.FirstOrDefaultAsync( g => g.Id == command.GroupId, diff --git a/backend/src/TeleWave.Application/Programming/Groups/FindGroupCandidates/FindGroupCandidatesQueryHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/FindGroupCandidates/FindGroupCandidatesQueryHandler.cs index 61c8cb4..c5be0b5 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/FindGroupCandidates/FindGroupCandidatesQueryHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/FindGroupCandidates/FindGroupCandidatesQueryHandler.cs @@ -58,9 +58,7 @@ public sealed class FindGroupCandidatesQueryHandler( } var info = await resolver.ResolveAsync(elements, cancellationToken); - var inGroup = group - .Items.Select(i => (i.ElementKind, i.ElementId)) - .ToHashSet(); + var inGroup = group.Items.Select(i => (i.ElementKind, i.ElementId)).ToHashSet(); var result = new List(); foreach (var (kind, id) in elements) diff --git a/backend/src/TeleWave.Application/Programming/Groups/GetGroup/GetGroupQueryHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/GetGroup/GetGroupQueryHandler.cs index 9f39590..494a898 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/GetGroup/GetGroupQueryHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/GetGroup/GetGroupQueryHandler.cs @@ -36,7 +36,8 @@ public sealed class GetGroupQueryHandler(IAppDbContext dbContext, GroupElementRe i.ElementId, // Элемент мог исчезнуть из библиотеки между чисткой и чтением — показываем прочерк, // а не роняем весь экран группы. - element?.Name ?? "—", + element?.Name + ?? "—", i.Weight, i.Position, element?.UnitCount ?? 0, diff --git a/backend/src/TeleWave.Application/Programming/Groups/GroupElementResolver.cs b/backend/src/TeleWave.Application/Programming/Groups/GroupElementResolver.cs index 4e078e9..9a49f3c 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/GroupElementResolver.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/GroupElementResolver.cs @@ -27,7 +27,9 @@ public sealed record GroupElementInfo( /// public sealed class GroupElementResolver(IAppDbContext dbContext) { - public async Task> ResolveAsync( + public async Task< + IReadOnlyDictionary<(GroupElementKind Kind, Guid Id), GroupElementInfo> + > ResolveAsync( IEnumerable<(GroupElementKind Kind, Guid Id)> elements, CancellationToken cancellationToken ) @@ -126,7 +128,9 @@ public sealed class GroupElementResolver(IAppDbContext dbContext) DurationOf(partAssets), null, // Рейтинг коллекции — самый строгий среди частей: по нему отбирают в детское время. - parts.Count == 0 ? null : parts.Max(p => p!.Audience), + parts.Count == 0 + ? null + : parts.Max(p => p!.Audience), parts.Count == 0 ? null : parts.Min(p => p!.Year), collection.PosterImageId ); diff --git a/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandHandler.cs index 347ff5e..27708fa 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandHandler.cs @@ -8,7 +8,10 @@ namespace TeleWave.Application.Programming.Groups.UpdateGroup; public sealed class UpdateGroupCommandHandler(IAppDbContext dbContext) : ICommandHandler { - public async Task Handle(UpdateGroupCommand command, CancellationToken cancellationToken) + public async Task Handle( + UpdateGroupCommand command, + CancellationToken cancellationToken + ) { var group = await dbContext.Groups.FirstOrDefaultAsync( g => g.Id == command.GroupId, diff --git a/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandValidator.cs b/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandValidator.cs index 1bd6dc4..3b53e9a 100644 --- a/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandValidator.cs +++ b/backend/src/TeleWave.Application/Programming/Groups/UpdateGroup/UpdateGroupCommandValidator.cs @@ -13,10 +13,18 @@ public sealed class UpdateGroupCommandValidator : AbstractValidator x.Filter is not null, () => { - RuleFor(x => x.Filter!.YearMin).InclusiveBetween(1870, 2200).When(x => x.Filter!.YearMin is not null); - RuleFor(x => x.Filter!.YearMax).InclusiveBetween(1870, 2200).When(x => x.Filter!.YearMax is not null); - RuleFor(x => x.Filter!.UnitMinutesMin).GreaterThanOrEqualTo(0).When(x => x.Filter!.UnitMinutesMin is not null); - RuleFor(x => x.Filter!.UnitMinutesMax).GreaterThanOrEqualTo(0).When(x => x.Filter!.UnitMinutesMax is not null); + RuleFor(x => x.Filter!.YearMin) + .InclusiveBetween(1870, 2200) + .When(x => x.Filter!.YearMin is not null); + RuleFor(x => x.Filter!.YearMax) + .InclusiveBetween(1870, 2200) + .When(x => x.Filter!.YearMax is not null); + RuleFor(x => x.Filter!.UnitMinutesMin) + .GreaterThanOrEqualTo(0) + .When(x => x.Filter!.UnitMinutesMin is not null); + RuleFor(x => x.Filter!.UnitMinutesMax) + .GreaterThanOrEqualTo(0) + .When(x => x.Filter!.UnitMinutesMax is not null); } ); } diff --git a/backend/src/TeleWave.Application/Programming/Planning/ApplyTemplate/ApplyChannelTemplateCommand.cs b/backend/src/TeleWave.Application/Programming/Planning/ApplyTemplate/ApplyChannelTemplateCommand.cs index 2d857fa..6a016b7 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/ApplyTemplate/ApplyChannelTemplateCommand.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/ApplyTemplate/ApplyChannelTemplateCommand.cs @@ -12,9 +12,6 @@ namespace TeleWave.Application.Programming.Planning.ApplyTemplate; public sealed record ApplyChannelTemplateCommand(Guid ChannelId) : ICommand>; /// Итог применения: сколько записей получилось и что стоит показать админу. -public sealed record ApplyResultDto( - int Added, - IReadOnlyList Warnings -); +public sealed record ApplyResultDto(int Added, IReadOnlyList Warnings); public sealed record PlanningWarningDto(PlanningWarningKind Kind, Guid? SlotId, string Details); diff --git a/backend/src/TeleWave.Application/Programming/Planning/BumperResolver.cs b/backend/src/TeleWave.Application/Programming/Planning/BumperResolver.cs index 549c964..54860c0 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/BumperResolver.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/BumperResolver.cs @@ -11,7 +11,12 @@ using TeleWave.Domain.Programming.Planning; namespace TeleWave.Application.Programming.Planning; /// Ключ отрендеренной заставки: блок, подблок и пара шоу, между которыми она стоит. -public readonly record struct BumperKey(Guid TemplateId, Guid VariantId, Guid FromShowId, Guid ToShowId); +public readonly record struct BumperKey( + Guid TemplateId, + Guid VariantId, + Guid FromShowId, + Guid ToShowId +); /// /// Подставляет ассеты заставкам, которые планировщик зарезервировал. Резерв и рендер разделены diff --git a/backend/src/TeleWave.Application/Programming/Planning/Diff/PreviewApplyDiffQueryHandler.cs b/backend/src/TeleWave.Application/Programming/Planning/Diff/PreviewApplyDiffQueryHandler.cs index 1d6ba77..4bc9205 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/Diff/PreviewApplyDiffQueryHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/Diff/PreviewApplyDiffQueryHandler.cs @@ -80,7 +80,10 @@ public sealed class PreviewApplyDiffQueryHandler( private sealed record Described(DateTimeOffset StartsAtUtc, string Label); - private static Described Describe(ScheduleEntry entry, IReadOnlyDictionary names) => + private static Described Describe( + ScheduleEntry entry, + IReadOnlyDictionary names + ) => new( entry.StartsAtUtc, entry.Kind switch diff --git a/backend/src/TeleWave.Application/Programming/Planning/EffectiveGridBuilder.cs b/backend/src/TeleWave.Application/Programming/Planning/EffectiveGridBuilder.cs index ef01fd7..9b8d229 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/EffectiveGridBuilder.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/EffectiveGridBuilder.cs @@ -89,7 +89,13 @@ public static class EffectiveGridBuilder if (taken.Any(t => from < t.To && t.From < to)) continue; - result.Add(new ScheduledSlot(slot, date, ToUtc(date, slot.TargetStart, offset, dayStartTime))); + result.Add( + new ScheduledSlot( + slot, + date, + ToUtc(date, slot.TargetStart, offset, dayStartTime) + ) + ); added.Add((from, to)); } diff --git a/backend/src/TeleWave.Application/Programming/Planning/GridScheduleGenerator.cs b/backend/src/TeleWave.Application/Programming/Planning/GridScheduleGenerator.cs index 9159743..9ef2c17 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/GridScheduleGenerator.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/GridScheduleGenerator.cs @@ -132,7 +132,10 @@ public sealed class GridScheduleGenerator( foreach (var item in result.Items) { var assetId = item.MediaAssetId; - if (item.Kind == PlannedItemKind.Bumper && !TryResolveBumper(item, bumperAssets, out assetId)) + if ( + item.Kind == PlannedItemKind.Bumper + && !TryResolveBumper(item, bumperAssets, out assetId) + ) continue; // Без ассета запись стала бы дырой в ленте. dbContext.ScheduleEntries.Add( @@ -207,14 +210,21 @@ public sealed class GridScheduleGenerator( cancellationToken ); - return result with { Warnings = [.. result.Warnings, .. postWarnings] }; + return result with + { + Warnings = [.. result.Warnings, .. postWarnings], + }; } /// /// Чистит прошлое сверх окна хранения. Окно должно покрывать самое долгое остывание среди правил — /// история показов берётся из самой ленты, отдельного журнала нет. /// - private Task CleanupAsync(Guid channelId, DateTimeOffset now, CancellationToken cancellationToken) + private Task CleanupAsync( + Guid channelId, + DateTimeOffset now, + CancellationToken cancellationToken + ) { var cutoff = now.AddDays(-Math.Max(1, _options.RetentionDays)); return dbContext @@ -326,7 +336,11 @@ public sealed class GridScheduleGenerator( var strategy = ToPlanningStrategy(SlotStrategy.FromJson(slot.StrategyJson)); var cursor = states.TryGetValue(slot.Id, out var state) - ? new PlanningCursor(state.CurrentElementKind, state.CurrentElementId, state.NextUnitIndex) + ? new PlanningCursor( + state.CurrentElementKind, + state.CurrentElementId, + state.NextUnitIndex + ) : null; slots.Add( @@ -354,7 +368,9 @@ public sealed class GridScheduleGenerator( ), rules?.AudienceAt( TimeOnly.FromDateTime( - item.StartUtc.ToOffset(TimeSpan.FromMinutes(channel.UtcOffsetMinutes)).DateTime + item.StartUtc.ToOffset( + TimeSpan.FromMinutes(channel.UtcOffsetMinutes) + ).DateTime ) ), repeatLimit @@ -489,7 +505,12 @@ public sealed class GridScheduleGenerator( var offset = TimeSpan.FromMinutes(channel.UtcOffsetMinutes); var sourceDate = scheduled.BroadcastDate.AddDays(-Math.Max(1, source.DaysAgo)); - var from = EffectiveGridBuilder.ToUtc(sourceDate, source.Time, offset, channel.DayStartTime); + var from = EffectiveGridBuilder.ToUtc( + sourceDate, + source.Time, + offset, + channel.DayStartTime + ); var to = from.AddMinutes(Math.Max(1, source.DurationMinutes)); var entries = await dbContext diff --git a/backend/src/TeleWave.Application/Programming/Planning/PostCheckRunner.cs b/backend/src/TeleWave.Application/Programming/Planning/PostCheckRunner.cs index e45d0a6..70acff2 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/PostCheckRunner.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/PostCheckRunner.cs @@ -115,7 +115,10 @@ public sealed class PostCheckRunner(IAppDbContext dbContext) .Select(s => new { s.Id, - GenreId = s.Genres.Where(g => g.IsPrimary).Select(g => (Guid?)g.GenreId).FirstOrDefault(), + GenreId = s + .Genres.Where(g => g.IsPrimary) + .Select(g => (Guid?)g.GenreId) + .FirstOrDefault(), }) .Where(s => s.GenreId != null) .ToDictionaryAsync(s => s.Id, s => s.GenreId!.Value, cancellationToken); diff --git a/backend/src/TeleWave.Application/Programming/Planning/Trace/GetEntryTraceQueryHandler.cs b/backend/src/TeleWave.Application/Programming/Planning/Trace/GetEntryTraceQueryHandler.cs index acef815..47e6c01 100644 --- a/backend/src/TeleWave.Application/Programming/Planning/Trace/GetEntryTraceQueryHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Planning/Trace/GetEntryTraceQueryHandler.cs @@ -32,14 +32,13 @@ public sealed class GetEntryTraceQueryHandler(IAppDbContext dbContext) if (entry is null) return Result.Failure(ChannelErrors.NotFound); - var showName = - entry.ShowId is { } showId - ? await dbContext - .Shows.AsNoTracking() - .Where(s => s.Id == showId) - .Select(s => s.Name) - .FirstOrDefaultAsync(cancellationToken) - : null; + var showName = entry.ShowId is { } showId + ? await dbContext + .Shows.AsNoTracking() + .Where(s => s.Id == showId) + .Select(s => s.Name) + .FirstOrDefaultAsync(cancellationToken) + : null; var collectionName = entry.CollectionId is { } collectionId ? await dbContext @@ -80,7 +79,9 @@ public sealed class GetEntryTraceQueryHandler(IAppDbContext dbContext) // Слот мог быть удалён или изменён после генерации — трейс от этого не портится, просто // часть подписей окажется пустой. var slot = trace.SlotId is { } slotId - ? await dbContext.Slots.AsNoTracking().FirstOrDefaultAsync(s => s.Id == slotId, cancellationToken) + ? await dbContext + .Slots.AsNoTracking() + .FirstOrDefaultAsync(s => s.Id == slotId, cancellationToken) : null; var layer = slot is null ? null diff --git a/backend/src/TeleWave.Application/Programming/Templates/CopyTemplate/CopyTemplateCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Templates/CopyTemplate/CopyTemplateCommandHandler.cs index 4c6e385..e94021b 100644 --- a/backend/src/TeleWave.Application/Programming/Templates/CopyTemplate/CopyTemplateCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Templates/CopyTemplate/CopyTemplateCommandHandler.cs @@ -70,7 +70,10 @@ public sealed class CopyTemplateCommandHandler(IAppDbContext dbContext) var copyTemplate = ScheduleTemplate.Create(target.Id, source.Name); copyTemplate.SetFallbackGroup(source.FallbackGroupId); copyTemplate.SetRules(source.RulesJson); - if (source.DefaultJunctionId is { } defaultJunction && junctionMap.TryGetValue(defaultJunction, out var mappedDefault)) + if ( + source.DefaultJunctionId is { } defaultJunction + && junctionMap.TryGetValue(defaultJunction, out var mappedDefault) + ) copyTemplate.SetDefaultJunction(mappedDefault); var (layers, slots) = CopyGrid(source, copyTemplate, junctionMap); diff --git a/backend/src/TeleWave.Application/Programming/Templates/CreateTemplate/CreateChannelTemplateCommandHandler.cs b/backend/src/TeleWave.Application/Programming/Templates/CreateTemplate/CreateChannelTemplateCommandHandler.cs index 4bd8b70..8ff8224 100644 --- a/backend/src/TeleWave.Application/Programming/Templates/CreateTemplate/CreateChannelTemplateCommandHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Templates/CreateTemplate/CreateChannelTemplateCommandHandler.cs @@ -24,11 +24,10 @@ public sealed class CreateChannelTemplateCommandHandler(IAppDbContext dbContext) // Шаблон мог остаться от прошлой жизни канала, потеряв ссылку на себя, — тогда просто // возвращаем его, а не заводим второй: одна сетка на канал. - var existing = await dbContext - .ScheduleTemplates.FirstOrDefaultAsync( - t => t.ChannelId == channel.Id, - cancellationToken - ); + var existing = await dbContext.ScheduleTemplates.FirstOrDefaultAsync( + t => t.ChannelId == channel.Id, + cancellationToken + ); if (existing is not null) { channel.SetTemplate(existing.Id); diff --git a/backend/src/TeleWave.Application/Programming/Templates/Layers/LayerCommandHandlers.cs b/backend/src/TeleWave.Application/Programming/Templates/Layers/LayerCommandHandlers.cs index 5977872..0815330 100644 --- a/backend/src/TeleWave.Application/Programming/Templates/Layers/LayerCommandHandlers.cs +++ b/backend/src/TeleWave.Application/Programming/Templates/Layers/LayerCommandHandlers.cs @@ -31,9 +31,16 @@ public sealed class CreateLayerCommandHandler(IAppDbContext dbContext) public sealed class UpdateLayerCommandHandler(IAppDbContext dbContext) : ICommandHandler { - public async Task Handle(UpdateLayerCommand command, CancellationToken cancellationToken) + public async Task Handle( + UpdateLayerCommand command, + CancellationToken cancellationToken + ) { - var template = await LayerLoader.ByLayerAsync(dbContext, command.LayerId, cancellationToken); + var template = await LayerLoader.ByLayerAsync( + dbContext, + command.LayerId, + cancellationToken + ); var layer = template?.FindLayer(command.LayerId); if (template is null || layer is null) return Result.Failure(TemplateErrors.LayerNotFound); @@ -52,9 +59,16 @@ public sealed class UpdateLayerCommandHandler(IAppDbContext dbContext) public sealed class DeleteLayerCommandHandler(IAppDbContext dbContext) : ICommandHandler { - public async Task Handle(DeleteLayerCommand command, CancellationToken cancellationToken) + public async Task Handle( + DeleteLayerCommand command, + CancellationToken cancellationToken + ) { - var template = await LayerLoader.ByLayerAsync(dbContext, command.LayerId, cancellationToken); + var template = await LayerLoader.ByLayerAsync( + dbContext, + command.LayerId, + cancellationToken + ); var layer = template?.FindLayer(command.LayerId); if (template is null || layer is null) return Result.Failure(TemplateErrors.LayerNotFound); diff --git a/backend/src/TeleWave.Application/Programming/Templates/Validate/ValidateTemplateQueryHandler.cs b/backend/src/TeleWave.Application/Programming/Templates/Validate/ValidateTemplateQueryHandler.cs index f42c4bb..0d23f52 100644 --- a/backend/src/TeleWave.Application/Programming/Templates/Validate/ValidateTemplateQueryHandler.cs +++ b/backend/src/TeleWave.Application/Programming/Templates/Validate/ValidateTemplateQueryHandler.cs @@ -292,7 +292,10 @@ public sealed class ValidateTemplateQueryHandler(IAppDbContext dbContext) // Список id собираем до запроса: проекция по материализованной коллекции внутри дерева // выражений заставляет EF пересобирать её на каждый вызов. - var neededShowIds = showIds.Concat(partsByCollection.Select(p => p.ShowId)).Distinct().ToList(); + var neededShowIds = showIds + .Concat(partsByCollection.Select(p => p.ShowId)) + .Distinct() + .ToList(); var audiences = await dbContext .Shows.AsNoTracking() diff --git a/backend/src/TeleWave.Domain/Library/Genre.cs b/backend/src/TeleWave.Domain/Library/Genre.cs index 78021f2..7f91f78 100644 --- a/backend/src/TeleWave.Domain/Library/Genre.cs +++ b/backend/src/TeleWave.Domain/Library/Genre.cs @@ -33,7 +33,12 @@ public class Genre private Genre() { } - public static Genre Create(string name, string slug, int sortOrder = 0, bool isSystem = false) => + public static Genre Create( + string name, + string slug, + int sortOrder = 0, + bool isSystem = false + ) => new() { Id = Guid.NewGuid(), diff --git a/backend/src/TeleWave.Domain/Library/GenreAlias.cs b/backend/src/TeleWave.Domain/Library/GenreAlias.cs index 9617d05..57673f5 100644 --- a/backend/src/TeleWave.Domain/Library/GenreAlias.cs +++ b/backend/src/TeleWave.Domain/Library/GenreAlias.cs @@ -36,7 +36,10 @@ public class GenreAlias var trimmed = value.Trim().ToLowerInvariant(); return string.Join( ' ', - trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + trimmed.Split( + ' ', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + ) ); } diff --git a/backend/src/TeleWave.Domain/Library/Show.cs b/backend/src/TeleWave.Domain/Library/Show.cs index 0b9aeac..e54a8a3 100644 --- a/backend/src/TeleWave.Domain/Library/Show.cs +++ b/backend/src/TeleWave.Domain/Library/Show.cs @@ -84,7 +84,8 @@ public class Show if (ids.Count == 0) return; - var primary = primaryGenreId is { } candidate && ids.Contains(candidate) ? candidate : ids[0]; + var primary = + primaryGenreId is { } candidate && ids.Contains(candidate) ? candidate : ids[0]; foreach (var id in ids) _genres.Add(ShowGenre.Create(Id, id, id == primary)); } diff --git a/backend/src/TeleWave.Domain/Programming/Planning/ElementSelector.cs b/backend/src/TeleWave.Domain/Programming/Planning/ElementSelector.cs index 1118216..e84f5f9 100644 --- a/backend/src/TeleWave.Domain/Programming/Planning/ElementSelector.cs +++ b/backend/src/TeleWave.Domain/Programming/Planning/ElementSelector.cs @@ -68,7 +68,9 @@ public static class ElementSelector if (current is not null && HasUnitsLeft(slot, current)) return Continue(slot, current); - var currentIndex = current is null ? -1 : ordered.FindIndex(e => e.ElementId == current.ElementId); + var currentIndex = current is null + ? -1 + : ordered.FindIndex(e => e.ElementId == current.ElementId); var nextIndex = currentIndex + 1; if (nextIndex >= ordered.Count) @@ -104,11 +106,12 @@ public static class ElementSelector var withinLimit = ApplyRepeatLimit(slot, playable, moment); var cooldown = TimeSpan.FromDays(Math.Max(0, slot.Strategy.CooldownDays)); - var eligible = cooldown <= TimeSpan.Zero - ? withinLimit - : withinLimit - .Where(e => e.LastPlayedUtc is not { } last || moment - last >= cooldown) - .ToList(); + var eligible = + cooldown <= TimeSpan.Zero + ? withinLimit + : withinLimit + .Where(e => e.LastPlayedUtc is not { } last || moment - last >= cooldown) + .ToList(); var exhausted = eligible.Count == 0; if (exhausted) diff --git a/backend/src/TeleWave.Domain/Programming/Planning/SchedulePlanner.cs b/backend/src/TeleWave.Domain/Programming/Planning/SchedulePlanner.cs index 1c3007f..503a514 100644 --- a/backend/src/TeleWave.Domain/Programming/Planning/SchedulePlanner.cs +++ b/backend/src/TeleWave.Domain/Programming/Planning/SchedulePlanner.cs @@ -123,16 +123,7 @@ public static class SchedulePlanner ) ); - trace = new PlanTrace( - slot.SlotId, - slot.SlotKind, - null, - null, - null, - null, - drift, - snapped - ); + trace = new PlanTrace(slot.SlotId, slot.SlotKind, null, null, null, null, drift, snapped); return cursor; } @@ -291,12 +282,7 @@ public static class SchedulePlanner slot.JunctionAfter, cursor, limit, - new JunctionPlacement( - slot.SlotId, - run.PreviousShowId, - null, - ElementChanged: true - ), + new JunctionPlacement(slot.SlotId, run.PreviousShowId, null, ElementChanged: true), run.Junctions, run.Items, slotTrace @@ -356,7 +342,8 @@ public static class SchedulePlanner { SlotBlockMode.Count => placed < Math.Max(1, slot.BlockValue), // Последняя единица входит целиком: обрезать видеофайл нельзя. - SlotBlockMode.Duration => accumulated < TimeSpan.FromMinutes(Math.Max(1, slot.BlockValue)), + SlotBlockMode.Duration => accumulated + < TimeSpan.FromMinutes(Math.Max(1, slot.BlockValue)), _ => cursor + unit.Duration <= budgetEnd, }; } diff --git a/backend/src/TeleWave.Domain/Programming/ScheduleTemplate.cs b/backend/src/TeleWave.Domain/Programming/ScheduleTemplate.cs index 4f2e17d..ae3bcfb 100644 --- a/backend/src/TeleWave.Domain/Programming/ScheduleTemplate.cs +++ b/backend/src/TeleWave.Domain/Programming/ScheduleTemplate.cs @@ -58,7 +58,12 @@ public class ScheduleTemplate }; // Фоновый слой заводится сразу: без него первая же дыра в сетке осталась бы нечем закрыть. template._layers.Add( - GridLayer.Create(template.Id, BackgroundLayerName, GridLayer.BackgroundPriority, isBackground: true) + GridLayer.Create( + template.Id, + BackgroundLayerName, + GridLayer.BackgroundPriority, + isBackground: true + ) ); return template; } diff --git a/backend/src/TeleWave.Infrastructure/Broadcast/MaintenanceBackgroundService.cs b/backend/src/TeleWave.Infrastructure/Broadcast/MaintenanceBackgroundService.cs index 6e42ad6..97806aa 100644 --- a/backend/src/TeleWave.Infrastructure/Broadcast/MaintenanceBackgroundService.cs +++ b/backend/src/TeleWave.Infrastructure/Broadcast/MaintenanceBackgroundService.cs @@ -60,9 +60,7 @@ public sealed class MaintenanceBackgroundService( // Осиротевшей считается заставка, чей ассет не встречается ни в одной записи расписания. // Границу по времени не ставим: окно хранения расписания уже определяет, что живо. var removed = await db - .BumperAssets.Where(b => - !db.ScheduleEntries.Any(e => e.MediaAssetId == b.MediaAssetId) - ) + .BumperAssets.Where(b => !db.ScheduleEntries.Any(e => e.MediaAssetId == b.MediaAssetId)) .ExecuteDeleteAsync(cancellationToken); if (removed > 0) diff --git a/backend/src/TeleWave.Infrastructure/Media/BumperRenderBackgroundService.cs b/backend/src/TeleWave.Infrastructure/Media/BumperRenderBackgroundService.cs index 1b983e9..8b944c3 100644 --- a/backend/src/TeleWave.Infrastructure/Media/BumperRenderBackgroundService.cs +++ b/backend/src/TeleWave.Infrastructure/Media/BumperRenderBackgroundService.cs @@ -41,8 +41,8 @@ internal sealed class BumperRenderBackgroundService( { try { - var spec = await WithScopeAsync( - loader => loader.LoadAsync(job.AssetId, cancellationToken) + var spec = await WithScopeAsync(loader => + loader.LoadAsync(job.AssetId, cancellationToken) ); if (spec is null) { diff --git a/backend/src/TeleWave.Infrastructure/Media/MediaClaimingBackgroundService.cs b/backend/src/TeleWave.Infrastructure/Media/MediaClaimingBackgroundService.cs index af3054b..c18963d 100644 --- a/backend/src/TeleWave.Infrastructure/Media/MediaClaimingBackgroundService.cs +++ b/backend/src/TeleWave.Infrastructure/Media/MediaClaimingBackgroundService.cs @@ -156,12 +156,7 @@ internal abstract class MediaClaimingBackgroundService( Guid assetId, string error, CancellationToken cancellationToken - ) => - await WithAssetAsync( - assetId, - asset => asset.MarkFailed(error), - cancellationToken - ); + ) => await WithAssetAsync(assetId, asset => asset.MarkFailed(error), cancellationToken); /// Находит ассет в свежем scope, применяет к нему изменение и сохраняет. protected async Task WithAssetAsync( diff --git a/backend/src/TeleWave.Infrastructure/Media/MediaProcessingBackgroundService.cs b/backend/src/TeleWave.Infrastructure/Media/MediaProcessingBackgroundService.cs index 83f1d5f..eb12123 100644 --- a/backend/src/TeleWave.Infrastructure/Media/MediaProcessingBackgroundService.cs +++ b/backend/src/TeleWave.Infrastructure/Media/MediaProcessingBackgroundService.cs @@ -48,7 +48,11 @@ internal sealed class MediaProcessingBackgroundService( { try { - var result = await processor.ProcessAsync(job.AssetId, job.Extension, cancellationToken); + var result = await processor.ProcessAsync( + job.AssetId, + job.Extension, + cancellationToken + ); await WithAssetAsync( job.AssetId, asset => diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726012618_AddGenres.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726012618_AddGenres.cs index 77d9915..4e1e6c5 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726012618_AddGenres.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726012618_AddGenres.cs @@ -16,16 +16,28 @@ namespace TeleWave.Infrastructure.Migrations columns: table => new { Id = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), - Slug = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column( + type: "character varying(128)", + maxLength: 128, + nullable: false + ), + Slug = table.Column( + type: "character varying(64)", + maxLength: 64, + nullable: false + ), SortOrder = table.Column(type: "integer", nullable: false), IsSystem = table.Column(type: "boolean", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + CreatedAt = table.Column( + type: "timestamp with time zone", + nullable: false + ), }, constraints: table => { table.PrimaryKey("PK_Genres", x => x.Id); - }); + } + ); migrationBuilder.CreateTable( name: "GenreAliases", @@ -33,7 +45,11 @@ namespace TeleWave.Infrastructure.Migrations { Id = table.Column(type: "uuid", nullable: false), GenreId = table.Column(type: "uuid", nullable: false), - Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false) + Value = table.Column( + type: "character varying(128)", + maxLength: 128, + nullable: false + ), }, constraints: table => { @@ -43,8 +59,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.GenreId, principalTable: "Genres", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "ShowGenres", @@ -52,7 +70,7 @@ namespace TeleWave.Infrastructure.Migrations { ShowId = table.Column(type: "uuid", nullable: false), GenreId = table.Column(type: "uuid", nullable: false), - IsPrimary = table.Column(type: "boolean", nullable: false) + IsPrimary = table.Column(type: "boolean", nullable: false), }, constraints: table => { @@ -62,49 +80,53 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.GenreId, principalTable: "Genres", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Restrict + ); table.ForeignKey( name: "FK_ShowGenres_Shows_ShowId", column: x => x.ShowId, principalTable: "Shows", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_GenreAliases_GenreId", table: "GenreAliases", - column: "GenreId"); + column: "GenreId" + ); migrationBuilder.CreateIndex( name: "IX_GenreAliases_Value", table: "GenreAliases", column: "Value", - unique: true); + unique: true + ); migrationBuilder.CreateIndex( name: "IX_Genres_Slug", table: "Genres", column: "Slug", - unique: true); + unique: true + ); migrationBuilder.CreateIndex( name: "IX_ShowGenres_GenreId", table: "ShowGenres", - column: "GenreId"); + column: "GenreId" + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "GenreAliases"); + migrationBuilder.DropTable(name: "GenreAliases"); - migrationBuilder.DropTable( - name: "ShowGenres"); + migrationBuilder.DropTable(name: "ShowGenres"); - migrationBuilder.DropTable( - name: "Genres"); + migrationBuilder.DropTable(name: "Genres"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726014301_AddCollections.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726014301_AddCollections.cs index bbd3d69..c0f61ae 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726014301_AddCollections.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726014301_AddCollections.cs @@ -16,15 +16,27 @@ namespace TeleWave.Infrastructure.Migrations columns: table => new { Id = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + Name = table.Column( + type: "character varying(256)", + maxLength: 256, + nullable: false + ), + Description = table.Column( + type: "character varying(2048)", + maxLength: 2048, + nullable: true + ), PosterImageId = table.Column(type: "uuid", nullable: true), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + CreatedAt = table.Column( + type: "timestamp with time zone", + nullable: false + ), }, constraints: table => { table.PrimaryKey("PK_Collections", x => x.Id); - }); + } + ); migrationBuilder.CreateTable( name: "CollectionItems", @@ -33,7 +45,7 @@ namespace TeleWave.Infrastructure.Migrations Id = table.Column(type: "uuid", nullable: false), CollectionId = table.Column(type: "uuid", nullable: false), ShowId = table.Column(type: "uuid", nullable: false), - Position = table.Column(type: "integer", nullable: false) + Position = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -43,40 +55,44 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.CollectionId, principalTable: "Collections", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); + onDelete: ReferentialAction.Cascade + ); table.ForeignKey( name: "FK_CollectionItems_Shows_ShowId", column: x => x.ShowId, principalTable: "Shows", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_CollectionItems_CollectionId_Position", table: "CollectionItems", - columns: new[] { "CollectionId", "Position" }); + columns: new[] { "CollectionId", "Position" } + ); migrationBuilder.CreateIndex( name: "IX_CollectionItems_CollectionId_ShowId", table: "CollectionItems", columns: new[] { "CollectionId", "ShowId" }, - unique: true); + unique: true + ); migrationBuilder.CreateIndex( name: "IX_CollectionItems_ShowId", table: "CollectionItems", - column: "ShowId"); + column: "ShowId" + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "CollectionItems"); + migrationBuilder.DropTable(name: "CollectionItems"); - migrationBuilder.DropTable( - name: "Collections"); + migrationBuilder.DropTable(name: "Collections"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726014922_AddGroups.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726014922_AddGroups.cs index b847fc9..4dc96dd 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726014922_AddGroups.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726014922_AddGroups.cs @@ -16,19 +16,34 @@ namespace TeleWave.Infrastructure.Migrations columns: table => new { Id = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + Name = table.Column( + type: "character varying(256)", + maxLength: 256, + nullable: false + ), + Description = table.Column( + type: "character varying(2048)", + maxLength: 2048, + nullable: true + ), FilterJson = table.Column(type: "jsonb", nullable: true), ItemCount = table.Column(type: "integer", nullable: false), UnitCount = table.Column(type: "integer", nullable: false), TotalDuration = table.Column(type: "interval", nullable: false), - StatsComputedAt = table.Column(type: "timestamp with time zone", nullable: true), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + StatsComputedAt = table.Column( + type: "timestamp with time zone", + nullable: true + ), + CreatedAt = table.Column( + type: "timestamp with time zone", + nullable: false + ), }, constraints: table => { table.PrimaryKey("PK_Groups", x => x.Id); - }); + } + ); migrationBuilder.CreateTable( name: "GroupItems", @@ -39,7 +54,7 @@ namespace TeleWave.Infrastructure.Migrations ElementKind = table.Column(type: "integer", nullable: false), ElementId = table.Column(type: "uuid", nullable: false), Weight = table.Column(type: "integer", nullable: false), - Position = table.Column(type: "integer", nullable: false) + Position = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -49,34 +64,37 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.GroupId, principalTable: "Groups", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_GroupItems_ElementKind_ElementId", table: "GroupItems", - columns: new[] { "ElementKind", "ElementId" }); + columns: new[] { "ElementKind", "ElementId" } + ); migrationBuilder.CreateIndex( name: "IX_GroupItems_GroupId_ElementKind_ElementId", table: "GroupItems", columns: new[] { "GroupId", "ElementKind", "ElementId" }, - unique: true); + unique: true + ); migrationBuilder.CreateIndex( name: "IX_GroupItems_GroupId_Position", table: "GroupItems", - columns: new[] { "GroupId", "Position" }); + columns: new[] { "GroupId", "Position" } + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "GroupItems"); + migrationBuilder.DropTable(name: "GroupItems"); - migrationBuilder.DropTable( - name: "Groups"); + migrationBuilder.DropTable(name: "Groups"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726020225_AddScheduleTemplate.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726020225_AddScheduleTemplate.cs index 05b9522..54821d2 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726020225_AddScheduleTemplate.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726020225_AddScheduleTemplate.cs @@ -16,26 +16,30 @@ namespace TeleWave.Infrastructure.Migrations table: "Channels", type: "time without time zone", nullable: false, - defaultValue: new TimeOnly(0, 0, 0)); + defaultValue: new TimeOnly(0, 0, 0) + ); migrationBuilder.AddColumn( name: "Number", table: "Channels", type: "integer", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "TemplateId", table: "Channels", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "UtcOffsetMinutes", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.CreateTable( name: "ScheduleTemplates", @@ -43,16 +47,24 @@ namespace TeleWave.Infrastructure.Migrations { Id = table.Column(type: "uuid", nullable: false), ChannelId = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column( + type: "character varying(256)", + maxLength: 256, + nullable: false + ), FallbackGroupId = table.Column(type: "uuid", nullable: true), Revision = table.Column(type: "integer", nullable: false), AppliedRevision = table.Column(type: "integer", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + CreatedAt = table.Column( + type: "timestamp with time zone", + nullable: false + ), }, constraints: table => { table.PrimaryKey("PK_ScheduleTemplates", x => x.Id); - }); + } + ); migrationBuilder.CreateTable( name: "GridLayers", @@ -60,11 +72,15 @@ namespace TeleWave.Infrastructure.Migrations { Id = table.Column(type: "uuid", nullable: false), TemplateId = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column( + type: "character varying(128)", + maxLength: 128, + nullable: false + ), Priority = table.Column(type: "integer", nullable: false), ApplicabilityJson = table.Column(type: "jsonb", nullable: true), IsEnabled = table.Column(type: "boolean", nullable: false), - IsBackground = table.Column(type: "boolean", nullable: false) + IsBackground = table.Column(type: "boolean", nullable: false), }, constraints: table => { @@ -74,8 +90,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.TemplateId, principalTable: "ScheduleTemplates", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "Slots", @@ -84,9 +102,16 @@ namespace TeleWave.Infrastructure.Migrations Id = table.Column(type: "uuid", nullable: false), LayerId = table.Column(type: "uuid", nullable: false), Weekday = table.Column(type: "integer", nullable: true), - TargetStart = table.Column(type: "time without time zone", nullable: false), + TargetStart = table.Column( + type: "time without time zone", + nullable: false + ), TargetDurationMinutes = table.Column(type: "integer", nullable: false), - Title = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Title = table.Column( + type: "character varying(256)", + maxLength: 256, + nullable: false + ), Daypart = table.Column(type: "integer", nullable: false), SlotKind = table.Column(type: "integer", nullable: false), GroupId = table.Column(type: "uuid", nullable: true), @@ -97,7 +122,7 @@ namespace TeleWave.Infrastructure.Migrations OverflowPolicy = table.Column(type: "integer", nullable: false), IsAnchor = table.Column(type: "boolean", nullable: false), MaxDriftMinutes = table.Column(type: "integer", nullable: false), - SnapToMinutes = table.Column(type: "integer", nullable: true) + SnapToMinutes = table.Column(type: "integer", nullable: true), }, constraints: table => { @@ -107,14 +132,17 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.LayerId, principalTable: "GridLayers", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); + onDelete: ReferentialAction.Cascade + ); table.ForeignKey( name: "FK_Slots_Groups_GroupId", column: x => x.GroupId, principalTable: "Groups", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); + onDelete: ReferentialAction.Restrict + ); + } + ); migrationBuilder.CreateTable( name: "SlotStates", @@ -123,7 +151,7 @@ namespace TeleWave.Infrastructure.Migrations SlotId = table.Column(type: "uuid", nullable: false), CurrentElementKind = table.Column(type: "integer", nullable: true), CurrentElementId = table.Column(type: "uuid", nullable: true), - NextUnitIndex = table.Column(type: "integer", nullable: false) + NextUnitIndex = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -133,71 +161,64 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.SlotId, principalTable: "Slots", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_Channels_Number", table: "Channels", column: "Number", unique: true, - filter: "\"Number\" IS NOT NULL"); + filter: "\"Number\" IS NOT NULL" + ); migrationBuilder.CreateIndex( name: "IX_GridLayers_TemplateId_Priority", table: "GridLayers", - columns: new[] { "TemplateId", "Priority" }); + columns: new[] { "TemplateId", "Priority" } + ); migrationBuilder.CreateIndex( name: "IX_ScheduleTemplates_ChannelId", table: "ScheduleTemplates", - column: "ChannelId"); + column: "ChannelId" + ); migrationBuilder.CreateIndex( name: "IX_Slots_GroupId", table: "Slots", - column: "GroupId"); + column: "GroupId" + ); migrationBuilder.CreateIndex( name: "IX_Slots_LayerId_TargetStart", table: "Slots", - columns: new[] { "LayerId", "TargetStart" }); + columns: new[] { "LayerId", "TargetStart" } + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "SlotStates"); + migrationBuilder.DropTable(name: "SlotStates"); - migrationBuilder.DropTable( - name: "Slots"); + migrationBuilder.DropTable(name: "Slots"); - migrationBuilder.DropTable( - name: "GridLayers"); + migrationBuilder.DropTable(name: "GridLayers"); - migrationBuilder.DropTable( - name: "ScheduleTemplates"); + migrationBuilder.DropTable(name: "ScheduleTemplates"); - migrationBuilder.DropIndex( - name: "IX_Channels_Number", - table: "Channels"); + migrationBuilder.DropIndex(name: "IX_Channels_Number", table: "Channels"); - migrationBuilder.DropColumn( - name: "DayStartTime", - table: "Channels"); + migrationBuilder.DropColumn(name: "DayStartTime", table: "Channels"); - migrationBuilder.DropColumn( - name: "Number", - table: "Channels"); + migrationBuilder.DropColumn(name: "Number", table: "Channels"); - migrationBuilder.DropColumn( - name: "TemplateId", - table: "Channels"); + migrationBuilder.DropColumn(name: "TemplateId", table: "Channels"); - migrationBuilder.DropColumn( - name: "UtcOffsetMinutes", - table: "Channels"); + migrationBuilder.DropColumn(name: "UtcOffsetMinutes", table: "Channels"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726072637_ScheduleEntryTrace.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726072637_ScheduleEntryTrace.cs index 72bcfaf..d5cf8e9 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726072637_ScheduleEntryTrace.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726072637_ScheduleEntryTrace.cs @@ -13,24 +13,28 @@ namespace TeleWave.Infrastructure.Migrations { migrationBuilder.DropIndex( name: "IX_ScheduleEntries_ChannelId_ShowId", - table: "ScheduleEntries"); + table: "ScheduleEntries" + ); migrationBuilder.AddColumn( name: "SlotId", table: "ScheduleEntries", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "TraceJson", table: "ScheduleEntries", type: "jsonb", - nullable: true); + nullable: true + ); migrationBuilder.CreateIndex( name: "IX_ScheduleEntries_ChannelId_ShowId_StartsAtUtc", table: "ScheduleEntries", - columns: new[] { "ChannelId", "ShowId", "StartsAtUtc" }); + columns: new[] { "ChannelId", "ShowId", "StartsAtUtc" } + ); } /// @@ -38,20 +42,18 @@ namespace TeleWave.Infrastructure.Migrations { migrationBuilder.DropIndex( name: "IX_ScheduleEntries_ChannelId_ShowId_StartsAtUtc", - table: "ScheduleEntries"); + table: "ScheduleEntries" + ); - migrationBuilder.DropColumn( - name: "SlotId", - table: "ScheduleEntries"); + migrationBuilder.DropColumn(name: "SlotId", table: "ScheduleEntries"); - migrationBuilder.DropColumn( - name: "TraceJson", - table: "ScheduleEntries"); + migrationBuilder.DropColumn(name: "TraceJson", table: "ScheduleEntries"); migrationBuilder.CreateIndex( name: "IX_ScheduleEntries_ChannelId_ShowId", table: "ScheduleEntries", - columns: new[] { "ChannelId", "ShowId" }); + columns: new[] { "ChannelId", "ShowId" } + ); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726100547_DropLegacyRotation.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726100547_DropLegacyRotation.cs index 2636fa0..d4a6629 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726100547_DropLegacyRotation.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726100547_DropLegacyRotation.cs @@ -11,32 +11,21 @@ namespace TeleWave.Infrastructure.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "ChannelAd"); + migrationBuilder.DropTable(name: "ChannelAd"); - migrationBuilder.DropTable( - name: "ChannelShowHour"); + migrationBuilder.DropTable(name: "ChannelShowHour"); - migrationBuilder.DropTable( - name: "OverrideShow"); + migrationBuilder.DropTable(name: "OverrideShow"); - migrationBuilder.DropTable( - name: "ChannelShow"); + migrationBuilder.DropTable(name: "ChannelShow"); - migrationBuilder.DropTable( - name: "ProgrammingOverride"); + migrationBuilder.DropTable(name: "ProgrammingOverride"); - migrationBuilder.DropColumn( - name: "AdInsertion", - table: "Channels"); + migrationBuilder.DropColumn(name: "AdInsertion", table: "Channels"); - migrationBuilder.DropColumn( - name: "AdsPerBreak", - table: "Channels"); + migrationBuilder.DropColumn(name: "AdsPerBreak", table: "Channels"); - migrationBuilder.DropColumn( - name: "NextAdIndex", - table: "Channels"); + migrationBuilder.DropColumn(name: "NextAdIndex", table: "Channels"); } /// @@ -47,21 +36,24 @@ namespace TeleWave.Infrastructure.Migrations table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.AddColumn( name: "AdsPerBreak", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.AddColumn( name: "NextAdIndex", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.CreateTable( name: "ChannelAd", @@ -70,7 +62,7 @@ namespace TeleWave.Infrastructure.Migrations Id = table.Column(type: "uuid", nullable: false), ChannelId = table.Column(type: "uuid", nullable: false), MediaAssetId = table.Column(type: "uuid", nullable: false), - Position = table.Column(type: "integer", nullable: false) + Position = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -80,8 +72,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.ChannelId, principalTable: "Channels", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "ChannelShow", @@ -93,9 +87,13 @@ namespace TeleWave.Infrastructure.Migrations ChannelId = table.Column(type: "uuid", nullable: false), IsEnabled = table.Column(type: "boolean", nullable: false), NextEpisodeIndex = table.Column(type: "integer", nullable: false), - PreferredWeightMultiplier = table.Column(type: "integer", nullable: false, defaultValue: 3), + PreferredWeightMultiplier = table.Column( + type: "integer", + nullable: false, + defaultValue: 3 + ), ShowId = table.Column(type: "uuid", nullable: false), - Weight = table.Column(type: "integer", nullable: false) + Weight = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -105,8 +103,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.ChannelId, principalTable: "Channels", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "ProgrammingOverride", @@ -116,11 +116,17 @@ namespace TeleWave.Infrastructure.Migrations ChannelId = table.Column(type: "uuid", nullable: false), DayOfWeek = table.Column(type: "integer", nullable: true), EndMinute = table.Column(type: "integer", nullable: true), - EndsAtUtc = table.Column(type: "timestamp with time zone", nullable: true), + EndsAtUtc = table.Column( + type: "timestamp with time zone", + nullable: true + ), Mode = table.Column(type: "integer", nullable: false), Recurrence = table.Column(type: "integer", nullable: false), StartMinute = table.Column(type: "integer", nullable: true), - StartsAtUtc = table.Column(type: "timestamp with time zone", nullable: true) + StartsAtUtc = table.Column( + type: "timestamp with time zone", + nullable: true + ), }, constraints: table => { @@ -130,8 +136,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.ChannelId, principalTable: "Channels", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "ChannelShowHour", @@ -140,7 +148,7 @@ namespace TeleWave.Infrastructure.Migrations Id = table.Column(type: "uuid", nullable: false), ChannelShowId = table.Column(type: "uuid", nullable: false), EndHour = table.Column(type: "integer", nullable: false), - StartHour = table.Column(type: "integer", nullable: false) + StartHour = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -150,8 +158,10 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.ChannelShowId, principalTable: "ChannelShow", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateTable( name: "OverrideShow", @@ -160,7 +170,7 @@ namespace TeleWave.Infrastructure.Migrations Id = table.Column(type: "uuid", nullable: false), ProgrammingOverrideId = table.Column(type: "uuid", nullable: false), ShowId = table.Column(type: "uuid", nullable: false), - Weight = table.Column(type: "integer", nullable: false) + Weight = table.Column(type: "integer", nullable: false), }, constraints: table => { @@ -170,33 +180,40 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.ProgrammingOverrideId, principalTable: "ProgrammingOverride", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_ChannelAd_ChannelId_Position", table: "ChannelAd", - columns: new[] { "ChannelId", "Position" }); + columns: new[] { "ChannelId", "Position" } + ); migrationBuilder.CreateIndex( name: "IX_ChannelShow_ChannelId_ShowId", table: "ChannelShow", - columns: new[] { "ChannelId", "ShowId" }); + columns: new[] { "ChannelId", "ShowId" } + ); migrationBuilder.CreateIndex( name: "IX_ChannelShowHour_ChannelShowId", table: "ChannelShowHour", - column: "ChannelShowId"); + column: "ChannelShowId" + ); migrationBuilder.CreateIndex( name: "IX_OverrideShow_ProgrammingOverrideId", table: "OverrideShow", - column: "ProgrammingOverrideId"); + column: "ProgrammingOverrideId" + ); migrationBuilder.CreateIndex( name: "IX_ProgrammingOverride_ChannelId_StartsAtUtc_EndsAtUtc", table: "ProgrammingOverride", - columns: new[] { "ChannelId", "StartsAtUtc", "EndsAtUtc" }); + columns: new[] { "ChannelId", "StartsAtUtc", "EndsAtUtc" } + ); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726102012_AddJunctionTemplates.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726102012_AddJunctionTemplates.cs index 17e44a8..e3c8fdb 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726102012_AddJunctionTemplates.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726102012_AddJunctionTemplates.cs @@ -15,19 +15,22 @@ namespace TeleWave.Infrastructure.Migrations name: "JunctionAfterId", table: "Slots", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "JunctionBetweenId", table: "Slots", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "DefaultJunctionId", table: "ScheduleTemplates", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.CreateTable( name: "JunctionTemplates", @@ -35,13 +38,21 @@ namespace TeleWave.Infrastructure.Migrations { Id = table.Column(type: "uuid", nullable: false), ChannelId = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + Name = table.Column( + type: "character varying(128)", + maxLength: 128, + nullable: false + ), + CreatedAt = table.Column( + type: "timestamp with time zone", + nullable: false + ), }, constraints: table => { table.PrimaryKey("PK_JunctionTemplates", x => x.Id); - }); + } + ); migrationBuilder.CreateTable( name: "JunctionElements", @@ -56,7 +67,7 @@ namespace TeleWave.Infrastructure.Migrations AmountMode = table.Column(type: "integer", nullable: false), AmountValue = table.Column(type: "integer", nullable: false), IsRequired = table.Column(type: "boolean", nullable: false), - ConditionsJson = table.Column(type: "jsonb", nullable: true) + ConditionsJson = table.Column(type: "jsonb", nullable: true), }, constraints: table => { @@ -66,51 +77,49 @@ namespace TeleWave.Infrastructure.Migrations column: x => x.GroupId, principalTable: "Groups", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Restrict + ); table.ForeignKey( name: "FK_JunctionElements_JunctionTemplates_JunctionTemplateId", column: x => x.JunctionTemplateId, principalTable: "JunctionTemplates", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); + onDelete: ReferentialAction.Cascade + ); + } + ); migrationBuilder.CreateIndex( name: "IX_JunctionElements_GroupId", table: "JunctionElements", - column: "GroupId"); + column: "GroupId" + ); migrationBuilder.CreateIndex( name: "IX_JunctionElements_JunctionTemplateId_Position", table: "JunctionElements", - columns: new[] { "JunctionTemplateId", "Position" }); + columns: new[] { "JunctionTemplateId", "Position" } + ); migrationBuilder.CreateIndex( name: "IX_JunctionTemplates_ChannelId", table: "JunctionTemplates", - column: "ChannelId"); + column: "ChannelId" + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "JunctionElements"); + migrationBuilder.DropTable(name: "JunctionElements"); - migrationBuilder.DropTable( - name: "JunctionTemplates"); + migrationBuilder.DropTable(name: "JunctionTemplates"); - migrationBuilder.DropColumn( - name: "JunctionAfterId", - table: "Slots"); + migrationBuilder.DropColumn(name: "JunctionAfterId", table: "Slots"); - migrationBuilder.DropColumn( - name: "JunctionBetweenId", - table: "Slots"); + migrationBuilder.DropColumn(name: "JunctionBetweenId", table: "Slots"); - migrationBuilder.DropColumn( - name: "DefaultJunctionId", - table: "ScheduleTemplates"); + migrationBuilder.DropColumn(name: "DefaultJunctionId", table: "ScheduleTemplates"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726105315_DropDeadBumperSettings.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726105315_DropDeadBumperSettings.cs index 8111e3a..4089d36 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726105315_DropDeadBumperSettings.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726105315_DropDeadBumperSettings.cs @@ -16,21 +16,13 @@ namespace TeleWave.Infrastructure.Migrations """UPDATE "Channels" SET "BumperSelection" = 3 WHERE "BumperSelection" = 0;""" ); - migrationBuilder.DropColumn( - name: "BumperEpisodeChangeChance", - table: "Channels"); + migrationBuilder.DropColumn(name: "BumperEpisodeChangeChance", table: "Channels"); - migrationBuilder.DropColumn( - name: "BumperMinIntervalMinutes", - table: "Channels"); + migrationBuilder.DropColumn(name: "BumperMinIntervalMinutes", table: "Channels"); - migrationBuilder.DropColumn( - name: "BumperShowChangeChance", - table: "Channels"); + migrationBuilder.DropColumn(name: "BumperShowChangeChance", table: "Channels"); - migrationBuilder.DropColumn( - name: "NextBumperIndex", - table: "Channels"); + migrationBuilder.DropColumn(name: "NextBumperIndex", table: "Channels"); } /// @@ -41,28 +33,32 @@ namespace TeleWave.Infrastructure.Migrations table: "Channels", type: "double precision", nullable: false, - defaultValue: 0.0); + defaultValue: 0.0 + ); migrationBuilder.AddColumn( name: "BumperMinIntervalMinutes", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.AddColumn( name: "BumperShowChangeChance", table: "Channels", type: "double precision", nullable: false, - defaultValue: 0.0); + defaultValue: 0.0 + ); migrationBuilder.AddColumn( name: "NextBumperIndex", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726110935_TemplatePlanningRules.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726110935_TemplatePlanningRules.cs index 1fe9fa5..cb929b9 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726110935_TemplatePlanningRules.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726110935_TemplatePlanningRules.cs @@ -14,15 +14,14 @@ namespace TeleWave.Infrastructure.Migrations name: "RulesJson", table: "ScheduleTemplates", type: "jsonb", - nullable: true); + nullable: true + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropColumn( - name: "RulesJson", - table: "ScheduleTemplates"); + migrationBuilder.DropColumn(name: "RulesJson", table: "ScheduleTemplates"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726114417_ChannelViewerSettings.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726114417_ChannelViewerSettings.cs index 411223b..6d0cd37 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726114417_ChannelViewerSettings.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726114417_ChannelViewerSettings.cs @@ -16,58 +16,53 @@ namespace TeleWave.Infrastructure.Migrations table: "Channels", type: "double precision", nullable: false, - defaultValue: 0.0); + defaultValue: 0.0 + ); migrationBuilder.AddColumn( name: "LogoCorner", table: "Channels", type: "integer", nullable: false, - defaultValue: 0); + defaultValue: 0 + ); migrationBuilder.AddColumn( name: "LogoImageId", table: "Channels", type: "uuid", - nullable: true); + nullable: true + ); migrationBuilder.AddColumn( name: "LogoOpacity", table: "Channels", type: "double precision", nullable: false, - defaultValue: 0.0); + defaultValue: 0.0 + ); migrationBuilder.AddColumn( name: "ShowClock", table: "Channels", type: "boolean", nullable: false, - defaultValue: false); + defaultValue: false + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropColumn( - name: "AnalogFilterStrength", - table: "Channels"); + migrationBuilder.DropColumn(name: "AnalogFilterStrength", table: "Channels"); - migrationBuilder.DropColumn( - name: "LogoCorner", - table: "Channels"); + migrationBuilder.DropColumn(name: "LogoCorner", table: "Channels"); - migrationBuilder.DropColumn( - name: "LogoImageId", - table: "Channels"); + migrationBuilder.DropColumn(name: "LogoImageId", table: "Channels"); - migrationBuilder.DropColumn( - name: "LogoOpacity", - table: "Channels"); + migrationBuilder.DropColumn(name: "LogoOpacity", table: "Channels"); - migrationBuilder.DropColumn( - name: "ShowClock", - table: "Channels"); + migrationBuilder.DropColumn(name: "ShowClock", table: "Channels"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726115300_ScheduleEntryCollection.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726115300_ScheduleEntryCollection.cs index ddcbb33..95792b3 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726115300_ScheduleEntryCollection.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726115300_ScheduleEntryCollection.cs @@ -15,15 +15,14 @@ namespace TeleWave.Infrastructure.Migrations name: "CollectionId", table: "ScheduleEntries", type: "uuid", - nullable: true); + nullable: true + ); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropColumn( - name: "CollectionId", - table: "ScheduleEntries"); + migrationBuilder.DropColumn(name: "CollectionId", table: "ScheduleEntries"); } } } diff --git a/backend/src/TeleWave.Infrastructure/Migrations/20260726190050_ShowAudienceMpaa.cs b/backend/src/TeleWave.Infrastructure/Migrations/20260726190050_ShowAudienceMpaa.cs index dee7790..2792122 100644 --- a/backend/src/TeleWave.Infrastructure/Migrations/20260726190050_ShowAudienceMpaa.cs +++ b/backend/src/TeleWave.Infrastructure/Migrations/20260726190050_ShowAudienceMpaa.cs @@ -16,7 +16,8 @@ namespace TeleWave.Infrastructure.Migrations type: "integer", nullable: true, oldClrType: typeof(int), - oldType: "integer"); + oldType: "integer" + ); } /// @@ -30,7 +31,8 @@ namespace TeleWave.Infrastructure.Migrations defaultValue: 0, oldClrType: typeof(int), oldType: "integer", - oldNullable: true); + oldNullable: true + ); } } } diff --git a/backend/src/TeleWave.Infrastructure/Persistence/Configurations/GroupConfiguration.cs b/backend/src/TeleWave.Infrastructure/Persistence/Configurations/GroupConfiguration.cs index 73b44f2..21f5953 100644 --- a/backend/src/TeleWave.Infrastructure/Persistence/Configurations/GroupConfiguration.cs +++ b/backend/src/TeleWave.Infrastructure/Persistence/Configurations/GroupConfiguration.cs @@ -30,12 +30,14 @@ public class GroupItemConfiguration : IEntityTypeConfiguration { builder.HasIndex(x => new { x.GroupId, x.Position }); // Элемент входит в группу не более одного раза — иначе вес и порядок становятся неоднозначны. - builder.HasIndex(x => new - { - x.GroupId, - x.ElementKind, - x.ElementId, - }).IsUnique(); + builder + .HasIndex(x => new + { + x.GroupId, + x.ElementKind, + x.ElementId, + }) + .IsUnique(); // По этому индексу чистятся позиции при удалении шоу/коллекции: внешнего ключа на // полиморфную ссылку нет, удаление идёт командой. diff --git a/backend/src/TeleWave.Infrastructure/Settings/SiteSettings.cs b/backend/src/TeleWave.Infrastructure/Settings/SiteSettings.cs index 3c869f8..626d5ef 100644 --- a/backend/src/TeleWave.Infrastructure/Settings/SiteSettings.cs +++ b/backend/src/TeleWave.Infrastructure/Settings/SiteSettings.cs @@ -33,7 +33,11 @@ public sealed class SiteSettings(IAppDbContext dbContext) : ISiteSettings dbContext.GetBoolSettingAsync(SettingKeys.ChannelNumbersEnabled, false, cancellationToken); public Task SetChannelNumbersEnabledAsync(bool enabled, CancellationToken cancellationToken) => - UpsertAsync(SettingKeys.ChannelNumbersEnabled, enabled ? "true" : "false", cancellationToken); + UpsertAsync( + SettingKeys.ChannelNumbersEnabled, + enabled ? "true" : "false", + cancellationToken + ); private async Task UpsertAsync(string key, string value, CancellationToken cancellationToken) { diff --git a/backend/tests/TeleWave.Application.Tests/Broadcast/ChannelHandlersTests.cs b/backend/tests/TeleWave.Application.Tests/Broadcast/ChannelHandlersTests.cs index e265282..0b28eef 100644 --- a/backend/tests/TeleWave.Application.Tests/Broadcast/ChannelHandlersTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Broadcast/ChannelHandlersTests.cs @@ -35,9 +35,6 @@ public class ChannelHandlersTests Assert.Equal(ChannelErrors.DuplicateSlug, dup.Error); } - - - [Fact] public async Task UpdateChannelSettings_UpdatesBumperChances() { @@ -69,7 +66,4 @@ public class ChannelHandlersTests Assert.Equal(BumperFont.Sans, stored!.BumperFont); Assert.Equal(BumperSelection.WeightedRandom, stored.BumperSelection); } - - - } diff --git a/backend/tests/TeleWave.Application.Tests/Broadcast/QueryHandlersTests.cs b/backend/tests/TeleWave.Application.Tests/Broadcast/QueryHandlersTests.cs index 0b84724..c382fe3 100644 --- a/backend/tests/TeleWave.Application.Tests/Broadcast/QueryHandlersTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Broadcast/QueryHandlersTests.cs @@ -24,7 +24,6 @@ public class QueryHandlersTests private static GroupMembershipCleaner GroupCleaner(IAppDbContext db) => new(db, new GroupStatsService(db, new GroupElementResolver(db))); - [Fact] public async Task GetChannel_UnknownId_ReturnsNotFound() { @@ -152,7 +151,6 @@ public class QueryHandlersTests Assert.True(ok.IsSuccess); } - [Fact] public async Task AddAndRemoveBumperTemplate_WorkThroughStorage() { diff --git a/backend/tests/TeleWave.Application.Tests/Media/ImportManualInboxValidatorTests.cs b/backend/tests/TeleWave.Application.Tests/Media/ImportManualInboxValidatorTests.cs index 7c13b3b..5fa1f7a 100644 --- a/backend/tests/TeleWave.Application.Tests/Media/ImportManualInboxValidatorTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Media/ImportManualInboxValidatorTests.cs @@ -16,7 +16,9 @@ public class ImportManualInboxValidatorTests [InlineData(null, null)] // номера не заданы — сервер разберёт имя сам public void AllowsRealWorldNumbers(int? season, int? episode) { - Assert.True(new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid); + Assert.True( + new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid + ); } [Theory] @@ -26,7 +28,9 @@ public class ImportManualInboxValidatorTests [InlineData(1, 1000)] public void RejectsOutOfRange(int? season, int? episode) { - Assert.False(new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid); + Assert.False( + new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid + ); } [Fact] diff --git a/backend/tests/TeleWave.Application.Tests/Media/MediaStatsTests.cs b/backend/tests/TeleWave.Application.Tests/Media/MediaStatsTests.cs index 50b7c10..7663a1b 100644 --- a/backend/tests/TeleWave.Application.Tests/Media/MediaStatsTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Media/MediaStatsTests.cs @@ -22,7 +22,16 @@ public class MediaStatsTests var a = Pending(name); a.MarkProcessing(); a.MarkReady( - new MediaReadyInfo(TimeSpan.FromMinutes(20), 2, 600, 1920, 1080, "h264", "aac", "assets/x") + new MediaReadyInfo( + TimeSpan.FromMinutes(20), + 2, + 600, + 1920, + 1080, + "h264", + "aac", + "assets/x" + ) ); return a; } diff --git a/backend/tests/TeleWave.Application.Tests/Metadata/ApplyShowMetadataTests.cs b/backend/tests/TeleWave.Application.Tests/Metadata/ApplyShowMetadataTests.cs index a6467b4..a50596a 100644 --- a/backend/tests/TeleWave.Application.Tests/Metadata/ApplyShowMetadataTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Metadata/ApplyShowMetadataTests.cs @@ -26,9 +26,7 @@ public class ApplyShowMetadataTests var result = await ApplyAsync(arranged); Assert.True(result); - await arranged - .Provider.Received(1) - .GetShowAsync("42", kind, Arg.Any()); + await arranged.Provider.Received(1).GetShowAsync("42", kind, Arg.Any()); } [Fact] @@ -48,7 +46,10 @@ public class ApplyShowMetadataTests // «Not Rated» — это отсутствие данных. Снять им проставленный рейтинг нельзя: обновление // метаданных тихо открыло бы взрослому шоу дорогу в детское время. var arranged = await ArrangeAsync(ShowKind.Single, ShowAudience.R); - Respond(arranged.Provider, new ShowMetadata("42", "A", 2000, null, null, null, "Not Rated")); + Respond( + arranged.Provider, + new ShowMetadata("42", "A", 2000, null, null, null, "Not Rated") + ); await ApplyAsync(arranged); @@ -63,11 +64,7 @@ public class ApplyShowMetadataTests Assert.False(await ApplyAsync(arranged)); await arranged .Provider.DidNotReceive() - .GetShowAsync( - Arg.Any(), - Arg.Any(), - Arg.Any() - ); + .GetShowAsync(Arg.Any(), Arg.Any(), Arg.Any()); } private static void Respond(IMetadataProvider provider, ShowMetadata meta) => diff --git a/backend/tests/TeleWave.Application.Tests/Programming/LayerApplicabilityTests.cs b/backend/tests/TeleWave.Application.Tests/Programming/LayerApplicabilityTests.cs index 43aba33..0a59448 100644 --- a/backend/tests/TeleWave.Application.Tests/Programming/LayerApplicabilityTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Programming/LayerApplicabilityTests.cs @@ -38,9 +38,7 @@ public class LayerApplicabilityTests { // «20 декабря — 8 января» задаётся один раз и работает в любом году, поэтому сравнение идёт // по паре (месяц, день), а не по датам. - var applicability = new LayerApplicability( - AnnualRanges: [new AnnualRange(12, 20, 1, 8)] - ); + var applicability = new LayerApplicability(AnnualRanges: [new AnnualRange(12, 20, 1, 8)]); Assert.Equal(expected, applicability.Covers(new DateOnly(year, month, day))); } @@ -128,8 +126,12 @@ public class LayerApplicabilityTests Assert.Empty(Build(template)); } - private static void AddSlot(GridLayer layer, string title, TimeOnly start, int durationMinutes) => - layer.AddSlot(title, start, durationMinutes); + private static void AddSlot( + GridLayer layer, + string title, + TimeOnly start, + int durationMinutes + ) => layer.AddSlot(title, start, durationMinutes); private static IReadOnlyList Build( ScheduleTemplate template, diff --git a/backend/tests/TeleWave.Application.Tests/Programming/PlanningRulesTests.cs b/backend/tests/TeleWave.Application.Tests/Programming/PlanningRulesTests.cs index b780d45..c5c8a57 100644 --- a/backend/tests/TeleWave.Application.Tests/Programming/PlanningRulesTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Programming/PlanningRulesTests.cs @@ -15,9 +15,9 @@ public class PlanningRulesTests [InlineData(2, 0, false)] public void AudienceAt_DayWindow(int hour, int minute, bool inside) { - var rules = new PlanningRules( - [new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.Pg13)] - ); + var rules = new PlanningRules([ + new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.Pg13), + ]); var result = rules.AudienceAt(new TimeOnly(hour, minute)); @@ -31,9 +31,9 @@ public class PlanningRulesTests public void AudienceAt_WindowCrossingMidnight(int hour, int minute, bool inside) { // «С 23:00 до 06:00» — ночное окно, границы сравниваются в обратную сторону. - var rules = new PlanningRules( - [new AudienceWindow(new TimeOnly(23, 0), new TimeOnly(6, 0), ShowAudience.Nc17)] - ); + var rules = new PlanningRules([ + new AudienceWindow(new TimeOnly(23, 0), new TimeOnly(6, 0), ShowAudience.Nc17), + ]); var result = rules.AudienceAt(new TimeOnly(hour, minute)); @@ -44,12 +44,10 @@ public class PlanningRulesTests public void AudienceAt_OverlappingWindows_TakesTheStrictest() { // Широкое окно, случайно наложенное поверх детского, не должно его отменять. - var rules = new PlanningRules( - [ - new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.R), - new AudienceWindow(new TimeOnly(7, 0), new TimeOnly(10, 0), ShowAudience.G), - ] - ); + var rules = new PlanningRules([ + new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.R), + new AudienceWindow(new TimeOnly(7, 0), new TimeOnly(10, 0), ShowAudience.G), + ]); Assert.Equal(ShowAudience.G, rules.AudienceAt(new TimeOnly(8, 0))); Assert.Equal(ShowAudience.R, rules.AudienceAt(new TimeOnly(12, 0))); @@ -90,9 +88,9 @@ public class PlanningRulesTests // Рейтинг уезжает в jsonb шаблона и в API ровно тем написанием, каким приходит от источников. // Round-trip этого не поймает: он одинаково зелёный и на «Pg13», а такое значение потом // придётся переводить на каждой границе. - var json = new PlanningRules( - [new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.Pg13)] - ).ToJson(); + var json = new PlanningRules([ + new AudienceWindow(new TimeOnly(6, 0), new TimeOnly(23, 0), ShowAudience.Pg13), + ]).ToJson(); Assert.Contains("\"PG-13\"", json, StringComparison.Ordinal); } diff --git a/backend/tests/TeleWave.Application.Tests/Validators/ValidatorTests.cs b/backend/tests/TeleWave.Application.Tests/Validators/ValidatorTests.cs index 0712d73..2e09dba 100644 --- a/backend/tests/TeleWave.Application.Tests/Validators/ValidatorTests.cs +++ b/backend/tests/TeleWave.Application.Tests/Validators/ValidatorTests.cs @@ -10,7 +10,6 @@ namespace TeleWave.Application.Tests.Validators; public class ValidatorTests { - [Fact] public void UpdateBumperTextVariant_ChecksLengthsAndWeight() { @@ -55,7 +54,6 @@ public class ValidatorTests Assert.False(v.Validate(good with { Name = "" }).IsValid); } - [Fact] public void ResetUserPassword_RequiresMinLength() { diff --git a/backend/tests/TeleWave.Domain.Tests/Media/MediaAssetTests.cs b/backend/tests/TeleWave.Domain.Tests/Media/MediaAssetTests.cs index 1b7328a..faae281 100644 --- a/backend/tests/TeleWave.Domain.Tests/Media/MediaAssetTests.cs +++ b/backend/tests/TeleWave.Domain.Tests/Media/MediaAssetTests.cs @@ -67,7 +67,16 @@ public class MediaAssetTests Assert.Null(asset.ProcessingDuration); asset.MarkReady( - new MediaReadyInfo(TimeSpan.FromSeconds(120), 2, 60, 1920, 1080, "h264", "aac", "assets/abc") + new MediaReadyInfo( + TimeSpan.FromSeconds(120), + 2, + 60, + 1920, + 1080, + "h264", + "aac", + "assets/abc" + ) ); Assert.NotNull(asset.ProcessingDuration); @@ -80,7 +89,16 @@ public class MediaAssetTests var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload); asset.MarkReady( - new MediaReadyInfo(TimeSpan.FromSeconds(120), 2, 60, 1920, 1080, "h264", "aac", "assets/abc") + new MediaReadyInfo( + TimeSpan.FromSeconds(120), + 2, + 60, + 1920, + 1080, + "h264", + "aac", + "assets/abc" + ) ); Assert.Null(asset.ProcessingDuration); diff --git a/backend/tests/TeleWave.Domain.Tests/Programming/CandidateFilterTests.cs b/backend/tests/TeleWave.Domain.Tests/Programming/CandidateFilterTests.cs index b010ee3..8613906 100644 --- a/backend/tests/TeleWave.Domain.Tests/Programming/CandidateFilterTests.cs +++ b/backend/tests/TeleWave.Domain.Tests/Programming/CandidateFilterTests.cs @@ -125,7 +125,11 @@ public class CandidateFilterTests var teen = Element(ShowAudience.Pg13, position: 1); var pick = ElementSelector.Select( - Slot([adult, teen], maxAudience: ShowAudience.Pg13, strategy: SlotStrategyKind.Sequential), + Slot( + [adult, teen], + maxAudience: ShowAudience.Pg13, + strategy: SlotStrategyKind.Sequential + ), T0, new FirstAlways() ); @@ -193,9 +197,16 @@ public class CandidateFilterTests lastPlayed: T0.AddDays(-10), recentPlays: [T0.AddDays(-10), T0.AddDays(-9), T0.AddDays(-8)] ); - var recent = Element(position: 1, lastPlayed: T0.AddHours(-1), recentPlays: [T0.AddHours(-1)]); + var recent = Element( + position: 1, + lastPlayed: T0.AddHours(-1), + recentPlays: [T0.AddHours(-1)] + ); - var slot = Slot([overCap, recent], repeatLimit: new RepeatLimit(WindowDays: 30, Max: 2)) with + var slot = Slot( + [overCap, recent], + repeatLimit: new RepeatLimit(WindowDays: 30, Max: 2) + ) with { Strategy = new PlanningStrategy(SlotStrategyKind.RandomWithCooldown, CooldownDays: 2), }; diff --git a/backend/tests/TeleWave.Domain.Tests/Programming/GoldenScheduleTests.cs b/backend/tests/TeleWave.Domain.Tests/Programming/GoldenScheduleTests.cs index 0b86817..ea8c05f 100644 --- a/backend/tests/TeleWave.Domain.Tests/Programming/GoldenScheduleTests.cs +++ b/backend/tests/TeleWave.Domain.Tests/Programming/GoldenScheduleTests.cs @@ -1,10 +1,10 @@ using System.Globalization; using System.Text; using TeleWave.Domain.Broadcast.Scheduling; -using GridPlanner = TeleWave.Domain.Programming.Planning.SchedulePlanner; using TeleWave.Domain.Programming; using TeleWave.Domain.Programming.Planning; using Xunit; +using GridPlanner = TeleWave.Domain.Programming.Planning.SchedulePlanner; namespace TeleWave.Domain.Tests.Programming; @@ -43,9 +43,10 @@ public class GoldenScheduleTests .Items.OrderBy(i => i.StartsAtUtc) .Select(item => { - var label = item.ShowId is { } showId && names.TryGetValue(showId, out var name) - ? $"{name}#{item.UnitIndex}" - : item.Kind.ToString(); + var label = + item.ShowId is { } showId && names.TryGetValue(showId, out var name) + ? $"{name}#{item.UnitIndex}" + : item.Kind.ToString(); return string.Create( CultureInfo.InvariantCulture, $"{item.StartsAtUtc:HH:mm} {label}" @@ -60,10 +61,7 @@ public class GoldenScheduleTests .Range(0, episodes) .Select(i => new PlanningUnit(Guid.NewGuid(), TimeSpan.FromMinutes(minutes), showId, i)) .ToList(); - return ( - new PlanningElement(GroupElementKind.Show, Guid.NewGuid(), 1, 0, units), - showId - ); + return (new PlanningElement(GroupElementKind.Show, Guid.NewGuid(), 1, 0, units), showId); } private static PlanningSlot ContentSlot( @@ -129,12 +127,7 @@ public class GoldenScheduleTests .ToList(); Assert.Equal( - [ - "07:00 Мультфильмы#0", - "07:20 Мультфильмы#1", - "07:40 Мультфильмы#2", - "20:00 Кино#0", - ], + ["07:00 Мультфильмы#0", "07:20 Мультфильмы#1", "07:40 Мультфильмы#2", "20:00 Кино#0"], tape ); } @@ -148,9 +141,7 @@ public class GoldenScheduleTests // и разбег накапливается, пока его не подберёт следующий целевой старт. var slots = Enumerable .Range(0, 3) - .Select(i => - ContentSlot(Day.AddHours(i), 60, [series], SlotBlockMode.Count, 2) - ) + .Select(i => ContentSlot(Day.AddHours(i), 60, [series], SlotBlockMode.Count, 2)) .ToArray(); var input = new PlanningInput( diff --git a/backend/tests/TeleWave.Domain.Tests/Programming/JunctionFillerTests.cs b/backend/tests/TeleWave.Domain.Tests/Programming/JunctionFillerTests.cs index 10816c7..49e4460 100644 --- a/backend/tests/TeleWave.Domain.Tests/Programming/JunctionFillerTests.cs +++ b/backend/tests/TeleWave.Domain.Tests/Programming/JunctionFillerTests.cs @@ -22,10 +22,7 @@ public class JunctionFillerTests { showId = Guid.NewGuid(); var id = showId; - var units = Enumerable - .Range(0, episodes) - .Select(i => Unit(minutes, id, i)) - .ToList(); + var units = Enumerable.Range(0, episodes).Select(i => Unit(minutes, id, i)).ToList(); return new PlanningElement(GroupElementKind.Show, Guid.NewGuid(), 1, 0, units); } diff --git a/backend/tests/TeleWave.Domain.Tests/Programming/SchedulePlannerTests.cs b/backend/tests/TeleWave.Domain.Tests/Programming/SchedulePlannerTests.cs index 843b470..9f9bfb1 100644 --- a/backend/tests/TeleWave.Domain.Tests/Programming/SchedulePlannerTests.cs +++ b/backend/tests/TeleWave.Domain.Tests/Programming/SchedulePlannerTests.cs @@ -116,7 +116,10 @@ public class SchedulePlannerTests { var element = Element(10, 20); var result = Run( - Input([Slot(T0, 300, [element], SlotBlockMode.Duration, blockValue: 50)], horizonHours: 2) + Input( + [Slot(T0, 300, [element], SlotBlockMode.Duration, blockValue: 50)], + horizonHours: 2 + ) ); // 20+20 < 50, третья добирает до 60 — обрезать видеофайл нельзя. diff --git a/backend/tests/TeleWave.Integration.Tests/GridScheduleGeneratorIntegrationTests.cs b/backend/tests/TeleWave.Integration.Tests/GridScheduleGeneratorIntegrationTests.cs index b57d1c3..a5ed784 100644 --- a/backend/tests/TeleWave.Integration.Tests/GridScheduleGeneratorIntegrationTests.cs +++ b/backend/tests/TeleWave.Integration.Tests/GridScheduleGeneratorIntegrationTests.cs @@ -60,7 +60,9 @@ public sealed class GridScheduleGeneratorIntegrationTests(PostgresFixture fixtur Assert.True(state.NextUnitIndex > 0); // И шаблон помечен применённым: баннер «правила изменены» должен погаснуть. - Assert.False(verify.ScheduleTemplates.Single(t => t.Id == world.TemplateId).HasPendingChanges); + Assert.False( + verify.ScheduleTemplates.Single(t => t.Id == world.TemplateId).HasPendingChanges + ); } [SkippableFact] @@ -154,7 +156,9 @@ public sealed class GridScheduleGeneratorIntegrationTests(PostgresFixture fixtur Assert.Empty(verify.ScheduleEntries.Where(e => e.ChannelId == world.ChannelId)); Assert.Empty(verify.SlotStates.Where(s => s.SlotId == world.SlotId)); // Отметку о применении сухой прогон тоже не ставит: применять по-прежнему есть что. - Assert.True(verify.ScheduleTemplates.Single(t => t.Id == world.TemplateId).HasPendingChanges); + Assert.True( + verify.ScheduleTemplates.Single(t => t.Id == world.TemplateId).HasPendingChanges + ); } [SkippableFact] diff --git a/backend/tests/TeleWave.Integration.Tests/ManualInboxIntegrationTests.cs b/backend/tests/TeleWave.Integration.Tests/ManualInboxIntegrationTests.cs index 7751495..7ac8a40 100644 --- a/backend/tests/TeleWave.Integration.Tests/ManualInboxIntegrationTests.cs +++ b/backend/tests/TeleWave.Integration.Tests/ManualInboxIntegrationTests.cs @@ -29,12 +29,10 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture) var storage = Substitute.For(); storage .ListManualInbox(Arg.Any()) - .Returns( - [ - new IMediaStorage.ManualInboxFile($"Сериал/{first}", first, 1000), - new IMediaStorage.ManualInboxFile($"Сериал/{second}", second, 1000), - ] - ); + .Returns([ + new IMediaStorage.ManualInboxFile($"Сериал/{first}", first, 1000), + new IMediaStorage.ManualInboxFile($"Сериал/{second}", second, 1000), + ]); await using var db = fixture.CreateContext(); var result = await new ImportManualInboxCommandHandler( @@ -101,12 +99,10 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture) var storage = Substitute.For(); storage .ListManualInbox(Arg.Any()) - .Returns( - [ - new IMediaStorage.ManualInboxFile(good, good, 1000), - new IMediaStorage.ManualInboxFile("readme.txt", "readme.txt", 10), - ] - ); + .Returns([ + new IMediaStorage.ManualInboxFile(good, good, 1000), + new IMediaStorage.ManualInboxFile("readme.txt", "readme.txt", 10), + ]); await using var db = fixture.CreateContext(); var result = await new ImportManualInboxCommandHandler( @@ -148,7 +144,10 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture) db, storage, Substitute.For() - ).Handle(new ImportManualInboxCommand([new ManualImportItem(name, 4, 12)], showId), default); + ).Handle( + new ImportManualInboxCommand([new ManualImportItem(name, 4, 12)], showId), + default + ); Assert.True(result.IsSuccess); await db.SaveChangesAsync(); diff --git a/backend/tests/TeleWave.Integration.Tests/ManualInboxStorageTests.cs b/backend/tests/TeleWave.Integration.Tests/ManualInboxStorageTests.cs index 3eb0537..cd065d8 100644 --- a/backend/tests/TeleWave.Integration.Tests/ManualInboxStorageTests.cs +++ b/backend/tests/TeleWave.Integration.Tests/ManualInboxStorageTests.cs @@ -147,7 +147,10 @@ public sealed class ManualInboxStorageTests : IDisposable private void Write(string relativePath) { - var full = Path.Combine(_paths.ManualDir, relativePath.Replace('/', Path.DirectorySeparatorChar)); + var full = Path.Combine( + _paths.ManualDir, + relativePath.Replace('/', Path.DirectorySeparatorChar) + ); Directory.CreateDirectory(Path.GetDirectoryName(full)!); File.WriteAllText(full, "x"); } diff --git a/backend/tests/TeleWave.Integration.Tests/TemplateOperationsIntegrationTests.cs b/backend/tests/TeleWave.Integration.Tests/TemplateOperationsIntegrationTests.cs index fc57d9f..d319c83 100644 --- a/backend/tests/TeleWave.Integration.Tests/TemplateOperationsIntegrationTests.cs +++ b/backend/tests/TeleWave.Integration.Tests/TemplateOperationsIntegrationTests.cs @@ -100,7 +100,11 @@ public sealed class TemplateOperationsIntegrationTests(PostgresFixture fixture) // Канал из старой ротации: сетки нет, ссылки на неё тоже. await using var seedDb = fixture.CreateContext(); var suffix = Guid.NewGuid().ToString("N")[..8]; - var channel = Channel.Create($"Без сетки {suffix}", $"nogrid-{suffix}", DateTimeOffset.UtcNow); + var channel = Channel.Create( + $"Без сетки {suffix}", + $"nogrid-{suffix}", + DateTimeOffset.UtcNow + ); seedDb.Channels.Add(channel); await seedDb.SaveChangesAsync(); @@ -131,7 +135,9 @@ public sealed class TemplateOperationsIntegrationTests(PostgresFixture fixture) } /// Два канала: у источника слой со слотом, группой и стыком; у приёмника — пустая сетка. - private static async Task<(Guid Source, Guid Target, Guid GroupId)> SeedPairAsync(AppDbContext db) + private static async Task<(Guid Source, Guid Target, Guid GroupId)> SeedPairAsync( + AppDbContext db + ) { var suffix = Guid.NewGuid().ToString("N")[..8]; diff --git a/backend/tests/TeleWave.Integration.Tests/TransactionIntegrationTests.cs b/backend/tests/TeleWave.Integration.Tests/TransactionIntegrationTests.cs index b7fe261..53aad73 100644 --- a/backend/tests/TeleWave.Integration.Tests/TransactionIntegrationTests.cs +++ b/backend/tests/TeleWave.Integration.Tests/TransactionIntegrationTests.cs @@ -53,7 +53,16 @@ public sealed class TransactionIntegrationTests(PostgresFixture fixture) var show = Show.Create("Show", ShowKind.Series); var asset = MediaAsset.Register("ep.mkv", ".mkv", MediaSource.Upload); asset.MarkReady( - new MediaReadyInfo(TimeSpan.FromMinutes(20), 2, 600, 1920, 1080, "h264", "aac", "assets/x") + new MediaReadyInfo( + TimeSpan.FromMinutes(20), + 2, + 600, + 1920, + 1080, + "h264", + "aac", + "assets/x" + ) ); show.AddEpisode(asset.Id); var entry = ScheduleEntry.Program(