Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ntfy #4703

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Ombi.Api.Ntfy/INtfyApi.cs
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions src/Ombi.Api.Ntfy/Models/NtfyNotificationBody.cs
Original file line number Diff line number Diff line change
@@ -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 changes: 26 additions & 0 deletions src/Ombi.Api.Ntfy/NtfyApi.cs
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/Ombi.Api.Ntfy/Ombi.Api.Ntfy.csproj
Original file line number Diff line number Diff line change
@@ -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 changes: 23 additions & 0 deletions src/Ombi.Core/Models/UI/NtfyNotificationViewModel.cs
Original file line number Diff line number Diff line change
@@ -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; }

}
}
3 changes: 3 additions & 0 deletions src/Ombi.DependencyInjection/IocExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
using Ombi.Api.RottenTomatoes;
using System.Net.Http;
using Microsoft.Extensions.Logging;
using Ombi.Api.Ntfy;
using Ombi.Core.Services;
using Ombi.Core.Helpers;

Expand Down Expand Up @@ -159,6 +160,7 @@ public static void RegisterApi(this IServiceCollection services)
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>();
Expand Down Expand Up @@ -223,6 +225,7 @@ public static void RegisterServices(this IServiceCollection services)
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>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
1 change: 1 addition & 0 deletions src/Ombi.Helpers/LoggingEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class LoggingEvents
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);
Expand Down
3 changes: 2 additions & 1 deletion src/Ombi.Helpers/NotificationAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum NotificationAgent
Mobile = 7,
Gotify = 8,
Webhook = 9,
WhatsApp = 10
WhatsApp = 10,
Ntfy = 11
}
}
1 change: 1 addition & 0 deletions src/Ombi.Mapping/Profiles/SettingsProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public SettingsProfile()
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();
Expand Down
4 changes: 2 additions & 2 deletions src/Ombi.Notifications.Tests/NotificationServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public void Setup()
[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));
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/Ombi.Notifications/Agents/Interfaces/INtfyNotification.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Ombi.Notifications.Agents
{
public interface INtfyNotification : INotification
{
}
}
130 changes: 130 additions & 0 deletions src/Ombi.Notifications/Agents/NtfyNotification.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
1 change: 1 addition & 0 deletions src/Ombi.Notifications/Ombi.Notifications.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
11 changes: 11 additions & 0 deletions src/Ombi.Settings/Settings/Models/Notifications/NtfySettings.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
9 changes: 9 additions & 0 deletions src/Ombi.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down
11 changes: 10 additions & 1 deletion src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export enum NotificationAgent {
Mattermost = 6,
Mobile = 7,
Gotify = 8,
WhatsApp = 9
WhatsApp = 9,
Ntfy = 10
}

export enum NotificationType {
Expand Down Expand Up @@ -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;
Expand Down
Loading