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; } } }