From 43a1b245996abc343b29a426f5824562a44c6367 Mon Sep 17 00:00:00 2001 From: gaetansnl Date: Wed, 27 Jul 2022 09:08:33 +0200 Subject: [PATCH] feat: add ntfy --- src/Ombi.Api.Ntfy/INtfyApi.cs | 8 ++ .../Models/NtfyNotificationBody.cs | 21 +++ src/Ombi.Api.Ntfy/NtfyApi.cs | 26 ++++ src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj | 13 ++ .../Models/UI/NtfyNotificationViewModel.cs | 23 ++++ src/Ombi.DependencyInjection/IocExtensions.cs | 3 + .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/LoggingEvents.cs | 1 + src/Ombi.Helpers/NotificationAgent.cs | 3 +- src/Ombi.Mapping/Profiles/SettingsProfile.cs | 1 + .../NotificationServiceTests.cs | 4 +- .../Agents/Interfaces/INtfyNotification.cs | 6 + .../Agents/NtfyNotification.cs | 130 ++++++++++++++++++ .../Ombi.Notifications.csproj | 1 + .../Models/Notifications/NtfySettings.cs | 11 ++ src/Ombi.sln | 9 ++ .../app/interfaces/INotificationSettings.ts | 11 +- .../services/applications/tester.service.ts | 5 + .../src/app/services/settings.service.ts | 9 ++ .../notifications/ntfy.component.html | 74 ++++++++++ .../settings/notifications/ntfy.component.ts | 70 ++++++++++ .../src/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + .../V1/External/TesterController.cs | 29 +++- src/Ombi/Controllers/V1/SettingsController.cs | 34 +++++ 25 files changed, 492 insertions(+), 5 deletions(-) create mode 100644 src/Ombi.Api.Ntfy/INtfyApi.cs create mode 100644 src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs create mode 100644 src/Ombi.Api.Ntfy/NtfyApi.cs create mode 100644 src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj create mode 100644 src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs create mode 100644 src/Ombi.Notifications/Agents/Interfaces/INtfyNotification.cs create mode 100644 src/Ombi.Notifications/Agents/NtfyNotification.cs create mode 100644 src/Ombi.Settings/Settings/Models/Notifications/NtfySettings.cs create mode 100644 src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.html create mode 100644 src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.ts diff --git a/src/Ombi.Api.Ntfy/INtfyApi.cs b/src/Ombi.Api.Ntfy/INtfyApi.cs new file mode 100644 index 000000000..783a7b4b3 --- /dev/null +++ b/src/Ombi.Api.Ntfy/INtfyApi.cs @@ -0,0 +1,8 @@ +using Ombi.Api.Ntfy.Models; + +namespace Ombi.Api.Ntfy; + +public interface INtfyApi +{ + Task PushAsync(string endpoint, string authorizationHeader, NtfyNotificationBody body); +} \ No newline at end of file diff --git a/src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs b/src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs new file mode 100644 index 000000000..ba4442d95 --- /dev/null +++ b/src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace Ombi.Api.Ntfy.Models; + +public class NtfyNotificationBody +{ + [JsonConstructor] + public NtfyNotificationBody() + { + } + + public string topic { get; set; } + public string message { get; set; } + public string title { get; set; } + public List tags { get; set; } + public sbyte priority { get; set; } + public string click { get; set; } + public string attach { get; set; } + public string filename { get; set; } + public string delay { get; set; } +} \ No newline at end of file diff --git a/src/Ombi.Api.Ntfy/NtfyApi.cs b/src/Ombi.Api.Ntfy/NtfyApi.cs new file mode 100644 index 000000000..f72c9ff8f --- /dev/null +++ b/src/Ombi.Api.Ntfy/NtfyApi.cs @@ -0,0 +1,26 @@ +using Ombi.Api.Ntfy.Models; + +namespace Ombi.Api.Ntfy; + +public class NtfyApi: INtfyApi +{ + public NtfyApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + + public async Task PushAsync(string endpoint, string authorizationHeader, NtfyNotificationBody body) + { + var request = new Request("/", endpoint, HttpMethod.Post); + if(!String.IsNullOrEmpty(authorizationHeader)) request.AddHeader("Authorization", authorizationHeader); + request.ApplicationJsonContentType(); + request.AddJsonBody(body); + + Console.WriteLine(endpoint); + Console.WriteLine(request.JsonBody); + + await _api.Request(request); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj b/src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj new file mode 100644 index 000000000..7a95484c6 --- /dev/null +++ b/src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs b/src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs new file mode 100644 index 000000000..3b4172563 --- /dev/null +++ b/src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs @@ -0,0 +1,23 @@ + +using System.Collections.Generic; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + /// + /// The view model for the notification settings page + /// + /// + public class NtfyNotificationViewModel : NtfySettings + { + /// + /// Gets or sets the notification templates. + /// + /// + /// The notification templates. + /// + public List NotificationTemplates { get; set; } + + } +} diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 691aca237..5ec729daf 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -69,6 +69,7 @@ using Ombi.Api.CloudService; using Ombi.Api.RottenTomatoes; using System.Net.Http; using Microsoft.Extensions.Logging; +using Ombi.Api.Ntfy; using Ombi.Core.Services; using Ombi.Core.Helpers; @@ -159,6 +160,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -223,6 +225,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 93b839c07..547f9e364 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -30,6 +30,7 @@ + diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index ed6a7bc2a..f2e125a97 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -37,6 +37,7 @@ namespace Ombi.Helpers public static EventId GotifyNotification => new EventId(4007); public static EventId WhatsApp => new EventId(4008); public static EventId WebhookNotification => new EventId(4009); + public static EventId NtfyNotification => new EventId(4010); public static EventId TvSender => new EventId(5000); public static EventId SonarrSender => new EventId(5001); diff --git a/src/Ombi.Helpers/NotificationAgent.cs b/src/Ombi.Helpers/NotificationAgent.cs index 9b5cc93fc..ab2da9f27 100644 --- a/src/Ombi.Helpers/NotificationAgent.cs +++ b/src/Ombi.Helpers/NotificationAgent.cs @@ -12,6 +12,7 @@ Mobile = 7, Gotify = 8, Webhook = 9, - WhatsApp = 10 + WhatsApp = 10, + Ntfy = 11 } } \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs index 3c27fff7e..78cf0308a 100644 --- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs +++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs @@ -20,6 +20,7 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); diff --git a/src/Ombi.Notifications.Tests/NotificationServiceTests.cs b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs index fedd7707e..d70fbf2e1 100644 --- a/src/Ombi.Notifications.Tests/NotificationServiceTests.cs +++ b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs @@ -25,8 +25,8 @@ namespace Ombi.Notifications.Tests [Test] public void PopulateAgentsTests() { - Assert.That(_subject.Agents, Has.Count.EqualTo(12)); - Assert.That(_subject.Agents.DistinctBy(x => x.NotificationName).ToList(), Has.Count.EqualTo(12)); + Assert.That(_subject.Agents, Has.Count.EqualTo(13)); + Assert.That(_subject.Agents.DistinctBy(x => x.NotificationName).ToList(), Has.Count.EqualTo(13)); } } diff --git a/src/Ombi.Notifications/Agents/Interfaces/INtfyNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/INtfyNotification.cs new file mode 100644 index 000000000..603282f11 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/INtfyNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface INtfyNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/NtfyNotification.cs b/src/Ombi.Notifications/Agents/NtfyNotification.cs new file mode 100644 index 000000000..32ede7134 --- /dev/null +++ b/src/Ombi.Notifications/Agents/NtfyNotification.cs @@ -0,0 +1,130 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using Ombi.Api.Ntfy; +using Ombi.Api.Ntfy; +using Ombi.Api.Ntfy.Models; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class NtfyNotification : BaseNotification, INtfyNotification + { + public NtfyNotification(INtfyApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "NtfyNotification"; + + private INtfyApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(NtfySettings settings) + { + return settings.Enabled && !string.IsNullOrEmpty(settings.BaseUrl); + } + + protected override async Task NewRequest(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + + protected override async Task NewIssue(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, NtfySettings settings) + { + try + { + await Api.PushAsync(settings.BaseUrl, settings.AuthorizationHeader, new NtfyNotificationBody() + { + topic = settings.Topic, // To change + title = model.Subject, + message = model.Message, + priority = settings.Priority + }); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.NtfyNotification, e, "Failed to send Ntfy notification"); + } + } + + protected override async Task Test(NotificationOptions model, NtfySettings settings) + { + var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + var notification = new NotificationMessage + { + Message = message, + }; + await Send(notification, settings); + } + + private async Task Run(NotificationOptions model, NtfySettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Ntfy, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Ntfy}"); + return; + } + + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + await Send(notification, settings); + } + + protected override async Task PartiallyAvailable(NotificationOptions model, NtfySettings settings) + { + await Run(model, settings, NotificationType.PartiallyAvailable); + } + } +} diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 41fd3ae17..7636255f0 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/Notifications/NtfySettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/NtfySettings.cs new file mode 100644 index 000000000..d2af4a56f --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/NtfySettings.cs @@ -0,0 +1,11 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class NtfySettings : Settings + { + public bool Enabled { get; set; } + public string BaseUrl { get; set; } + public string AuthorizationHeader { get; set; } + public string Topic { get; set; } + public sbyte Priority { get; set; } = 4; + } +} \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index a92df055e..1d4f58c8d 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -128,6 +128,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.I18n", "Ombi.I18n\Ombi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MediaServer", "Ombi.Api.MediaServer\Ombi.Api.MediaServer.csproj", "{AFC0BA9B-E38D-479F-825A-2F94EE4D6120}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Ntfy", "Ombi.Api.Ntfy\Ombi.Api.Ntfy.csproj", "{8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -447,6 +449,12 @@ Global {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.Build.0 = Release|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.NonUiBuild|Any CPU.ActiveCfg = Debug|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.NonUiBuild|Any CPU.Build.0 = Debug|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -496,6 +504,7 @@ Global {5DE40A66-B369-469E-8626-ECE23D9D8034} = {9293CA11-360A-4C20-A674-B9E794431BF5} {8F19C701-7881-4BC7-8BBA-B068A6B954AD} = {9293CA11-360A-4C20-A674-B9E794431BF5} {AFC0BA9B-E38D-479F-825A-2F94EE4D6120} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {8E9AD285-C322-45CA-8D7B-6FE4E8E5D580} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts index 460a970fe..ba71cfb4a 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts @@ -35,7 +35,8 @@ export enum NotificationAgent { Mattermost = 6, Mobile = 7, Gotify = 8, - WhatsApp = 9 + WhatsApp = 9, + Ntfy = 10 } export enum NotificationType { @@ -120,6 +121,14 @@ export interface IGotifyNotificationSettings extends INotificationSettings { priority: number; } +export interface INtfyNotificationSettings extends INotificationSettings { + notificationTemplates: INotificationTemplates[]; + baseUrl: string; + authorizationHeader: string; + topic: string; + priority: number; +} + export interface IWebhookNotificationSettings extends INotificationSettings { webhookUrl: string; applicationToken: string; diff --git a/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts index 9209cf84f..b174e940d 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts @@ -13,6 +13,7 @@ import { IEmbyServer, IJellyfinServer, IGotifyNotificationSettings, + INtfyNotificationSettings, ILidarrSettings, IMattermostNotifcationSettings, IMobileNotificationTestSettings, @@ -52,6 +53,10 @@ export class TesterService extends ServiceHelpers { return this.http.post(`${this.url}gotify`, JSON.stringify(settings), { headers: this.headers }); } + public ntfyTest(settings: INtfyNotificationSettings): Observable { + return this.http.post(`${this.url}ntfy`, JSON.stringify(settings), { headers: this.headers }); + } + public webhookTest(settings: IWebhookNotificationSettings): Observable { return this.http.post(`${this.url}webhook`, JSON.stringify(settings), { headers: this.headers }); } diff --git a/src/Ombi/ClientApp/src/app/services/settings.service.ts b/src/Ombi/ClientApp/src/app/services/settings.service.ts index 4758c8382..ac85f759b 100644 --- a/src/Ombi/ClientApp/src/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/src/app/services/settings.service.ts @@ -16,6 +16,7 @@ import { IEmbySettings, IJellyfinSettings, IGotifyNotificationSettings, + INtfyNotificationSettings, IIssueSettings, IJobSettings, IJobSettingsViewModel, @@ -204,6 +205,14 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/gotify`, JSON.stringify(settings), { headers: this.headers }); } + public getNtfyNotificationSettings(): Observable { + return this.http.get(`${this.url}/notifications/ntfy`, { headers: this.headers }); + } + public saveNtfyNotificationSettings(settings: INtfyNotificationSettings): Observable { + return this.http + .post(`${this.url}/notifications/ntfy`, JSON.stringify(settings), { headers: this.headers }); + } + public getWebhookNotificationSettings(): Observable { return this.http.get(`${this.url}/notifications/webhook`, { headers: this.headers }); } diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.html new file mode 100644 index 000000000..4e3f8b36b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.html @@ -0,0 +1,74 @@ + + +
+
+ Ntfy Notifications +
+
+ +
+
+ + +
+
+ +
+ + + + The Base URL is required +
+ +
+ + + + The Authorization Header is required +
+ +
+ + + + The Topic is required +
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ + + +
+
+ +
+
+
+
+ + +
+ +
+
+
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.ts new file mode 100644 index 000000000..19aea4c82 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/ntfy.component.ts @@ -0,0 +1,70 @@ +import { Component, OnInit } from "@angular/core"; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; + +import { INtfyNotificationSettings, INotificationTemplates, NotificationType } from "../../interfaces"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./ntfy.component.html", + styleUrls: ["./notificationtemplate.component.scss"] +}) +export class NtfyComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: UntypedFormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: UntypedFormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getNtfyNotificationSettings().subscribe(x => { + this.templates = x.notificationTemplates; + + this.form = this.fb.group({ + enabled: [x.enabled], + baseUrl: [x.baseUrl, [Validators.required]], + authorizationHeader: [x.authorizationHeader, []], + topic: [x.topic, [Validators.required]], + priority: [x.priority], + }); + }); + } + + public onSubmit(form: UntypedFormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + settings.notificationTemplates = this.templates; + + this.settingsService.saveNtfyNotificationSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Ntfy settings"); + } else { + this.notificationService.success("There was an error when saving the Ntfy settings"); + } + }); + + } + + public test(form: UntypedFormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.ntfyTest(form.value).subscribe(x => { + if (x) { + this.notificationService.success("Successfully sent a Ntfy message"); + } else { + this.notificationService.error("There was an error when sending the Ntfy message. Please check your settings"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/settings.module.ts b/src/Ombi/ClientApp/src/app/settings/settings.module.ts index 144322194..06dfb8a2a 100644 --- a/src/Ombi/ClientApp/src/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/src/app/settings/settings.module.ts @@ -40,6 +40,7 @@ import { EmbyComponent } from "./emby/emby.component"; import { FailedRequestsComponent } from "./failedrequests/failedrequests.component"; import { FeaturesComponent } from "./features/features.component"; import { GotifyComponent } from "./notifications/gotify.component"; +import { NtfyComponent } from "./notifications/ntfy.component"; import { HubService } from "../services/hub.service"; import {InputSwitchModule} from "primeng/inputswitch"; import {InputTextModule} from "primeng/inputtext"; @@ -100,6 +101,7 @@ const routes: Routes = [ { path: "Pushover", component: PushoverComponent, canActivate: [AuthGuard] }, { path: "Pushbullet", component: PushbulletComponent, canActivate: [AuthGuard] }, { path: "Gotify", component: GotifyComponent, canActivate: [AuthGuard] }, + { path: "Ntfy", component: NtfyComponent, canActivate: [AuthGuard] }, { path: "Webhook", component: WebhookComponent, canActivate: [AuthGuard] }, { path: "Mattermost", component: MattermostComponent, canActivate: [AuthGuard] }, { path: "Twilio", component: TwilioComponent, canActivate: [AuthGuard] }, @@ -165,6 +167,7 @@ const routes: Routes = [ MattermostComponent, PushbulletComponent, GotifyComponent, + NtfyComponent, WebhookComponent, UserManagementComponent, UpdateComponent, diff --git a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html index bcbe7bd3a..66e5de9bc 100644 --- a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html @@ -52,6 +52,7 @@ + diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index 6ee0ebe22..37b1e959a 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -48,7 +48,7 @@ namespace Ombi.Controllers.V1.External IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, IPlexApi plex, IEmbyApiFactory emby, IRadarrV3Api radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, - ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification, + ILidarrApi lidarrApi, IGotifyNotification gotifyNotification,INtfyNotification ntfyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification, IJellyfinApi jellyfinApi, IPrincipal user) { Service = service; @@ -71,6 +71,7 @@ namespace Ombi.Controllers.V1.External MobileNotification = mobileNotification; LidarrApi = lidarrApi; GotifyNotification = gotifyNotification; + NtfyNotification = ntfyNotification; WhatsAppApi = whatsAppApi; UserManager = um; WebhookNotification = webhookNotification; @@ -85,6 +86,7 @@ namespace Ombi.Controllers.V1.External private ISlackNotification SlackNotification { get; } private IPushoverNotification PushoverNotification { get; } private IGotifyNotification GotifyNotification { get; } + private INtfyNotification NtfyNotification { get; } private IWebhookNotification WebhookNotification { get; } private IMattermostNotification MattermostNotification { get; } private IPlexApi PlexApi { get; } @@ -198,6 +200,31 @@ namespace Ombi.Controllers.V1.External } } + + + /// + /// Sends a test message to Ntfy using the provided settings + /// + /// The settings. + /// + [HttpPost("ntfy")] + public bool Ntfy([FromBody] NtfySettings settings) + { + try + { + settings.Enabled = true; + NtfyNotification.NotifyAsync( + new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings); + + return true; + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test Ntfy"); + return false; + } + + } /// /// Sends a test message to configured webhook using the provided settings diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index 0892b1dda..3fad57b9d 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -1140,6 +1140,40 @@ namespace Ombi.Controllers.V1 return model; } + + /// + /// Saves the ntfy notification settings. + /// + /// The model. + /// + [HttpPost("notifications/ntfy")] + public async Task NtfyNotificationSettings([FromBody] NtfyNotificationViewModel model) + { + // Save the email settings + var settings = Mapper.Map(model); + var result = await Save(settings); + + // Save the templates + await TemplateRepository.UpdateRange(model.NotificationTemplates); + + return result; + } + + /// + /// Gets the ntfy Notification Settings. + /// + /// + [HttpGet("notifications/ntfy")] + public async Task NtfyNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + // Lookup to see if we have any templates saved + model.NotificationTemplates = BuildTemplates(NotificationAgent.Ntfy); + + return model; + } /// /// Saves the webhook notification settings.