More work for #254

This commit is contained in:
tidusjar 2016-07-27 12:55:22 +01:00
parent 9aad3f9dc9
commit 5041653c9a
5 changed files with 163 additions and 67 deletions

View file

@ -205,7 +205,7 @@ namespace PlexRequests.Services.Jobs
foreach (var lib in tvLibs) foreach (var lib in tvLibs)
{ {
shows.AddRange(lib.Directory.Select(x => new PlexTvShow() // shows are in the directory list shows.AddRange(lib.Directory.Select(x => new PlexTvShow // shows are in the directory list
{ {
Title = x.Title, Title = x.Title,
ReleaseYear = x.Year, ReleaseYear = x.Year,

View file

@ -42,6 +42,7 @@ namespace PlexRequests.Store
public string ArtistName { get; set; } public string ArtistName { get; set; }
public string ArtistId { get; set; } public string ArtistId { get; set; }
public int IssueId { get; set; } public int IssueId { get; set; }
public EpisodesModel[] Episodes { get; set; }
[JsonIgnore] [JsonIgnore]
public List<string> AllUsers public List<string> AllUsers
@ -105,4 +106,10 @@ namespace PlexRequests.Store
PlaybackIssues = 3, PlaybackIssues = 3,
Other = 4, // Provide a message Other = 4, // Provide a message
} }
public class EpisodesModel
{
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
}
} }

View file

@ -24,6 +24,10 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/ // ************************************************************************/
#endregion #endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using NLog; using NLog;
using PlexRequests.Api.Interfaces; using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Models.SickRage; using PlexRequests.Api.Models.SickRage;
@ -32,6 +36,10 @@ using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers; using PlexRequests.Helpers;
using PlexRequests.Store; using PlexRequests.Store;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using PlexRequests.Helpers.Exceptions;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Helpers namespace PlexRequests.UI.Helpers
{ {
@ -46,15 +54,15 @@ namespace PlexRequests.UI.Helpers
private ISickRageApi SickrageApi { get; } private ISickRageApi SickrageApi { get; }
private static Logger Log = LogManager.GetCurrentClassLogger(); private static Logger Log = LogManager.GetCurrentClassLogger();
public SonarrAddSeries SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model) public async Task<SonarrAddSeries> SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model)
{ {
return SendToSonarr(sonarrSettings, model, string.Empty); return await SendToSonarr(sonarrSettings, model, string.Empty);
} }
public SonarrAddSeries SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model, string qualityId) public async Task<SonarrAddSeries> SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model, string qualityId)
{ {
var qualityProfile = 0; var qualityProfile = 0;
var episodeRequest = model.Episodes.Length > 0;
if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
{ {
int.TryParse(qualityId, out qualityProfile); int.TryParse(qualityId, out qualityProfile);
@ -65,6 +73,53 @@ namespace PlexRequests.UI.Helpers
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile); int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
} }
// Does series exist?
var series = await GetSonarrSeries(sonarrSettings, model.ProviderId);
// Series Exists
if (episodeRequest)
{
if (series != null)
{
// Request the episodes in the existing series
RequestEpisodesWithExistingSeries(model, series, sonarrSettings);
}
else
{
// Series doesn't exist, need to add it as unmonitored.
var addResult = await Task.Run(() => SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile,
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, 0, new int[0], sonarrSettings.ApiKey,
sonarrSettings.FullUri));
if (string.IsNullOrEmpty(addResult?.title))
{
var sw = new Stopwatch();
sw.Start();
while (series == null)
{
await Task.Delay(TimeSpan.FromSeconds(5));
series = await GetSonarrSeries(sonarrSettings, model.ProviderId);
// Check how long we have been doing this for
if (sw.Elapsed > TimeSpan.FromSeconds(30))
{
// 30 seconds is a long time, it's not going to work.
throw new ApiRequestException("Sonarr still didn't have the series added after 30 seconds.");
}
}
sw.Stop();
}
// We now have the series in Sonarr
RequestEpisodesWithExistingSeries(model, series, sonarrSettings);
return addResult;
}
}
var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile, var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile,
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.SeasonCount, model.SeasonList, sonarrSettings.ApiKey, sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.SeasonCount, model.SeasonList, sonarrSettings.ApiKey,
sonarrSettings.FullUri); sonarrSettings.FullUri);
@ -93,5 +148,41 @@ namespace PlexRequests.UI.Helpers
return result; return result;
} }
private bool RequestEpisodesWithExistingSeries(RequestedModel model, Series selectedSeries, SonarrSettings sonarrSettings)
{
// Show Exists
// Look up all episodes
var episodes = SonarrApi.GetEpisodes(selectedSeries.id.ToString(), sonarrSettings.ApiKey, sonarrSettings.FullUri).ToList();
var internalEpisodeIds = new List<int>();
var tasks = new List<Task>();
foreach (var r in model.Episodes)
{
var episode =
episodes.FirstOrDefault(
x => x.episodeNumber == r.EpisodeNumber && x.seasonNumber == r.SeasonNumber);
if (episode == null)
{
continue;
}
var episodeInfo = SonarrApi.GetEpisode(episode.id.ToString(), sonarrSettings.ApiKey, sonarrSettings.FullUri);
episodeInfo.monitored = true; // Set the episode to monitored
tasks.Add(Task.Run(() => SonarrApi.UpdateEpisode(episodeInfo, sonarrSettings.ApiKey,
sonarrSettings.FullUri)));
internalEpisodeIds.Add(episode.id);
}
Task.WaitAll(tasks.ToArray());
SonarrApi.SearchForEpisodes(internalEpisodeIds.ToArray(), sonarrSettings.ApiKey, sonarrSettings.FullUri);
return true;
}
private async Task<Series> GetSonarrSeries(SonarrSettings sonarrSettings, int showId)
{
var task = await Task.Run(() => SonarrApi.GetSeries(sonarrSettings.ApiKey, sonarrSettings.FullUri)).ConfigureAwait(false);
var selectedSeries = task.FirstOrDefault(series => series.tvdbId == showId);
return selectedSeries;
}
} }
} }

View file

@ -458,7 +458,7 @@ namespace PlexRequests.UI.Modules
else if (sonarr.Enabled) else if (sonarr.Enabled)
{ {
var res = sender.SendToSonarr(sonarr, r); var res = await sender.SendToSonarr(sonarr, r);
if (!string.IsNullOrEmpty(res?.title)) if (!string.IsNullOrEmpty(res?.title))
{ {
r.Approved = true; r.Approved = true;

View file

@ -117,7 +117,7 @@ namespace PlexRequests.UI.Modules
Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId); 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/tvEpisodes", true] = async (x, ct) => await RequestTvShow(0, "episode");
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId); Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
Post["/notifyuser", true] = async (x, ct) => await NotifyUser((bool)Request.Form.notify); Post["/notifyuser", true] = async (x, ct) => await NotifyUser((bool)Request.Form.notify);
@ -530,7 +530,6 @@ namespace PlexRequests.UI.Modules
var json = req.FirstOrDefault()?.ToString(); var json = req.FirstOrDefault()?.ToString();
var episodeModel = JsonConvert.DeserializeObject<EpisodeRequestModel>(json); // Convert it into the object var episodeModel = JsonConvert.DeserializeObject<EpisodeRequestModel>(json); // Convert it into the object
var episodeResult = false;
var episodeRequest = false; var episodeRequest = false;
var settings = await PrService.GetSettingsAsync(); var settings = await PrService.GetSettingsAsync();
@ -540,46 +539,46 @@ namespace PlexRequests.UI.Modules
} }
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();
// This means we are requesting an episode rather than a whole series or season // This means we are requesting an episode rather than a whole series or season
if (episodeModel != null) if (episodeModel != null)
{ {
episodeRequest = true; episodeRequest = true;
var sonarrSettings = await SonarrService.GetSettingsAsync(); var s = await sonarrSettings;
if (!sonarrSettings.Enabled) if (!s.Enabled)
{ {
return Response.AsJson("This is currently only supported with Sonarr"); return Response.AsJson("This is currently only supported with Sonarr");
} }
var series = await GetSonarrSeries(sonarrSettings, episodeModel.ShowId);
if (series != null)
{
// The series already exists in Sonarr
episodeResult = RequestEpisodesWithExistingSeries(episodeModel, series, sonarrSettings);
}
} }
var showInfo = TvApi.ShowLookupByTheTvDbId(showId); var showInfo = TvApi.ShowLookupByTheTvDbId(showId);
DateTime firstAir; DateTime firstAir;
DateTime.TryParse(showInfo.premiered, out firstAir); DateTime.TryParse(showInfo.premiered, out firstAir);
string fullShowName = $"{showInfo.name} ({firstAir.Year})"; string fullShowName = $"{showInfo.name} ({firstAir.Year})";
//#if !DEBUG
if (showInfo.externals?.thetvdb == null) if (showInfo.externals?.thetvdb == null)
{ {
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Our TV Provider (TVMaze) doesn't have a TheTVDBId for this item. Please report this to TVMaze. We cannot add the series sorry." }); return Response.AsJson(new JsonResponseModel { Result = false, Message = "Our TV Provider (TVMaze) doesn't have a TheTVDBId for this item. Please report this to TVMaze. We cannot add the series sorry." });
} }
// check if the show has already been requested // check if the show/episodes have already been requested
var existingRequest = await RequestService.CheckRequestAsync(showId); var existingRequest = await RequestService.CheckRequestAsync(showId);
if (existingRequest != null) if (existingRequest != null)
{ {
// check if the current user is already marked as a requester for this show, if not, add them if (episodeRequest)
if (!existingRequest.UserHasRequested(Username))
{ {
existingRequest.RequestedUsers.Add(Username); var difference = GetListDifferences(existingRequest.Episodes, episodeModel.Episodes).ToList();
await RequestService.UpdateRequestAsync(existingRequest); if (!difference.Any())
{
return await AddUserToRequest(existingRequest, settings, fullShowName);
}
// We have an episode that has not yet been requested, let's continue
}
else
{
return await AddUserToRequest(existingRequest, settings, fullShowName);
} }
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}" : $"{fullShowName} {Resources.UI.Search_AlreadyRequested}" });
} }
try try
@ -601,7 +600,6 @@ namespace PlexRequests.UI.Modules
{ {
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) });
} }
//#endif
var model = new RequestedModel var model = new RequestedModel
@ -622,8 +620,8 @@ namespace PlexRequests.UI.Modules
TvDbId = showId.ToString() TvDbId = showId.ToString()
}; };
var seasonsList = new List<int>(); var seasonsList = new List<int>();
//TODO something here for the episodes
switch (seasons) switch (seasons)
{ {
case "first": case "first":
@ -638,7 +636,12 @@ namespace PlexRequests.UI.Modules
model.SeasonsRequested = "All"; model.SeasonsRequested = "All";
break; break;
case "episode": case "episode":
model.Episodes = new Store.EpisodesModel[episodeModel.Episodes.Length];
for (var i = 0; i < episodeModel.Episodes.Length; i++)
{
model.Episodes[i] = new Store.EpisodesModel { EpisodeNumber = episodeModel.Episodes[i].EpisodeNumber, SeasonNumber = episodeModel.Episodes[i].SeasonNumber };
}
break;
default: default:
model.SeasonsRequested = seasons; model.SeasonsRequested = seasons;
var split = seasons.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var split = seasons.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
@ -658,11 +661,11 @@ namespace PlexRequests.UI.Modules
if (ShouldAutoApprove(RequestType.TvShow, settings)) if (ShouldAutoApprove(RequestType.TvShow, settings))
{ {
model.Approved = true; model.Approved = true;
var sonarrSettings = await SonarrService.GetSettingsAsync(); var s = await sonarrSettings;
var sender = new TvSender(SonarrApi, SickrageApi); var sender = new TvSender(SonarrApi, SickrageApi);
if (sonarrSettings.Enabled) if (s.Enabled)
{ {
var result = sender.SendToSonarr(sonarrSettings, model); var result = await sender.SendToSonarr(s, model);
if (!string.IsNullOrEmpty(result?.title)) if (!string.IsNullOrEmpty(result?.title))
{ {
return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"); return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
@ -682,7 +685,7 @@ namespace PlexRequests.UI.Modules
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 && !sonarrSettings.Enabled) if (!srSettings.Enabled && !s.Enabled)
{ {
return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"); return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
} }
@ -693,6 +696,26 @@ namespace PlexRequests.UI.Modules
return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"); return await AddRequest(model, settings, $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}");
} }
private async Task<Response> AddUserToRequest(RequestedModel existingRequest, PlexRequestSettings settings, string fullShowName)
{
// check if the current user is already marked as a requester for this show, if not, add them
if (!existingRequest.UserHasRequested(Username))
{
existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
}
return
Response.AsJson(
new JsonResponseModel
{
Result = true,
Message =
settings.UsersCanViewOnlyOwnRequests
? $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"
: $"{fullShowName} {Resources.UI.Search_AlreadyRequested}"
});
}
private bool ShouldSendNotification(RequestType type, PlexRequestSettings prSettings) private bool ShouldSendNotification(RequestType type, PlexRequestSettings prSettings)
{ {
var sendNotification = ShouldAutoApprove(type, prSettings) ? !prSettings.IgnoreNotifyForAutoApprovedRequests : true; var sendNotification = ShouldAutoApprove(type, prSettings) ? !prSettings.IgnoreNotifyForAutoApprovedRequests : true;
@ -986,42 +1009,17 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(new JsonResponseModel { Result = true, Message = message }); return Response.AsJson(new JsonResponseModel { Result = true, Message = message });
} }
private bool RequestEpisodesWithExistingSeries(EpisodeRequestModel model, Series selectedSeries, SonarrSettings sonarrSettings) private IEnumerable<Store.EpisodesModel> GetListDifferences(IEnumerable<Store.EpisodesModel> model, IEnumerable<Models.EpisodesModel> request)
{ {
// Show Exists var newRequest = request
// Look up all episodes .Select(r =>
var episodes = SonarrApi.GetEpisodes(selectedSeries.id.ToString(), sonarrSettings.ApiKey, sonarrSettings.FullUri).ToList(); new Store.EpisodesModel
var internalEpisodeIds = new List<int>();
var tasks = new List<Task>();
foreach (var r in model.Episodes)
{ {
var episode = SeasonNumber = r.SeasonNumber,
episodes.FirstOrDefault( EpisodeNumber = r.EpisodeNumber
x => x.episodeNumber == r.EpisodeNumber && x.seasonNumber == r.SeasonNumber); }).ToList();
if (episode == null)
{ return newRequest.Except(model);
continue;
} }
var episodeInfo = SonarrApi.GetEpisode(episode.id.ToString(), sonarrSettings.ApiKey, sonarrSettings.FullUri);
episodeInfo.monitored = true; // Set the episode to monitored
tasks.Add(Task.Run(() => SonarrApi.UpdateEpisode(episodeInfo, sonarrSettings.ApiKey,
sonarrSettings.FullUri)));
internalEpisodeIds.Add(episode.id);
}
Task.WaitAll(tasks.ToArray());
SonarrApi.SearchForEpisodes(internalEpisodeIds.ToArray(), sonarrSettings.ApiKey, sonarrSettings.FullUri);
return true;
}
private async Task<Series> GetSonarrSeries(SonarrSettings sonarrSettings, int showId)
{
var task = await Task.Run(() => SonarrApi.GetSeries(sonarrSettings.ApiKey, sonarrSettings.FullUri)).ConfigureAwait(false);
var selectedSeries = task.FirstOrDefault(series => series.tvdbId == showId);
return selectedSeries;
}
} }
} }