466 lines
18 KiB
C#
466 lines
18 KiB
C#
using Shared.Engine.RxEnumerate;
|
||
using Shared.Models.Base;
|
||
using Shared.Models.Online.Eneyida;
|
||
using Shared.Models.Templates;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using System.Text.RegularExpressions;
|
||
using System.Web;
|
||
|
||
namespace Shared.Engine.Online
|
||
{
|
||
public struct KinoukrInvoke
|
||
{
|
||
#region unic
|
||
static string ArrayList => "qwertyuioplkjhgfdsazxcvbnm";
|
||
static string ArrayListToNumber => "1234567890";
|
||
public static string unic(int size = 8, bool IsNumberCode = false)
|
||
{
|
||
StringBuilder array = new StringBuilder(size);
|
||
for (int i = 0; i < size; i++)
|
||
{
|
||
array.Append(IsNumberCode ? ArrayListToNumber[Random.Shared.Next(0, ArrayListToNumber.Length)] : ArrayList[Random.Shared.Next(0, ArrayList.Length)]);
|
||
}
|
||
|
||
return array.ToString();
|
||
}
|
||
#endregion
|
||
|
||
#region KinoukrInvoke
|
||
string host;
|
||
string apihost;
|
||
HttpHydra http;
|
||
Func<string, string> onstreamfile;
|
||
Func<string, string> onlog;
|
||
Action requesterror;
|
||
|
||
public KinoukrInvoke(string host, string apihost, HttpHydra httpHydra, Func<string, string> onstreamfile, Func<string, string> onlog = null, Action requesterror = null)
|
||
{
|
||
this.host = host != null ? $"{host}/" : null;
|
||
this.apihost = apihost;
|
||
http = httpHydra;
|
||
this.onstreamfile = onstreamfile;
|
||
this.onlog = onlog;
|
||
this.requesterror = requesterror;
|
||
}
|
||
#endregion
|
||
|
||
#region Embed
|
||
public async Task<EmbedModel> Embed(string original_title, int year, string href)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(href) && (string.IsNullOrWhiteSpace(original_title) || year == 0))
|
||
return null;
|
||
|
||
return null;
|
||
|
||
//string link = href;
|
||
//var result = new EmbedModel();
|
||
|
||
//if (string.IsNullOrWhiteSpace(link))
|
||
//{
|
||
// onlog?.Invoke("search start");
|
||
// //string? search = await onget.Invoke($"{apihost}/index.php?do=search&subaction=search&from_page=0&story={HttpUtility.UrlEncode(original_title)}");
|
||
|
||
// // $"{apihost}/index.php?do=search"
|
||
// string search = await onpost.Invoke($"{apihost}/{unic(4, true)}-{unic(Random.Shared.Next(4, 8))}-{unic(Random.Shared.Next(5, 10))}.html", $"do=search&subaction=search&story={HttpUtility.UrlEncode(original_title)}");
|
||
// if (search == null)
|
||
// {
|
||
// requesterror?.Invoke();
|
||
// return null;
|
||
// }
|
||
|
||
// onlog?.Invoke("search ok");
|
||
|
||
// foreach (string row in search.Split("\"short clearfix with-mask\"").Skip(1))
|
||
// {
|
||
// if (row.Contains(">Анонс</div>") || row.Contains(">Трейлер</div>"))
|
||
// continue;
|
||
|
||
// string newslink = Regex.Match(row, "href=\"(https?://[^/]+/[^\"]+\\.html)\"").Groups[1].Value;
|
||
// if (string.IsNullOrWhiteSpace(newslink))
|
||
// continue;
|
||
|
||
// string name = Regex.Match(row, "class=\"short-title\" [^>]+>([^<]+)<").Groups[1].Value;
|
||
// if (result.similars == null)
|
||
// result.similars = new List<Similar>();
|
||
|
||
// result.similars.Add(new Similar()
|
||
// {
|
||
// title = name,
|
||
// href = newslink
|
||
// });
|
||
// }
|
||
|
||
// if (result.similars == null || result.similars.Count == 0)
|
||
// {
|
||
// if (search.Contains(">Пошук по сайту<"))
|
||
// return new EmbedModel() { IsEmpty = true };
|
||
|
||
// return null;
|
||
// }
|
||
|
||
// if (result.similars.Count > 1)
|
||
// return result;
|
||
|
||
// link = result.similars[0].href;
|
||
//}
|
||
|
||
//onlog?.Invoke("link: " + link);
|
||
//string news = await onget.Invoke(link);
|
||
//if (news == null)
|
||
//{
|
||
// requesterror?.Invoke();
|
||
// return null;
|
||
//}
|
||
|
||
//result.quel = Regex.Match(news, "class=\"m-meta m-qual\">([^<]+)<").Groups[1].Value;
|
||
|
||
//string iframeUri = Regex.Match(news, "src=\"(https?://tortuga\\.[a-z]+/[^\"]+)\"").Groups[1].Value;
|
||
//if (string.IsNullOrEmpty(iframeUri))
|
||
//{
|
||
// iframeUri = Regex.Match(news, "src=\"(https?://ashdi\\.vip/[^\"]+)\"").Groups[1].Value;
|
||
// if (string.IsNullOrEmpty(iframeUri))
|
||
// return null;
|
||
//}
|
||
|
||
//onlog?.Invoke("iframeUri: " + iframeUri);
|
||
//string content = await onget.Invoke(iframeUri);
|
||
//if (content == null || !content.Contains("file:"))
|
||
//{
|
||
// requesterror?.Invoke();
|
||
// return null;
|
||
//}
|
||
|
||
//string player = StringConvert.FindLastText(content, "new Playerjs", "</script>");
|
||
//if (player == null)
|
||
// return null;
|
||
|
||
//if (Regex.IsMatch(content, "file: ?'\\["))
|
||
//{
|
||
// Models.Online.Tortuga.Voice[] root = null;
|
||
|
||
// try
|
||
// {
|
||
// root = JsonSerializer.Deserialize<Models.Online.Tortuga.Voice[]>(Regex.Match(content, "file: ?'([^\n\r]+)',").Groups[1].Value);
|
||
// if (root == null || root.Length == 0)
|
||
// return null;
|
||
// }
|
||
// catch { return null; }
|
||
|
||
// result.serial = root;
|
||
//}
|
||
//else
|
||
//{
|
||
// result.content = player;
|
||
// onlog?.Invoke("content: " + result.content);
|
||
//}
|
||
|
||
//return result;
|
||
}
|
||
#endregion
|
||
|
||
#region EmbedKurwa
|
||
public async Task<EmbedModel> EmbedKurwa(int clarification, string title, string original_title, int year, string href)
|
||
{
|
||
string iframeUri = href;
|
||
var result = new EmbedModel();
|
||
|
||
if (string.IsNullOrEmpty(iframeUri))
|
||
{
|
||
string arg = clarification == 1 || string.IsNullOrWhiteSpace(original_title)
|
||
? $"name={HttpUtility.UrlEncode(title)}"
|
||
: $"eng_name={HttpUtility.UrlEncode(original_title)}";
|
||
|
||
var root = await http.Get<BobrKurwa[]>("http://194.246.82.144/ukr?" + arg);
|
||
if (root == null)
|
||
{
|
||
requesterror?.Invoke();
|
||
return null;
|
||
}
|
||
|
||
result.similars = new List<Similar>(root.Length);
|
||
|
||
foreach (var item in root)
|
||
{
|
||
var model = new Similar()
|
||
{
|
||
href = item.tortuga ?? item.ashdi,
|
||
title = $"{item.name} / {item.eng_name}",
|
||
year = item.year
|
||
};
|
||
|
||
if (item.year == year.ToString())
|
||
result.similars.Insert(0, model);
|
||
else
|
||
result.similars.Add(model);
|
||
}
|
||
|
||
if (result.similars.Count == 0)
|
||
return new EmbedModel() { IsEmpty = true };
|
||
|
||
if (result.similars.Count > 1 && result.similars[0].year != year.ToString())
|
||
return result;
|
||
|
||
iframeUri = result.similars[0].href;
|
||
}
|
||
|
||
onlog?.Invoke("iframeUri: " + iframeUri);
|
||
|
||
await http.GetSpan(iframeUri, content =>
|
||
{
|
||
if (!content.Contains("file:", StringComparison.Ordinal))
|
||
return;
|
||
|
||
if (iframeUri.Contains("ashdi"))
|
||
{
|
||
result.source_type = "ashdi";
|
||
|
||
if (Regex.IsMatch(content, "file: ?'\\["))
|
||
{
|
||
try
|
||
{
|
||
var root = JsonSerializer.Deserialize<Models.Online.Ashdi.Voice[]>(Rx.Match(content, "file: ?'([^\n\r]+)',"));
|
||
if (root != null && root.Length > 0)
|
||
result.serial_ashdi = root;
|
||
}
|
||
catch { }
|
||
}
|
||
else
|
||
{
|
||
var rx = Rx.Split("new Playerjs", content);
|
||
if (1 > rx.Count)
|
||
return;
|
||
|
||
result.content = rx[1].ToString();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
result.source_type = "tortuga";
|
||
|
||
if (Regex.IsMatch(content, "file: ?'"))
|
||
{
|
||
try
|
||
{
|
||
string file = Rx.Match(content, "file: ?'([^\n\r]+)',");
|
||
if (file.EndsWith("=="))
|
||
{
|
||
file = Regex.Replace(file, "==$", "");
|
||
file = string.Join("", CrypTo.DecodeBase64(file).Reverse());
|
||
}
|
||
|
||
var root = JsonSerializer.Deserialize<Models.Online.Tortuga.Voice[]>(file);
|
||
if (root != null && root.Length > 0)
|
||
result.serial = root;
|
||
}
|
||
catch { }
|
||
}
|
||
else
|
||
{
|
||
result.content = content.ToString();
|
||
}
|
||
}
|
||
});
|
||
|
||
if (string.IsNullOrEmpty(result.content) && result.serial_ashdi == null && result.serial == null)
|
||
{
|
||
requesterror?.Invoke();
|
||
return null;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
#endregion
|
||
|
||
#region getIframeSource
|
||
public async Task<string> getIframeSource(string link)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(link))
|
||
return null;
|
||
|
||
string iframeUri = null;
|
||
|
||
await http.GetSpan(link, news =>
|
||
{
|
||
iframeUri = Rx.Match(news, "src=\"(https?://tortuga\\.[a-z]+/[^\"]+)\"");
|
||
if (string.IsNullOrEmpty(iframeUri))
|
||
iframeUri = Rx.Match(news, "src=\"(https?://ashdi\\.vip/[^\"]+)\"");
|
||
});
|
||
|
||
if (string.IsNullOrEmpty(iframeUri))
|
||
{
|
||
requesterror?.Invoke();
|
||
return null;
|
||
}
|
||
|
||
return iframeUri;
|
||
}
|
||
#endregion
|
||
|
||
#region Tpl
|
||
public ITplResult Tpl(EmbedModel result, int clarification, string title, string original_title, int year, string t, int s, string href, VastConf vast = null, bool rjson = false)
|
||
{
|
||
if (result == null || result.IsEmpty)
|
||
return default;
|
||
|
||
string enc_title = HttpUtility.UrlEncode(title);
|
||
string enc_original_title = HttpUtility.UrlEncode(original_title);
|
||
string enc_href = HttpUtility.UrlEncode(href);
|
||
|
||
#region similar
|
||
if (result.content == null && result.serial == null && result.serial_ashdi == null)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(href) && result.similars != null && result.similars.Count > 0)
|
||
{
|
||
var stpl = new SimilarTpl(result.similars.Count);
|
||
|
||
foreach (var similar in result.similars)
|
||
{
|
||
string link = host + $"lite/kinoukr?rjson={rjson}&clarification={clarification}&title={enc_title}&original_title={enc_original_title}&year={year}&href={HttpUtility.UrlEncode(similar.href)}";
|
||
|
||
stpl.Append(similar.title, similar.year, string.Empty, link);
|
||
}
|
||
|
||
return stpl;
|
||
}
|
||
|
||
return default;
|
||
}
|
||
#endregion
|
||
|
||
if (result.source_type == "ashdi")
|
||
{
|
||
var invk = new AshdiInvoke(host, apihost, http, onstreamfile, requesterror: requesterror);
|
||
int.TryParse(t, out int _t);
|
||
|
||
var md = new Models.Online.Ashdi.EmbedModel()
|
||
{
|
||
content = result.content,
|
||
serial = result.serial_ashdi
|
||
};
|
||
|
||
return invk.Tpl(md, 0, title, original_title, _t, s, vast, rjson, host + $"lite/kinoukr?rjson={rjson}&clarification={clarification}&title={enc_title}&original_title={enc_original_title}&year={year}&href={enc_href}");
|
||
}
|
||
|
||
if (result.content != null)
|
||
{
|
||
#region Фильм
|
||
var mtpl = new MovieTpl(title, original_title, 1);
|
||
|
||
string hls = Regex.Match(result.content, "file: ?(\"|')(?<hls>https?://[^\"']+/index\\.m3u8)(\"|')").Groups["hls"].Value;
|
||
if (string.IsNullOrWhiteSpace(hls))
|
||
{
|
||
string base64 = Regex.Match(result.content, "file: ?(\"|')(?<base64>[^\"']+)(\"|')").Groups["base64"].Value;
|
||
base64 = Regex.Replace(base64, "==$", "");
|
||
|
||
hls = string.Join("", CrypTo.DecodeBase64(base64).Reverse());
|
||
|
||
if (string.IsNullOrWhiteSpace(hls))
|
||
return default;
|
||
}
|
||
|
||
#region subtitle
|
||
var subtitles = new SubtitleTpl();
|
||
string subtitle = new Regex("\"subtitle\": ?\"([^\"]+)\"").Match(result.content).Groups[1].Value;
|
||
|
||
if (!string.IsNullOrEmpty(subtitle))
|
||
{
|
||
var match = new Regex("\\[([^\\]]+)\\](https?://[^\\,]+)").Match(subtitle);
|
||
while (match.Success)
|
||
{
|
||
subtitles.Append(match.Groups[1].Value, onstreamfile.Invoke(match.Groups[2].Value));
|
||
match = match.NextMatch();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
mtpl.Append(string.IsNullOrEmpty(result.quel) ? "По умолчанию" : result.quel, onstreamfile.Invoke(hls), subtitles: subtitles, vast: vast);
|
||
|
||
return mtpl;
|
||
#endregion
|
||
}
|
||
else
|
||
{
|
||
#region Сериал
|
||
try
|
||
{
|
||
if (s == -1)
|
||
{
|
||
#region Сезоны
|
||
var tpl = new SeasonTpl();
|
||
|
||
foreach (var season in result.serial)
|
||
{
|
||
string link = host + $"lite/kinoukr?rjson={rjson}&clarification={clarification}&title={enc_title}&original_title={enc_original_title}&year={year}&href={enc_href}&s={season.season}";
|
||
|
||
tpl.Append(season.title, link, season.season);
|
||
}
|
||
|
||
return tpl;
|
||
#endregion
|
||
}
|
||
else
|
||
{
|
||
string sArhc = s.ToString();
|
||
var episodes = result.serial.First(i => i.season == sArhc).folder;
|
||
|
||
#region Перевод
|
||
var vtpl = new VoiceTpl();
|
||
var hashVoice = new HashSet<string>(20);
|
||
|
||
foreach (var episode in episodes)
|
||
{
|
||
foreach (var voice in episode.folder)
|
||
{
|
||
if (!hashVoice.Add(voice.title))
|
||
continue;
|
||
|
||
if (string.IsNullOrEmpty(t))
|
||
t = voice.title;
|
||
|
||
string link = host + $"lite/kinoukr?rjson={rjson}&clarification={clarification}&title={enc_title}&original_title={enc_original_title}&year={year}&href={enc_href}&s={s}&t={voice.title}";
|
||
vtpl.Append(voice.title, t == voice.title, link);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
var etpl = new EpisodeTpl(vtpl, episodes.Length);
|
||
|
||
foreach (var episode in episodes)
|
||
{
|
||
var video = episode.folder.FirstOrDefault(i => i.title == t);
|
||
if (video.file == null)
|
||
continue;
|
||
|
||
#region subtitle
|
||
var subtitles = new SubtitleTpl();
|
||
|
||
if (!string.IsNullOrEmpty(video.subtitle))
|
||
{
|
||
var match = new Regex("\\[([^\\]]+)\\](https?://[^\\,]+)").Match(video.subtitle);
|
||
while (match.Success)
|
||
{
|
||
subtitles.Append(match.Groups[1].Value, onstreamfile.Invoke(match.Groups[2].Value));
|
||
match = match.NextMatch();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
string file = onstreamfile.Invoke(video.file);
|
||
etpl.Append(episode.title, title ?? original_title, sArhc, episode.number, file, subtitles: subtitles, vast: vast);
|
||
}
|
||
|
||
return etpl;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
return default;
|
||
}
|
||
#endregion
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
}
|