Compare commits

..

No commits in common. "0189cb929c9d6aefea45f8b72ffce16e439a6ce2" and "3ee62e24f6bd459f154ead65e0c9bab0d13e3e9b" have entirely different histories.

2 changed files with 16 additions and 83 deletions

View File

@ -19,12 +19,5 @@ namespace LME.Uaflix.Models
/// Перший елемент відповідає iframeUrl, наступні — додаткові плеєри (напр. з субтитрами) /// Перший елемент відповідає iframeUrl, наступні — додаткові плеєри (напр. з субтитрами)
/// </summary> /// </summary>
public List<string> zetvideoIframeUrls { get; set; } public List<string> zetvideoIframeUrls { get; set; }
/// <summary>
/// Епізод позначено як «Прем'єра» (ще не вийшов) на сторінці сезону.
/// У таких епізодів у vi-desc → vi-title зазначено "Прем'єра. ДД.ММ.РРРР".
/// ProbeSeasonPlayer не робитиме зайвого HTTP-запиту для таких епізодів.
/// </summary>
public bool IsPremiere { get; set; }
} }
} }

View File

@ -361,14 +361,6 @@ namespace LME.Uaflix
if (episode == null || string.IsNullOrWhiteSpace(episode.url)) if (episode == null || string.IsNullOrWhiteSpace(episode.url))
continue; continue;
// Пропускаємо епізоди, позначені як «Прем'єра» — вони ще не вийшли,
// робити зайвий HTTP-запит на сторінку епізоду не потрібно.
if (episode.IsPremiere)
{
_onLog($"ProbeSeasonPlayer: Пропускаю епізод {episode.episode} — позначено як прем'єра");
continue;
}
var probed = await ProbeEpisodePlayer(episode.url); var probed = await ProbeEpisodePlayer(episode.url);
if (probed == null) if (probed == null)
continue; continue;
@ -433,17 +425,6 @@ namespace LME.Uaflix
if (structure == null || string.IsNullOrWhiteSpace(playerType) || seasonEpisodes == null || seasonEpisodes.Count == 0) if (structure == null || string.IsNullOrWhiteSpace(playerType) || seasonEpisodes == null || seasonEpisodes.Count == 0)
return; return;
// Відфільтровуємо епізоди, що ще не вийшли (позначені як «Прем'єра»)
var availableEpisodes = seasonEpisodes.Where(e => !e.IsPremiere).ToList();
int filteredCount = seasonEpisodes.Count - availableEpisodes.Count;
if (filteredCount > 0)
_onLog($"AddVodSeasonEpisodes: Відфільтровано {filteredCount} прем'єрних епізодів із сезону {season}");
if (availableEpisodes.Count == 0)
{
_onLog($"AddVodSeasonEpisodes: Усі епізоди сезону {season} є прем'єрами, пропускаю");
return;
}
string displayName = playerType == "ashdi-vod" ? "Uaflix #3" : "Uaflix #2"; string displayName = playerType == "ashdi-vod" ? "Uaflix #3" : "Uaflix #2";
if (!structure.Voices.ContainsKey(displayName)) if (!structure.Voices.ContainsKey(displayName))
{ {
@ -456,7 +437,7 @@ namespace LME.Uaflix
}; };
} }
var episodes = availableEpisodes var episodes = seasonEpisodes
.OrderBy(ep => ep.episode) .OrderBy(ep => ep.episode)
.Select(ep => new EpisodeInfo .Select(ep => new EpisodeInfo
{ {
@ -1103,28 +1084,13 @@ namespace LME.Uaflix
parsedEpisode = episodeFromUrl; parsedEpisode = episodeFromUrl;
} }
var episode = new EpisodeLinkInfo episodes.Add(new EpisodeLinkInfo
{ {
url = episodeUrl, url = episodeUrl,
title = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim() ?? $"Епізод {parsedEpisode}", title = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim() ?? $"Епізод {parsedEpisode}",
season = parsedSeason, season = parsedSeason,
episode = parsedEpisode episode = parsedEpisode
}; });
// Перевірка на «Прем'єра» — епізод ще не вийшов, плеєра немає
var viDesc = episodeNode.SelectSingleNode(".//div[contains(@class, 'vi-desc')]");
if (viDesc != null)
{
var viTitle = viDesc.SelectSingleNode(".//div[contains(@class, 'vi-title')]");
string descText = viTitle?.InnerText?.Trim() ?? string.Empty;
if (descText.IndexOf("Прем'єра", StringComparison.OrdinalIgnoreCase) >= 0)
{
episode.IsPremiere = true;
_onLog($"ParseSeasonEpisodesFromHtml: Серія {parsedEpisode} позначена як прем'єра: '{descText}'");
}
}
episodes.Add(episode);
fallbackEpisode = Math.Max(fallbackEpisode, parsedEpisode + 1); fallbackEpisode = Math.Max(fallbackEpisode, parsedEpisode + 1);
} }
@ -1141,8 +1107,8 @@ namespace LME.Uaflix
if (season < 0) if (season < 0)
return null; return null;
// v3 — інвалідація старих структур, що містили прем'єрні серії // v2 — зміна кеш-ключа для інвалідації старих структур без multi-voice
string memKey = $"lme_uaflix:season-structure-v3:{serialUrl}:{season}"; string memKey = $"lme_uaflix:season-structure-v2:{serialUrl}:{season}";
if (_hybridCache.TryGetValue(memKey, out SerialAggregatedStructure cached)) if (_hybridCache.TryGetValue(memKey, out SerialAggregatedStructure cached))
{ {
_onLog($"GetSeasonStructure: Using cached structure for season={season}, url={serialUrl}"); _onLog($"GetSeasonStructure: Using cached structure for season={season}, url={serialUrl}");
@ -1209,24 +1175,13 @@ namespace LME.Uaflix
} }
else if (seasonProbe.PlayerType == "ashdi-vod" || seasonProbe.PlayerType == "zetvideo-vod") else if (seasonProbe.PlayerType == "ashdi-vod" || seasonProbe.PlayerType == "zetvideo-vod")
{ {
// Відфільтровуємо прем'єрні епізоди (ще не вийшли) перед додаванням у структуру
var seasonAvailable = seasonEpisodes.Where(e => !e.IsPremiere).ToList();
int filteredCount = seasonEpisodes.Count - seasonAvailable.Count;
if (filteredCount > 0)
_onLog($"GetSeasonStructure: Відфільтровано {filteredCount} прем'єрних епізодів із сезону {season}");
if (seasonAvailable.Count == 0)
{
_onLog($"GetSeasonStructure: Усі епізоди сезону {season} є прем'єрами, повертаю null");
return null;
}
// Створюємо базовий голос (перший плеєр) // Створюємо базовий голос (перший плеєр)
AddVodSeasonEpisodes(structure, seasonProbe.PlayerType, season, seasonAvailable); AddVodSeasonEpisodes(structure, seasonProbe.PlayerType, season, seasonEpisodes);
// Якщо є додаткові zetvideo плеєри — створюємо окремий голос для кожного // Якщо є додаткові zetvideo плеєри — створюємо окремий голос для кожного
if (seasonAvailable.Count > 0) if (seasonEpisodes != null && seasonEpisodes.Count > 0)
{ {
var firstEp = seasonAvailable.FirstOrDefault(e => e.zetvideoIframeUrls != null && e.zetvideoIframeUrls.Count > 1); var firstEp = seasonEpisodes.FirstOrDefault(e => e.zetvideoIframeUrls != null && e.zetvideoIframeUrls.Count > 1);
if (firstEp != null) if (firstEp != null)
{ {
// Додаткові плеєри починаються з індексу 1 // Додаткові плеєри починаються з індексу 1
@ -1235,7 +1190,7 @@ namespace LME.Uaflix
string extraVoiceName = GetZetvideoVoiceName(extraIdx); string extraVoiceName = GetZetvideoVoiceName(extraIdx);
_onLog($"GetSeasonStructure: створюю додатковий голос '{extraVoiceName}' для zetvideo плеєра #{extraIdx + 1}"); _onLog($"GetSeasonStructure: створюю додатковий голос '{extraVoiceName}' для zetvideo плеєра #{extraIdx + 1}");
var extraEpisodes = seasonAvailable var extraEpisodes = seasonEpisodes
.OrderBy(ep => ep.episode) .OrderBy(ep => ep.episode)
.Select(ep => new EpisodeInfo .Select(ep => new EpisodeInfo
{ {
@ -1999,31 +1954,16 @@ namespace LME.Uaflix
var match = Regex.Match(episodeUrl, @"season-(\d+).*?episode-(\d+)"); var match = Regex.Match(episodeUrl, @"season-(\d+).*?episode-(\d+)");
if (match.Success) if (match.Success)
{
var ep = new EpisodeLinkInfo
{
url = episodeUrl,
title = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim() ?? $"Епізод {match.Groups[2].Value}",
season = int.Parse(match.Groups[1].Value),
episode = int.Parse(match.Groups[2].Value)
};
// Перевірка на «Прем'єра» — епізод ще не вийшов
var viDesc = episodeNode.SelectSingleNode(".//div[contains(@class, 'vi-desc')]");
if (viDesc != null)
{
var viTitle = viDesc.SelectSingleNode(".//div[contains(@class, 'vi-title')]");
string descText = viTitle?.InnerText?.Trim() ?? string.Empty;
if (descText.IndexOf("Прем'єра", StringComparison.OrdinalIgnoreCase) >= 0)
{ {
ep.IsPremiere = true; allEpisodes.Add(new EpisodeLinkInfo
_onLog($"GetPaginationInfo: Серія {ep.episode} позначена як прем'єра: '{descText}'"); {
url = episodeUrl,
title = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim() ?? $"Епізод {match.Groups[2].Value}",
season = int.Parse(match.Groups[1].Value),
episode = int.Parse(match.Groups[2].Value)
});
} }
} }
allEpisodes.Add(ep);
}
}
} }
} }