diff --git a/Core/DataObjects/PTMagicData.cs b/Core/DataObjects/PTMagicData.cs index 0083de6..25865a1 100644 --- a/Core/DataObjects/PTMagicData.cs +++ b/Core/DataObjects/PTMagicData.cs @@ -36,8 +36,10 @@ namespace Core.Main.DataObjects.PTMagicData public bool TestMode { get; set; } = true; public bool EnableBetaFeatures { get; set; } = false; public string ProfitTrailerLicense { get; set; } = ""; + public string ProfitTrailerLicenseXtra { get; set; } = ""; public string ProfitTrailerServerAPIToken { get; set; } - public string ProfitTrailerMonitorURL { get; set; } = "http://localhost:8081/"; + public string ProfitTrailerMonitorURL { get; set; } = ""; + public string ProfitTrailerMonitorURLXtra { get; set; } = ""; public string ProfitTrailerDefaultSettingName { get; set; } = "default"; public int FloodProtectionMinutes { get; set; } = 15; public string Exchange { get; set; } @@ -517,4 +519,4 @@ namespace Core.Main.DataObjects.PTMagicData } #endregion -} +} \ No newline at end of file diff --git a/Core/ProfitTrailer/SettingsAPI.cs b/Core/ProfitTrailer/SettingsAPI.cs index 83dd315..ef77c4d 100644 --- a/Core/ProfitTrailer/SettingsAPI.cs +++ b/Core/ProfitTrailer/SettingsAPI.cs @@ -19,95 +19,122 @@ namespace Core.ProfitTrailer bool transferCompleted = false; bool transferCanceled = false; - while (!transferCompleted && !transferCanceled) + // get PT license list + string licenses = systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense; + if (systemConfiguration.GeneralSettings.Application.ProfitTrailerLicenseXtra != "") { - try + licenses = licenses + ", " + systemConfiguration.GeneralSettings.Application.ProfitTrailerLicenseXtra; + } + List licenseList = SystemHelper.ConvertTokenStringToList(licenses, ","); + int licenseCount = licenseList.Count; + + // get URL list + string urls = systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL; + if (systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURLXtra != "") + { + urls = urls + ", " + systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURLXtra; + } + List urlList = SystemHelper.ConvertTokenStringToList(urls, ","); + int urlCount = urlList.Count; + + log.DoLogInfo("Found " + licenseCount + " licenses and " + urlCount + " URLs"); + if (urlCount != licenseCount) + { + log.DoLogWarn("ERROR - urlCount must match licenseCount"); + } + for (int i = 0; i < licenseCount; i++) + { + transferCompleted = false; + while (!transferCompleted && !transferCanceled) { - ServicePointManager.Expect100Continue = true; - ServicePointManager.DefaultConnectionLimit = 9999; - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; - ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(CertificateHelper.AllwaysGoodCertificate); - - HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL + "settingsapi/settings/saveAll"); - httpWebRequest.ContentType = "application/x-www-form-urlencoded"; - httpWebRequest.Method = "POST"; - httpWebRequest.Proxy = null; - httpWebRequest.Timeout = 30000; - - // PT is using ordinary POST data, not JSON - string query = "configName=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "&license=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense; - string pairsPropertiesString = SystemHelper.ConvertListToTokenString(pairsLines, Environment.NewLine, false); - string dcaPropertiesString = SystemHelper.ConvertListToTokenString(dcaLines, Environment.NewLine, false); - string indicatorsPropertiesString = SystemHelper.ConvertListToTokenString(indicatorsLines, Environment.NewLine, false); - query += "&pairsData=" + WebUtility.UrlEncode(pairsPropertiesString) + "&dcaData=" + WebUtility.UrlEncode(dcaPropertiesString) + "&indicatorsData=" + WebUtility.UrlEncode(indicatorsPropertiesString); - - byte[] formData = Encoding.ASCII.GetBytes(query); - httpWebRequest.ContentLength = formData.Length; - - using (Stream stream = httpWebRequest.GetRequestStream()) + try { - stream.Write(formData, 0, formData.Length); + ServicePointManager.Expect100Continue = true; + ServicePointManager.DefaultConnectionLimit = 9999; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(CertificateHelper.AllwaysGoodCertificate); + HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(urlList[i] + "settingsapi/settings/saveAll"); + httpWebRequest.ContentType = "application/x-www-form-urlencoded"; + httpWebRequest.Method = "POST"; + httpWebRequest.Proxy = null; + httpWebRequest.Timeout = 30000; + + // PT is using ordinary POST data, not JSON + string query = "configName=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName; + query = query + "&license=" + licenseList[i]; + string pairsPropertiesString = SystemHelper.ConvertListToTokenString(pairsLines, Environment.NewLine, false); + string dcaPropertiesString = SystemHelper.ConvertListToTokenString(dcaLines, Environment.NewLine, false); + string indicatorsPropertiesString = SystemHelper.ConvertListToTokenString(indicatorsLines, Environment.NewLine, false); + query += "&pairsData=" + WebUtility.UrlEncode(pairsPropertiesString) + "&dcaData=" + WebUtility.UrlEncode(dcaPropertiesString) + "&indicatorsData=" + WebUtility.UrlEncode(indicatorsPropertiesString); + byte[] formData = Encoding.ASCII.GetBytes(query); + httpWebRequest.ContentLength = formData.Length; + using (Stream stream = httpWebRequest.GetRequestStream()) + { + stream.Write(formData, 0, formData.Length); + } + log.DoLogDebug("Built POST request for Properties"); + int adjustedCount = i+1; + log.DoLogInfo("Sending Properties to license " + adjustedCount + " at " + urlList[i]); + using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse()) + { + log.DoLogInfo("Properties sent!"); + httpResponse.Close(); + log.DoLogDebug("Properties response object closed."); + } + + transferCompleted = true; } - log.DoLogDebug("Built POST request for Properties"); + catch (WebException ex) + { + // Manual error handling as PT doesn't seem to provide a proper error response... + if (ex.Message.IndexOf("401") > -1) + { + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); + transferCanceled = true; + } + else if (ex.Message.IndexOf("timed out") > -1) + { + // Handle timeout seperately + retryCount++; + if (retryCount <= maxRetries) + { + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); + } + else + { + transferCanceled = true; + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries."); + } + } + else + { + log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); + transferCanceled = true; + } - log.DoLogInfo("Sending Properties..."); - using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse()) - { - log.DoLogInfo("Properties sent!"); - httpResponse.Close(); - log.DoLogDebug("Properties response object closed."); } - - transferCompleted = true; - } - catch (WebException ex) - { - // Manual error handling as PT doesn't seem to provide a proper error response... - if (ex.Message.IndexOf("401") > -1) + catch (TimeoutException ex) { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); - transferCanceled = true; - } - else if (ex.Message.IndexOf("timed out") > -1) - { - // Handle timeout seperately retryCount++; if (retryCount <= maxRetries) { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); } else { transferCanceled = true; - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries."); + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries."); } } - else + catch (Exception ex) { log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); transferCanceled = true; } - - } - catch (TimeoutException ex) - { - retryCount++; - if (retryCount <= maxRetries) - { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); - } - else - { - transferCanceled = true; - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries."); - } - } - catch (Exception ex) - { - log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); - transferCanceled = true; } } + + } } } \ No newline at end of file diff --git a/Core/ProfitTrailer/SettingsHandler.cs b/Core/ProfitTrailer/SettingsHandler.cs index 71bac93..c119c64 100644 --- a/Core/ProfitTrailer/SettingsHandler.cs +++ b/Core/ProfitTrailer/SettingsHandler.cs @@ -144,9 +144,8 @@ namespace Core.ProfitTrailer foreach (string line in pairsLines) { - if (line.Replace(" ", "").StartsWith("ALL_enabled_pairs", StringComparison.InvariantCultureIgnoreCase) || line.Replace(" ", "").StartsWith("enabled_pairs", StringComparison.InvariantCultureIgnoreCase)) + if (line.Replace(" ", "").StartsWith("enabled_pairs", StringComparison.InvariantCultureIgnoreCase)) { - result = line.Replace("ALL_enabled_pairs", "", StringComparison.InvariantCultureIgnoreCase); result = result.Replace("enabled_pairs", "", StringComparison.InvariantCultureIgnoreCase); result = result.Replace("#", ""); result = result.Replace("=", "").Trim(); @@ -644,4 +643,4 @@ namespace Core.ProfitTrailer } #endregion } -} +} \ No newline at end of file diff --git a/PTMagic/Program.cs b/PTMagic/Program.cs index 7e510b4..a4be87c 100644 --- a/PTMagic/Program.cs +++ b/PTMagic/Program.cs @@ -6,7 +6,7 @@ using Core.Helper; using Microsoft.Extensions.DependencyInjection; -[assembly: AssemblyVersion("2.5.11")] +[assembly: AssemblyVersion("2.5.12")] [assembly: AssemblyProduct("PT Magic")] namespace PTMagic diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json index eac6cf2..4f9bb22 100644 --- a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json +++ b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json @@ -3,10 +3,12 @@ "Application": { "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed - "ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above) + "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) + "ProfitTrailerLicenseXtra": "", // Licenses for additional bots for PTM to update (optional - comma separated list) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token - "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above) - "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above) + "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) + "ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list) + "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer "TimezoneOffset": "+0:00", // Your timezone offset from UTC time @@ -19,9 +21,9 @@ "Monitor": { "IsPasswordProtected": true, // Defines if your monitor will be asking to setup a password on its first start "OpenBrowserOnStart": false, // If active, a browser window will open as soon as you start the monitor - "Port": 5000, // The port you want to run your monitor on + "Port": 8080, // The port you want to run your monitor on "RootUrl": "/", // The root Url of your monitor - "AnalyzerChart":"", // By default the chart on the market analyzer page displays your base currency against USD. You may change this if you like (eg., BTCEUR) + "AnalyzerChart": "", // By default the chart on the Market Analyzer page will use your default currency against USD. You can change that here. (eg., BTCEUR) "GraphIntervalMinutes": 60, // The interval for the monitor market trend graph to draw points "GraphMaxTimeframeHours": 24, // This will enable you to define the timeframe that your graph for market trends covers "RefreshSeconds": 30, // The refresh interval of your monitor main page diff --git a/_Development/DevSettings/settings.general.json b/_Development/DevSettings/settings.general.json index 33b8405..4f9bb22 100644 --- a/_Development/DevSettings/settings.general.json +++ b/_Development/DevSettings/settings.general.json @@ -3,10 +3,12 @@ "Application": { "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed - "ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above) + "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) + "ProfitTrailerLicenseXtra": "", // Licenses for additional bots for PTM to update (optional - comma separated list) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token - "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above) - "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above) + "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) + "ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list) + "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer "TimezoneOffset": "+0:00", // Your timezone offset from UTC time