pull/591/head^2
tidusjar 8 years ago
parent 1a0e7cbe7b
commit 512d2131bd

@ -44,6 +44,6 @@ namespace PlexRequests.Api.Interfaces
PlexSearch GetAllEpisodes(string authToken, Uri host, string section, int startPage, int returnCount);
PlexServer GetServer(string authToken);
PlexSeasonMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey);
RecentlyAdded RecentlyAdded(string authToken, Uri plexFullHost);
RecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId);
}
}

@ -1,7 +1,7 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: RecentlyAdded.cs
// File: RecentlyAddedModel.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
@ -32,53 +32,102 @@ namespace PlexRequests.Api.Models.Plex
public class RecentlyAddedChild
{
public string _elementType { get; set; }
public string allowSync { get; set; }
public string librarySectionID { get; set; }
public string librarySectionTitle { get; set; }
public string librarySectionUUID { get; set; }
public int ratingKey { get; set; }
public string key { get; set; }
public int parentRatingKey { get; set; }
public int grandparentRatingKey { get; set; }
public string type { get; set; }
public string title { get; set; }
public string grandparentKey { get; set; }
public string parentKey { get; set; }
public string parentTitle { get; set; }
public string parentSummary { get; set; }
public string grandparentTitle { get; set; }
public string summary { get; set; }
public int index { get; set; }
public int parentIndex { get; set; }
public string thumb { get; set; }
public string art { get; set; }
public string parentThumb { get; set; }
public int leafCount { get; set; }
public int viewedLeafCount { get; set; }
public string grandparentThumb { get; set; }
public string grandparentArt { get; set; }
public int duration { get; set; }
public int addedAt { get; set; }
public int updatedAt { get; set; }
public List<object> _children { get; set; }
public string studio { get; set; }
public string chapterSource { get; set; }
public List<Child2> _children { get; set; }
public string contentRating { get; set; }
public string rating { get; set; }
public int? viewCount { get; set; }
public int? lastViewedAt { get; set; }
public int? year { get; set; }
public int? duration { get; set; }
public string parentThumb { get; set; }
public string grandparentTheme { get; set; }
public string originallyAvailableAt { get; set; }
public string chapterSource { get; set; }
public string parentTheme { get; set; }
public string titleSort { get; set; }
public string tagline { get; set; }
public int? viewCount { get; set; }
public int? lastViewedAt { get; set; }
public int? viewOffset { get; set; }
public string rating { get; set; }
public string studio { get; set; }
public string tagline { get; set; }
public string originalTitle { get; set; }
public string audienceRating { get; set; }
public string audienceRatingImage { get; set; }
public string ratingImage { get; set; }
}
public class Child3
{
public string _elementType { get; set; }
public string id { get; set; }
public string key { get; set; }
public double duration { get; set; }
public string file { get; set; }
public double size { get; set; }
public string audioProfile { get; set; }
public string container { get; set; }
public string videoProfile { get; set; }
public string deepAnalysisVersion { get; set; }
public string requiredBandwidths { get; set; }
public string hasThumbnail { get; set; }
public bool? has64bitOffsets { get; set; }
public bool? optimizedForStreaming { get; set; }
public bool? hasChapterTextStream { get; set; }
}
public class RecentlyAdded
public class Child2
{
public string _elementType { get; set; }
public string videoResolution { get; set; }
public int id { get; set; }
public int duration { get; set; }
public int bitrate { get; set; }
public int width { get; set; }
public int height { get; set; }
public string aspectRatio { get; set; }
public int audioChannels { get; set; }
public string audioCodec { get; set; }
public string videoCodec { get; set; }
public string container { get; set; }
public string videoFrameRate { get; set; }
public string audioProfile { get; set; }
public string videoProfile { get; set; }
public List<Child3> _children { get; set; }
public string tag { get; set; }
}
public class RecentlyAddedModel
{
public string _elementType { get; set; }
public string allowSync { get; set; }
public string art { get; set; }
public string identifier { get; set; }
public string librarySectionID { get; set; }
public string librarySectionTitle { get; set; }
public string librarySectionUUID { get; set; }
public string mediaTagPrefix { get; set; }
public string mediaTagVersion { get; set; }
public string mixedParents { get; set; }
public string nocache { get; set; }
public string thumb { get; set; }
public string title1 { get; set; }
public string title2 { get; set; }
public string viewGroup { get; set; }
public string viewMode { get; set; }
public List<RecentlyAddedChild> _children { get; set; }
}
}

