From bb376e1f63f9fe8f3017da344c76b1e7ba7c301d Mon Sep 17 00:00:00 2001 From: Nick Blakely Date: Sun, 16 Aug 2020 02:52:58 -0700 Subject: [PATCH] Add Discord link to launcher. --- Giants.Launcher/LauncherForm.Designer.cs | 17 + Giants.Launcher/LauncherForm.cs | 135 ++-- Giants.Launcher/LauncherForm.resx | 6 +- .../Properties/Resources.Designer.cs | 9 + Giants.Launcher/Properties/Resources.resx | 3 + Giants.WebApi.Clients/Clients.cs | 694 ++++++++++++------ Giants.WebApi.Clients/swagger.json | 194 ++--- 7 files changed, 689 insertions(+), 369 deletions(-) diff --git a/Giants.Launcher/LauncherForm.Designer.cs b/Giants.Launcher/LauncherForm.Designer.cs index 6a81b09..5c358b0 100644 --- a/Giants.Launcher/LauncherForm.Designer.cs +++ b/Giants.Launcher/LauncherForm.Designer.cs @@ -34,6 +34,7 @@ this.btnPlay = new Giants.Launcher.ImageButton(); this.updateProgressBar = new System.Windows.Forms.ProgressBar(); this.txtProgress = new System.Windows.Forms.Label(); + this.DiscordLabel = new System.Windows.Forms.LinkLabel(); ((System.ComponentModel.ISupportInitialize)(this.btnExit)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.btnOptions)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.btnPlay)).BeginInit(); @@ -107,6 +108,20 @@ this.txtProgress.Text = "ProgressText"; this.txtProgress.Visible = false; // + // DiscordLabel + // + this.DiscordLabel.AutoSize = true; + this.DiscordLabel.BackColor = System.Drawing.Color.Transparent; + this.DiscordLabel.LinkColor = System.Drawing.Color.Aquamarine; + this.DiscordLabel.Location = new System.Drawing.Point(12, 9); + this.DiscordLabel.Name = "DiscordLabel"; + this.DiscordLabel.Size = new System.Drawing.Size(69, 13); + this.DiscordLabel.TabIndex = 12; + this.DiscordLabel.TabStop = true; + this.DiscordLabel.Text = "DiscordLabel"; + this.DiscordLabel.Visible = false; + this.DiscordLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.DiscordLabel_LinkClicked); + // // LauncherForm // this.AcceptButton = this.btnPlay; @@ -116,6 +131,7 @@ this.CancelButton = this.btnExit; this.ClientSize = new System.Drawing.Size(800, 500); this.ControlBox = false; + this.Controls.Add(this.DiscordLabel); this.Controls.Add(this.txtProgress); this.Controls.Add(this.updateProgressBar); this.Controls.Add(this.btnExit); @@ -145,6 +161,7 @@ private ImageButton btnExit; private System.Windows.Forms.ProgressBar updateProgressBar; private System.Windows.Forms.Label txtProgress; + private System.Windows.Forms.LinkLabel DiscordLabel; } } diff --git a/Giants.Launcher/LauncherForm.cs b/Giants.Launcher/LauncherForm.cs index 2344dec..440d225 100644 --- a/Giants.Launcher/LauncherForm.cs +++ b/Giants.Launcher/LauncherForm.cs @@ -16,25 +16,34 @@ namespace Giants.Launcher public partial class LauncherForm : Form { // Constant settings - private const string GAME_NAME = "Giants: Citizen Kabuto"; - private const string GAME_PATH = "GiantsMain.exe"; - private const string REGISTRY_KEY = @"HKEY_CURRENT_USER\Software\PlanetMoon\Giants"; - private const string REGISTRY_VALUE = "DestDir"; - private readonly VersionClient httpClient; + private const string GameName = "Giants: Citizen Kabuto"; + private const string GamePath = "GiantsMain.exe"; + private const string RegistryKey = @"HKEY_CURRENT_USER\Software\PlanetMoon\Giants"; + private const string RegistryValue = "DestDir"; + private const string BaseUrl = "https://giants.azurewebsites.net"; // TODO: Read from file + + private readonly HttpClient httpClient; + private readonly VersionClient versionHttpClient; + private readonly DiscordClient discordHttpClient; private string commandLine = String.Empty; private string gamePath = null; private Updater updater; + private string discordUri; public LauncherForm() { this.InitializeComponent(); // Set window title - this.Text = GAME_NAME; + this.Text = GameName; - this.httpClient = new VersionClient(new HttpClient()); - this.httpClient.BaseUrl = "https://giants.azurewebsites.net"; // TODO: Read from file + this.httpClient = new HttpClient(); + this.versionHttpClient = new VersionClient(this.httpClient); + this.versionHttpClient.BaseUrl = BaseUrl; + + this.discordHttpClient = new DiscordClient(this.httpClient); + this.discordHttpClient.BaseUrl = BaseUrl; } private void btnExit_Click(object sender, EventArgs e) @@ -73,7 +82,7 @@ namespace Giants.Launcher private void btnOptions_Click(object sender, EventArgs e) { - OptionsForm form = new OptionsForm(GAME_NAME + " Options", this.gamePath); + OptionsForm form = new OptionsForm(GameName + " Options", this.gamePath); form.ShowDialog(); } @@ -82,16 +91,16 @@ namespace Giants.Launcher { // Find the game executable, first looking for it relative to our current directory and then // using the registry path if that fails. - this.gamePath = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + GAME_PATH; + this.gamePath = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + GamePath; if (!File.Exists(this.gamePath)) { - this.gamePath = (string)Registry.GetValue(REGISTRY_KEY, REGISTRY_VALUE, null); + this.gamePath = (string)Registry.GetValue(RegistryKey, RegistryValue, null); if (this.gamePath != null) - this.gamePath = Path.Combine(this.gamePath, GAME_PATH); + this.gamePath = Path.Combine(this.gamePath, GamePath); if (this.gamePath == null || !File.Exists(this.gamePath)) { - string message = string.Format(Resources.AppNotFound, GAME_NAME); + string message = string.Format(Resources.AppNotFound, GameName); MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; @@ -102,43 +111,68 @@ namespace Giants.Launcher GameSettings.Load(this.gamePath); if (GameSettings.Get("NoAutoUpdate") == 0) - { - Version gameVersion = VersionHelper.GetGameVersion(this.gamePath); - if (gameVersion == null) - { - string message = string.Format(Resources.AppNotFound, GAME_NAME); - MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - Application.Exit(); - } + { + Version gameVersion = VersionHelper.GetGameVersion(this.gamePath); + if (gameVersion == null) + { + string message = string.Format(Resources.AppNotFound, GameName); + MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + Application.Exit(); + } - var appVersions = new Dictionary() - { - [ApplicationType.Game] = gameVersion, - [ApplicationType.Launcher] = VersionHelper.GetLauncherVersion() - }; + var appVersions = new Dictionary() + { + [ApplicationType.Game] = gameVersion, + [ApplicationType.Launcher] = VersionHelper.GetLauncherVersion() + }; - // Check for updates - this.updater = new Updater( - appVersions: appVersions, - updateCompletedCallback: this.LauncherForm_DownloadCompletedCallback, - updateProgressCallback: this.LauncherForm_DownloadProgressCallback); + // Check for updates + Task updateTask = this.CheckForUpdates(appVersions); + Task discordTask = this.CheckDiscordStatus(); - Task gameVersionInfo = this.GetVersionInfo(ApplicationNames.Giants); - Task launcherVersionInfo = this.GetVersionInfo(ApplicationNames.GiantsLauncher); - - await Task.WhenAll(gameVersionInfo, launcherVersionInfo); - - await this.updater.UpdateApplication(ApplicationType.Game, gameVersionInfo.Result); - await this.updater.UpdateApplication(ApplicationType.Launcher, launcherVersionInfo.Result); - } + await Task.WhenAll(updateTask, discordTask); + } } - private async Task GetVersionInfo(string appName) + private async Task CheckDiscordStatus() + { + try + { + var status = await this.discordHttpClient.GetDiscordStatusAsync(); + + this.discordUri = status.DiscordUri; + this.DiscordLabel.Text = Resources.DiscordLabel; + this.DiscordLabel.Visible = true; + } + catch (Exception) + { + // Ignore + } + } + + + private async Task CheckForUpdates(Dictionary appVersions) + { + this.updater = new Updater( + appVersions: appVersions, + updateCompletedCallback: this.LauncherForm_DownloadCompletedCallback, + updateProgressCallback: this.LauncherForm_DownloadProgressCallback); + + Task gameVersionInfo = this.GetVersionInfo(ApplicationNames.Giants); + Task launcherVersionInfo = this.GetVersionInfo(ApplicationNames.GiantsLauncher); + + await Task.WhenAll(gameVersionInfo, launcherVersionInfo); + + await this.updater.UpdateApplication(ApplicationType.Game, gameVersionInfo.Result); + await this.updater.UpdateApplication(ApplicationType.Launcher, launcherVersionInfo.Result); + } + + private async Task GetVersionInfo(string appName) { VersionInfo versionInfo; try { - versionInfo = await this.httpClient.GetVersionInfoAsync(appName); + versionInfo = await this.versionHttpClient.GetVersionInfoAsync(appName); return versionInfo; } catch (ApiException ex) @@ -236,5 +270,22 @@ namespace Giants.Launcher this.txtProgress.Visible = true; this.txtProgress.Text = string.Format(Resources.DownloadProgress, e.ProgressPercentage, info.FileSize / 1024 / 1024); } - } + + private void DiscordLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + if (string.IsNullOrEmpty(this.discordUri)) + { + return; + } + + var uri = new Uri(this.discordUri); + if (uri.Scheme != "https") + { + // For security, reject any non-HTTPS or local file system URIs + return; + } + + Process.Start(this.discordUri); + } + } } diff --git a/Giants.Launcher/LauncherForm.resx b/Giants.Launcher/LauncherForm.resx index e1c3759..b06cf3d 100644 --- a/Giants.Launcher/LauncherForm.resx +++ b/Giants.Launcher/LauncherForm.resx @@ -112,12 +112,12 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + iVBORw0KGgoAAAANSUhEUgAAAEYAAAAnCAYAAACyhj57AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 diff --git a/Giants.Launcher/Properties/Resources.Designer.cs b/Giants.Launcher/Properties/Resources.Designer.cs index f2d8467..2c03f5c 100644 --- a/Giants.Launcher/Properties/Resources.Designer.cs +++ b/Giants.Launcher/Properties/Resources.Designer.cs @@ -79,6 +79,15 @@ namespace Giants.Launcher { } } + /// + /// Looks up a localized string similar to Join the community on Discord!. + /// + internal static string DiscordLabel { + get { + return ResourceManager.GetString("DiscordLabel", resourceCulture); + } + } + /// /// Looks up a localized string similar to Downloading - {0}% of {1} MB. /// diff --git a/Giants.Launcher/Properties/Resources.resx b/Giants.Launcher/Properties/Resources.resx index 087caec..92921b2 100644 --- a/Giants.Launcher/Properties/Resources.resx +++ b/Giants.Launcher/Properties/Resources.resx @@ -199,4 +199,7 @@ {0} Samples + + Join the community on Discord! + \ No newline at end of file diff --git a/Giants.WebApi.Clients/Clients.cs b/Giants.WebApi.Clients/Clients.cs index 647b411..30b7162 100644 --- a/Giants.WebApi.Clients/Clients.cs +++ b/Giants.WebApi.Clients/Clients.cs @@ -14,212 +14,6 @@ namespace Giants.WebApi.Clients { using System = global::System; - [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.7.0.0 (NJsonSchema v10.1.24.0 (Newtonsoft.Json v11.0.0.0))")] - public partial class VersionClient - { - private string _baseUrl = "https://localhost:44304"; - private System.Net.Http.HttpClient _httpClient; - private System.Lazy _settings; - - public VersionClient(System.Net.Http.HttpClient httpClient) - { - _httpClient = httpClient; - _settings = new System.Lazy(CreateSerializerSettings); - } - - private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() - { - var settings = new Newtonsoft.Json.JsonSerializerSettings(); - UpdateJsonSerializerSettings(settings); - return settings; - } - - public string BaseUrl - { - get { return _baseUrl; } - set { _baseUrl = value; } - } - - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } - - partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); - partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); - partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); - partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); - - /// A server side error occurred. - public System.Threading.Tasks.Task GetVersionInfoAsync(string appName) - { - return GetVersionInfoAsync(appName, System.Threading.CancellationToken.None); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A server side error occurred. - public async System.Threading.Tasks.Task GetVersionInfoAsync(string appName, System.Threading.CancellationToken cancellationToken) - { - var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Version?"); - if (appName != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("appName") + "=").Append(System.Uri.EscapeDataString(ConvertToString(appName, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); - } - urlBuilder_.Length--; - - var client_ = _httpClient; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); - - PrepareRequest(client_, request_, urlBuilder_); - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - try - { - var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (response_ != null) - response_.Dispose(); - } - } - } - finally - { - } - } - - protected struct ObjectResponseResult - { - public ObjectResponseResult(T responseObject, string responseText) - { - this.Object = responseObject; - this.Text = responseText; - } - - public T Object { get; } - - public string Text { get; } - } - - public bool ReadResponseAsString { get; set; } - - protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers) - { - if (response == null || response.Content == null) - { - return new ObjectResponseResult(default(T), string.Empty); - } - - if (ReadResponseAsString) - { - var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - try - { - var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); - return new ObjectResponseResult(typedBody, responseText); - } - catch (Newtonsoft.Json.JsonException exception) - { - var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; - throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); - } - } - else - { - try - { - using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - using (var streamReader = new System.IO.StreamReader(responseStream)) - using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) - { - var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); - var typedBody = serializer.Deserialize(jsonTextReader); - return new ObjectResponseResult(typedBody, string.Empty); - } - } - catch (Newtonsoft.Json.JsonException exception) - { - var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; - throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); - } - } - } - - private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) - { - if (value == null) - { - return null; - } - - if (value is System.Enum) - { - var name = System.Enum.GetName(value.GetType(), value); - if (name != null) - { - var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); - if (field != null) - { - var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) - as System.Runtime.Serialization.EnumMemberAttribute; - if (attribute != null) - { - return attribute.Value != null ? attribute.Value : name; - } - } - - return System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); - } - } - else if (value is bool) - { - return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); - } - else if (value is byte[]) - { - return System.Convert.ToBase64String((byte[]) value); - } - else if (value.GetType().IsArray) - { - var array = System.Linq.Enumerable.OfType((System.Array) value); - return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo))); - } - - var result = System.Convert.ToString(value, cultureInfo); - return (result is null) ? string.Empty : result; - } - } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.7.0.0 (NJsonSchema v10.1.24.0 (Newtonsoft.Json v11.0.0.0))")] public partial class ServersClient { @@ -546,43 +340,414 @@ namespace Giants.WebApi.Clients return (result is null) ? string.Empty : result; } } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.7.0.0 (NJsonSchema v10.1.24.0 (Newtonsoft.Json v11.0.0.0))")] + public partial class DiscordClient + { + private string _baseUrl = "https://localhost:44304"; + private System.Net.Http.HttpClient _httpClient; + private System.Lazy _settings; + + public DiscordClient(System.Net.Http.HttpClient httpClient) + { + _httpClient = httpClient; + _settings = new System.Lazy(CreateSerializerSettings); + } + + private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + } + + public string BaseUrl + { + get { return _baseUrl; } + set { _baseUrl = value; } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + + partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// A server side error occurred. + public System.Threading.Tasks.Task GetDiscordStatusAsync() + { + return GetDiscordStatusAsync(System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetDiscordStatusAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Discord"); + + var client_ = _httpClient; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + } + } + + protected struct ObjectResponseResult + { + public ObjectResponseResult(T responseObject, string responseText) + { + this.Object = responseObject; + this.Text = responseText; + } + + public T Object { get; } + + public string Text { get; } + } + + public bool ReadResponseAsString { get; set; } + + protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers) + { + if (response == null || response.Content == null) + { + return new ObjectResponseResult(default(T), string.Empty); + } + + if (ReadResponseAsString) + { + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); + return new ObjectResponseResult(typedBody, responseText); + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); + } + } + else + { + try + { + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new System.IO.StreamReader(responseStream)) + using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) + { + var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); + var typedBody = serializer.Deserialize(jsonTextReader); + return new ObjectResponseResult(typedBody, string.Empty); + } + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); + } + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value == null) + { + return null; + } + + if (value is System.Enum) + { + var name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value != null ? attribute.Value : name; + } + } + + return System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); + } + } + else if (value is bool) + { + return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value.GetType().IsArray) + { + var array = System.Linq.Enumerable.OfType((System.Array) value); + return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo))); + } + + var result = System.Convert.ToString(value, cultureInfo); + return (result is null) ? string.Empty : result; + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.7.0.0 (NJsonSchema v10.1.24.0 (Newtonsoft.Json v11.0.0.0))")] + public partial class VersionClient + { + private string _baseUrl = "https://localhost:44304"; + private System.Net.Http.HttpClient _httpClient; + private System.Lazy _settings; + + public VersionClient(System.Net.Http.HttpClient httpClient) + { + _httpClient = httpClient; + _settings = new System.Lazy(CreateSerializerSettings); + } + + private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + } + + public string BaseUrl + { + get { return _baseUrl; } + set { _baseUrl = value; } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + + partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// A server side error occurred. + public System.Threading.Tasks.Task GetVersionInfoAsync(string appName) + { + return GetVersionInfoAsync(appName, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetVersionInfoAsync(string appName, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Version?"); + if (appName != null) + { + urlBuilder_.Append(System.Uri.EscapeDataString("appName") + "=").Append(System.Uri.EscapeDataString(ConvertToString(appName, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } + urlBuilder_.Length--; + + var client_ = _httpClient; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + } + } + + protected struct ObjectResponseResult + { + public ObjectResponseResult(T responseObject, string responseText) + { + this.Object = responseObject; + this.Text = responseText; + } + + public T Object { get; } + + public string Text { get; } + } + + public bool ReadResponseAsString { get; set; } + + protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers) + { + if (response == null || response.Content == null) + { + return new ObjectResponseResult(default(T), string.Empty); + } + + if (ReadResponseAsString) + { + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); + return new ObjectResponseResult(typedBody, responseText); + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); + } + } + else + { + try + { + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new System.IO.StreamReader(responseStream)) + using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) + { + var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); + var typedBody = serializer.Deserialize(jsonTextReader); + return new ObjectResponseResult(typedBody, string.Empty); + } + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); + } + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value == null) + { + return null; + } + + if (value is System.Enum) + { + var name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value != null ? attribute.Value : name; + } + } + + return System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); + } + } + else if (value is bool) + { + return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value.GetType().IsArray) + { + var array = System.Linq.Enumerable.OfType((System.Array) value); + return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo))); + } + + var result = System.Convert.ToString(value, cultureInfo); + return (result is null) ? string.Empty : result; + } + } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] - public partial class VersionInfo - { - [Newtonsoft.Json.JsonProperty("appName", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string AppName { get; set; } - - [Newtonsoft.Json.JsonProperty("version", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public AppVersion Version { get; set; } = new AppVersion(); - - [Newtonsoft.Json.JsonProperty("installerUri", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public System.Uri InstallerUri { get; set; } - - - } - - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] - public partial class AppVersion - { - [Newtonsoft.Json.JsonProperty("build", Required = Newtonsoft.Json.Required.Always)] - public int Build { get; set; } - - [Newtonsoft.Json.JsonProperty("major", Required = Newtonsoft.Json.Required.Always)] - public int Major { get; set; } - - [Newtonsoft.Json.JsonProperty("minor", Required = Newtonsoft.Json.Required.Always)] - public int Minor { get; set; } - - [Newtonsoft.Json.JsonProperty("revision", Required = Newtonsoft.Json.Required.Always)] - public int Revision { get; set; } - - - } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] public partial class ServerInfoWithHostAddress : ServerInfo { @@ -648,6 +813,24 @@ namespace Giants.WebApi.Clients public System.Collections.Generic.ICollection PlayerInfo { get; set; } = new System.Collections.ObjectModel.Collection(); + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] + public partial class AppVersion + { + [Newtonsoft.Json.JsonProperty("build", Required = Newtonsoft.Json.Required.Always)] + public int Build { get; set; } + + [Newtonsoft.Json.JsonProperty("major", Required = Newtonsoft.Json.Required.Always)] + public int Major { get; set; } + + [Newtonsoft.Json.JsonProperty("minor", Required = Newtonsoft.Json.Required.Always)] + public int Minor { get; set; } + + [Newtonsoft.Json.JsonProperty("revision", Required = Newtonsoft.Json.Required.Always)] + public int Revision { get; set; } + + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] @@ -671,6 +854,33 @@ namespace Giants.WebApi.Clients public string TeamName { get; set; } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] + public partial class DiscordStatus + { + [Newtonsoft.Json.JsonProperty("discordUri", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string DiscordUri { get; set; } + + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v11.0.0.0)")] + public partial class VersionInfo + { + [Newtonsoft.Json.JsonProperty("appName", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string AppName { get; set; } + + [Newtonsoft.Json.JsonProperty("version", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public AppVersion Version { get; set; } = new AppVersion(); + + [Newtonsoft.Json.JsonProperty("installerUri", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public System.Uri InstallerUri { get; set; } + + } [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.7.0.0 (NJsonSchema v10.1.24.0 (Newtonsoft.Json v11.0.0.0))")] diff --git a/Giants.WebApi.Clients/swagger.json b/Giants.WebApi.Clients/swagger.json index 3076fb1..ac96b8a 100644 --- a/Giants.WebApi.Clients/swagger.json +++ b/Giants.WebApi.Clients/swagger.json @@ -11,37 +11,6 @@ } ], "paths": { - "/api/Version": { - "get": { - "tags": [ - "Version" - ], - "operationId": "Version_GetVersionInfo", - "parameters": [ - { - "name": "appName", - "in": "query", - "schema": { - "type": "string", - "nullable": true - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VersionInfo" - } - } - } - } - } - } - }, "/api/Servers": { "delete": { "tags": [ @@ -98,61 +67,61 @@ } } } + }, + "/api/Discord": { + "get": { + "tags": [ + "Discord" + ], + "operationId": "Discord_GetDiscordStatus", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DiscordStatus" + } + } + } + } + } + } + }, + "/api/Version": { + "get": { + "tags": [ + "Version" + ], + "operationId": "Version_GetVersionInfo", + "parameters": [ + { + "name": "appName", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionInfo" + } + } + } + } + } + } } }, "components": { "schemas": { - "VersionInfo": { - "type": "object", - "additionalProperties": false, - "required": [ - "appName", - "version", - "installerUri" - ], - "properties": { - "appName": { - "type": "string", - "minLength": 1 - }, - "version": { - "$ref": "#/components/schemas/AppVersion" - }, - "installerUri": { - "type": "string", - "format": "uri", - "minLength": 1 - } - } - }, - "AppVersion": { - "type": "object", - "additionalProperties": false, - "required": [ - "build", - "major", - "minor", - "revision" - ], - "properties": { - "build": { - "type": "integer", - "format": "int32" - }, - "major": { - "type": "integer", - "format": "int32" - }, - "minor": { - "type": "integer", - "format": "int32" - }, - "revision": { - "type": "integer", - "format": "int32" - } - } - }, "ServerInfoWithHostAddress": { "allOf": [ { @@ -251,6 +220,34 @@ } } }, + "AppVersion": { + "type": "object", + "additionalProperties": false, + "required": [ + "build", + "major", + "minor", + "revision" + ], + "properties": { + "build": { + "type": "integer", + "format": "int32" + }, + "major": { + "type": "integer", + "format": "int32" + }, + "minor": { + "type": "integer", + "format": "int32" + }, + "revision": { + "type": "integer", + "format": "int32" + } + } + }, "PlayerInfo": { "type": "object", "additionalProperties": false, @@ -283,6 +280,39 @@ "minLength": 1 } } + }, + "DiscordStatus": { + "type": "object", + "additionalProperties": false, + "properties": { + "discordUri": { + "type": "string", + "nullable": true + } + } + }, + "VersionInfo": { + "type": "object", + "additionalProperties": false, + "required": [ + "appName", + "version", + "installerUri" + ], + "properties": { + "appName": { + "type": "string", + "minLength": 1 + }, + "version": { + "$ref": "#/components/schemas/AppVersion" + }, + "installerUri": { + "type": "string", + "format": "uri", + "minLength": 1 + } + } } } }