Compare commits

..

No commits in common. "a45e26537ad066c8762950fe3f8df3958997c4ca" and "8e2ddcc3de42d8355fcf32f95c80fa1717bf76ad" have entirely different histories.

126 changed files with 469 additions and 498 deletions

1
.gitignore vendored
View File

@ -16,4 +16,3 @@ bin
obj obj
.vscode/settings.json .vscode/settings.json
.qwen .qwen
log

View File

@ -9,10 +9,10 @@ using System.Linq;
using System.Text; using System.Text;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using LME.AnimeON.Models; using AnimeON.Models;
using Shared.Engine; using Shared.Engine;
namespace LME.AnimeON namespace AnimeON
{ {
public class AnimeONInvoke public class AnimeONInvoke
{ {

View File

@ -8,14 +8,14 @@ using System.Web;
using System.Linq; using System.Linq;
using Shared; using Shared;
using Shared.Models.Templates; using Shared.Models.Templates;
using LME.AnimeON.Models; using AnimeON.Models;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Text; using System.Text;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models; using Shared.Models;
using HtmlAgilityPack; using HtmlAgilityPack;
namespace LME.AnimeON.Controllers namespace AnimeON.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -27,7 +27,7 @@ namespace LME.AnimeON.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.animeon")] [Route("lite/animeon")]
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, bool checksearch = 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, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -42,13 +42,13 @@ namespace LME.AnimeON.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
var checkSeasons = await invoke.Search(imdb_id, kinopoisk_id, title, original_title, year, serial); var checkSeasons = await invoke.Search(imdb_id, kinopoisk_id, title, original_title, year, serial);
if (checkSeasons != null && checkSeasons.Count > 0) if (checkSeasons != null && checkSeasons.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
} }
OnLog($"AnimeON Index: title={title}, original_title={original_title}, serial={serial}, s={s}, t={t}, year={year}, imdb_id={imdb_id}, kp={kinopoisk_id}"); OnLog($"AnimeON Index: title={title}, original_title={original_title}, serial={serial}, s={s}, t={t}, year={year}, imdb_id={imdb_id}, kp={kinopoisk_id}");
@ -56,7 +56,7 @@ namespace LME.AnimeON.Controllers
var seasons = await invoke.Search(imdb_id, kinopoisk_id, title, original_title, year, serial); var seasons = await invoke.Search(imdb_id, kinopoisk_id, title, original_title, year, serial);
OnLog($"AnimeON: search results = {seasons?.Count ?? 0}"); OnLog($"AnimeON: search results = {seasons?.Count ?? 0}");
if (seasons == null || seasons.Count == 0) if (seasons == null || seasons.Count == 0)
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
// [Refactoring] Використовується агрегована структура (AggregateSerialStructure) — попередній збір allOptions не потрібний // [Refactoring] Використовується агрегована структура (AggregateSerialStructure) — попередній збір allOptions не потрібний
@ -82,7 +82,7 @@ namespace LME.AnimeON.Controllers
foreach (var item in seasonItems) foreach (var item in seasonItems)
{ {
string seasonName = item.SeasonNumber.ToString(); string seasonName = item.SeasonNumber.ToString();
string link = $"{host}/lite/lme.animeon?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={item.SeasonNumber}"; string link = $"{host}/lite/animeon?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={item.SeasonNumber}";
season_tpl.Append(seasonName, link, seasonName); season_tpl.Append(seasonName, link, seasonName);
} }
OnLog($"AnimeON: return seasons count={seasonItems.Count}"); OnLog($"AnimeON: return seasons count={seasonItems.Count}");
@ -107,13 +107,13 @@ namespace LME.AnimeON.Controllers
selected = new { Anime = seasons[s], Index = s, SeasonNumber = seasons[s].Season > 0 ? seasons[s].Season : s + 1 }; selected = new { Anime = seasons[s], Index = s, SeasonNumber = seasons[s].Season > 0 ? seasons[s].Season : s + 1 };
if (selected == null) if (selected == null)
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
var selectedAnime = selected.Anime; var selectedAnime = selected.Anime;
int selectedSeasonNumber = selected.SeasonNumber; int selectedSeasonNumber = selected.SeasonNumber;
var structure = await invoke.AggregateSerialStructure(selectedAnime.Id, selectedSeasonNumber); var structure = await invoke.AggregateSerialStructure(selectedAnime.Id, selectedSeasonNumber);
if (structure == null || !structure.Voices.Any()) if (structure == null || !structure.Voices.Any())
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
OnLog($"AnimeON: voices found = {structure.Voices.Count}"); OnLog($"AnimeON: voices found = {structure.Voices.Count}");
var voiceItems = structure.Voices var voiceItems = structure.Voices
@ -136,14 +136,14 @@ namespace LME.AnimeON.Controllers
var voice_tpl = new VoiceTpl(); var voice_tpl = new VoiceTpl();
foreach (var voice in voiceItems) foreach (var voice in voiceItems)
{ {
string voiceLink = $"{host}/lite/lme.animeon?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.Key)}"; string voiceLink = $"{host}/lite/animeon?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.Key)}";
bool isActive = voice.Key == t; bool isActive = voice.Key == t;
voice_tpl.Append(voice.Display, isActive, voiceLink); voice_tpl.Append(voice.Display, isActive, voiceLink);
} }
// Перевірка вибраної озвучки // Перевірка вибраної озвучки
if (!structure.Voices.ContainsKey(t)) if (!structure.Voices.ContainsKey(t))
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
var episode_tpl = new EpisodeTpl(); var episode_tpl = new EpisodeTpl();
var selectedVoiceInfo = structure.Voices[t]; var selectedVoiceInfo = structure.Voices[t];
@ -180,7 +180,7 @@ namespace LME.AnimeON.Controllers
if (string.IsNullOrEmpty(streamLink) && ep.EpisodeId > 0) if (string.IsNullOrEmpty(streamLink) && ep.EpisodeId > 0)
{ {
string callUrl = $"{host}/lite/lme.animeon/play?episode_id={ep.EpisodeId}&serial=1"; string callUrl = $"{host}/lite/animeon/play?episode_id={ep.EpisodeId}&serial=1";
episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call"); episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call");
continue; continue;
} }
@ -190,7 +190,7 @@ namespace LME.AnimeON.Controllers
if (needsResolve || streamLink.Contains("moonanime.art") || streamLink.Contains("ashdi.vip/vod")) if (needsResolve || streamLink.Contains("moonanime.art") || streamLink.Contains("ashdi.vip/vod"))
{ {
string callUrl = $"{host}/lite/lme.animeon/play?url={HttpUtility.UrlEncode(streamLink)}&serial=1"; string callUrl = $"{host}/lite/animeon/play?url={HttpUtility.UrlEncode(streamLink)}&serial=1";
episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call"); episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call");
} }
else else
@ -213,12 +213,12 @@ namespace LME.AnimeON.Controllers
{ {
var firstAnime = seasons.FirstOrDefault(); var firstAnime = seasons.FirstOrDefault();
if (firstAnime == null) if (firstAnime == null)
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
var fundubs = await invoke.GetFundubs(firstAnime.Id); var fundubs = await invoke.GetFundubs(firstAnime.Id);
OnLog($"AnimeON: movie fundubs count = {fundubs?.Count ?? 0}"); OnLog($"AnimeON: movie fundubs count = {fundubs?.Count ?? 0}");
if (fundubs == null || fundubs.Count == 0) if (fundubs == null || fundubs.Count == 0)
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
var tpl = new MovieTpl(title, original_title); var tpl = new MovieTpl(title, original_title);
@ -252,7 +252,7 @@ namespace LME.AnimeON.Controllers
foreach (var ashdiStream in ashdiStreams) foreach (var ashdiStream in ashdiStreams)
{ {
string optionName = $"{translationName} {ashdiStream.title}"; string optionName = $"{translationName} {ashdiStream.title}";
string callUrl = $"{host}/lite/lme.animeon/play?url={HttpUtility.UrlEncode(ashdiStream.link)}"; string callUrl = $"{host}/lite/animeon/play?url={HttpUtility.UrlEncode(ashdiStream.link)}";
tpl.Append(optionName, accsArgs(callUrl), "call"); tpl.Append(optionName, accsArgs(callUrl), "call");
} }
continue; continue;
@ -261,7 +261,7 @@ namespace LME.AnimeON.Controllers
if (needsResolve || streamLink.Contains("moonanime.art/iframe/") || streamLink.Contains("ashdi.vip/vod")) if (needsResolve || streamLink.Contains("moonanime.art/iframe/") || streamLink.Contains("ashdi.vip/vod"))
{ {
string callUrl = $"{host}/lite/lme.animeon/play?url={HttpUtility.UrlEncode(streamLink)}"; string callUrl = $"{host}/lite/animeon/play?url={HttpUtility.UrlEncode(streamLink)}";
tpl.Append(translationName, accsArgs(callUrl), "call"); tpl.Append(translationName, accsArgs(callUrl), "call");
} }
else else
@ -273,7 +273,7 @@ namespace LME.AnimeON.Controllers
// Якщо не зібрали жодної опції — повертаємо помилку // Якщо не зібрали жодної опції — повертаємо помилку
if (tpl.data == null || tpl.data.Count == 0) if (tpl.data == null || tpl.data.Count == 0)
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
OnLog("AnimeON: return movie options"); OnLog("AnimeON: return movie options");
return rjson ? Content(tpl.ToJson(), "application/json; charset=utf-8") : Content(tpl.ToHtml(), "text/html; charset=utf-8"); return rjson ? Content(tpl.ToJson(), "application/json; charset=utf-8") : Content(tpl.ToHtml(), "text/html; charset=utf-8");
@ -374,7 +374,7 @@ namespace LME.AnimeON.Controllers
return null; return null;
} }
[HttpGet("lite/lme.animeon/play")] [HttpGet("lite/animeon/play")]
public async Task<ActionResult> Play(string url, int episode_id = 0, string title = null, int serial = 0) public async Task<ActionResult> Play(string url, int episode_id = 0, string title = null, int serial = 0)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -400,13 +400,13 @@ namespace LME.AnimeON.Controllers
else else
{ {
OnLog("AnimeON Play: empty url"); OnLog("AnimeON Play: empty url");
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
} }
if (string.IsNullOrEmpty(streamLink)) if (string.IsNullOrEmpty(streamLink))
{ {
OnLog("AnimeON Play: cannot extract stream"); OnLog("AnimeON Play: cannot extract stream");
return OnError("lme.animeon", refresh_proxy: true); return OnError("animeon", refresh_proxy: true);
} }
List<HeadersModel> streamHeaders = null; List<HeadersModel> streamHeaders = null;

View File

@ -22,11 +22,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.AnimeON namespace AnimeON
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 4.1; public static double Version => 4.0;
public static OnlinesSettings AnimeON; public static OnlinesSettings AnimeON;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -45,7 +45,7 @@ namespace LME.AnimeON
{ {
AnimeON = new OnlinesSettings("LME.AnimeON", "https://animeon.club", streamproxy: false, useproxy: false) AnimeON = new OnlinesSettings("AnimeON", "https://animeon.club", streamproxy: false, useproxy: false)
{ {
displayname = "AnimeON", displayname = "AnimeON",
displayindex = 0, displayindex = 0,
@ -64,7 +64,7 @@ namespace LME.AnimeON
["ashdi"] = ApnHelper.DefaultHost ["ashdi"] = ApnHelper.DefaultHost
}; };
var conf = ModuleInvoke.Init("LME.AnimeON", defaults) ?? defaults; var conf = ModuleInvoke.Init("AnimeON", defaults) ?? defaults;
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf); MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf);
conf.Remove("magic_apn"); conf.Remove("magic_apn");
@ -85,7 +85,7 @@ namespace LME.AnimeON
} }
// Виводити "уточнити пошук" // Виводити "уточнити пошук"
RegisterWithSearch("lme.animeon"); RegisterWithSearch("animeon");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.AnimeON.Models namespace AnimeON.Models
{ {
/// <summary> Aggregated structure for AnimeON serial content to match Lampac standard navigation.</summary> /// <summary> Aggregated structure for AnimeON serial content to match Lampac standard navigation.</summary>
public class AnimeONAggregatedStructure public class AnimeONAggregatedStructure

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.AnimeON.Models namespace AnimeON.Models
{ {
public class EmbedModel public class EmbedModel
{ {

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.AnimeON.Models namespace AnimeON.Models
{ {
public class SearchResponseModel public class SearchResponseModel
{ {

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.AnimeON.Models namespace AnimeON.Models
{ {
public class Serial public class Serial
{ {

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.AnimeON.Models namespace AnimeON.Models
{ {
public class Voice public class Voice
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.AnimeON namespace AnimeON
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -30,7 +30,7 @@ namespace LME.AnimeON
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.animeon")); online.Add(new ModuleOnlineItem(init, "animeon"));
} }
return online; return online;

3
AnimeON/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -5,14 +5,14 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using LME.Bamboo.Models; using Bamboo.Models;
using HtmlAgilityPack; using HtmlAgilityPack;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
namespace LME.Bamboo namespace Bamboo
{ {
public class BambooInvoke public class BambooInvoke
{ {

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using LME.Bamboo.Models; using Bamboo.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
@ -11,7 +11,7 @@ using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models.Templates; using Shared.Models.Templates;
namespace LME.Bamboo.Controllers namespace Bamboo.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -23,7 +23,7 @@ namespace LME.Bamboo.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.bamboo")] [Route("lite/bamboo")]
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, string href = null, bool checksearch = 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, string href = null, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -37,13 +37,13 @@ namespace LME.Bamboo.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
var searchResults = await invoke.Search(title, original_title); var searchResults = await invoke.Search(title, original_title);
if (searchResults != null && searchResults.Count > 0) if (searchResults != null && searchResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
} }
string itemUrl = href; string itemUrl = href;
@ -51,14 +51,14 @@ namespace LME.Bamboo.Controllers
{ {
var searchResults = await invoke.Search(title, original_title); var searchResults = await invoke.Search(title, original_title);
if (searchResults == null || searchResults.Count == 0) if (searchResults == null || searchResults.Count == 0)
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
if (searchResults.Count > 1) if (searchResults.Count > 1)
{ {
var similar_tpl = new SimilarTpl(searchResults.Count); var similar_tpl = new SimilarTpl(searchResults.Count);
foreach (var res in searchResults) foreach (var res in searchResults)
{ {
string link = $"{host}/lite/lme.bamboo?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(res.Url)}"; string link = $"{host}/lite/bamboo?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(res.Url)}";
similar_tpl.Append(res.Title, string.Empty, string.Empty, link, res.Poster); similar_tpl.Append(res.Title, string.Empty, string.Empty, link, res.Poster);
} }
@ -72,7 +72,7 @@ namespace LME.Bamboo.Controllers
{ {
var series = await invoke.GetSeriesEpisodes(itemUrl); var series = await invoke.GetSeriesEpisodes(itemUrl);
if (series == null || (series.Sub.Count == 0 && series.Dub.Count == 0)) if (series == null || (series.Sub.Count == 0 && series.Dub.Count == 0))
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
var voice_tpl = new VoiceTpl(); var voice_tpl = new VoiceTpl();
var episode_tpl = new EpisodeTpl(); var episode_tpl = new EpisodeTpl();
@ -88,13 +88,13 @@ namespace LME.Bamboo.Controllers
foreach (var voice in availableVoices) foreach (var voice in availableVoices)
{ {
string voiceLink = $"{host}/lite/lme.bamboo?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&t={voice.key}&href={HttpUtility.UrlEncode(itemUrl)}"; string voiceLink = $"{host}/lite/bamboo?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&t={voice.key}&href={HttpUtility.UrlEncode(itemUrl)}";
voice_tpl.Append(voice.name, voice.key == t, voiceLink); voice_tpl.Append(voice.name, voice.key == t, voiceLink);
} }
var selected = availableVoices.FirstOrDefault(v => v.key == t); var selected = availableVoices.FirstOrDefault(v => v.key == t);
if (selected.episodes == null || selected.episodes.Count == 0) if (selected.episodes == null || selected.episodes.Count == 0)
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
int index = 1; int index = 1;
foreach (var ep in selected.episodes.OrderBy(e => e.Episode ?? int.MaxValue)) foreach (var ep in selected.episodes.OrderBy(e => e.Episode ?? int.MaxValue))
@ -116,7 +116,7 @@ namespace LME.Bamboo.Controllers
{ {
var streams = await invoke.GetMovieStreams(itemUrl); var streams = await invoke.GetMovieStreams(itemUrl);
if (streams == null || streams.Count == 0) if (streams == null || streams.Count == 0)
return OnError("lme.bamboo", refresh_proxy: true); return OnError("bamboo", refresh_proxy: true);
var movie_tpl = new MovieTpl(title, original_title); var movie_tpl = new MovieTpl(title, original_title);
for (int i = 0; i < streams.Count; i++) for (int i = 0; i < streams.Count; i++)

View File

@ -21,11 +21,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Bamboo namespace Bamboo
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 4.1; public static double Version => 4.0;
public static OnlinesSettings Bamboo; public static OnlinesSettings Bamboo;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -43,7 +43,7 @@ namespace LME.Bamboo
{ {
Bamboo = new OnlinesSettings("LME.Bamboo", "https://bambooua.com", streamproxy: false, useproxy: false) Bamboo = new OnlinesSettings("Bamboo", "https://bambooua.com", streamproxy: false, useproxy: false)
{ {
displayname = "BambooUA", displayname = "BambooUA",
displayindex = 0, displayindex = 0,
@ -57,7 +57,7 @@ namespace LME.Bamboo
}; };
var defaults = JObject.FromObject(Bamboo); var defaults = JObject.FromObject(Bamboo);
defaults["enabled"] = true; defaults["enabled"] = true;
var conf = ModuleInvoke.Init("LME.Bamboo", defaults); var conf = ModuleInvoke.Init("Bamboo", defaults);
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
@ -76,7 +76,7 @@ namespace LME.Bamboo
} }
// Виводити "уточнити пошук" // Виводити "уточнити пошук"
RegisterWithSearch("lme.bamboo"); RegisterWithSearch("bamboo");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.Bamboo.Models namespace Bamboo.Models
{ {
public class SearchResult public class SearchResult
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Bamboo namespace Bamboo
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -33,7 +33,7 @@ namespace LME.Bamboo
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.bamboo")); online.Add(new ModuleOnlineItem(init, "bamboo"));
} }
return online; return online;

3
Bamboo/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -1,4 +1,4 @@
using LME.JackTor.Models; using JackTor.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Shared; using Shared;
using Shared.Models; using Shared.Models;
@ -14,7 +14,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace LME.JackTor.Controllers namespace JackTor.Controllers
{ {
public class Controller : BaseOnlineController<JackTorSettings> public class Controller : BaseOnlineController<JackTorSettings>
{ {
@ -26,7 +26,7 @@ namespace LME.JackTor.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.jacktor")] [Route("lite/jacktor")]
async public Task<ActionResult> Index( async public Task<ActionResult> Index(
long id, long id,
string imdb_id, string imdb_id,
@ -57,20 +57,20 @@ namespace LME.JackTor.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
var check = await invoke.Search(title, original_title, year, serial, original_language); var check = await invoke.Search(title, original_title, year, serial, original_language);
if (check.Count > 0) if (check.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
} }
var torrents = await invoke.Search(title, original_title, year, serial, original_language); var torrents = await invoke.Search(title, original_title, year, serial, original_language);
if (torrents == null || torrents.Count == 0) if (torrents == null || torrents.Count == 0)
{ {
string debugInfo = $"title={title}\noriginal_title={original_title}\nyear={year}\nserial={serial}\njackett={MaskSensitiveUrl(init.jackett)}\nmin_sid={init.min_sid}\nmin_peers={init.min_peers}"; string debugInfo = $"title={title}\noriginal_title={original_title}\nyear={year}\nserial={serial}\njackett={MaskSensitiveUrl(init.jackett)}\nmin_sid={init.min_sid}\nmin_peers={init.min_peers}";
return OnError("lme.jacktor", refresh_proxy: true, weblog: debugInfo); return OnError("jacktor", refresh_proxy: true, weblog: debugInfo);
} }
if (serial == 1) if (serial == 1)
@ -97,7 +97,7 @@ namespace LME.JackTor.Controllers
{ {
seasonTpl.Append( seasonTpl.Append(
$"{season} сезон", $"{season} сезон",
$"{host}/lite/lme.jacktor?rjson={rjson}&title={enTitle}&original_title={enOriginal}&year={year}&original_language={original_language}&serial=1&s={season}", $"{host}/lite/jacktor?rjson={rjson}&title={enTitle}&original_title={enOriginal}&year={year}&original_language={original_language}&serial=1&s={season}",
season); season);
} }
@ -126,7 +126,7 @@ namespace LME.JackTor.Controllers
: $"{seasonLabel} • {torrent.Voice}"; : $"{seasonLabel} • {torrent.Voice}";
string qualityInfo = $"{torrent.Tracker} / {torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}"; string qualityInfo = $"{torrent.Tracker} / {torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}";
string releaseLink = accsArgs($"{host}/lite/lme.jacktor/serial/{torrent.Rid}?rjson={rjson}&title={enTitle}&original_title={enOriginal}&s={targetSeason}"); string releaseLink = accsArgs($"{host}/lite/jacktor/serial/{torrent.Rid}?rjson={rjson}&title={enTitle}&original_title={enOriginal}&s={targetSeason}");
similarTpl.Append(releaseName, null, qualityInfo, releaseLink); similarTpl.Append(releaseName, null, qualityInfo, releaseLink);
} }
@ -146,7 +146,7 @@ namespace LME.JackTor.Controllers
: torrent.Voice; : torrent.Voice;
string voiceName = $"{torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}"; string voiceName = $"{torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}";
string streamLink = accsArgs($"{host}/lite/lme.jacktor/s{torrent.Rid}"); string streamLink = accsArgs($"{host}/lite/jacktor/s{torrent.Rid}");
movieTpl.Append( movieTpl.Append(
voice, voice,
@ -162,7 +162,7 @@ namespace LME.JackTor.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.jacktor/serial/{rid}")] [Route("lite/jacktor/serial/{rid}")]
async public ValueTask<ActionResult> Serial(string rid, string account_email, string title, string original_title, int s = 1, bool rjson = false) async public ValueTask<ActionResult> Serial(string rid, string account_email, string title, string original_title, int s = 1, bool rjson = false)
{ {
var init = loadKit(ModInit.Settings); var init = loadKit(ModInit.Settings);
@ -174,9 +174,9 @@ namespace LME.JackTor.Controllers
var invoke = new JackTorInvoke(init, hybridCache, OnLog, proxyManager); var invoke = new JackTorInvoke(init, hybridCache, OnLog, proxyManager);
if (!invoke.TryGetSource(rid, out JackTorSourceCache source)) if (!invoke.TryGetSource(rid, out JackTorSourceCache source))
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
string memKey = $"lme.jacktor:serial:{rid}"; string memKey = $"jacktor:serial:{rid}";
return await InvkSemaphore(memKey, null, async () => return await InvkSemaphore(memKey, null, async () =>
{ {
@ -184,7 +184,7 @@ namespace LME.JackTor.Controllers
{ {
var ts = ResolveProbeTorrentServer(init, account_email); var ts = ResolveProbeTorrentServer(init, account_email);
if (string.IsNullOrWhiteSpace(ts.host)) if (string.IsNullOrWhiteSpace(ts.host))
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
string hashResponse = await httpHydra.Post( string hashResponse = await httpHydra.Post(
$"{ts.host}/torrents", $"{ts.host}/torrents",
@ -194,7 +194,7 @@ namespace LME.JackTor.Controllers
string hash = ExtractHash(hashResponse); string hash = ExtractHash(hashResponse);
if (string.IsNullOrWhiteSpace(hash)) if (string.IsNullOrWhiteSpace(hash))
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
Stat stat = null; Stat stat = null;
DateTime deadline = DateTime.Now.AddSeconds(20); DateTime deadline = DateTime.Now.AddSeconds(20);
@ -213,7 +213,7 @@ namespace LME.JackTor.Controllers
if (DateTime.Now > deadline) if (DateTime.Now > deadline)
{ {
_ = httpHydra.Post($"{ts.host}/torrents", BuildRemovePayload(hash), statusCodeOK: false, newheaders: ts.headers); _ = httpHydra.Post($"{ts.host}/torrents", BuildRemovePayload(hash), statusCodeOK: false, newheaders: ts.headers);
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
} }
await Task.Delay(250); await Task.Delay(250);
@ -226,7 +226,7 @@ namespace LME.JackTor.Controllers
} }
if (fileStats == null || fileStats.Length == 0) if (fileStats == null || fileStats.Length == 0)
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
var episodeTpl = new EpisodeTpl(); var episodeTpl = new EpisodeTpl();
int appended = 0; int appended = 0;
@ -241,13 +241,13 @@ namespace LME.JackTor.Controllers
title ?? original_title, title ?? original_title,
s.ToString(), s.ToString(),
file.Id.ToString(), file.Id.ToString(),
accsArgs($"{host}/lite/lme.jacktor/s{rid}?tsid={file.Id}")); accsArgs($"{host}/lite/jacktor/s{rid}?tsid={file.Id}"));
appended++; appended++;
} }
if (appended == 0) if (appended == 0)
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
return rjson return rjson
? Content(episodeTpl.ToJson(), "application/json; charset=utf-8") ? Content(episodeTpl.ToJson(), "application/json; charset=utf-8")
@ -256,7 +256,7 @@ namespace LME.JackTor.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.jacktor/s{rid}")] [Route("lite/jacktor/s{rid}")]
async public ValueTask<ActionResult> Stream(string rid, int tsid = -1, string account_email = null) async public ValueTask<ActionResult> Stream(string rid, int tsid = -1, string account_email = null)
{ {
var init = loadKit(ModInit.Settings); var init = loadKit(ModInit.Settings);
@ -268,14 +268,14 @@ namespace LME.JackTor.Controllers
var invoke = new JackTorInvoke(init, hybridCache, OnLog, proxyManager); var invoke = new JackTorInvoke(init, hybridCache, OnLog, proxyManager);
if (!invoke.TryGetSource(rid, out JackTorSourceCache source)) if (!invoke.TryGetSource(rid, out JackTorSourceCache source))
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
int index = tsid != -1 ? tsid : 1; int index = tsid != -1 ? tsid : 1;
string country = requestInfo.Country; string country = requestInfo.Country;
async ValueTask<ActionResult> AuthStream(string tsHost, string login, string passwd, string uhost = null, Dictionary<string, string> addheaders = null) async ValueTask<ActionResult> AuthStream(string tsHost, string login, string passwd, string uhost = null, Dictionary<string, string> addheaders = null)
{ {
string memKey = $"lme.jacktor:auth_stream:{rid}:{uhost ?? tsHost}"; string memKey = $"jacktor:auth_stream:{rid}:{uhost ?? tsHost}";
if (!hybridCache.TryGetValue(memKey, out string hash)) if (!hybridCache.TryGetValue(memKey, out string hash))
{ {
login = (login ?? string.Empty).Replace("{account_email}", account_email ?? string.Empty); login = (login ?? string.Empty).Replace("{account_email}", account_email ?? string.Empty);
@ -291,7 +291,7 @@ namespace LME.JackTor.Controllers
hash = ExtractHash(response); hash = ExtractHash(response);
if (string.IsNullOrWhiteSpace(hash)) if (string.IsNullOrWhiteSpace(hash))
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
hybridCache.Set(memKey, hash, DateTime.Now.AddMinutes(1)); hybridCache.Set(memKey, hash, DateTime.Now.AddMinutes(1));
} }
@ -315,7 +315,7 @@ namespace LME.JackTor.Controllers
if (init.auth_torrs != null && init.auth_torrs.Count > 0) if (init.auth_torrs != null && init.auth_torrs.Count > 0)
{ {
string tsKey = $"lme.jacktor:ts2:{rid}:{requestInfo.IP}"; string tsKey = $"jacktor:ts2:{rid}:{requestInfo.IP}";
if (!hybridCache.TryGetValue(tsKey, out PidTorAuthTS ts)) if (!hybridCache.TryGetValue(tsKey, out PidTorAuthTS ts))
{ {
var servers = init.auth_torrs.Where(i => i.enable).ToList(); var servers = init.auth_torrs.Where(i => i.enable).ToList();
@ -328,7 +328,7 @@ namespace LME.JackTor.Controllers
} }
if (servers.Count == 0) if (servers.Count == 0)
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
ts = servers[Random.Shared.Next(0, servers.Count)]; ts = servers[Random.Shared.Next(0, servers.Count)];
hybridCache.Set(tsKey, ts, DateTime.Now.AddHours(4)); hybridCache.Set(tsKey, ts, DateTime.Now.AddHours(4));
@ -341,9 +341,9 @@ namespace LME.JackTor.Controllers
if (init.base_auth != null && init.base_auth.enable) if (init.base_auth != null && init.base_auth.enable)
{ {
if (init.torrs == null || init.torrs.Length == 0) if (init.torrs == null || init.torrs.Length == 0)
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
string tsKey = $"lme.jacktor:ts3:{rid}:{requestInfo.IP}"; string tsKey = $"jacktor:ts3:{rid}:{requestInfo.IP}";
if (!hybridCache.TryGetValue(tsKey, out string tsHost)) if (!hybridCache.TryGetValue(tsKey, out string tsHost))
{ {
tsHost = init.torrs[Random.Shared.Next(0, init.torrs.Length)]; tsHost = init.torrs[Random.Shared.Next(0, init.torrs.Length)];
@ -354,9 +354,9 @@ namespace LME.JackTor.Controllers
} }
if (init.torrs == null || init.torrs.Length == 0) if (init.torrs == null || init.torrs.Length == 0)
return OnError("lme.jacktor", refresh_proxy: true); return OnError("jacktor", refresh_proxy: true);
string key = $"lme.jacktor:ts4:{rid}:{requestInfo.IP}"; string key = $"jacktor:ts4:{rid}:{requestInfo.IP}";
if (!hybridCache.TryGetValue(key, out string torrentHost)) if (!hybridCache.TryGetValue(key, out string torrentHost))
{ {
torrentHost = init.torrs[Random.Shared.Next(0, init.torrs.Length)]; torrentHost = init.torrs[Random.Shared.Next(0, init.torrs.Length)];

View File

@ -1,4 +1,4 @@
using LME.JackTor.Models; using JackTor.Models;
using Shared.Models; using Shared.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -10,7 +10,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace LME.JackTor namespace JackTor
{ {
public class JackTorInvoke public class JackTorInvoke
{ {
@ -45,7 +45,7 @@ namespace LME.JackTor
public async Task<List<JackTorParsedResult>> Search(string title, string originalTitle, int year, int serial, string originalLanguage) public async Task<List<JackTorParsedResult>> Search(string title, string originalTitle, int year, int serial, string originalLanguage)
{ {
string memKey = $"lme.jacktor:search:{serial}:{year}:{(title ?? string.Empty).Trim().ToLowerInvariant()}:{(originalTitle ?? string.Empty).Trim().ToLowerInvariant()}"; string memKey = $"jacktor:search:{serial}:{year}:{(title ?? string.Empty).Trim().ToLowerInvariant()}:{(originalTitle ?? string.Empty).Trim().ToLowerInvariant()}";
if (_hybridCache.TryGetValue(memKey, out List<JackTorParsedResult> cached)) if (_hybridCache.TryGetValue(memKey, out List<JackTorParsedResult> cached))
return cached; return cached;
@ -83,7 +83,7 @@ namespace LME.JackTor
public bool TryGetSource(string rid, out JackTorSourceCache source) public bool TryGetSource(string rid, out JackTorSourceCache source)
{ {
return _hybridCache.TryGetValue($"lme.jacktor:source:{rid}", out source); return _hybridCache.TryGetValue($"jacktor:source:{rid}", out source);
} }
private async Task<List<JackettResult>> SearchRaw(string query, int categoryId) private async Task<List<JackettResult>> SearchRaw(string query, int categoryId)
@ -731,7 +731,7 @@ namespace LME.JackTor
Seasons = item.Seasons Seasons = item.Seasons
}; };
_hybridCache.Set($"lme.jacktor:source:{item.Rid}", cacheItem, expires); _hybridCache.Set($"jacktor:source:{item.Rid}", cacheItem, expires);
} }
} }
} }

View File

@ -1,4 +1,4 @@
using LME.JackTor.Models; using JackTor.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Shared; using Shared;
@ -13,11 +13,11 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.JackTor namespace JackTor
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 2.1; public static double Version => 2.0;
public static JackTorSettings JackTor; public static JackTorSettings JackTor;
@ -32,7 +32,7 @@ namespace LME.JackTor
/// </summary> /// </summary>
public void Loaded(InitspaceModel initspace) public void Loaded(InitspaceModel initspace)
{ {
JackTor = new JackTorSettings("LME.JackTor", "http://127.0.0.1:9117", streamproxy: false, useproxy: false) JackTor = new JackTorSettings("JackTor", "http://127.0.0.1:9117", streamproxy: false, useproxy: false)
{ {
displayname = "JackTor", displayname = "JackTor",
displayindex = 0, displayindex = 0,
@ -68,7 +68,7 @@ namespace LME.JackTor
var defaults = JObject.FromObject(JackTor); var defaults = JObject.FromObject(JackTor);
defaults["enabled"] = true; defaults["enabled"] = true;
var conf = ModuleInvoke.Init("LME.JackTor", defaults) ?? defaults; var conf = ModuleInvoke.Init("JackTor", defaults) ?? defaults;
JackTor = conf.ToObject<JackTorSettings>(); JackTor = conf.ToObject<JackTorSettings>();
if (string.IsNullOrWhiteSpace(JackTor.jackett)) if (string.IsNullOrWhiteSpace(JackTor.jackett))
@ -78,7 +78,7 @@ namespace LME.JackTor
JackTor.host = JackTor.jackett; JackTor.host = JackTor.jackett;
// Показувати «уточнити пошук». // Показувати «уточнити пошук».
RegisterWithSearch("lme.jacktor"); RegisterWithSearch("jacktor");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -2,7 +2,7 @@ using Shared.Models.Online.Settings;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.JackTor.Models namespace JackTor.Models
{ {
public class JackTorSettings : OnlinesSettings, ICloneable public class JackTorSettings : OnlinesSettings, ICloneable
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.JackTor namespace JackTor
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -26,7 +26,7 @@ namespace LME.JackTor
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.jacktor")); online.Add(new ModuleOnlineItem(init, "jacktor"));
} }
return online; return online;

3
JackTor/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -3,14 +3,14 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using LME.KlonFUN.Models; using KlonFUN.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models.Templates; using Shared.Models.Templates;
namespace LME.KlonFUN.Controllers namespace KlonFUN.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -22,7 +22,7 @@ namespace LME.KlonFUN.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.klonfun")] [Route("lite/klonfun")]
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, string href = null, bool checksearch = 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, string href = null, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -38,13 +38,13 @@ namespace LME.KlonFUN.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
var checkResults = await invoke.Search(imdb_id, title, original_title); var checkResults = await invoke.Search(imdb_id, title, original_title);
if (checkResults != null && checkResults.Count > 0) if (checkResults != null && checkResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
} }
string itemUrl = href; string itemUrl = href;
@ -52,14 +52,14 @@ namespace LME.KlonFUN.Controllers
{ {
var searchResults = await invoke.Search(imdb_id, title, original_title); var searchResults = await invoke.Search(imdb_id, title, original_title);
if (searchResults == null || searchResults.Count == 0) if (searchResults == null || searchResults.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
if (searchResults.Count > 1) if (searchResults.Count > 1)
{ {
var similarTpl = new SimilarTpl(searchResults.Count); var similarTpl = new SimilarTpl(searchResults.Count);
foreach (SearchResult result in searchResults) foreach (SearchResult result in searchResults)
{ {
string link = $"{host}/lite/lme.klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(result.Url)}"; string link = $"{host}/lite/klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(result.Url)}";
similarTpl.Append(result.Title, result.Year > 0 ? result.Year.ToString() : string.Empty, string.Empty, link, result.Poster); similarTpl.Append(result.Title, result.Year > 0 ? result.Year.ToString() : string.Empty, string.Empty, link, result.Poster);
} }
@ -75,7 +75,7 @@ namespace LME.KlonFUN.Controllers
if (item == null || string.IsNullOrWhiteSpace(item.PlayerUrl)) if (item == null || string.IsNullOrWhiteSpace(item.PlayerUrl))
{ {
OnLog($"KlonFUN: не знайдено iframe-плеєр для {itemUrl}"); OnLog($"KlonFUN: не знайдено iframe-плеєр для {itemUrl}");
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
} }
string contentTitle = !string.IsNullOrWhiteSpace(title) ? title : item.Title; string contentTitle = !string.IsNullOrWhiteSpace(title) ? title : item.Title;
@ -89,7 +89,7 @@ namespace LME.KlonFUN.Controllers
{ {
var serialStructure = await invoke.GetSerialStructure(item.PlayerUrl); var serialStructure = await invoke.GetSerialStructure(item.PlayerUrl);
if (serialStructure == null || serialStructure.Voices.Count == 0) if (serialStructure == null || serialStructure.Voices.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
if (s == -1) if (s == -1)
{ {
@ -120,12 +120,12 @@ namespace LME.KlonFUN.Controllers
} }
if (seasons.Count == 0) if (seasons.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
var seasonTpl = new SeasonTpl(seasons.Count); var seasonTpl = new SeasonTpl(seasons.Count);
foreach (int seasonNumber in seasons) foreach (int seasonNumber in seasons)
{ {
string link = $"{host}/lite/lme.klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={seasonNumber}&href={HttpUtility.UrlEncode(itemUrl)}"; string link = $"{host}/lite/klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={seasonNumber}&href={HttpUtility.UrlEncode(itemUrl)}";
if (!string.IsNullOrWhiteSpace(t)) if (!string.IsNullOrWhiteSpace(t))
link += $"&t={HttpUtility.UrlEncode(t)}"; link += $"&t={HttpUtility.UrlEncode(t)}";
@ -142,7 +142,7 @@ namespace LME.KlonFUN.Controllers
.ToList(); .ToList();
if (voicesForSeason.Count == 0) if (voicesForSeason.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
var selectedVoiceForSeason = voicesForSeason var selectedVoiceForSeason = voicesForSeason
.FirstOrDefault(v => !string.IsNullOrWhiteSpace(t) && v.Key.Equals(t, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(v => !string.IsNullOrWhiteSpace(t) && v.Key.Equals(t, StringComparison.OrdinalIgnoreCase))
@ -151,12 +151,12 @@ namespace LME.KlonFUN.Controllers
var voiceTpl = new VoiceTpl(voicesForSeason.Count); var voiceTpl = new VoiceTpl(voicesForSeason.Count);
foreach (var voice in voicesForSeason) foreach (var voice in voicesForSeason)
{ {
string voiceLink = $"{host}/lite/lme.klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.Key)}&href={HttpUtility.UrlEncode(itemUrl)}"; string voiceLink = $"{host}/lite/klonfun?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.Key)}&href={HttpUtility.UrlEncode(itemUrl)}";
voiceTpl.Append(voice.DisplayName, voice.Key.Equals(selectedVoiceForSeason.Key, StringComparison.OrdinalIgnoreCase), voiceLink); voiceTpl.Append(voice.DisplayName, voice.Key.Equals(selectedVoiceForSeason.Key, StringComparison.OrdinalIgnoreCase), voiceLink);
} }
if (!selectedVoiceForSeason.Seasons.TryGetValue(s, out List<SerialEpisode> episodes) || episodes.Count == 0) if (!selectedVoiceForSeason.Seasons.TryGetValue(s, out List<SerialEpisode> episodes) || episodes.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
var episodeTpl = new EpisodeTpl(episodes.Count); var episodeTpl = new EpisodeTpl(episodes.Count);
foreach (SerialEpisode episode in episodes.OrderBy(e => e.Number)) foreach (SerialEpisode episode in episodes.OrderBy(e => e.Number))
@ -179,7 +179,7 @@ namespace LME.KlonFUN.Controllers
{ {
var streams = await invoke.GetMovieStreams(item.PlayerUrl); var streams = await invoke.GetMovieStreams(item.PlayerUrl);
if (streams == null || streams.Count == 0) if (streams == null || streams.Count == 0)
return OnError("lme.klonfun", refresh_proxy: true); return OnError("klonfun", refresh_proxy: true);
var movieTpl = new MovieTpl(contentTitle, contentOriginalTitle, streams.Count); var movieTpl = new MovieTpl(contentTitle, contentOriginalTitle, streams.Count);
for (int i = 0; i < streams.Count; i++) for (int i = 0; i < streams.Count; i++)

View File

@ -6,7 +6,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using HtmlAgilityPack; using HtmlAgilityPack;
using LME.KlonFUN.Models; using KlonFUN.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Shared; using Shared;
@ -14,7 +14,7 @@ using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
namespace LME.KlonFUN namespace KlonFUN
{ {
public class KlonFUNInvoke public class KlonFUNInvoke
{ {

View File

@ -16,11 +16,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Shared.Models.Events; using Shared.Models.Events;
namespace LME.KlonFUN namespace KlonFUN
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 2.1; public static double Version => 2.0;
public static ModuleConfig KlonFUN; public static ModuleConfig KlonFUN;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -41,12 +41,12 @@ namespace LME.KlonFUN
EventListener.UpdateInitFile += UpdateConfig; EventListener.UpdateInitFile += UpdateConfig;
// Додаємо підтримку "уточнити пошук". // Додаємо підтримку "уточнити пошук".
RegisterWithSearch("lme.klonfun"); RegisterWithSearch("klonfun");
} }
private void UpdateConfig() private void UpdateConfig()
{ {
KlonFUN = new ModuleConfig("LME.KlonFUN", "https://klon.fun", streamproxy: false, useproxy: false) KlonFUN = new ModuleConfig("KlonFUN", "https://klon.fun", streamproxy: false, useproxy: false)
{ {
displayname = "KlonFUN", displayname = "KlonFUN",
displayindex = 0, displayindex = 0,
@ -66,7 +66,7 @@ namespace LME.KlonFUN
["ashdi"] = ApnHelper.DefaultHost ["ashdi"] = ApnHelper.DefaultHost
}; };
var conf = ModuleInvoke.Init("LME.KlonFUN", defaults) ?? defaults; var conf = ModuleInvoke.Init("KlonFUN", defaults) ?? defaults;
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf); MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf);
conf.Remove("magic_apn"); conf.Remove("magic_apn");

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.KlonFUN.Models namespace KlonFUN.Models
{ {
public class SearchResult public class SearchResult
{ {

View File

@ -1,6 +1,6 @@
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
namespace LME.KlonFUN namespace KlonFUN
{ {
public class MagicApnSettings public class MagicApnSettings
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.KlonFUN namespace KlonFUN
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -26,7 +26,7 @@ namespace LME.KlonFUN
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.klonfun")); online.Add(new ModuleOnlineItem(init, "klonfun"));
} }
return online; return online;

3
KlonFUN/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.AnimeON.ModInit",
"online": "LME.AnimeON.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.Bamboo.ModInit",
"online": "LME.Bamboo.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.JackTor.ModInit",
"online": "LME.JackTor.OnlineApi"
}

View File

@ -1,5 +0,0 @@
{
"enable": true,
"initspace": "LME.KlonFUN.ModInit",
"online": "LME.KlonFUN.OnlineApi"
}

View File

@ -1,5 +0,0 @@
{
"enable": true,
"initspace": "LME.Makhno.ModInit",
"online": "LME.Makhno.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.Mikai.ModInit",
"online": "LME.Mikai.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.NMoonAnime.ModInit",
"online": "LME.NMoonAnime.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.StarLight.ModInit",
"online": "LME.StarLight.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.UafilmME.ModInit",
"online": "LME.UafilmME.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.Uaflix.ModInit",
"online": "LME.Uaflix.OnlineApi"
}

View File

@ -1,6 +0,0 @@
{
"enable": true,
"version": 3,
"initspace": "LME.Unimay.ModInit",
"online": "LME.Unimay.OnlineApi"
}

View File

@ -9,11 +9,11 @@ using Shared;
using Shared.Models.Templates; using Shared.Models.Templates;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models; using Shared.Models;
using LME.Makhno.Models; using Makhno.Models;
namespace LME.Makhno namespace Makhno
{ {
[Route("lite/lme.makhno")] [Route("lite/makhno")]
public class MakhnoController : BaseOnlineController public class MakhnoController : BaseOnlineController
{ {
private readonly ProxyManager proxyManager; private readonly ProxyManager proxyManager;
@ -42,7 +42,7 @@ namespace LME.Makhno
TryEnableMagicApn(init); TryEnableMagicApn(init);
Initialization(init); Initialization(init);
OnLog($"lme.makhno: {title} (serial={serial}, s={s}, season={season}, t={t})"); OnLog($"Makhno: {title} (serial={serial}, s={s}, season={season}, t={t})");
var invoke = new MakhnoInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new MakhnoInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
@ -75,14 +75,14 @@ namespace LME.Makhno
if (resolved == null || string.IsNullOrEmpty(resolved.PlayUrl)) if (resolved == null || string.IsNullOrEmpty(resolved.PlayUrl))
return OnError(); return OnError();
var playerData = await InvokeCache<PlayerData>($"lme.makhno:player:{resolved.PlayUrl}", TimeSpan.FromMinutes(10), async () => var playerData = await InvokeCache<PlayerData>($"makhno:player:{resolved.PlayUrl}", TimeSpan.FromMinutes(10), async () =>
{ {
return await invoke.GetPlayerData(resolved.PlayUrl); return await invoke.GetPlayerData(resolved.PlayUrl);
}); });
if (playerData?.Voices == null || !playerData.Voices.Any()) if (playerData?.Voices == null || !playerData.Voices.Any())
{ {
OnLog("lme.makhno Play: no voices parsed"); OnLog("Makhno Play: no voices parsed");
return OnError(); return OnError();
} }
@ -99,7 +99,7 @@ namespace LME.Makhno
{ {
if (episode.Id == episodeId && !string.IsNullOrEmpty(episode.File)) if (episode.Id == episodeId && !string.IsNullOrEmpty(episode.File))
{ {
OnLog($"lme.makhno Play: Found episode {episode.Title}, stream: {episode.File}"); OnLog($"Makhno Play: Found episode {episode.Title}, stream: {episode.File}");
string streamUrl = BuildStreamUrl(init, episode.File); string streamUrl = BuildStreamUrl(init, episode.File);
string episodeTitle = $"{title ?? original_title} - {episode.Title}"; string episodeTitle = $"{title ?? original_title} - {episode.Title}";
@ -111,7 +111,7 @@ namespace LME.Makhno
} }
} }
OnLog("lme.makhno Play: Episode not found"); OnLog("Makhno Play: Episode not found");
return OnError(); return OnError();
} }
@ -127,21 +127,21 @@ namespace LME.Makhno
TryEnableMagicApn(init); TryEnableMagicApn(init);
Initialization(init); Initialization(init);
OnLog($"lme.makhno PlayMovie: {title} ({year}) play={play}"); OnLog($"Makhno PlayMovie: {title} ({year}) play={play}");
var invoke = new MakhnoInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new MakhnoInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
var resolved = await ResolvePlaySource(imdb_id, serial: 0, invoke); var resolved = await ResolvePlaySource(imdb_id, serial: 0, invoke);
if (resolved == null || string.IsNullOrEmpty(resolved.PlayUrl)) if (resolved == null || string.IsNullOrEmpty(resolved.PlayUrl))
return OnError(); return OnError();
var playerData = await InvokeCache<PlayerData>($"lme.makhno:player:{resolved.PlayUrl}", TimeSpan.FromMinutes(10), async () => var playerData = await InvokeCache<PlayerData>($"makhno:player:{resolved.PlayUrl}", TimeSpan.FromMinutes(10), async () =>
{ {
return await invoke.GetPlayerData(resolved.PlayUrl); return await invoke.GetPlayerData(resolved.PlayUrl);
}); });
if (playerData?.File == null) if (playerData?.File == null)
{ {
OnLog("lme.makhno PlayMovie: no file parsed"); OnLog("Makhno PlayMovie: no file parsed");
return OnError(); return OnError();
} }
@ -156,7 +156,7 @@ namespace LME.Makhno
private async Task<ActionResult> HandleMovie(string playUrl, string imdb_id, string title, string original_title, int year, bool rjson, MakhnoInvoke invoke) private async Task<ActionResult> HandleMovie(string playUrl, string imdb_id, string title, string original_title, int year, bool rjson, MakhnoInvoke invoke)
{ {
var init = ModInit.Makhno; var init = ModInit.Makhno;
var playerData = await InvokeCache<PlayerData>($"lme.makhno:player:{playUrl}", TimeSpan.FromMinutes(10), async () => var playerData = await InvokeCache<PlayerData>($"makhno:player:{playUrl}", TimeSpan.FromMinutes(10), async () =>
{ {
return await invoke.GetPlayerData(playUrl); return await invoke.GetPlayerData(playUrl);
}); });
@ -177,7 +177,7 @@ namespace LME.Makhno
if (movieStreams.Count == 0) if (movieStreams.Count == 0)
{ {
OnLog("lme.makhno HandleMovie: no file parsed"); OnLog("Makhno HandleMovie: no file parsed");
return OnError(); return OnError();
} }
@ -200,14 +200,14 @@ namespace LME.Makhno
{ {
var init = ModInit.Makhno; var init = ModInit.Makhno;
var playerData = await InvokeCache<PlayerData>($"lme.makhno:player:{playUrl}", TimeSpan.FromMinutes(10), async () => var playerData = await InvokeCache<PlayerData>($"makhno:player:{playUrl}", TimeSpan.FromMinutes(10), async () =>
{ {
return await invoke.GetPlayerData(playUrl); return await invoke.GetPlayerData(playUrl);
}); });
if (playerData?.Voices == null || !playerData.Voices.Any()) if (playerData?.Voices == null || !playerData.Voices.Any())
{ {
OnLog("lme.makhno HandleSerial: no voices parsed"); OnLog("Makhno HandleSerial: no voices parsed");
return OnError(); return OnError();
} }
@ -270,7 +270,7 @@ namespace LME.Makhno
string voiceParam = seasonVoiceIndex.HasValue ? $"&t={seasonVoiceIndex.Value}" : string.Empty; string voiceParam = seasonVoiceIndex.HasValue ? $"&t={seasonVoiceIndex.Value}" : string.Empty;
string seasonName = seasonItem.HasValue ? seasonItem.Value.Season?.Title ?? $"Сезон {seasonNumber}" : $"Сезон {seasonNumber}"; string seasonName = seasonItem.HasValue ? seasonItem.Value.Season?.Title ?? $"Сезон {seasonNumber}" : $"Сезон {seasonNumber}";
string link = $"{host}/lite/lme.makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={seasonNumber}{voiceParam}"; string link = $"{host}/lite/makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={seasonNumber}{voiceParam}";
season_tpl.Append(seasonName, link, seasonNumber.ToString()); season_tpl.Append(seasonName, link, seasonNumber.ToString());
} }
@ -340,7 +340,7 @@ namespace LME.Makhno
string voiceParam = seasonVoiceIndexForTpl.HasValue ? $"&t={seasonVoiceIndexForTpl.Value}" : string.Empty; string voiceParam = seasonVoiceIndexForTpl.HasValue ? $"&t={seasonVoiceIndexForTpl.Value}" : string.Empty;
string seasonName = seasonItem.HasValue ? seasonItem.Value.Season?.Title ?? $"Сезон {seasonNumber}" : $"Сезон {seasonNumber}"; string seasonName = seasonItem.HasValue ? seasonItem.Value.Season?.Title ?? $"Сезон {seasonNumber}" : $"Сезон {seasonNumber}";
string link = $"{host}/lite/lme.makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={seasonNumber}{voiceParam}"; string link = $"{host}/lite/makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={seasonNumber}{voiceParam}";
seasonTplForVoice.Append(seasonName, link, seasonNumber.ToString()); seasonTplForVoice.Append(seasonName, link, seasonNumber.ToString());
} }
@ -357,11 +357,11 @@ namespace LME.Makhno
bool sameSeasonSet = seasonsForVoice.Select(s => s.Number).ToHashSet().SetEquals(selectedVoiceSeasonSet); bool sameSeasonSet = seasonsForVoice.Select(s => s.Number).ToHashSet().SetEquals(selectedVoiceSeasonSet);
if (hasRequestedSeason && sameSeasonSet) if (hasRequestedSeason && sameSeasonSet)
{ {
voiceLink = $"{host}/lite/lme.makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={requestedSeason}&t={i}"; voiceLink = $"{host}/lite/makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season={requestedSeason}&t={i}";
} }
else else
{ {
voiceLink = $"{host}/lite/lme.makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season=-1&t={i}"; voiceLink = $"{host}/lite/makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season=-1&t={i}";
} }
bool isActive = selectedVoice == i.ToString(); bool isActive = selectedVoice == i.ToString();
@ -377,7 +377,7 @@ namespace LME.Makhno
bool hasRequestedSeason = seasonsForVoice.Any(s => s.Number == requestedSeason); bool hasRequestedSeason = seasonsForVoice.Any(s => s.Number == requestedSeason);
if (!hasRequestedSeason) if (!hasRequestedSeason)
{ {
string redirectUrl = $"{host}/lite/lme.makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season=-1&t={voiceIndex}"; string redirectUrl = $"{host}/lite/makhno?imdb_id={imdb_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&season=-1&t={voiceIndex}";
return UpdateService.Validate(Redirect(redirectUrl)); return UpdateService.Validate(Redirect(redirectUrl));
} }
@ -448,7 +448,7 @@ namespace LME.Makhno
if (string.IsNullOrWhiteSpace(imdbId)) if (string.IsNullOrWhiteSpace(imdbId))
return null; return null;
string cacheKey = $"lme.makhno:wormhole:{imdbId}"; string cacheKey = $"makhno:wormhole:{imdbId}";
string playUrl = await InvokeCache<string>(cacheKey, TimeSpan.FromMinutes(5), async () => string playUrl = await InvokeCache<string>(cacheKey, TimeSpan.FromMinutes(5), async () =>
{ {
return await invoke.GetWormholePlay(imdbId); return await invoke.GetWormholePlay(imdbId);
@ -530,7 +530,7 @@ namespace LME.Makhno
return; return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init); ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"lme.makhno: увімкнено magic_apn для Ashdi (player={player ?? "unknown"})."); OnLog($"Makhno: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
} }
private class ResolveResult private class ResolveResult

View File

@ -10,9 +10,9 @@ using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using LME.Makhno.Models; using Makhno.Models;
namespace LME.Makhno namespace Makhno
{ {
public class MakhnoInvoke public class MakhnoInvoke
{ {
@ -57,7 +57,7 @@ namespace LME.Makhno
} }
catch (Exception ex) catch (Exception ex)
{ {
_onLog($"lme.makhno wormhole error: {ex.Message}"); _onLog($"Makhno wormhole error: {ex.Message}");
return null; return null;
} }
} }
@ -84,7 +84,7 @@ namespace LME.Makhno
if (ApnHelper.IsAshdiUrl(sourceUrl) && ApnHelper.IsEnabled(_init) && string.IsNullOrWhiteSpace(_init.webcorshost)) if (ApnHelper.IsAshdiUrl(sourceUrl) && ApnHelper.IsEnabled(_init) && string.IsNullOrWhiteSpace(_init.webcorshost))
requestUrl = ApnHelper.WrapUrl(_init, sourceUrl); requestUrl = ApnHelper.WrapUrl(_init, sourceUrl);
_onLog($"lme.makhno getting player data from: {requestUrl}"); _onLog($"Makhno getting player data from: {requestUrl}");
var response = await HttpGet(requestUrl, headers); var response = await HttpGet(requestUrl, headers);
if (string.IsNullOrEmpty(response)) if (string.IsNullOrEmpty(response))
@ -133,14 +133,14 @@ namespace LME.Makhno
string jsonData = ExtractPlayerJson(html); string jsonData = ExtractPlayerJson(html);
if (jsonData == null) if (jsonData == null)
_onLog("lme.makhno ParsePlayerData: file array not found"); _onLog("Makhno ParsePlayerData: file array not found");
else else
_onLog($"lme.makhno ParsePlayerData: file array length={jsonData.Length}"); _onLog($"Makhno ParsePlayerData: file array length={jsonData.Length}");
if (!string.IsNullOrEmpty(jsonData)) if (!string.IsNullOrEmpty(jsonData))
{ {
var voices = ParseVoicesJson(jsonData); var voices = ParseVoicesJson(jsonData);
var movies = ParseMovieVariantsJson(jsonData); var movies = ParseMovieVariantsJson(jsonData);
_onLog($"lme.makhno ParsePlayerData: voices={voices?.Count ?? 0}"); _onLog($"Makhno ParsePlayerData: voices={voices?.Count ?? 0}");
return new PlayerData return new PlayerData
{ {
File = movies.FirstOrDefault()?.File, File = movies.FirstOrDefault()?.File,
@ -153,7 +153,7 @@ namespace LME.Makhno
var m3u8Match = Regex.Match(html, @"(https?://[^""'\s>]+\.m3u8[^""'\s>]*)", RegexOptions.IgnoreCase); var m3u8Match = Regex.Match(html, @"(https?://[^""'\s>]+\.m3u8[^""'\s>]*)", RegexOptions.IgnoreCase);
if (m3u8Match.Success) if (m3u8Match.Success)
{ {
_onLog("lme.makhno ParsePlayerData: fallback m3u8 match"); _onLog("Makhno ParsePlayerData: fallback m3u8 match");
return new PlayerData return new PlayerData
{ {
File = m3u8Match.Groups[1].Value, File = m3u8Match.Groups[1].Value,
@ -174,7 +174,7 @@ namespace LME.Makhno
var sourceMatch = Regex.Match(html, @"<source[^>]*src=[""']([^""']+)[""']", RegexOptions.IgnoreCase); var sourceMatch = Regex.Match(html, @"<source[^>]*src=[""']([^""']+)[""']", RegexOptions.IgnoreCase);
if (sourceMatch.Success) if (sourceMatch.Success)
{ {
_onLog("lme.makhno ParsePlayerData: fallback source match"); _onLog("Makhno ParsePlayerData: fallback source match");
return new PlayerData return new PlayerData
{ {
File = sourceMatch.Groups[1].Value, File = sourceMatch.Groups[1].Value,
@ -196,7 +196,7 @@ namespace LME.Makhno
} }
catch (Exception ex) catch (Exception ex)
{ {
_onLog($"lme.makhno ParsePlayerData error: {ex.Message}"); _onLog($"Makhno ParsePlayerData error: {ex.Message}");
return null; return null;
} }
} }
@ -263,7 +263,7 @@ namespace LME.Makhno
} }
catch (Exception ex) catch (Exception ex)
{ {
_onLog($"lme.makhno ParseVoicesJson error: {ex.Message}"); _onLog($"Makhno ParseVoicesJson error: {ex.Message}");
return new List<Voice>(); return new List<Voice>();
} }
} }
@ -298,7 +298,7 @@ namespace LME.Makhno
} }
catch (Exception ex) catch (Exception ex)
{ {
_onLog($"lme.makhno ParseMovieVariantsJson error: {ex.Message}"); _onLog($"Makhno ParseMovieVariantsJson error: {ex.Message}");
return new List<MovieVariant>(); return new List<MovieVariant>();
} }
} }

View File

@ -20,11 +20,11 @@ using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Makhno namespace Makhno
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 3.1; public static double Version => 3.0;
public static OnlinesSettings Makhno; public static OnlinesSettings Makhno;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -41,7 +41,7 @@ namespace LME.Makhno
/// </summary> /// </summary>
public void Loaded(InitspaceModel initspace) public void Loaded(InitspaceModel initspace)
{ {
Makhno = new OnlinesSettings("LME.Makhno", "https://wh.lme.isroot.in", streamproxy: false, useproxy: false) Makhno = new OnlinesSettings("Makhno", "https://wh.lme.isroot.in", streamproxy: false, useproxy: false)
{ {
displayname = "Махно", displayname = "Махно",
displayindex = 0, displayindex = 0,
@ -60,7 +60,7 @@ namespace LME.Makhno
["ashdi"] = ApnHelper.DefaultHost ["ashdi"] = ApnHelper.DefaultHost
}; };
var conf = ModuleInvoke.Init("LME.Makhno", defaults) ?? defaults; var conf = ModuleInvoke.Init("Makhno", defaults) ?? defaults;
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf); MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf);
conf.Remove("magic_apn"); conf.Remove("magic_apn");
@ -84,7 +84,7 @@ namespace LME.Makhno
} }
// Виводити "уточнити пошук" // Виводити "уточнити пошук"
RegisterWithSearch("lme.makhno"); RegisterWithSearch("makhno");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.Makhno.Models namespace Makhno.Models
{ {
public class PlayerData public class PlayerData
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Makhno namespace Makhno
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -26,7 +26,7 @@ namespace LME.Makhno
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.makhno")); online.Add(new ModuleOnlineItem(init, "makhno"));
} }
return online; return online;

3
Makhno/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -4,14 +4,14 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using LME.Mikai.Models; using Mikai.Models;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models.Templates; using Shared.Models.Templates;
namespace LME.Mikai.Controllers namespace Mikai.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -23,7 +23,7 @@ namespace LME.Mikai.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.mikai")] [Route("lite/mikai")]
public async 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, bool checksearch = false) public async 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, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -38,34 +38,34 @@ namespace LME.Mikai.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
var checkResults = await invoke.Search(title, original_title, year); var checkResults = await invoke.Search(title, original_title, year);
if (checkResults != null && checkResults.Count > 0) if (checkResults != null && checkResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
} }
OnLog($"Mikai Index: title={title}, original_title={original_title}, serial={serial}, s={s}, t={t}, year={year}"); OnLog($"Mikai Index: title={title}, original_title={original_title}, serial={serial}, s={s}, t={t}, year={year}");
var searchResults = await invoke.Search(title, original_title, year); var searchResults = await invoke.Search(title, original_title, year);
if (searchResults == null || searchResults.Count == 0) if (searchResults == null || searchResults.Count == 0)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
var selected = searchResults.FirstOrDefault(); var selected = searchResults.FirstOrDefault();
if (selected == null) if (selected == null)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
var details = await invoke.GetDetails(selected.Id); var details = await invoke.GetDetails(selected.Id);
if (details == null || details.Players == null || details.Players.Count == 0) if (details == null || details.Players == null || details.Players.Count == 0)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
bool isSerial = serial == 1 || (serial == -1 && !string.Equals(details.Format, "movie", StringComparison.OrdinalIgnoreCase)); bool isSerial = serial == 1 || (serial == -1 && !string.Equals(details.Format, "movie", StringComparison.OrdinalIgnoreCase));
var seasonDetails = await CollectSeasonDetails(details, invoke); var seasonDetails = await CollectSeasonDetails(details, invoke);
var voices = BuildVoices(seasonDetails); var voices = BuildVoices(seasonDetails);
if (voices.Count == 0) if (voices.Count == 0)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
string displayTitle = title ?? details.Details?.Names?.Name ?? original_title; string displayTitle = title ?? details.Details?.Names?.Name ?? original_title;
@ -82,14 +82,14 @@ namespace LME.Mikai.Controllers
.ToList(); .ToList();
if (seasonNumbers.Count == 0) if (seasonNumbers.Count == 0)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
if (s == -1) if (s == -1)
{ {
var seasonTpl = new SeasonTpl(seasonNumbers.Count); var seasonTpl = new SeasonTpl(seasonNumbers.Count);
foreach (var seasonNumber in seasonNumbers) foreach (var seasonNumber in seasonNumbers)
{ {
string link = $"{host}/lite/lme.mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={seasonNumber}"; string link = $"{host}/lite/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={seasonNumber}";
if (restrictByVoice) if (restrictByVoice)
link += $"&t={HttpUtility.UrlEncode(t)}"; link += $"&t={HttpUtility.UrlEncode(t)}";
seasonTpl.Append($"{seasonNumber}", link, seasonNumber.ToString()); seasonTpl.Append($"{seasonNumber}", link, seasonNumber.ToString());
@ -105,7 +105,7 @@ namespace LME.Mikai.Controllers
.ToList(); .ToList();
if (!voicesForSeason.Any()) if (!voicesForSeason.Any())
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
if (string.IsNullOrEmpty(t)) if (string.IsNullOrEmpty(t))
t = voicesForSeason[0].Key; t = voicesForSeason[0].Key;
@ -119,7 +119,7 @@ namespace LME.Mikai.Controllers
{ {
var targetSeasonSet = GetSeasonSet(voice.Value); var targetSeasonSet = GetSeasonSet(voice.Value);
bool sameSeasonSet = targetSeasonSet.SetEquals(selectedSeasonSet); bool sameSeasonSet = targetSeasonSet.SetEquals(selectedSeasonSet);
string voiceLink = $"{host}/lite/lme.mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1"; string voiceLink = $"{host}/lite/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1";
if (sameSeasonSet) if (sameSeasonSet)
voiceLink += $"&s={s}&t={HttpUtility.UrlEncode(voice.Key)}"; voiceLink += $"&s={s}&t={HttpUtility.UrlEncode(voice.Key)}";
else else
@ -129,7 +129,7 @@ namespace LME.Mikai.Controllers
if (!voices.ContainsKey(t) || !voices[t].Seasons.ContainsKey(s)) if (!voices.ContainsKey(t) || !voices[t].Seasons.ContainsKey(s))
{ {
string redirectUrl = $"{host}/lite/lme.mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s=-1&t={HttpUtility.UrlEncode(t)}"; string redirectUrl = $"{host}/lite/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s=-1&t={HttpUtility.UrlEncode(t)}";
return Redirect(redirectUrl); return Redirect(redirectUrl);
} }
@ -144,7 +144,7 @@ namespace LME.Mikai.Controllers
if (NeedsResolve(voices[t].ProviderName, streamLink)) if (NeedsResolve(voices[t].ProviderName, streamLink))
{ {
string callUrl = $"{host}/lite/lme.mikai/play?url={HttpUtility.UrlEncode(streamLink)}&title={HttpUtility.UrlEncode(displayTitle)}&serial=1"; string callUrl = $"{host}/lite/mikai/play?url={HttpUtility.UrlEncode(streamLink)}&title={HttpUtility.UrlEncode(displayTitle)}&serial=1";
episodeTpl.Append(episodeName, displayTitle, s.ToString(), ep.Number.ToString(), accsArgs(callUrl), "call"); episodeTpl.Append(episodeName, displayTitle, s.ToString(), ep.Number.ToString(), accsArgs(callUrl), "call");
} }
else else
@ -178,14 +178,14 @@ namespace LME.Mikai.Controllers
foreach (var ashdiStream in ashdiStreams) foreach (var ashdiStream in ashdiStreams)
{ {
string optionName = $"{voice.DisplayName} {ashdiStream.title}"; string optionName = $"{voice.DisplayName} {ashdiStream.title}";
string ashdiCallUrl = $"{host}/lite/lme.mikai/play?url={HttpUtility.UrlEncode(ashdiStream.link)}&title={HttpUtility.UrlEncode(displayTitle)}"; string ashdiCallUrl = $"{host}/lite/mikai/play?url={HttpUtility.UrlEncode(ashdiStream.link)}&title={HttpUtility.UrlEncode(displayTitle)}";
movieTpl.Append(optionName, accsArgs(ashdiCallUrl), "call"); movieTpl.Append(optionName, accsArgs(ashdiCallUrl), "call");
} }
continue; continue;
} }
} }
string callUrl = $"{host}/lite/lme.mikai/play?url={HttpUtility.UrlEncode(episode.Url)}&title={HttpUtility.UrlEncode(displayTitle)}"; string callUrl = $"{host}/lite/mikai/play?url={HttpUtility.UrlEncode(episode.Url)}&title={HttpUtility.UrlEncode(displayTitle)}";
movieTpl.Append(voice.DisplayName, accsArgs(callUrl), "call"); movieTpl.Append(voice.DisplayName, accsArgs(callUrl), "call");
} }
else else
@ -196,14 +196,14 @@ namespace LME.Mikai.Controllers
} }
if (movieTpl.data == null || movieTpl.data.Count == 0) if (movieTpl.data == null || movieTpl.data.Count == 0)
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
return rjson return rjson
? Content(movieTpl.ToJson(), "application/json; charset=utf-8") ? Content(movieTpl.ToJson(), "application/json; charset=utf-8")
: Content(movieTpl.ToHtml(), "text/html; charset=utf-8"); : Content(movieTpl.ToHtml(), "text/html; charset=utf-8");
} }
[HttpGet("lite/lme.mikai/play")] [HttpGet("lite/mikai/play")]
public async Task<ActionResult> Play(string url, string title = null, int serial = 0) public async Task<ActionResult> Play(string url, string title = null, int serial = 0)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -214,14 +214,14 @@ namespace LME.Mikai.Controllers
TryEnableMagicApn(init); TryEnableMagicApn(init);
if (string.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
var invoke = new MikaiInvoke(init, hybridCache, OnLog, _proxyManager, httpHydra); var invoke = new MikaiInvoke(init, hybridCache, OnLog, _proxyManager, httpHydra);
OnLog($"Mikai Play: url={url}, serial={serial}"); OnLog($"Mikai Play: url={url}, serial={serial}");
string streamLink = await invoke.ResolveVideoUrl(url, serial == 1); string streamLink = await invoke.ResolveVideoUrl(url, serial == 1);
if (string.IsNullOrEmpty(streamLink)) if (string.IsNullOrEmpty(streamLink))
return OnError("lme.mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
List<HeadersModel> streamHeaders = null; List<HeadersModel> streamHeaders = null;
bool forceProxy = false; bool forceProxy = false;

View File

@ -6,13 +6,13 @@ using System.Threading.Tasks;
using System.Web; using System.Web;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using LME.Mikai.Models; using Mikai.Models;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
namespace LME.Mikai namespace Mikai
{ {
public class MikaiInvoke public class MikaiInvoke
{ {

View File

@ -21,11 +21,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Mikai namespace Mikai
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 4.1; public static double Version => 4.0;
public static OnlinesSettings Mikai; public static OnlinesSettings Mikai;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -44,7 +44,7 @@ namespace LME.Mikai
{ {
Mikai = new OnlinesSettings("LME.Mikai", "https://mikai.me", streamproxy: false, useproxy: false) Mikai = new OnlinesSettings("Mikai", "https://mikai.me", streamproxy: false, useproxy: false)
{ {
displayname = "Mikai", displayname = "Mikai",
displayindex = 0, displayindex = 0,
@ -65,7 +65,7 @@ namespace LME.Mikai
["ashdi"] = ApnHelper.DefaultHost ["ashdi"] = ApnHelper.DefaultHost
}; };
var conf = ModuleInvoke.Init("LME.Mikai", defaults) ?? defaults; var conf = ModuleInvoke.Init("Mikai", defaults) ?? defaults;
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf); MagicApnAshdiHost = ApnHelper.TryGetMagicAshdiHost(conf);
conf.Remove("magic_apn"); conf.Remove("magic_apn");
@ -86,7 +86,7 @@ namespace LME.Mikai
} }
// Виводити "уточнити пошук" // Виводити "уточнити пошук"
RegisterWithSearch("lme.mikai"); RegisterWithSearch("mikai");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.Mikai.Models namespace Mikai.Models
{ {
public class SearchResponse public class SearchResponse
{ {

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.Mikai.Models namespace Mikai.Models
{ {
public class MikaiVoiceInfo public class MikaiVoiceInfo
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.Mikai namespace Mikai
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -30,7 +30,7 @@ namespace LME.Mikai
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.mikai")); online.Add(new ModuleOnlineItem(init, "mikai"));
} }
return online; return online;

3
Mikai/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using LME.NMoonAnime.Models; using NMoonAnime.Models;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
@ -13,7 +13,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace LME.NMoonAnime.Controllers namespace NMoonAnime.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -25,7 +25,7 @@ namespace LME.NMoonAnime.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.nmoonanime")] [Route("lite/nmoonanime")]
public async 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 mal_id, string t, int s = -1, bool rjson = false, bool checksearch = false) public async 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 mal_id, string t, int s = -1, bool rjson = false, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -40,20 +40,20 @@ namespace LME.NMoonAnime.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
var checkResults = await invoke.Search(imdb_id, effectiveMalId, title, year); var checkResults = await invoke.Search(imdb_id, effectiveMalId, title, year);
if (checkResults != null && checkResults.Count > 0) if (checkResults != null && checkResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
} }
OnLog($"NMoonAnime: назва={title}, source={source}, imdb={imdb_id}, kinopoisk_id(як mal_id)={kinopoisk_id}, mal_id_ефективний={effectiveMalId}, рік={year}, серіал={serial}, сезон={s}, озвучка={t}"); OnLog($"NMoonAnime: назва={title}, source={source}, imdb={imdb_id}, kinopoisk_id(як mal_id)={kinopoisk_id}, mal_id_ефективний={effectiveMalId}, рік={year}, серіал={serial}, сезон={s}, озвучка={t}");
var seasons = await invoke.Search(imdb_id, effectiveMalId, title, year); var seasons = await invoke.Search(imdb_id, effectiveMalId, title, year);
if (seasons == null || seasons.Count == 0) if (seasons == null || seasons.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
bool isSeries = serial == 1; bool isSeries = serial == 1;
NMoonAnimeSeasonContent firstSeasonData = null; NMoonAnimeSeasonContent firstSeasonData = null;
@ -62,7 +62,7 @@ namespace LME.NMoonAnime.Controllers
{ {
firstSeasonData = await invoke.GetSeasonContent(seasons[0]); firstSeasonData = await invoke.GetSeasonContent(seasons[0]);
if (firstSeasonData == null || firstSeasonData.Voices.Count == 0) if (firstSeasonData == null || firstSeasonData.Voices.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
isSeries = firstSeasonData.IsSeries; isSeries = firstSeasonData.IsSeries;
} }
@ -75,7 +75,7 @@ namespace LME.NMoonAnime.Controllers
return await RenderMovie(invoke, seasons, title, original_title, firstSeasonData, rjson); return await RenderMovie(invoke, seasons, title, original_title, firstSeasonData, rjson);
} }
[HttpGet("lite/lme.nmoonanime/play")] [HttpGet("lite/nmoonanime/play")]
public async Task<ActionResult> Play(string file, string title = null) public async Task<ActionResult> Play(string file, string title = null)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -85,12 +85,12 @@ namespace LME.NMoonAnime.Controllers
return Forbid(); return Forbid();
if (string.IsNullOrWhiteSpace(file)) if (string.IsNullOrWhiteSpace(file))
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
var invoke = new NMoonAnimeInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new NMoonAnimeInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
var streams = invoke.ParseStreams(file); var streams = invoke.ParseStreams(file);
if (streams == null || streams.Count == 0) if (streams == null || streams.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
if (streams.Count == 1) if (streams.Count == 1)
{ {
@ -107,7 +107,7 @@ namespace LME.NMoonAnime.Controllers
} }
if (!streamQuality.Any()) if (!streamQuality.Any())
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
var first = streamQuality.Firts(); var first = streamQuality.Firts();
string json = VideoTpl.ToJson("play", first.link, title ?? string.Empty, streamquality: streamQuality); string json = VideoTpl.ToJson("play", first.link, title ?? string.Empty, streamquality: streamQuality);
@ -133,7 +133,7 @@ namespace LME.NMoonAnime.Controllers
.ToList(); .ToList();
if (orderedSeasons.Count == 0) if (orderedSeasons.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
if (selectedSeason == -1) if (selectedSeason == -1)
{ {
@ -154,14 +154,14 @@ namespace LME.NMoonAnime.Controllers
var currentSeason = orderedSeasons.FirstOrDefault(s => s.SeasonNumber == selectedSeason) ?? orderedSeasons[0]; var currentSeason = orderedSeasons.FirstOrDefault(s => s.SeasonNumber == selectedSeason) ?? orderedSeasons[0];
var seasonData = await invoke.GetSeasonContent(currentSeason); var seasonData = await invoke.GetSeasonContent(currentSeason);
if (seasonData == null) if (seasonData == null)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
var voices = seasonData.Voices var voices = seasonData.Voices
.Where(v => v != null && v.Episodes != null && v.Episodes.Count > 0) .Where(v => v != null && v.Episodes != null && v.Episodes.Count > 0)
.ToList(); .ToList();
if (voices.Count == 0) if (voices.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
int activeVoiceIndex = ParseVoiceIndex(selectedVoice, voices.Count); int activeVoiceIndex = ParseVoiceIndex(selectedVoice, voices.Count);
var voiceTpl = new VoiceTpl(voices.Count); var voiceTpl = new VoiceTpl(voices.Count);
@ -180,7 +180,7 @@ namespace LME.NMoonAnime.Controllers
.ToList(); .ToList();
if (episodes.Count == 0) if (episodes.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
string displayTitle = !string.IsNullOrWhiteSpace(title) string displayTitle = !string.IsNullOrWhiteSpace(title)
? title ? title
@ -193,7 +193,7 @@ namespace LME.NMoonAnime.Controllers
{ {
int episodeNumber = episode.Number <= 0 ? 1 : episode.Number; int episodeNumber = episode.Number <= 0 ? 1 : episode.Number;
string episodeName = string.IsNullOrWhiteSpace(episode.Name) ? $"Епізод {episodeNumber}" : episode.Name; string episodeName = string.IsNullOrWhiteSpace(episode.Name) ? $"Епізод {episodeNumber}" : episode.Name;
string callUrl = $"{host}/lite/lme.nmoonanime/play?file={HttpUtility.UrlEncode(episode.File)}&title={HttpUtility.UrlEncode(displayTitle)}"; string callUrl = $"{host}/lite/nmoonanime/play?file={HttpUtility.UrlEncode(episode.File)}&title={HttpUtility.UrlEncode(displayTitle)}";
episodeTpl.Append(episodeName, displayTitle, currentSeason.SeasonNumber.ToString(), episodeNumber.ToString(), accsArgs(callUrl), "call"); episodeTpl.Append(episodeName, displayTitle, currentSeason.SeasonNumber.ToString(), episodeNumber.ToString(), accsArgs(callUrl), "call");
} }
@ -218,14 +218,14 @@ namespace LME.NMoonAnime.Controllers
.FirstOrDefault(); .FirstOrDefault();
if (currentSeason == null) if (currentSeason == null)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
NMoonAnimeSeasonContent seasonData = firstSeasonData; NMoonAnimeSeasonContent seasonData = firstSeasonData;
if (seasonData == null || !string.Equals(seasonData.Url, currentSeason.Url, StringComparison.OrdinalIgnoreCase)) if (seasonData == null || !string.Equals(seasonData.Url, currentSeason.Url, StringComparison.OrdinalIgnoreCase))
seasonData = await invoke.GetSeasonContent(currentSeason); seasonData = await invoke.GetSeasonContent(currentSeason);
if (seasonData == null || seasonData.Voices.Count == 0) if (seasonData == null || seasonData.Voices.Count == 0)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
string displayTitle = !string.IsNullOrWhiteSpace(title) string displayTitle = !string.IsNullOrWhiteSpace(title)
? title ? title
@ -249,13 +249,13 @@ namespace LME.NMoonAnime.Controllers
continue; continue;
string voiceName = string.IsNullOrWhiteSpace(voice.Name) ? $"Озвучка {fallbackIndex}" : voice.Name; string voiceName = string.IsNullOrWhiteSpace(voice.Name) ? $"Озвучка {fallbackIndex}" : voice.Name;
string callUrl = $"{host}/lite/lme.nmoonanime/play?file={HttpUtility.UrlEncode(file)}&title={HttpUtility.UrlEncode(displayTitle)}"; string callUrl = $"{host}/lite/nmoonanime/play?file={HttpUtility.UrlEncode(file)}&title={HttpUtility.UrlEncode(displayTitle)}";
movieTpl.Append(voiceName, accsArgs(callUrl), "call"); movieTpl.Append(voiceName, accsArgs(callUrl), "call");
fallbackIndex++; fallbackIndex++;
} }
if (movieTpl.IsEmpty) if (movieTpl.IsEmpty)
return OnError("lme.nmoonanime", refresh_proxy: true); return OnError("nmoonanime", refresh_proxy: true);
return rjson return rjson
? Content(movieTpl.ToJson(), "application/json; charset=utf-8") ? Content(movieTpl.ToJson(), "application/json; charset=utf-8")
@ -265,7 +265,7 @@ namespace LME.NMoonAnime.Controllers
private string BuildIndexUrl(string imdbId, long kinopoiskId, string title, string originalTitle, int year, int serial, string malId, int season, string voice) private string BuildIndexUrl(string imdbId, long kinopoiskId, string title, string originalTitle, int year, int serial, string malId, int season, string voice)
{ {
var url = new StringBuilder(); var url = new StringBuilder();
url.Append($"{host}/lite/lme.nmoonanime?imdb_id={HttpUtility.UrlEncode(imdbId)}"); url.Append($"{host}/lite/nmoonanime?imdb_id={HttpUtility.UrlEncode(imdbId)}");
url.Append($"&kinopoisk_id={kinopoiskId}"); url.Append($"&kinopoisk_id={kinopoiskId}");
url.Append($"&title={HttpUtility.UrlEncode(title)}"); url.Append($"&title={HttpUtility.UrlEncode(title)}");
url.Append($"&original_title={HttpUtility.UrlEncode(originalTitle)}"); url.Append($"&original_title={HttpUtility.UrlEncode(originalTitle)}");

View File

@ -15,11 +15,11 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.NMoonAnime namespace NMoonAnime
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 2.1; public static double Version => 2.0;
public static OnlinesSettings NMoonAnime; public static OnlinesSettings NMoonAnime;
@ -36,7 +36,7 @@ namespace LME.NMoonAnime
/// </summary> /// </summary>
public void Loaded(InitspaceModel initspace) public void Loaded(InitspaceModel initspace)
{ {
NMoonAnime = new OnlinesSettings("LME.NMoonAnime", "https://moonanime.art", "https://apx.lme.isroot.in", streamproxy: false, useproxy: false) NMoonAnime = new OnlinesSettings("NMoonAnime", "https://moonanime.art", "https://apx.lme.isroot.in", streamproxy: false, useproxy: false)
{ {
displayname = "New MoonAnime", displayname = "New MoonAnime",
displayindex = 0, displayindex = 0,
@ -51,7 +51,7 @@ namespace LME.NMoonAnime
var defaults = JObject.FromObject(NMoonAnime); var defaults = JObject.FromObject(NMoonAnime);
defaults["enabled"] = true; defaults["enabled"] = true;
var conf = ModuleInvoke.Init("LME.NMoonAnime", defaults) ?? JObject.FromObject(NMoonAnime); var conf = ModuleInvoke.Init("NMoonAnime", defaults) ?? JObject.FromObject(NMoonAnime);
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
@ -71,7 +71,7 @@ namespace LME.NMoonAnime
NMoonAnime.apn = null; NMoonAnime.apn = null;
} }
RegisterWithSearch("lme.nmoonanime"); RegisterWithSearch("nmoonanime");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LME.NMoonAnime.Models namespace NMoonAnime.Models
{ {
public class NMoonAnimeSearchResponse public class NMoonAnimeSearchResponse
{ {

View File

@ -1,4 +1,4 @@
using LME.NMoonAnime.Models; using NMoonAnime.Models;
using Shared; using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
@ -14,7 +14,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace LME.NMoonAnime namespace NMoonAnime
{ {
public class NMoonAnimeInvoke public class NMoonAnimeInvoke
{ {

View File

@ -6,7 +6,7 @@ using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.NMoonAnime namespace NMoonAnime
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -30,7 +30,7 @@ namespace LME.NMoonAnime
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.nmoonanime")); online.Add(new ModuleOnlineItem(init, "nmoonanime"));
} }
return online; return online;

3
NMoonAnime/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -1,23 +1,19 @@
# Ukraine online source for Lampac NextGen # Ukraine online source for Lampac NextGen
> **Important:** All modules use the prefix `LME.` (Lampac Modules Extended) to avoid conflicts with Lampac's built-in modules.
> Text names, namespaces, keys in `init.conf`, and routes all use the prefix `LME.`.
## Sources ## Sources
### TVShows and Movies ### TVShows and Movies
- [x] LME.Uaflix - [x] UAFlix
- [x] LME.Makhno - [x] Makhno
- [x] LME.StarLight - [x] StarLight
- [x] LME.KlonFUN - [x] KlonFUN
- [x] LME.UafilmME
### Anime and Dorama ### Anime and Dorama
- [x] LME.AnimeON - [x] AnimeON
- [x] LME.Bamboo - [x] BambooUA
- [x] LME.Unimay - [x] Unimay
- [x] LME.Mikai - [x] Mikai
- [x] LME.NMoonAnime - [x] NMoonAnime
## Installation ## Installation
@ -30,7 +26,7 @@
- If Lampac is installed system-wide, move the modules to the `module` directory. - If Lampac is installed system-wide, move the modules to the `module` directory.
- If Lampac is running in Docker, mount the volume: - If Lampac is running in Docker, mount the volume:
```bash ```bash
-v /path/to/your/cloned/repo/LME.Uaflix:/home/module/LME.Uaflix -v /path/to/your/cloned/repo/Uaflix:/home/module/Uaflix
``` ```
## Auto installation ## Auto installation
@ -40,20 +36,18 @@ If Lampac version 148.1 and newer
Create or update the module/repository.yaml file Create or update the module/repository.yaml file
```YAML ```YAML
- repository: https://github.com/lampac-ukraine/lampac-ukraine - repository: https://github.com/lampame/lampac-ukraine
branch: main branch: main
modules: modules:
- LME.AnimeON - AnimeON
- LME.Unimay - Unimay
- LME.Mikai - Mikai
- LME.NMoonAnime - NMoonAnime
- LME.Uaflix - Uaflix
- LME.Bamboo - Bamboo
- LME.Makhno - Makhno
- LME.StarLight - StarLight
- LME.KlonFUN - KlonFUN
- LME.UafilmME
- LME.JackTor
``` ```
branch - optional, default main branch - optional, default main
@ -62,11 +56,8 @@ modules - optional, if not specified, all modules from the repository will be in
## Init support ## Init support
> **Note:** The key in `init.conf` must match the module name (`LME.XXX`), **not** the provider name.
> For example, for Uaflix, use `“LME.Uaflix”`, not `“Uaflix”`.
```json ```json
"LME.Uaflix": { "Uaflix": {
"enable": true, "enable": true,
"domain": "https://uaflix.net", "domain": "https://uaflix.net",
"displayname": "Uaflix", "displayname": "Uaflix",
@ -94,13 +85,13 @@ modules - optional, if not specified, all modules from the repository will be in
Parameter compatibility: Parameter compatibility:
- `webcorshost` + `useproxy`: work together (parsing via CORS host, and network output can go through a proxy with `useproxy`). - `webcorshost` + `useproxy`: work together (parsing via CORS host, and network output can go through a proxy with `useproxy`).
- `webcorshost` does not conflict with `streamproxy`: CORS is used for parsing, `streamproxy` is used for streaming. - `webcorshost` does not conflict with `streamproxy`: CORS is used for parsing, `streamproxy` is used for streaming.
- `magic_apn.ashdi` is used only for Ashdi links and only when the value is not empty. - `magic_apn.ashdi` використовується тільки для Ashdi-посилань і лише коли значення непорожнє.
- `webcorshost` does not conflict with `magic_apn`: CORS is used for parsing, while `magic_apn` is used for Ashdi streaming. - `webcorshost` не конфліктує з `magic_apn`: CORS використовується для парсингу, `magic_apn` — для Ashdi-стрімінгу.
## JackTor config example (`init.conf`) ## JackTor config example (`init.conf`)
```json ```json
"LME.JackTor": { "JackTor": {
"enable": true, "enable": true,
"displayname": "JackTor", "displayname": "JackTor",
"displayindex": 0, "displayindex": 0,
@ -166,6 +157,16 @@ Key parameters at a glance:
- `torrs`, `auth_torrs`, `base_auth`: TorrServer nodes used for playback. - `torrs`, `auth_torrs`, `base_auth`: TorrServer nodes used for playback.
- `filter` / `filter_ignore`: regex filters for release title and voice labels. - `filter` / `filter_ignore`: regex filters for release title and voice labels.
## APN support
Sources with APN support:
- AnimeON
- Uaflix
- Mikai
- Makhno
- KlonFUN
- NMoonAnime
## Source/player availability check script ## Source/player availability check script
```bash ```bash

View File

@ -10,9 +10,9 @@ using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using Shared.Models.Templates; using Shared.Models.Templates;
using LME.StarLight.Models; using StarLight.Models;
namespace LME.StarLight.Controllers namespace StarLight.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -24,7 +24,7 @@ namespace LME.StarLight.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.starlight")] [Route("lite/starlight")]
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, int s = -1, bool rjson = false, string href = null, bool checksearch = 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, int s = -1, bool rjson = false, string href = null, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -38,13 +38,13 @@ namespace LME.StarLight.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
var searchResults = await invoke.Search(title, original_title); var searchResults = await invoke.Search(title, original_title);
if (searchResults != null && searchResults.Count > 0) if (searchResults != null && searchResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
} }
string itemUrl = href; string itemUrl = href;
@ -52,14 +52,14 @@ namespace LME.StarLight.Controllers
{ {
var searchResults = await invoke.Search(title, original_title); var searchResults = await invoke.Search(title, original_title);
if (searchResults == null || searchResults.Count == 0) if (searchResults == null || searchResults.Count == 0)
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
if (searchResults.Count > 1) if (searchResults.Count > 1)
{ {
var similar_tpl = new SimilarTpl(searchResults.Count); var similar_tpl = new SimilarTpl(searchResults.Count);
foreach (var res in searchResults) foreach (var res in searchResults)
{ {
string link = $"{host}/lite/lme.starlight?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(res.Href)}"; string link = $"{host}/lite/starlight?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={HttpUtility.UrlEncode(res.Href)}";
similar_tpl.Append(res.Title, string.Empty, string.Empty, link, string.Empty); similar_tpl.Append(res.Title, string.Empty, string.Empty, link, string.Empty);
} }
@ -71,7 +71,7 @@ namespace LME.StarLight.Controllers
var project = await invoke.GetProject(itemUrl); var project = await invoke.GetProject(itemUrl);
if (project == null) if (project == null)
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
if (serial == 1 && project.Seasons.Count > 0) if (serial == 1 && project.Seasons.Count > 0)
{ {
@ -82,7 +82,7 @@ namespace LME.StarLight.Controllers
{ {
var seasonInfo = project.Seasons[i]; var seasonInfo = project.Seasons[i];
string seasonName = string.IsNullOrEmpty(seasonInfo.Title) ? $"Сезон {i + 1}" : seasonInfo.Title; string seasonName = string.IsNullOrEmpty(seasonInfo.Title) ? $"Сезон {i + 1}" : seasonInfo.Title;
string link = $"{host}/lite/lme.starlight?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={i}&href={HttpUtility.UrlEncode(itemUrl)}"; string link = $"{host}/lite/starlight?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={i}&href={HttpUtility.UrlEncode(itemUrl)}";
season_tpl.Append(seasonName, link, i.ToString()); season_tpl.Append(seasonName, link, i.ToString());
} }
@ -90,13 +90,13 @@ namespace LME.StarLight.Controllers
} }
if (s < 0 || s >= project.Seasons.Count) if (s < 0 || s >= project.Seasons.Count)
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
var season = project.Seasons[s]; var season = project.Seasons[s];
string seasonSlug = season.Slug; string seasonSlug = season.Slug;
var episodes = invoke.GetEpisodes(project, seasonSlug); var episodes = invoke.GetEpisodes(project, seasonSlug);
if (episodes == null || episodes.Count == 0) if (episodes == null || episodes.Count == 0)
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
var episode_tpl = new EpisodeTpl(); var episode_tpl = new EpisodeTpl();
int index = 1; int index = 1;
@ -114,7 +114,7 @@ namespace LME.StarLight.Controllers
continue; continue;
string episodeName = string.IsNullOrEmpty(ep.Title) ? $"Епізод {index}" : ep.Title; string episodeName = string.IsNullOrEmpty(ep.Title) ? $"Епізод {index}" : ep.Title;
string callUrl = $"{host}/lite/lme.starlight/play?hash={HttpUtility.UrlEncode(ep.Hash)}&title={HttpUtility.UrlEncode(title ?? original_title)}"; string callUrl = $"{host}/lite/starlight/play?hash={HttpUtility.UrlEncode(ep.Hash)}&title={HttpUtility.UrlEncode(title ?? original_title)}";
episode_tpl.Append(episodeName, title ?? original_title, seasonNumber, index.ToString("D2"), accsArgs(callUrl), "call"); episode_tpl.Append(episodeName, title ?? original_title, seasonNumber, index.ToString("D2"), accsArgs(callUrl), "call");
index++; index++;
} }
@ -128,9 +128,9 @@ namespace LME.StarLight.Controllers
hash = project.Episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e.Hash))?.Hash; hash = project.Episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e.Hash))?.Hash;
if (string.IsNullOrEmpty(hash)) if (string.IsNullOrEmpty(hash))
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
string callUrl = $"{host}/lite/lme.starlight/play?hash={HttpUtility.UrlEncode(hash)}&title={HttpUtility.UrlEncode(title ?? original_title)}"; string callUrl = $"{host}/lite/starlight/play?hash={HttpUtility.UrlEncode(hash)}&title={HttpUtility.UrlEncode(title ?? original_title)}";
var movie_tpl = new MovieTpl(title, original_title, 1); var movie_tpl = new MovieTpl(title, original_title, 1);
movie_tpl.Append(string.IsNullOrEmpty(title) ? "StarLight" : title, accsArgs(callUrl), "call"); movie_tpl.Append(string.IsNullOrEmpty(title) ? "StarLight" : title, accsArgs(callUrl), "call");
@ -139,13 +139,13 @@ namespace LME.StarLight.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.starlight/play")] [Route("lite/starlight/play")]
async public Task<ActionResult> Play(string hash, string title) async public Task<ActionResult> Play(string hash, string title)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
if (string.IsNullOrEmpty(hash)) if (string.IsNullOrEmpty(hash))
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
var init = loadKit(ModInit.StarLight); var init = loadKit(ModInit.StarLight);
if (!init.enable) if (!init.enable)
@ -154,7 +154,7 @@ namespace LME.StarLight.Controllers
var invoke = new StarLightInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new StarLightInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
var result = await invoke.ResolveStream(hash); var result = await invoke.ResolveStream(hash);
if (result == null || string.IsNullOrEmpty(result.Stream)) if (result == null || string.IsNullOrEmpty(result.Stream))
return OnError("lme.starlight", refresh_proxy: true); return OnError("starlight", refresh_proxy: true);
string videoTitle = title ?? result.Name ?? ""; string videoTitle = title ?? result.Name ?? "";

View File

@ -21,11 +21,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.StarLight namespace StarLight
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 4.1; public static double Version => 4.0;
public static OnlinesSettings StarLight; public static OnlinesSettings StarLight;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -43,7 +43,7 @@ namespace LME.StarLight
{ {
StarLight = new OnlinesSettings("LME.StarLight", "https://tp-back.starlight.digital", streamproxy: false, useproxy: false) StarLight = new OnlinesSettings("StarLight", "https://tp-back.starlight.digital", streamproxy: false, useproxy: false)
{ {
displayname = "StarLight", displayname = "StarLight",
displayindex = 0, displayindex = 0,
@ -57,7 +57,7 @@ namespace LME.StarLight
}; };
var defaults = JObject.FromObject(StarLight); var defaults = JObject.FromObject(StarLight);
defaults["enabled"] = true; defaults["enabled"] = true;
var conf = ModuleInvoke.Init("LME.StarLight", defaults); var conf = ModuleInvoke.Init("StarLight", defaults);
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
@ -76,7 +76,7 @@ namespace LME.StarLight
} }
// Виводити "уточнити пошук" // Виводити "уточнити пошук"
RegisterWithSearch("lme.starlight"); RegisterWithSearch("starlight");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.StarLight.Models namespace StarLight.Models
{ {
public class SearchResult public class SearchResult
{ {

View File

@ -7,7 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.StarLight namespace StarLight
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -30,7 +30,7 @@ namespace LME.StarLight
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.starlight")); online.Add(new ModuleOnlineItem(init, "starlight"));
} }
return online; return online;

View File

@ -11,9 +11,9 @@ using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using LME.StarLight.Models; using StarLight.Models;
namespace LME.StarLight namespace StarLight
{ {
public class StarLightInvoke public class StarLightInvoke
{ {

3
StarLight/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"enable": true
}

View File

@ -9,9 +9,9 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using LME.UafilmME.Models; using UafilmME.Models;
namespace LME.UafilmME.Controllers namespace UafilmME.Controllers
{ {
public class Controller : BaseOnlineController public class Controller : BaseOnlineController
{ {
@ -23,7 +23,7 @@ namespace LME.UafilmME.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.uafilmme")] [Route("lite/uafilmme")]
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, string href = null, bool checksearch = 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, string href = null, bool checksearch = false)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
@ -37,13 +37,13 @@ namespace LME.UafilmME.Controllers
if (checksearch) if (checksearch)
{ {
if (!IsCheckOnlineSearchEnabled()) if (!IsCheckOnlineSearchEnabled())
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
var searchResults = await invoke.Search(title, original_title, year); var searchResults = await invoke.Search(title, original_title, year);
if (searchResults != null && searchResults.Count > 0) if (searchResults != null && searchResults.Count > 0)
return Content("data-json=", "text/plain; charset=utf-8"); return Content("data-json=", "text/plain; charset=utf-8");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
long titleId = 0; long titleId = 0;
@ -54,8 +54,8 @@ namespace LME.UafilmME.Controllers
var searchResults = await invoke.Search(title, original_title, year); var searchResults = await invoke.Search(title, original_title, year);
if (searchResults == null || searchResults.Count == 0) if (searchResults == null || searchResults.Count == 0)
{ {
OnLog("lme.uafilmme: пошук нічого не повернув."); OnLog("UafilmME: пошук нічого не повернув.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var best = invoke.SelectBestSearchResult(searchResults, id, imdb_id, title, original_title, year, serial); var best = invoke.SelectBestSearchResult(searchResults, id, imdb_id, title, original_title, year, serial);
@ -72,11 +72,11 @@ namespace LME.UafilmME.Controllers
{ {
string details = item.IsSeries ? "Серіал" : "Фільм"; string details = item.IsSeries ? "Серіал" : "Фільм";
string itemYear = item.Year > 1900 ? item.Year.ToString() : string.Empty; string itemYear = item.Year > 1900 ? item.Year.ToString() : string.Empty;
string link = $"{host}/lite/lme.uafilmme?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={item.Id}"; string link = $"{host}/lite/uafilmme?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial={serial}&href={item.Id}";
similarTpl.Append(item.Name, itemYear, details, link, item.Poster); similarTpl.Append(item.Name, itemYear, details, link, item.Poster);
} }
OnLog($"lme.uafilmme: кілька схожих збігів, повертаю SimilarTpl ({ordered.Count})."); OnLog($"UafilmME: кілька схожих збігів, повертаю SimilarTpl ({ordered.Count}).");
return rjson return rjson
? Content(similarTpl.ToJson(), "application/json; charset=utf-8") ? Content(similarTpl.ToJson(), "application/json; charset=utf-8")
: Content(similarTpl.ToHtml(), "text/html; charset=utf-8"); : Content(similarTpl.ToHtml(), "text/html; charset=utf-8");
@ -87,8 +87,8 @@ namespace LME.UafilmME.Controllers
if (titleId <= 0) if (titleId <= 0)
{ {
OnLog("lme.uafilmme: не вдалося визначити title_id."); OnLog("UafilmME: не вдалося визначити title_id.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
if (serial == 1) if (serial == 1)
@ -98,8 +98,8 @@ namespace LME.UafilmME.Controllers
var seasons = await invoke.GetAllSeasons(titleId); var seasons = await invoke.GetAllSeasons(titleId);
if (seasons == null || seasons.Count == 0) if (seasons == null || seasons.Count == 0)
{ {
OnLog($"lme.uafilmme: сезони не знайдено для title_id={titleId}."); OnLog($"UafilmME: сезони не знайдено для title_id={titleId}.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var seasonTpl = new SeasonTpl(seasons.Count); var seasonTpl = new SeasonTpl(seasons.Count);
@ -109,7 +109,7 @@ namespace LME.UafilmME.Controllers
? $"Сезон {season.Number} ({season.EpisodesCount} еп.)" ? $"Сезон {season.Number} ({season.EpisodesCount} еп.)"
: $"Сезон {season.Number}"; : $"Сезон {season.Number}";
string link = $"{host}/lite/lme.uafilmme?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={season.Number}&href={titleId}"; string link = $"{host}/lite/uafilmme?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={season.Number}&href={titleId}";
seasonTpl.Append(seasonName, link, season.Number.ToString()); seasonTpl.Append(seasonName, link, season.Number.ToString());
} }
@ -120,15 +120,15 @@ namespace LME.UafilmME.Controllers
if (s <= 0) if (s <= 0)
{ {
OnLog($"lme.uafilmme: некоректний номер сезону s={s}."); OnLog($"UafilmME: некоректний номер сезону s={s}.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var episodes = await invoke.GetSeasonEpisodes(titleId, s); var episodes = await invoke.GetSeasonEpisodes(titleId, s);
if (episodes == null || episodes.Count == 0) if (episodes == null || episodes.Count == 0)
{ {
OnLog($"lme.uafilmme: епізоди не знайдено для title_id={titleId}, season={s}."); OnLog($"UafilmME: епізоди не знайдено для title_id={titleId}, season={s}.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var episodeTpl = new EpisodeTpl(); var episodeTpl = new EpisodeTpl();
@ -145,7 +145,7 @@ namespace LME.UafilmME.Controllers
? episode.Name ? episode.Name
: $"Епізод {episodeNumber}"; : $"Епізод {episodeNumber}";
string callUrl = $"{host}/lite/lme.uafilmme/play?video_id={episode.PrimaryVideoId}&title_id={titleId}&s={s}&e={episodeNumber}&title={HttpUtility.UrlEncode(title ?? original_title)}"; string callUrl = $"{host}/lite/uafilmme/play?video_id={episode.PrimaryVideoId}&title_id={titleId}&s={s}&e={episodeNumber}&title={HttpUtility.UrlEncode(title ?? original_title)}";
episodeTpl.Append(episodeName, title ?? original_title, s.ToString(), episodeNumber.ToString("D2"), accsArgs(callUrl), "call"); episodeTpl.Append(episodeName, title ?? original_title, s.ToString(), episodeNumber.ToString("D2"), accsArgs(callUrl), "call");
fallbackEpisodeNumber = Math.Max(fallbackEpisodeNumber, episodeNumber + 1); fallbackEpisodeNumber = Math.Max(fallbackEpisodeNumber, episodeNumber + 1);
@ -154,8 +154,8 @@ namespace LME.UafilmME.Controllers
if (appended == 0) if (appended == 0)
{ {
OnLog($"lme.uafilmme: у сезоні {s} немає епізодів з playable video_id."); OnLog($"UafilmME: у сезоні {s} немає епізодів з playable video_id.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
return rjson return rjson
@ -167,8 +167,8 @@ namespace LME.UafilmME.Controllers
var videos = await invoke.GetMovieVideos(titleId); var videos = await invoke.GetMovieVideos(titleId);
if (videos == null || videos.Count == 0) if (videos == null || videos.Count == 0)
{ {
OnLog($"lme.uafilmme: не знайдено відео для фільму title_id={titleId}."); OnLog($"UafilmME: не знайдено відео для фільму title_id={titleId}.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var movieTpl = new MovieTpl(title, original_title, videos.Count); var movieTpl = new MovieTpl(title, original_title, videos.Count);
@ -176,7 +176,7 @@ namespace LME.UafilmME.Controllers
foreach (var video in videos) foreach (var video in videos)
{ {
string label = BuildVideoLabel(video, index); string label = BuildVideoLabel(video, index);
string callUrl = $"{host}/lite/lme.uafilmme/play?video_id={video.Id}&title_id={titleId}&title={HttpUtility.UrlEncode(title ?? original_title)}"; string callUrl = $"{host}/lite/uafilmme/play?video_id={video.Id}&title_id={titleId}&title={HttpUtility.UrlEncode(title ?? original_title)}";
movieTpl.Append(label, accsArgs(callUrl), "call"); movieTpl.Append(label, accsArgs(callUrl), "call");
index++; index++;
} }
@ -188,13 +188,13 @@ namespace LME.UafilmME.Controllers
} }
[HttpGet] [HttpGet]
[Route("lite/lme.uafilmme/play")] [Route("lite/uafilmme/play")]
async public Task<ActionResult> Play(long video_id, long title_id = 0, int s = 0, int e = 0, string title = null) async public Task<ActionResult> Play(long video_id, long title_id = 0, int s = 0, int e = 0, string title = null)
{ {
await UpdateService.ConnectAsync(host); await UpdateService.ConnectAsync(host);
if (video_id <= 0) if (video_id <= 0)
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
var init = loadKit(ModInit.UafilmME); var init = loadKit(ModInit.UafilmME);
if (!init.enable) if (!init.enable)
@ -205,8 +205,8 @@ namespace LME.UafilmME.Controllers
var videos = invoke.CollectPlayableVideos(watch); var videos = invoke.CollectPlayableVideos(watch);
if (videos == null || videos.Count == 0) if (videos == null || videos.Count == 0)
{ {
OnLog($"lme.uafilmme Play: watch/{video_id} не повернув playable stream."); OnLog($"UafilmME Play: watch/{video_id} не повернув playable stream.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
var headers = new List<HeadersModel>() var headers = new List<HeadersModel>()
@ -229,8 +229,8 @@ namespace LME.UafilmME.Controllers
var first = streamQuality.Firts(); var first = streamQuality.Firts();
if (string.IsNullOrWhiteSpace(first.link)) if (string.IsNullOrWhiteSpace(first.link))
{ {
OnLog($"lme.uafilmme Play: не вдалося зібрати streamquality для video_id={video_id}."); OnLog($"UafilmME Play: не вдалося зібрати streamquality для video_id={video_id}.");
return OnError("lme.uafilmme", refresh_proxy: true); return OnError("uafilmme", refresh_proxy: true);
} }
string videoTitle = !string.IsNullOrWhiteSpace(title) string videoTitle = !string.IsNullOrWhiteSpace(title)

View File

@ -15,11 +15,11 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LME.UafilmME namespace UafilmME
{ {
public class ModInit : IModuleLoaded public class ModInit : IModuleLoaded
{ {
public static double Version => 1.1; public static double Version => 1.0;
public static OnlinesSettings UafilmME; public static OnlinesSettings UafilmME;
public static bool ApnHostProvided; public static bool ApnHostProvided;
@ -35,7 +35,7 @@ namespace LME.UafilmME
/// </summary> /// </summary>
public void Loaded(InitspaceModel initspace) public void Loaded(InitspaceModel initspace)
{ {
UafilmME = new OnlinesSettings("LME.UafilmME", "https://uafilm.me", streamproxy: false, useproxy: false) UafilmME = new OnlinesSettings("UafilmME", "https://uafilm.me", streamproxy: false, useproxy: false)
{ {
displayname = "UAFilmME", displayname = "UAFilmME",
displayindex = 0, displayindex = 0,
@ -50,7 +50,7 @@ namespace LME.UafilmME
var defaults = JObject.FromObject(UafilmME); var defaults = JObject.FromObject(UafilmME);
defaults["enabled"] = true; defaults["enabled"] = true;
var conf = ModuleInvoke.Init("LME.UafilmME", defaults); var conf = ModuleInvoke.Init("UafilmME", defaults);
bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost); bool hasApn = ApnHelper.TryGetInitConf(conf, out bool apnEnabled, out string apnHost);
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
@ -69,7 +69,7 @@ namespace LME.UafilmME
UafilmME.apn = null; UafilmME.apn = null;
} }
RegisterWithSearch("lme.uafilmme"); RegisterWithSearch("uafilmme");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.UafilmME.Models namespace UafilmME.Models
{ {
public class UafilmSearchItem public class UafilmSearchItem
{ {

View File

@ -4,7 +4,7 @@ using Shared.Models.Module;
using Shared.Models.Module.Interfaces; using Shared.Models.Module.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
namespace LME.UafilmME namespace UafilmME
{ {
public class OnlineApi : IModuleOnline public class OnlineApi : IModuleOnline
{ {
@ -24,7 +24,7 @@ namespace LME.UafilmME
if (UpdateService.IsDisconnected()) if (UpdateService.IsDisconnected())
init.overridehost = null; init.overridehost = null;
online.Add(new ModuleOnlineItem(init, "lme.uafilmme")); online.Add(new ModuleOnlineItem(init, "uafilmme"));
} }
return online; return online;

View File

@ -10,9 +10,9 @@ using Shared;
using Shared.Engine; using Shared.Engine;
using Shared.Models; using Shared.Models;
using Shared.Models.Online.Settings; using Shared.Models.Online.Settings;
using LME.UafilmME.Models; using UafilmME.Models;
namespace LME.UafilmME namespace UafilmME
{ {
public class UafilmMEInvoke public class UafilmMEInvoke
{ {

6
UafilmME/manifest.json Normal file
View File

@ -0,0 +1,6 @@
{
"enable": true,
"version": 3,
"initspace": "UafilmME.ModInit",
"online": "UafilmME.OnlineApi"
}

Some files were not shown because too many files have changed in this diff Show More