mirror of
https://github.com/2dust/v2rayN.git
synced 2026-04-16 20:45:45 +00:00
Auto-fill empty node remarks during speed tests
This commit is contained in:
parent
8ebc168db8
commit
5d76a3e26e
3 changed files with 117 additions and 7 deletions
|
|
@ -3,6 +3,11 @@ namespace ServiceLib.Handler;
|
|||
public static class ConnectionHandler
|
||||
{
|
||||
private static readonly string _tag = "ConnectionHandler";
|
||||
private static readonly string[] _speedtestIpApiUrls =
|
||||
[
|
||||
"https://api.ipapi.is",
|
||||
"https://api.ip.sb/geoip"
|
||||
];
|
||||
|
||||
public static async Task<string> RunAvailabilityCheck()
|
||||
{
|
||||
|
|
@ -20,23 +25,83 @@ public static class ConnectionHandler
|
|||
return null;
|
||||
}
|
||||
|
||||
var downloadHandle = new DownloadService();
|
||||
var result = await downloadHandle.TryDownloadString(url, true, "");
|
||||
if (result == null)
|
||||
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{port}");
|
||||
var ipInfo = await GetIpApiInfo(url, webProxy, 10);
|
||||
return FormatCountryAndIp(ipInfo, false);
|
||||
}
|
||||
|
||||
public static async Task<string?> GetCountryCodeAndIP(IWebProxy? webProxy, int downloadTimeout = 10)
|
||||
{
|
||||
foreach (var url in _speedtestIpApiUrls)
|
||||
{
|
||||
var ipInfo = await GetIpApiInfo(url, webProxy, downloadTimeout);
|
||||
var compact = FormatCountryAndIp(ipInfo, true);
|
||||
if (compact.IsNotEmpty())
|
||||
{
|
||||
return compact;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async Task<IPAPIInfo?> GetIpApiInfo(string url, IWebProxy? webProxy, int downloadTimeout)
|
||||
{
|
||||
if (url.IsNullOrEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(downloadTimeout));
|
||||
using var client = new HttpClient(new SocketsHttpHandler()
|
||||
{
|
||||
Proxy = webProxy,
|
||||
UseProxy = webProxy != null
|
||||
});
|
||||
client.DefaultRequestHeaders.UserAgent.TryParseAdd(Utils.GetVersion(false));
|
||||
|
||||
using var response = await client.GetAsync(url, cts.Token).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = await response.Content.ReadAsStringAsync(cts.Token).ConfigureAwait(false);
|
||||
return JsonUtils.Deserialize<IPAPIInfo>(result);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? FormatCountryAndIp(IPAPIInfo? ipInfo, bool compact)
|
||||
{
|
||||
if (ipInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;
|
||||
var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code;
|
||||
var ip = (ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query)?.Trim();
|
||||
if (ip.IsNullOrEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return $"({country ?? "unknown"}) {ip}";
|
||||
var country = (ipInfo.country_code ?? ipInfo.countryCode ?? ipInfo.location?.country_code ?? ipInfo.country)?.Trim();
|
||||
if (country.IsNullOrEmpty())
|
||||
{
|
||||
country = "unknown";
|
||||
}
|
||||
else
|
||||
{
|
||||
country = country.ToUpperInvariant();
|
||||
}
|
||||
|
||||
return compact ? $"{country}{ip}" : $"({country}) {ip}";
|
||||
}
|
||||
|
||||
private static async Task<int> GetRealPingTimeInfo()
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ public class ServerTestItem
|
|||
public int Port { get; set; }
|
||||
public EConfigType ConfigType { get; set; }
|
||||
public bool AllowTest { get; set; }
|
||||
public bool NeedAutoFillRemarks { get; set; }
|
||||
public int QueueNum { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,19 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
|||
private readonly Config? _config = config;
|
||||
private readonly Func<SpeedTestResult, Task>? _updateFunc = updateFunc;
|
||||
private static readonly ConcurrentBag<string> _lstExitLoop = new();
|
||||
private int _remarksUpdated;
|
||||
|
||||
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Interlocked.Exchange(ref _remarksUpdated, 0);
|
||||
await RunAsync(actionType, selecteds);
|
||||
await ProfileExManager.Instance.SaveTo();
|
||||
if (Interlocked.CompareExchange(ref _remarksUpdated, 0, 0) > 0)
|
||||
{
|
||||
AppEvents.ProfilesRefreshRequested.Publish();
|
||||
}
|
||||
await UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||
});
|
||||
}
|
||||
|
|
@ -80,6 +86,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
|||
Address = it.Address,
|
||||
Port = it.Port,
|
||||
ConfigType = it.ConfigType,
|
||||
NeedAutoFillRemarks = it.Remarks.IsNullOrEmpty(),
|
||||
QueueNum = selecteds.IndexOf(it)
|
||||
});
|
||||
}
|
||||
|
|
@ -297,11 +304,48 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
|||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||
var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||
|
||||
if (responseTime > 0 && it.NeedAutoFillRemarks)
|
||||
{
|
||||
await TryAutoFillRemarks(it, webProxy);
|
||||
}
|
||||
|
||||
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||
await UpdateFunc(it.IndexId, responseTime.ToString());
|
||||
return responseTime;
|
||||
}
|
||||
|
||||
private async Task TryAutoFillRemarks(ServerTestItem it, IWebProxy webProxy)
|
||||
{
|
||||
if (!it.NeedAutoFillRemarks || it.IndexId.IsNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var remarks = await ConnectionHandler.GetCountryCodeAndIP(webProxy, 8);
|
||||
if (remarks.IsNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var profileItem = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (profileItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (profileItem.Remarks.IsNotEmpty())
|
||||
{
|
||||
it.NeedAutoFillRemarks = false;
|
||||
return;
|
||||
}
|
||||
|
||||
profileItem.Remarks = remarks;
|
||||
if (await SQLiteHelper.Instance.UpdateAsync(profileItem) > 0)
|
||||
{
|
||||
it.NeedAutoFillRemarks = false;
|
||||
Interlocked.Increment(ref _remarksUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DoSpeedTest(DownloadService downloadHandle, ServerTestItem it)
|
||||
{
|
||||
await UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
||||
|
|
|
|||
Loading…
Reference in a new issue