Compare commits

..

3 Commits

Author SHA1 Message Date
Felix
31549455ee feat(apn): add magic_apn support for Ashdi streams
Introduce a new configuration option `magic_apn` that allows automatic enabling of APN for Ashdi streams when using the inner player. The configuration is an object with an `ashdi` property that specifies the host to use for Ashdi APN.

Changes include:
- Add `TryGetMagicAshdiHost` method to parse `magic_apn` configuration
- Add `NormalizeHost`
2026-04-01 18:54:32 +03:00
Felix
0cb8412036
Merge pull request #24 from levende/lampac-ng
Add magic apn
2026-04-01 18:22:00 +03:00
Oleksandr Zhyzhchenko
fc7ddf2668 Add magic apn 2026-04-01 15:02:33 +03:00
17 changed files with 363 additions and 40 deletions

View File

@ -25,6 +25,23 @@ namespace Shared.Engine
return true; return true;
} }
public static string TryGetMagicAshdiHost(JObject conf)
{
if (conf == null || !conf.TryGetValue("magic_apn", out var magicToken) || magicToken == null)
return null;
if (magicToken.Type == JTokenType.Boolean)
return magicToken.Value<bool>() ? DefaultHost : null;
if (magicToken.Type == JTokenType.String)
return NormalizeHost(magicToken.Value<string>());
if (magicToken.Type != JTokenType.Object)
return null;
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
}
public static void ApplyInitConf(bool enabled, string host, BaseSettings init) public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
{ {
if (init == null) if (init == null)
@ -37,8 +54,13 @@ namespace Shared.Engine
return; return;
} }
if (string.IsNullOrWhiteSpace(host)) host = NormalizeHost(host);
host = DefaultHost; if (host == null)
{
init.apnstream = false;
init.apn = null;
return;
}
if (init.apn == null) if (init.apn == null)
init.apn = new ApnConf(); init.apn = new ApnConf();
@ -82,5 +104,13 @@ namespace Shared.Engine
return $"{host.TrimEnd('/')}/{url}"; return $"{host.TrimEnd('/')}/{url}";
} }
private static string NormalizeHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return null;
return host.Trim();
}
} }
} }

View File

@ -36,6 +36,7 @@ namespace AnimeON.Controllers
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
TryEnableMagicApn(init);
var invoke = new AnimeONInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new AnimeONInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
if (checksearch) if (checksearch)
@ -382,6 +383,7 @@ namespace AnimeON.Controllers
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
TryEnableMagicApn(init);
var invoke = new AnimeONInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new AnimeONInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
bool disableAshdiMultivoiceForVod = serial == 1; bool disableAshdiMultivoiceForVod = serial == 1;
OnLog($"AnimeON Play: url={url}, episode_id={episode_id}, serial={serial}"); OnLog($"AnimeON Play: url={url}, episode_id={episode_id}, serial={serial}");
@ -463,6 +465,24 @@ namespace AnimeON.Controllers
return HostStreamProxy(init, link, headers: headers, force_streamproxy: forceProxy); return HostStreamProxy(init, link, headers: headers, force_streamproxy: forceProxy);
} }
private void TryEnableMagicApn(OnlinesSettings init)
{
if (init == null
|| init.apn != null
|| init.streamproxy
|| string.IsNullOrWhiteSpace(ModInit.MagicApnAshdiHost))
return;
string player = new RchClient(HttpContext, host, init, requestInfo).InfoConnected()?.player;
bool useInnerPlayer = string.IsNullOrWhiteSpace(player)
|| player.Equals("inner", StringComparison.OrdinalIgnoreCase);
if (!useInnerPlayer)
return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"AnimeON: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
}
private static bool IsCheckOnlineSearchEnabled() private static bool IsCheckOnlineSearchEnabled()
{ {
try try

View File

@ -30,6 +30,7 @@ namespace AnimeON
public static OnlinesSettings AnimeON; public static OnlinesSettings AnimeON;
public static bool ApnHostProvided; public static bool ApnHostProvided;
public static string MagicApnAshdiHost;
public static OnlinesSettings Settings public static OnlinesSettings Settings
{ {
@ -56,15 +57,23 @@ namespace AnimeON
list = new string[] { "socks5://ip:port" } list = new string[] { "socks5://ip:port" }
} }
}; };
var conf = ModuleInvoke.Init("AnimeON", JObject.FromObject(AnimeON)); var defaults = JObject.FromObject(AnimeON);
defaults["magic_apn"] = new JObject()
{
["ashdi"] = ApnHelper.DefaultHost
};
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);
conf.Remove("magic_apn");
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
AnimeON = conf.ToObject<OnlinesSettings>(); AnimeON = conf.ToObject<OnlinesSettings>();
if (hasApn) if (hasApn)
ApnHelper.ApplyInitConf(apnEnabled, apnHost, AnimeON); ApnHelper.ApplyInitConf(apnEnabled, apnHost, AnimeON);
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost); ApnHostProvided = ApnHelper.IsEnabled(AnimeON);
if (hasApn && apnEnabled) if (ApnHostProvided)
{ {
AnimeON.streamproxy = false; AnimeON.streamproxy = false;
} }
@ -235,4 +244,4 @@ namespace AnimeON
} }
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled); public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
} }

