diff --git a/PlexRequests.Core/Models/NotificationType.cs b/PlexRequests.Core/Models/NotificationType.cs
index a01d153dd..eace7b018 100644
--- a/PlexRequests.Core/Models/NotificationType.cs
+++ b/PlexRequests.Core/Models/NotificationType.cs
@@ -34,6 +34,7 @@ namespace PlexRequests.Core.Models
RequestApproved,
AdminNote,
Test,
-
+ RequestDeclined,
+ ItemAddedToFaultQueue
}
}
diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj
index 2800771ca..8faf4e83a 100644
--- a/PlexRequests.Core/PlexRequests.Core.csproj
+++ b/PlexRequests.Core/PlexRequests.Core.csproj
@@ -39,6 +39,10 @@
..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll
True
+
+ ..\packages\Dapper.1.50.0-beta8\lib\net45\Dapper.dll
+ True
+
..\Assemblies\Mono.Data.Sqlite.dll
@@ -105,6 +109,7 @@
+
diff --git a/PlexRequests.Core/Queue/ITransientFaultQueue.cs b/PlexRequests.Core/Queue/ITransientFaultQueue.cs
new file mode 100644
index 000000000..ac62add0f
--- /dev/null
+++ b/PlexRequests.Core/Queue/ITransientFaultQueue.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using PlexRequests.Store;
+using PlexRequests.Store.Models;
+
+namespace PlexRequests.Core.Queue
+{
+ public interface ITransientFaultQueue
+ {
+ void Dequeue();
+ Task DequeueAsync();
+ IEnumerable GetQueue();
+ Task> GetQueueAsync();
+ void QueueItem(RequestedModel request, RequestType type, FaultType faultType);
+ Task QueueItemAsync(RequestedModel request, RequestType type, FaultType faultType);
+ }
+}
\ No newline at end of file
diff --git a/PlexRequests.Core/Queue/TransientFaultQueue.cs b/PlexRequests.Core/Queue/TransientFaultQueue.cs
index e3621ee0f..108387f03 100644
--- a/PlexRequests.Core/Queue/TransientFaultQueue.cs
+++ b/PlexRequests.Core/Queue/TransientFaultQueue.cs
@@ -26,7 +26,9 @@
#endregion
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
+using Dapper;
using PlexRequests.Helpers;
using PlexRequests.Store;
using PlexRequests.Store.Models;
@@ -34,7 +36,7 @@ using PlexRequests.Store.Repository;
namespace PlexRequests.Core.Queue
{
- public class TransientFaultQueue
+ public class TransientFaultQueue : ITransientFaultQueue
{
public TransientFaultQueue(IRepository queue)
{
@@ -44,44 +46,84 @@ namespace PlexRequests.Core.Queue
private IRepository RequestQueue { get; }
- public void QueueItem(RequestedModel request, RequestType type)
+ public void QueueItem(RequestedModel request, RequestType type, FaultType faultType)
{
+ //Ensure there is not a duplicate queued item
+ var existingItem = RequestQueue.Custom(
+ connection =>
+ {
+ connection.Open();
+ var result = connection.Query("select * from RequestQueue where PrimaryIdentifier = @ProviderId", new { ProviderId = request.ProviderId });
+
+ return result;
+ }).FirstOrDefault();
+
+ if (existingItem != null)
+ {
+ // It's already in the queue
+ return;
+ }
+
var queue = new RequestQueue
{
Type = type,
Content = ByteConverterHelper.ReturnBytes(request),
- PrimaryIdentifier = request.ProviderId
+ PrimaryIdentifier = request.ProviderId,
+ FaultType = faultType
};
RequestQueue.Insert(queue);
}
- public async Task QueueItemAsync(RequestedModel request, RequestType type)
+ public async Task QueueItemAsync(RequestedModel request, RequestType type, FaultType faultType)
{
+ //Ensure there is not a duplicate queued item
+ var existingItem = await RequestQueue.CustomAsync(async connection =>
+ {
+ connection.Open();
+ var result = await connection.QueryAsync("select * from RequestQueue where PrimaryIdentifier = @ProviderId", new { ProviderId = request.ProviderId });
+
+ return result;
+ });
+
+ if (existingItem.FirstOrDefault() != null)
+ {
+ // It's already in the queue
+ return;
+ }
+
var queue = new RequestQueue
{
Type = type,
Content = ByteConverterHelper.ReturnBytes(request),
- PrimaryIdentifier = request.ProviderId
+ PrimaryIdentifier = request.ProviderId,
+ FaultType = faultType
};
await RequestQueue.InsertAsync(queue);
}
- public IEnumerable Dequeue()
+ public IEnumerable GetQueue()
{
var items = RequestQueue.GetAll();
- RequestQueue.DeleteAll("RequestQueue");
return items;
}
- public async Task> DequeueAsync()
+ public async Task> GetQueueAsync()
{
var items = RequestQueue.GetAllAsync();
-
- await RequestQueue.DeleteAllAsync("RequestQueue");
-
+
return await items;
}
+
+ public void Dequeue()
+ {
+ RequestQueue.DeleteAll("RequestQueue");
+ }
+
+ public async Task DequeueAsync()
+ {
+ await RequestQueue.DeleteAllAsync("RequestQueue");
+ }
}
}
\ No newline at end of file
diff --git a/PlexRequests.Core/packages.config b/PlexRequests.Core/packages.config
index e8f81f5a9..d698d0fd5 100644
--- a/PlexRequests.Core/packages.config
+++ b/PlexRequests.Core/packages.config
@@ -2,6 +2,7 @@
+
diff --git a/PlexRequests.Services/Notification/EmailMessageNotification.cs b/PlexRequests.Services/Notification/EmailMessageNotification.cs
index 3f6bf9c91..52727dba8 100644
--- a/PlexRequests.Services/Notification/EmailMessageNotification.cs
+++ b/PlexRequests.Services/Notification/EmailMessageNotification.cs
@@ -87,6 +87,14 @@ namespace PlexRequests.Services.Notification
case NotificationType.Test:
await EmailTest(model, emailSettings);
break;
+ case NotificationType.RequestDeclined:
+ throw new NotImplementedException();
+
+ case NotificationType.ItemAddedToFaultQueue:
+ await EmailAddedToRequestQueue(model, emailSettings);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
}
}
@@ -129,7 +137,7 @@ namespace PlexRequests.Services.Notification
$"Plex Requests: New {model.RequestType.GetString()?.ToLower()} request for {model.Title}!",
$"Hello! The user '{model.User}' has requested the {model.RequestType.GetString()?.ToLower()} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime.ToString("f")}",
model.ImgSrc);
- var body = new BodyBuilder { HtmlBody = html, TextBody = "This email is only available on devices that support HTML." };
+ var body = new BodyBuilder { HtmlBody = html, TextBody = $"Hello! The user '{model.User}' has requested the {model.RequestType.GetString()?.ToLower()} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime.ToString("f")}" };
var message = new MimeMessage
{
@@ -150,7 +158,7 @@ namespace PlexRequests.Services.Notification
$"Plex Requests: New issue for {model.Title}!",
$"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!",
model.ImgSrc);
- var body = new BodyBuilder { HtmlBody = html, TextBody = "This email is only available on devices that support HTML." };
+ var body = new BodyBuilder { HtmlBody = html, TextBody = $"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!"};
var message = new MimeMessage
{
@@ -164,6 +172,27 @@ namespace PlexRequests.Services.Notification
await Send(message, settings);
}
+ private async Task EmailAddedToRequestQueue(NotificationModel model, EmailNotificationSettings settings)
+ {
+ var email = new EmailBasicTemplate();
+ var html = email.LoadTemplate(
+ "Plex Requests: A request could not be added.",
+ $"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying",
+ model.ImgSrc);
+ var body = new BodyBuilder { HtmlBody = html, TextBody = $"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying" };
+
+ var message = new MimeMessage
+ {
+ Body = body.ToMessageBody(),
+ Subject = $"Plex Requests: A request could not be added"
+ };
+ message.From.Add(new MailboxAddress(settings.EmailSender, settings.EmailSender));
+ message.To.Add(new MailboxAddress(settings.RecipientEmail, settings.RecipientEmail));
+
+
+ await Send(message, settings);
+ }
+
private async Task EmailAvailableRequest(NotificationModel model, EmailNotificationSettings settings)
{
if (!settings.EnableUserEmailNotifications)
@@ -175,7 +204,7 @@ namespace PlexRequests.Services.Notification
$"Plex Requests: {model.Title} is now available!",
$"Hello! You requested {model.Title} on PlexRequests! This is now available on Plex! :)",
model.ImgSrc);
- var body = new BodyBuilder { HtmlBody = html, TextBody = "This email is only available on devices that support HTML." };
+ var body = new BodyBuilder { HtmlBody = html, TextBody = $"Hello! You requested {model.Title} on PlexRequests! This is now available on Plex! :)" };
var message = new MimeMessage
{
diff --git a/PlexRequests.Store/Models/RequestQueue.cs b/PlexRequests.Store/Models/RequestQueue.cs
index bdbf25a2f..15067fbc7 100644
--- a/PlexRequests.Store/Models/RequestQueue.cs
+++ b/PlexRequests.Store/Models/RequestQueue.cs
@@ -38,5 +38,12 @@ namespace PlexRequests.Store.Models
public byte[] Content { get; set; }
+ public FaultType FaultType { get; set; }
+ }
+
+ public enum FaultType
+ {
+ RequestFault,
+ MissingInformation
}
}
\ No newline at end of file
diff --git a/PlexRequests.Store/SqlTables.sql b/PlexRequests.Store/SqlTables.sql
index a22258a5d..220664ba1 100644
--- a/PlexRequests.Store/SqlTables.sql
+++ b/PlexRequests.Store/SqlTables.sql
@@ -138,6 +138,7 @@ CREATE TABLE IF NOT EXISTS RequestQueue
Id INTEGER PRIMARY KEY AUTOINCREMENT,
PrimaryIdentifier INTEGER NOT NULL,
Type INTEGER NOT NULL,
+ FaultType INTEGER NOT NULL,
Content BLOB NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS PlexUsers_Id ON PlexUsers (Id);
diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs
index e10e5b92d..ef35e08b6 100644
--- a/PlexRequests.UI/Modules/SearchModule.cs
+++ b/PlexRequests.UI/Modules/SearchModule.cs
@@ -1,4 +1,5 @@
#region Copyright
+
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SearchModule.cs
@@ -23,7 +24,9 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
+
#endregion
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -54,13 +57,13 @@ using Newtonsoft.Json;
using PlexRequests.Api.Models.Sonarr;
using PlexRequests.Api.Models.Tv;
using PlexRequests.Core.Models;
+using PlexRequests.Core.Queue;
using PlexRequests.Helpers.Analytics;
using PlexRequests.Helpers.Permissions;
using PlexRequests.Store.Models;
using PlexRequests.Store.Repository;
using TMDbLib.Objects.General;
-using TMDbLib.Objects.Search;
using Action = PlexRequests.Helpers.Analytics.Action;
using EpisodesModel = PlexRequests.Store.EpisodesModel;
@@ -73,10 +76,13 @@ namespace PlexRequests.UI.Modules
ISettingsService prSettings, IAvailabilityChecker checker,
IRequestService request, ISonarrApi sonarrApi, ISettingsService sonarrSettings,
ISettingsService sickRageService, ICouchPotatoApi cpApi, ISickRageApi srApi,
- INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi, ISettingsService hpService,
+ INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi,
+ ISettingsService hpService,
ICouchPotatoCacher cpCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi,
- ISettingsService plexService, ISettingsService auth, IRepository u, ISettingsService email,
- IIssueService issue, IAnalytics a, IRepository rl) : base("search", prSettings)
+ ISettingsService plexService, ISettingsService auth,
+ IRepository u, ISettingsService email,
+ IIssueService issue, IAnalytics a, IRepository rl, ITransientFaultQueue tfQueue)
+ : base("search", prSettings)
{
Auth = auth;
PlexService = plexService;
@@ -104,6 +110,7 @@ namespace PlexRequests.UI.Modules
IssueService = issue;
Analytics = a;
RequestLimitRepo = rl;
+ FaultQueue = tfQueue;
TvApi = new TvMazeApi();
@@ -118,7 +125,8 @@ namespace PlexRequests.UI.Modules
Get["movie/playing", true] = async (x, ct) => await CurrentlyPlayingMovies();
Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId);
- Post["request/tv", true] = async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
+ Post["request/tv", true] =
+ async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
Post["request/tvEpisodes", true] = async (x, ct) => await RequestTvShow(0, "episode");
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
@@ -128,6 +136,7 @@ namespace PlexRequests.UI.Modules
Get["/seasons"] = x => GetSeasons();
Get["/episodes", true] = async (x, ct) => await GetEpisodes();
}
+
private TvMazeApi TvApi { get; }
private IPlexApi PlexApi { get; }
private TheMovieDbApi MovieApi { get; }
@@ -154,6 +163,7 @@ namespace PlexRequests.UI.Modules
private IRepository UsersToNotifyRepo { get; }
private IIssueService IssueService { get; }
private IAnalytics Analytics { get; }
+ private ITransientFaultQueue FaultQueue { get; }
private IRepository RequestLimitRepo { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
@@ -167,19 +177,22 @@ namespace PlexRequests.UI.Modules
private async Task UpcomingMovies()
{
- Analytics.TrackEventAsync(Category.Search, Action.Movie, "Upcoming", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Movie, "Upcoming", Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
return await ProcessMovies(MovieSearchType.Upcoming, string.Empty);
}
private async Task CurrentlyPlayingMovies()
{
- Analytics.TrackEventAsync(Category.Search, Action.Movie, "CurrentlyPlaying", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Movie, "CurrentlyPlaying", Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
return await ProcessMovies(MovieSearchType.CurrentlyPlaying, string.Empty);
}
private async Task SearchMovie(string searchTerm)
{
- Analytics.TrackEventAsync(Category.Search, Action.Movie, searchTerm, Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Movie, searchTerm, Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
return await ProcessMovies(MovieSearchType.Search, searchTerm);
}
@@ -192,24 +205,24 @@ namespace PlexRequests.UI.Modules
case MovieSearchType.Search:
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
apiMovies = movies.Select(x =>
- new MovieResult
- {
- Adult = x.Adult,
- BackdropPath = x.BackdropPath,
- GenreIds = x.GenreIds,
- Id = x.Id,
- OriginalLanguage = x.OriginalLanguage,
- OriginalTitle = x.OriginalTitle,
- Overview = x.Overview,
- Popularity = x.Popularity,
- PosterPath = x.PosterPath,
- ReleaseDate = x.ReleaseDate,
- Title = x.Title,
- Video = x.Video,
- VoteAverage = x.VoteAverage,
- VoteCount = x.VoteCount
- })
- .ToList();
+ new MovieResult
+ {
+ Adult = x.Adult,
+ BackdropPath = x.BackdropPath,
+ GenreIds = x.GenreIds,
+ Id = x.Id,
+ OriginalLanguage = x.OriginalLanguage,
+ OriginalTitle = x.OriginalTitle,
+ Overview = x.Overview,
+ Popularity = x.Popularity,
+ PosterPath = x.PosterPath,
+ ReleaseDate = x.ReleaseDate,
+ Title = x.Title,
+ Video = x.Video,
+ VoteAverage = x.VoteAverage,
+ VoteCount = x.VoteCount
+ })
+ .ToList();
break;
case MovieSearchType.CurrentlyPlaying:
apiMovies = await MovieApi.GetCurrentPlayingMovies();
@@ -239,8 +252,9 @@ namespace PlexRequests.UI.Modules
var imdbId = string.Empty;
if (counter <= 5) // Let's only do it for the first 5 items
{
- var movieInfoTask = await MovieApi.GetMovieInformation(movie.Id).ConfigureAwait(false); // TODO needs to be careful about this, it's adding extra time to search...
- // https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
+ var movieInfoTask = await MovieApi.GetMovieInformation(movie.Id).ConfigureAwait(false);
+ // TODO needs to be careful about this, it's adding extra time to search...
+ // https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
imdbId = movieInfoTask.ImdbId;
counter++;
}
@@ -263,7 +277,8 @@ namespace PlexRequests.UI.Modules
VoteCount = movie.VoteCount
};
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
- var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(), imdbId);
+ var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(),
+ imdbId);
if (plexMovie != null)
{
viewMovie.Available = true;
@@ -288,7 +303,8 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(viewMovies);
}
- private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests, Dictionary moviesInDb)
+ private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests,
+ Dictionary moviesInDb)
{
if (usersCanViewOnlyOwnRequests)
{
@@ -302,7 +318,8 @@ namespace PlexRequests.UI.Modules
private async Task SearchTvShow(string searchTerm)
{
- Analytics.TrackEventAsync(Category.Search, Action.TvShow, searchTerm, Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.TvShow, searchTerm, Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
var plexSettings = await PlexService.GetSettingsAsync();
var prSettings = await PrService.GetSettingsAsync();
var providerId = string.Empty;
@@ -360,7 +377,8 @@ namespace PlexRequests.UI.Modules
providerId = viewT.Id.ToString();
}
- var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
+ var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
+ providerId);
if (plexShow != null)
{
viewT.Available = true;
@@ -377,7 +395,8 @@ namespace PlexRequests.UI.Modules
viewT.Episodes = dbt.Episodes.ToList();
viewT.Approved = dbt.Approved;
}
- if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid)) // compare to the sonarr/sickrage db
+ if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid))
+ // compare to the sonarr/sickrage db
{
viewT.Requested = true;
}
@@ -391,7 +410,8 @@ namespace PlexRequests.UI.Modules
private async Task SearchAlbum(string searchTerm)
{
- Analytics.TrackEventAsync(Category.Search, Action.Album, searchTerm, Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Album, searchTerm, Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
var apiAlbums = new List();
await Task.Run(() => MusicBrainzApi.SearchAlbum(searchTerm)).ContinueWith((t) =>
{
@@ -448,7 +468,7 @@ namespace PlexRequests.UI.Modules
if (Security.DoesNotHavePermissions(Permissions.ReadOnlyUser, User))
{
return
- Response.AsJson(new JsonResponseModel()
+ Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Sorry, you do not have the correct permissions to request a movie!"
@@ -457,12 +477,19 @@ namespace PlexRequests.UI.Modules
var settings = await PrService.GetSettingsAsync();
if (!await CheckRequestLimit(settings, RequestType.Movie))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = "You have reached your weekly request limit for Movies! Please contact your admin." });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = "You have reached your weekly request limit for Movies! Please contact your admin."
+ });
}
- Analytics.TrackEventAsync(Category.Search, Action.Request, "Movie", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Request, "Movie", Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
var movieInfo = await MovieApi.GetMovieInformation(movieId);
- var fullMovieName = $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}";
+ var fullMovieName =
+ $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}";
var existingRequest = await RequestService.CheckRequestAsync(movieId);
if (existingRequest != null)
@@ -474,7 +501,15 @@ namespace PlexRequests.UI.Modules
await RequestService.UpdateRequestAsync(existingRequest);
}
- return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}" : $"{fullMovieName} {Resources.UI.Search_AlreadyRequested}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message =
+ settings.UsersCanViewOnlyOwnRequests
+ ? $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"
+ : $"{fullMovieName} {Resources.UI.Search_AlreadyRequested}"
+ });
}
try
@@ -482,13 +517,23 @@ namespace PlexRequests.UI.Modules
var movies = Checker.GetPlexMovies();
if (Checker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullMovieName} is already in Plex!" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = $"{fullMovieName} is already in Plex!"
+ });
}
}
catch (Exception e)
{
Log.Error(e);
- return Response.AsJson(new JsonResponseModel { Result = false, Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName) });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName)
+ });
}
//#endif
@@ -508,41 +553,58 @@ namespace PlexRequests.UI.Modules
Issues = IssueState.None,
};
-
- if (ShouldAutoApprove(RequestType.Movie, settings))
- {
- var cpSettings = await CpService.GetSettingsAsync();
- model.Approved = true;
- if (cpSettings.Enabled)
- {
- Log.Info("Adding movie to CP (No approval required)");
- var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title,
- cpSettings.FullUri, cpSettings.ProfileId);
- Log.Debug("Adding movie to CP result {0}", result);
- if (result)
- {
- return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
- }
-
- return Response.AsJson(new JsonResponseModel
- {
- Result = false,
- Message = Resources.UI.Search_CouchPotatoError
- });
- }
- model.Approved = true;
- return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
- }
-
try
{
+ if (ShouldAutoApprove(RequestType.Movie, settings))
+ {
+ var cpSettings = await CpService.GetSettingsAsync();
+ model.Approved = true;
+ if (cpSettings.Enabled)
+ {
+ Log.Info("Adding movie to CP (No approval required)");
+ var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title,
+ cpSettings.FullUri, cpSettings.ProfileId);
+ Log.Debug("Adding movie to CP result {0}", result);
+ if (result)
+ {
+ return
+ await
+ AddRequest(model, settings,
+ $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+
+ return Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = Resources.UI.Search_CouchPotatoError
+ });
+ }
+ model.Approved = true;
+ return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+
+
return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
}
catch (Exception e)
{
Log.Fatal(e);
+ await FaultQueue.QueueItemAsync(model, RequestType.Movie, FaultType.RequestFault);
- return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_CouchPotatoError });
+ await NotificationService.Publish(new NotificationModel
+ {
+ DateTime = DateTime.Now,
+ User = Username,
+ RequestType = RequestType.Movie,
+ Title = model.Title,
+ NotificationType = NotificationType.ItemAddedToFaultQueue
+ });
+
+ return Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message = $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"
+ });
}
}
@@ -576,9 +638,15 @@ namespace PlexRequests.UI.Modules
var settings = await PrService.GetSettingsAsync();
if (!await CheckRequestLimit(settings, RequestType.TvShow))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_WeeklyRequestLimitTVShow });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = Resources.UI.Search_WeeklyRequestLimitTVShow
+ });
}
- Analytics.TrackEventAsync(Category.Search, Action.Request, "TvShow", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Request, "TvShow", Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
var sonarrSettings = SonarrService.GetSettingsAsync();
@@ -590,7 +658,13 @@ namespace PlexRequests.UI.Modules
var s = await sonarrSettings;
if (!s.Enabled)
{
- return Response.AsJson(new JsonResponseModel { Message = "This is currently only supported with Sonarr, Please enable Sonarr for this feature", Result = false });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Message =
+ "This is currently only supported with Sonarr, Please enable Sonarr for this feature",
+ Result = false
+ });
}
}
@@ -599,14 +673,8 @@ namespace PlexRequests.UI.Modules
DateTime.TryParse(showInfo.premiered, out firstAir);
string fullShowName = $"{showInfo.name} ({firstAir.Year})";
- if (showInfo.externals?.thetvdb == null)
- {
- return Response.AsJson(new JsonResponseModel { Result = false, Message = "Our TV Provider (TVMaze) doesn't have a TheTVDBId for this TV Show :( We cannot add the TV Show automatically sorry! Please report this problem to the server admin so he/she can sort it out!" });
- }
-
var model = new RequestedModel
{
- ProviderId = showInfo.externals?.thetvdb ?? 0,
Type = RequestType.TvShow,
Overview = showInfo.summary.RemoveHtml(),
PosterPath = showInfo.image?.medium,
@@ -622,6 +690,25 @@ namespace PlexRequests.UI.Modules
TvDbId = showId.ToString()
};
+ if (showInfo.externals?.thetvdb == null)
+ {
+ await FaultQueue.QueueItemAsync(model, RequestType.TvShow, FaultType.MissingInformation);
+ await NotificationService.Publish(new NotificationModel
+ {
+ DateTime = DateTime.Now,
+ User = Username,
+ RequestType = RequestType.TvShow,
+ Title = model.Title,
+ NotificationType = NotificationType.ItemAddedToFaultQueue
+ });
+ return Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message = $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"
+ });
+ }
+
+ model.ProviderId = showInfo.externals?.thetvdb ?? 0;
var seasonsList = new List();
switch (seasons)
@@ -642,9 +729,14 @@ namespace PlexRequests.UI.Modules
foreach (var ep in episodeModel?.Episodes ?? new Models.EpisodesModel[0])
{
- model.Episodes.Add(new EpisodesModel { EpisodeNumber = ep.EpisodeNumber, SeasonNumber = ep.SeasonNumber });
+ model.Episodes.Add(new EpisodesModel
+ {
+ EpisodeNumber = ep.EpisodeNumber,
+ SeasonNumber = ep.SeasonNumber
+ });
}
- Analytics.TrackEventAsync(Category.Requests, Action.TvShow, $"Episode request for {model.Title}", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Requests, Action.TvShow, $"Episode request for {model.Title}",
+ Username, CookieHelper.GetAnalyticClientId(Cookies));
break;
default:
model.SeasonsRequested = seasons;
@@ -691,7 +783,12 @@ namespace PlexRequests.UI.Modules
else
{
// We no episodes to approve
- return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
+ });
}
}
else if (model.SeasonList.Except(existingRequest.SeasonList).Any())
@@ -720,9 +817,19 @@ namespace PlexRequests.UI.Modules
var cachedEpisodes = cachedEpisodesTask.ToList();
foreach (var d in difference) // difference is from an existing request
{
- if (cachedEpisodes.Any(x => x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber && x.ProviderId == providerId))
+ if (
+ cachedEpisodes.Any(
+ x =>
+ x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
+ x.ProviderId == providerId))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {Resources.UI.Search_AlreadyInPlex}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message =
+ $"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {Resources.UI.Search_AlreadyInPlex}"
+ });
}
}
@@ -738,66 +845,118 @@ namespace PlexRequests.UI.Modules
var result = Checker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber, s.EpisodeNumber);
if (result)
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
+ });
}
}
}
- else if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4), providerId, model.SeasonList))
+ else if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4),
+ providerId, model.SeasonList))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
+ });
}
}
}
catch (Exception)
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName) });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName)
+ });
}
-
- if (ShouldAutoApprove(RequestType.TvShow, settings))
+ try
{
- model.Approved = true;
- var s = await sonarrSettings;
- var sender = new TvSenderOld(SonarrApi, SickrageApi); // TODO put back
- if (s.Enabled)
+ if (ShouldAutoApprove(RequestType.TvShow, settings))
{
- var result = await sender.SendToSonarr(s, model);
- if (!string.IsNullOrEmpty(result?.title))
+ model.Approved = true;
+ var s = await sonarrSettings;
+ var sender = new TvSenderOld(SonarrApi, SickrageApi); // TODO put back
+ if (s.Enabled)
{
- if (existingRequest != null)
+ var result = await sender.SendToSonarr(s, model);
+ if (!string.IsNullOrEmpty(result?.title))
{
- return await UpdateRequest(model, settings,
+ if (existingRequest != null)
+ {
+ return await UpdateRequest(model, settings,
+ $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+ return
+ await
+ AddRequest(model, settings,
$"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
}
- return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ Log.Debug("Error with sending to sonarr.");
+ return
+ Response.AsJson(ValidationHelper.SendSonarrError(result?.ErrorMessages ?? new List()));
}
- Log.Debug("Error with sending to sonarr.");
- return Response.AsJson(ValidationHelper.SendSonarrError(result?.ErrorMessages ?? new List()));
- }
- var srSettings = SickRageService.GetSettings();
- if (srSettings.Enabled)
- {
- var result = sender.SendToSickRage(srSettings, model);
- if (result?.result == "success")
+ var srSettings = SickRageService.GetSettings();
+ if (srSettings.Enabled)
{
- return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ var result = sender.SendToSickRage(srSettings, model);
+ if (result?.result == "success")
+ {
+ return
+ await
+ AddRequest(model, settings,
+ $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = result?.message ?? Resources.UI.Search_SickrageError
+ });
}
- return Response.AsJson(new JsonResponseModel { Result = false, Message = result?.message ?? Resources.UI.Search_SickrageError });
+
+ if (!srSettings.Enabled && !s.Enabled)
+ {
+ return
+ await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+
+ return
+ Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_TvNotSetUp });
+
}
-
- if (!srSettings.Enabled && !s.Enabled)
- {
- return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
- }
-
- return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_TvNotSetUp });
-
+ return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
+ }
+ catch (Exception e)
+ {
+ await FaultQueue.QueueItemAsync(model, RequestType.TvShow, FaultType.RequestFault);
+ await NotificationService.Publish(new NotificationModel
+ {
+ DateTime = DateTime.Now,
+ User = Username,
+ RequestType = RequestType.TvShow,
+ Title = model.Title,
+ NotificationType = NotificationType.ItemAddedToFaultQueue
+ });
+ Log.Error(e);
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message = $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"
+ });
}
- return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
}
- private async Task AddUserToRequest(RequestedModel existingRequest, PlexRequestSettings settings, string fullShowName, bool episodeReq = false)
+ private async Task AddUserToRequest(RequestedModel existingRequest, PlexRequestSettings settings,
+ string fullShowName, bool episodeReq = false)
{
// check if the current user is already marked as a requester for this show, if not, add them
if (!existingRequest.UserHasRequested(Username))
@@ -812,12 +971,15 @@ namespace PlexRequests.UI.Modules
$"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
}
- return await UpdateRequest(existingRequest, settings, $"{fullShowName} {Resources.UI.Search_AlreadyRequested}");
+ return
+ await UpdateRequest(existingRequest, settings, $"{fullShowName} {Resources.UI.Search_AlreadyRequested}");
}
private bool ShouldSendNotification(RequestType type, PlexRequestSettings prSettings)
{
- var sendNotification = ShouldAutoApprove(type, prSettings) ? !prSettings.IgnoreNotifyForAutoApprovedRequests : true;
+ var sendNotification = ShouldAutoApprove(type, prSettings)
+ ? !prSettings.IgnoreNotifyForAutoApprovedRequests
+ : true;
var claims = Context.CurrentUser?.Claims;
if (claims != null)
{
@@ -836,9 +998,15 @@ namespace PlexRequests.UI.Modules
var settings = await PrService.GetSettingsAsync();
if (!await CheckRequestLimit(settings, RequestType.Album))
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_WeeklyRequestLimitAlbums });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = Resources.UI.Search_WeeklyRequestLimitAlbums
+ });
}
- Analytics.TrackEventAsync(Category.Search, Action.Request, "Album", Username, CookieHelper.GetAnalyticClientId(Cookies));
+ Analytics.TrackEventAsync(Category.Search, Action.Request, "Album", Username,
+ CookieHelper.GetAnalyticClientId(Cookies));
var existingRequest = await RequestService.CheckRequestAsync(releaseId);
if (existingRequest != null)
@@ -848,7 +1016,15 @@ namespace PlexRequests.UI.Modules
existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
}
- return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{existingRequest.Title} {Resources.UI.Search_SuccessfullyAdded}" : $"{existingRequest.Title} {Resources.UI.Search_AlreadyRequested}" });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message =
+ settings.UsersCanViewOnlyOwnRequests
+ ? $"{existingRequest.Title} {Resources.UI.Search_SuccessfullyAdded}"
+ : $"{existingRequest.Title} {Resources.UI.Search_AlreadyRequested}"
+ });
}
var albumInfo = MusicBrainzApi.GetAlbum(releaseId);
@@ -858,11 +1034,17 @@ namespace PlexRequests.UI.Modules
var artist = albumInfo.ArtistCredits?.FirstOrDefault()?.artist;
if (artist == null)
{
- return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_MusicBrainzError });
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = false,
+ Message = Resources.UI.Search_MusicBrainzError
+ });
}
var albums = Checker.GetPlexAlbums();
- var alreadyInPlex = Checker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"), artist.name);
+ var alreadyInPlex = Checker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"),
+ artist.name);
if (alreadyInPlex)
{
@@ -892,28 +1074,46 @@ namespace PlexRequests.UI.Modules
ArtistId = artist.id
};
- if (ShouldAutoApprove(RequestType.Album, settings))
+ try
{
- model.Approved = true;
- var hpSettings = HeadphonesService.GetSettings();
-
- if (!hpSettings.Enabled)
+ if (ShouldAutoApprove(RequestType.Album, settings))
{
- await RequestService.AddRequestAsync(model);
- return
- Response.AsJson(new JsonResponseModel
- {
- Result = true,
- Message = $"{model.Title} {Resources.UI.Search_SuccessfullyAdded}"
- });
+ model.Approved = true;
+ var hpSettings = HeadphonesService.GetSettings();
+
+ if (!hpSettings.Enabled)
+ {
+ await RequestService.AddRequestAsync(model);
+ return
+ Response.AsJson(new JsonResponseModel
+ {
+ Result = true,
+ Message = $"{model.Title} {Resources.UI.Search_SuccessfullyAdded}"
+ });
+ }
+
+ var sender = new HeadphonesSender(HeadphonesApi, hpSettings, RequestService);
+ await sender.AddAlbum(model);
+ return await AddRequest(model, settings, $"{model.Title} {Resources.UI.Search_SuccessfullyAdded}");
}
- var sender = new HeadphonesSender(HeadphonesApi, hpSettings, RequestService);
- await sender.AddAlbum(model);
return await AddRequest(model, settings, $"{model.Title} {Resources.UI.Search_SuccessfullyAdded}");
}
+ catch (Exception e)
+ {
+ Log.Error(e);
+ await FaultQueue.QueueItemAsync(model, RequestType.Movie, FaultType.RequestFault);
- return await AddRequest(model, settings, $"{model.Title} {Resources.UI.Search_SuccessfullyAdded}");
+ await NotificationService.Publish(new NotificationModel
+ {
+ DateTime = DateTime.Now,
+ User = Username,
+ RequestType = RequestType.Album,
+ Title = model.Title,
+ NotificationType = NotificationType.ItemAddedToFaultQueue
+ });
+ throw;
+ }
}
private string GetMusicBrainzCoverArt(string id)
diff --git a/PlexRequests.UI/NinjectModules/ServicesModule.cs b/PlexRequests.UI/NinjectModules/ServicesModule.cs
index a180335d6..a7ba11dea 100644
--- a/PlexRequests.UI/NinjectModules/ServicesModule.cs
+++ b/PlexRequests.UI/NinjectModules/ServicesModule.cs
@@ -25,7 +25,7 @@
// ************************************************************************/
#endregion
using Ninject.Modules;
-
+using PlexRequests.Core.Queue;
using PlexRequests.Helpers.Analytics;
using PlexRequests.Services.Interfaces;
using PlexRequests.Services.Jobs;
@@ -51,6 +51,8 @@ namespace PlexRequests.UI.NinjectModules
Bind().To();
Bind().To();
Bind().To();
+
+ Bind().To();
}
}
}
\ No newline at end of file