mirror of
https://github.com/lampame/lampac-ukraine.git
synced 2026-06-17 12:08:54 +00:00
refactor: centralize module update logic and search registration into shared services while removing redundant helper files
This commit is contained in:
parent
fc68b69fd2
commit
35c16258f8
@ -1,116 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeHost(string host)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return host.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -85,27 +85,7 @@ namespace LME.AnimeON
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_animeon");
|
OnlineRegistry.RegisterWithSearch("lme_animeon");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -115,120 +95,17 @@ namespace LME.AnimeON
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.AnimeON.ModInit",
|
"initspace": "LME.AnimeON.ModInit",
|
||||||
"online": "LME.AnimeON.OnlineApi"
|
"online": "LME.AnimeON.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,86 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
host = DefaultHost;
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -63,7 +63,7 @@ namespace LME.Bamboo
|
|||||||
conf.Remove("apn_host");
|
conf.Remove("apn_host");
|
||||||
Bamboo = conf.ToObject<OnlinesSettings>();
|
Bamboo = conf.ToObject<OnlinesSettings>();
|
||||||
if (hasApn)
|
if (hasApn)
|
||||||
ApnHelper.ApplyInitConf(apnEnabled, apnHost, Bamboo);
|
ApnHelper.ApplyInitConf(apnEnabled, apnHost, Bamboo, useDefaultHostWhenEmpty: true);
|
||||||
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
||||||
if (hasApn && apnEnabled)
|
if (hasApn && apnEnabled)
|
||||||
{
|
{
|
||||||
@ -76,27 +76,7 @@ namespace LME.Bamboo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_bamboo");
|
OnlineRegistry.RegisterWithSearch("lme_bamboo");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -106,120 +86,17 @@ namespace LME.Bamboo
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.Bamboo.ModInit",
|
"initspace": "LME.Bamboo.ModInit",
|
||||||
"online": "LME.Bamboo.OnlineApi"
|
"online": "LME.Bamboo.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -78,27 +78,7 @@ namespace LME.JackTor
|
|||||||
JackTor.host = JackTor.jackett;
|
JackTor.host = JackTor.jackett;
|
||||||
|
|
||||||
// Показувати «уточнити пошук».
|
// Показувати «уточнити пошук».
|
||||||
RegisterWithSearch("lme_jacktor");
|
OnlineRegistry.RegisterWithSearch("lme_jacktor");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -108,110 +88,17 @@ namespace LME.JackTor
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
public static ActionResult Validate(ActionResult result)
|
||||||
|
=> _service.Validate(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.JackTor.ModInit",
|
"initspace": "LME.JackTor.ModInit",
|
||||||
"online": "LME.JackTor.OnlineApi"
|
"online": "LME.JackTor.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,116 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url)
|
|
||||||
&& url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeHost(string host)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return host.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -41,7 +41,7 @@ namespace LME.KlonFUN
|
|||||||
EventListener.UpdateInitFile += UpdateConfig;
|
EventListener.UpdateInitFile += UpdateConfig;
|
||||||
|
|
||||||
// Додаємо підтримку "уточнити пошук".
|
// Додаємо підтримку "уточнити пошук".
|
||||||
RegisterWithSearch("lme_klonfun");
|
OnlineRegistry.RegisterWithSearch("lme_klonfun");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateConfig()
|
private void UpdateConfig()
|
||||||
@ -88,26 +88,6 @@ namespace LME.KlonFUN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
EventListener.UpdateInitFile -= UpdateConfig;
|
EventListener.UpdateInitFile -= UpdateConfig;
|
||||||
@ -116,121 +96,17 @@ namespace LME.KlonFUN
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"initspace": "LME.KlonFUN.ModInit",
|
"initspace": "LME.KlonFUN.ModInit",
|
||||||
"online": "LME.KlonFUN.OnlineApi"
|
"online": "LME.KlonFUN.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -84,27 +84,7 @@ namespace LME.Makhno
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_makhno");
|
OnlineRegistry.RegisterWithSearch("lme_makhno");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -114,120 +94,17 @@ namespace LME.Makhno
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"initspace": "LME.Makhno.ModInit",
|
"initspace": "LME.Makhno.ModInit",
|
||||||
"online": "LME.Makhno.OnlineApi"
|
"online": "LME.Makhno.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,116 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeHost(string host)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return host.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -86,27 +86,7 @@ namespace LME.Mikai
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_mikai");
|
OnlineRegistry.RegisterWithSearch("lme_mikai");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -116,120 +96,17 @@ namespace LME.Mikai
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.Mikai.ModInit",
|
"initspace": "LME.Mikai.ModInit",
|
||||||
"online": "LME.Mikai.OnlineApi"
|
"online": "LME.Mikai.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,86 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
host = DefaultHost;
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -58,7 +58,7 @@ namespace LME.NMoonAnime
|
|||||||
NMoonAnime = conf.ToObject<OnlinesSettings>();
|
NMoonAnime = conf.ToObject<OnlinesSettings>();
|
||||||
|
|
||||||
if (hasApn)
|
if (hasApn)
|
||||||
ApnHelper.ApplyInitConf(apnEnabled, apnHost, NMoonAnime);
|
ApnHelper.ApplyInitConf(apnEnabled, apnHost, NMoonAnime, useDefaultHostWhenEmpty: true);
|
||||||
|
|
||||||
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
||||||
if (hasApn && apnEnabled)
|
if (hasApn && apnEnabled)
|
||||||
@ -71,27 +71,7 @@ namespace LME.NMoonAnime
|
|||||||
NMoonAnime.apn = null;
|
NMoonAnime.apn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterWithSearch("lme_nmoonanime");
|
OnlineRegistry.RegisterWithSearch("lme_nmoonanime");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -101,121 +81,17 @@ namespace LME.NMoonAnime
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.NMoonAnime.ModInit",
|
"initspace": "LME.NMoonAnime.ModInit",
|
||||||
"online": "LME.NMoonAnime.OnlineApi"
|
"online": "LME.NMoonAnime.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ namespace Shared.Engine
|
|||||||
return NormalizeHost(((JObject)magicToken).Value<string>("ashdi"));
|
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, bool useDefaultHostWhenEmpty = false)
|
||||||
{
|
{
|
||||||
if (init == null)
|
if (init == null)
|
||||||
return;
|
return;
|
||||||
@ -67,6 +67,9 @@ namespace Shared.Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
host = NormalizeHost(host);
|
||||||
|
if (host == null && useDefaultHostWhenEmpty)
|
||||||
|
host = DefaultHost;
|
||||||
|
|
||||||
if (host == null)
|
if (host == null)
|
||||||
{
|
{
|
||||||
init.apnstream = false;
|
init.apnstream = false;
|
||||||
@ -2,3 +2,5 @@ global using Shared.Services;
|
|||||||
global using Shared.Services.Hybrid;
|
global using Shared.Services.Hybrid;
|
||||||
global using Shared.Models.Base;
|
global using Shared.Models.Base;
|
||||||
global using AppInit = Shared.CoreInit;
|
global using AppInit = Shared.CoreInit;
|
||||||
|
global using LME.Shared.Online;
|
||||||
|
global using LME.Shared.Update;
|
||||||
28
LME.Shared/Online/OnlineRegistry.cs
Normal file
28
LME.Shared/Online/OnlineRegistry.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Shared;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LME.Shared.Online
|
||||||
|
{
|
||||||
|
public static class OnlineRegistry
|
||||||
|
{
|
||||||
|
public static void RegisterWithSearch(string plugin)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (CoreInit.conf.online.with_search == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var item in CoreInit.conf.online.with_search)
|
||||||
|
{
|
||||||
|
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreInit.conf.online.with_search.Add(plugin);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
LME.Shared/Update/ModuleUpdateService.cs
Normal file
139
LME.Shared/Update/ModuleUpdateService.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Mime;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LME.Shared.Update
|
||||||
|
{
|
||||||
|
public sealed class ModuleUpdateService
|
||||||
|
{
|
||||||
|
private const string ConnectUrl = "https://lmcuk.lme.isroot.in/stats";
|
||||||
|
|
||||||
|
private readonly Func<string> _pluginResolver;
|
||||||
|
private readonly Func<double> _versionResolver;
|
||||||
|
|
||||||
|
private ConnectResponse? _connect;
|
||||||
|
private DateTime? _connectTime;
|
||||||
|
private DateTime? _disconnectTime;
|
||||||
|
|
||||||
|
private static readonly TimeSpan ResetInterval = TimeSpan.FromHours(4);
|
||||||
|
private Timer? _resetTimer;
|
||||||
|
|
||||||
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
public ModuleUpdateService(Func<string> pluginResolver, Func<double> versionResolver)
|
||||||
|
{
|
||||||
|
_pluginResolver = pluginResolver;
|
||||||
|
_versionResolver = versionResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (_connectTime is not null || _connect?.IsUpdateUnavailable == true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_connectTime is not null || _connect?.IsUpdateUnavailable == true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_connectTime = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var handler = new SocketsHttpHandler
|
||||||
|
{
|
||||||
|
SslOptions = new SslClientAuthenticationOptions
|
||||||
|
{
|
||||||
|
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
||||||
|
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using var client = new HttpClient(handler);
|
||||||
|
client.Timeout = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
|
var request = new
|
||||||
|
{
|
||||||
|
Host = host,
|
||||||
|
Module = _pluginResolver(),
|
||||||
|
Version = _versionResolver(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
||||||
|
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||||
|
|
||||||
|
var response = await client
|
||||||
|
.PostAsync(ConnectUrl, requestContent, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
if (response.Content.Headers.ContentLength > 0)
|
||||||
|
{
|
||||||
|
var responseText = await response.Content
|
||||||
|
.ReadAsStringAsync(cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
_connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_resetTimer?.Dispose();
|
||||||
|
_resetTimer = null;
|
||||||
|
|
||||||
|
if (_connect?.IsUpdateUnavailable != true)
|
||||||
|
{
|
||||||
|
_resetTimer = new Timer(ResetConnectTime, null, ResetInterval, Timeout.InfiniteTimeSpan);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_disconnectTime = _connect?.IsNoiseEnabled == true
|
||||||
|
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
||||||
|
: DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ResetConnectTime(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDisconnected()
|
||||||
|
{
|
||||||
|
return _disconnectTime is not null
|
||||||
|
&& DateTime.UtcNow >= _disconnectTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionResult Validate(ActionResult result)
|
||||||
|
{
|
||||||
|
return IsDisconnected()
|
||||||
|
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetConnectTime(object? state)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_connectTime = null;
|
||||||
|
_connect = null;
|
||||||
|
|
||||||
|
_resetTimer?.Dispose();
|
||||||
|
_resetTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,86 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
host = DefaultHost;
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -63,7 +63,7 @@ namespace LME.StarLight
|
|||||||
conf.Remove("apn_host");
|
conf.Remove("apn_host");
|
||||||
StarLight = conf.ToObject<OnlinesSettings>();
|
StarLight = conf.ToObject<OnlinesSettings>();
|
||||||
if (hasApn)
|
if (hasApn)
|
||||||
ApnHelper.ApplyInitConf(apnEnabled, apnHost, StarLight);
|
ApnHelper.ApplyInitConf(apnEnabled, apnHost, StarLight, useDefaultHostWhenEmpty: true);
|
||||||
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
ApnHostProvided = hasApn && apnEnabled && !string.IsNullOrWhiteSpace(apnHost);
|
||||||
if (hasApn && apnEnabled)
|
if (hasApn && apnEnabled)
|
||||||
{
|
{
|
||||||
@ -76,27 +76,7 @@ namespace LME.StarLight
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_starlight");
|
OnlineRegistry.RegisterWithSearch("lme_starlight");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -106,120 +86,17 @@ namespace LME.StarLight
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.StarLight.ModInit",
|
"initspace": "LME.StarLight.ModInit",
|
||||||
"online": "LME.StarLight.OnlineApi"
|
"online": "LME.StarLight.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ApplyInitConf(bool enabled, string host, BaseSettings init)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeHost(string host)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return host.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -69,27 +69,7 @@ namespace LME.UafilmME
|
|||||||
UafilmME.apn = null;
|
UafilmME.apn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterWithSearch("lme_uafilmme");
|
OnlineRegistry.RegisterWithSearch("lme_uafilmme");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -99,117 +79,17 @@ namespace LME.UafilmME
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.UafilmME.ModInit",
|
"initspace": "LME.UafilmME.ModInit",
|
||||||
"online": "LME.UafilmME.OnlineApi"
|
"online": "LME.UafilmME.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,116 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Shared.Models.Base;
|
|
||||||
using System;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Shared.Engine
|
|
||||||
{
|
|
||||||
public static class ApnHelper
|
|
||||||
{
|
|
||||||
public const string DefaultHost = "https://tut.im/proxy.php?url={encodeurl}";
|
|
||||||
|
|
||||||
public static bool TryGetInitConf(JObject conf, out bool enabled, out string host)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
host = null;
|
|
||||||
|
|
||||||
if (conf == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!conf.TryGetValue("apn", out var apnToken) || apnToken?.Type != JTokenType.Boolean)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
enabled = apnToken.Value<bool>();
|
|
||||||
host = conf.Value<string>("apn_host");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (init == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
host = NormalizeHost(host);
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
init.apnstream = false;
|
|
||||||
init.apn = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init.apn == null)
|
|
||||||
init.apn = new ApnConf();
|
|
||||||
|
|
||||||
init.apn.host = host;
|
|
||||||
init.apnstream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsEnabled(BaseSettings init)
|
|
||||||
{
|
|
||||||
return init?.apnstream == true && !string.IsNullOrWhiteSpace(init?.apn?.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsAshdiUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url) &&
|
|
||||||
url.IndexOf("ashdi.vip", StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string WrapUrl(BaseSettings init, string url)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(init))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
return BuildUrl(init.apn.host, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string BuildUrl(string host, string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(url))
|
|
||||||
return url;
|
|
||||||
|
|
||||||
if (host.Contains("{encodeurl}"))
|
|
||||||
return host.Replace("{encodeurl}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{encode_uri}"))
|
|
||||||
return host.Replace("{encode_uri}", HttpUtility.UrlEncode(url));
|
|
||||||
|
|
||||||
if (host.Contains("{uri}"))
|
|
||||||
return host.Replace("{uri}", url);
|
|
||||||
|
|
||||||
return $"{host.TrimEnd('/')}/{url}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeHost(string host)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return host.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -85,27 +85,7 @@ namespace LME.Uaflix
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Показувати «уточнити пошук».
|
// Показувати «уточнити пошук».
|
||||||
RegisterWithSearch("lme_uaflix");
|
OnlineRegistry.RegisterWithSearch("lme_uaflix");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -115,121 +95,17 @@ namespace LME.Uaflix
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.Uaflix.ModInit",
|
"initspace": "LME.Uaflix.ModInit",
|
||||||
"online": "LME.Uaflix.OnlineApi"
|
"online": "LME.Uaflix.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
global using Shared.Services;
|
|
||||||
global using Shared.Services.Hybrid;
|
|
||||||
global using Shared.Models.Base;
|
|
||||||
global using AppInit = Shared.CoreInit;
|
|
||||||
@ -54,27 +54,7 @@ namespace LME.Unimay
|
|||||||
Unimay = ModuleInvoke.Init("LME.Unimay", defaults).ToObject<OnlinesSettings>();
|
Unimay = ModuleInvoke.Init("LME.Unimay", defaults).ToObject<OnlinesSettings>();
|
||||||
|
|
||||||
// Виводити "уточнити пошук"
|
// Виводити "уточнити пошук"
|
||||||
RegisterWithSearch("lme_unimay");
|
OnlineRegistry.RegisterWithSearch("lme_unimay");
|
||||||
}
|
|
||||||
|
|
||||||
private static void RegisterWithSearch(string plugin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CoreInit.conf.online.with_search == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var item in CoreInit.conf.online.with_search)
|
|
||||||
{
|
|
||||||
if (string.Equals(item, plugin, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInit.conf.online.with_search.Add(plugin);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -84,120 +64,17 @@ namespace LME.Unimay
|
|||||||
|
|
||||||
public static class UpdateService
|
public static class UpdateService
|
||||||
{
|
{
|
||||||
private static readonly string _connectUrl = "https://lmcuk.lme.isroot.in/stats";
|
private static readonly ModuleUpdateService _service = new(
|
||||||
|
() => ModInit.Settings?.plugin,
|
||||||
|
() => ModInit.Version);
|
||||||
|
|
||||||
private static ConnectResponse? Connect = null;
|
public static Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
||||||
private static DateTime? _connectTime = null;
|
=> _service.ConnectAsync(host, cancellationToken);
|
||||||
private static DateTime? _disconnectTime = null;
|
|
||||||
|
|
||||||
private static readonly TimeSpan _resetInterval = TimeSpan.FromHours(4);
|
|
||||||
private static Timer? _resetTimer = null;
|
|
||||||
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static async Task ConnectAsync(string host, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_connectTime is not null || Connect?.IsUpdateUnavailable == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var handler = new SocketsHttpHandler
|
|
||||||
{
|
|
||||||
SslOptions = new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler);
|
|
||||||
client.Timeout = TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
var request = new
|
|
||||||
{
|
|
||||||
Host = host,
|
|
||||||
Module = ModInit.Settings.plugin,
|
|
||||||
Version = ModInit.Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
var requestJson = JsonConvert.SerializeObject(request, Formatting.None);
|
|
||||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, MediaTypeNames.Application.Json);
|
|
||||||
|
|
||||||
var response = await client
|
|
||||||
.PostAsync(_connectUrl, requestContent, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
if (response.Content.Headers.ContentLength > 0)
|
|
||||||
{
|
|
||||||
var responseText = await response.Content
|
|
||||||
.ReadAsStringAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
Connect = JsonConvert.DeserializeObject<ConnectResponse>(responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
|
|
||||||
if (Connect?.IsUpdateUnavailable != true)
|
|
||||||
{
|
|
||||||
_resetTimer = new Timer(ResetConnectTime, null, _resetInterval, Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_disconnectTime = Connect?.IsNoiseEnabled == true
|
|
||||||
? DateTime.UtcNow.AddHours(Random.Shared.Next(1, 4))
|
|
||||||
: DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ResetConnectTime(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResetConnectTime(object? state)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_connectTime = null;
|
|
||||||
Connect = null;
|
|
||||||
|
|
||||||
_resetTimer?.Dispose();
|
|
||||||
_resetTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsDisconnected()
|
public static bool IsDisconnected()
|
||||||
{
|
=> _service.IsDisconnected();
|
||||||
return _disconnectTime is not null
|
|
||||||
&& DateTime.UtcNow >= _disconnectTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ActionResult Validate(ActionResult result)
|
public static ActionResult Validate(ActionResult result)
|
||||||
{
|
=> _service.Validate(result);
|
||||||
return IsDisconnected()
|
|
||||||
? throw new JsonReaderException($"Disconnect error: {Guid.CreateVersion7()}")
|
|
||||||
: result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ConnectResponse(bool IsUpdateUnavailable, bool IsNoiseEnabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,11 @@
|
|||||||
"enable": true,
|
"enable": true,
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"initspace": "LME.Unimay.ModInit",
|
"initspace": "LME.Unimay.ModInit",
|
||||||
"online": "LME.Unimay.OnlineApi"
|
"online": "LME.Unimay.OnlineApi",
|
||||||
}
|
"syntaxPaths": [
|
||||||
|
"../LME.Shared/GlobalUsings.cs",
|
||||||
|
"../LME.Shared/Online/OnlineRegistry.cs",
|
||||||
|
"../LME.Shared/Update/ModuleUpdateService.cs",
|
||||||
|
"../LME.Shared/Apn/ApnHelper.cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user