Added the actual notification part of #27

pull/193/head
tidusjar 9 years ago
parent 3ea708aca5
commit c50e2bb644

@ -36,7 +36,12 @@ namespace PlexRequests.Services.Interfaces
string NotificationName { get; } string NotificationName { get; }
Task NotifyAsync(NotificationModel model); Task NotifyAsync(NotificationModel model);
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
Task NotifyAsync(NotificationModel model, Settings settings); Task NotifyAsync(NotificationModel model, Settings settings);
} }
} }

@ -33,7 +33,18 @@ namespace PlexRequests.Services.Interfaces
{ {
public interface INotificationService public interface INotificationService
{ {
/// <summary>
/// Sends a notification to the user. This one is used in normal notification scenarios
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
Task Publish(NotificationModel model); Task Publish(NotificationModel model);
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
Task Publish(NotificationModel model, Settings settings); Task Publish(NotificationModel model, Settings settings);
void Subscribe(INotification notification); void Subscribe(INotification notification);
void UnSubscribe(INotification notification); void UnSubscribe(INotification notification);

@ -37,6 +37,7 @@ using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers; using PlexRequests.Helpers;
using PlexRequests.Services.Interfaces; using PlexRequests.Services.Interfaces;
using PlexRequests.Services.Models; using PlexRequests.Services.Models;
using PlexRequests.Services.Notification;
using PlexRequests.Store; using PlexRequests.Store;
using Quartz; using Quartz;
@ -45,13 +46,15 @@ namespace PlexRequests.Services.Jobs
{ {
public class PlexAvailabilityChecker : IJob, IAvailabilityChecker public class PlexAvailabilityChecker : IJob, IAvailabilityChecker
{ {
public PlexAvailabilityChecker(ISettingsService<PlexSettings> plexSettings, ISettingsService<AuthenticationSettings> auth, IRequestService request, IPlexApi plex, ICacheProvider cache) public PlexAvailabilityChecker(ISettingsService<PlexSettings> plexSettings, ISettingsService<AuthenticationSettings> auth, IRequestService request, IPlexApi plex, ICacheProvider cache,
INotificationService notify)
{ {
Plex = plexSettings; Plex = plexSettings;
Auth = auth; Auth = auth;
RequestService = request; RequestService = request;
PlexApi = plex; PlexApi = plex;
Cache = cache; Cache = cache;
Notification = notify;
} }
private ISettingsService<PlexSettings> Plex { get; } private ISettingsService<PlexSettings> Plex { get; }
@ -60,6 +63,7 @@ namespace PlexRequests.Services.Jobs
private static Logger Log = LogManager.GetCurrentClassLogger(); private static Logger Log = LogManager.GetCurrentClassLogger();
private IPlexApi PlexApi { get; } private IPlexApi PlexApi { get; }
private ICacheProvider Cache { get; } private ICacheProvider Cache { get; }
private INotificationService Notification { get; }
public void CheckAndUpdateAll() public void CheckAndUpdateAll()
{ {
@ -67,7 +71,7 @@ namespace PlexRequests.Services.Jobs
var plexSettings = Plex.GetSettings(); var plexSettings = Plex.GetSettings();
var authSettings = Auth.GetSettings(); var authSettings = Auth.GetSettings();
Log.Trace("Getting all the requests"); Log.Trace("Getting all the requests");
if (!ValidateSettings(plexSettings, authSettings)) if (!ValidateSettings(plexSettings, authSettings))
{ {
Log.Info("Validation of the plex settings failed."); Log.Info("Validation of the plex settings failed.");
@ -95,22 +99,12 @@ namespace PlexRequests.Services.Jobs
Log.Info("There are no requests to check."); Log.Info("There are no requests to check.");
return; return;
} }
var modifiedModel = new List<RequestedModel>(); var modifiedModel = new List<RequestedModel>();
foreach (var r in requestedModels) foreach (var r in requestedModels)
{ {
Log.Trace("We are going to see if Plex has the following title: {0}", r.Title); Log.Trace("We are going to see if Plex has the following title: {0}", r.Title);
if (libraries == null)
{
libraries = new List<PlexSearch> { PlexApi.SearchContent(authSettings.PlexAuthToken, r.Title, plexSettings.FullUri) };
if (libraries.Count == 0)
{
Log.Trace("Could not find any matching result for this title.");
continue;
}
}
Log.Trace("Search results from Plex for the following request: {0}", r.Title); Log.Trace("Search results from Plex for the following request: {0}", r.Title);
var releaseDate = r.ReleaseDate == DateTime.MinValue ? string.Empty : r.ReleaseDate.ToString("yyyy"); var releaseDate = r.ReleaseDate == DateTime.MinValue ? string.Empty : r.ReleaseDate.ToString("yyyy");
@ -130,7 +124,7 @@ namespace PlexRequests.Services.Jobs
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
if (matchResult) if (matchResult)
{ {
r.Available = true; r.Available = true;
@ -146,8 +140,10 @@ namespace PlexRequests.Services.Jobs
if (modifiedModel.Any()) if (modifiedModel.Any())
{ {
NotifyUsers(modifiedModel, authSettings.PlexAuthToken);
RequestService.BatchUpdate(modifiedModel); RequestService.BatchUpdate(modifiedModel);
} }
} }
public List<PlexMovie> GetPlexMovies() public List<PlexMovie> GetPlexMovies()
@ -205,8 +201,8 @@ namespace PlexRequests.Services.Jobs
public bool IsTvShowAvailable(PlexTvShow[] plexShows, string title, string year) public bool IsTvShowAvailable(PlexTvShow[] plexShows, string title, string year)
{ {
return plexShows.Any(x => return plexShows.Any(x =>
(x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) || x.Title.StartsWith(title, StringComparison.CurrentCultureIgnoreCase)) && (x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) || x.Title.StartsWith(title, StringComparison.CurrentCultureIgnoreCase)) &&
x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)); x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase));
} }
@ -237,8 +233,8 @@ namespace PlexRequests.Services.Jobs
public bool IsAlbumAvailable(PlexAlbum[] plexAlbums, string title, string year, string artist) public bool IsAlbumAvailable(PlexAlbum[] plexAlbums, string title, string year, string artist)
{ {
return plexAlbums.Any(x => return plexAlbums.Any(x =>
x.Title.Contains(title) && x.Title.Contains(title) &&
//x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase) && //x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase) &&
x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase));
} }
@ -271,7 +267,8 @@ namespace PlexRequests.Services.Jobs
else else
{ {
Log.Trace("Plex Lib GetSet Call"); Log.Trace("Plex Lib GetSet Call");
results = Cache.GetOrSet(CacheKeys.PlexLibaries, () => { results = Cache.GetOrSet(CacheKeys.PlexLibaries, () =>
{
Log.Trace("Plex Lib API Call (inside getset)"); Log.Trace("Plex Lib API Call (inside getset)");
return GetLibraries(authSettings, plexSettings); return GetLibraries(authSettings, plexSettings);
}, CacheKeys.TimeFrameMinutes.SchedulerCaching); }, CacheKeys.TimeFrameMinutes.SchedulerCaching);
@ -281,7 +278,7 @@ namespace PlexRequests.Services.Jobs
{ {
Log.Error(ex, "Failed to obtain Plex libraries"); Log.Error(ex, "Failed to obtain Plex libraries");
} }
return results; return results;
} }
@ -305,7 +302,7 @@ namespace PlexRequests.Services.Jobs
Log.Trace("Returning Plex Libs"); Log.Trace("Returning Plex Libs");
return libs; return libs;
} }
private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth) private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth)
{ {
@ -317,9 +314,49 @@ namespace PlexRequests.Services.Jobs
return true; return true;
} }
private void NotifyUsers(IEnumerable<RequestedModel> modelChanged, string apiKey)
{
try
{
var plexUser = PlexApi.GetUsers(apiKey);
if (plexUser?.User == null || plexUser.User.Length == 0)
{
return;
}
foreach (var model in modelChanged)
{
var usersToNotify = model.UsersToNotify; // Users that selected the notification button when requesting a movie/tv show
foreach (var user in usersToNotify)
{
var email = plexUser.User.FirstOrDefault(x => x.Username == user);
if (email == null)
{
// We do not have a plex user that requested this!
continue;
}
var notificationModel = new NotificationModel
{
User = email.Username,
UserEmail = email.Email,
NotificationType = NotificationType.RequestAvailable,
Title = model.Title
};
// Send the notification to the user.
Notification.Publish(notificationModel);
}
}
}
catch (Exception e)
{
Log.Error(e);
}
}
public void Execute(IJobExecutionContext context) public void Execute(IJobExecutionContext context)
{ {
CheckAndUpdateAll(); CheckAndUpdateAll();
} }
} }
} }

@ -71,8 +71,8 @@ namespace PlexRequests.Services.Notification
await EmailIssue(model, emailSettings); await EmailIssue(model, emailSettings);
break; break;
case NotificationType.RequestAvailable: case NotificationType.RequestAvailable:
throw new NotImplementedException(); await EmailAvailableRequest(model, emailSettings);
break;
case NotificationType.RequestApproved: case NotificationType.RequestApproved:
throw new NotImplementedException(); throw new NotImplementedException();
@ -120,23 +120,7 @@ namespace PlexRequests.Services.Notification
Subject = $"Plex Requests: New request for {model.Title}!" Subject = $"Plex Requests: New request for {model.Title}!"
}; };
try await Send(message, settings);
{
using (var smtp = new SmtpClient(settings.EmailHost, settings.EmailPort))
{
smtp.Credentials = new NetworkCredential(settings.EmailUsername, settings.EmailPassword);
smtp.EnableSsl = settings.Ssl;
await smtp.SendMailAsync(message).ConfigureAwait(false);
}
}
catch (SmtpException smtp)
{
Log.Error(smtp);
}
catch (Exception e)
{
Log.Error(e);
}
} }
private async Task EmailIssue(NotificationModel model, EmailNotificationSettings settings) private async Task EmailIssue(NotificationModel model, EmailNotificationSettings settings)
@ -146,10 +130,34 @@ namespace PlexRequests.Services.Notification
IsBodyHtml = true, IsBodyHtml = true,
To = { new MailAddress(settings.RecipientEmail) }, To = { new MailAddress(settings.RecipientEmail) },
Body = $"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!", Body = $"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!",
From = new MailAddress(settings.RecipientEmail), From = new MailAddress(settings.EmailSender),
Subject = $"Plex Requests: New issue for {model.Title}!" Subject = $"Plex Requests: New issue for {model.Title}!"
}; };
await Send(message, settings);
}
private async Task EmailAvailableRequest(NotificationModel model, EmailNotificationSettings settings)
{
if (!settings.EnableUserEmailNotifications)
{
await Task.FromResult(false);
}
var message = new MailMessage
{
IsBodyHtml = true,
To = { new MailAddress(model.UserEmail) },
Body = $"Hello! You requested {model.Title} on PlexRequests! This is now available on Plex! :)",
From = new MailAddress(settings.EmailSender),
Subject = $"Plex Requests: {model.Title} is now available!"
};
await Send(message, settings);
}
private async Task Send(MailMessage message, EmailNotificationSettings settings)
{
try try
{ {
using (var smtp = new SmtpClient(settings.EmailHost, settings.EmailPort)) using (var smtp = new SmtpClient(settings.EmailHost, settings.EmailPort))
@ -176,27 +184,11 @@ namespace PlexRequests.Services.Notification
IsBodyHtml = true, IsBodyHtml = true,
To = { new MailAddress(settings.RecipientEmail) }, To = { new MailAddress(settings.RecipientEmail) },
Body = "This is just a test! Success!", Body = "This is just a test! Success!",
From = new MailAddress(settings.RecipientEmail), From = new MailAddress(settings.EmailSender),
Subject = "Plex Requests: Test Message!" Subject = "Plex Requests: Test Message!"
}; };
try await Send(message, settings);
{
using (var smtp = new SmtpClient(settings.EmailHost, settings.EmailPort))
{
smtp.Credentials = new NetworkCredential(settings.EmailUsername, settings.EmailPassword);
smtp.EnableSsl = settings.Ssl;
await smtp.SendMailAsync(message).ConfigureAwait(false);
}
}
catch (SmtpException smtp)
{
Log.Error(smtp);
}
catch (Exception e)
{
Log.Error(e);
}
} }
} }
} }

@ -35,5 +35,6 @@ namespace PlexRequests.Services.Notification
public DateTime DateTime { get; set; } public DateTime DateTime { get; set; }
public NotificationType NotificationType { get; set; } public NotificationType NotificationType { get; set; }
public string User { get; set; } public string User { get; set; }
public string UserEmail { get; set; }
} }
} }

@ -41,6 +41,11 @@ namespace PlexRequests.Services.Notification
private static Logger Log = LogManager.GetCurrentClassLogger(); private static Logger Log = LogManager.GetCurrentClassLogger();
public ConcurrentDictionary<string, INotification> Observers { get; } = new ConcurrentDictionary<string, INotification>(); public ConcurrentDictionary<string, INotification> Observers { get; } = new ConcurrentDictionary<string, INotification>();
/// <summary>
/// Sends a notification to the user. This one is used in normal notification scenarios
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
public async Task Publish(NotificationModel model) public async Task Publish(NotificationModel model)
{ {
var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model)); var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model));
@ -48,6 +53,12 @@ namespace PlexRequests.Services.Notification
await Task.WhenAll(notificationTasks).ConfigureAwait(false); await Task.WhenAll(notificationTasks).ConfigureAwait(false);
} }
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
public async Task Publish(NotificationModel model, Settings settings) public async Task Publish(NotificationModel model, Settings settings)
{ {
var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model, settings)); var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model, settings));