View File

@ -25,6 +25,23 @@ namespace Shared.Engine
return true; return true;
} }
public static string TryGetMagicAshdiHost(JObject conf)
{
if (conf == null || !conf.TryGetValue("magic_apn", out var magicToken) || magicToken == null)
return null;
if (magicToken.Type == JTokenType.Boolean)
return magicToken.Value<bool>() ? DefaultHost : null;
if (magicToken.Type == JTokenType.String)
return NormalizeHost(magicToken.Value<string>());
if (magicToken.Type != JTokenType.Object)
return null;
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
}
public static void ApplyInitConf(bool enabled, string host, BaseSettings init) public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
{ {
if (init == null) if (init == null)
@ -37,8 +54,13 @@ namespace Shared.Engine
return; return;
} }
if (string.IsNullOrWhiteSpace(host)) host = NormalizeHost(host);
host = DefaultHost; if (host == null)
{
init.apnstream = false;
init.apn = null;
return;
}
if (init.apn == null) if (init.apn == null)
init.apn = new ApnConf(); init.apn = new ApnConf();
@ -82,5 +104,13 @@ namespace Shared.Engine
return $"{host.TrimEnd('/')}/{url}"; return $"{host.TrimEnd('/')}/{url}";
} }
private static string NormalizeHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return null;
return host.Trim();
}
} }
} }

View File

