From 3741abb5d407d48445b897347ad5200355f8300f Mon Sep 17 00:00:00 2001 From: parasit32 Date: Sun, 9 Oct 2022 23:52:22 +0500 Subject: [PATCH] Checks availability of all servers --- .../ViewModels/MainWindowViewModel.cs | 24 ++++- .../AlbumDownloader.cs | 99 ++++++++++++++++--- .../Exceptions/AllServersAreUnreachable.cs | 24 +++++ 3 files changed, 133 insertions(+), 14 deletions(-) create mode 100644 src/CyberdropDownloader.Core/Exceptions/AllServersAreUnreachable.cs diff --git a/src/CyberdropDownloader.Avalonia/ViewModels/MainWindowViewModel.cs b/src/CyberdropDownloader.Avalonia/ViewModels/MainWindowViewModel.cs index ffc6b46..af5adc6 100644 --- a/src/CyberdropDownloader.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/src/CyberdropDownloader.Avalonia/ViewModels/MainWindowViewModel.cs @@ -196,8 +196,28 @@ await Task.Run(async () => } } - // Download album - await _albumDownloader.DownloadAsync(_webScraper.Album, _destinationInput.Text, _cancellationTokenSource?.Token, 100).ConfigureAwait(false); + try + { + // Download album + await _albumDownloader.DownloadAsync(_webScraper.Album, _destinationInput.Text, _cancellationTokenSource?.Token, 100).ConfigureAwait(false); + } + catch (Exception ex) + { + switch (ex) + { + case UriFormatException: + Log("Invalid URL format."); + break; + + case AllServersAreUnreachable: + Log("All Cyberdrop servers are unreachable at the time"); + break; + + default: + Log($"Unknown webscraper error. Please report this to the github repository. {ex.Message}"); + continue; + } + } } // IF the total downloads are greater or equal to 1 then log the total downloads diff --git a/src/CyberdropDownloader.Core/AlbumDownloader.cs b/src/CyberdropDownloader.Core/AlbumDownloader.cs index d288d20..512bc1b 100644 --- a/src/CyberdropDownloader.Core/AlbumDownloader.cs +++ b/src/CyberdropDownloader.Core/AlbumDownloader.cs @@ -9,6 +9,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using CyberdropDownloader.Core.Exceptions; namespace CyberdropDownloader.Core { @@ -17,15 +18,17 @@ public class AlbumDownloader private readonly HttpClient _downloadClient; private bool _authorized; private bool _running; + private List knownServers = new List{"fs-01", "fs-02", "fs-03", "fs-04", "fs-05", "fs-06"}; + private string workingServer = null; public AlbumDownloader(bool authorized) { + HttpClientHandler clientHandler = new HttpClientHandler(); + clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; + clientHandler.AllowAutoRedirect = true; + // Setup and initialize HttpClient - _downloadClient = new HttpClient(new SocketsHttpHandler() - { - AllowAutoRedirect = true, - KeepAlivePingTimeout = Timeout.InfiniteTimeSpan - }); + _downloadClient = new HttpClient(clientHandler); // Times out current download if it surpasses 5 minutes (might need tweaked) _downloadClient.Timeout = TimeSpan.FromMinutes(5); @@ -69,15 +72,46 @@ public async Task DownloadAsync(Album album, string path, CancellationToken? can string filePath = $"{path}\\{NormalizeFileName(file.Name)}"; + // Checking if we can avoid useless server call + // in case we already know this precise server is down based on previous album downloads + if (workingServer != null && workingServer != GetServerNameFromURL(file.Url)) + { + file.Url = ReplaceServerName(file.Url, workingServer); + } try { - HttpResponseMessage response = await _downloadClient.GetAsync(file.Url, HttpCompletionOption.ResponseHeadersRead); - - if (response.ReasonPhrase == "Bad Gateway") - throw new Exception(response.ReasonPhrase); - - while (response.ReasonPhrase == "Moved Temporarily") - response = await _downloadClient.GetAsync(response.Headers.Location, HttpCompletionOption.ResponseHeadersRead); + HttpResponseMessage response = await CheckAvailability(file); + // Next block will be executed only if we didn't have name of the working server from previous albums + if (response == null) + { + // If we couldn't get response from the server, then this server is down and should be removed from list + knownServers.Remove(GetServerNameFromURL(file.Url)); + // Iterating through all known server names and trying to make a request. + // If a precise server won't make a valid response, then its name will be deleted from server list + foreach (string serverName in knownServers) + { + file.Url = ReplaceServerName(file.Url, serverName); + response = await CheckAvailability(file); + if (response != null) + { + workingServer = serverName; + break; + } + else + { + knownServers.Remove(serverName); + if (!knownServers.Any()) + { + throw new AllServersAreUnreachable(); + } + } + } + } + // If response from server is good, then we should use this server for furure calls + else + { + workingServer = GetServerNameFromURL(file.Url); + } if (File.Exists(filePath)) { @@ -184,5 +218,46 @@ private static string NormalizePath(string data) return data; } + + private static string GetServerNameFromURL(string url) + { + Regex regex = new Regex(@"(fs-\d{2})"); + string result = null; + Match match = regex.Match(url); + if (match.Success) + { + result = match.Captures[0].ToString(); + } + else + { + throw new UriFormatException(); + } + return result; + } + + private static string ReplaceServerName(string url, string newServerName) + { + Regex regex = new Regex(@"(fs-\d{2})"); + if (!regex.Match(url).Success) + { + throw new UriFormatException(); + } + return regex.Replace(url, newServerName, 1); + } + + private async Task CheckAvailability(AlbumFile file) { + HttpResponseMessage response = null; + try + { + response = await _downloadClient.GetAsync(file.Url, HttpCompletionOption.ResponseHeadersRead); + if (response.ReasonPhrase == "Bad Gateway") + throw new Exception(response.ReasonPhrase); + + while (response.ReasonPhrase == "Moved Temporarily") + response = await _downloadClient.GetAsync(response.Headers.Location, HttpCompletionOption.ResponseHeadersRead); + } + catch (Exception) {} + return response; + } } } diff --git a/src/CyberdropDownloader.Core/Exceptions/AllServersAreUnreachable.cs b/src/CyberdropDownloader.Core/Exceptions/AllServersAreUnreachable.cs new file mode 100644 index 0000000..0e43978 --- /dev/null +++ b/src/CyberdropDownloader.Core/Exceptions/AllServersAreUnreachable.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.Serialization; + +namespace CyberdropDownloader.Core.Exceptions +{ + public class AllServersAreUnreachable : Exception + { + public AllServersAreUnreachable() + { + } + + public AllServersAreUnreachable(string message) : base(message) + { + } + + public AllServersAreUnreachable(string message, Exception innerException) : base(message, innerException) + { + } + + protected AllServersAreUnreachable(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +}