added the new mobile notification provider

pull/3435/head
Jamie Rees 4 years ago
parent 3a89483599
commit 7a422cd82e

@ -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<bool> 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<CloudMobileNotification> logger)
{
_api = api;
_logger = logger;
}
public async Task<bool> 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<string, string> Data { get; set; }
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
</ItemGroup>
</Project>

@ -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<IGroupMeApi, GroupMeApi>();
services.AddTransient<IMusicBrainzApi, MusicBrainzApi>();
services.AddTransient<IWhatsAppApi, WhatsAppApi>();
services.AddTransient<ICloudMobileNotification, CloudMobileNotification>();
}
public static void RegisterStore(this IServiceCollection services) {
@ -194,7 +196,7 @@ namespace Ombi.DependencyInjection
services.AddTransient<IGotifyNotification, GotifyNotification>();
services.AddTransient<IWebhookNotification, WebhookNotification>();
services.AddTransient<ITelegramNotification, TelegramNotification>();
services.AddTransient<IMobileNotification, MobileNotification>();
services.AddTransient<ILegacyMobileNotification, LegacyMobileNotification>();
services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>();
}

@ -16,6 +16,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.CloudService\Ombi.Api.CloudService.csproj" />
<ProjectReference Include="..\Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj" />
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
<ProjectReference Include="..\Ombi.Api.DogNzb\Ombi.Api.DogNzb.csproj" />

@ -0,0 +1,6 @@
namespace Ombi.Notifications.Agents
{
public interface ILegacyMobileNotification : INotification
{
}
}

@ -1,6 +1,8 @@
namespace Ombi.Notifications.Agents

namespace Ombi.Notifications.Agents
{
public interface IMobileNotification : INotification
{
}
}

@ -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<MobileNotificationSettings>, ILegacyMobileNotification
{
public LegacyMobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<LegacyMobileNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music, IRepository<Issues> issueRepository,
IRepository<UserNotificationPreferences> 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<LegacyMobileNotification> _logger;
private readonly IRepository<NotificationUserId> _notifications;
private readonly UserManager<OmbiUser> _userManager;
private readonly IRepository<Issues> _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<string> 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<List<string>> 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<string> GetUsers(NotificationOptions model, NotificationType type)
{
var notificationIds = new List<NotificationUserId>();
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<List<string>> GetUsersForIssue(NotificationOptions model, int issueId, NotificationType type)
{
var notificationIds = new List<NotificationUserId>();
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<string> 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));
}
}
}
}
}
}

@ -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<MobileNotificationSettings>, IMobileNotification
{
public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
public MobileNotification(ICloudMobileNotification api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<MobileDevices> notification,
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music, IRepository<Issues> issueRepository,
IRepository<UserNotificationPreferences> 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<MobileNotification> _logger;
private readonly IRepository<NotificationUserId> _notifications;
private readonly ICloudMobileNotification _api;
private readonly ILogger _logger;
private readonly IRepository<MobileDevices> _notifications;
private readonly UserManager<OmbiUser> _userManager;
private readonly IRepository<Issues> _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(

@ -15,6 +15,7 @@
</ItemGroup>
<ItemGroup>
<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.Webhook\Ombi.Api.Webhook.csproj" />

@ -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}

@ -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<TesterController> 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;}

Loading…
Cancel
Save