@ -73,7 +73,7 @@
<Compile Include="Plex\PlexStatus.cs" />
<Compile Include="Plex\PlexMediaType.cs" />
<Compile Include="Plex\PlexUserRequest.cs" />
<Compile Include="Plex\RecentlyAdded.cs" />
<Compile Include="Plex\RecentlyAddedModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SickRage\SickRageBase.cs" />
<Compile Include="SickRage\SickrageShows.cs" />

@ -76,7 +76,7 @@ namespace PlexRequests.Api
Method = Method.POST
};
AddHeaders(ref request);
AddHeaders(ref request, false);
request.AddJsonBody(userModel);
@ -93,7 +93,7 @@ namespace PlexRequests.Api
Method = Method.GET,
};
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
var users = RetryHandler.Execute(() => Api.ExecuteXml<PlexFriends> (request, new Uri(FriendsUri)),
(exception, timespan) => Log.Error (exception, "Exception when calling GetUsers for Plex, Retrying {0}", timespan), null);
@ -118,7 +118,7 @@ namespace PlexRequests.Api
};
request.AddUrlSegment("searchTerm", searchTerm);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
var search = RetryHandler.Execute(() => Api.ExecuteXml<PlexSearch> (request, plexFullHost),
(exception, timespan) => Log.Error (exception, "Exception when calling SearchContent for Plex, Retrying {0}", timespan), null);
@ -133,7 +133,7 @@ namespace PlexRequests.Api
Method = Method.GET,
};
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
var users = RetryHandler.Execute(() => Api.ExecuteXml<PlexStatus> (request, uri),
(exception, timespan) => Log.Error (exception, "Exception when calling GetStatus for Plex, Retrying {0}", timespan), null);
@ -148,7 +148,7 @@ namespace PlexRequests.Api
Method = Method.GET,
};
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
var account = RetryHandler.Execute(() => Api.ExecuteXml<PlexAccount> (request, new Uri(GetAccountUri)),
(exception, timespan) => Log.Error (exception, "Exception when calling GetAccount for Plex, Retrying {0}", timespan), null);
@ -164,7 +164,7 @@ namespace PlexRequests.Api
Resource = "library/sections"
};
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -193,7 +193,7 @@ namespace PlexRequests.Api
};
request.AddUrlSegment("libraryId", libraryId);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -228,7 +228,7 @@ namespace PlexRequests.Api
};
request.AddUrlSegment("ratingKey", ratingKey);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -253,10 +253,9 @@ namespace PlexRequests.Api
};
request.AddQueryParameter("type", 4.ToString());
request.AddQueryParameter("X-Plex-Container-Start", startPage.ToString());
request.AddQueryParameter("X-Plex-Container-Size", returnCount.ToString());
AddLimitHeaders(ref request, startPage, returnCount);
request.AddUrlSegment("section", section);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -281,7 +280,7 @@ namespace PlexRequests.Api
};
request.AddUrlSegment("itemId", itemId);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -311,7 +310,7 @@ namespace PlexRequests.Api
};
request.AddUrlSegment("ratingKey", ratingKey);
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
try
{
@ -338,7 +337,7 @@ namespace PlexRequests.Api
Method = Method.GET,
};
AddHeaders(ref request, authToken);
AddHeaders(ref request, authToken, false);
var servers = RetryHandler.Execute(() => Api.ExecuteXml<PlexServer>(request, new Uri(ServerUri)),
(exception, timespan) => Log.Error(exception, "Exception when calling GetServer for Plex, Retrying {0}", timespan));
@ -347,25 +346,22 @@ namespace PlexRequests.Api
return servers;
}
public RecentlyAdded RecentlyAdded(string authToken, Uri plexFullHost)
public RecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId)
{
var request = new RestRequest
{
Method = Method.GET,
Resource = "library/recentlyAdded"
Resource = "library/sections/{sectionId}/recentlyAdded"
};
request.AddHeader("X-Plex-Token", authToken);
request.AddHeader("X-Plex-Client-Identifier", $"PlexRequests.Net{Version}");
request.AddHeader("X-Plex-Product", "Plex Requests .Net");
request.AddHeader("X-Plex-Version", Version);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddUrlSegment("sectionId", sectionId);
AddHeaders(ref request, authToken, true);
AddLimitHeaders(ref request, 0, 25);
try
{
var lib = RetryHandler.Execute(() => Api.ExecuteJson<RecentlyAdded>(request, plexFullHost),
(exception, timespan) => Log.Error(exception, "Exception when calling RecentlyAdded for Plex, Retrying {0}", timespan), new[] {
var lib = RetryHandler.Execute(() => Api.ExecuteJson<RecentlyAddedModel>(request, plexFullHost),
(exception, timespan) => Log.Error(exception, "Exception when calling RecentlyAddedModel for Plex, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (5),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(30)
@ -375,23 +371,30 @@ namespace PlexRequests.Api
}
catch (Exception e)
{
Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAdded");
return new RecentlyAdded();
Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAddedModel");
return new RecentlyAddedModel();
}
}
private void AddHeaders(ref RestRequest request, string authToken)
private void AddLimitHeaders(ref RestRequest request, int from, int to)
{
request.AddHeader("X-Plex-Container-Start", from.ToString());
request.AddHeader("X-Plex-Container-Size", to.ToString());
}
private void AddHeaders(ref RestRequest request, string authToken, bool json)
{
request.AddHeader("X-Plex-Token", authToken);
AddHeaders(ref request);
AddHeaders(ref request, json);
}
private void AddHeaders(ref RestRequest request)
private void AddHeaders(ref RestRequest request, bool json)
{
request.AddHeader("X-Plex-Client-Identifier", $"PlexRequests.Net{Version}");
request.AddHeader("X-Plex-Product", "Plex Requests .Net");
request.AddHeader("X-Plex-Version", Version);
request.AddHeader("Content-Type", "application/xml");
request.AddHeader("Content-Type", json ? "application/json" : "application/xml");
request.AddHeader("Accept", json ? "application/json" : "application/xml");
}
}
}

@ -1,42 +1,50 @@
using System;
using System.Globalization;
using System.Linq;
namespace PlexRequests.Helpers
{
public static class DateTimeHelper
{
public static DateTimeOffset OffsetUTCDateTime(DateTime utcDateTime, int minuteOffset)
{
//TimeSpan ts = TimeSpan.FromMinutes(-minuteOffset);
//return new DateTimeOffset(utcDateTime).ToOffset(ts);
// this is a workaround below to work with MONO
var tzi = FindTimeZoneFromOffset(minuteOffset);
var utcOffset = tzi.GetUtcOffset(utcDateTime);
var newDate = utcDateTime + utcOffset;
return new DateTimeOffset(newDate.Ticks, utcOffset);
}
public static void CustomParse(string date, out DateTime dt)
{
// Try and parse it
if (DateTime.TryParse(date, out dt))
{
return;
}
// Maybe it's only a year?
if (DateTime.TryParseExact(date, "yyyy", CultureInfo.CurrentCulture, DateTimeStyles.None, out dt))
{
return;
}
}
private static TimeZoneInfo FindTimeZoneFromOffset(int minuteOffset)
{
var tzc = TimeZoneInfo.GetSystemTimeZones();
return tzc.FirstOrDefault(x => x.BaseUtcOffset.TotalMinutes == -minuteOffset);
}
}
}
using System;
using System.Globalization;
using System.Linq;
namespace PlexRequests.Helpers
{
public static class DateTimeHelper
{
public static DateTimeOffset OffsetUTCDateTime(DateTime utcDateTime, int minuteOffset)
{
//TimeSpan ts = TimeSpan.FromMinutes(-minuteOffset);
//return new DateTimeOffset(utcDateTime).ToOffset(ts);
// this is a workaround below to work with MONO
var tzi = FindTimeZoneFromOffset(minuteOffset);
var utcOffset = tzi.GetUtcOffset(utcDateTime);
var newDate = utcDateTime + utcOffset;
return new DateTimeOffset(newDate.Ticks, utcOffset);
}
public static void CustomParse(string date, out DateTime dt)
{
// Try and parse it
if (DateTime.TryParse(date, out dt))
{
return;
}
// Maybe it's only a year?
if (DateTime.TryParseExact(date, "yyyy", CultureInfo.CurrentCulture, DateTimeStyles.None, out dt))
{
return;
}
}
private static TimeZoneInfo FindTimeZoneFromOffset(int minuteOffset)
{
var tzc = TimeZoneInfo.GetSystemTimeZones();
return tzc.FirstOrDefault(x => x.BaseUtcOffset.TotalMinutes == -minuteOffset);
}
public static DateTime UnixTimeStampToDateTime(this int unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
}
}

@ -123,12 +123,13 @@ namespace PlexRequests.Services.Jobs
case RequestType.TvShow:
if (!plexSettings.EnableTvEpisodeSearching)
{
matchResult = IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId);
matchResult = IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList);
}
else
{
matchResult =
r.Episodes.All(x => IsEpisodeAvailable(r.TvDbId, x.SeasonNumber, x.EpisodeNumber));
matchResult = r.Episodes.Any() ?
r.Episodes.All(x => IsEpisodeAvailable(r.TvDbId, x.SeasonNumber, x.EpisodeNumber)) :
IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList);
}
break;
case RequestType.Album:
@ -270,7 +271,7 @@ namespace PlexRequests.Services.Jobs
{
if (advanced)
{
if (seasons != null && show.ProviderId == providerId)
if (show.ProviderId == providerId)
{
if (seasons.Any(season => show.Seasons.Contains(season)))
{

@ -2,7 +2,7 @@
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: RecentlyAdded.cs
// File: RecentlyAddedModel.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
@ -114,7 +114,7 @@ namespace PlexRequests.Services.Jobs
public void Test()
{
StartDb(true);
Start(true);
}
private void Start(bool testEmail = false)
@ -122,18 +122,15 @@ namespace PlexRequests.Services.Jobs
var sb = new StringBuilder();
var plexSettings = PlexSettings.GetSettings();
var recentlyAdded = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri);
var libs = Api.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri);
var tvSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase));
var movieSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase));
var movies =
recentlyAdded._children.Where(x => x.type.Equals("Movie", StringComparison.CurrentCultureIgnoreCase));
var tv =
recentlyAdded._children.Where(
x => x.type.Equals("season", StringComparison.CurrentCultureIgnoreCase))
.GroupBy(x => x.parentTitle)
.Select(x => x.FirstOrDefault());
var recentlyAddedTv = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection.Key);
var recentlyAddedMovies = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, movieSection.Key);
GenerateMovieHtml(movies, plexSettings, ref sb);
GenerateTvHtml(tv, plexSettings, ref sb);
GenerateMovieHtml(recentlyAddedMovies, plexSettings, ref sb);
GenerateTvHtml(recentlyAddedTv, plexSettings, ref sb);
var template = new RecentlyAddedTemplate();
var html = template.LoadTemplate(sb.ToString());
@ -160,12 +157,12 @@ namespace PlexRequests.Services.Jobs
Send(html, plexSettings, testEmail);
}
private void GenerateMovieHtml(IEnumerable<RecentlyAddedChild> movies, PlexSettings plexSettings, ref StringBuilder sb)
private void GenerateMovieHtml(RecentlyAddedModel movies, PlexSettings plexSettings, ref StringBuilder sb)
{
sb.Append("<h1>New Movies:</h1><br/><br/>");
sb.Append(
"<table border=\"0\" cellpadding=\"0\" align=\"center\" cellspacing=\"0\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\" width=\"100%\">");
foreach (var movie in movies.OrderByDescending(x => x.addedAt))
foreach (var movie in movies._children.OrderByDescending(x => x.addedAt.UnixTimeStampToDateTime()))
{
var plexGUID = string.Empty;
try
@ -264,15 +261,14 @@ namespace PlexRequests.Services.Jobs
}
sb.Append("</table><br/><br/>");
}
[Obsolete("Use the new DB Version")]
private void GenerateTvHtml(IEnumerable<RecentlyAddedChild> tv, PlexSettings plexSettings, ref StringBuilder sb)
private void GenerateTvHtml(RecentlyAddedModel tv, PlexSettings plexSettings, ref StringBuilder sb)
{
// TV
sb.Append("<h1>New Episodes:</h1><br/><br/>");
sb.Append(
"<table border=\"0\" cellpadding=\"0\" align=\"center\" cellspacing=\"0\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\" width=\"100%\">");
foreach (var t in tv.OrderByDescending(x => x.addedAt))
foreach (var t in tv._children.OrderByDescending(x => x.addedAt.UnixTimeStampToDateTime()))
{
var plexGUID = string.Empty;
try
@ -298,12 +294,14 @@ namespace PlexRequests.Services.Jobs
sb.Append("<tr>");
sb.Append("<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
var title = $"{t.grandparentTitle} - {t.title} {t.originallyAvailableAt.Substring(0, 4)}";
sb.AppendFormat("<a href=\"https://www.imdb.com/title/{0}/\"><h3 style=\"font-family: sans-serif; font-weight: normal; margin: 0; Margin-bottom: 15px;\">{1} {2}</p></a>",
info.externals.imdb, info.name, info.premiered.Substring(0, 4)); // Only the year
info.externals.imdb, title); // Only the year
sb.AppendFormat("<p style=\"font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;\">Genre: {0}</p>", string.Join(", ", info.genres.Select(x => x.ToString()).ToArray()));
sb.AppendFormat("<p style=\"font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;\">{0}</p>",
string.IsNullOrEmpty(parentMetaData.Directory.Summary) ? info.summary : parentMetaData.Directory.Summary); // Episode Summary
string.IsNullOrEmpty(t.summary) ? info.summary : t.summary); // Episode Summary
sb.Append("<td");
sb.Append("<hr>");

@ -66,7 +66,7 @@ namespace PlexRequests.UI.Jobs
JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build(),
JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build(),
JobBuilder.Create<UserRequestLimitResetter>().WithIdentity("UserRequestLimiter", "Request").Build(),
JobBuilder.Create<RecentlyAdded>().WithIdentity("RecentlyAdded", "Email").Build()
JobBuilder.Create<RecentlyAdded>().WithIdentity("RecentlyAddedModel", "Email").Build()
};
@ -168,7 +168,7 @@ namespace PlexRequests.UI.Jobs
var rencentlyAdded =
TriggerBuilder.Create()
.WithIdentity("RecentlyAdded", "Email")
.WithIdentity("RecentlyAddedModel", "Email")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInHours(2).RepeatForever())
.Build();

@ -67,9 +67,6 @@ namespace PlexRequests.UI
Debug.WriteLine("Finished bootstrapper");
var scheduler = new Scheduler();
scheduler.StartScheduler();
var r = kernel.Get<IRecentlyAdded>();
r.Test();
}
catch (Exception exception)
{

@ -82,7 +82,7 @@
<div class="form-group">
<label for="RecentlyAdded" class="control-label">Recently Added Email (hours)</label>
<div>
<input type="text" class="form-control form-control-custom " id="RecentlyAdded" name="RecentlyAdded" value="@Model.RecentlyAdded">
<input type="text" class="form-control form-control-custom " id="RecentlyAdded" name="RecentlyAddedModel" value="@Model.RecentlyAddedModel">
</div>
</div>

Loading…
Cancel
Save