From 7a422cd82e2009b199c967bcc5b7b0865e9b792c Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 20 Feb 2020 22:01:09 +0000 Subject: [PATCH] added the new mobile notification provider --- src/Ombi.Api.CloudService/Class1.cs | 48 +++ .../Ombi.Api.CloudService.csproj | 11 + src/Ombi.DependencyInjection/IocExtensions.cs | 4 +- .../Ombi.DependencyInjection.csproj | 1 + .../Interfaces/ILegacyMobileNotification.cs | 6 + .../Agents/Interfaces/IMobileNotification.cs | 4 +- .../Agents/LegacyMobileNotification.cs | 320 ++++++++++++++++++ .../Agents/MobileNotification.cs | 27 +- .../Ombi.Notifications.csproj | 1 + src/Ombi.sln | 12 +- .../V1/External/TesterController.cs | 4 +- 11 files changed, 419 insertions(+), 19 deletions(-) create mode 100644 src/Ombi.Api.CloudService/Class1.cs create mode 100644 src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj create mode 100644 src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs create mode 100644 src/Ombi.Notifications/Agents/LegacyMobileNotification.cs diff --git a/src/Ombi.Api.CloudService/Class1.cs b/src/Ombi.Api.CloudService/Class1.cs new file mode 100644 index 000000000..704883f07 --- /dev/null +++ b/src/Ombi.Api.CloudService/Class1.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Ombi.Api.CloudService +{ + public interface ICloudMobileNotification + { + Task SendMessage(MobileNotificationRequest notification); + } + public class CloudMobileNotification : ICloudMobileNotification + { + private readonly IApi _api; + private readonly ILogger _logger; + private const string BaseUrl = "https://ombinotifications.azurewebsites.net/api/"; + + public CloudMobileNotification(IApi api, ILogger logger) + { + _api = api; + _logger = logger; + } + + public async Task SendMessage(MobileNotificationRequest notification) + { + var request = new Request("MobileNotification", BaseUrl, HttpMethod.Post); + request.AddJsonBody(notification); + var response = await _api.Request(request); + + if (!response.IsSuccessStatusCode) + { + _logger.LogError($"Error when sending mobile notification message, status code: {response.StatusCode}. Please raise an issue on Github, might be a problem with" + + $" the notification service!"); + return false; + } + return true; + } + } + + public class MobileNotificationRequest + { + public string Title { get; set; } + public string Body { get; set; } + public string To { get; set; } + public Dictionary Data { get; set; } + } +} diff --git a/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj b/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj new file mode 100644 index 000000000..3c31ecb84 --- /dev/null +++ b/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.1 + + + + + + + diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 575508e99..22129f287 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -64,6 +64,7 @@ using Ombi.Schedule.Processor; using Quartz.Spi; using Ombi.Api.MusicBrainz; using Ombi.Api.Twilio; +using Ombi.Api.CloudService; namespace Ombi.DependencyInjection { @@ -149,6 +150,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { @@ -194,7 +196,7 @@ namespace Ombi.DependencyInjection 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 0a5768500..3661731de 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs new file mode 100644 index 000000000..d0d6db725 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface ILegacyMobileNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs index 1daf7e46a..d4d085dd6 100644 --- a/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs +++ b/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs @@ -1,6 +1,8 @@ -namespace Ombi.Notifications.Agents + +namespace Ombi.Notifications.Agents { public interface IMobileNotification : INotification { + } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs new file mode 100644 index 000000000..78fdc6304 --- /dev/null +++ b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Api.Notifications; +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.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class LegacyMobileNotification : BaseNotification, ILegacyMobileNotification + { + public LegacyMobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, + UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + { + _api = api; + _logger = log; + _notifications = notification; + _userManager = um; + _issueRepository = issueRepository; + } + + public override string NotificationName => "LegacyMobileNotification"; + + private readonly IOneSignalApi _api; + private readonly ILogger _logger; + private readonly IRepository _notifications; + private readonly UserManager _userManager; + private readonly IRepository _issueRepository; + + protected override bool ValidateConfiguration(MobileNotificationSettings settings) + { + return true; + } + + protected override async Task NewRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.NewRequest, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.NewRequest); + await Send(playerIds, notification, settings, model, true); + } + + protected override async Task NewIssue(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.Issue, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.Issue); + await Send(playerIds, notification, settings, model); + } + + protected override async Task IssueComment(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.IssueComment, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) + { + var isAdmin = bool.Parse(isAdminString); + if (isAdmin) + { + model.Substitutes.TryGetValue("IssueId", out var issueId); + // Send to user + var playerIds = await GetUsersForIssue(model, int.Parse(issueId), NotificationType.IssueComment); + await Send(playerIds, notification, settings, model); + } + else + { + // Send to admin + var playerIds = await GetAdmins(NotificationType.IssueComment); + await Send(playerIds, notification, settings, model); + } + } + } + + protected override async Task IssueResolved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.IssueResolved, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.IssueResolved); + + await Send(playerIds, notification, settings, model); + } + + + protected override async Task AddedToRequestQueue(NotificationOptions model, MobileNotificationSettings settings) + { + + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.ItemAddedToFaultQueue, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.ItemAddedToFaultQueue} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.Test); + await Send(playerIds, notification, settings, model); + } + + protected override async Task RequestDeclined(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestDeclined, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestDeclined); + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + + protected override async Task RequestApproved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestApproved, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestApproved); + + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + + protected override async Task AvailableRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestAvailable, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestAvailable); + + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + protected override Task Send(NotificationMessage model, MobileNotificationSettings settings) + { + throw new NotImplementedException(); + } + + protected async Task Send(List playerIds, NotificationMessage model, MobileNotificationSettings settings, NotificationOptions requestModel, bool isAdminNotification = false) + { + if (playerIds == null || !playerIds.Any()) + { + return; + } + var response = await _api.PushNotification(playerIds, model.Message, isAdminNotification, requestModel.RequestId, (int)requestModel.RequestType); + _logger.LogDebug("Sent message to {0} recipients with message id {1}", response.recipients, response.id); + } + + 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, + }; + // Send to user + var user = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id.Equals(model.UserId)); + if (user == null) + { + return; + } + + var playerIds = user.NotificationUserIds.Select(x => x.PlayerId).ToList(); + await Send(playerIds, notification, settings, model); + } + + private async Task> GetAdmins(NotificationType type) + { + var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); + var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); + var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync(); + if (!playerIds.Any()) + { + _logger.LogInformation( + $"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + return playerIds; + } + + private List GetUsers(NotificationOptions model, NotificationType type) + { + var notificationIds = new List(); + if (MovieRequest != null || TvRequest != null) + { + notificationIds = model.RequestType == RequestType.Movie + ? MovieRequest?.RequestedUser?.NotificationUserIds + : TvRequest?.RequestedUser?.NotificationUserIds; + } + if (model.UserId.HasValue() && (!notificationIds?.Any() ?? true)) + { + var user = _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefault(x => x.Id == model.UserId); + notificationIds = user.NotificationUserIds; + } + + if (!notificationIds?.Any() ?? true) + { + _logger.LogInformation( + $"there are no users to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + var playerIds = notificationIds.Select(x => x.PlayerId).ToList(); + return playerIds; + } + + private async Task> GetUsersForIssue(NotificationOptions model, int issueId, NotificationType type) + { + var notificationIds = new List(); + + var issue = await _issueRepository.GetAll() + .FirstOrDefaultAsync(x => x.Id == issueId); + + // Get the user that raised the issue to send the notification to + var userRaised = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id == issue.UserReportedId); + + notificationIds = userRaised.NotificationUserIds; + + if (!notificationIds?.Any() ?? true) + { + _logger.LogInformation( + $"there are no users to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + var playerIds = notificationIds.Select(x => x.PlayerId).ToList(); + return playerIds; + } + + private async Task AddSubscribedUsers(List playerIds) + { + if (await SubsribedUsers.AnyAsync()) + { + foreach (var user in SubsribedUsers.Include(x => x.NotificationUserIds)) + { + var notificationId = user.NotificationUserIds; + if (notificationId.Any()) + { + playerIds.AddRange(notificationId.Select(x => x.PlayerId)); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index 363029190..778adb7a9 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Api.Notifications; +using Ombi.Api.CloudService; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents { public class MobileNotification : BaseNotification, IMobileNotification { - public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, - IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, + public MobileNotification(ICloudMobileNotification api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { @@ -34,9 +34,9 @@ namespace Ombi.Notifications.Agents public override string NotificationName => "MobileNotification"; - private readonly IOneSignalApi _api; - private readonly ILogger _logger; - private readonly IRepository _notifications; + private readonly ICloudMobileNotification _api; + private readonly ILogger _logger; + private readonly IRepository _notifications; private readonly UserManager _userManager; private readonly IRepository _issueRepository; @@ -219,8 +219,17 @@ namespace Ombi.Notifications.Agents { return; } - var response = await _api.PushNotification(playerIds, model.Message, isAdminNotification, requestModel.RequestId, (int)requestModel.RequestType); - _logger.LogDebug("Sent message to {0} recipients with message id {1}", response.recipients, response.id); + foreach (var token in playerIds) + { + await _api.SendMessage(new MobileNotificationRequest() + { + Body = model.Message, + Title = model.Subject, + To = token + }); + } + + _logger.LogDebug("Sent message to {0} recipients", playerIds.Count); } protected override async Task Test(NotificationOptions model, MobileNotificationSettings settings) @@ -245,7 +254,7 @@ namespace Ombi.Notifications.Agents { var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); - var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync(); + var playerIds = await notificationUsers.Select(x => x.Token).ToListAsync(); if (!playerIds.Any()) { _logger.LogInformation( diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 63f024647..93afe0c14 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Ombi.sln b/src/Ombi.sln index 653ee8454..f7e267c60 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -116,7 +116,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.HealthChecks", "Ombi.H EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Webhook", "Ombi.Api.Webhook\Ombi.Api.Webhook.csproj", "{E2186FDA-D827-4781-8663-130AC382F12C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Firebase", "Ombi.Api.Firebase\Ombi.Api.Firebase.csproj", "{1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.CloudService", "Ombi.Api.CloudService\Ombi.Api.CloudService.csproj", "{5DE40A66-B369-469E-8626-ECE23D9D8034}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -312,10 +312,10 @@ Global {E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.Build.0 = Release|Any CPU - {1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341}.Release|Any CPU.Build.0 = Release|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -361,7 +361,7 @@ Global {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3} = {9293CA11-360A-4C20-A674-B9E794431BF5} {59D19538-0496-44EE-936E-EBBC22CF7B27} = {410F36CF-9C60-428A-B191-6FD90610991A} {E2186FDA-D827-4781-8663-130AC382F12C} = {9293CA11-360A-4C20-A674-B9E794431BF5} - {1ADD2FBB-3233-4AA8-9CBB-1F1A3E4D3341} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {5DE40A66-B369-469E-8626-ECE23D9D8034} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index 0f4fdd69a..d66fa29e9 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -43,7 +43,7 @@ namespace Ombi.Controllers.V1.External public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN, IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, - ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification, + ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification) { Service = service; @@ -90,7 +90,7 @@ namespace Ombi.Controllers.V1.External private ITelegramNotification TelegramNotification { get; } private ISickRageApi SickRageApi { get; } private INewsletterJob Newsletter { get; } - private IMobileNotification MobileNotification { get; } + private ILegacyMobileNotification MobileNotification { get; } private ILidarrApi LidarrApi { get; } private IWhatsAppApi WhatsAppApi { get; } private OmbiUserManager UserManager {get;}