using Microsoft.AspNetCore.Mvc;
using Shared.Engine.RxEnumerate;
namespace Online.Controllers
{
public class Animevost : BaseOnlineController
{
public Animevost() : base(AppInit.conf.Animevost) { }
[HttpGet]
[Route("lite/animevost")]
async public Task Index(string title, int year, string uri, int s, bool rjson = false, bool similar = false)
{
if (await IsRequestBlocked(rch: true))
return badInitMsg;
if (string.IsNullOrWhiteSpace(title))
return OnError();
rhubFallback:
if (string.IsNullOrWhiteSpace(uri))
{
#region Поиск
var cache = await InvokeCacheResult>($"animevost:search:{title}:{similar}", 40, async e =>
{
List<(string title, string year, string uri, string s, string img)> smlr = null;
List<(string title, string year, string uri, string s, string img)> catalog = null;
string data = $"do=search&subaction=search&search_start=0&full_search=0&result_from=1&story={HttpUtility.UrlEncode(title)}";
await httpHydra.PostSpan($"{init.corsHost()}/index.php?do=search", data, search =>
{
var rx = Rx.Split("class=\"shortstory\"", search, 1);
if (rx.Count == 0)
return;
smlr = new List<(string title, string year, string uri, string s, string img)>(rx.Count);
catalog = new List<(string title, string year, string uri, string s, string img)>(rx.Count);
foreach (var row in rx.Rows())
{
var g = row.Groups("([^<]+)");
string animeyear = row.Match("Год выхода: ?([0-9]{4})
");
string img = row.Match(" src=\"(/uploads/[^\"]+)\"");
if (!string.IsNullOrEmpty(img))
img = init.host + img;
if (!string.IsNullOrWhiteSpace(g[1].Value) && !string.IsNullOrWhiteSpace(g[2].Value))
{
string season = Regex.Match(g[2].Value, "([0-9 ]+) ?nd ", RegexOptions.IgnoreCase).Groups[1].Value.Trim();
if (string.IsNullOrEmpty(season))
{
season = Regex.Match(g[2].Value, "Season ([0-9]+)", RegexOptions.IgnoreCase).Groups[1].Value.Trim();
if (string.IsNullOrEmpty(season))
season = "1";
}
smlr.Add((g[2].Value, animeyear, g[1].Value, season, string.IsNullOrEmpty(img) ? null : img));
if (animeyear == year.ToString() && StringConvert.SearchName(g[2].Value).Contains(StringConvert.SearchName(title)))
catalog.Add((g[2].Value, animeyear, g[1].Value, season, null));
}
}
});
if ((catalog == null || catalog.Count == 0) && (smlr == null || smlr.Count == 0))
return e.Fail("catalog", refresh_proxy: true);
if (!similar && catalog?.Count > 0)
return e.Success(catalog);
return e.Success(smlr);
});
if (IsRhubFallback(cache))
goto rhubFallback;
if (!similar && cache.Value != null && cache.Value.Count == 1)
return LocalRedirect(accsArgs($"/lite/animevost?rjson={rjson}&title={HttpUtility.UrlEncode(title)}&uri={HttpUtility.UrlEncode(cache.Value[0].uri)}&s={cache.Value[0].s}"));
return await ContentTpl(cache, () =>
{
if (cache.Value.Count == 0)
return default;
var stpl = new SimilarTpl(cache.Value.Count);
foreach (var res in cache.Value)
{
string uri = $"{host}/lite/animevost?title={HttpUtility.UrlEncode(title)}&uri={HttpUtility.UrlEncode(res.uri)}&s={res.s}";
stpl.Append(res.title, res.year, string.Empty, uri, PosterApi.Size(res.img));
}
return stpl;
});
#endregion
}
else
{
#region Серии
var cache = await InvokeCacheResult>($"animevost:playlist:{uri}", 30, async e =>
{
var links = new List<(string episode, string id)>(4);
await httpHydra.GetSpan(uri, news =>
{
string data = Rx.Match(news, "var data = ([^\n\r]+)");
if (data == null)
return;
var match = Regex.Match(data, "\"([^\"]+)\":\"([0-9]+)\",");
while (match.Success)
{
if (!string.IsNullOrWhiteSpace(match.Groups[1].Value) && !string.IsNullOrWhiteSpace(match.Groups[2].Value))
links.Add((match.Groups[1].Value, match.Groups[2].Value));
match = match.NextMatch();
}
});
if (links.Count == 0)
return e.Fail("links", refresh_proxy: true);
return e.Success(links);
});
if (IsRhubFallback(cache))
goto rhubFallback;
return await ContentTpl(cache, () =>
{
var etpl = new EpisodeTpl(cache.Value.Count);
foreach (var l in cache.Value)
{
string link = $"{host}/lite/animevost/video?id={l.id}&title={HttpUtility.UrlEncode(title)}";
etpl.Append(l.episode, title, s.ToString(), Regex.Match(l.episode, "^([0-9]+)").Groups[1].Value, link, "call", streamlink: accsArgs($"{link}&play=true"));
}
return etpl;
});
#endregion
}
}
#region Video
[HttpGet]
[Route("lite/animevost/video")]
async public ValueTask Video(int id, string title, bool play)
{
if (await IsRequestBlocked(rch: true, rch_check: false))
return badInitMsg;
if (rch != null)
{
if (rch.IsNotConnected())
{
if (init.rhub_fallback && play)
rch.Disabled();
else
return ContentTo(rch.connectionMsg);
}
if (!play && rch.IsRequiredConnected())
return ContentTo(rch.connectionMsg);
if (rch.IsNotSupport(out string rch_error))
return ShowError(rch_error);
}
rhubFallback:
var cache = await InvokeCacheResult>($"animevost:video:{id}", 20, async e =>
{
var links = new List<(string l, string q)>(2);
await httpHydra.GetSpan($"{init.corsHost()}/frame5.php?play={id}&old=1", iframe =>
{
string mp4 = Rx.Match(iframe, "download=\"invoice\"[^>]+href=\"(https?://[^\"]+)\">720p");
if (mp4 != null)
links.Add((mp4, "720p"));
mp4 = Rx.Match(iframe, "download=\"invoice\"[^>]+href=\"(https?://[^\"]+)\">480p");
if (mp4 != null)
links.Add((mp4, "480p"));
});
if (links.Count == 0)
return e.Fail("mp4", refresh_proxy: true);
return e.Success(links);
});
if (IsRhubFallback(cache))
goto rhubFallback;
if (cache.IsSuccess && play)
return Redirect(HostStreamProxy(cache.Value[0].l));
return OnResult(cache, () =>
{
string link = HostStreamProxy(cache.Value[0].l);
return VideoTpl.ToJson("play", link, title, vast: init.vast);
});
}
#endregion
}
}