diff --git a/README.md b/README.md index 69c7253..df0e885 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# UPDATE 2023-08-29 +I've begun working on a new version of SynoAI from the ground up which has an administrative interface instead of a config based approach. I will also be taking the opportunity to implement a number of requested features that have been requested for a long time. + # SynoAI A Synology Surveillance Station notification system utilising DeepStack AI, inspired by Christopher Adams' [sssAI](https://github.com/Christofo/sssAI) implementation. @@ -188,6 +191,8 @@ The Deepstack API is a free to use AI that can identify objects, faces and more. ### CodeProject.AI-Server +For a full list of supported types see the [CodeProject.AI documentation](https://www.codeproject.com/AI/docs/api/api_reference.html). + ```json "AI": { "Type": "CodeProjectAIServer", @@ -235,7 +240,8 @@ The webhook notification can be used to make web requests (e.g. API calls) eithe "Method": "POST", "Authentication": "Bearer", "Token": "XYZ.123456", - "SendImage": "false" + "SendImage": false, + "AllowInsecureUrl": false } ``` * Url [required]: The URL to send the image to @@ -252,7 +258,8 @@ The webhook notification can be used to make web requests (e.g. API calls) eithe * Bearer * Token [optional]: The token to use when using Basic Authorization * ImageField [optional] (Default: ```image```): The field name of the image in the POST data -* SendImage [optional] (Default: ```true```): The image will be sent to the webhook when the method is POST, PATCH or PUT. +* SendImage [optional] (Default: ```true```): The image will be sent to the webhook when the method is POST, PATCH or PUT +* AllowInsecureUrl [optional] (Default: ```false```): Whether to allow an insecure HTTPS connection to the Webhook. #### Example POST data The following is example data for when ```SendImage``` is ```false``` and ```SynoAIUrl``` is ```"http://192.168.1.2"```. diff --git a/SynoAI/Notifiers/Webhook/Webhook.cs b/SynoAI/Notifiers/Webhook/Webhook.cs index ebe5235..fce9931 100644 --- a/SynoAI/Notifiers/Webhook/Webhook.cs +++ b/SynoAI/Notifiers/Webhook/Webhook.cs @@ -1,5 +1,11 @@ using Newtonsoft.Json; using SynoAI.Models; +using SynoAI.Services; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; using System.Net.Http.Headers; using System.Text; @@ -45,6 +51,10 @@ internal class Webhook : NotifierBase /// content-type of multipart/form-data. /// public bool SendImage { get; set; } + /// + /// Allow insecure URL Access to the API. + /// + public bool AllowInsecureUrl { get; set; } /// /// Sends a notification to the Webhook. @@ -55,7 +65,7 @@ internal class Webhook : NotifierBase public override async Task SendAsync(Camera camera, Notification notification, ILogger logger) { logger.LogInformation($"{camera.Name}: Webhook: Processing"); - using (HttpClient client = new()) + using (HttpClient client = GetHttpClient()) { FileStream fileStream = null; client.DefaultRequestHeaders.Authorization = GetAuthenticationHeader(); @@ -106,26 +116,34 @@ public override async Task SendAsync(Camera camera, Notification notification, I logger.LogInformation($"{camera.Name}: Webhook: Calling {Method}."); HttpResponseMessage response; - switch (Method) + try + { + switch (Method) + { + case "DELETE": + response = await client.DeleteAsync(Url); + break; + case "GET": + response = await client.GetAsync(Url); + break; + case "PATCH": + response = await client.PatchAsync(Url, content); + break; + case "POST": + response = await client.PostAsync(Url, content); + break; + case "PUT": + response = await client.PutAsync(Url, content); + break; + default: + logger.LogError($"{camera.Name}: Webhook: The method type '{Method}' is not supported."); + return; + } + } + catch (Exception ex) { - case "DELETE": - response = await client.DeleteAsync(Url); - break; - case "GET": - response = await client.GetAsync(Url); - break; - case "PATCH": - response = await client.PatchAsync(Url, content); - break; - case "POST": - response = await client.PostAsync(Url, content); - break; - case "PUT": - response = await client.PutAsync(Url, content); - break; - default: - logger.LogError($"{camera.Name}: Webhook: The method type '{Method}' is not supported."); - return; + logger.LogError($"{camera.Name}: Webhook: Unhandled Exception occurred '{ex.Message}'."); + return; } if (response.IsSuccessStatusCode) @@ -145,6 +163,24 @@ public override async Task SendAsync(Camera camera, Notification notification, I } } + /// + /// Gets a object for the Webhook request. + /// + /// A . + private HttpClient GetHttpClient() + { + if (!Config.AllowInsecureUrl) + { + return new(); + } + + HttpClientHandler httpClientHandler = new() + { + ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true + }; + return new(httpClientHandler); + } + /// /// Generates an authentication header for the client. /// diff --git a/SynoAI/Notifiers/Webhook/WebhookFactory.cs b/SynoAI/Notifiers/Webhook/WebhookFactory.cs index 3ae5779..34629c0 100644 --- a/SynoAI/Notifiers/Webhook/WebhookFactory.cs +++ b/SynoAI/Notifiers/Webhook/WebhookFactory.cs @@ -17,15 +17,17 @@ public override INotifier Create(ILogger logger, IConfigurationSection section) string method = section.GetValue("Method", "POST"); bool sendImage = section.GetValue("SendImage", true); bool sendTypes = section.GetValue("SendTypes", false); + bool allowInsecureUrl = section.GetValue("AllowInsecureUrl", false); - Webhook webhook = new Webhook() + Webhook webhook = new() { Url = url, Authentication = authentication, Username = username, Password = password, Token = token, - SendImage = sendImage + SendImage = sendImage, + AllowInsecureUrl = allowInsecureUrl }; if (!string.IsNullOrWhiteSpace(imageField))