diff --git a/Tranga.sln.DotSettings b/Tranga.sln.DotSettings index 672ec3b..e47766a 100644 --- a/Tranga.sln.DotSettings +++ b/Tranga.sln.DotSettings @@ -9,5 +9,6 @@ True True True + True True True \ No newline at end of file diff --git a/Tranga/NotificationConnectors/NotificationConnector.cs b/Tranga/NotificationConnectors/NotificationConnector.cs index c497657..51b9469 100644 --- a/Tranga/NotificationConnectors/NotificationConnector.cs +++ b/Tranga/NotificationConnectors/NotificationConnector.cs @@ -10,7 +10,7 @@ public abstract class NotificationConnector : GlobalBase this.notificationConnectorType = notificationConnectorType; } - public enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1 } + public enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1, Ntfy = 2 } public abstract void SendNotification(string title, string notificationText); } \ No newline at end of file diff --git a/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs b/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs index 5214183..c5963c2 100644 --- a/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs +++ b/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs @@ -21,11 +21,15 @@ public class NotificationManagerJsonConverter : JsonConverter JsonSerializer serializer) { JObject jo = JObject.Load(reader); - if (jo["notificationConnectorType"]!.Value() == (byte)NotificationConnector.NotificationConnectorType.Gotify) - return new Gotify(this._clone, jo.GetValue("endpoint")!.Value()!, jo.GetValue("appToken")!.Value()!); - else if (jo["notificationConnectorType"]!.Value() == - (byte)NotificationConnector.NotificationConnectorType.LunaSea) - return new LunaSea(this._clone, jo.GetValue("id")!.Value()!); + switch (jo["notificationConnectorType"]!.Value()) + { + case (byte)NotificationConnector.NotificationConnectorType.Gotify: + return new Gotify(this._clone, jo.GetValue("endpoint")!.Value()!, jo.GetValue("appToken")!.Value()!); + case (byte)NotificationConnector.NotificationConnectorType.LunaSea: + return new LunaSea(this._clone, jo.GetValue("id")!.Value()!); + case (byte)NotificationConnector.NotificationConnectorType.Ntfy: + return new Ntfy(this._clone, jo.GetValue("endpoint")!.Value()!, jo.GetValue("auth")!.Value()!); + } throw new Exception(); } diff --git a/Tranga/NotificationConnectors/Ntfy.cs b/Tranga/NotificationConnectors/Ntfy.cs new file mode 100644 index 0000000..a7fed50 --- /dev/null +++ b/Tranga/NotificationConnectors/Ntfy.cs @@ -0,0 +1,58 @@ +using System.Text; +using Newtonsoft.Json; + +namespace Tranga.NotificationConnectors; + +public class Ntfy : NotificationConnector +{ + // ReSharper disable once MemberCanBePrivate.Global + public string endpoint { get; init; } + private string auth { get; init; } + private const string Topic = "tranga"; + private readonly HttpClient _client = new(); + + [JsonConstructor] + public Ntfy(GlobalBase clone, string endpoint, string auth) : base(clone, NotificationConnectorType.Ntfy) + { + if (!baseUrlRex.IsMatch(endpoint)) + throw new ArgumentException("endpoint does not match pattern"); + this.endpoint = endpoint; + this.auth = auth; + } + + public override string ToString() + { + return $"Ntfy {endpoint} {Topic}"; + } + + public override void SendNotification(string title, string notificationText) + { + Log($"Sending notification: {title} - {notificationText}"); + MessageData message = new(title, notificationText); + HttpRequestMessage request = new(HttpMethod.Post, $"{this.endpoint}?auth={this.auth}"); + request.Content = new StringContent(JsonConvert.SerializeObject(message, Formatting.None), Encoding.UTF8, "application/json"); + HttpResponseMessage response = _client.Send(request); + if (!response.IsSuccessStatusCode) + { + StreamReader sr = new (response.Content.ReadAsStream()); + Log($"{response.StatusCode}: {sr.ReadToEnd()}"); + } + } + + private class MessageData + { + // ReSharper disable UnusedAutoPropertyAccessor.Local + public string topic { get; } + public string title { get; } + public string message { get; } + public int priority { get; } + + public MessageData(string title, string message) + { + this.topic = Topic; + this.title = title; + this.message = message; + this.priority = 3; + } + } +} \ No newline at end of file diff --git a/Tranga/Server.cs b/Tranga/Server.cs index 7ba6122..e2c2e1d 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -362,10 +362,7 @@ public class Server : GlobalBase } AddNotificationConnector(new Gotify(this, gotifyUrl, gotifyAppToken)); SendResponse(HttpStatusCode.Accepted, response); - break; - } - - if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea) + }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea) { if (!requestVariables.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook)) { @@ -374,7 +371,20 @@ public class Server : GlobalBase } AddNotificationConnector(new LunaSea(this, lunaseaWebhook)); SendResponse(HttpStatusCode.Accepted, response); - break; + }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy) + { + if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) || + !requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth)) + { + SendResponse(HttpStatusCode.BadRequest, response); + break; + } + AddNotificationConnector(new Ntfy(this, ntfyUrl, ntfyAuth)); + SendResponse(HttpStatusCode.Accepted, response); + } + else + { + SendResponse(HttpStatusCode.BadRequest, response); } break; case "LibraryConnectors/Update":