@ -31,6 +31,8 @@ namespace KlonFUN.Controllers
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
TryEnableMagicApn(init);
var invoke = new KlonFUNInvoke(init, hybridCache, OnLog, proxyManager, httpHydra); var invoke = new KlonFUNInvoke(init, hybridCache, OnLog, proxyManager, httpHydra);
if (checksearch) if (checksearch)
@ -217,6 +219,24 @@ namespace KlonFUN.Controllers
return HostStreamProxy(init, link); return HostStreamProxy(init, link);
} }
private void TryEnableMagicApn(OnlinesSettings init)
{
if (init == null
|| init.apn != null
|| init.streamproxy
|| string.IsNullOrWhiteSpace(ModInit.MagicApnAshdiHost))
return;
string player = new RchClient(HttpContext, host, init, requestInfo).InfoConnected()?.player;
bool useInnerPlayer = string.IsNullOrWhiteSpace(player)
|| player.Equals("inner", StringComparison.OrdinalIgnoreCase);
if (!useInnerPlayer)
return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"KlonFUN: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
}
private static string StripLampacArgs(string url) private static string StripLampacArgs(string url)
{ {
if (string.IsNullOrWhiteSpace(url)) if (string.IsNullOrWhiteSpace(url))

View File

@ -14,6 +14,7 @@ using System.Security.Authentication;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Shared.Models.Events;
namespace KlonFUN namespace KlonFUN
{ {
@ -21,10 +22,11 @@ namespace KlonFUN
{ {
public static double Version => 2.0; public static double Version => 2.0;
public static OnlinesSettings KlonFUN; public static ModuleConfig KlonFUN;
public static bool ApnHostProvided; public static bool ApnHostProvided;
public static string MagicApnAshdiHost;
public static OnlinesSettings Settings public static ModuleConfig Settings
{ {
get => KlonFUN; get => KlonFUN;
set => KlonFUN = value; set => KlonFUN = value;
@ -35,7 +37,16 @@ namespace KlonFUN
/// </summary> /// </summary>
public void Loaded(InitspaceModel initspace) public void Loaded(InitspaceModel initspace)
{ {
KlonFUN = new OnlinesSettings("KlonFUN", "https://klon.fun", streamproxy: false, useproxy: false) UpdateConfig();
EventListener.UpdateInitFile += UpdateConfig;
// Додаємо підтримку "уточнити пошук".
RegisterWithSearch("klonfun");
}
private void UpdateConfig()
{
KlonFUN = new ModuleConfig("KlonFUN", "https://klon.fun", streamproxy: false, useproxy: false)
{ {
displayname = "KlonFUN", displayname = "KlonFUN",
displayindex = 0, displayindex = 0,
@ -48,16 +59,24 @@ namespace KlonFUN
} }
}; };
var conf = ModuleInvoke.Init("KlonFUN", JObject.FromObject(KlonFUN)); var defaults = JObject.FromObject(KlonFUN);
defaults["magic_apn"] = new JObject()
{
["ashdi"] = ApnHelper.DefaultHost
};
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);
conf.Remove("magic_apn");
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
KlonFUN = conf.ToObject<OnlinesSettings>(); KlonFUN = conf.ToObject<ModuleConfig>();
if (hasApn) if (hasApn)
ApnHelper.ApplyInitConf(apnEnabled, apnHost, KlonFUN); ApnHelper.ApplyInitConf(apnEnabled, apnHost, KlonFUN);
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost); ApnHostProvided = ApnHelper.IsEnabled(KlonFUN);
if (hasApn && apnEnabled) if (ApnHostProvided)
{ {
KlonFUN.streamproxy = false; KlonFUN.streamproxy = false;
} }
@ -66,9 +85,6 @@ namespace KlonFUN
KlonFUN.apnstream = false; KlonFUN.apnstream = false;
KlonFUN.apn = null; KlonFUN.apn = null;
} }
// Додаємо підтримку "уточнити пошук".
RegisterWithSearch("klonfun");
} }
private static void RegisterWithSearch(string plugin) private static void RegisterWithSearch(string plugin)
@ -107,6 +123,7 @@ namespace KlonFUN
public void Dispose() public void Dispose()
{ {
EventListener.UpdateInitFile -= UpdateConfig;
} }
} }

18
KlonFUN/ModuleConfig.cs Normal file
View File

@ -0,0 +1,18 @@
using Shared.Models.Online.Settings;
namespace KlonFUN
{
public class MagicApnSettings
{
public string ashdi { get; set; }
}
public class ModuleConfig : OnlinesSettings
{
public ModuleConfig(string plugin, string host, string apihost = null, bool useproxy = false, string token = null, bool enable = true, bool streamproxy = false, bool rip = false, bool forceEncryptToken = false, string rch_access = null, string stream_access = null) : base(plugin, host, apihost, useproxy, token, enable, streamproxy, rip, forceEncryptToken, rch_access, stream_access)
{
}
public MagicApnSettings magic_apn { get; set; }
}
}

View File

