mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-06 05:01:13 -07:00
feat: add ntfy
This commit is contained in:
parent
c3284bc70a
commit
43a1b24599
25 changed files with 492 additions and 5 deletions
8
src/Ombi.Api.Ntfy/INtfyApi.cs
Normal file
8
src/Ombi.Api.Ntfy/INtfyApi.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
using Ombi.Api.Ntfy.Models;
|
||||
|
||||
namespace Ombi.Api.Ntfy;
|
||||
|
||||
public interface INtfyApi
|
||||
{
|
||||
Task PushAsync(string endpoint, string authorizationHeader, NtfyNotificationBody body);
|
||||
}
|
21
src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs
Normal file
21
src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs
Normal file
|
@ -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<string> 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; }
|
||||
}
|
26
src/Ombi.Api.Ntfy/NtfyApi.cs
Normal file
26
src/Ombi.Api.Ntfy/NtfyApi.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
13
src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj
Normal file
13
src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj
Normal file
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
23
src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs
Normal file
23
src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Ombi.Settings.Settings.Models.Notifications;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Models.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// The view model for the notification settings page
|
||||
/// </summary>
|
||||
/// <seealso cref="NtfyNotificationViewModel" />
|
||||
public class NtfyNotificationViewModel : NtfySettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the notification templates.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The notification templates.
|
||||
/// </value>
|
||||
public List<NotificationTemplates> NotificationTemplates { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -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<IFanartTvApi, FanartTvApi>();
|
||||
services.AddTransient<IPushoverApi, PushoverApi>();
|
||||
services.AddTransient<IGotifyApi, GotifyApi>();
|
||||
services.AddTransient<INtfyApi, NtfyApi>();
|
||||
services.AddTransient<IWebhookApi, WebhookApi>();
|
||||
services.AddTransient<IMattermostApi, MattermostApi>();
|
||||
services.AddTransient<ICouchPotatoApi, CouchPotatoApi>();
|
||||
|
@ -223,6 +225,7 @@ namespace Ombi.DependencyInjection
|
|||
services.AddTransient<IMattermostNotification, MattermostNotification>();
|
||||
services.AddTransient<IPushoverNotification, PushoverNotification>();
|
||||
services.AddTransient<IGotifyNotification, GotifyNotification>();
|
||||
services.AddTransient<INtfyNotification, NtfyNotification>();
|
||||
services.AddTransient<IWebhookNotification, WebhookNotification>();
|
||||
services.AddTransient<ITelegramNotification, TelegramNotification>();
|
||||
services.AddTransient<ILegacyMobileNotification, LegacyMobileNotification>();
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<ProjectReference Include="..\Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Notifications\Ombi.Api.Notifications.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Ntfy\Ombi.Api.Ntfy.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Pushover\Ombi.Api.Pushover.csproj" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
Mobile = 7,
|
||||
Gotify = 8,
|
||||
Webhook = 9,
|
||||
WhatsApp = 10
|
||||
WhatsApp = 10,
|
||||
Ntfy = 11
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ namespace Ombi.Mapping.Profiles
|
|||
CreateMap<MobileNotificationsViewModel, MobileNotificationSettings>().ReverseMap();
|
||||
CreateMap<NewsletterNotificationViewModel, NewsletterSettings>().ReverseMap();
|
||||
CreateMap<GotifyNotificationViewModel, GotifySettings>().ReverseMap();
|
||||
CreateMap<NtfyNotificationViewModel, NtfySettings>().ReverseMap();
|
||||
CreateMap<WhatsAppSettingsViewModel, WhatsAppSettings>().ReverseMap();
|
||||
CreateMap<TwilioSettingsViewModel, TwilioSettings>().ReverseMap();
|
||||
CreateMap<WebhookNotificationViewModel, WebhookSettings>().ReverseMap();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
namespace Ombi.Notifications.Agents
|
||||
{
|
||||
public interface INtfyNotification : INotification
|
||||
{
|
||||
}
|
||||
}
|
130
src/Ombi.Notifications/Agents/NtfyNotification.cs
Normal file
130
src/Ombi.Notifications/Agents/NtfyNotification.cs
Normal file
|
@ -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<NtfySettings>, INtfyNotification
|
||||
{
|
||||
public NtfyNotification(INtfyApi api, ISettingsService<NtfySettings> sn, ILogger<NtfyNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music,
|
||||
IRepository<UserNotificationPreferences> userPref, UserManager<OmbiUser> 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<NtfyNotification> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
<ProjectReference Include="..\Ombi.Api.CloudService\Ombi.Api.CloudService.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Gotify\Ombi.Api.Gotify.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Ntfy\Ombi.Api.Ntfy.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Webhook\Ombi.Api.Webhook.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Notifications\Ombi.Api.Notifications.csproj" />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<boolean>(`${this.url}gotify`, JSON.stringify(settings), { headers: this.headers });
|
||||
}
|
||||
|
||||
public ntfyTest(settings: INtfyNotificationSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}ntfy`, JSON.stringify(settings), { headers: this.headers });
|
||||
}
|
||||
|
||||
public webhookTest(settings: IWebhookNotificationSettings): Observable<boolean> {
|
||||
return this.http.post<boolean>(`${this.url}webhook`, JSON.stringify(settings), { headers: this.headers });
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
IEmbySettings,
|
||||
IJellyfinSettings,
|
||||
IGotifyNotificationSettings,
|
||||
INtfyNotificationSettings,
|
||||
IIssueSettings,
|
||||
IJobSettings,
|
||||
IJobSettingsViewModel,
|
||||
|
@ -204,6 +205,14 @@ export class SettingsService extends ServiceHelpers {
|
|||
.post<boolean>(`${this.url}/notifications/gotify`, JSON.stringify(settings), { headers: this.headers });
|
||||
}
|
||||
|
||||
public getNtfyNotificationSettings(): Observable<INtfyNotificationSettings> {
|
||||
return this.http.get<INtfyNotificationSettings>(`${this.url}/notifications/ntfy`, { headers: this.headers });
|
||||
}
|
||||
public saveNtfyNotificationSettings(settings: INtfyNotificationSettings): Observable<boolean> {
|
||||
return this.http
|
||||
.post<boolean>(`${this.url}/notifications/ntfy`, JSON.stringify(settings), { headers: this.headers });
|
||||
}
|
||||
|
||||
public getWebhookNotificationSettings(): Observable<IWebhookNotificationSettings> {
|
||||
return this.http.get<IWebhookNotificationSettings>(`${this.url}/notifications/webhook`, { headers: this.headers });
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
<settings-menu></settings-menu>
|
||||
<div *ngIf="form" class="small-middle-container">
|
||||
<fieldset>
|
||||
<legend>Ntfy Notifications</legend>
|
||||
<div class="col-md-6">
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="enable" formControlName="enabled">
|
||||
<label for="enable">Enabled</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="baseUrl" class="control-label">Base URL</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="baseUrl" name="baseUrl" [ngClass]="{'form-error': form.get('baseUrl').hasError('required')}" formControlName="baseUrl" pTooltip="Enter the URL of your ntfy server.">
|
||||
<small *ngIf="form.get('baseUrl').hasError('required')" class="error-text">The Base URL is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="authorizationHeader" class="control-label">Authorization Header</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="authorizationHeader" name="authorizationHeader" [ngClass]="{'form-error': form.get('authorizationHeader').hasError('required')}" formControlName="authorizationHeader" pTooltip="Enter your Authorization header from Ntfy.">
|
||||
<small *ngIf="form.get('authorizationHeader').hasError('required')" class="error-text">The Authorization Header is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="topic" class="control-label">Topic</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="topic" name="topic" [ngClass]="{'form-error': form.get('topic').hasError('required')}" formControlName="topic" pTooltip="Enter your topic from Ntfy.">
|
||||
<small *ngIf="form.get('topic').hasError('required')" class="error-text">The Topic is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="priority" class="control-label">Priority</label>
|
||||
<div>
|
||||
<select class="form-control form-control-custom " id="priority" name="priority" formControlName="priority" pTooltip="The priority you want your ntfy notifications sent as.">
|
||||
<option value="4">Normal</option>
|
||||
<option value="8">High</option>
|
||||
<option value="2">Low</option>
|
||||
<option value="0">Lowest</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button [disabled]="form.invalid" mat-raised-button type="button" (click)="test(form)" class="btn btn-primary-outline">
|
||||
Test
|
||||
<div id="spinner"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button [disabled]="form.invalid" mat-raised-button type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-6">
|
||||
<notification-templates [templates]="templates" [showSubject]="false"></notification-templates>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
|
@ -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 = <INtfyNotificationSettings> 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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<button mat-menu-item [routerLink]="['/Settings/Mattermost']"><i class="far fa-comments icon-spacing"></i> Mattermost</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Telegram']"><i class="fab fa-telegram icon-spacing"></i> Telegram</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Gotify']"><i class="fas fa-comments icon-spacing"></i> Gotify</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Ntfy']"><i class="fas fa-comments icon-spacing"></i> Ntfy</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Twilio']"><i class="fas fa-sms icon-spacing"></i> Twilio</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Webhook']"><i class="fas fa-sync icon-spacing"></i> Webhook</button>
|
||||
</mat-menu>
|
||||
|
|
|
@ -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<TesterController> 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; }
|
||||
|
@ -199,6 +201,31 @@ namespace Ombi.Controllers.V1.External
|
|||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a test message to Ntfy using the provided settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <returns></returns>
|
||||
[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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a test message to configured webhook using the provided settings
|
||||
/// </summary>
|
||||
|
|
|
@ -1141,6 +1141,40 @@ namespace Ombi.Controllers.V1
|
|||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the ntfy notification settings.
|
||||
/// </summary>
|
||||
/// <param name="model">The model.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("notifications/ntfy")]
|
||||
public async Task<bool> NtfyNotificationSettings([FromBody] NtfyNotificationViewModel model)
|
||||
{
|
||||
// Save the email settings
|
||||
var settings = Mapper.Map<NtfySettings>(model);
|
||||
var result = await Save(settings);
|
||||
|
||||
// Save the templates
|
||||
await TemplateRepository.UpdateRange(model.NotificationTemplates);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ntfy Notification Settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("notifications/ntfy")]
|
||||
public async Task<NtfyNotificationViewModel> NtfyNotificationSettings()
|
||||
{
|
||||
var settings = await Get<NtfySettings>();
|
||||
var model = Mapper.Map<NtfyNotificationViewModel>(settings);
|
||||
|
||||
// Lookup to see if we have any templates saved
|
||||
model.NotificationTemplates = BuildTemplates(NotificationAgent.Ntfy);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the webhook notification settings.
|
||||
/// </summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue