private static async Task <SearchQueryImages> GetSearchQueryImages(WebClient wc, string booru, string apiKey, string query, int page) { // Set required headers wc.Headers["User-Agent"] = UserAgent; string queryUrl = GetSearchQueryUrl(booru, apiKey, query, page); try { string searchJson = await wc.DownloadStringTaskAsync(queryUrl); SearchQueryImages result; if (booru != "twibooru.org") { result = JsonConvert.DeserializeObject <SearchQueryImages>(searchJson); } else { SearchQueryImagesTwibooru intermResult = JsonConvert.DeserializeObject <SearchQueryImagesTwibooru>(searchJson); result = new SearchQueryImages(); result.total = intermResult.total; result.images = intermResult.search.ConvertAll(im => (Image)im); } if (result.images == null) { Console.WriteLine($"Null search images. JSON: {searchJson}"); } return(result); } catch (WebException ex) { if (ex.Status == WebExceptionStatus.ProtocolError) { HttpWebResponse response = ex.Response as HttpWebResponse; if (response != null) { // Other http status code Console.WriteLine($"Error uploading image ({response.StatusCode})(request: {queryUrl}"); } else { // no http status code available Console.WriteLine("Error uploading image (Unknown error)"); } } else { // no http status code available Console.WriteLine("Error uploading image (Unknown error)"); } return(null); } }
public static async Task Main(string[] args) { Console.WriteLine($"Philomena Copier v{Version}"); Console.WriteLine(); Console.WriteLine("Ensure your filters are set correctly on the source booru. The active filter will be used when copying images."); Console.WriteLine("API keys can be found on the Account page."); Console.WriteLine(); // Get booru info string sourceBooru = GetInputWithPattern(DomainPattern, "Enter source booru url: "); string sourceApiKey = GetInputWithPattern(ApiKeyPattern, "Enter source booru API Key: "); string targetBooru = GetInputWithPattern(DomainPattern, "Enter target booru url: "); string targetApiKey = GetInputWithPattern(ApiKeyPattern, "Enter target booru API Key: "); // Get query Console.WriteLine("Enter query to copy from the source booru to the target booru. Any query that can be made on the site will work."); Console.Write("Query: "); string searchQuery = Console.ReadLine().Trim(); using (WebClient wc = new WebClient()) { // Get the first page of images int currentPage = 1; SearchQueryImages searchImages = await GetSearchQueryImages(wc, sourceBooru, sourceApiKey, searchQuery, currentPage); // Check how many images are in the query if (searchImages.total == 0) { Console.WriteLine("This query has no images! Double-check the query and try again."); return; } Console.WriteLine($"There are {searchImages.total} images in this query"); Console.WriteLine("Ensure the query and image count are correct! If they are not, Ctrl-C to exit. Otherwise, press enter to continue."); Console.ReadLine(); if (searchImages.images == null) { Console.WriteLine("Fatal error, searchImages.images is null"); } // Upload all images int currentImage = 1; TimeSpan currentRetryDelay; string sourceBooruAbbreviated = sourceBooru.Substring(0, sourceBooru.LastIndexOf(".")); while (searchImages.images.Count > 0) { // Upload the current page foreach (Image image in searchImages.images) { // Reset the retry delay currentRetryDelay = InitialRetryDelay; image.description = Regex.Replace(image.description, InSiteLinkPattern, new MatchEvaluator(match => ReplaceMDLink(match, sourceBooru))); image.description = Regex.Replace(image.description, RelativeLinkPattern, new MatchEvaluator(match => ReplaceRelLink(match, sourceBooru))); image.tags.Add($"{sourceBooruAbbreviated} import"); bool success = false; int attemptsAtMaxDelay = 0; while (!success && attemptsAtMaxDelay < maxAttemptsAtMaxDelay) { Console.WriteLine($"Uploading image {currentImage}/{searchImages.total} ({image.id})..."); PostStatus status = await UploadImage(wc, image, targetBooru, targetApiKey); if (status == PostStatus.Failure) { // Exponential backoff to prevent overloading server Console.WriteLine($"Retrying in {currentRetryDelay.TotalSeconds} seconds..."); await Task.Delay(currentRetryDelay); // Double the delay for next time, if it is below the max if (currentRetryDelay < MaxRetryDelay) { currentRetryDelay *= 2; } else { attemptsAtMaxDelay++; } } else { // Move to the next image success = true; } } if (attemptsAtMaxDelay >= maxAttemptsAtMaxDelay) { Console.WriteLine("Max attempts reached; moving onto next image."); } currentImage++; // Delay to prevent overloading servers await Task.Delay(InitialRetryDelay); } currentRetryDelay = InitialRetryDelay; // Load the next page currentPage++; do { searchImages = await GetSearchQueryImages(wc, sourceBooru, sourceApiKey, searchQuery, currentPage); if (searchImages == null) { Console.WriteLine($"Retrying in {currentRetryDelay.TotalSeconds} seconds..."); await Task.Delay(currentRetryDelay); if (currentRetryDelay < MaxRetryDelay) { currentRetryDelay *= 2; } } } while(searchImages == null); } } Console.WriteLine("Complete!"); }
public static async Task Main(string[] args) { Console.WriteLine($"Philomena Copier v{Version}"); Console.WriteLine(); Console.WriteLine("Ensure your filters are set correctly on the source booru. The active filter will be used when copying images."); Console.WriteLine("API keys can be found on the Account page."); Console.WriteLine(); // Get booru info string sourceBooru = GetInputWithPattern(DomainPattern, "Enter source booru url: "); string sourceApiKey = GetInputWithPattern(ApiKeyPattern, "Enter source booru API Key: "); string targetBooru = GetInputWithPattern(DomainPattern, "Enter target booru url: "); string targetApiKey = GetInputWithPattern(ApiKeyPattern, "Enter target booru API Key: "); // Get query Console.WriteLine("Enter query to copy from the source booru to the target booru. Any query that can be made on the site will work."); Console.Write("Query: "); string searchQuery = Console.ReadLine().Trim(); using (WebClient wc = new WebClient()) { // Get the first page of images int currentPage = 1; SearchQueryImages searchImages = await GetSearchQueryImages(wc, sourceBooru, sourceApiKey, searchQuery, currentPage); // Check how many images are in the query if (searchImages.total == 0) { Console.WriteLine("This query has no images! Double-check the query and try again."); return; } Console.WriteLine($"There are {searchImages.total} images in this query"); Console.WriteLine("Ensure the query and image count are correct! If they are not, Ctrl-C to exit. Otherwise, press enter to continue."); Console.ReadLine(); // Upload all images int currentImage = 1; TimeSpan currentRetryDelay; while (searchImages.images.Count > 0) { // Upload the current page foreach (Image image in searchImages.images) { // Reset the retry delay currentRetryDelay = InitialRetryDelay; bool success = false; while (!success) { Console.WriteLine($"Uploading image {currentImage}/{searchImages.total} ({image.id})..."); PostStatus status = await UploadImage(wc, image, targetBooru, targetApiKey); if (status == PostStatus.Failure) { // Exponential backoff to prevent overloading server Console.WriteLine($"Retrying in {currentRetryDelay.TotalSeconds} seconds..."); await Task.Delay(currentRetryDelay); // Double the delay for next time, if it is below the max if (currentRetryDelay < MaxRetryDelay) { currentRetryDelay *= 2; } } else { // Move to the next image success = true; } } currentImage++; // Delay to prevent overloading servers await Task.Delay(InitialRetryDelay); } // Load the next page currentPage++; searchImages = await GetSearchQueryImages(wc, sourceBooru, sourceApiKey, searchQuery, currentPage); } } Console.WriteLine("Complete!"); }