@ -23,20 +23,37 @@ namespace Shared.Engine
if (apnToken.Type == JTokenType.Boolean) if (apnToken.Type == JTokenType.Boolean)
{ {
enabled = apnToken.Value<bool>(); enabled = apnToken.Value<bool>();
host = conf.Value<string>("apn_host"); host = NormalizeHost(conf.Value<string>("apn_host"));
return true; return true;
} }
if (apnToken.Type == JTokenType.String) if (apnToken.Type == JTokenType.String)
{ {
host = apnToken.Value<string>(); host = NormalizeHost(apnToken.Value<string>());
enabled = !string.IsNullOrWhiteSpace(host); enabled = host != null;
return true; return true;
} }
return false; return false;
} }
public static string TryGetMagicAshdiHost(JObject conf)
{
if (conf == null || !conf.TryGetValue("magic_apn", out var magicToken) || magicToken == null)
return null;
if (magicToken.Type == JTokenType.Boolean)
return magicToken.Value<bool>() ? DefaultHost : null;
if (magicToken.Type == JTokenType.String)
return NormalizeHost(magicToken.Value<string>());
if (magicToken.Type != JTokenType.Object)
return null;
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
}
public static void ApplyInitConf(bool enabled, string host, BaseSettings init) public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
{ {
if (init == null) if (init == null)
@ -49,8 +66,13 @@ namespace Shared.Engine
return; return;
} }
if (string.IsNullOrWhiteSpace(host)) host = NormalizeHost(host);
host = DefaultHost; if (host == null)
{
init.apnstream = false;
init.apn = null;
return;
}
if (init.apn == null) if (init.apn == null)
init.apn = new ApnConf(); init.apn = new ApnConf();
@ -94,5 +116,13 @@ namespace Shared.Engine
return $"{host.TrimEnd('/')}/{url}"; return $"{host.TrimEnd('/')}/{url}";
} }
private static string NormalizeHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return null;
return host.Trim();
}
} }
} }

View File

@ -39,6 +39,7 @@ namespace Makhno
var init = loadKit(ModInit.Makhno); var init = loadKit(ModInit.Makhno);
if (!init.enable) if (!init.enable)
return OnError(); return OnError();
TryEnableMagicApn(init);
Initialization(init); Initialization(init);
OnLog($"Makhno: {title} (serial={serial}, s={s}, season={season}, t={t})"); OnLog($"Makhno: {title} (serial={serial}, s={s}, season={season}, t={t})");
@ -64,6 +65,7 @@ namespace Makhno
var init = loadKit(ModInit.Makhno); var init = loadKit(ModInit.Makhno);
if (!init.enable) if (!init.enable)
return OnError(); return OnError();
TryEnableMagicApn(init);
Initialization(init); Initialization(init);
OnLog($"Makhno Play: {title} (s={s}, season={season}, t={t}, episodeId={episodeId}) play={play}"); OnLog($"Makhno Play: {title} (s={s}, season={season}, t={t}, episodeId={episodeId}) play={play}");
@ -122,6 +124,7 @@ namespace Makhno
var init = loadKit(ModInit.Makhno); var init = loadKit(ModInit.Makhno);
if (!init.enable) if (!init.enable)
return OnError(); return OnError();
TryEnableMagicApn(init);
Initialization(init); Initialization(init);
OnLog($"Makhno PlayMovie: {title} ({year}) play={play}"); OnLog($"Makhno PlayMovie: {title} ({year}) play={play}");
@ -512,6 +515,24 @@ namespace Makhno
return HostStreamProxy(init, link); return HostStreamProxy(init, link);
} }
private void TryEnableMagicApn(OnlinesSettings init)
{
if (init == null
|| init.apn != null
|| init.streamproxy
|| string.IsNullOrWhiteSpace(ModInit.MagicApnAshdiHost))
return;
string player = new RchClient(HttpContext, host, init, requestInfo).InfoConnected()?.player;
bool useInnerPlayer = string.IsNullOrWhiteSpace(player)
|| player.Equals("inner", StringComparison.OrdinalIgnoreCase);
if (!useInnerPlayer)
return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"Makhno: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
}
private class ResolveResult private class ResolveResult
{ {
public string PlayUrl { get; set; } public string PlayUrl { get; set; }

View File

@ -28,6 +28,7 @@ namespace Makhno
public static OnlinesSettings Makhno; public static OnlinesSettings Makhno;
public static bool ApnHostProvided; public static bool ApnHostProvided;
public static string MagicApnAshdiHost;
public static OnlinesSettings Settings public static OnlinesSettings Settings
{ {
@ -52,8 +53,16 @@ namespace Makhno
list = new string[] { "socks5://ip:port" } list = new string[] { "socks5://ip:port" }
} }
}; };
var conf = ModuleInvoke.Init("Makhno", JObject.FromObject(Makhno)); var defaults = JObject.FromObject(Makhno);
defaults["magic_apn"] = new JObject()
{
["ashdi"] = ApnHelper.DefaultHost
};
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);
conf.Remove("magic_apn");
if (hasApn) if (hasApn)
{ {
conf.Remove("apn"); conf.Remove("apn");
@ -62,8 +71,8 @@ namespace Makhno
Makhno = conf.ToObject<OnlinesSettings>(); Makhno = conf.ToObject<OnlinesSettings>();
if (hasApn) if (hasApn)
ApnHelper.ApplyInitConf(apnEnabled, apnHost, Makhno); ApnHelper.ApplyInitConf(apnEnabled, apnHost, Makhno);
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost); ApnHostProvided = ApnHelper.IsEnabled(Makhno);
if (hasApn && apnEnabled) if (ApnHostProvided)
{ {
Makhno.streamproxy = false; Makhno.streamproxy = false;
} }

View File

@ -25,6 +25,23 @@ namespace Shared.Engine
return true; return true;
} }
public static string TryGetMagicAshdiHost(JObject conf)
{
if (conf == null || !conf.TryGetValue("magic_apn", out var magicToken) || magicToken == null)
return null;
if (magicToken.Type == JTokenType.Boolean)
return magicToken.Value<bool>() ? DefaultHost : null;
if (magicToken.Type == JTokenType.String)
return NormalizeHost(magicToken.Value<string>());
if (magicToken.Type != JTokenType.Object)
return null;
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
}
public static void ApplyInitConf(bool enabled, string host, BaseSettings init) public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
{ {
if (init == null) if (init == null)
@ -37,8 +54,13 @@ namespace Shared.Engine
return; return;
} }
if (string.IsNullOrWhiteSpace(host)) host = NormalizeHost(host);
host = DefaultHost; if (host == null)
{
init.apnstream = false;
init.apn = null;
return;
}
if (init.apn == null) if (init.apn == null)
init.apn = new ApnConf(); init.apn = new ApnConf();
@ -82,5 +104,13 @@ namespace Shared.Engine
return $"{host.TrimEnd('/')}/{url}"; return $"{host.TrimEnd('/')}/{url}";
} }
private static string NormalizeHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return null;
return host.Trim();
}
} }
} }

View File

