From 952db09e28b1e08065e1f3f85a902a2718960baf Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 11 Jan 2020 00:41:55 +0000 Subject: [PATCH] Started on whatsapp --- src/Ombi.Api.Twilio/IWhatsAppApi.cs | 9 ++ src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj | 11 ++ src/Ombi.Api.Twilio/WhatsAppApi.cs | 30 +++++ src/Ombi.Api.Twilio/WhatsAppModel.cs | 9 ++ .../UI/WhatsAppNotificationsViewModel.cs | 21 +++ src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/LoggingEvents.cs | 1 + src/Ombi.Helpers/NotificationAgent.cs | 1 + .../Agents/WhatsAppNotification.cs | 125 ++++++++++++++++++ .../Ombi.Notifications.csproj | 1 + .../Models/Notifications/WhatsAppSettings.cs | 10 ++ src/Ombi.sln | 9 +- src/Ombi/Controllers/V1/SettingsController.cs | 34 +++++ src/Ombi/Ombi.csproj | 1 + src/Ombi/Startup.cs | 3 - 16 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 src/Ombi.Api.Twilio/IWhatsAppApi.cs create mode 100644 src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj create mode 100644 src/Ombi.Api.Twilio/WhatsAppApi.cs create mode 100644 src/Ombi.Api.Twilio/WhatsAppModel.cs create mode 100644 src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs create mode 100644 src/Ombi.Notifications/Agents/WhatsAppNotification.cs create mode 100644 src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs diff --git a/src/Ombi.Api.Twilio/IWhatsAppApi.cs b/src/Ombi.Api.Twilio/IWhatsAppApi.cs new file mode 100644 index 000000000..490aaa8fc --- /dev/null +++ b/src/Ombi.Api.Twilio/IWhatsAppApi.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Api.Twilio +{ + public interface IWhatsAppApi + { + Task SendMessage(WhatsAppModel message, string accountSid, string authToken); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj b/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj new file mode 100644 index 000000000..d55f9680a --- /dev/null +++ b/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/Ombi.Api.Twilio/WhatsAppApi.cs b/src/Ombi.Api.Twilio/WhatsAppApi.cs new file mode 100644 index 000000000..0e5ce4347 --- /dev/null +++ b/src/Ombi.Api.Twilio/WhatsAppApi.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using Twilio; +using Twilio.Rest.Api.V2010.Account; +using Twilio.Types; + +namespace Ombi.Api.Twilio +{ + public class WhatsAppApi : IWhatsAppApi + { + + public async Task SendMessage(WhatsAppModel message, string accountSid, string authToken) + { + // Find your Account Sid and Token at twilio.com/console + // DANGER! This is insecure. See http://twil.io/secure + //const string accountSid = "AC8a1b6ab0d9f351be8210ccc8f7930d27"; + //const string authToken = "f280272092780a770f7cd4fb0beed125"; + + TwilioClient.Init(accountSid, authToken); + + var response =await MessageResource.CreateAsync( + body: message.Message, + from: new PhoneNumber($"whatsapp:{message.From}"), + to: new PhoneNumber($"whatsapp:{message.To}") + ); + + return response.Sid; + } + } +} diff --git a/src/Ombi.Api.Twilio/WhatsAppModel.cs b/src/Ombi.Api.Twilio/WhatsAppModel.cs new file mode 100644 index 000000000..e7f4e5c21 --- /dev/null +++ b/src/Ombi.Api.Twilio/WhatsAppModel.cs @@ -0,0 +1,9 @@ +namespace Ombi.Api.Twilio +{ + public class WhatsAppModel + { + public string Message { get; set; } + public string To { get; set; } + public string From { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs b/src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs new file mode 100644 index 000000000..048ec1dfa --- /dev/null +++ b/src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs @@ -0,0 +1,21 @@ +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 WhatsAppNotificationsViewModel : WhatsAppSettings + { + /// + /// 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 dd7dcd3b8..66e0a05e6 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -64,6 +64,7 @@ using Ombi.Schedule.Processor; using Ombi.Store.Entities; using Quartz.Spi; using Ombi.Api.MusicBrainz; +using Ombi.Api.Twilio; namespace Ombi.DependencyInjection { @@ -147,6 +148,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 59a37d6aa..636e96a3c 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -37,6 +37,7 @@ + diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index 0723800ab..7c4bd73f7 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -33,6 +33,7 @@ namespace Ombi.Helpers public static EventId PushoverNotification => new EventId(4005); public static EventId TelegramNotifcation => new EventId(4006); public static EventId GotifyNotification => new EventId(4007); + public static EventId WhatsApp => new EventId(4008); 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 18f28105a..78fe529c0 100644 --- a/src/Ombi.Helpers/NotificationAgent.cs +++ b/src/Ombi.Helpers/NotificationAgent.cs @@ -11,5 +11,6 @@ Mattermost = 6, Mobile = 7, Gotify = 8, + WhatsApp = 9 } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs new file mode 100644 index 000000000..116120e99 --- /dev/null +++ b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs @@ -0,0 +1,125 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +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; +using Ombi.Api.Twilio; + +namespace Ombi.Notifications.Agents +{ + public class WhatsAppNotification : BaseNotification + { + public WhatsAppNotification(IWhatsAppApi api, ISettingsService sn, ILogger log, + INotificationTemplatesRepository r, IMovieRequestRepository m, + ITvRequestRepository t, ISettingsService s + , IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "WhatsAppNotification"; + + private IWhatsAppApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(WhatsAppSettings settings) + { + if (!settings.Enabled) + { + return false; + } + return !settings.AccountSid.IsNullOrEmpty() && !settings.AuthToken.IsNullOrEmpty() && !settings.From.IsNullOrEmpty(); + } + + protected override async Task NewRequest(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + protected override async Task NewIssue(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, WhatsAppSettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, WhatsAppSettings settings) + { + try + { + var whatsApp = new WhatsAppModel + { + Message = model.Message, + From = settings.From, + To = ""// TODO + }; + await Api.SendMessage(whatsApp, settings.AccountSid, settings.AuthToken); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.WhatsApp, e, "Failed to send WhatsApp Notification"); + } + } + + protected override async Task Test(NotificationOptions model, WhatsAppSettings 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, WhatsAppSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.WhatsApp, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.WhatsApp}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + await Send(notification, settings); + } + } +} diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 3015c150d..c613f5b61 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs new file mode 100644 index 000000000..caa862c41 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs @@ -0,0 +1,10 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class WhatsAppSettings : Settings + { + public bool Enabled { get; set; } + public string AccountSid { get; set; } + public string AuthToken { get; set; } + public string From { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index d557516c9..78d3898ac 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -108,7 +108,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Hubs", "Ombi.Hubs\Ombi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.GroupMe", "Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj", "{9266403C-B04D-4C0F-AC39-82F12C781949}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -292,6 +294,10 @@ Global {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.Build.0 = Release|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -334,6 +340,7 @@ Global {27111E7C-748E-4996-BD71-2117027C6460} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5} {C5C1769B-4197-4410-A160-0EEF39EDDC98} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index 26ac4053f..d3bf7845c 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -963,6 +963,40 @@ namespace Ombi.Controllers.V1 return model; } + /// + /// Gets the WhatsApp Notification Settings. + /// + /// + [HttpGet("notifications/whatsapp")] + public async Task WhatsAppNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + // Lookup to see if we have any templates saved + model.NotificationTemplates = BuildTemplates(NotificationAgent.WhatsApp); + + return model; + } + + /// + /// Saves the Mattermost notification settings. + /// + /// The model. + /// + [HttpPost("notifications/whatsapp")] + public async Task WhatsAppNotificationSettings([FromBody] WhatsAppNotificationsViewModel 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; + } + /// /// Saves the Mobile notification settings. /// diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 30b63a904..883dad833 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -81,6 +81,7 @@ + diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 9bb5ef629..db794a490 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -2,12 +2,10 @@ using AutoMapper.EquivalencyExpression; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -24,7 +22,6 @@ using Ombi.Store.Context; using Ombi.Store.Entities; using Ombi.Store.Repository; using Serilog; -using SQLitePCL; using System; using System.IO; using Microsoft.AspNetCore.StaticFiles.Infrastructure;