From ae613d848f63eca0844994d6dca1c43513b4ecae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KennethG=C3=B3mez?= Date: Sun, 21 Mar 2021 18:19:00 +0100 Subject: [PATCH] Implement CustomUploadService --- LiveShot.API/Container.cs | 24 ++++- LiveShot.API/Properties/Resources.Designer.cs | 53 +++++++---- .../Properties/Resources.en-US.Designer.cs | 53 +++++++---- LiveShot.API/Properties/Resources.en-US.resx | 6 ++ .../Properties/Resources.es-ES.Designer.cs | 53 +++++++---- LiveShot.API/Properties/Resources.es-ES.resx | 6 ++ LiveShot.API/Properties/Resources.resx | 6 ++ .../Upload/Custom/CustomUploadService.cs | 93 +++++++++++++++++++ .../Exceptions/InvalidUploadTypeException.cs | 12 +++ LiveShot.UI/App.xaml.cs | 2 +- LiveShot.UI/Properties/appsettings.json | 17 +++- 11 files changed, 260 insertions(+), 65 deletions(-) create mode 100644 LiveShot.API/Upload/Custom/CustomUploadService.cs create mode 100644 LiveShot.API/Upload/Exceptions/InvalidUploadTypeException.cs diff --git a/LiveShot.API/Container.cs b/LiveShot.API/Container.cs index 8a278ee..7e64013 100644 --- a/LiveShot.API/Container.cs +++ b/LiveShot.API/Container.cs @@ -2,17 +2,37 @@ using System.Reflection; using LiveShot.API.Drawing; using LiveShot.API.Upload; +using LiveShot.API.Upload.Custom; using LiveShot.API.Upload.Imgur; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace LiveShot.API { public static class Container { - public static IServiceCollection ConfigureAPI(this IServiceCollection services) + public static IServiceCollection ConfigureAPI(this IServiceCollection services, IConfiguration? configuration) { services.AddSingleton(); - services.AddSingleton(); + + if (configuration != null) + { + string? uploadType = configuration["UploadType"]; + + if (uploadType != null && uploadType.ToLower().Equals("imgur")) + { + services.AddSingleton(); + } + else + { + services.AddSingleton(); + } + } + else + { + services.AddSingleton(); + } + services.AddSingleton(); var drawingTools = Assembly diff --git a/LiveShot.API/Properties/Resources.Designer.cs b/LiveShot.API/Properties/Resources.Designer.cs index 2926ecd..ad3dbfa 100644 --- a/LiveShot.API/Properties/Resources.Designer.cs +++ b/LiveShot.API/Properties/Resources.Designer.cs @@ -8,15 +8,10 @@ // //------------------------------------------------------------------------------ -using System.CodeDom.Compiler; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Resources; -using System.Runtime.CompilerServices; - namespace LiveShot.API.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -24,27 +19,27 @@ namespace LiveShot.API.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [DebuggerNonUserCode()] - [CompilerGenerated()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { - private static ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static ResourceManager ResourceManager { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { get { - if (ReferenceEquals(resourceMan, null)) { - ResourceManager temp = new ResourceManager("LiveShot.API.Properties.Resources", typeof(Resources).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LiveShot.API.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -55,8 +50,8 @@ public static ResourceManager ResourceManager { /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static CultureInfo Culture { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -299,5 +294,23 @@ public static string Imgur_InvalidClientIdException { return ResourceManager.GetString("Imgur.InvalidClientIdException", resourceCulture); } } + + /// + /// Looks up a localized string similar to Upload.InvalidUploadType. + /// + public static string Upload_InvalidUpload_Type { + get { + return ResourceManager.GetString("Upload.InvalidUpload.Type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload.Success. + /// + public static string Upload_Success { + get { + return ResourceManager.GetString("Upload.Success", resourceCulture); + } + } } } diff --git a/LiveShot.API/Properties/Resources.en-US.Designer.cs b/LiveShot.API/Properties/Resources.en-US.Designer.cs index b0d5a41..daf1709 100644 --- a/LiveShot.API/Properties/Resources.en-US.Designer.cs +++ b/LiveShot.API/Properties/Resources.en-US.Designer.cs @@ -8,15 +8,10 @@ // //------------------------------------------------------------------------------ -using System.CodeDom.Compiler; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Resources; -using System.Runtime.CompilerServices; - namespace LiveShot.API.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -24,27 +19,27 @@ namespace LiveShot.API.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [DebuggerNonUserCode()] - [CompilerGenerated()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources_en_US { - private static ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources_en_US() { } /// /// Returns the cached ResourceManager instance used by this class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static ResourceManager ResourceManager { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { get { - if (ReferenceEquals(resourceMan, null)) { - ResourceManager temp = new ResourceManager("LiveShot.API.Properties.Resources.en-US", typeof(Resources_en_US).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LiveShot.API.Properties.Resources.en-US", typeof(Resources_en_US).Assembly); resourceMan = temp; } return resourceMan; @@ -55,8 +50,8 @@ public static ResourceManager ResourceManager { /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static CultureInfo Culture { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -298,5 +293,23 @@ public static string Imgur_InvalidClientIdException { return ResourceManager.GetString("Imgur.InvalidClientIdException", resourceCulture); } } + + /// + /// Looks up a localized string similar to Invalid upload type in application configuration. + /// + public static string Upload_InvalidUpload_Type { + get { + return ResourceManager.GetString("Upload.InvalidUpload.Type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Image uploaded successfully. + /// + public static string Upload_Success { + get { + return ResourceManager.GetString("Upload.Success", resourceCulture); + } + } } } diff --git a/LiveShot.API/Properties/Resources.en-US.resx b/LiveShot.API/Properties/Resources.en-US.resx index 6d68d7b..3230de0 100644 --- a/LiveShot.API/Properties/Resources.en-US.resx +++ b/LiveShot.API/Properties/Resources.en-US.resx @@ -96,4 +96,10 @@ Eye dropper + + Image uploaded successfully + + + Invalid upload type in application configuration + \ No newline at end of file diff --git a/LiveShot.API/Properties/Resources.es-ES.Designer.cs b/LiveShot.API/Properties/Resources.es-ES.Designer.cs index f05ef48..91021a9 100644 --- a/LiveShot.API/Properties/Resources.es-ES.Designer.cs +++ b/LiveShot.API/Properties/Resources.es-ES.Designer.cs @@ -8,15 +8,10 @@ // //------------------------------------------------------------------------------ -using System.CodeDom.Compiler; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Resources; -using System.Runtime.CompilerServices; - namespace LiveShot.API.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -24,27 +19,27 @@ namespace LiveShot.API.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [DebuggerNonUserCode()] - [CompilerGenerated()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources_es_ES { - private static ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources_es_ES() { } /// /// Returns the cached ResourceManager instance used by this class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - internal static ResourceManager ResourceManager { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { get { - if (ReferenceEquals(resourceMan, null)) { - ResourceManager temp = new ResourceManager("LiveShot.API.Properties.Resources.es-ES", typeof(Resources_es_ES).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LiveShot.API.Properties.Resources.es-ES", typeof(Resources_es_ES).Assembly); resourceMan = temp; } return resourceMan; @@ -55,8 +50,8 @@ internal static ResourceManager ResourceManager { /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - internal static CultureInfo Culture { + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -298,5 +293,23 @@ internal static string Imgur_InvalidClientIdException { return ResourceManager.GetString("Imgur.InvalidClientIdException", resourceCulture); } } + + /// + /// Looks up a localized string similar to El UploadType de la configuración ee la aplicacion es inválido. + /// + internal static string Upload_InvalidUpload_Type { + get { + return ResourceManager.GetString("Upload.InvalidUpload.Type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Imagen subida exitosamente. + /// + internal static string Upload_Success { + get { + return ResourceManager.GetString("Upload.Success", resourceCulture); + } + } } } diff --git a/LiveShot.API/Properties/Resources.es-ES.resx b/LiveShot.API/Properties/Resources.es-ES.resx index 8b334c9..b98e435 100644 --- a/LiveShot.API/Properties/Resources.es-ES.resx +++ b/LiveShot.API/Properties/Resources.es-ES.resx @@ -96,4 +96,10 @@ Cuentagotas + + Imagen subida exitosamente + + + El UploadType de la configuración ee la aplicacion es inválido + \ No newline at end of file diff --git a/LiveShot.API/Properties/Resources.resx b/LiveShot.API/Properties/Resources.resx index 00e0024..5e6002e 100644 --- a/LiveShot.API/Properties/Resources.resx +++ b/LiveShot.API/Properties/Resources.resx @@ -97,4 +97,10 @@ CaptureScreen.CanvasButtons.Stroke CaptureScreen.CanvasButtons.EyeDropper + + Upload.Success + + + Upload.InvalidUploadType + \ No newline at end of file diff --git a/LiveShot.API/Upload/Custom/CustomUploadService.cs b/LiveShot.API/Upload/Custom/CustomUploadService.cs new file mode 100644 index 0000000..1ea872c --- /dev/null +++ b/LiveShot.API/Upload/Custom/CustomUploadService.cs @@ -0,0 +1,93 @@ +using System; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using System.Web; +using LiveShot.API.Properties; +using LiveShot.API.Upload.Exceptions; +using Microsoft.Extensions.Configuration; + +namespace LiveShot.API.Upload.Custom +{ + public class CustomUploadService : IUploadService + { + private readonly IConfiguration _configuration; + + public CustomUploadService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task Upload(Bitmap bitmap) + { + var webRequest = await CreateWebRequest(bitmap); + + WebResponse response = await webRequest.GetResponseAsync(); + + Stream responseStream = response.GetResponseStream(); + StreamReader responseReader = new(responseStream); + + await responseReader.ReadToEndAsync(); + + return Resources.Upload_Success; + } + + private async Task CreateWebRequest(Bitmap bitmap) + { + string uploadType = _configuration["UploadType"] ?? throw new InvalidUploadTypeException(); + + var uploadConfig = _configuration + .GetSection("UploadTypes") + ?.GetSection(uploadType) ?? throw new InvalidUploadTypeException(); + + string endpoint = uploadConfig["Endpoint"] ?? throw new InvalidUploadTypeException(); + + string uploadRequestString = GetUploadRequestString(uploadConfig, bitmap); + + HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(endpoint); + webRequest.Method = uploadConfig["Method"] ?? "POST"; + + var headers = uploadConfig.GetSection("Headers")?.GetChildren(); + + if (headers != null) + { + foreach (var child in headers) + { + webRequest.Headers.Add(child.Key, child.Value); + } + } + + webRequest.ContentType = uploadConfig["ContentType"] ?? "application/x-www-form-urlencoded"; + webRequest.ServicePoint.Expect100Continue = false; + + await using StreamWriter streamWriter = new(webRequest.GetRequestStream()); + await streamWriter.WriteAsync(uploadRequestString); + + return webRequest; + } + + private static string GetUploadRequestString(IConfiguration uploadConfig, Bitmap bitmap) + { + ImageConverter converter = new(); + byte[] bytes = (byte[]) converter.ConvertTo(bitmap, typeof(byte[])); + + string uploadRequestString = $"{HttpUtility.UrlEncode(uploadConfig["BodyImageKey"] ?? "image")}=" + + Uri.EscapeDataString(Convert.ToBase64String(bytes)); + + var body = uploadConfig.GetSection("Body")?.GetChildren(); + + if (body == null) + return uploadRequestString; + + string[] bodyArray = body + .Select(c => $"{HttpUtility.UrlEncode(c.Key)}={HttpUtility.UrlEncode(c.Value)}") + .ToArray(); + + uploadRequestString += "&" + string.Join("&", bodyArray); + + return uploadRequestString; + } + } +} \ No newline at end of file diff --git a/LiveShot.API/Upload/Exceptions/InvalidUploadTypeException.cs b/LiveShot.API/Upload/Exceptions/InvalidUploadTypeException.cs new file mode 100644 index 0000000..719348a --- /dev/null +++ b/LiveShot.API/Upload/Exceptions/InvalidUploadTypeException.cs @@ -0,0 +1,12 @@ +using System; +using LiveShot.API.Properties; + +namespace LiveShot.API.Upload.Exceptions +{ + public class InvalidUploadTypeException : Exception + { + public InvalidUploadTypeException() : base(Resources.Upload_InvalidUpload_Type) + { + } + } +} \ No newline at end of file diff --git a/LiveShot.UI/App.xaml.cs b/LiveShot.UI/App.xaml.cs index cb6aa51..a49741e 100644 --- a/LiveShot.UI/App.xaml.cs +++ b/LiveShot.UI/App.xaml.cs @@ -25,7 +25,7 @@ protected override void OnStartup(StartupEventArgs e) SetUICulture(); var serviceCollection = new ServiceCollection() - .ConfigureAPI() + .ConfigureAPI(Configuration) .ConfigureUI(); if (Configuration != null) diff --git a/LiveShot.UI/Properties/appsettings.json b/LiveShot.UI/Properties/appsettings.json index 460301a..325b382 100644 --- a/LiveShot.UI/Properties/appsettings.json +++ b/LiveShot.UI/Properties/appsettings.json @@ -1,6 +1,19 @@ { "CultureUI": "en-US", - "Imgur": { - "ClientID": "d4d456ae8b941e7" + "UploadType": "CustomExample", + "UploadTypes": { + "Imgur": { + "ClientID": "d4d456ae8b941e7" + }, + "CustomExample": { + "Endpoint": "https://api.imgur.com/3/image", + "Method": "POST", + "Headers": { + "Authorization": "Client-ID d4d456ae8b941e7" + }, + "ContentType": "application/x-www-form-urlencoded", + "BodyImageKey": "image", + "Body": {} + } } } \ No newline at end of file