@ -32,6 +32,7 @@ namespace Mikai.Controllers
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
TryEnableMagicApn(init);
var invoke = new MikaiInvoke(init, hybridCache, OnLog, _proxyManager, httpHydra); var invoke = new MikaiInvoke(init, hybridCache, OnLog, _proxyManager, httpHydra);
if (checksearch) if (checksearch)
@ -211,6 +212,7 @@ namespace Mikai.Controllers
if (!init.enable) if (!init.enable)
return Forbid(); return Forbid();
TryEnableMagicApn(init);
if (string.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))
return OnError("mikai", refresh_proxy: true); return OnError("mikai", refresh_proxy: true);
@ -463,6 +465,24 @@ namespace Mikai.Controllers
return HostStreamProxy(init, link, headers: headers, force_streamproxy: forceProxy); return HostStreamProxy(init, link, headers: headers, force_streamproxy: forceProxy);
} }
private void TryEnableMagicApn(OnlinesSettings init)
{
if (init == null
|| init.apn != null
|| init.streamproxy
|| string.IsNullOrWhiteSpace(ModInit.MagicApnAshdiHost))
return;
string player = new RchClient(HttpContext, host, init, requestInfo).InfoConnected()?.player;
bool useInnerPlayer = string.IsNullOrWhiteSpace(player)
|| player.Equals("inner", StringComparison.OrdinalIgnoreCase);
if (!useInnerPlayer)
return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"Mikai: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
}
private static bool IsCheckOnlineSearchEnabled() private static bool IsCheckOnlineSearchEnabled()
{ {
try try

View File

@ -29,6 +29,7 @@ namespace Mikai
public static OnlinesSettings Mikai; public static OnlinesSettings Mikai;
public static bool ApnHostProvided; public static bool ApnHostProvided;
public static string MagicApnAshdiHost;
public static OnlinesSettings Settings public static OnlinesSettings Settings
{ {
@ -57,15 +58,23 @@ namespace Mikai
} }
}; };
var conf = ModuleInvoke.Init("Mikai", JObject.FromObject(Mikai)); var defaults = JObject.FromObject(Mikai);
defaults["magic_apn"] = new JObject()
{
["ashdi"] = ApnHelper.DefaultHost
};
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);
conf.Remove("magic_apn");
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
Mikai = conf.ToObject<OnlinesSettings>(); Mikai = conf.ToObject<OnlinesSettings>();
if (hasApn) if (hasApn)
ApnHelper.ApplyInitConf(apnEnabled, apnHost, Mikai); ApnHelper.ApplyInitConf(apnEnabled, apnHost, Mikai);
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost); ApnHostProvided = ApnHelper.IsEnabled(Mikai);
if (hasApn && apnEnabled) if (ApnHostProvided)
{ {
Mikai.streamproxy = false; Mikai.streamproxy = false;
} }
@ -236,4 +245,4 @@ namespace Mikai
} }
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled); public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
} }

View File

@ -76,15 +76,17 @@ modules - optional, if not specified, all modules from the repository will be in
] ]
}, },
"displayindex": 1, "displayindex": 1,
"apn": true, "magic_apn": {
"apn_host": "domaine.com/{encodeurl}" "ashdi": "https://tut.im/proxy.php?url={encodeurl}"
}
} }
``` ```
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.
- `webcorshost` does not conflict with `apn`: APN is used at the streaming stage, not for regular parsing. - `magic_apn.ashdi` використовується тільки для Ashdi-посилань і лише коли значення непорожнє.
- `webcorshost` не конфліктує з `magic_apn`: CORS використовується для парсингу, `magic_apn` — для Ashdi-стрімінгу.
## JackTor config example (`init.conf`) ## JackTor config example (`init.conf`)

View File

@ -25,6 +25,23 @@ namespace Shared.Engine
return true; return true;
} }
public static string TryGetMagicAshdiHost(JObject conf)
{
if (conf == null || !conf.TryGetValue("magic_apn", out var magicToken) || magicToken == null)
return null;
if (magicToken.Type == JTokenType.Boolean)
return magicToken.Value<bool>() ? DefaultHost : null;
if (magicToken.Type == JTokenType.String)
return NormalizeHost(magicToken.Value<string>());
if (magicToken.Type != JTokenType.Object)
return null;
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
}
public static void ApplyInitConf(bool enabled, string host, BaseSettings init) public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
{ {
if (init == null) if (init == null)
@ -37,8 +54,13 @@ namespace Shared.Engine
return; return;
} }
if (string.IsNullOrWhiteSpace(host)) host = NormalizeHost(host);
host = DefaultHost; if (host == null)
{
init.apnstream = false;
init.apn = null;
return;
}
if (init.apn == null) if (init.apn == null)
init.apn = new ApnConf(); init.apn = new ApnConf();
@ -82,5 +104,13 @@ namespace Shared.Engine
return $"{host.TrimEnd('/')}/{url}"; return $"{host.TrimEnd('/')}/{url}";
} }
private static string NormalizeHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return null;
return host.Trim();
}
} }
} }

