lampac/Shared/Engine/Online/FilmixTV.cs
lampac-talks f843f04fd4 chore: initial commit 154.3
Signed-off-by: lampac-talks <lampac-talks@users.noreply.github.com>
2026-01-30 16:23:09 +03:00

313 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Newtonsoft.Json.Linq;
using Shared.Models;
using Shared.Models.Base;
using Shared.Models.Online.Filmix;
using Shared.Models.Online.FilmixTV;
using Shared.Models.Templates;
using System.Text.Json;
using System.Web;
namespace Shared.Engine.Online
{
public class FilmixTVInvoke
{
#region FilmixTVInvoke
string host;
string apihost;
List<HeadersModel> bearer;
HttpHydra httpHydra;
Func<string, string> onstreamfile;
Func<string, string> onlog;
Action requesterror;
bool rjson;
public FilmixTVInvoke(string host, string apihost, List<HeadersModel> bearer, HttpHydra httpHydra, Func<string, string> onstreamfile, Func<string, string> onlog = null, Action requesterror = null, bool rjson = false)
{
this.host = host != null ? $"{host}/" : null;
this.apihost = apihost;
this.bearer = bearer;
this.httpHydra = httpHydra;
this.onstreamfile = onstreamfile;
this.onlog = onlog;
this.requesterror = requesterror;
this.rjson = rjson;
}
#endregion
#region Search
async public Task<SearchResult> Search(string title, string original_title, int clarification, int year, bool similar)
{
if (string.IsNullOrWhiteSpace(title ?? original_title))
return null;
string uri = $"{apihost}/api-fx/list?search={HttpUtility.UrlEncode(clarification == 1 ? title : (original_title ?? title))}&limit=48";
onlog?.Invoke(uri);
var root = await httpHydra.Get<JObject>(uri, addheaders: bearer, safety: true);
if (root == null || !root.ContainsKey("items"))
return await Search2(title, original_title, year, clarification);
List<SearchModel> items = null;
try
{
items = root["items"].ToObject<List<SearchModel>>();
}
catch { }
if (items == null || items.Count == 0)
return await Search2(title, original_title, year, clarification);
var ids = new List<int>(items.Count);
var stpl = new SimilarTpl(items.Count);
string enc_title = HttpUtility.UrlEncode(title);
string enc_original_title = HttpUtility.UrlEncode(original_title);
string stitle = StringConvert.SearchName(title);
string sorigtitle = StringConvert.SearchName(original_title);
foreach (var item in items)
{
if (item == null)
continue;
string name = !string.IsNullOrEmpty(item.title) && !string.IsNullOrEmpty(item.original_name) ? $"{item.title} / {item.original_name}" : (item.title ?? item.original_name);
stpl.Append(name, item.year.ToString(), string.Empty, host + $"lite/filmixtv?postid={item.id}&title={enc_title}&original_title={enc_original_title}", PosterApi.Size(item.poster));
if ((!string.IsNullOrEmpty(stitle) && StringConvert.SearchName(item.title) == stitle) ||
(!string.IsNullOrEmpty(sorigtitle) && StringConvert.SearchName(item.original_name) == sorigtitle))
{
if (item.year == year)
ids.Add(item.id);
}
}
if (ids.Count == 1 && !similar)
return new SearchResult() { id = ids[0] };
return new SearchResult() { similars = stpl };
}
#endregion
#region Search2
async Task<SearchResult> Search2(string title, string original_title, int year, int clarification)
{
var result = await gosearch(clarification == 1 ? original_title : title);
if (result == null)
result = await gosearch(clarification == 1 ? title : original_title);
if (result == null)
return null;
var ids = new List<int>(result.Count);
var stpl = new SimilarTpl(result.Count);
string enc_title = HttpUtility.UrlEncode(title);
string enc_original_title = HttpUtility.UrlEncode(original_title);
string stitle = StringConvert.SearchName(title);
string sorigtitle = StringConvert.SearchName(original_title);
foreach (var item in result)
{
if (item == null)
continue;
string name = !string.IsNullOrEmpty(item.title) && !string.IsNullOrEmpty(item.original_title) ? $"{item.title} / {item.original_title}" : (item.title ?? item.original_title);
stpl.Append(name, item.year.ToString(), string.Empty, host + $"lite/filmixtv?postid={item.id}&title={enc_title}&original_title={enc_original_title}", PosterApi.Size(item.poster));
if ((!string.IsNullOrEmpty(stitle) && StringConvert.SearchName(item.title) == stitle) ||
(!string.IsNullOrEmpty(sorigtitle) && StringConvert.SearchName(item.original_title) == sorigtitle))
{
if (item.year == year)
ids.Add(item.id);
}
}
if (ids.Count == 1)
return new SearchResult() { id = ids[0] };
return new SearchResult() { similars = stpl };
}
async Task<List<SearchModel>> gosearch(string story)
{
if (string.IsNullOrEmpty(story))
return null;
string uri = $"{AppInit.conf.Filmix.corsHost()}/api/v2/search?story={HttpUtility.UrlEncode(story)}&user_dev_apk=2.0.1&user_dev_id=&user_dev_name=Xiaomi&user_dev_os=11&user_dev_token=&user_dev_vendor=Xiaomi";
var root = await httpHydra.Get<List<SearchModel>>(uri, addheaders: bearer, safety: true);
if (root == null || root.Count == 0)
return null;
return root;
}
#endregion
#region Post
public Models.Online.FilmixTV.RootObject Post(string json)
{
if (string.IsNullOrWhiteSpace(json))
{
requesterror?.Invoke();
return null;
}
try
{
var rootMs = new Models.Online.FilmixTV.RootObject();
if (JsonDocument.Parse(json).RootElement.ValueKind == JsonValueKind.Array)
{
rootMs.Movies = JsonSerializer.Deserialize<MovieTV[]>(json);
}
else
{
rootMs.SerialVoice = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Season>>>(json);
}
return rootMs;
}
catch { return null; }
}
#endregion
#region Tpl
public ITplResult Tpl(Models.Online.FilmixTV.RootObject root, bool pro, int postid, string title, string original_title, int t, int? s, VastConf vast = null)
{
if (root == null)
return default;
#region Сериал
if (root.SerialVoice != null)
{
string enc_title = HttpUtility.UrlEncode(title);
string enc_original_title = HttpUtility.UrlEncode(original_title);
if (s == null)
{
#region Сезоны
var maxQuality = root.SerialVoice.SelectMany(i => i.Value)
.SelectMany(season => season.Value.episodes)
.SelectMany(episode => episode.Value.files)
.Max(file => file.quality);
var tpl = new SeasonTpl($"{maxQuality}p");
var temp = new HashSet<int>();
foreach (var translation in root.SerialVoice)
{
foreach (var season in translation.Value)
{
if (temp.Contains(season.Value.season))
continue;
temp.Add(season.Value.season);
var link = $"{host}lite/filmixtv?rjson={rjson}&postid={postid}&title={enc_title}&original_title={enc_original_title}&s={season.Value.season}";
tpl.Append($"{season.Value.season} сезон", link, season.Value.season);
}
}
return tpl;
#endregion
}
else
{
#region Перевод
int indexTranslate = 0;
var vtpl = new VoiceTpl();
foreach (var translation in root.SerialVoice)
{
foreach (var season in translation.Value)
{
if (season.Value.season == s)
{
string link = host + $"lite/filmixtv?rjson={rjson}&postid={postid}&title={enc_title}&original_title={enc_original_title}&s={s}&t={indexTranslate}";
bool active = t == indexTranslate;
if (t == -1)
t = indexTranslate;
vtpl.Append(translation.Key, active, link);
}
}
indexTranslate++;
}
#endregion
var selectedSeason = root.SerialVoice.ElementAt(t).Value.FirstOrDefault(x => x.Value.season == s);
if (selectedSeason.Value.episodes == null)
return default;
var etpl = new EpisodeTpl(vtpl, selectedSeason.Value.episodes.Count);
foreach (var episode in selectedSeason.Value.episodes)
{
var streamquality = new StreamQualityTpl();
var sortedFiles = episode.Value.files
.Where(file => pro || file.quality <= 720)
.OrderByDescending(file => file.quality);
foreach (var file in sortedFiles)
streamquality.Append(onstreamfile.Invoke(file.url), $"{file.quality}p");
if (!streamquality.Any())
continue;
etpl.Append($"{episode.Key.TrimStart('e')} серия", title ?? original_title, selectedSeason.Value.season.ToString(), episode.Key.TrimStart('e'), streamquality.Firts().link, streamquality: streamquality, vast: vast);
}
return etpl;
}
}
#endregion
#region Фильм
else if (root.Movies != null)
{
var mtpl = new MovieTpl(title, original_title, root.Movies.Length);
foreach (var item in root.Movies)
{
var streamquality = new StreamQualityTpl();
foreach (var file in item.files)
{
if (!pro)
{
if (pro && file.quality > 480)
continue;
if (file.quality > 720)
continue;
}
streamquality.Append(onstreamfile.Invoke(file.url), $"{file.quality}p");
}
if (!streamquality.Any())
continue;
mtpl.Append(item.voiceover, streamquality.Firts().link, streamquality: streamquality, vast: vast);
}
return mtpl;
}
#endregion
return default;
}
#endregion
}
}