mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 04:49:33 -07:00
Merge remote-tracking branch 'refs/remotes/origin/dev'
Conflicts: PlexRequests.Services/Jobs/RecentlyAdded.cs
This commit is contained in:
commit
71446f0b59
34 changed files with 761 additions and 323 deletions
|
@ -44,6 +44,6 @@ namespace PlexRequests.Api.Interfaces
|
||||||
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);
|
||||||
PlexSeasonMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey);
|
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
|
#region Copyright
|
||||||
// /************************************************************************
|
// /************************************************************************
|
||||||
// Copyright (c) 2016 Jamie Rees
|
// Copyright (c) 2016 Jamie Rees
|
||||||
// File: RecentlyAdded.cs
|
// File: RecentlyAddedModel.cs
|
||||||
// Created By: Jamie Rees
|
// Created By: Jamie Rees
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
@ -32,53 +32,102 @@ namespace PlexRequests.Api.Models.Plex
|
||||||
public class RecentlyAddedChild
|
public class RecentlyAddedChild
|
||||||
{
|
{
|
||||||
public string _elementType { get; set; }
|
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 int ratingKey { get; set; }
|
||||||
public string key { get; set; }
|
public string key { get; set; }
|
||||||
public int parentRatingKey { get; set; }
|
public int parentRatingKey { get; set; }
|
||||||
|
public int grandparentRatingKey { get; set; }
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public string title { get; set; }
|
public string title { get; set; }
|
||||||
|
public string grandparentKey { get; set; }
|
||||||
public string parentKey { get; set; }
|
public string parentKey { get; set; }
|
||||||
public string parentTitle { get; set; }
|
public string grandparentTitle { get; set; }
|
||||||
public string parentSummary { get; set; }
|
|
||||||
public string summary { get; set; }
|
public string summary { get; set; }
|
||||||
public int index { get; set; }
|
public int index { get; set; }
|
||||||
public int parentIndex { get; set; }
|
public int parentIndex { get; set; }
|
||||||
public string thumb { get; set; }
|
public string thumb { get; set; }
|
||||||
public string art { get; set; }
|
public string art { get; set; }
|
||||||
public string parentThumb { get; set; }
|
public string grandparentThumb { get; set; }
|
||||||
public int leafCount { get; set; }
|
public string grandparentArt { get; set; }
|
||||||
public int viewedLeafCount { get; set; }
|
public int duration { get; set; }
|
||||||
public int addedAt { get; set; }
|
public int addedAt { get; set; }
|
||||||
public int updatedAt { get; set; }
|
public int updatedAt { get; set; }
|
||||||
public List<object> _children { get; set; }
|
public string chapterSource { get; set; }
|
||||||
public string studio { get; set; }
|
public List<Child2> _children { get; set; }
|
||||||
public string contentRating { get; set; }
|
public string contentRating { get; set; }
|
||||||
public string rating { get; set; }
|
public int? year { get; set; }
|
||||||
|
public string parentThumb { get; set; }
|
||||||
|
public string grandparentTheme { get; set; }
|
||||||
|
public string originallyAvailableAt { get; set; }
|
||||||
|
public string titleSort { get; set; }
|
||||||
public int? viewCount { get; set; }
|
public int? viewCount { get; set; }
|
||||||
public int? lastViewedAt { get; set; }
|
public int? lastViewedAt { get; set; }
|
||||||
public int? year { get; set; }
|
|
||||||
public int? duration { 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? viewOffset { 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 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 _elementType { get; set; }
|
||||||
public string allowSync { get; set; }
|
public string allowSync { get; set; }
|
||||||
|
public string art { get; set; }
|
||||||
public string identifier { 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 mediaTagPrefix { get; set; }
|
||||||
public string mediaTagVersion { get; set; }
|
public string mediaTagVersion { get; set; }
|
||||||
public string mixedParents { 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; }
|
public List<RecentlyAddedChild> _children { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -73,7 +73,7 @@
|
||||||
<Compile Include="Plex\PlexStatus.cs" />
|
<Compile Include="Plex\PlexStatus.cs" />
|
||||||
<Compile Include="Plex\PlexMediaType.cs" />
|
<Compile Include="Plex\PlexMediaType.cs" />
|
||||||
<Compile Include="Plex\PlexUserRequest.cs" />
|
<Compile Include="Plex\PlexUserRequest.cs" />
|
||||||
<Compile Include="Plex\RecentlyAdded.cs" />
|
<Compile Include="Plex\RecentlyAddedModel.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="SickRage\SickRageBase.cs" />
|
<Compile Include="SickRage\SickRageBase.cs" />
|
||||||
<Compile Include="SickRage\SickrageShows.cs" />
|
<Compile Include="SickRage\SickrageShows.cs" />
|
||||||
|
|
|
@ -1,79 +1,89 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PlexRequests.Api.Models.Tv
|
namespace PlexRequests.Api.Models.Tv
|
||||||
{
|
{
|
||||||
public class TvMazeShow
|
public class TvMazeShow
|
||||||
{
|
{
|
||||||
public int id { get; set; }
|
public TvMazeShow()
|
||||||
public string url { get; set; }
|
{
|
||||||
public string name { get; set; }
|
Season = new List<TvMazeCustomSeason>();
|
||||||
public string type { get; set; }
|
}
|
||||||
public string language { get; set; }
|
public int id { get; set; }
|
||||||
public List<string> genres { get; set; }
|
public string url { get; set; }
|
||||||
public string status { get; set; }
|
public string name { get; set; }
|
||||||
public int runtime { get; set; }
|
public string type { get; set; }
|
||||||
public string premiered { get; set; }
|
public string language { get; set; }
|
||||||
public Schedule schedule { get; set; }
|
public List<string> genres { get; set; }
|
||||||
public Rating rating { get; set; }
|
public string status { get; set; }
|
||||||
public int weight { get; set; }
|
public int runtime { get; set; }
|
||||||
public Network network { get; set; }
|
public string premiered { get; set; }
|
||||||
public object webChannel { get; set; }
|
public Schedule schedule { get; set; }
|
||||||
public Externals externals { get; set; }
|
public Rating rating { get; set; }
|
||||||
public Image image { get; set; }
|
public int weight { get; set; }
|
||||||
public string summary { get; set; }
|
public Network network { get; set; }
|
||||||
public int updated { get; set; }
|
public object webChannel { get; set; }
|
||||||
public Links _links { get; set; }
|
public Externals externals { get; set; }
|
||||||
public int seasonCount { get; set; }
|
public Image image { get; set; }
|
||||||
public Embedded _embedded { get; set; }
|
public string summary { get; set; }
|
||||||
}
|
public int updated { get; set; }
|
||||||
|
public Links _links { get; set; }
|
||||||
public class Season
|
public List<TvMazeCustomSeason> Season { get; set; }
|
||||||
{
|
public Embedded _embedded { get; set; }
|
||||||
public int id { get; set; }
|
}
|
||||||
public string url { get; set; }
|
|
||||||
public int number { get; set; }
|
public class TvMazeCustomSeason
|
||||||
public string name { get; set; }
|
{
|
||||||
public int? episodeOrder { get; set; }
|
public int SeasonNumber { get; set; }
|
||||||
public string premiereDate { get; set; }
|
public int EpisodeNumber { get; set; }
|
||||||
public string endDate { get; set; }
|
}
|
||||||
public Network2 network { get; set; }
|
|
||||||
public object webChannel { get; set; }
|
public class Season
|
||||||
public Image2 image { get; set; }
|
{
|
||||||
public string summary { get; set; }
|
public int id { get; set; }
|
||||||
public Links2 _links { get; set; }
|
public string url { get; set; }
|
||||||
}
|
public int number { get; set; }
|
||||||
public class Country2
|
public string name { get; set; }
|
||||||
{
|
public int? episodeOrder { get; set; }
|
||||||
public string name { get; set; }
|
public string premiereDate { get; set; }
|
||||||
public string code { get; set; }
|
public string endDate { get; set; }
|
||||||
public string timezone { get; set; }
|
public Network2 network { get; set; }
|
||||||
}
|
public object webChannel { get; set; }
|
||||||
|
public Image2 image { get; set; }
|
||||||
public class Network2
|
public string summary { get; set; }
|
||||||
{
|
public Links2 _links { get; set; }
|
||||||
public int id { get; set; }
|
}
|
||||||
public string name { get; set; }
|
public class Country2
|
||||||
public Country2 country { get; set; }
|
{
|
||||||
}
|
public string name { get; set; }
|
||||||
|
public string code { get; set; }
|
||||||
public class Image2
|
public string timezone { get; set; }
|
||||||
{
|
}
|
||||||
public string medium { get; set; }
|
|
||||||
public string original { get; set; }
|
public class Network2
|
||||||
}
|
{
|
||||||
|
public int id { get; set; }
|
||||||
public class Self2
|
public string name { get; set; }
|
||||||
{
|
public Country2 country { get; set; }
|
||||||
public string href { get; set; }
|
}
|
||||||
}
|
|
||||||
|
public class Image2
|
||||||
public class Links2
|
{
|
||||||
{
|
public string medium { get; set; }
|
||||||
public Self2 self { get; set; }
|
public string original { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Embedded
|
public class Self2
|
||||||
{
|
{
|
||||||
public List<Season> seasons { get; set; }
|
public string href { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Links2
|
||||||
|
{
|
||||||
|
public Self2 self { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Embedded
|
||||||
|
{
|
||||||
|
public List<Season> seasons { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -76,7 +76,7 @@ namespace PlexRequests.Api
|
||||||
Method = Method.POST
|
Method = Method.POST
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request);
|
AddHeaders(ref request, false);
|
||||||
|
|
||||||
request.AddJsonBody(userModel);
|
request.AddJsonBody(userModel);
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ namespace PlexRequests.Api
|
||||||
Method = Method.GET,
|
Method = Method.GET,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
var users = RetryHandler.Execute(() => Api.ExecuteXml<PlexFriends> (request, new Uri(FriendsUri)),
|
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);
|
(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);
|
request.AddUrlSegment("searchTerm", searchTerm);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
var search = RetryHandler.Execute(() => Api.ExecuteXml<PlexSearch> (request, plexFullHost),
|
var search = RetryHandler.Execute(() => Api.ExecuteXml<PlexSearch> (request, plexFullHost),
|
||||||
(exception, timespan) => Log.Error (exception, "Exception when calling SearchContent for Plex, Retrying {0}", timespan), null);
|
(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,
|
Method = Method.GET,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
var users = RetryHandler.Execute(() => Api.ExecuteXml<PlexStatus> (request, uri),
|
var users = RetryHandler.Execute(() => Api.ExecuteXml<PlexStatus> (request, uri),
|
||||||
(exception, timespan) => Log.Error (exception, "Exception when calling GetStatus for Plex, Retrying {0}", timespan), null);
|
(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,
|
Method = Method.GET,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
var account = RetryHandler.Execute(() => Api.ExecuteXml<PlexAccount> (request, new Uri(GetAccountUri)),
|
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);
|
(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"
|
Resource = "library/sections"
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ namespace PlexRequests.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddUrlSegment("libraryId", libraryId);
|
request.AddUrlSegment("libraryId", libraryId);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -228,7 +228,7 @@ namespace PlexRequests.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddUrlSegment("ratingKey", ratingKey);
|
request.AddUrlSegment("ratingKey", ratingKey);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -253,10 +253,9 @@ namespace PlexRequests.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddQueryParameter("type", 4.ToString());
|
request.AddQueryParameter("type", 4.ToString());
|
||||||
request.AddQueryParameter("X-Plex-Container-Start", startPage.ToString());
|
AddLimitHeaders(ref request, startPage, returnCount);
|
||||||
request.AddQueryParameter("X-Plex-Container-Size", returnCount.ToString());
|
|
||||||
request.AddUrlSegment("section", section);
|
request.AddUrlSegment("section", section);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -281,7 +280,7 @@ namespace PlexRequests.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddUrlSegment("itemId", itemId);
|
request.AddUrlSegment("itemId", itemId);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -311,7 +310,7 @@ namespace PlexRequests.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddUrlSegment("ratingKey", ratingKey);
|
request.AddUrlSegment("ratingKey", ratingKey);
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -338,7 +337,7 @@ namespace PlexRequests.Api
|
||||||
Method = Method.GET,
|
Method = Method.GET,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddHeaders(ref request, authToken);
|
AddHeaders(ref request, authToken, false);
|
||||||
|
|
||||||
var servers = RetryHandler.Execute(() => Api.ExecuteXml<PlexServer>(request, new Uri(ServerUri)),
|
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));
|
(exception, timespan) => Log.Error(exception, "Exception when calling GetServer for Plex, Retrying {0}", timespan));
|
||||||
|
@ -347,25 +346,22 @@ namespace PlexRequests.Api
|
||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecentlyAdded RecentlyAdded(string authToken, Uri plexFullHost)
|
public RecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId)
|
||||||
{
|
{
|
||||||
var request = new RestRequest
|
var request = new RestRequest
|
||||||
{
|
{
|
||||||
Method = Method.GET,
|
Method = Method.GET,
|
||||||
Resource = "library/recentlyAdded"
|
Resource = "library/sections/{sectionId}/recentlyAdded"
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddHeader("X-Plex-Token", authToken);
|
request.AddUrlSegment("sectionId", sectionId);
|
||||||
request.AddHeader("X-Plex-Client-Identifier", $"PlexRequests.Net{Version}");
|
AddHeaders(ref request, authToken, true);
|
||||||
request.AddHeader("X-Plex-Product", "Plex Requests .Net");
|
AddLimitHeaders(ref request, 0, 25);
|
||||||
request.AddHeader("X-Plex-Version", Version);
|
|
||||||
request.AddHeader("Content-Type", "application/json");
|
|
||||||
request.AddHeader("Accept", "application/json");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var lib = RetryHandler.Execute(() => Api.ExecuteJson<RecentlyAdded>(request, plexFullHost),
|
var lib = RetryHandler.Execute(() => Api.ExecuteJson<RecentlyAddedModel>(request, plexFullHost),
|
||||||
(exception, timespan) => Log.Error(exception, "Exception when calling RecentlyAdded for Plex, Retrying {0}", timespan), new[] {
|
(exception, timespan) => Log.Error(exception, "Exception when calling RecentlyAddedModel for Plex, Retrying {0}", timespan), new[] {
|
||||||
TimeSpan.FromSeconds (5),
|
TimeSpan.FromSeconds (5),
|
||||||
TimeSpan.FromSeconds(10),
|
TimeSpan.FromSeconds(10),
|
||||||
TimeSpan.FromSeconds(30)
|
TimeSpan.FromSeconds(30)
|
||||||
|
@ -375,23 +371,30 @@ namespace PlexRequests.Api
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAdded");
|
Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAddedModel");
|
||||||
return new RecentlyAdded();
|
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-Token", authToken);
|
request.AddHeader("X-Plex-Container-Start", from.ToString());
|
||||||
AddHeaders(ref request);
|
request.AddHeader("X-Plex-Container-Size", to.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddHeaders(ref RestRequest request)
|
private void AddHeaders(ref RestRequest request, string authToken, bool json)
|
||||||
|
{
|
||||||
|
request.AddHeader("X-Plex-Token", authToken);
|
||||||
|
AddHeaders(ref request, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddHeaders(ref RestRequest request, bool json)
|
||||||
{
|
{
|
||||||
request.AddHeader("X-Plex-Client-Identifier", $"PlexRequests.Net{Version}");
|
request.AddHeader("X-Plex-Client-Identifier", $"PlexRequests.Net{Version}");
|
||||||
request.AddHeader("X-Plex-Product", "Plex Requests .Net");
|
request.AddHeader("X-Plex-Product", "Plex Requests .Net");
|
||||||
request.AddHeader("X-Plex-Version", Version);
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,9 @@
|
||||||
<Reference Include="Nancy, Version=1.4.2.0, Culture=neutral, PublicKeyToken=null">
|
<Reference Include="Nancy, Version=1.4.2.0, Culture=neutral, PublicKeyToken=null">
|
||||||
<HintPath>..\packages\Nancy.1.4.3\lib\net40\Nancy.dll</HintPath>
|
<HintPath>..\packages\Nancy.1.4.3\lib\net40\Nancy.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="TMDbLib, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null">
|
<Reference Include="TMDbLib, Version=0.9.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath>
|
<HintPath>..\packages\TMDbLib.0.9.6.0-alpha\lib\net45\TMDbLib.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -122,7 +122,7 @@ namespace PlexRequests.Api
|
||||||
});
|
});
|
||||||
|
|
||||||
result = policy.Execute(() => Api.ExecuteJson<SonarrAddSeries>(request, baseUrl));
|
result = policy.Execute(() => Api.ExecuteJson<SonarrAddSeries>(request, baseUrl));
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException jse)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
Log.Error(jse);
|
Log.Error(jse);
|
||||||
|
|
|
@ -46,44 +46,44 @@ namespace PlexRequests.Api
|
||||||
public TMDbClient Client { get; set; }
|
public TMDbClient Client { get; set; }
|
||||||
public async Task<List<SearchMovie>> SearchMovie(string searchTerm)
|
public async Task<List<SearchMovie>> SearchMovie(string searchTerm)
|
||||||
{
|
{
|
||||||
var results = await Client.SearchMovie(searchTerm);
|
var results = await Client.SearchMovieAsync(searchTerm);
|
||||||
return results.Results;
|
return results.Results;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Should use TvMaze for TV")]
|
[Obsolete("Should use TvMaze for TV")]
|
||||||
public async Task<List<SearchTv>> SearchTv(string searchTerm)
|
public async Task<List<SearchTv>> SearchTv(string searchTerm)
|
||||||
{
|
{
|
||||||
var results = await Client.SearchTvShow(searchTerm);
|
var results = await Client.SearchTvShowAsync(searchTerm);
|
||||||
return results.Results;
|
return results.Results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MovieResult>> GetCurrentPlayingMovies()
|
public async Task<List<SearchMovie>> GetCurrentPlayingMovies()
|
||||||
{
|
{
|
||||||
var movies = await Client.GetMovieList(MovieListType.NowPlaying);
|
var movies = await Client.GetMovieNowPlayingListAsync();
|
||||||
return movies.Results;
|
return movies.Results;
|
||||||
}
|
}
|
||||||
public async Task<List<MovieResult>> GetUpcomingMovies()
|
public async Task<List<SearchMovie>> GetUpcomingMovies()
|
||||||
{
|
{
|
||||||
var movies = await Client.GetMovieList(MovieListType.Upcoming);
|
var movies = await Client.GetMovieUpcomingListAsync();
|
||||||
return movies.Results;
|
return movies.Results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Movie> GetMovieInformation(int tmdbId)
|
public async Task<Movie> GetMovieInformation(int tmdbId)
|
||||||
{
|
{
|
||||||
var movies = await Client.GetMovie(tmdbId);
|
var movies = await Client.GetMovieAsync(tmdbId);
|
||||||
return movies;
|
return movies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Movie> GetMovieInformation(string imdbId)
|
public async Task<Movie> GetMovieInformation(string imdbId)
|
||||||
{
|
{
|
||||||
var movies = await Client.GetMovie(imdbId);
|
var movies = await Client.GetMovieAsync(imdbId);
|
||||||
return movies;
|
return movies;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Should use TvMaze for TV")]
|
[Obsolete("Should use TvMaze for TV")]
|
||||||
public async Task<TvShow> GetTvShowInformation(int tmdbId)
|
public async Task<TvShow> GetTvShowInformation(int tmdbId)
|
||||||
{
|
{
|
||||||
var show = await Client.GetTvShow(tmdbId);
|
var show = await Client.GetTvShowAsync(tmdbId);
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,18 @@ namespace PlexRequests.Api
|
||||||
request.AddHeader("Content-Type", "application/json");
|
request.AddHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
var obj = Api.Execute<TvMazeShow>(request, new Uri(Uri));
|
var obj = Api.Execute<TvMazeShow>(request, new Uri(Uri));
|
||||||
obj.seasonCount = GetSeasonCount(obj.id);
|
|
||||||
|
|
||||||
|
var episodes = EpisodeLookup(obj.id).ToList();
|
||||||
|
|
||||||
|
foreach (var e in episodes)
|
||||||
|
{
|
||||||
|
obj.Season.Add(new TvMazeCustomSeason
|
||||||
|
{
|
||||||
|
SeasonNumber = e.season,
|
||||||
|
EpisodeNumber = e.number
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +120,7 @@ namespace PlexRequests.Api
|
||||||
|
|
||||||
return Api.Execute<List<TvMazeSeasons>>(request, new Uri(Uri));
|
return Api.Execute<List<TvMazeSeasons>>(request, new Uri(Uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetSeasonCount(int id)
|
public int GetSeasonCount(int id)
|
||||||
{
|
{
|
||||||
var obj = GetSeasons(id);
|
var obj = GetSeasons(id);
|
||||||
|
|
|
@ -6,5 +6,6 @@
|
||||||
<package id="NLog" version="4.3.6" targetFramework="net45" />
|
<package id="NLog" version="4.3.6" targetFramework="net45" />
|
||||||
<package id="Polly-Signed" version="4.3.0" targetFramework="net45" />
|
<package id="Polly-Signed" version="4.3.0" targetFramework="net45" />
|
||||||
<package id="RestSharp" version="105.2.3" targetFramework="net45" />
|
<package id="RestSharp" version="105.2.3" targetFramework="net45" />
|
||||||
<package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" />
|
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" />
|
||||||
|
<package id="TMDbLib" version="0.9.6.0-alpha" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Store;
|
using PlexRequests.Store;
|
||||||
using PlexRequests.Store.Models.Plex;
|
using PlexRequests.Store.Models.Plex;
|
||||||
|
@ -44,7 +45,8 @@ namespace PlexRequests.Core
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride))
|
if (!string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride))
|
||||||
{
|
{
|
||||||
Plex.DbLocation = settings.PlexDatabaseLocationOverride;
|
//Overriden setting
|
||||||
|
Plex.DbLocation = Path.Combine(settings.PlexDatabaseLocationOverride, "Plug-in Support", "Databases", "com.plexapp.plugins.library.db");
|
||||||
}
|
}
|
||||||
else if (Type.GetType("Mono.Runtime") != null)
|
else if (Type.GetType("Mono.Runtime") != null)
|
||||||
{
|
{
|
||||||
|
@ -61,8 +63,20 @@ namespace PlexRequests.Core
|
||||||
|
|
||||||
public IEnumerable<MetadataItems> GetItemsAddedAfterDate(DateTime dateTime)
|
public IEnumerable<MetadataItems> GetItemsAddedAfterDate(DateTime dateTime)
|
||||||
{
|
{
|
||||||
return Plex.QueryMetadataItems("select * from metadata_items where added_at > @AddedAt",
|
// type 1 = Movie, type 4 = TV Episode
|
||||||
new { AddedAt = dateTime });
|
var movies = Plex.QueryMetadataItems(@"SELECT * FROM metadata_items
|
||||||
|
WHERE added_at > @AddedAt
|
||||||
|
AND metadata_type = 1
|
||||||
|
AND title <> ''", new { AddedAt = dateTime });
|
||||||
|
|
||||||
|
// Custom query to include the series title
|
||||||
|
var tv = Plex.QueryMetadataItems(@"SELECT series.title AS SeriesTitle, mi.* FROM metadata_items mi
|
||||||
|
INNER JOIN metadata_items season ON mi.parent_id = season.id
|
||||||
|
INNER JOIN metadata_items series ON series.id = season.parent_id
|
||||||
|
WHERE mi.added_at > @AddedAt
|
||||||
|
AND mi.metadata_type = 4", new { AddedAt = dateTime });
|
||||||
|
|
||||||
|
return movies.Union(tv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,42 +1,50 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace PlexRequests.Helpers
|
namespace PlexRequests.Helpers
|
||||||
{
|
{
|
||||||
public static class DateTimeHelper
|
public static class DateTimeHelper
|
||||||
{
|
{
|
||||||
public static DateTimeOffset OffsetUTCDateTime(DateTime utcDateTime, int minuteOffset)
|
public static DateTimeOffset OffsetUTCDateTime(DateTime utcDateTime, int minuteOffset)
|
||||||
{
|
{
|
||||||
//TimeSpan ts = TimeSpan.FromMinutes(-minuteOffset);
|
//TimeSpan ts = TimeSpan.FromMinutes(-minuteOffset);
|
||||||
//return new DateTimeOffset(utcDateTime).ToOffset(ts);
|
//return new DateTimeOffset(utcDateTime).ToOffset(ts);
|
||||||
|
|
||||||
// this is a workaround below to work with MONO
|
// this is a workaround below to work with MONO
|
||||||
var tzi = FindTimeZoneFromOffset(minuteOffset);
|
var tzi = FindTimeZoneFromOffset(minuteOffset);
|
||||||
var utcOffset = tzi.GetUtcOffset(utcDateTime);
|
var utcOffset = tzi.GetUtcOffset(utcDateTime);
|
||||||
var newDate = utcDateTime + utcOffset;
|
var newDate = utcDateTime + utcOffset;
|
||||||
return new DateTimeOffset(newDate.Ticks, utcOffset);
|
return new DateTimeOffset(newDate.Ticks, utcOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CustomParse(string date, out DateTime dt)
|
public static void CustomParse(string date, out DateTime dt)
|
||||||
{
|
{
|
||||||
// Try and parse it
|
// Try and parse it
|
||||||
if (DateTime.TryParse(date, out dt))
|
if (DateTime.TryParse(date, out dt))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maybe it's only a year?
|
// Maybe it's only a year?
|
||||||
if (DateTime.TryParseExact(date, "yyyy", CultureInfo.CurrentCulture, DateTimeStyles.None, out dt))
|
if (DateTime.TryParseExact(date, "yyyy", CultureInfo.CurrentCulture, DateTimeStyles.None, out dt))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeZoneInfo FindTimeZoneFromOffset(int minuteOffset)
|
private static TimeZoneInfo FindTimeZoneFromOffset(int minuteOffset)
|
||||||
{
|
{
|
||||||
var tzc = TimeZoneInfo.GetSystemTimeZones();
|
var tzc = TimeZoneInfo.GetSystemTimeZones();
|
||||||
return tzc.FirstOrDefault(x => x.BaseUtcOffset.TotalMinutes == -minuteOffset);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -102,6 +102,12 @@ namespace PlexRequests.Helpers
|
||||||
$"https://app.plex.tv/web/app#!/server/{machineId}/details/%2Flibrary%2Fmetadata%2F{mediaId}";
|
$"https://app.plex.tv/web/app#!/server/{machineId}/details/%2Flibrary%2Fmetadata%2F{mediaId}";
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FormatGenres(string tags)
|
||||||
|
{
|
||||||
|
var split = tags.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
return string.Join(", ", split);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EpisodeModelHelper
|
public class EpisodeModelHelper
|
||||||
|
|
71
PlexRequests.Services/Jobs/HtmlTemplateGenerator.cs
Normal file
71
PlexRequests.Services/Jobs/HtmlTemplateGenerator.cs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: HtmlTemplateGenerator.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// 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.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web.UI;
|
||||||
|
|
||||||
|
namespace PlexRequests.Services.Jobs
|
||||||
|
{
|
||||||
|
public abstract class HtmlTemplateGenerator
|
||||||
|
{
|
||||||
|
protected virtual void AddParagraph(ref StringBuilder stringBuilder, string text, int fontSize = 14, string fontWeight = "normal")
|
||||||
|
{
|
||||||
|
stringBuilder.AppendFormat("<p style=\"font-family: sans-serif; font-size: {1}px; font-weight: {2}; margin: 0; Margin-bottom: 15px;\">{0}</p>", text, fontSize, fontWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void AddImageInsideTable(ref StringBuilder sb, string url)
|
||||||
|
{
|
||||||
|
sb.Append("<tr>");
|
||||||
|
sb.Append("<td align=\"center\">");
|
||||||
|
sb.AppendFormat(
|
||||||
|
"<img src=\"{0}\" width=\"400px\" text-align=\"center\" />",
|
||||||
|
url);
|
||||||
|
sb.Append("</td>");
|
||||||
|
sb.Append("</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Href(ref StringBuilder sb, string url)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("<a href=\"{0}\">", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void EndTag(ref StringBuilder sb, string tag)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("</{0}>", tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Header(ref StringBuilder sb, int size, string text, string fontWeight = "normal")
|
||||||
|
{
|
||||||
|
sb.AppendFormat(
|
||||||
|
"<h{0} style=\"font-family: sans-serif; font-weight: {2}; margin: 0; Margin-bottom: 15px;\">{1}</h{0}>",
|
||||||
|
size, text, fontWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -123,12 +123,13 @@ namespace PlexRequests.Services.Jobs
|
||||||
case RequestType.TvShow:
|
case RequestType.TvShow:
|
||||||
if (!plexSettings.EnableTvEpisodeSearching)
|
if (!plexSettings.EnableTvEpisodeSearching)
|
||||||
{
|
{
|
||||||
matchResult = IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId);
|
matchResult = IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
matchResult =
|
matchResult = r.Episodes.Any() ?
|
||||||
r.Episodes.All(x => IsEpisodeAvailable(r.TvDbId, x.SeasonNumber, x.EpisodeNumber));
|
r.Episodes.All(x => IsEpisodeAvailable(r.TvDbId, x.SeasonNumber, x.EpisodeNumber)) :
|
||||||
|
IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RequestType.Album:
|
case RequestType.Album:
|
||||||
|
@ -270,7 +271,7 @@ namespace PlexRequests.Services.Jobs
|
||||||
{
|
{
|
||||||
if (advanced)
|
if (advanced)
|
||||||
{
|
{
|
||||||
if (seasons != null && show.ProviderId == providerId)
|
if (show.ProviderId == providerId && seasons != null)
|
||||||
{
|
{
|
||||||
if (seasons.Any(season => show.Seasons.Contains(season)))
|
if (seasons.Any(season => show.Seasons.Contains(season)))
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,6 +112,10 @@ namespace PlexRequests.Services.Jobs
|
||||||
// Loop through the metadata and create the model to insert into the DB
|
// Loop through the metadata and create the model to insert into the DB
|
||||||
foreach (var metadataVideo in metadata.Video)
|
foreach (var metadataVideo in metadata.Video)
|
||||||
{
|
{
|
||||||
|
if(string.IsNullOrEmpty(metadataVideo.GrandparentTitle))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var epInfo = PlexHelper.GetSeasonsAndEpisodesFromPlexGuid(metadataVideo.Guid);
|
var epInfo = PlexHelper.GetSeasonsAndEpisodesFromPlexGuid(metadataVideo.Guid);
|
||||||
entities.TryAdd(
|
entities.TryAdd(
|
||||||
new PlexEpisodes
|
new PlexEpisodes
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// /************************************************************************
|
// /************************************************************************
|
||||||
// Copyright (c) 2016 Jamie Rees
|
// Copyright (c) 2016 Jamie Rees
|
||||||
// File: RecentlyAdded.cs
|
// File: RecentlyAddedModel.cs
|
||||||
// Created By: Jamie Rees
|
// Created By: Jamie Rees
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
@ -42,15 +42,19 @@ using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
using PlexRequests.Helpers;
|
||||||
using PlexRequests.Services.Interfaces;
|
using PlexRequests.Services.Interfaces;
|
||||||
using PlexRequests.Services.Jobs.Templates;
|
using PlexRequests.Services.Jobs.Templates;
|
||||||
|
using PlexRequests.Store.Models.Plex;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
|
|
||||||
|
|
||||||
namespace PlexRequests.Services.Jobs
|
namespace PlexRequests.Services.Jobs
|
||||||
{
|
{
|
||||||
public class RecentlyAdded : IJob, IRecentlyAdded
|
public class RecentlyAdded : HtmlTemplateGenerator, IJob, IRecentlyAdded
|
||||||
{
|
{
|
||||||
public RecentlyAdded(IPlexApi api, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmailNotificationSettings> email,
|
public RecentlyAdded(IPlexApi api, ISettingsService<PlexSettings> plexSettings,
|
||||||
ISettingsService<ScheduledJobsSettings> scheduledService, IJobRecord rec, ISettingsService<NewletterSettings> newsletter)
|
ISettingsService<EmailNotificationSettings> email,
|
||||||
|
ISettingsService<ScheduledJobsSettings> scheduledService, IJobRecord rec,
|
||||||
|
ISettingsService<NewletterSettings> newsletter,
|
||||||
|
IPlexReadOnlyDatabase db)
|
||||||
{
|
{
|
||||||
JobRecord = rec;
|
JobRecord = rec;
|
||||||
Api = api;
|
Api = api;
|
||||||
|
@ -58,16 +62,20 @@ namespace PlexRequests.Services.Jobs
|
||||||
EmailSettings = email;
|
EmailSettings = email;
|
||||||
ScheduledJobsSettings = scheduledService;
|
ScheduledJobsSettings = scheduledService;
|
||||||
NewsletterSettings = newsletter;
|
NewsletterSettings = newsletter;
|
||||||
|
PlexDb = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IPlexApi Api { get; }
|
private IPlexApi Api { get; }
|
||||||
private TvMazeApi TvApi = new TvMazeApi();
|
private TvMazeApi TvApi = new TvMazeApi();
|
||||||
private readonly TheMovieDbApi _movieApi = new TheMovieDbApi();
|
private readonly TheMovieDbApi _movieApi = new TheMovieDbApi();
|
||||||
|
private const int MetadataTypeTv = 4;
|
||||||
|
private const int MetadataTypeMovie = 1;
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
private ISettingsService<EmailNotificationSettings> EmailSettings { get; }
|
private ISettingsService<EmailNotificationSettings> EmailSettings { get; }
|
||||||
private ISettingsService<NewletterSettings> NewsletterSettings { get; }
|
private ISettingsService<NewletterSettings> NewsletterSettings { get; }
|
||||||
private ISettingsService<ScheduledJobsSettings> ScheduledJobsSettings { get; }
|
private ISettingsService<ScheduledJobsSettings> ScheduledJobsSettings { get; }
|
||||||
private IJobRecord JobRecord { get; }
|
private IJobRecord JobRecord { get; }
|
||||||
|
private IPlexReadOnlyDatabase PlexDb { get; }
|
||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
@ -114,18 +122,15 @@ namespace PlexRequests.Services.Jobs
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
var plexSettings = PlexSettings.GetSettings();
|
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 =
|
var recentlyAddedTv = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection.Key);
|
||||||
recentlyAdded._children.Where(x => x.type.Equals("Movie", StringComparison.CurrentCultureIgnoreCase));
|
var recentlyAddedMovies = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, movieSection.Key);
|
||||||
var tv =
|
|
||||||
recentlyAdded._children.Where(
|
|
||||||
x => x.type.Equals("season", StringComparison.CurrentCultureIgnoreCase))
|
|
||||||
.GroupBy(x => x.parentTitle)
|
|
||||||
.Select(x => x.FirstOrDefault());
|
|
||||||
|
|
||||||
GenerateMovieHtml(movies, plexSettings, ref sb);
|
GenerateMovieHtml(recentlyAddedMovies, plexSettings, ref sb);
|
||||||
GenerateTvHtml(tv, plexSettings, ref sb);
|
GenerateTvHtml(recentlyAddedTv, plexSettings, ref sb);
|
||||||
|
|
||||||
var template = new RecentlyAddedTemplate();
|
var template = new RecentlyAddedTemplate();
|
||||||
var html = template.LoadTemplate(sb.ToString());
|
var html = template.LoadTemplate(sb.ToString());
|
||||||
|
@ -133,13 +138,31 @@ namespace PlexRequests.Services.Jobs
|
||||||
Send(html, plexSettings, testEmail);
|
Send(html, plexSettings, testEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateMovieHtml(IEnumerable<RecentlyAddedChild> movies, PlexSettings plexSettings,
|
private void StartDb(bool testEmail = false)
|
||||||
ref StringBuilder sb)
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var plexSettings = PlexSettings.GetSettings();
|
||||||
|
|
||||||
|
var recentlyAdded = PlexDb.GetItemsAddedAfterDate(DateTime.Now.AddDays(-12)).ToList(); // TODO Date configurable
|
||||||
|
|
||||||
|
var movies = recentlyAdded.Where(x => x.metadata_type == MetadataTypeMovie);
|
||||||
|
var tv = recentlyAdded.Where(x => x.metadata_type == MetadataTypeTv);
|
||||||
|
|
||||||
|
GenerateMovieHtml(movies, ref sb);
|
||||||
|
GenerateTvHtml(tv, ref sb);
|
||||||
|
|
||||||
|
var template = new RecentlyAddedTemplate();
|
||||||
|
var html = template.LoadTemplate(sb.ToString());
|
||||||
|
|
||||||
|
Send(html, plexSettings, testEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateMovieHtml(RecentlyAddedModel movies, PlexSettings plexSettings, ref StringBuilder sb)
|
||||||
{
|
{
|
||||||
sb.Append("<h1>New Movies:</h1><br/><br/>");
|
sb.Append("<h1>New Movies:</h1><br/><br/>");
|
||||||
sb.Append(
|
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%\">");
|
"<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)
|
foreach (var movie in movies._children.OrderByDescending(x => x.addedAt.UnixTimeStampToDateTime()))
|
||||||
{
|
{
|
||||||
var plexGUID = string.Empty;
|
var plexGUID = string.Empty;
|
||||||
try
|
try
|
||||||
|
@ -152,36 +175,24 @@ namespace PlexRequests.Services.Jobs
|
||||||
var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID);
|
var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID);
|
||||||
var info = _movieApi.GetMovieInformation(imdbId).Result;
|
var info = _movieApi.GetMovieInformation(imdbId).Result;
|
||||||
|
|
||||||
sb.Append("<tr>");
|
AddImageInsideTable(ref sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
|
||||||
sb.Append("<td align=\"center\">");
|
|
||||||
sb.AppendFormat(
|
|
||||||
"<img src=\"https://image.tmdb.org/t/p/w500{0}\" width=\"400px\" text-align=\"center\" />",
|
|
||||||
info.BackdropPath);
|
|
||||||
sb.Append("</td>");
|
|
||||||
sb.Append("</tr>");
|
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
sb.Append(
|
sb.Append(
|
||||||
"<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
"<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
||||||
|
|
||||||
sb.AppendFormat(
|
Href(ref sb, $"https://www.imdb.com/title/{info.ImdbId}/");
|
||||||
"<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>",
|
Header(ref sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}");
|
||||||
info.ImdbId, info.Title, info.ReleaseDate?.ToString("yyyy") ?? string.Empty);
|
EndTag(ref sb, "a");
|
||||||
|
|
||||||
if (info.Genres.Any())
|
if (info.Genres.Any())
|
||||||
{
|
{
|
||||||
sb.AppendFormat(
|
AddParagraph(ref sb, $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}");
|
||||||
"<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.Name.ToString()).ToArray()));
|
|
||||||
}
|
}
|
||||||
sb.AppendFormat(
|
|
||||||
"<p style=\"font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;\">{0}</p>",
|
|
||||||
info.Overview);
|
|
||||||
|
|
||||||
sb.Append("<td");
|
AddParagraph(ref sb, info.Overview);
|
||||||
sb.Append("<hr>");
|
|
||||||
sb.Append("<br>");
|
EndLoopHtml(ref sb);
|
||||||
sb.Append("<br>");
|
|
||||||
sb.Append("</tr>");
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -193,13 +204,71 @@ namespace PlexRequests.Services.Jobs
|
||||||
sb.Append("</table><br/><br/>");
|
sb.Append("</table><br/><br/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateTvHtml(IEnumerable<RecentlyAddedChild> tv, PlexSettings plexSettings, ref StringBuilder sb)
|
private void GenerateMovieHtml(IEnumerable<MetadataItems> movies, ref StringBuilder sb)
|
||||||
|
{
|
||||||
|
var items = movies as MetadataItems[] ?? movies.ToArray();
|
||||||
|
if (!items.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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 items.OrderByDescending(x => x.added_at))
|
||||||
|
{
|
||||||
|
var plexGUID = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plexGUID = movie.guid;
|
||||||
|
|
||||||
|
var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID);
|
||||||
|
|
||||||
|
var info = _movieApi.GetMovieInformation(imdbId).Result; // TODO remove this and get the image info from Plex https://github.com/jakewaldron/PlexEmail/blob/master/scripts/plexEmail.py#L391
|
||||||
|
|
||||||
|
AddImageInsideTable(ref sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
|
||||||
|
|
||||||
|
sb.Append("<tr>");
|
||||||
|
sb.Append("<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
||||||
|
|
||||||
|
Href(ref sb, $"https://www.imdb.com/title/{info.ImdbId}/");
|
||||||
|
var title = string.IsNullOrEmpty(movie.original_title)
|
||||||
|
? $"{movie.title} {movie.originally_available_at:yyyy}"
|
||||||
|
: $"{movie.original_title} AKA {movie.title} {movie.originally_available_at:yyyy}";
|
||||||
|
|
||||||
|
Header(ref sb, 3, title);
|
||||||
|
EndTag(ref sb, "a");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(movie.tagline))
|
||||||
|
{
|
||||||
|
AddParagraph(ref sb, movie.tagline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(movie.tags_genre))
|
||||||
|
{
|
||||||
|
AddParagraph(ref sb, $"Genre: {PlexHelper.FormatGenres(movie.tags_genre)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
AddParagraph(ref sb, movie.summary);
|
||||||
|
|
||||||
|
EndLoopHtml(ref sb);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
Log.Error("Exception when trying to process a Movie, either in getting the metadata from Plex OR getting the information from TheMovieDB, Plex GUID = {0}", plexGUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
sb.Append("</table><br/><br/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateTvHtml(RecentlyAddedModel tv, PlexSettings plexSettings, ref StringBuilder sb)
|
||||||
{
|
{
|
||||||
// TV
|
// TV
|
||||||
sb.Append("<h1>New Episodes:</h1><br/><br/>");
|
sb.Append("<h1>New Episodes:</h1><br/><br/>");
|
||||||
sb.Append(
|
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%\">");
|
"<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)
|
foreach (var t in tv._children.OrderByDescending(x => x.addedAt.UnixTimeStampToDateTime()))
|
||||||
{
|
{
|
||||||
var plexGUID = string.Empty;
|
var plexGUID = string.Empty;
|
||||||
try
|
try
|
||||||
|
@ -225,12 +294,83 @@ namespace PlexRequests.Services.Jobs
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
sb.Append("<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
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>",
|
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;\">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>",
|
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>");
|
||||||
|
sb.Append("<br>");
|
||||||
|
sb.Append("<br>");
|
||||||
|
sb.Append("</tr>");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
Log.Error("Exception when trying to process a TV Show, either in getting the metadata from Plex OR getting the information from TVMaze, Plex GUID = {0}", plexGUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.Append("</table><br/><br/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateTvHtml(IEnumerable<MetadataItems> tv, ref StringBuilder sb)
|
||||||
|
{
|
||||||
|
var items = tv as MetadataItems[] ?? tv.ToArray();
|
||||||
|
if (!items.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 items.OrderByDescending(x => x.added_at))
|
||||||
|
{
|
||||||
|
var plexGUID = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
plexGUID = t.guid;
|
||||||
|
var seasonInfo = PlexHelper.GetSeasonsAndEpisodesFromPlexGuid(plexGUID);
|
||||||
|
|
||||||
|
var info = TvApi.ShowLookupByTheTvDbId(int.Parse(PlexHelper.GetProviderIdFromPlexGuid(plexGUID)));
|
||||||
|
|
||||||
|
var banner = info.image?.original;
|
||||||
|
if (!string.IsNullOrEmpty(banner))
|
||||||
|
{
|
||||||
|
banner = banner.Replace("http", "https"); // Always use the Https banners
|
||||||
|
}
|
||||||
|
sb.Append("<tr>");
|
||||||
|
sb.Append("<td align=\"center\">");
|
||||||
|
sb.AppendFormat("<img src=\"{0}\" width=\"400px\" text-align=\"center\" />", banner);
|
||||||
|
sb.Append("</td>");
|
||||||
|
sb.Append("</tr>");
|
||||||
|
sb.Append("<tr>");
|
||||||
|
sb.Append("<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
||||||
|
|
||||||
|
var title = !string.IsNullOrEmpty(t.SeriesTitle)
|
||||||
|
? $"{t.SeriesTitle} - {t.title} {t.originally_available_at:yyyy}"
|
||||||
|
: $"{t.title}";
|
||||||
|
|
||||||
|
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}</p></a>",
|
||||||
|
info.externals.imdb, title);
|
||||||
|
|
||||||
|
sb.AppendFormat("<p style=\"font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;\">Season: {0}, Episode: {1}</p>", seasonInfo.SeasonNumber, seasonInfo.EpisodeNumber);
|
||||||
|
|
||||||
|
if (info.genres.Any())
|
||||||
|
{
|
||||||
|
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(t.summary) ? info.summary : t.summary); // Episode Summary
|
||||||
|
|
||||||
sb.Append("<td");
|
sb.Append("<td");
|
||||||
sb.Append("<hr>");
|
sb.Append("<hr>");
|
||||||
|
@ -298,5 +438,15 @@ namespace PlexRequests.Services.Jobs
|
||||||
Log.Error(e);
|
Log.Error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EndLoopHtml(ref StringBuilder sb)
|
||||||
|
{
|
||||||
|
sb.Append("<td");
|
||||||
|
sb.Append("<hr>");
|
||||||
|
sb.Append("<br>");
|
||||||
|
sb.Append("<br>");
|
||||||
|
sb.Append("</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -80,6 +80,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Interfaces\IJobRecord.cs" />
|
<Compile Include="Interfaces\IJobRecord.cs" />
|
||||||
<Compile Include="Interfaces\INotificationEngine.cs" />
|
<Compile Include="Interfaces\INotificationEngine.cs" />
|
||||||
|
<Compile Include="Jobs\HtmlTemplateGenerator.cs" />
|
||||||
<Compile Include="Jobs\IRecentlyAdded.cs" />
|
<Compile Include="Jobs\IRecentlyAdded.cs" />
|
||||||
<Compile Include="Jobs\JobRecord.cs" />
|
<Compile Include="Jobs\JobRecord.cs" />
|
||||||
<Compile Include="Jobs\JobNames.cs" />
|
<Compile Include="Jobs\JobNames.cs" />
|
||||||
|
|
|
@ -26,70 +26,43 @@
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Data.Linq.Mapping;
|
using Dapper;
|
||||||
|
using Dapper.Contrib.Extensions;
|
||||||
|
|
||||||
namespace PlexRequests.Store.Models.Plex
|
namespace PlexRequests.Store.Models.Plex
|
||||||
{
|
{
|
||||||
[Table(Name = "metadata_items")]
|
[Table("metadata_items")]
|
||||||
public class MetadataItems
|
public class MetadataItems
|
||||||
{
|
{
|
||||||
[Column(IsPrimaryKey = true)]
|
[Key]
|
||||||
public int Id { get; set; }
|
public int id { get; set; }
|
||||||
|
|
||||||
[Column(Name = "library_section_id")]
|
public int library_section_id { get; set; }
|
||||||
public int LibrarySectionId { get; set; }
|
public int parent_id { get; set; }
|
||||||
|
public int metadata_type { get; set; }
|
||||||
[Column(Name = "parent_id")]
|
public string guid { get; set; }
|
||||||
public int ParentId { get; set; }
|
public int media_item_count { get; set; }
|
||||||
|
public string title { get; set; }
|
||||||
[Column(Name = "metadata_type")]
|
public string title_sort { get; set; }
|
||||||
public int MetadataType { get; set; }
|
public string original_title { get; set; }
|
||||||
|
public string studio { get; set; }
|
||||||
[Column(Name = "guid")]
|
public float rating { get; set; }
|
||||||
public string Guid { get; set; }
|
public int rating_count { get; set; }
|
||||||
|
public string tagline { get; set; }
|
||||||
[Column(Name = "media_item_count")]
|
public string summary { get; set; }
|
||||||
public int MediaItemCount { get; set; }
|
public string trivia { get; set; }
|
||||||
|
public string quotes { get; set; }
|
||||||
[Column(Name = "title")]
|
public string content_rating { get; set; }
|
||||||
public string Title { get; set; }
|
public int content_rating_age { get; set; }
|
||||||
|
|
||||||
[Column(Name = "title_sort")]
|
|
||||||
public string TitleSort { get; set; }
|
|
||||||
|
|
||||||
[Column(Name = "OriginalTitle")]
|
|
||||||
public string OriginalTitle { get; set; }
|
|
||||||
|
|
||||||
[Column(Name = "studio")]
|
|
||||||
public string Studio { get; set; }
|
|
||||||
[Column(Name = "rating")]
|
|
||||||
public float Rating { get; set; }
|
|
||||||
[Column(Name = "rating_count")]
|
|
||||||
public int RatingCount { get; set; }
|
|
||||||
[Column(Name = "tagline")]
|
|
||||||
public string Tagline { get; set; }
|
|
||||||
[Column(Name = "summary")]
|
|
||||||
public string Summary { get; set; }
|
|
||||||
[Column(Name = "trivia")]
|
|
||||||
public string Trivia { get; set; }
|
|
||||||
[Column(Name = "quotes")]
|
|
||||||
public string Quotes { get; set; }
|
|
||||||
[Column(Name = "content_rating")]
|
|
||||||
public string ContentRating { get; set; }
|
|
||||||
[Column(Name = "content_rating_age")]
|
|
||||||
public int ContentRatingAge { get; set; }
|
|
||||||
[Column(Name = "Index")]
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
public string tags_genre { get; set; }
|
||||||
// SKIP Until Date Times
|
// SKIP Until Date Times
|
||||||
|
|
||||||
[Column(Name = "originally_available_at")]
|
public DateTime originally_available_at { get; set; }
|
||||||
public DateTime OriginallyAvailableAt { get; set; }
|
public DateTime available_at { get; set; }
|
||||||
[Column(Name = "available_at")]
|
public DateTime expires_at { get; set; }
|
||||||
public DateTime AvailableAt { get; set; }
|
|
||||||
[Column(Name = "expires_at")]
|
|
||||||
public DateTime ExpiresAt { get; set; }
|
|
||||||
// Skip RefreshedAt and Year
|
// Skip RefreshedAt and Year
|
||||||
[Column(Name = "added_at")]
|
public DateTime added_at { get; set; }
|
||||||
public DateTime AddedAt { get; set; }
|
public string SeriesTitle { get; set; } // Only used in a custom query for the TV Shows
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,7 @@ namespace PlexRequests.Store
|
||||||
{
|
{
|
||||||
throw new SqliteException("Factory returned null");
|
throw new SqliteException("Factory returned null");
|
||||||
}
|
}
|
||||||
fact.ConnectionString = "Data Source=" + "Plex Path";
|
fact.ConnectionString = "Data Source=" + DbLocation;
|
||||||
return fact;
|
return fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,10 @@ namespace PlexRequests.Store
|
||||||
{
|
{
|
||||||
using (var con = DbConnection())
|
using (var con = DbConnection())
|
||||||
{
|
{
|
||||||
return con.Query<MetadataItems>(query, param);
|
con.Open();
|
||||||
|
var data = con.Query<MetadataItems>(query, param);
|
||||||
|
con.Close();
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dapper;
|
|
||||||
using Dapper.Contrib.Extensions;
|
using Dapper.Contrib.Extensions;
|
||||||
|
using Dapper;
|
||||||
|
|
||||||
using Mono.Data.Sqlite;
|
using Mono.Data.Sqlite;
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace PlexRequests.UI.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("Needs work")]
|
||||||
public async Task HappyPathSendSeriesToSonarrAllSeason()
|
public async Task HappyPathSendSeriesToSonarrAllSeason()
|
||||||
{
|
{
|
||||||
var seriesResult = new SonarrAddSeries() { title = "ABC"};
|
var seriesResult = new SonarrAddSeries() { title = "ABC"};
|
||||||
|
|
|
@ -122,8 +122,8 @@ namespace PlexRequests.UI.Helpers
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
var startUrl = $"{content}/Content";
|
var startUrl = $"{content}/Content";
|
||||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"/{startUrl}/datepicker.min.css\" type=\"text/css\"/>");
|
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{startUrl}/datepicker.min.css\" type=\"text/css\"/>");
|
||||||
sb.AppendLine($"<script src=\"/{startUrl}/bootstrap-datetimepicker.min.js\"></script>");
|
sb.AppendLine($"<script src=\"{startUrl}/bootstrap-datetimepicker.min.js\"></script>");
|
||||||
|
|
||||||
return helper.Raw(sb.ToString());
|
return helper.Raw(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,15 @@ namespace PlexRequests.UI.Helpers
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
series = await GetSonarrSeries(sonarrSettings, model.ProviderId);
|
series = await GetSonarrSeries(sonarrSettings, model.ProviderId);
|
||||||
|
|
||||||
|
|
||||||
|
// Due to the bug above, we need to make sure all seasons are not monitored
|
||||||
|
foreach (var s in series.seasons)
|
||||||
|
{
|
||||||
|
s.monitored = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SonarrApi.UpdateSeries(series, sonarrSettings.ApiKey, sonarrSettings.FullUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first ?? false)
|
if (first ?? false)
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace PlexRequests.UI.Jobs
|
||||||
JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build(),
|
JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build(),
|
||||||
JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build(),
|
JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build(),
|
||||||
JobBuilder.Create<UserRequestLimitResetter>().WithIdentity("UserRequestLimiter", "Request").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 =
|
var rencentlyAdded =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("RecentlyAdded", "Email")
|
.WithIdentity("RecentlyAddedModel", "Email")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInHours(2).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInHours(2).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Mono.Data.Sqlite;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using Nancy.ModelBinding;
|
using Nancy.ModelBinding;
|
||||||
using Nancy.Security;
|
using Nancy.Security;
|
||||||
|
@ -35,6 +36,8 @@ using NLog;
|
||||||
using PlexRequests.Api.Interfaces;
|
using PlexRequests.Api.Interfaces;
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.Store.Repository;
|
||||||
using PlexRequests.UI.Helpers;
|
using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ namespace PlexRequests.UI.Modules
|
||||||
Post["/plex"] = _ => PlexTest();
|
Post["/plex"] = _ => PlexTest();
|
||||||
Post["/sickrage"] = _ => SickRageTest();
|
Post["/sickrage"] = _ => SickRageTest();
|
||||||
Post["/headphones"] = _ => HeadphonesTest();
|
Post["/headphones"] = _ => HeadphonesTest();
|
||||||
|
Post["/plexdb"] = _ => TestPlexDb();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
@ -223,5 +226,65 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); ;
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response TestPlexDb()
|
||||||
|
{
|
||||||
|
var settings = this.Bind<PlexSettings>();
|
||||||
|
var valid = this.Validate(settings);
|
||||||
|
if (!valid.IsValid)
|
||||||
|
{
|
||||||
|
return Response.AsJson(valid.SendJsonError());
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var location = string.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride))
|
||||||
|
{
|
||||||
|
if (Type.GetType("Mono.Runtime") != null)
|
||||||
|
{
|
||||||
|
// Mono
|
||||||
|
location = Path.Combine("/var/lib/plexmediaserver/Library/Application Support/",
|
||||||
|
"Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default Windows
|
||||||
|
location = Path.Combine(Environment.ExpandEnvironmentVariables("%LOCALAPPDATA%"),
|
||||||
|
"Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
location = Path.Combine(settings.PlexDatabaseLocationOverride, "Plug-in Support", "Databases", "com.plexapp.plugins.library.db");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(location))
|
||||||
|
{
|
||||||
|
return Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = true,
|
||||||
|
Message = "Found the database!"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = $"Could not find the database at the following full location : {location}"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Warn("Exception thrown when attempting to find the plex database: ");
|
||||||
|
Log.Warn(e);
|
||||||
|
var message = $"Could not find Plex's DB, please check your settings. <strong>Exception Message:</strong> {e.Message}";
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
message = $"Could not find Plex's DB, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); ;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -184,14 +184,14 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
|
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
|
||||||
{
|
{
|
||||||
List<MovieResult> apiMovies;
|
List<SearchMovie> apiMovies;
|
||||||
|
|
||||||
switch (searchType)
|
switch (searchType)
|
||||||
{
|
{
|
||||||
case MovieSearchType.Search:
|
case MovieSearchType.Search:
|
||||||
var movies = await MovieApi.SearchMovie(searchTerm);
|
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
|
||||||
apiMovies = movies.Select(x =>
|
apiMovies = movies.Select(x =>
|
||||||
new MovieResult
|
new SearchMovie
|
||||||
{
|
{
|
||||||
Adult = x.Adult,
|
Adult = x.Adult,
|
||||||
BackdropPath = x.BackdropPath,
|
BackdropPath = x.BackdropPath,
|
||||||
|
@ -217,7 +217,7 @@ namespace PlexRequests.UI.Modules
|
||||||
apiMovies = await MovieApi.GetUpcomingMovies();
|
apiMovies = await MovieApi.GetUpcomingMovies();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
apiMovies = new List<MovieResult>();
|
apiMovies = new List<SearchMovie>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +234,8 @@ namespace PlexRequests.UI.Modules
|
||||||
var viewMovies = new List<SearchMovieViewModel>();
|
var viewMovies = new List<SearchMovieViewModel>();
|
||||||
foreach (var movie in apiMovies)
|
foreach (var movie in apiMovies)
|
||||||
{
|
{
|
||||||
|
var movieInfoTask = 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 viewMovie = new SearchMovieViewModel
|
var viewMovie = new SearchMovieViewModel
|
||||||
{
|
{
|
||||||
Adult = movie.Adult,
|
Adult = movie.Adult,
|
||||||
|
@ -252,7 +254,8 @@ namespace PlexRequests.UI.Modules
|
||||||
VoteCount = movie.VoteCount
|
VoteCount = movie.VoteCount
|
||||||
};
|
};
|
||||||
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
|
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
|
||||||
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString());
|
var movieInfo = await movieInfoTask;
|
||||||
|
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(), movieInfo.ImdbId);
|
||||||
if (plexMovie != null)
|
if (plexMovie != null)
|
||||||
{
|
{
|
||||||
viewMovie.Available = true;
|
viewMovie.Available = true;
|
||||||
|
@ -349,8 +352,7 @@ namespace PlexRequests.UI.Modules
|
||||||
providerId = viewT.Id.ToString();
|
providerId = viewT.Id.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
|
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
|
||||||
providerId);
|
|
||||||
if (plexShow != null)
|
if (plexShow != null)
|
||||||
{
|
{
|
||||||
viewT.Available = true;
|
viewT.Available = true;
|
||||||
|
@ -590,7 +592,7 @@ namespace PlexRequests.UI.Modules
|
||||||
RequestedUsers = new List<string> { Username },
|
RequestedUsers = new List<string> { Username },
|
||||||
Issues = IssueState.None,
|
Issues = IssueState.None,
|
||||||
ImdbId = showInfo.externals?.imdb ?? string.Empty,
|
ImdbId = showInfo.externals?.imdb ?? string.Empty,
|
||||||
SeasonCount = showInfo.seasonCount,
|
SeasonCount = showInfo.Season.Count,
|
||||||
TvDbId = showId.ToString()
|
TvDbId = showId.ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -703,7 +705,18 @@ namespace PlexRequests.UI.Modules
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4), providerId, model.SeasonList))
|
if (plexSettings.EnableTvEpisodeSearching)
|
||||||
|
{
|
||||||
|
foreach (var s in showInfo.Season)
|
||||||
|
{
|
||||||
|
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}" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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}" });
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,9 @@ namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false });
|
return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false });
|
||||||
}
|
}
|
||||||
|
#if DEBUG
|
||||||
|
return Response.AsJson(new JsonUpdateAvailableModel {UpdateAvailable = false});
|
||||||
|
#endif
|
||||||
var checker = new StatusChecker();
|
var checker = new StatusChecker();
|
||||||
var release = await Cache.GetOrSetAsync(CacheKeys.LastestProductVersion, async() => await checker.GetStatus(), 30);
|
var release = await Cache.GetOrSetAsync(CacheKeys.LastestProductVersion, async() => await checker.GetStatus(), 30);
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace PlexRequests.UI.NinjectModules
|
||||||
Bind<ICacheProvider>().To<MemoryCacheProvider>().InSingletonScope();
|
Bind<ICacheProvider>().To<MemoryCacheProvider>().InSingletonScope();
|
||||||
Bind<ISqliteConfiguration>().To<DbConfiguration>().WithConstructorArgument("provider", new SqliteFactory());
|
Bind<ISqliteConfiguration>().To<DbConfiguration>().WithConstructorArgument("provider", new SqliteFactory());
|
||||||
Bind<IPlexDatabase>().To<PlexDatabase>().WithConstructorArgument("provider", new SqliteFactory());
|
Bind<IPlexDatabase>().To<PlexDatabase>().WithConstructorArgument("provider", new SqliteFactory());
|
||||||
|
Bind<IPlexReadOnlyDatabase>().To<PlexReadOnlyDatabase>();
|
||||||
|
|
||||||
|
|
||||||
Bind<IUserMapper>().To<UserMapper>();
|
Bind<IUserMapper>().To<UserMapper>();
|
||||||
|
|
|
@ -117,6 +117,7 @@
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Web.Extensions" />
|
<Reference Include="System.Web.Extensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
@ -196,8 +197,9 @@
|
||||||
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
|
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
|
||||||
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath>
|
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="TMDbLib, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null">
|
<Reference Include="TMDbLib, Version=0.9.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath>
|
<HintPath>..\packages\TMDbLib.0.9.6.0-alpha\lib\net45\TMDbLib.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -32,7 +32,7 @@ using Ninject.Planning.Bindings.Resolvers;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
using Owin;
|
using Owin;
|
||||||
|
using PlexRequests.Services.Jobs;
|
||||||
using PlexRequests.UI.Helpers;
|
using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Jobs;
|
using PlexRequests.UI.Jobs;
|
||||||
using PlexRequests.UI.NinjectModules;
|
using PlexRequests.UI.NinjectModules;
|
||||||
|
|
|
@ -121,6 +121,8 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#save').click(function (e) {
|
$('#save').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
var start = '';
|
var start = '';
|
||||||
var end = '';
|
var end = '';
|
||||||
if ($startDate.data("DateTimePicker").date()) {
|
if ($startDate.data("DateTimePicker").date()) {
|
||||||
|
@ -130,8 +132,6 @@
|
||||||
end = $endDate.data("DateTimePicker").date().toISOString();
|
end = $endDate.data("DateTimePicker").date().toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var $form = $("#mainForm");
|
var $form = $("#mainForm");
|
||||||
|
|
||||||
var data = $form.serialize();
|
var data = $form.serialize();
|
||||||
|
|
|
@ -91,7 +91,15 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="PlexDatabaseLocationOverride" class="control-label">Plex Database Override</label>
|
<label for="PlexDatabaseLocationOverride" class="control-label">Plex Database Override</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " id="PlexDatabaseLocationOverride" name="PlexDatabaseLocationOverride" value="@Model.PlexDatabaseLocationOverride">
|
<input type="text" class="form-control form-control-custom " id="PlexDatabaseLocationOverride" name="PlexDatabaseLocationOverride" placeholder="%LOCALAPPDATA%\Plex Media Server\" value="@Model.PlexDatabaseLocationOverride">
|
||||||
|
</div>
|
||||||
|
<small>
|
||||||
|
This is your Plex data directory location, if we cannot manually find it then you need to specify the location! See <a href="https://support.plex.tv/hc/en-us/articles/202915258-Where-is-the-Plex-Media-Server-data-directory-located-">Here</a>.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="">
|
||||||
|
<button id="dbTest" class="btn btn-primary-outline">Test Database Directory <i class="fa fa-database"></i> <div id="dbSpinner"></div></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -101,6 +109,8 @@
|
||||||
<input type="text" class="form-control-custom form-control" id="authToken" name="PlexAuthToken" placeholder="Plex Auth Token" value="@Model.PlexAuthToken">
|
<input type="text" class="form-control-custom form-control" id="authToken" name="PlexAuthToken" placeholder="Plex Auth Token" value="@Model.PlexAuthToken">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username" class="control-label">Username and Password</label>
|
<label for="username" class="control-label">Username and Password</label>
|
||||||
|
@ -173,6 +183,38 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#dbTest').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var url = createBaseUrl(base, '/test/plexdb');
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
|
||||||
|
$('#dbSpinner').attr("class", "fa fa-spinner fa-spin");
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
url: url,
|
||||||
|
data: $form.serialize(),
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
$('#dbSpinner').attr("class", "");
|
||||||
|
console.log(response);
|
||||||
|
if (response.result === true) {
|
||||||
|
generateNotify(response.message, "success");
|
||||||
|
|
||||||
|
$('#dbSpinner').attr("class", "fa fa-check");
|
||||||
|
} else {
|
||||||
|
generateNotify(response.message, "warning");
|
||||||
|
$('#dbSpinner').attr("class", "fa fa-times");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
|
||||||
|
$('#spinner').attr("class", "fa fa-times");
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('#requestToken').click(function (e) {
|
$('#requestToken').click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var $form = $("#mainForm");
|
var $form = $("#mainForm");
|
||||||
|
|
|
@ -44,11 +44,12 @@
|
||||||
<package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net45" />
|
<package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Globalization" version="4.0.0" targetFramework="net45" />
|
<package id="System.Globalization" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Linq" version="4.0.0" targetFramework="net45" />
|
<package id="System.Linq" version="4.0.0" targetFramework="net45" />
|
||||||
|
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Reflection" version="4.0.0" targetFramework="net45" />
|
<package id="System.Reflection" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Reflection.Extensions" version="4.0.0" targetFramework="net45" />
|
<package id="System.Reflection.Extensions" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net45" />
|
<package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Runtime" version="4.0.0" targetFramework="net45" />
|
<package id="System.Runtime" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net45" />
|
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="System.Text.RegularExpressions" version="4.0.0" targetFramework="net45" />
|
<package id="System.Text.RegularExpressions" version="4.0.0" targetFramework="net45" />
|
||||||
<package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" />
|
<package id="TMDbLib" version="0.9.6.0-alpha" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
Loading…
Add table
Add a link
Reference in a new issue