From 9ce08902d73c38d8f4fde9b2a9f918e671bd32cb Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 2 Mar 2016 17:21:11 +0000 Subject: [PATCH] Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details --- RequestPlex.Api/Models/Tv/TvSearchResult.cs | 4 +- RequestPlex.Api/Models/Tv/TvShow.cs | 55 +++++++++++++++++++++ RequestPlex.Api/MovieBase.cs | 5 +- RequestPlex.Api/RequestPlex.Api.csproj | 5 +- RequestPlex.Api/TheTvDbApi.cs | 24 +++++---- RequestPlex.Api/TvBase.cs | 8 +-- RequestPlex.Core/CacheKeys.cs | 33 +++++++++++++ RequestPlex.Core/RequestPlex.Core.csproj | 1 + RequestPlex.Core/RequestService.cs | 6 +-- RequestPlex.Core/SettingsService.cs | 44 +++++++++++------ RequestPlex.Store/RequestedModel.cs | 2 +- RequestPlex.Store/SqlTables.sql | 2 +- RequestPlex.UI/Content/search.js | 3 +- RequestPlex.UI/Modules/RequestsModule.cs | 8 +-- RequestPlex.UI/Modules/SearchModule.cs | 27 ++++++---- 15 files changed, 173 insertions(+), 54 deletions(-) create mode 100644 RequestPlex.Api/Models/Tv/TvShow.cs create mode 100644 RequestPlex.Core/CacheKeys.cs diff --git a/RequestPlex.Api/Models/Tv/TvSearchResult.cs b/RequestPlex.Api/Models/Tv/TvSearchResult.cs index 8b9e4d246..edeee7e30 100644 --- a/RequestPlex.Api/Models/Tv/TvSearchResult.cs +++ b/RequestPlex.Api/Models/Tv/TvSearchResult.cs @@ -28,7 +28,7 @@ using System.Collections.Generic; namespace RequestPlex.Api.Models.Tv { - public class TvShow + public class TvShowSearchResult { public int id { get; set; } public int airedSeason { get; set; } @@ -63,6 +63,6 @@ namespace RequestPlex.Api.Models.Tv public class TvSearchResult { - public TvShow[] data { get; set; } + public List data { get; set; } } } diff --git a/RequestPlex.Api/Models/Tv/TvShow.cs b/RequestPlex.Api/Models/Tv/TvShow.cs new file mode 100644 index 000000000..30205b5f8 --- /dev/null +++ b/RequestPlex.Api/Models/Tv/TvShow.cs @@ -0,0 +1,55 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: TvShow.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.Collections.Generic; + +namespace RequestPlex.Api.Models.Tv +{ + public class TvShow + { + public int id { get; set; } + public string seriesName { get; set; } + public List aliases { get; set; } + public string banner { get; set; } + public int seriesId { get; set; } + public string status { get; set; } + public string firstAired { get; set; } + public string network { get; set; } + public string networkId { get; set; } + public string runtime { get; set; } + public List genre { get; set; } + public string overview { get; set; } + public int lastUpdated { get; set; } + public string airsDayOfWeek { get; set; } + public string airsTime { get; set; } + public string rating { get; set; } + public string imdbId { get; set; } + public string zap2itId { get; set; } + public string added { get; set; } + public int siteRating { get; set; } + + } +} diff --git a/RequestPlex.Api/MovieBase.cs b/RequestPlex.Api/MovieBase.cs index fa10e88fb..af8e920e3 100644 --- a/RequestPlex.Api/MovieBase.cs +++ b/RequestPlex.Api/MovieBase.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: MovieBase.cs +// File: TvBase.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -30,10 +30,9 @@ using RequestPlex.Helpers; namespace RequestPlex.Api { - public abstract class TvBase + public abstract class MovieBase { private static readonly string Encrypted = "0T3QNSseexLO7n7UPiJvl70Y+KKnvbeTlsusl7Kwq0hPH0BHOuFNGwksNCjkwqWedyDdI/MJeUR4wtL4bIl0Z+//uHXEaYM/4H2pjeLbH5EWdUe5TTj1AhaIR5PQweamvcienRyFD/3YPCC/+qL5mHkKXBkPumMod3Zb/4yN0Ik="; protected string ApiKey = StringCipher.Decrypt(Encrypted, "ApiKey"); - protected Uri Url = new Uri("http://api.themoviedb.org/3"); } } diff --git a/RequestPlex.Api/RequestPlex.Api.csproj b/RequestPlex.Api/RequestPlex.Api.csproj index be86dbb2f..8b1f02364 100644 --- a/RequestPlex.Api/RequestPlex.Api.csproj +++ b/RequestPlex.Api/RequestPlex.Api.csproj @@ -66,10 +66,11 @@ - + + - + diff --git a/RequestPlex.Api/TheTvDbApi.cs b/RequestPlex.Api/TheTvDbApi.cs index 68ceb7f5b..1b669eac0 100644 --- a/RequestPlex.Api/TheTvDbApi.cs +++ b/RequestPlex.Api/TheTvDbApi.cs @@ -45,18 +45,21 @@ namespace RequestPlex.Api /// Authenticates against TheTVDB. /// /// - public Authentication Authenticate() + public string Authenticate() { var request = new RestRequest { Method = Method.POST, - Resource = "login" + Resource = "login", + RequestFormat = DataFormat.Json, + }; var apiKey = new { apikey = ApiKey }; - var json = JsonConvert.SerializeObject(apiKey); - request.AddBody(json); + + request.AddBody(apiKey); + request.AddHeader("Content-Type", "application/json"); - return Api.Execute(request, Url); + return Api.Execute(request, Url).token; } /// @@ -72,6 +75,7 @@ namespace RequestPlex.Api Resource = "refresh_token" }; request.AddHeader("Authorization", $"Bearer {oldToken}"); + request.AddHeader("Content-Type", "application/json"); return Api.Execute(request, Url); } @@ -86,11 +90,12 @@ namespace RequestPlex.Api { var request = new RestRequest { - Method = Method.POST, + Method = Method.GET, Resource = "search/series?name={searchTerm}" }; request.AddUrlSegment("searchTerm", searchTerm); request.AddHeader("Authorization", $"Bearer {token}"); + request.AddHeader("Content-Type", "application/json"); return Api.Execute(request, Url); } @@ -102,17 +107,18 @@ namespace RequestPlex.Api /// The TVDB identifier. /// The token. /// - public TvSearchResult GetInformation(int tvdbId, string token) + public TvShow GetInformation(int tvdbId, string token) { var request = new RestRequest { - Method = Method.POST, + Method = Method.GET, Resource = "search/{id}" }; request.AddUrlSegment("id", tvdbId.ToString()); request.AddHeader("Authorization", $"Bearer {token}"); + request.AddHeader("Content-Type", "application/json"); - return Api.Execute(request, Url); + return Api.Execute(request, Url); } } } diff --git a/RequestPlex.Api/TvBase.cs b/RequestPlex.Api/TvBase.cs index 2d1aa0a27..7ea97031a 100644 --- a/RequestPlex.Api/TvBase.cs +++ b/RequestPlex.Api/TvBase.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: TvBase.cs +// File: MovieBase.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -24,14 +24,16 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion +using System; + using RequestPlex.Helpers; namespace RequestPlex.Api { - public abstract class MovieBase + public abstract class TvBase { private static readonly string Encrypted = "AVdhrVK6XX8anvrQgEyN/qNr9rk8ZPwy7/r1t5t5cKyUEzxcyk0L1v6dSxgE7hTCxvITUX2cWa6VlFMlTMgJWyuPZml7fN3csCHntgd/VGYro6VfNf24snZ/rQ3mf005"; protected string ApiKey = StringCipher.Decrypt(Encrypted, "ApiKey"); - protected string Url = "https://api-beta.thetvdb.com/"; + protected Uri Url = new Uri("https://api-beta.thetvdb.com/"); } } diff --git a/RequestPlex.Core/CacheKeys.cs b/RequestPlex.Core/CacheKeys.cs new file mode 100644 index 000000000..ff826d135 --- /dev/null +++ b/RequestPlex.Core/CacheKeys.cs @@ -0,0 +1,33 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: CacheKeys.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 +namespace RequestPlex.Core +{ + public class CacheKeys + { + public const string TvDbToken = "TheTvDbApiToken"; + } +} \ No newline at end of file diff --git a/RequestPlex.Core/RequestPlex.Core.csproj b/RequestPlex.Core/RequestPlex.Core.csproj index b105c28e8..c277b1166 100644 --- a/RequestPlex.Core/RequestPlex.Core.csproj +++ b/RequestPlex.Core/RequestPlex.Core.csproj @@ -62,6 +62,7 @@ + diff --git a/RequestPlex.Core/RequestService.cs b/RequestPlex.Core/RequestService.cs index 51845784d..de81fbb2a 100644 --- a/RequestPlex.Core/RequestService.cs +++ b/RequestPlex.Core/RequestService.cs @@ -43,7 +43,7 @@ namespace RequestPlex.Core { var model = new RequestedModel { - Tmdbid = tmdbid, + ProviderId = tmdbid, Type = type }; @@ -52,12 +52,12 @@ namespace RequestPlex.Core public bool CheckRequest(int tmdbid) { - return Repo.GetAll().Any(x => x.Tmdbid == tmdbid); + return Repo.GetAll().Any(x => x.ProviderId == tmdbid); } public void DeleteRequest(int tmdbId) { - var entity = Repo.GetAll().FirstOrDefault(x => x.Tmdbid == tmdbId); + var entity = Repo.GetAll().FirstOrDefault(x => x.ProviderId == tmdbId); Repo.Delete(entity); } diff --git a/RequestPlex.Core/SettingsService.cs b/RequestPlex.Core/SettingsService.cs index 9e37f3d3c..76fd71362 100644 --- a/RequestPlex.Core/SettingsService.cs +++ b/RequestPlex.Core/SettingsService.cs @@ -30,6 +30,8 @@ using System.Linq; using Mono.Data.Sqlite; using RequestPlex.Api; +using RequestPlex.Api.Models.Tv; +using RequestPlex.Helpers; using RequestPlex.Store; namespace RequestPlex.Core @@ -37,7 +39,7 @@ namespace RequestPlex.Core public class SettingsService { - public SettingsModel GetSettings() + public SettingsModel GetSettings(ICacheProvider cache) { var db = new DbConfiguration(new SqliteFactory()); var repo = new GenericRepository(db); @@ -46,18 +48,20 @@ namespace RequestPlex.Core return settings; } + private ICacheProvider Cache { get; set; } - public void AddRequest(int tmdbid, RequestType type) + public void AddRequest(int providerId, RequestType type) { - var api = new TheMovieDbApi(); + var model = new RequestedModel(); if (type == RequestType.Movie) { - var movieInfo = api.GetMovieInformation(tmdbid).Result; + var movieApi = new TheMovieDbApi(); + var movieInfo = movieApi.GetMovieInformation(providerId).Result; model = new RequestedModel { - Tmdbid = movieInfo.Id, + ProviderId = movieInfo.Id, Type = type, Overview = movieInfo.Overview, ImdbId = movieInfo.ImdbId, @@ -71,17 +75,23 @@ namespace RequestPlex.Core } else { - var showInfo = api.GetTvShowInformation(tmdbid).Result; + var tvApi = new TheTvDbApi(); + var token = GetAuthToken(tvApi); + + var showInfo = tvApi.GetInformation(providerId, token); + + DateTime firstAir; + DateTime.TryParse(showInfo.firstAired, out firstAir); model = new RequestedModel { - Tmdbid = showInfo.Id, + ProviderId = showInfo.id, Type = type, - Overview = showInfo.Overview, - PosterPath = "http://image.tmdb.org/t/p/w150/" + showInfo.PosterPath, - Title = showInfo.Name, - ReleaseDate = showInfo.FirstAirDate ?? DateTime.MinValue, - Status = showInfo.Status, + Overview = showInfo.overview, + PosterPath = "http://image.tmdb.org/t/p/w150/" + showInfo.banner, // This is incorrect + Title = showInfo.seriesName, + ReleaseDate = firstAir, + Status = showInfo.status, RequestedDate = DateTime.Now, Approved = false }; @@ -92,21 +102,25 @@ namespace RequestPlex.Core repo.Insert(model); } - public bool CheckRequest(int tmdbid) + public bool CheckRequest(int providerId) { var db = new DbConfiguration(new SqliteFactory()); var repo = new GenericRepository(db); - return repo.GetAll().Any(x => x.Tmdbid == tmdbid); + return repo.GetAll().Any(x => x.ProviderId == providerId); } public void DeleteRequest(int tmdbId) { var db = new DbConfiguration(new SqliteFactory()); var repo = new GenericRepository(db); - var entity = repo.GetAll().FirstOrDefault(x => x.Tmdbid == tmdbId); + var entity = repo.GetAll().FirstOrDefault(x => x.ProviderId == tmdbId); repo.Delete(entity); } + private string GetAuthToken(TheTvDbApi api) + { + return Cache.GetOrSet(CacheKeys.TvDbToken, api.Authenticate, 50); + } } } diff --git a/RequestPlex.Store/RequestedModel.cs b/RequestPlex.Store/RequestedModel.cs index dca2f384b..b336fc073 100644 --- a/RequestPlex.Store/RequestedModel.cs +++ b/RequestPlex.Store/RequestedModel.cs @@ -8,7 +8,7 @@ namespace RequestPlex.Store public class RequestedModel : Entity { // ReSharper disable once IdentifierTypo - public int Tmdbid { get; set; } + public int ProviderId { get; set; } public string ImdbId { get; set; } public string Overview { get; set; } public string Title { get; set; } diff --git a/RequestPlex.Store/SqlTables.sql b/RequestPlex.Store/SqlTables.sql index f6bb567da..64ec50e9c 100644 --- a/RequestPlex.Store/SqlTables.sql +++ b/RequestPlex.Store/SqlTables.sql @@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS Requested ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Type INTEGER NOT NULL, - Tmdbid INTEGER NOT NULL, + ProviderId INTEGER NOT NULL, ImdbId varchar(50), Overview varchar(50) NOT NULL, Title varchar(50) NOT NULL, diff --git a/RequestPlex.UI/Content/search.js b/RequestPlex.UI/Content/search.js index 868240c76..e84af8e68 100644 --- a/RequestPlex.UI/Content/search.js +++ b/RequestPlex.UI/Content/search.js @@ -99,7 +99,8 @@ function tvSearch() { var query = $("#tvSearchContent").val(); $.ajax("/search/tv/" + query).success(function (results) { - results.forEach(function (result) { + + results.data.forEach(function (result) { var context = buildTvShowContext(result); var html = searchTemplate(context); $("#tvList").append(html); diff --git a/RequestPlex.UI/Modules/RequestsModule.cs b/RequestPlex.UI/Modules/RequestsModule.cs index 87478c498..9ef381f78 100644 --- a/RequestPlex.UI/Modules/RequestsModule.cs +++ b/RequestPlex.UI/Modules/RequestsModule.cs @@ -65,7 +65,7 @@ namespace RequestPlex.UI.Modules var dbMovies = Service.GetAll().Where(x => x.Type == RequestType.Movie); var viewModel = dbMovies.Select(tv => new RequestViewModel { - Tmdbid = tv.Tmdbid, + Tmdbid = tv.ProviderId, Type = tv.Type, Status = tv.Status, ImdbId = tv.ImdbId, @@ -88,7 +88,7 @@ namespace RequestPlex.UI.Modules var dbTv = Service.GetAll().Where(x => x.Type == RequestType.TvShow); var viewModel = dbTv.Select(tv => new RequestViewModel { - Tmdbid = tv.Tmdbid, + Tmdbid = tv.ProviderId, Type = tv.Type, Status = tv.Status, ImdbId = tv.ImdbId, @@ -106,9 +106,9 @@ namespace RequestPlex.UI.Modules return Response.AsJson(viewModel); } - private Response DeleteRequest(int tmdbId, RequestType type) + private Response DeleteRequest(int providerId, RequestType type) { - var currentEntity = Service.GetAll().FirstOrDefault(x => x.Tmdbid == tmdbId && x.Type == type); + var currentEntity = Service.GetAll().FirstOrDefault(x => x.ProviderId == providerId && x.Type == type); Service.Delete(currentEntity); return Response.AsJson(new { Result = true }); } diff --git a/RequestPlex.UI/Modules/SearchModule.cs b/RequestPlex.UI/Modules/SearchModule.cs index 7eeab7a02..3e73a170f 100644 --- a/RequestPlex.UI/Modules/SearchModule.cs +++ b/RequestPlex.UI/Modules/SearchModule.cs @@ -2,16 +2,21 @@ using Nancy; using Nancy.Responses.Negotiation; using RequestPlex.Api; +using RequestPlex.Api.Models.Tv; using RequestPlex.Core; +using RequestPlex.Helpers; using RequestPlex.Store; namespace RequestPlex.UI.Modules { public class SearchModule : NancyModule { - public SearchModule() : base("search") + public SearchModule(ICacheProvider cache) : base("search") { - Api = new TheMovieDbApi(); + MovieApi = new TheMovieDbApi(); + TvApi = new TheTvDbApi(); + Cache = cache; + Get["/"] = parameters => RequestLoad(); Get["movie/{searchTerm}"] = parameters => SearchMovie((string)parameters.searchTerm); @@ -23,37 +28,39 @@ namespace RequestPlex.UI.Modules Post["request/movie"] = parameters => RequestMovie((int)Request.Form.movieId); Post["request/tv"] = parameters => RequestTvShow((int)Request.Form.tvId, (bool)Request.Form.latest); } - private TheMovieDbApi Api { get; } + private TheMovieDbApi MovieApi { get; } + private TheTvDbApi TvApi { get; } + private ICacheProvider Cache { get; } + private string AuthToken => Cache.GetOrSet(CacheKeys.TvDbToken, TvApi.Authenticate, 50); private Negotiator RequestLoad() - { + { return View["Search/Index"]; } private Response SearchMovie(string searchTerm) { - var movies = Api.SearchMovie(searchTerm); + var movies = MovieApi.SearchMovie(searchTerm); var result = movies.Result; return Response.AsJson(result); } private Response SearchTvShow(string searchTerm) { - var tvShow = Api.SearchTv(searchTerm); - var result = tvShow.Result; - return Response.AsJson(result); + var tvShow = TvApi.SearchTv(searchTerm, AuthToken); + return Response.AsJson(tvShow); } private Response UpcomingMovies() { - var movies = Api.GetUpcomingMovies(); + var movies = MovieApi.GetUpcomingMovies(); var result = movies.Result; return Response.AsJson(result); } private Response CurrentlyPlayingMovies() { - var movies = Api.GetCurrentPlayingMovies(); + var movies = MovieApi.GetCurrentPlayingMovies(); var result = movies.Result; return Response.AsJson(result); }