Refactor IPTV endpoint logic for improved readability and maintainability
ci / build-backend (push) Successful in 1m34s
ci / build-frontend (push) Successful in 55s
ci / tests (push) Successful in 1m43s
ci / sonar (push) Successful in 4m38s

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:
Leonid Pershin
2026-07-30 01:37:20 +03:00
parent 8119305c36
commit bd89abf24b
3 changed files with 91 additions and 69 deletions
@@ -151,46 +151,14 @@ public static class IptvEndpoints
writer.WriteStartElement("tv");
writer.WriteAttributeString("generator-info-name", "TeleWave");
// Сначала все каналы, потом все передачи: XMLTV требует именно такого порядка секций.
foreach (var channel in channels)
WriteChannel(writer, channel, origin);
foreach (var channel in channels)
{
writer.WriteStartElement("channel");
writer.WriteAttributeString("id", channel.Slug);
writer.WriteElementString("display-name", channel.Name);
if (channel.Number is { } number)
writer.WriteElementString(
"display-name",
number.ToString(CultureInfo.InvariantCulture)
);
if (channel.LogoImageId is { } logoId)
{
writer.WriteStartElement("icon");
writer.WriteAttributeString("src", $"{origin}/api/images/{logoId}");
writer.WriteEndElement();
}
writer.WriteEndElement();
}
foreach (var channel in channels)
foreach (var programme in channel.Programmes)
{
writer.WriteStartElement("programme");
writer.WriteAttributeString("start", XmltvTime(programme.StartsAtUtc));
writer.WriteAttributeString("stop", XmltvTime(programme.EndsAtUtc));
writer.WriteAttributeString("channel", channel.Slug);
writer.WriteElementString("title", programme.Title);
if (!string.IsNullOrWhiteSpace(programme.SubTitle))
writer.WriteElementString("sub-title", programme.SubTitle);
if (!string.IsNullOrWhiteSpace(programme.Description))
writer.WriteElementString("desc", programme.Description);
if (programme.ImageId is { } imageId)
{
writer.WriteStartElement("icon");
writer.WriteAttributeString("src", $"{origin}/api/images/{imageId}");
writer.WriteEndElement();
}
writer.WriteEndElement();
foreach (var programme in channel.Programmes)
WriteProgramme(writer, channel.Slug, programme, origin);
}
writer.WriteEndElement();
@@ -200,6 +168,53 @@ public static class IptvEndpoints
return output.ToString();
}
private static void WriteChannel(XmlWriter writer, IptvChannelDto channel, string origin)
{
writer.WriteStartElement("channel");
writer.WriteAttributeString("id", channel.Slug);
writer.WriteElementString("display-name", channel.Name);
// Номер вторым display-name: так плееры с нумерацией подхватывают его без своих настроек.
if (channel.Number is { } number)
writer.WriteElementString(
"display-name",
number.ToString(CultureInfo.InvariantCulture)
);
WriteIcon(writer, channel.LogoImageId, origin);
writer.WriteEndElement();
}
private static void WriteProgramme(
XmlWriter writer,
string slug,
IptvProgrammeDto programme,
string origin
)
{
writer.WriteStartElement("programme");
writer.WriteAttributeString("start", XmltvTime(programme.StartsAtUtc));
writer.WriteAttributeString("stop", XmltvTime(programme.EndsAtUtc));
writer.WriteAttributeString("channel", slug);
writer.WriteElementString("title", programme.Title);
if (!string.IsNullOrWhiteSpace(programme.SubTitle))
writer.WriteElementString("sub-title", programme.SubTitle);
if (!string.IsNullOrWhiteSpace(programme.Description))
writer.WriteElementString("desc", programme.Description);
WriteIcon(writer, programme.ImageId, origin);
writer.WriteEndElement();
}
private static void WriteIcon(XmlWriter writer, Guid? imageId, string origin)
{
if (imageId is not { } id)
return;
writer.WriteStartElement("icon");
writer.WriteAttributeString("src", $"{origin}/api/images/{id}");
writer.WriteEndElement();
}
/// <summary>Время XMLTV: <c>YYYYMMDDHHMMSS +0000</c>. Отдаём в UTC — плеер сдвинет сам.</summary>
private static string XmltvTime(DateTimeOffset moment) =>
moment.ToUniversalTime().ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture)