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, um) { _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 GetPrivilegedUsersPlayerIds(); 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(); 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(); 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(); 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() { return await GetNotificationRecipients(await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)); } private async Task> GetPrivilegedUsersPlayerIds() { return await GetNotificationRecipients(await GetPrivilegedUsers()); } private async Task> GetNotificationRecipients(IEnumerable users) { var adminUsers = users.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 users to send a notification 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 Subscribed.AnyAsync()) { foreach (var user in Subscribed) { var notificationId = user.NotificationUserIds; if (notificationId.Any()) { playerIds.AddRange(notificationId.Select(x => x.PlayerId)); } } } } protected override async Task PartiallyAvailable(NotificationOptions model, MobileNotificationSettings settings) { var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.PartiallyAvailable, model); if (parsed.Disabled) { _logger.LogInformation($"Template {NotificationType.PartiallyAvailable} is disabled for {NotificationAgent.Mobile}"); return; } var notification = new NotificationMessage { Message = parsed.Message, }; // Send to user var playerIds = GetUsers(model, NotificationType.PartiallyAvailable); await AddSubscribedUsers(playerIds); await Send(playerIds, notification, settings, model); } } }