From c3709096194632044f00e7b1c25388ac9c61228b Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 1 Feb 2018 16:31:49 +0000 Subject: [PATCH] !wip --- src/Ombi.Api.Notifications/IOneSignalApi.cs | 11 + .../Models/OneSignalNotificationBody.cs | 21 ++ .../Models/OneSignalNotificationResponse.cs | 9 + .../Ombi.Api.Notifications.csproj | 11 + src/Ombi.Api.Notifications/OneSignalApi.cs | 48 ++++ src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Ombi.DependencyInjection.csproj | 1 + .../Agents/MobileNotification.cs | 206 ++++++++++++++++++ .../Ombi.Notifications.csproj | 1 + .../MobileNotificationSettings.cs | 7 + src/Ombi.Store/Context/OmbiContext.cs | 10 + .../Entities/ApplicationConfiguration.cs | 3 +- src/Ombi.sln | 11 +- 13 files changed, 338 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Api.Notifications/IOneSignalApi.cs create mode 100644 src/Ombi.Api.Notifications/Models/OneSignalNotificationBody.cs create mode 100644 src/Ombi.Api.Notifications/Models/OneSignalNotificationResponse.cs create mode 100644 src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj create mode 100644 src/Ombi.Api.Notifications/OneSignalApi.cs create mode 100644 src/Ombi.Notifications/Agents/MobileNotification.cs create mode 100644 src/Ombi.Settings/Settings/Models/Notifications/MobileNotificationSettings.cs diff --git a/src/Ombi.Api.Notifications/IOneSignalApi.cs b/src/Ombi.Api.Notifications/IOneSignalApi.cs new file mode 100644 index 000000000..2e3ef106e --- /dev/null +++ b/src/Ombi.Api.Notifications/IOneSignalApi.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Notifications.Models; + +namespace Ombi.Api.Notifications +{ + public interface IOneSignalApi + { + Task PushNotification(List playerIds, string message); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Notifications/Models/OneSignalNotificationBody.cs b/src/Ombi.Api.Notifications/Models/OneSignalNotificationBody.cs new file mode 100644 index 000000000..6c024fa67 --- /dev/null +++ b/src/Ombi.Api.Notifications/Models/OneSignalNotificationBody.cs @@ -0,0 +1,21 @@ +namespace Ombi.Api.Notifications.Models +{ + public class OneSignalNotificationBody + { + public string app_id { get; set; } + public string[] include_player_ids { get; set; } + public Data data { get; set; } + public Contents contents { get; set; } + } + + public class Data + { + public string foo { get; set; } + } + + public class Contents + { + public string en { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.Notifications/Models/OneSignalNotificationResponse.cs b/src/Ombi.Api.Notifications/Models/OneSignalNotificationResponse.cs new file mode 100644 index 000000000..5dab6db55 --- /dev/null +++ b/src/Ombi.Api.Notifications/Models/OneSignalNotificationResponse.cs @@ -0,0 +1,9 @@ +namespace Ombi.Api.Notifications.Models +{ + public class OneSignalNotificationResponse + { + public string id { get; set; } + public int recipients { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj new file mode 100644 index 000000000..a3651df3c --- /dev/null +++ b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/Ombi.Api.Notifications/OneSignalApi.cs b/src/Ombi.Api.Notifications/OneSignalApi.cs new file mode 100644 index 000000000..d4760bb09 --- /dev/null +++ b/src/Ombi.Api.Notifications/OneSignalApi.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Ombi.Api.Notifications.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Api.Notifications +{ + public class OneSignalApi : IOneSignalApi + { + public OneSignalApi(IApi api, IApplicationConfigRepository repo) + { + _api = api; + _appConfig = repo; + } + + private readonly IApi _api; + private readonly IApplicationConfigRepository _appConfig; + private const string ApiUrl = "https://onesignal.com/api/v1/notifications"; + + public async Task PushNotification(List playerIds, string message) + { + if (!playerIds.Any()) + { + return null; + } + var id = await _appConfig.Get(ConfigurationTypes.Notification); + var request = new Request(string.Empty, ApiUrl, HttpMethod.Post); + + var body = new OneSignalNotificationBody + { + app_id = id.Value, + contents = new Contents + { + en = message + }, + include_player_ids = playerIds.ToArray() + }; + + request.AddJsonBody(body); + + var result = await _api.Request(request); + return result; + } + } +} \ No newline at end of file diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 619d18be1..86d6da800 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -33,6 +33,7 @@ using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; using Ombi.Api.Mattermost; +using Ombi.Api.Notifications; using Ombi.Api.Pushbullet; using Ombi.Api.Pushover; using Ombi.Api.Service; @@ -110,6 +111,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 8a05580a6..060287c17 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs new file mode 100644 index 000000000..130e1c668 --- /dev/null +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Discord; +using Ombi.Api.Discord.Models; +using Ombi.Api.Notifications; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Interfaces; +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 MobileNotification : BaseNotification + { + public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s) : base(sn, r, m, t, s) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "DiscordNotification"; + + private IOneSignalApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(MobileNotificationSettings settings) + { + + return false; + } + + protected override async Task NewRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.NewRequest, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task NewIssue(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.Issue, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task IssueResolved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.IssueResolved, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, MobileNotificationSettings settings) + { + var user = string.Empty; + var title = string.Empty; + var image = string.Empty; + if (model.RequestType == RequestType.Movie) + { + user = MovieRequest.RequestedUser.UserAlias; + title = MovieRequest.Title; + image = MovieRequest.PosterPath; + } + else + { + user = TvRequest.RequestedUser.UserAlias; + title = TvRequest.ParentRequest.Title; + image = TvRequest.ParentRequest.PosterPath; + } + var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; + var notification = new NotificationMessage + { + Message = message + }; + notification.Other.Add("image", image); + await Send(notification, settings); + } + + protected override async Task RequestDeclined(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestDeclined, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task RequestApproved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestApproved, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task AvailableRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestAvailable, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } + + protected override async Task Send(NotificationMessage model, MobileNotificationSettings settings) + { + try + { + var discordBody = new DiscordWebhookBody + { + content = model.Message, + //username = settings.Username, + }; + + string image; + if (model.Other.TryGetValue("image", out image)) + { + discordBody.embeds = new List + { + new DiscordEmbeds + { + image = new DiscordImage + { + url = image + } + } + }; + } + + //await Api.SendMessage(discordBody, settings.WebHookId, settings.Token); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.DiscordNotification, e, "Failed to send Discord Notification"); + } + } + + protected override async Task Test(NotificationOptions model, MobileNotificationSettings 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); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index f415045d6..ccdb29e65 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/Notifications/MobileNotificationSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/MobileNotificationSettings.cs new file mode 100644 index 000000000..13864f05c --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/MobileNotificationSettings.cs @@ -0,0 +1,7 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class MobileNotificationSettings : Settings + { + + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 8988fe106..d18d5865f 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -99,6 +99,16 @@ namespace Ombi.Store.Context }); SaveChanges(); } + var notification = ApplicationConfigurations.FirstOrDefault(x => x.Type != ConfigurationTypes.Notification); + if (notification == null) + { + ApplicationConfigurations.Add(new ApplicationConfiguration + { + Type = ConfigurationTypes.Notification, + Value = "4f0260c4-9c3d-41ab-8d68-27cb5a593f0e" + }); + SaveChanges(); + } // VACUUM; Database.ExecuteSqlCommand("VACUUM;"); diff --git a/src/Ombi.Store/Entities/ApplicationConfiguration.cs b/src/Ombi.Store/Entities/ApplicationConfiguration.cs index d9cd5d460..1499ca34f 100644 --- a/src/Ombi.Store/Entities/ApplicationConfiguration.cs +++ b/src/Ombi.Store/Entities/ApplicationConfiguration.cs @@ -15,6 +15,7 @@ namespace Ombi.Store.Entities // 2 was used for Port before the beta FanartTv = 3, TheMovieDb = 4, - StoragePath = 5 + StoragePath = 5, + Notification = 6, } } \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index 494bb6329..ab9f8550c 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2009 +VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}" EndProject @@ -90,7 +90,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Telegram", "Ombi.A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Github", "Ombi.Api.Github\Ombi.Api.Github.csproj", "{55866DEE-46D1-4AF7-B1A2-62F6190C8EC7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.SickRage", "Ombi.Api.SickRage\Ombi.Api.SickRage.csproj", "{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.SickRage", "Ombi.Api.SickRage\Ombi.Api.SickRage.csproj", "{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Notifications", "Ombi.Api.Notifications\Ombi.Api.Notifications.csproj", "{10D1FE9D-9124-42B7-B1E1-CEB99B832618}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -238,6 +240,10 @@ Global {94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Debug|Any CPU.Build.0 = Debug|Any CPU {94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU {94C9A366-2595-45EA-AABB-8E4A2E90EC5B}.Release|Any CPU.Build.0 = Release|Any CPU + {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -272,6 +278,7 @@ Global {CB9DD209-8E09-4E01-983E-C77C89592D36} = {9293CA11-360A-4C20-A674-B9E794431BF5} {55866DEE-46D1-4AF7-B1A2-62F6190C8EC7} = {9293CA11-360A-4C20-A674-B9E794431BF5} {94C9A366-2595-45EA-AABB-8E4A2E90EC5B} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {10D1FE9D-9124-42B7-B1E1-CEB99B832618} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}