public static async Task <(Dictionary <string, WtmData> data, GetWtmCoinDataResult result)> GetWtmCoinData(IDictionary <string, double> coinHashList, bool interactive, StreamWriter logFile = null) { string statusBarText = "Downloading coin definitions from whattomine.com"; ViewModel.Instance.StatusBarText = statusBarText + "..."; int i = 0; int cnt = coinHashList.Count; var wtmRequestIntervalOld = ViewModel.Instance.WtmSettings.WtmRequestInterval; if (cnt > ViewModel.Instance.WtmSettings.DynamicRequestTrigger) { ViewModel.Instance.BypassUndo(() => { if (ViewModel.Instance.WtmSettings.WtmRequestInterval < ViewModel.Instance.WtmSettings.DynamicRequestInterval) { ViewModel.Instance.WtmSettings.WtmRequestInterval = ViewModel.Instance.WtmSettings.DynamicRequestInterval; } }); } bool errorFlag = false; bool continueFlag = false; bool exitEarly = false; CancellationTokenSource cancelSource = new CancellationTokenSource(); CancellationToken token = cancelSource.Token; ProgressManager pm = null; if (interactive) { pm = new ProgressManager("Accessing whattomine.com...", cancelSource); pm.SetIndeterminate(true); pm.SetProgressMaxValue(cnt); } await RespectTimeLimit(); var wtmLinks = await WhatToMine.GetWtmLinksFromJson(token).ConfigureAwait(false); if (token.IsCancellationRequested) { pm?.Close(); return(null, GetWtmCoinDataResult.Fail); } if (wtmLinks == null) { string errorMessage = "Failed to get the list of available coins from whattomine.com."; if (interactive) { pm?.Close(); MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } else { if (logFile != null) { logFile.WriteLine(errorMessage); } } return(null, GetWtmCoinDataResult.Fail); } if (interactive && pm != null) { pm.SetIndeterminate(false); pm.SetText("Downloading " + i + " of " + cnt); pm.SetProgressValue(0); } var wtmDataDict = new Dictionary <string, WtmData>(); string currentJsonStr = string.Empty; string currentCoinHtml = string.Empty; GetWtmCoinDataResult methodResult = GetWtmCoinDataResult.OK; foreach (var coin in coinHashList) { continueFlag = false; List <string> httpResults = new List <string>(); WtmLinks entry; wtmLinks.TryGetValue(coin.Key, out entry); if (entry == null) { string errorMessage = $"{coin.Key} has not been found among coins at http://whattomine.com/calculators. Execution aborted."; errorFlag = true; methodResult = GetWtmCoinDataResult.CoinNotFound; if (interactive) { Helpers.ShowErrorMessage(errorMessage); } else { if (logFile != null) { logFile.WriteLine(errorMessage); } } break; } //Check whattomine coin status if (!string.Equals(entry.Status, "Active", StringComparison.InvariantCultureIgnoreCase)) { MessageBoxResult response = MessageBoxResult.OK; string message = $"The status of {coin.Key} is reported as \"{entry.Status}\" by whattomine.com."; if (interactive) { response = MessageBox.Show(message, "Coin is not active", MessageBoxButton.OKCancel, MessageBoxImage.Warning); } else { logFile.WriteLine(message); } if (interactive && response == MessageBoxResult.Cancel) { errorFlag = true; break; } continue; } await RespectTimeLimit(); try { var response = await WtmHttpClient.GetAsync(entry.JsonLink + "?hr=" + coin.Value.ToString(CultureInfo.InvariantCulture), token).ConfigureAwait(false); var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); if (result != null && result.Contains("errors")) { var wtmErrorDict = JsonConverter.ConvertFromJson <Dictionary <string, object> >(result); if (wtmErrorDict != null) { object errorObj = null; wtmErrorDict.TryGetValue("errors", out errorObj); var errorList = errorObj as ArrayList; if (errorList != null) { string errorMessage = string.Join(". ", errorList.ToArray()); if (errorMessage != null) { throw new Exception(errorMessage); } } } } response.EnsureSuccessStatusCode(); httpResults.Add(result); } catch (Exception e) { if (interactive && e.Message == "A task was canceled.") { errorFlag = true; methodResult = GetWtmCoinDataResult.Fail; } else { string errorMessage = $"Failed to download {coin.Key} definition from whattomine.com."; //continueFlag = true; errorFlag = true; methodResult = GetWtmCoinDataResult.Fail; if (interactive) { Helpers.ShowErrorMessage(errorMessage + "\n\n" + e.Message); } else { if (logFile != null) { logFile.WriteLine(errorMessage); } } } } //if (continueFlag) // continue; if (errorFlag || httpResults == null) { break; } // Interpret JSON currentJsonStr = httpResults[0]; Dictionary <string, string> json = new Dictionary <string, string>(); json = JsonConverter.ConvertFromJson <Dictionary <string, string> >(currentJsonStr); if (json == null) { string errorMessage = $"Failed to interpret {coin.Key} definition from whattomine.com."; errorFlag = true; methodResult = GetWtmCoinDataResult.Fail; if (interactive) { Helpers.ShowErrorMessage(errorMessage); } else { if (logFile != null) { logFile.WriteLine(errorMessage); } } break; } else { var defaultHashrate = coin.Value; wtmDataDict.Add(coin.Key, new WtmData { DefaultHashrate = defaultHashrate, Json = json }); } if (pm != null && !pm.IsAlive) { exitEarly = true; break; } i++; if (interactive && pm != null) { pm.SetText("Downloaded " + i + " of " + cnt); pm.SetProgressValue(i); } else { ViewModel.Instance.StatusBarText = statusBarText + ": " + i + " of " + cnt; } } ViewModel.Instance.BypassUndo(() => ViewModel.Instance.WtmSettings.WtmRequestInterval = wtmRequestIntervalOld); ViewModel.Instance.UpdateNextJobStatus(); if (!exitEarly && interactive) { pm?.Close(); } if (errorFlag || exitEarly) { return(null, methodResult); } if (!interactive && (logFile != null)) { var noun = wtmDataDict.Count == 1 ? "coin" : "coins"; logFile.WriteLine($"The list of {wtmDataDict.Count} whattomine.com {noun} has been downloaded."); } return(wtmDataDict, GetWtmCoinDataResult.OK); }