@ -33,6 +33,7 @@ namespace PlexRequests.Services.Notification
RequestAvailable, RequestAvailable,
RequestApproved, RequestApproved,
AdminNote, AdminNote,
Test Test,
} }
} }

@ -45,7 +45,6 @@ namespace PlexRequests.Services.Notification
} }
private IPushbulletApi PushbulletApi { get; } private IPushbulletApi PushbulletApi { get; }
private ISettingsService<PushbulletNotificationSettings> SettingsService { get; } private ISettingsService<PushbulletNotificationSettings> SettingsService { get; }
private PushbulletNotificationSettings Settings => GetSettings();
private static Logger Log = LogManager.GetCurrentClassLogger(); private static Logger Log = LogManager.GetCurrentClassLogger();
public string NotificationName => "PushbulletNotification"; public string NotificationName => "PushbulletNotification";
@ -107,45 +106,28 @@ namespace PlexRequests.Services.Notification
{ {
var message = $"{model.Title} has been requested by user: {model.User}"; var message = $"{model.Title} has been requested by user: {model.User}";
var pushTitle = $"Plex Requests: {model.Title} has been requested!"; var pushTitle = $"Plex Requests: {model.Title} has been requested!";
try await Push(settings, message, pushTitle);
{
var result = await PushbulletApi.PushAsync(settings.AccessToken, pushTitle, message, settings.DeviceIdentifier);
if (result == null)
{
Log.Error("Pushbullet api returned a null value, the notification did not get pushed");
}
}
catch (Exception e)
{
Log.Error(e);
}
} }
private async Task PushIssueAsync(NotificationModel model, PushbulletNotificationSettings settings) private async Task PushIssueAsync(NotificationModel model, PushbulletNotificationSettings settings)
{ {
var message = $"A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}"; var message = $"A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}";
var pushTitle = $"Plex Requests: A new issue has been reported for {model.Title}"; var pushTitle = $"Plex Requests: A new issue has been reported for {model.Title}";
try await Push(settings, message, pushTitle);
{
var result = await PushbulletApi.PushAsync(settings.AccessToken, pushTitle, message, settings.DeviceIdentifier);
if (result != null)
{
Log.Error("Pushbullet api returned a null value, the notification did not get pushed");
}
}
catch (Exception e)
{
Log.Error(e);
}
} }
private async Task PushTestAsync(NotificationModel model, PushbulletNotificationSettings settings) private async Task PushTestAsync(NotificationModel model, PushbulletNotificationSettings settings)
{ {
var message = "This is just a test! Success!"; var message = "This is just a test! Success!";
var pushTitle = "Plex Requests: Test Message!"; var pushTitle = "Plex Requests: Test Message!";
await Push(settings, message, pushTitle);
}
private async Task Push(PushbulletNotificationSettings settings, string message, string title)
{
try try
{ {
var result = await PushbulletApi.PushAsync(settings.AccessToken, pushTitle, message, settings.DeviceIdentifier); var result = await PushbulletApi.PushAsync(settings.AccessToken, title, message, settings.DeviceIdentifier);
if (result != null) if (result != null)
{ {
Log.Error("Pushbullet api returned a null value, the notification did not get pushed"); Log.Error("Pushbullet api returned a null value, the notification did not get pushed");

@ -45,7 +45,6 @@ namespace PlexRequests.Services.Notification
} }
private IPushoverApi PushoverApi { get; } private IPushoverApi PushoverApi { get; }
private ISettingsService<PushoverNotificationSettings> SettingsService { get; } private ISettingsService<PushoverNotificationSettings> SettingsService { get; }
private PushoverNotificationSettings Settings => GetSettings();
private static Logger Log = LogManager.GetCurrentClassLogger(); private static Logger Log = LogManager.GetCurrentClassLogger();
public string NotificationName => "PushoverNotification"; public string NotificationName => "PushoverNotification";
@ -106,40 +105,23 @@ namespace PlexRequests.Services.Notification
private async Task PushNewRequestAsync(NotificationModel model, PushoverNotificationSettings settings) private async Task PushNewRequestAsync(NotificationModel model, PushoverNotificationSettings settings)
{ {
var message = $"Plex Requests: {model.Title} has been requested by user: {model.User}"; var message = $"Plex Requests: {model.Title} has been requested by user: {model.User}";
try await Push(settings, message);
{
var result = await PushoverApi.PushAsync(settings.AccessToken, message, settings.UserToken);
if (result?.status != 1)
{
Log.Error("Pushover api returned a status that was not 1, the notification did not get pushed");
}
}
catch (Exception e)
{
Log.Error(e);
}
} }
private async Task PushIssueAsync(NotificationModel model, PushoverNotificationSettings settings) private async Task PushIssueAsync(NotificationModel model, PushoverNotificationSettings settings)
{ {
var message = $"Plex Requests: A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}"; var message = $"Plex Requests: A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}";
try await Push(settings, message);
{
var result = await PushoverApi.PushAsync(settings.AccessToken, message, settings.UserToken);
if (result?.status != 1)
{
Log.Error("Pushover api returned a status that was not 1, the notification did not get pushed");
}
}
catch (Exception e)
{
Log.Error(e);
}
} }
private async Task PushTestAsync(NotificationModel model, PushoverNotificationSettings settings) private async Task PushTestAsync(NotificationModel model, PushoverNotificationSettings settings)
{ {
var message = $"Plex Requests: Test Message!"; var message = $"Plex Requests: Test Message!";
await Push(settings, message);
}
private async Task Push(PushoverNotificationSettings settings, string message)
{
try try
{ {
var result = await PushoverApi.PushAsync(settings.AccessToken, message, settings.UserToken); var result = await PushoverApi.PushAsync(settings.AccessToken, message, settings.UserToken);

Loading…
Cancel
Save