mirror of
https://github.com/lampame/lampac-ukraine.git
synced 2026-06-17 12:08:54 +00:00
refactor(uaflix): handle multiple iframe sources on episode pages
Extract iframe URLs from video-box containers, fallback to all page iframes, and include og:video:iframe metadata so pages with multiple players are parsed consistently. Update the episode resolver to probe all zetvideo embeds and aggregate playable streams instead of relying on a single iframe. Bump the module version to 5.3.
This commit is contained in:
parent
d2c7ee7c72
commit
dd40ed69f2
@ -19,7 +19,7 @@ namespace LME.Uaflix
|
|||||||
{
|
{
|
||||||
public class ModInit : IModuleLoaded
|
public class ModInit : IModuleLoaded
|
||||||
{
|
{
|
||||||
public static double Version => 5.2;
|
public static double Version => 5.3;
|
||||||
|
|
||||||
public static UaflixSettings UaFlix;
|
public static UaflixSettings UaFlix;
|
||||||
|
|
||||||
|
|||||||
@ -241,6 +241,51 @@ namespace LME.Uaflix
|
|||||||
return ExtractIframeFromMeta(doc);
|
return ExtractIframeFromMeta(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отримати всі iframe URL зі сторінки (з video-box, загальних iframe та og:meta)
|
||||||
|
/// Використовується для сторінок з кількома плеєрами (напр. zetvideo з субтитрами)
|
||||||
|
/// </summary>
|
||||||
|
private List<string> ExtractAllIframeUrls(HtmlDocument doc)
|
||||||
|
{
|
||||||
|
var result = new List<string>();
|
||||||
|
if (doc?.DocumentNode == null)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Спочатку збираємо всі iframe з video-box контейнерів
|
||||||
|
var videoBoxNodes = doc.DocumentNode.SelectNodes("//div[contains(@class, 'video-box')]//iframe");
|
||||||
|
if (videoBoxNodes != null)
|
||||||
|
{
|
||||||
|
foreach (var node in videoBoxNodes)
|
||||||
|
{
|
||||||
|
string url = NormalizeIframeUrl(node.GetAttributeValue("src", null));
|
||||||
|
if (!string.IsNullOrEmpty(url) && !result.Any(u => string.Equals(u, url, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
result.Add(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Якщо нічого не знайшли в video-box, шукаємо будь-які iframe
|
||||||
|
if (result.Count == 0)
|
||||||
|
{
|
||||||
|
var allIframeNodes = doc.DocumentNode.SelectNodes("//iframe");
|
||||||
|
if (allIframeNodes != null)
|
||||||
|
{
|
||||||
|
foreach (var node in allIframeNodes)
|
||||||
|
{
|
||||||
|
string url = NormalizeIframeUrl(node.GetAttributeValue("src", null));
|
||||||
|
if (!string.IsNullOrEmpty(url) && !result.Any(u => string.Equals(u, url, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
result.Add(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Також додаємо URL з og:video:iframe meta
|
||||||
|
string metaIframe = ExtractIframeFromMeta(doc);
|
||||||
|
if (!string.IsNullOrEmpty(metaIframe) && !result.Any(u => string.Equals(u, metaIframe, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
result.Add(metaIframe);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<(string iframeUrl, string playerType)> ProbeEpisodePlayer(string pageUrl)
|
private async Task<(string iframeUrl, string playerType)> ProbeEpisodePlayer(string pageUrl)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(pageUrl))
|
if (string.IsNullOrWhiteSpace(pageUrl))
|
||||||
@ -1896,6 +1941,42 @@ namespace LME.Uaflix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Отримуємо всі iframe зі сторінки (підтримка кількох плеєрів, напр. zetvideo з субтитрами)
|
||||||
|
var allIframes = ExtractAllIframeUrls(doc);
|
||||||
|
|
||||||
|
// Фільтруємо zetvideo iframe — повертаємо всі як окремі потоки
|
||||||
|
var zetvideoIframes = allIframes
|
||||||
|
.Where(u => u != null && u.Contains("zetvideo.net"))
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (zetvideoIframes.Count > 0)
|
||||||
|
{
|
||||||
|
int streamIndex = 0;
|
||||||
|
foreach (var zetIframe in zetvideoIframes)
|
||||||
|
{
|
||||||
|
var streams = await ParseAllZetvideoSources(zetIframe);
|
||||||
|
if (streams == null || streams.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var stream in streams)
|
||||||
|
{
|
||||||
|
// Перший потік → "Uaflix" (переклад), наступні → "Оригінал"
|
||||||
|
string label = streamIndex == 0 ? "Uaflix" : "Оригінал";
|
||||||
|
stream.title = label;
|
||||||
|
|
||||||
|
_onLog($"ParseEpisode: zetvideo потік #{streamIndex + 1}: {label} -> {zetIframe}" +
|
||||||
|
(stream.subtitles != null && stream.subtitles.Value.data != null && stream.subtitles.Value.data.Count > 0
|
||||||
|
? " (має субтитри)" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.streams.AddRange(streams);
|
||||||
|
streamIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Старий код: використовуємо перший iframe для ashdi/інших
|
||||||
string iframeUrl = ExtractIframeUrl(doc);
|
string iframeUrl = ExtractIframeUrl(doc);
|
||||||
if (!string.IsNullOrEmpty(iframeUrl))
|
if (!string.IsNullOrEmpty(iframeUrl))
|
||||||
{
|
{
|
||||||
@ -1912,9 +1993,7 @@ namespace LME.Uaflix
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iframeUrl.Contains("zetvideo.net"))
|
if (iframeUrl.Contains("ashdi.vip"))
|
||||||
result.streams = await ParseAllZetvideoSources(iframeUrl);
|
|
||||||
else if (iframeUrl.Contains("ashdi.vip"))
|
|
||||||
{
|
{
|
||||||
// Перевіряємо, чи це ashdi-vod (окремий епізод) або ashdi-serial (багатосерійний плеєр)
|
// Перевіряємо, чи це ashdi-vod (окремий епізод) або ashdi-serial (багатосерійний плеєр)
|
||||||
if (iframeUrl.Contains("/vod/"))
|
if (iframeUrl.Contains("/vod/"))
|
||||||
@ -1936,6 +2015,7 @@ namespace LME.Uaflix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_onLog($"ParseEpisode error: {ex.Message}");
|
_onLog($"ParseEpisode error: {ex.Message}");
|
||||||
@ -1988,15 +2068,27 @@ namespace LME.Uaflix
|
|||||||
var script = doc.DocumentNode.SelectSingleNode("//script[contains(text(), 'file:')]");
|
var script = doc.DocumentNode.SelectSingleNode("//script[contains(text(), 'file:')]");
|
||||||
if (script != null)
|
if (script != null)
|
||||||
{
|
{
|
||||||
var match = Regex.Match(script.InnerText, @"file:\s*""([^""]+\.m3u8)");
|
var fileMatch = Regex.Match(script.InnerText, @"file:\s*""([^""]+\.m3u8)");
|
||||||
if (match.Success)
|
if (fileMatch.Success)
|
||||||
{
|
{
|
||||||
string link = match.Groups[1].Value;
|
string link = fileMatch.Groups[1].Value;
|
||||||
|
|
||||||
|
// Парсимо subtitle з того ж Playerjs конфігу
|
||||||
|
SubtitleTpl? subtitles = null;
|
||||||
|
var subtitleMatch = Regex.Match(script.InnerText, @"subtitle:\s*""([^""]*)""");
|
||||||
|
if (subtitleMatch.Success)
|
||||||
|
{
|
||||||
|
string subtitleStr = subtitleMatch.Groups[1].Value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(subtitleStr))
|
||||||
|
subtitles = ApnHelper.ParseSubtitles(subtitleStr);
|
||||||
|
}
|
||||||
|
|
||||||
result.Add(new PlayStream
|
result.Add(new PlayStream
|
||||||
{
|
{
|
||||||
link = link,
|
link = link,
|
||||||
quality = "1080p",
|
quality = "1080p",
|
||||||
title = BuildDisplayTitle("Основне джерело", link, 1)
|
title = BuildDisplayTitle("Основне джерело", link, 1),
|
||||||
|
subtitles = subtitles
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user