View File

@ -37,6 +37,7 @@ namespace Uaflix.Controllers
return badInitMsg; return badInitMsg;
var init = this.init; var init = this.init;
TryEnableMagicApn(init);
OnLog($"=== UAFLIX INDEX START ==="); OnLog($"=== UAFLIX INDEX START ===");
OnLog($"Uaflix Index: title={title}, serial={serial}, s={s}, play={play}, href={href}, checksearch={checksearch}"); OnLog($"Uaflix Index: title={title}, serial={serial}, s={s}, play={play}, href={href}, checksearch={checksearch}");
OnLog($"Uaflix Index: kinopoisk_id={kinopoisk_id}, imdb_id={imdb_id}, id={id}"); OnLog($"Uaflix Index: kinopoisk_id={kinopoisk_id}, imdb_id={imdb_id}, id={id}");
@ -435,6 +436,24 @@ namespace Uaflix.Controllers
return HostStreamProxy(init, link); return HostStreamProxy(init, link);
} }
private void TryEnableMagicApn(OnlinesSettings init)
{
if (init == null
|| init.apn != null
|| init.streamproxy
|| string.IsNullOrWhiteSpace(ModInit.MagicApnAshdiHost))
return;
string player = new RchClient(HttpContext, host, init, requestInfo).InfoConnected()?.player;
bool useInnerPlayer = string.IsNullOrWhiteSpace(player)
|| player.Equals("inner", StringComparison.OrdinalIgnoreCase);
if (!useInnerPlayer)
return;
ApnHelper.ApplyInitConf(true, ModInit.MagicApnAshdiHost, init);
OnLog($"Uaflix: увімкнено magic_apn для Ashdi (player={player ?? "unknown"}).");
}
private static string StripLampacArgs(string url) private static string StripLampacArgs(string url)
{ {
if (string.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))

View File

@ -24,6 +24,7 @@ namespace Uaflix
public static UaflixSettings UaFlix; public static UaflixSettings UaFlix;
public static bool ApnHostProvided; public static bool ApnHostProvided;
public static string MagicApnAshdiHost;
public static UaflixSettings Settings public static UaflixSettings Settings
{ {
@ -54,8 +55,16 @@ namespace Uaflix
} }
}; };
var conf = ModuleInvoke.Init("Uaflix", JObject.FromObject(UaFlix)) ?? JObject.FromObject(UaFlix); var defaults = JObject.FromObject(UaFlix);
defaults["magic_apn"] = new JObject()
{
["ashdi"] = ApnHelper.DefaultHost
};
var conf = ModuleInvoke.Init("Uaflix", 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);
conf.Remove("magic_apn");
conf.Remove("apn"); conf.Remove("apn");
conf.Remove("apn_host"); conf.Remove("apn_host");
UaFlix = conf.ToObject<UaflixSettings>(); UaFlix = conf.ToObject<UaflixSettings>();
@ -63,8 +72,8 @@ namespace Uaflix
if (hasApn) if (hasApn)
ApnHelper.ApplyInitConf(apnEnabled, apnHost, UaFlix); ApnHelper.ApplyInitConf(apnEnabled, apnHost, UaFlix);
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost); ApnHostProvided = ApnHelper.IsEnabled(UaFlix);
if (hasApn && apnEnabled) if (ApnHostProvided)
{ {
UaFlix.streamproxy = false; UaFlix.streamproxy = false;
} }