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.
This commit is contained in:
Felix 2026-05-15 19:53:00 +03:00
parent a2071449f9
commit 6800c5d393

View File

@ -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; return vodUrl;
} }
catch (Exception ex) catch (Exception ex)
@ -247,6 +270,73 @@ namespace LME.UAKino
} }
} }
/// <summary>
/// Знайти позицію JSON масиву `[{...}]` після `file:'`
/// </summary>
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;
}
/// <summary>
/// Витягнути збалансований вміст між [ ] з урахуванням вкладеності та рядків
/// </summary>
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;
}
/// <summary> /// <summary>
/// Витягнути news_id з URL контенту /// Витягнути news_id з URL контенту
/// </summary> /// </summary>