Try add init4Uaflix

This commit is contained in:
Felix 2025-09-13 17:57:09 +03:00
parent 496a1f34b7
commit 66d712bb41
3 changed files with 224 additions and 200 deletions

View File

@ -11,26 +11,32 @@ using Shared;
using Shared.Models.Templates; using Shared.Models.Templates;
using Uaflix.Models; using Uaflix.Models;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Shared.Models.Online.Settings;
using Shared.Engine;
using Shared.Models;
namespace Uaflix.Controllers namespace Uaflix.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
ProxyManager proxyManager = new ProxyManager(ModInit.UaFlix); ProxyManager proxyManager;
static HttpClient httpClient = new HttpClient();
public Controller()
{
proxyManager = new ProxyManager(ModInit.UaFlix);
}
[HttpGet] [HttpGet]
[Route("uaflix")] [Route("uaflix")]
async public Task<ActionResult> Index(long id, string imdb_id, long kinopoisk_id, string title, string original_title, string original_language, int year, string source, int serial, string account_email, string t, int s = -1, bool rjson = false) async public Task<ActionResult> Index(long id, string imdb_id, long kinopoisk_id, string title, string original_title, string original_language, int year, string source, int serial, string account_email, string t, int s = -1, bool rjson = false)
{ {
var init = ModInit.UaFlix; var init = await loadKit(ModInit.UaFlix);
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
var proxy = proxyManager.Get(); var result = await search(init, imdb_id, kinopoisk_id, title, original_title, year, serial, s);
var result = await search(imdb_id, kinopoisk_id, title, original_title, year, serial);
if (result == null) if (result == null || result.movie == null)
{ {
proxyManager.Refresh(); proxyManager.Refresh();
return Content("Uaflix", "text/html; charset=utf-8"); return Content("Uaflix", "text/html; charset=utf-8");
@ -57,7 +63,7 @@ namespace Uaflix.Controllers
return rjson ? Content(season_tpl.ToJson(), "application/json; charset=utf-8") : Content(season_tpl.ToHtml(), "text/html; charset=utf-8"); return rjson ? Content(season_tpl.ToJson(), "application/json; charset=utf-8") : Content(season_tpl.ToHtml(), "text/html; charset=utf-8");
} }
var episodes = seasons.GetValueOrDefault(s, null); var episodes = seasons.GetValueOrDefault<int, List<Movie>>(s, null);
OnLog($"Вибраний сезон: {s}, кількість епізодів: {episodes?.Count ?? 0}"); OnLog($"Вибраний сезон: {s}, кількість епізодів: {episodes?.Count ?? 0}");
if (episodes == null) if (episodes == null)
return Content("Uaflix", "text/html; charset=utf-8"); return Content("Uaflix", "text/html; charset=utf-8");
@ -118,48 +124,74 @@ namespace Uaflix.Controllers
return Content("Uaflix", "text/html; charset=utf-8"); return Content("Uaflix", "text/html; charset=utf-8");
} }
async ValueTask<Result> search(string imdb_id, long kinopoisk_id, string title, string original_title, int year, int serial) async ValueTask<Result> search(OnlinesSettings init, string imdb_id, long kinopoisk_id, string title, string original_title, int year, int serial, int s = -1)
{ {
string memKey = $"UaFlix:view:{kinopoisk_id}:{imdb_id}"; string memKey = $"UaFlix:view:{kinopoisk_id}:{imdb_id}:{s}";
if (!hybridCache.TryGetValue(memKey, out Result res)) if (!hybridCache.TryGetValue(memKey, out Result res))
{ {
try try
{ {
string filmTitle = !string.IsNullOrEmpty(title) ? title : original_title; var proxy = proxyManager.Get();
string searchUrl = $"https://uafix.net/index.php?do=search&subaction=search&story={HttpUtility.UrlEncode(filmTitle)}";
httpClient.DefaultRequestHeaders.Clear(); string filmTitle = !string.IsNullOrEmpty(title) ? title : original_title;
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0"); string searchUrl = $"{init.host}/index.php?do=search&subaction=search&story={HttpUtility.UrlEncode(filmTitle)}";
httpClient.DefaultRequestHeaders.Add("Referer", "https://uafix.net/");
var searchHtml = await httpClient.GetStringAsync(searchUrl); var headers = new List<HeadersModel>()
var doc = new HtmlDocument(); {
doc.LoadHtml(searchHtml); new HeadersModel("User-Agent", "Mozilla/5.0"),
new HeadersModel("Referer", init.host)
};
string filmUrl = null; var searchHtml = await Http.Get(searchUrl, proxy: proxy, headers: headers);
var doc = new HtmlDocument();
doc.LoadHtml(searchHtml);
if (serial == 1) string filmUrl = null;
if (serial == 1)
{
var filmNode = doc.DocumentNode.SelectSingleNode("//a[contains(@class, 'sres-wrap')]");
if (filmNode == null)
{ {
var filmNode = doc.DocumentNode.SelectSingleNode("//a[contains(@class, 'sres-wrap')]"); OnLog("filmNode is null");
if (filmNode == null) return null;
{
OnLog("filmNode is null");
return null;
}
filmUrl = filmNode.GetAttributeValue("href", "");
} }
else filmUrl = filmNode.GetAttributeValue("href", "");
}
else
{
var filmNodes = doc.DocumentNode.SelectNodes("//a[contains(@class, 'sres-wrap')]");
if (filmNodes == null)
{ {
var filmNodes = doc.DocumentNode.SelectNodes("//a[contains(@class, 'sres-wrap')]"); OnLog("No search results found");
if (filmNodes == null) return null;
{ }
OnLog("No search results found");
return null;
}
// First try to find with year // First try to find with year
string selectedFilmUrl = null; string selectedFilmUrl = null;
HtmlNode selectedFilmNode = null; HtmlNode selectedFilmNode = null;
foreach (var filmNode in filmNodes)
{
var h2Node = filmNode.SelectSingleNode(".//h2");
if (h2Node == null) continue;
string nodeTitle = h2Node.InnerText.Trim().ToLower();
if (!nodeTitle.Contains(filmTitle.ToLower())) continue;
var descNode = filmNode.SelectSingleNode(".//div[contains(@class, 'sres-desc')]");
string desc = (descNode?.InnerText ?? "") + " " + nodeTitle;
if (year > 0 && desc.Contains(year.ToString()))
{
selectedFilmUrl = filmNode.GetAttributeValue("href", "");
selectedFilmNode = filmNode;
OnLog($"Selected film URL with year in description: {selectedFilmUrl} for title '{filmTitle}' year {year}");
break;
}
}
// If no match with year in description, check year on film page or pick first title match
if (string.IsNullOrEmpty(selectedFilmUrl))
{
foreach (var filmNode in filmNodes) foreach (var filmNode in filmNodes)
{ {
var h2Node = filmNode.SelectSingleNode(".//h2"); var h2Node = filmNode.SelectSingleNode(".//h2");
@ -168,18 +200,48 @@ namespace Uaflix.Controllers
string nodeTitle = h2Node.InnerText.Trim().ToLower(); string nodeTitle = h2Node.InnerText.Trim().ToLower();
if (!nodeTitle.Contains(filmTitle.ToLower())) continue; if (!nodeTitle.Contains(filmTitle.ToLower())) continue;
var descNode = filmNode.SelectSingleNode(".//div[contains(@class, 'sres-desc')]"); string href = filmNode.GetAttributeValue("href", "");
string desc = (descNode?.InnerText ?? "") + " " + nodeTitle; if (!href.StartsWith("http"))
if (year > 0 && desc.Contains(year.ToString())) href = init.host + href;
// Get film page and check year
try
{ {
selectedFilmUrl = filmNode.GetAttributeValue("href", ""); var filmPageHtml = await Http.Get(href, proxy: proxy, headers: headers);
selectedFilmNode = filmNode; var filmDoc = new HtmlDocument();
OnLog($"Selected film URL with year in description: {selectedFilmUrl} for title '{filmTitle}' year {year}"); filmDoc.LoadHtml(filmPageHtml);
break;
var yearNode = filmDoc.DocumentNode.SelectSingleNode("//span[@itemprop='dateCreated' and @class='year']");
int filmYear = 0;
if (yearNode != null)
{
if (int.TryParse(yearNode.InnerText, out int parsedYear))
{
filmYear = parsedYear;
}
}
if (year == 0 || filmYear == 0 || filmYear == year)
{
selectedFilmUrl = href;
selectedFilmNode = filmNode;
OnLog($"Selected film URL with year from page: {selectedFilmUrl} for title '{filmTitle}' year {year} (page year: {filmYear})");
break;
}
else
{
OnLog($"Film year mismatch: requested {year}, page {filmYear}. Skipping film.");
}
}
catch (Exception ex)
{
OnLog($"Error fetching film page {href}: {ex.Message}. Trying next film.");
// If error fetching page, try next film
continue;
} }
} }
// If no match with year in description, check year on film page or pick first title match // If still no match, pick first title match
if (string.IsNullOrEmpty(selectedFilmUrl)) if (string.IsNullOrEmpty(selectedFilmUrl))
{ {
foreach (var filmNode in filmNodes) foreach (var filmNode in filmNodes)
@ -188,150 +250,105 @@ namespace Uaflix.Controllers
if (h2Node == null) continue; if (h2Node == null) continue;
string nodeTitle = h2Node.InnerText.Trim().ToLower(); string nodeTitle = h2Node.InnerText.Trim().ToLower();
if (!nodeTitle.Contains(filmTitle.ToLower())) continue; if (nodeTitle.Contains(filmTitle.ToLower()))
string href = filmNode.GetAttributeValue("href", "");
if (!href.StartsWith("http"))
href = "https://uafix.net" + href;
// Get film page and check year
try
{ {
var filmPageHtml = await httpClient.GetStringAsync(href); selectedFilmUrl = filmNode.GetAttributeValue("href", "");
var filmDoc = new HtmlDocument(); selectedFilmNode = filmNode;
filmDoc.LoadHtml(filmPageHtml); OnLog($"Selected first matching film URL: {selectedFilmUrl} for title '{filmTitle}' (no year match)");
break;
var yearNode = filmDoc.DocumentNode.SelectSingleNode("//span[@itemprop='dateCreated' and @class='year']");
int filmYear = 0;
if (yearNode != null)
{
if (int.TryParse(yearNode.InnerText, out int parsedYear))
{
filmYear = parsedYear;
}
}
if (year == 0 || filmYear == 0 || filmYear == year)
{
selectedFilmUrl = href;
selectedFilmNode = filmNode;
OnLog($"Selected film URL with year from page: {selectedFilmUrl} for title '{filmTitle}' year {year} (page year: {filmYear})");
break;
}
else
{
OnLog($"Film year mismatch: requested {year}, page {filmYear}. Skipping film.");
}
}
catch (Exception ex)
{
OnLog($"Error fetching film page {href}: {ex.Message}. Trying next film.");
// If error fetching page, try next film
continue;
}
}
// If still no match, pick first title match
if (string.IsNullOrEmpty(selectedFilmUrl))
{
foreach (var filmNode in filmNodes)
{
var h2Node = filmNode.SelectSingleNode(".//h2");
if (h2Node == null) continue;
string nodeTitle = h2Node.InnerText.Trim().ToLower();
if (nodeTitle.Contains(filmTitle.ToLower()))
{
selectedFilmUrl = filmNode.GetAttributeValue("href", "");
selectedFilmNode = filmNode;
OnLog($"Selected first matching film URL: {selectedFilmUrl} for title '{filmTitle}' (no year match)");
break;
}
} }
} }
} }
if (string.IsNullOrEmpty(selectedFilmUrl))
{
OnLog($"No matching film found for '{filmTitle}'");
return null;
}
filmUrl = selectedFilmUrl;
} }
if (!filmUrl.StartsWith("http")) if (string.IsNullOrEmpty(selectedFilmUrl))
filmUrl = "https://uafix.net" + filmUrl;
var filmHtml = await httpClient.GetStringAsync(filmUrl);
doc.LoadHtml(filmHtml);
var movies = new List<Movie>();
if (serial == 1)
{ {
var episodeNodes = doc.DocumentNode.SelectNodes("//div[contains(@class, 'frels2')]//a[contains(@class, 'vi-img')]"); OnLog($"No matching film found for '{filmTitle}'");
if (episodeNodes != null) return null;
{ }
OnLog($"Знайдено {episodeNodes.Count} епізодів");
var uniqueEpisodes = new HashSet<string>();
foreach (var episodeNode in episodeNodes.Reverse())
{
string episodeUrl = episodeNode.GetAttributeValue("href", "");
if (!episodeUrl.StartsWith("http"))
episodeUrl = "https://uafix.net" + episodeUrl;
if (uniqueEpisodes.Add(episodeUrl)) filmUrl = selectedFilmUrl;
}
if (!filmUrl.StartsWith("http"))
filmUrl = init.host + filmUrl;
var filmHtml = await Http.Get(filmUrl, proxy: proxy, headers: headers);
doc.LoadHtml(filmHtml);
var movies = new List<Movie>();
if (serial == 1)
{
var episodeNodes = doc.DocumentNode.SelectNodes("//div[contains(@class, 'frels2')]//a[contains(@class, 'vi-img')]");
if (episodeNodes != null)
{
OnLog($"Знайдено {episodeNodes.Count} епізодів");
var uniqueEpisodes = new HashSet<string>();
foreach (var episodeNode in episodeNodes.Reverse())
{
string episodeUrl = episodeNode.GetAttributeValue("href", "");
if (!episodeUrl.StartsWith("http"))
episodeUrl = init.host + episodeUrl;
if (uniqueEpisodes.Add(episodeUrl))
{
string episodeTitle = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim();
var match = System.Text.RegularExpressions.Regex.Match(episodeUrl, @"season-(\d+).*?episode-(\d+)");
if (match.Success && match.Groups.Count > 2)
{ {
string episodeTitle = episodeNode.SelectSingleNode(".//div[@class='vi-rate']")?.InnerText.Trim(); if (int.TryParse(match.Groups[1].Value, out int seasonNumber) && int.TryParse(match.Groups[2].Value, out int episodeNumber))
var match = System.Text.RegularExpressions.Regex.Match(episodeUrl, @"season-(\d+).*?episode-(\d+)");
if (match.Success && match.Groups.Count > 2)
{ {
if (int.TryParse(match.Groups[1].Value, out int seasonNumber) && int.TryParse(match.Groups[2].Value, out int episodeNumber)) var episodeMovies = await ParseEpisode(init, episodeUrl, filmTitle, episodeTitle, seasonNumber, episodeNumber);
if (episodeMovies != null)
{ {
var episodeMovies = await ParseEpisode(episodeUrl, filmTitle, episodeTitle, seasonNumber, episodeNumber); movies.AddRange(episodeMovies);
if (episodeMovies != null)
{
movies.AddRange(episodeMovies);
}
} }
} }
} }
} }
} }
} }
else
{
var episodeMovies = await ParseEpisode(filmUrl, filmTitle, null, 1, 1);
if (episodeMovies != null)
movies.AddRange(episodeMovies);
}
if (movies.Count > 0)
{
res = new Result()
{
movie = movies
};
hybridCache.Set(memKey, res, cacheTime(5));
proxyManager.Success();
}
} }
catch (Exception ex) else
{ {
OnLog($"UaFlix error: {ex.Message}"); var episodeMovies = await ParseEpisode(init, filmUrl, filmTitle, null, 1, 1);
if (episodeMovies != null)
movies.AddRange(episodeMovies);
}
if (movies.Count > 0)
{
res = new Result()
{
movie = movies
};
hybridCache.Set(memKey, res, cacheTime(5));
proxyManager.Success();
} }
} }
return res; catch (Exception ex)
{
OnLog($"UaFlix error: {ex.Message}");
}
} }
return res;
}
async Task<List<Movie>> ParseEpisode(string url, string filmTitle, string episodeTitle = null, int seasonNumber = 0, int episodeNumber = 0) async Task<List<Movie>> ParseEpisode(OnlinesSettings init, string url, string filmTitle, string episodeTitle = null, int seasonNumber = 0, int episodeNumber = 0)
{ {
var movies = new List<Movie>(); var movies = new List<Movie>();
try try
{ {
string html = await httpClient.GetStringAsync(url); var proxy = proxyManager.Get();
var headers = new List<HeadersModel>()
{
new HeadersModel("User-Agent", "Mozilla/5.0"),
new HeadersModel("Referer", init.host)
};
string html = await Http.Get(url, proxy: proxy, headers: headers);
var doc = new HtmlDocument(); var doc = new HtmlDocument();
doc.LoadHtml(html); doc.LoadHtml(html);
@ -403,10 +420,13 @@ namespace Uaflix.Controllers
var result = new List<(string link, string quality)>(); var result = new List<(string link, string quality)>();
try try
{ {
var request = new HttpRequestMessage(HttpMethod.Get, iframeUrl); var proxy = proxyManager.Get();
request.Headers.Add("User-Agent", "Mozilla/5.0"); var headers = new List<HeadersModel>()
var response = await httpClient.SendAsync(request); {
var html = await response.Content.ReadAsStringAsync(); new HeadersModel("User-Agent", "Mozilla/5.0"),
new HeadersModel("Referer", "https://zetvideo.net/")
};
var html = await Http.Get(iframeUrl, proxy: proxy, headers: headers);
var doc = new HtmlDocument(); var doc = new HtmlDocument();
doc.LoadHtml(html); doc.LoadHtml(html);
@ -452,11 +472,14 @@ namespace Uaflix.Controllers
var result = new List<(string link, string quality)>(); var result = new List<(string link, string quality)>();
try try
{ {
var request = new HttpRequestMessage(HttpMethod.Get, iframeUrl); var proxy = proxyManager.Get();
request.Headers.Add("User-Agent", "Mozilla/5.0"); var headers = new List<HeadersModel>()
request.Headers.Add("Referer", "https://ashdi.vip/"); {
var response = await httpClient.SendAsync(request); new HeadersModel("User-Agent", "Mozilla/5.0"),
var html = await response.Content.ReadAsStringAsync(); new HeadersModel("Referer", "https://ashdi.vip/")
};
var html = await Http.Get(iframeUrl, proxy: proxy, headers: headers);
var doc = new HtmlDocument(); var doc = new HtmlDocument();
doc.LoadHtml(html); doc.LoadHtml(html);
@ -501,11 +524,16 @@ namespace Uaflix.Controllers
{ {
try try
{ {
var proxy = proxyManager.Get();
string url = $"https://ashdi.vip/vod/{id}"; string url = $"https://ashdi.vip/vod/{id}";
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0"); var headers = new List<HeadersModel>()
httpClient.DefaultRequestHeaders.Add("Referer", "https://ashdi.vip/"); {
var html = await httpClient.GetStringAsync(url); new HeadersModel("User-Agent", "Mozilla/5.0"),
new HeadersModel("Referer", "https://ashdi.vip/")
};
var html = await Http.Get(url, proxy: proxy, headers: headers);
string subtitle = new Regex("subtitle(\")?:\"([^\"]+)\"").Match(html).Groups[2].Value; string subtitle = new Regex("subtitle(\")?:\"([^\"]+)\"").Match(html).Groups[2].Value;
if (!string.IsNullOrEmpty(subtitle)) if (!string.IsNullOrEmpty(subtitle))

View File

@ -5,20 +5,20 @@ namespace Uaflix
{ {
public class ModInit public class ModInit
{ {
public static OnlinesSettings UaFlix; public static OnlinesSettings UaFlix;
/// <summary> /// <summary>
/// модуль загружен /// модуль загружен
/// </summary> /// </summary>
public static void loaded() public static void loaded()
{ {
UaFlix = new OnlinesSettings("UaFlix", "uafix.net", streamproxy: false) UaFlix = new OnlinesSettings("Uaflix", "https://uafix.net", streamproxy: false)
{ {
displayname = "🇺🇦 UaFlix" displayname = "🇺🇦 UaFlix"
}; };
// Выводить "уточнить поиск" // Виводити "уточнити пошук"
AppInit.conf.online.with_search.Add("uaflix"); AppInit.conf.online.with_search.Add("uaflix");
} }
} }
} }

View File

@ -9,20 +9,16 @@ namespace Uaflix
{ {
var online = new List<(string name, string url, string plugin, int index)>(); var online = new List<(string name, string url, string plugin, int index)>();
void send(BaseSettings init, string plugin) var init = ModInit.UaFlix;
if (init.enable && !init.rip)
{ {
if (init.enable && !init.rip) string url = init.overridehost;
{ if (string.IsNullOrEmpty(url))
string url = init.overridehost; url = $"{host}/uaflix";
if (string.IsNullOrEmpty(url))
url = $"{host}/{plugin}";
online.Add((init.displayname, url, plugin, online.Count)); online.Add((init.displayname, url, "uaflix", init.displayindex > 0 ? init.displayindex : online.Count));
}
} }
send(ModInit.UaFlix, "uaflix");
return online; return online;
} }
} }