From 6800c5d393eccf8da3f5da70f0fc83d04280d683 Mon Sep 17 00:00:00 2001 From: Felix Date: Fri, 15 May 2026 19:53:00 +0300 Subject: [PATCH] fix(uakino): parse Ashdi file arrays to resolve direct stream URL Handle Ashdi responses where `file` contains a JSON array encoded in the page script instead of a plain URL. Extract the balanced array payload, parse it safely, and return the first stream `file` entry when present. This prevents unresolved VOD links when complex playlist structures are embedded inline and keeps existing simple URL handling unchanged. --- LME.UAKino/UAKinoInvoke.cs | 92 +++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/LME.UAKino/UAKinoInvoke.cs b/LME.UAKino/UAKinoInvoke.cs index 7984283..ef22cbe 100644 --- a/LME.UAKino/UAKinoInvoke.cs +++ b/LME.UAKino/UAKinoInvoke.cs @@ -237,7 +237,30 @@ namespace LME.UAKino } } - // Складний масив — не парсимо, повертаємо як є + // Складний масив — знаходимо file:'[' і витягуємо збалансований JSON + int arrayStart = FindAshdiJsonArray(html); + if (arrayStart >= 0) + { + string jsonArray = ExtractBalancedBrackets(html, arrayStart); + if (!string.IsNullOrEmpty(jsonArray)) + { + try + { + using var arr = JsonDocument.Parse(jsonArray); + if (arr.RootElement.ValueKind == JsonValueKind.Array && arr.RootElement.GetArrayLength() > 0) + { + string firstFile = arr.RootElement[0].GetProperty("file").GetString(); + if (!string.IsNullOrEmpty(firstFile)) + { + _onLog?.Invoke($"UAKino resolved Ashdi (array): {firstFile}"); + return firstFile; + } + } + } + catch { } + } + } + return vodUrl; } catch (Exception ex) @@ -247,6 +270,73 @@ namespace LME.UAKino } } + /// + /// Знайти позицію JSON масиву `[{...}]` після `file:'` + /// + private static int FindAshdiJsonArray(string html) + { + int idx = html.IndexOf("file:'[", StringComparison.OrdinalIgnoreCase); + if (idx < 0) + idx = html.IndexOf("file:\"[", StringComparison.OrdinalIgnoreCase); + if (idx < 0) + return -1; + + int bracket = html.IndexOf('[', idx); + return bracket; + } + + /// + /// Витягнути збалансований вміст між [ ] з урахуванням вкладеності та рядків + /// + private static string ExtractBalancedBrackets(string text, int startIndex) + { + if (startIndex < 0 || startIndex >= text.Length || text[startIndex] != '[') + return null; + + int depth = 0; + bool inString = false; + char quote = '\0'; + + for (int i = startIndex; i < text.Length; i++) + { + char ch = text[i]; + + if (inString) + { + if (ch == '\\') + { + i++; // пропускаємо екранований символ + continue; + } + if (ch == quote) + inString = false; + continue; + } + + if (ch == '"' || ch == '\'') + { + inString = true; + quote = ch; + continue; + } + + if (ch == '[') + { + depth++; + continue; + } + + if (ch == ']') + { + depth--; + if (depth == 0) + return text.Substring(startIndex, i - startIndex + 1); + } + } + + return null; + } + /// /// Витягнути news_id з URL контенту ///