Refactor IPTV endpoint logic for improved readability and maintainability
Consolidated channel and programme XML writing into dedicated methods, WriteChannel and WriteProgramme, enhancing code clarity and reducing duplication. Introduced a WriteIcon method to streamline icon handling for both channels and programmes. Updated GetChannelScheduleQueryHandler to utilize a new FranchisePosition record for better representation of franchise details in schedule entries, improving the overall structure and readability of the code.
This commit is contained in:
+34
-26
@@ -97,13 +97,12 @@ public sealed class GetChannelScheduleQueryHandler(IAppDbContext dbContext)
|
||||
join collection in dbContext.Collections.AsNoTracking()
|
||||
on item.CollectionId equals collection.Id
|
||||
where collectionIds.Contains(item.CollectionId)
|
||||
select new
|
||||
{
|
||||
select new CollectionPart(
|
||||
item.CollectionId,
|
||||
item.ShowId,
|
||||
item.Position,
|
||||
collection.Name,
|
||||
}
|
||||
collection.Name
|
||||
)
|
||||
).ToListAsync(cancellationToken);
|
||||
var partsByCollection = collectionParts
|
||||
.GroupBy(p => p.CollectionId)
|
||||
@@ -120,25 +119,7 @@ public sealed class GetChannelScheduleQueryHandler(IAppDbContext dbContext)
|
||||
bumperText = BumperText(bumper.RenderedLinesJson);
|
||||
}
|
||||
|
||||
// Номер части ищем по позиции шоу в коллекции, а не по индексу записи: франшизу могли
|
||||
// переупорядочить, и «часть 2» обязана означать вторую в текущем составе.
|
||||
int? part = null;
|
||||
int? parts = null;
|
||||
string? collectionName = null;
|
||||
if (
|
||||
e.CollectionId is { } collectionId
|
||||
&& e.ShowId is { } showId
|
||||
&& partsByCollection.TryGetValue(collectionId, out var ordered)
|
||||
)
|
||||
{
|
||||
var at = ordered.FindIndex(p => p.ShowId == showId);
|
||||
if (at >= 0)
|
||||
{
|
||||
part = at + 1;
|
||||
parts = ordered.Count;
|
||||
collectionName = ordered[0].Name;
|
||||
}
|
||||
}
|
||||
var franchise = FranchisePart(partsByCollection, e.CollectionId, e.ShowId);
|
||||
|
||||
dtos.Add(
|
||||
new ScheduleEntryDto(
|
||||
@@ -155,9 +136,9 @@ public sealed class GetChannelScheduleQueryHandler(IAppDbContext dbContext)
|
||||
: null,
|
||||
bumperName,
|
||||
bumperText,
|
||||
part,
|
||||
parts,
|
||||
collectionName
|
||||
franchise?.Part,
|
||||
franchise?.Total,
|
||||
franchise?.Name
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -165,6 +146,33 @@ public sealed class GetChannelScheduleQueryHandler(IAppDbContext dbContext)
|
||||
return Result.Success<IReadOnlyList<ScheduleEntryDto>>(dtos);
|
||||
}
|
||||
|
||||
/// <summary>Место записи во франшизе: «часть N из M» и её название.</summary>
|
||||
private sealed record FranchisePosition(int Part, int Total, string Name);
|
||||
|
||||
/// <summary>
|
||||
/// Какой частью коллекции шла запись. Номер ищется по позиции шоу в текущем составе, а не по
|
||||
/// индексу записи: франшизу могли переупорядочить, и «часть 2» обязана означать вторую сейчас.
|
||||
/// </summary>
|
||||
private static FranchisePosition? FranchisePart(
|
||||
IReadOnlyDictionary<Guid, List<CollectionPart>> partsByCollection,
|
||||
Guid? collectionId,
|
||||
Guid? showId
|
||||
)
|
||||
{
|
||||
if (
|
||||
collectionId is not { } id
|
||||
|| showId is not { } show
|
||||
|| !partsByCollection.TryGetValue(id, out var ordered)
|
||||
)
|
||||
return null;
|
||||
|
||||
var at = ordered.FindIndex(p => p.ShowId == show);
|
||||
return at < 0 ? null : new FranchisePosition(at + 1, ordered.Count, ordered[0].Name);
|
||||
}
|
||||
|
||||
/// <summary>Позиция шоу в коллекции вместе с её названием — то, чем считается номер части.</summary>
|
||||
private sealed record CollectionPart(Guid CollectionId, Guid ShowId, int Position, string Name);
|
||||
|
||||
/// <summary>Строки сыгравшей заставки одной меткой для расписания; null — показывать нечего.</summary>
|
||||
private static string? BumperText(string? renderedLinesJson)
|
||||
{
|
||||
|
||||
@@ -102,11 +102,10 @@ public sealed class GetIptvGuideQueryHandler(IAppDbContext dbContext)
|
||||
// Серии одного шоу встык — это один блок программы. Склеиваем по id, а не по
|
||||
// названию: у разных шоу оно может совпасть. Разрыв во времени блок рвёт — между
|
||||
// выходами шла реклама, и объявлять это одной передачей нельзя.
|
||||
if (
|
||||
lastShowId == entry.ShowId
|
||||
&& programmes.Count > 0
|
||||
&& programmes[^1].EndsAtUtc == entry.StartsAtUtc
|
||||
)
|
||||
//
|
||||
// Непустоту списка не проверяем: lastShowId выставляется только вместе с добавленной
|
||||
// передачей, и совпасть с ним на пустом списке нечему.
|
||||
if (lastShowId == entry.ShowId && programmes[^1].EndsAtUtc == entry.StartsAtUtc)
|
||||
{
|
||||
programmes[^1] = programmes[^1] with { EndsAtUtc = entry.EndsAtUtc };
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user