mirror of
https://github.com/Megghy/MegghysAPI.git
synced 2025-12-06 22:26:56 +08:00
fix: 修复文件列表为空时的返回值处理并添加图像处理相关依赖
This commit is contained in:
177
Modules/ProxyManager.cs
Normal file
177
Modules/ProxyManager.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MegghysAPI.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// 代理IP管理器
|
||||
/// </summary>
|
||||
public static class ProxyManager
|
||||
{
|
||||
// 用于获取代理IP的客户端,不使用代理
|
||||
private static readonly HttpClient ProxyApiHttpClient = new();
|
||||
// 缓存代理IP的响应
|
||||
private static readonly MemoryCache ProxyResponseCache = new(new MemoryCacheOptions());
|
||||
// 缓存配置了代理的HttpClient
|
||||
private static readonly MemoryCache HttpClientCache = new(new MemoryCacheOptions());
|
||||
|
||||
private const string BaseUrl = "https://share.proxy.qg.net/get";
|
||||
private const string DefaultKey = "9IK2T3XL";
|
||||
private const string DefaultPassword = "04BC86C88CDB";
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置了代理的 HttpClient,带缓存和自动释放功能
|
||||
/// </summary>
|
||||
/// <param name="proxyAddress">可选的代理地址。如果为空,则自动获取。</param>
|
||||
/// <param name="key">代理用户名</param>
|
||||
/// <param name="password">代理密码</param>
|
||||
/// <returns>配置好代理的 HttpClient</returns>
|
||||
public static async Task<HttpClient> GetHttpClientAsync(string? proxyAddress = null, string key = DefaultKey, string password = DefaultPassword)
|
||||
{
|
||||
// 如果未提供代理地址,则从API获取
|
||||
if (string.IsNullOrWhiteSpace(proxyAddress))
|
||||
{
|
||||
var proxyResponse = await GetProxyAsync(key: key);
|
||||
var proxyIp = proxyResponse?.Data?.FirstOrDefault();
|
||||
|
||||
if (proxyIp?.Server == null || proxyIp.Deadline == null)
|
||||
{
|
||||
// 如果无法获取有效代理,返回一个不带代理的普通HttpClient
|
||||
return new HttpClient();
|
||||
}
|
||||
|
||||
// 检查缓存中是否已有此代理的HttpClient
|
||||
if (HttpClientCache.TryGetValue(proxyIp.Server, out HttpClient? cachedClient))
|
||||
{
|
||||
return cachedClient!;
|
||||
}
|
||||
|
||||
// 创建新的HttpClient并配置缓存
|
||||
var client = CreateConfiguredHttpClient(proxyIp.Server, key, password);
|
||||
var deadline = DateTime.Parse(proxyIp.Deadline);
|
||||
|
||||
var cacheEntryOptions = new MemoryCacheEntryOptions()
|
||||
.SetAbsoluteExpiration(deadline)
|
||||
.RegisterPostEvictionCallback((cacheKey, value, reason, state) =>
|
||||
{
|
||||
(value as HttpClient)?.Dispose();
|
||||
});
|
||||
|
||||
HttpClientCache.Set(proxyIp.Server, client, cacheEntryOptions);
|
||||
return client;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果用户手动提供了代理地址,我们无法知道其过期时间,因此不进行缓存
|
||||
return CreateConfiguredHttpClient(proxyAddress, key, password);
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpClient CreateConfiguredHttpClient(string proxyAddress, string key, string password)
|
||||
{
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.All,
|
||||
Proxy = new WebProxy(proxyAddress, false)
|
||||
{
|
||||
Credentials = new NetworkCredential(key, password)
|
||||
},
|
||||
UseProxy = true
|
||||
};
|
||||
var client = new HttpClient(handler, disposeHandler: true);
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取代理IP, 带缓存功能
|
||||
/// </summary>
|
||||
public static async Task<ProxyResponse?> GetProxyAsync(string key = DefaultKey, string? area = null, string? areaEx = null, int? isp = null, int? num = null, bool? distinct = null)
|
||||
{
|
||||
var queryParams = new Dictionary<string, string?>
|
||||
{
|
||||
{ "key", key },
|
||||
{ "area", area },
|
||||
{ "area_ex", areaEx },
|
||||
{ "isp", isp?.ToString() },
|
||||
{ "num", num?.ToString() },
|
||||
{ "distinct", distinct?.ToString().ToLower() }
|
||||
};
|
||||
|
||||
var queryString = string.Join("&", queryParams
|
||||
.Where(kvp => !string.IsNullOrEmpty(kvp.Value))
|
||||
.Select(kvp => $"{kvp.Key}={Uri.EscapeDataString(kvp.Value!)}"));
|
||||
|
||||
var cacheKey = $"ProxyResponse_{queryString}";
|
||||
|
||||
if (ProxyResponseCache.TryGetValue(cacheKey, out ProxyResponse? cachedResponse))
|
||||
{
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
var requestUrl = $"{BaseUrl}?{queryString}";
|
||||
|
||||
try
|
||||
{
|
||||
var response = await ProxyApiHttpClient.GetAsync(requestUrl);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
var proxyResponse = JsonSerializer.Deserialize<ProxyResponse>(json);
|
||||
|
||||
if (proxyResponse?.Code == "SUCCESS" && proxyResponse.Data?.Any() == true)
|
||||
{
|
||||
// 使用代理的过期时间作为缓存的过期时间
|
||||
var deadline = DateTime.Parse(proxyResponse.Data.First().Deadline!);
|
||||
ProxyResponseCache.Set(cacheKey, proxyResponse, deadline);
|
||||
}
|
||||
|
||||
return proxyResponse;
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
Console.WriteLine($"请求代理IP时发生错误: {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 代理IP接口响应
|
||||
/// </summary>
|
||||
public class ProxyResponse
|
||||
{
|
||||
[JsonPropertyName("code")]
|
||||
public string? Code { get; set; }
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public List<ProxyIp>? Data { get; set; }
|
||||
|
||||
[JsonPropertyName("request_id")]
|
||||
public string? RequestId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 代理IP信息
|
||||
/// </summary>
|
||||
public class ProxyIp
|
||||
{
|
||||
[JsonPropertyName("proxy_ip")]
|
||||
public string? ProxyIpAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("server")]
|
||||
public string? Server { get; set; }
|
||||
|
||||
[JsonPropertyName("area")]
|
||||
public string? Area { get; set; }
|
||||
|
||||
[JsonPropertyName("isp")]
|
||||
public string? Isp { get; set; }
|
||||
|
||||
[JsonPropertyName("deadline")]
|
||||
public string? Deadline { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user