pull/470/head
tidusjar 8 years ago
parent 4eff175424
commit d7997d5cc0

@ -43,6 +43,6 @@ namespace PlexRequests.Api.Interfaces
PlexEpisodeMetadata GetEpisodeMetaData(string authToken, Uri host, string ratingKey); PlexEpisodeMetadata GetEpisodeMetaData(string authToken, Uri host, string ratingKey);
PlexSearch GetAllEpisodes(string authToken, Uri host, string section, int startPage, int returnCount); PlexSearch GetAllEpisodes(string authToken, Uri host, string section, int startPage, int returnCount);
PlexServer GetServer(string authToken); PlexServer GetServer(string authToken);
PlexMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey); PlexSeasonMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey);
} }
} }

@ -55,4 +55,29 @@ namespace PlexRequests.Api.Models.Plex
public string MediaTagVersion { get; set; } public string MediaTagVersion { get; set; }
} }
[XmlRoot(ElementName = "MediaContainer")]
public class PlexSeasonMetadata
{
[XmlElement(ElementName = "Video")]
public Video Video { get; set; }
[XmlElement(ElementName = "Directory")]
public List<Directory1> Directory { get; set; }
[XmlAttribute(AttributeName = "size")]
public string Size { get; set; }
[XmlAttribute(AttributeName = "allowSync")]
public string AllowSync { get; set; }
[XmlAttribute(AttributeName = "identifier")]
public string Identifier { get; set; }
[XmlAttribute(AttributeName = "librarySectionID")]
public string LibrarySectionID { get; set; }
[XmlAttribute(AttributeName = "librarySectionTitle")]
public string LibrarySectionTitle { get; set; }
[XmlAttribute(AttributeName = "librarySectionUUID")]
public string LibrarySectionUUID { get; set; }
[XmlAttribute(AttributeName = "mediaTagPrefix")]
public string MediaTagPrefix { get; set; }
[XmlAttribute(AttributeName = "mediaTagVersion")]
public string MediaTagVersion { get; set; }
}
} }

