using System.Net.Http.Headers;
namespace ServiceLib.Services;
///
///Download
///
public class DownloadService
{
public event EventHandler? UpdateCompleted;
public event ErrorEventHandler? Error;
private static readonly string _tag = "DownloadService";
public async Task DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Func updateFunc)
{
try
{
var progress = new Progress();
progress.ProgressChanged += (sender, value) => updateFunc?.Invoke(false, $"{value}");
await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy,
url,
progress,
downloadTimeout);
}
catch (Exception ex)
{
await updateFunc?.Invoke(false, ex.Message);
if (ex.InnerException != null)
{
await updateFunc?.Invoke(false, ex.InnerException.Message);
}
}
return 0;
}
public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout)
{
try
{
UpdateCompleted?.Invoke(this, new RetResult(false, $"{ResUI.Downloading} {url}"));
var progress = new Progress();
progress.ProgressChanged += (sender, value) => UpdateCompleted?.Invoke(this, new RetResult(value > 100, $"...{value}%"));
var webProxy = await GetWebProxy(blProxy);
await DownloaderHelper.Instance.DownloadFileAsync(webProxy,
url,
fileName,
progress,
downloadTimeout);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
}
public async Task UrlRedirectAsync(string url, bool blProxy)
{
var webRequestHandler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
Proxy = await GetWebProxy(blProxy)
};
var client = new HttpClient(webRequestHandler);
var response = await client.GetAsync(url);
if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null)
{
return response.Headers.Location.ToString();
}
else
{
Error?.Invoke(this, new ErrorEventArgs(new Exception("StatusCode error: " + response.StatusCode)));
Logging.SaveLog("StatusCode error: " + url);
return null;
}
}
public async Task TryDownloadString(string url, bool blProxy, string userAgent)
{
try
{
var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15);
if (result1.IsNotEmpty())
{
return result1;
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
try
{
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15);
if (result2.IsNotEmpty())
{
return result2;
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
///
/// DownloadString
///
///
private async Task DownloadStringAsync(string url, bool blProxy, string userAgent, int timeout)
{
try
{
var webProxy = await GetWebProxy(blProxy);
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy,
UseProxy = webProxy != null
});
if (userAgent.IsNullOrEmpty())
{
userAgent = Utils.GetVersion(false);
}
client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);
Uri uri = new(url);
//Authorization Header
if (uri.UserInfo.IsNotEmpty())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo));
}
using var cts = new CancellationTokenSource();
var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
return result;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
///
/// DownloadString
///
///
private async Task DownloadStringViaDownloader(string url, bool blProxy, string userAgent, int timeout)
{
try
{
var webProxy = await GetWebProxy(blProxy);
if (userAgent.IsNullOrEmpty())
{
userAgent = Utils.GetVersion(false);
}
var result = await DownloaderHelper.Instance.DownloadStringAsync(webProxy, url, userAgent, timeout);
return result;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
private async Task GetWebProxy(bool blProxy)
{
if (!blProxy)
{
return null;
}
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
if (await SocketCheck(Global.Loopback, port) == false)
{
return null;
}
return new WebProxy($"socks5://{Global.Loopback}:{port}");
}
private async Task SocketCheck(string ip, int port)
{
try
{
IPEndPoint point = new(IPAddress.Parse(ip), port);
using Socket? sock = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await sock.ConnectAsync(point);
return true;
}
catch (Exception)
{
return false;
}
}
}