diff --git a/LME.UAKino/Controller.cs b/LME.UAKino/Controller.cs
index afa10e5..41b9ed7 100644
--- a/LME.UAKino/Controller.cs
+++ b/LME.UAKino/Controller.cs
@@ -99,7 +99,37 @@ namespace LME.UAKino.Controllers
var voices = await invoke.GetPlaylist(newsId);
if (voices == null || voices.Count == 0)
+ {
+ // Fallback: playlist API повернув ERR_NOT_DATA — пробуємо зі сторінки
+ string fallbackUrl = await invoke.GetPageFallbackUrl(itemUrl);
+ if (!string.IsNullOrEmpty(fallbackUrl))
+ {
+ if (serial == 1)
+ {
+ var voice_tpl = new VoiceTpl();
+ var episode_tpl = new EpisodeTpl();
+ string streamUrl = BuildStreamUrl(init, fallbackUrl);
+ voice_tpl.Append("Озвучення", true, null);
+ episode_tpl.Append("Епізод 1", title ?? original_title, s >= 0 ? s.ToString() : "1", "01", streamUrl);
+ episode_tpl.Append(voice_tpl);
+ return rjson
+ ? Content(episode_tpl.ToJson(), "application/json; charset=utf-8")
+ : Content(episode_tpl.ToHtml(), "text/html; charset=utf-8");
+ }
+ else
+ {
+ if (ApnHelper.IsAshdiUrl(fallbackUrl) && !fallbackUrl.Contains("multivoice"))
+ fallbackUrl += (fallbackUrl.Contains("?") ? "&" : "?") + "multivoice";
+ string streamUrl = BuildStreamUrl(init, fallbackUrl);
+ var movie_tpl = new MovieTpl(title, original_title);
+ movie_tpl.Append("Фільм", streamUrl);
+ return rjson
+ ? Content(movie_tpl.ToJson(), "application/json; charset=utf-8")
+ : Content(movie_tpl.ToHtml(), "text/html; charset=utf-8");
+ }
+ }
return OnError("lme_uakino", refresh_proxy: true);
+ }
if (serial == 1)
{
@@ -190,7 +220,11 @@ namespace LME.UAKino.Controllers
if (voices.Count == 1 && voice.Episodes.Count > 1)
label = ep.Title;
- string streamUrl = BuildStreamUrl(init, ep.FileUrl);
+ string fileUrl = ep.FileUrl;
+ if (ApnHelper.IsAshdiUrl(fileUrl) && !fileUrl.Contains("multivoice"))
+ fileUrl += (fileUrl.Contains("?") ? "&" : "?") + "multivoice";
+
+ string streamUrl = BuildStreamUrl(init, fileUrl);
movie_tpl.Append(label, streamUrl);
}
}
diff --git a/LME.UAKino/UAKinoInvoke.cs b/LME.UAKino/UAKinoInvoke.cs
index ef4d760..e8cb8da 100644
--- a/LME.UAKino/UAKinoInvoke.cs
+++ b/LME.UAKino/UAKinoInvoke.cs
@@ -139,6 +139,60 @@ namespace LME.UAKino
}
}
+ ///
+ /// Fallback: отримати стрім з HTML сторінки фільму коли playlist API недоступний
+ /// Парсить <link itemprop="video" value="..."> або <iframe id="pre" src="...">
+ ///
+ public async Task GetPageFallbackUrl(string pageUrl)
+ {
+ if (string.IsNullOrEmpty(pageUrl))
+ return null;
+
+ try
+ {
+ _onLog?.Invoke($"UAKino page fallback: {pageUrl}");
+
+ var headers = new List()
+ {
+ new HeadersModel("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3 Safari/605.1.15"),
+ new HeadersModel("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
+ new HeadersModel("Referer", _init.host)
+ };
+
+ string html = await HttpGet(pageUrl, headers);
+ if (string.IsNullOrEmpty(html))
+ return null;
+
+ var doc = new HtmlDocument();
+ doc.LoadHtml(html);
+
+ // Спершу пробуємо
+ var linkTag = doc.DocumentNode.SelectSingleNode("//link[@itemprop='video']");
+ if (linkTag != null)
+ {
+ string value = linkTag.GetAttributeValue("value", "");
+ if (!string.IsNullOrEmpty(value))
+ return NormalizeUrl(value);
+ }
+
+ // Fallback до