@ -244,6 +244,10 @@ namespace PlexRequests.Api.Models.Plex
[XmlRoot(ElementName = "Directory")] [XmlRoot(ElementName = "Directory")]
public class Directory1 public class Directory1
{ {
public Directory1()
{
Seasons = new List<Directory1>();
}
public string ProviderId { get; set; } public string ProviderId { get; set; }
[XmlAttribute(AttributeName = "guid")] [XmlAttribute(AttributeName = "guid")]
public string Guid { get; set; } public string Guid { get; set; }

@ -302,7 +302,7 @@ namespace PlexRequests.Api
} }
public PlexMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey) public PlexSeasonMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey)
{ {
var request = new RestRequest var request = new RestRequest
{ {
@ -315,7 +315,7 @@ namespace PlexRequests.Api
try try
{ {
var lib = RetryHandler.Execute(() => Api.ExecuteXml<PlexMetadata>(request, plexFullHost), var lib = RetryHandler.Execute(() => Api.ExecuteXml<PlexSeasonMetadata>(request, plexFullHost),
(exception, timespan) => Log.Error(exception, "Exception when calling GetMetadata for Plex, Retrying {0}", timespan), new[] { (exception, timespan) => Log.Error(exception, "Exception when calling GetMetadata for Plex, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (5), TimeSpan.FromSeconds (5),
TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10),
@ -327,7 +327,7 @@ namespace PlexRequests.Api
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "There has been a API Exception when attempting to get the Plex GetMetadata"); Log.Error(e, "There has been a API Exception when attempting to get the Plex GetMetadata");
return new PlexMetadata(); return new PlexSeasonMetadata();
} }
} }

@ -28,6 +28,10 @@ namespace PlexRequests.Core.SettingModels
{ {
public sealed class PlexSettings : ExternalSettings public sealed class PlexSettings : ExternalSettings
{ {
public PlexSettings()
{
AdvancedSearch = true;
}
public bool AdvancedSearch { get; set; } public bool AdvancedSearch { get; set; }
public bool EnableTvEpisodeSearching { get; set; } public bool EnableTvEpisodeSearching { get; set; }

@ -30,10 +30,10 @@ namespace PlexRequests.Core.SettingModels
{ {
public ScheduledJobsSettings() public ScheduledJobsSettings()
{ {
PlexAvailabilityChecker = 10; PlexAvailabilityChecker = 60;
SickRageCacher = 10; SickRageCacher = 60;
SonarrCacher = 10; SonarrCacher = 60;
CouchPotatoCacher = 10; CouchPotatoCacher = 60;
StoreBackup = 24; StoreBackup = 24;
StoreCleanup = 24; StoreCleanup = 24;
UserRequestLimitResetter = 12; UserRequestLimitResetter = 12;

@ -181,7 +181,7 @@ namespace PlexRequests.Services.Jobs
{ {
if (advanced) if (advanced)
{ {
if (!string.IsNullOrEmpty(movie.ProviderId) && if (!string.IsNullOrEmpty(movie.ProviderId) &&
movie.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) movie.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase))
{ {
return true; return true;
@ -209,7 +209,8 @@ namespace PlexRequests.Services.Jobs
).ToArray(); ).ToArray();
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,
@ -229,14 +230,15 @@ namespace PlexRequests.Services.Jobs
{ {
if (advanced) if (advanced)
{ {
if (seasons != null) if (seasons != null && show.ProviderId == providerId)
{ {
if (seasons.Any(season => show.Seasons.Contains(season))) if (seasons.Any(season => show.Seasons.Contains(season)))
{ {
return true; return true;
} }
return false;
} }
if (!string.IsNullOrEmpty(show.ProviderId) && if (!string.IsNullOrEmpty(show.ProviderId) &&
show.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) show.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase))
{ {
return true; return true;
@ -257,14 +259,14 @@ namespace PlexRequests.Services.Jobs
connection => connection =>
{ {
connection.Open(); connection.Open();
var result = connection.Query<PlexEpisodes>("select * from PlexEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId}); var result = connection.Query<PlexEpisodes>("select * from PlexEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId });
return result; return result;
}).ToList(); }).ToList();
if (!ep.Any()) if (!ep.Any())
{ {
Log.Info("Episode cache info is not available. tvdbid: {0}, season: {1}, episode: {2}",theTvDbId, season, episode); Log.Info("Episode cache info is not available. tvdbid: {0}, season: {1}, episode: {2}", theTvDbId, season, episode);
return false; return false;
} }
foreach (var result in ep) foreach (var result in ep)
@ -298,13 +300,13 @@ namespace PlexRequests.Services.Jobs
/// <returns></returns> /// <returns></returns>
public async Task<IEnumerable<PlexEpisodes>> GetEpisodes(int theTvDbId) public async Task<IEnumerable<PlexEpisodes>> GetEpisodes(int theTvDbId)
{ {
var ep = await EpisodeRepo.CustomAsync(async connection => var ep = await EpisodeRepo.CustomAsync(async connection =>
{ {
connection.Open(); connection.Open();
var result = await connection.QueryAsync<PlexEpisodes>("select * from PlexEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId }); var result = await connection.QueryAsync<PlexEpisodes>("select * from PlexEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId });
return result; return result;
}); });
var plexEpisodeses = ep as PlexEpisodes[] ?? ep.ToArray(); var plexEpisodeses = ep as PlexEpisodes[] ?? ep.ToArray();
if (!plexEpisodeses.Any()) if (!plexEpisodeses.Any())
@ -373,8 +375,23 @@ namespace PlexRequests.Services.Jobs
var currentItem = results[i].Directory[j]; var currentItem = results[i].Directory[j];
var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
currentItem.RatingKey); currentItem.RatingKey);
var seasons = PlexApi.GetSeasons(plexSettings.PlexAuthToken, plexSettings.FullUri, currentItem.RatingKey);
results[i].Directory[j] = seasons.Directory; // Get the seasons for each show
if (currentItem.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
var seasons = PlexApi.GetSeasons(plexSettings.PlexAuthToken, plexSettings.FullUri,
currentItem.RatingKey);
// We do not want "all episodes" this as a season
var filtered =
seasons.Directory.Where(
x =>
!x.Title.Equals("All episodes",
StringComparison.CurrentCultureIgnoreCase));
results[i].Directory[j].Seasons.AddRange(filtered);
}
var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.Directory.Guid); var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.Directory.Guid);
results[i].Directory[j].ProviderId = providerId; results[i].Directory[j].ProviderId = providerId;
} }

@ -584,7 +584,7 @@ $(function () {
var $form = $('#form' + tvId); var $form = $('#form' + tvId);
var model = []; var model = [];
var $checkedEpisodes = $('.selectedEpisodes:checkbox:checked'); var $checkedEpisodes = $('.selectedEpisodes:checkbox:checked:not(:disabled)');
$checkedEpisodes.each(function (index, element) { $checkedEpisodes.each(function (index, element) {
var $element = $('#' + element.id); var $element = $('#' + element.id);
var tempObj = {}; var tempObj = {};
@ -610,7 +610,7 @@ $(function () {
success: function (response) { success: function (response) {
finishLoading("episodesRequest", "primary", origHtml); finishLoading("episodesRequest", "primary", origHtml);
if (response.result === true) { if (response.result === true) {
generateNotify(response.message); generateNotify(response.message, "success");
} else { } else {
generateNotify(response.message, "warning"); generateNotify(response.message, "warning");
} }

@ -26,6 +26,9 @@ function utcToLocal(date) {
function generateNotify(message, type) { function generateNotify(message, type) {
// type = danger, warning, info, successs // type = danger, warning, info, successs
if (!type) {
type = "success";
}
$.notify({ $.notify({
// options // options
message: message message: message

@ -566,34 +566,6 @@ namespace PlexRequests.UI.Modules
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/episodes have already been requested
var existingRequest = await RequestService.CheckRequestAsync(showId);
var difference = new List<EpisodesModel>();
if (existingRequest != null)
{
if (episodeRequest)
{
difference = GetListDifferences(existingRequest.Episodes, episodeModel.Episodes).ToList();
if (difference.Any())
{
existingRequest.Episodes = episodeModel.Episodes
.Select(r =>
new EpisodesModel
{
SeasonNumber = r.SeasonNumber,
EpisodeNumber = r.EpisodeNumber
}).ToList();
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);
}
}
var model = new RequestedModel var model = new RequestedModel
{ {
ProviderId = showInfo.externals?.thetvdb ?? 0, ProviderId = showInfo.externals?.thetvdb ?? 0,
@ -652,6 +624,45 @@ namespace PlexRequests.UI.Modules
model.SeasonList = seasonsList.ToArray(); model.SeasonList = seasonsList.ToArray();
// check if the show/episodes have already been requested
var existingRequest = await RequestService.CheckRequestAsync(showId);
var difference = new List<EpisodesModel>();
if (existingRequest != null)
{
if (episodeRequest)
{
// Make sure we are not somehow adding dupes
difference = GetListDifferences(existingRequest.Episodes, episodeModel.Episodes).ToList();
if (difference.Any())
{
// Convert the request into the correct shape
var newEpisodes = episodeModel.Episodes?.Select(x => new EpisodesModel
{
SeasonNumber = x.SeasonNumber,
EpisodeNumber = x.EpisodeNumber
});
// Add it to the existing requests
existingRequest.Episodes.AddRange(newEpisodes ?? Enumerable.Empty<EpisodesModel>());
// It's technically a new request now, so set the status to not approved.
existingRequest.Approved = false;
return await AddUserToRequest(existingRequest, settings, fullShowName);
}
// We have an episode that has not yet been requested, let's continue
}
else if (model.SeasonList.Except(existingRequest.SeasonList).Any())
{
// This is a season being requested that we do not yet have
// Let's just continue
}
else
{
return await AddUserToRequest(existingRequest, settings, fullShowName);
}
}
try try
{ {
var shows = Checker.GetPlexTvShows(); var shows = Checker.GetPlexTvShows();
@ -673,11 +684,7 @@ namespace PlexRequests.UI.Modules
} }
} }
var episodes = await GetEpisodes(showId); var diff = await GetEpisodeRequestDifference(showId, model);
var availableEpisodes = episodes.Where(x => x.Requested).ToList();
var availble = availableEpisodes.Select(a => new EpisodesModel { EpisodeNumber = a.EpisodeNumber, SeasonNumber = a.SeasonNumber }).ToList();
var diff = model.Episodes.Except(availble);
model.Episodes = diff.ToList(); model.Episodes = diff.ToList();
} }
else else
@ -704,6 +711,11 @@ namespace PlexRequests.UI.Modules
var result = await sender.SendToSonarr(s, model); var result = await sender.SendToSonarr(s, model);
if (!string.IsNullOrEmpty(result?.title)) if (!string.IsNullOrEmpty(result?.title))
{ {
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."); Log.Debug("Error with sending to sonarr.");
@ -735,21 +747,14 @@ namespace PlexRequests.UI.Modules
private async Task<Response> AddUserToRequest(RequestedModel existingRequest, PlexRequestSettings settings, string fullShowName) 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 // check if the current user is already marked as a requester for this show, if not, add them
if (!existingRequest.UserHasRequested(Username) || existingRequest.Episodes.Any()) if (!existingRequest.UserHasRequested(Username))
{ {
existingRequest.RequestedUsers.Add(Username); existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
} }
return
Response.AsJson( return await UpdateRequest(existingRequest, settings, settings.UsersCanViewOnlyOwnRequests
new JsonResponseModel ? $"{fullShowName} {Resources.UI.Search_SuccessfullyAdded}"
{ : $"{fullShowName} {Resources.UI.Search_AlreadyRequested}");
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)
@ -1103,6 +1108,44 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(new JsonResponseModel { Result = true, Message = message }); return Response.AsJson(new JsonResponseModel { Result = true, Message = message });
} }
private async Task<Response> UpdateRequest(RequestedModel model, PlexRequestSettings settings, string message)
{
await RequestService.UpdateRequestAsync(model);
if (ShouldSendNotification(model.Type, settings))
{
var notificationModel = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest,
RequestType = model.Type
};
await NotificationService.Publish(notificationModel);
}
var limit = await RequestLimitRepo.GetAllAsync();
var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
if (usersLimit == null)
{
await RequestLimitRepo.InsertAsync(new RequestLimit
{
Username = Username,
RequestType = model.Type,
FirstRequestDate = DateTime.UtcNow,
RequestCount = 1
});
}
else
{
usersLimit.RequestCount++;
await RequestLimitRepo.UpdateAsync(usersLimit);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = message });
}
private IEnumerable<Store.EpisodesModel> GetListDifferences(IEnumerable<EpisodesModel> existing, IEnumerable<Models.EpisodesModel> request) private IEnumerable<Store.EpisodesModel> GetListDifferences(IEnumerable<EpisodesModel> existing, IEnumerable<Models.EpisodesModel> request)
{ {
var newRequest = request var newRequest = request
@ -1115,5 +1158,15 @@ namespace PlexRequests.UI.Modules
return newRequest.Except(existing); return newRequest.Except(existing);
} }
private async Task<IEnumerable<EpisodesModel>> GetEpisodeRequestDifference(int showId, RequestedModel model)
{
var episodes = await GetEpisodes(showId);
var availableEpisodes = episodes.Where(x => x.Requested).ToList();
var available = availableEpisodes.Select(a => new EpisodesModel { EpisodeNumber = a.EpisodeNumber, SeasonNumber = a.SeasonNumber }).ToList();
var diff = model.Episodes.Except(available);
return diff;
}
} }
} }

Loading…
Cancel
Save