diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs index c1cf2027a..2fc78b6bb 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; namespace Ombi.Core @@ -10,5 +11,8 @@ public interface ITVSearchEngineV2 Task GetShowInformation(string tvdbid, CancellationToken token); Task GetShowByRequest(int requestId, CancellationToken token); Task> GetStreamInformation(int movieDbId, CancellationToken cancellationToken); + Task> Popular(int currentlyLoaded, int amountToLoad); + Task> Anticipated(int currentlyLoaded, int amountToLoad); + Task> Trending(int currentlyLoaded, int amountToLoad); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index 156c76d6e..d549f9f56 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -22,6 +22,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using System.Threading; +using TraktSharp.Entities; namespace Ombi.Core.Engine { @@ -51,18 +52,18 @@ public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeA public async Task> Search(string searchTerm) { - var searchResult = await _theMovieDbApi.SearchTv(searchTerm); + var searchResult = await TvMazeApi.Search(searchTerm); if (searchResult != null) { var retVal = new List(); - foreach (var result in searchResult) + foreach (var tvMazeSearch in searchResult) { - //if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) - //{ - // continue; - //} - var mappedResult = await ProcessResult(result, false); + if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) + { + continue; + } + var mappedResult = await ProcessResult(tvMazeSearch, false); if (mappedResult == null) { continue; @@ -74,61 +75,56 @@ public async Task> Search(string searchTerm) return null; } - public async Task GetShowInformation(string theMovieDbId, CancellationToken token) + public async Task GetShowInformation(string tvdbid, CancellationToken token) { - var show = await Cache.GetOrAdd(nameof(GetShowInformation) + theMovieDbId, - async () => await _theMovieDbApi.GetTVInfo(theMovieDbId), DateTime.Now.AddHours(12)); + var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, + async () => await TvMazeApi.ShowLookupByTheTvDbId(int.Parse(tvdbid)), DateTime.Now.AddHours(12)); if (show == null) { // We don't have enough information return null; } - //var episodes = await Cache.GetOrAdd("TvMazeEpisodeLookup" + show.id, - // async () => await TvMazeApi.EpisodeLookup(show.id), DateTime.Now.AddHours(12)); - //if (episodes == null || !episodes.Any()) - //{ - // // We don't have enough information - // return null; - //} + var episodes = await Cache.GetOrAdd("TvMazeEpisodeLookup" + show.id, + async () => await TvMazeApi.EpisodeLookup(show.id), DateTime.Now.AddHours(12)); + if (episodes == null || !episodes.Any()) + { + // We don't have enough information + return null; + } var mapped = Mapper.Map(show); - foreach(var tvSeason in show.seasons) + foreach (var e in episodes) { - var seasonEpisodes = (await _theMovieDbApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token)); - - foreach (var episode in seasonEpisodes.episodes) + var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); + if (season == null) { - var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == episode.season_number); - if (season == null) + var newSeason = new SeasonRequests { - var newSeason = new SeasonRequests - { - SeasonNumber = episode.season_number, - Episodes = new List() - }; - newSeason.Episodes.Add(new EpisodeRequests - { - //Url = episode...ToHttpsUrl(), - Title = episode.name, - AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, - EpisodeNumber = episode.episode_number, - - }); - mapped.SeasonRequests.Add(newSeason); - } - else + SeasonNumber = e.season, + Episodes = new List() + }; + newSeason.Episodes.Add(new EpisodeRequests { - // We already have the season, so just add the episode - season.Episodes.Add(new EpisodeRequests - { - //Url = e.url.ToHttpsUrl(), - Title = episode.name, - AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, - EpisodeNumber = episode.episode_number, - }); - } + Url = e.url.ToHttpsUrl(), + Title = e.name, + AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, + EpisodeNumber = e.number, + + }); + mapped.SeasonRequests.Add(newSeason); + } + else + { + // We already have the season, so just add the episode + season.Episodes.Add(new EpisodeRequests + { + Url = e.url.ToHttpsUrl(), + Title = e.name, + AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, + EpisodeNumber = e.number, + }); } } @@ -147,11 +143,11 @@ public async Task> Popular(int currentlyLoade var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(Popular) + langCode + pagesToLoad.Page, - async () => await _theMovieDbApi.PopularTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + async () => await TraktApi.GetPopularShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } @@ -172,11 +168,11 @@ public async Task> Anticipated(int currentlyL var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(Anticipated) + langCode + pagesToLoad.Page, - async () => await _theMovieDbApi.UpcomingTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + async () => await TraktApi.GetAnticipatedShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); @@ -196,11 +192,11 @@ public async Task> Trending(int currentlyLoad var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(Trending) + langCode + pagesToLoad.Page, - async () => await _theMovieDbApi.TopRatedTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + async () => await TraktApi.GetTrendingShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index fb71c1eb7..9b9b40906 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -21,6 +21,7 @@ using Microsoft.EntityFrameworkCore; using System.Threading; using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; namespace Ombi.Core.Engine.V2 { @@ -30,16 +31,18 @@ public class TvSearchEngineV2 : BaseMediaEngine, ITVSearchEngineV2 private readonly IMapper _mapper; private readonly ITraktApi _traktApi; private readonly IMovieDbApi _movieApi; + private readonly ISettingsService _customization; public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, - IRepository sub, IMovieDbApi movieApi) + IRepository sub, IMovieDbApi movieApi, ISettingsService customization) : base(identity, service, r, um, memCache, s, sub) { _tvMaze = tvMaze; _mapper = mapper; _traktApi = trakt; _movieApi = movieApi; + _customization = customization; } @@ -104,6 +107,56 @@ public async Task GetShowInformation(string tvdbi return await ProcessResult(mapped); } + public async Task> Popular(int currentlyLoaded, int amountToLoad) + { + var langCode = await DefaultLanguageCode(null); + + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); + var results = new List(); + foreach (var pagesToLoad in pages) + { + var apiResult = await Cache.GetOrAdd(nameof(Popular) + langCode + pagesToLoad.Page, + async () => await _movieApi.PopularTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); + } + + var processed = ProcessResults(results); + return await processed; + } + + public async Task> Anticipated(int currentlyLoaded, int amountToLoad) + { + var langCode = await DefaultLanguageCode(null); + + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); + var results = new List(); + foreach (var pagesToLoad in pages) + { + var apiResult = await Cache.GetOrAdd(nameof(Anticipated) + langCode + pagesToLoad.Page, + async () => await _movieApi.UpcomingTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); + } + var processed = ProcessResults(results); + return await processed; + } + + public async Task> Trending(int currentlyLoaded, int amountToLoad) + { + var langCode = await DefaultLanguageCode(null); + + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); + var results = new List(); + foreach (var pagesToLoad in pages) + { + var apiResult = await Cache.GetOrAdd(nameof(Trending) + langCode + pagesToLoad.Page, + async () => await _movieApi.TopRatedTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); + } + var processed = ProcessResults(results); + return await processed; + } + + public async Task> GetStreamInformation(int movieDbId, CancellationToken cancellationToken) { var providers = await _movieApi.GetTvWatchProviders(movieDbId, cancellationToken); @@ -124,19 +177,28 @@ public async Task> GetStreamInformation(int movieDbId return data; } - private IEnumerable ProcessResults(IEnumerable items) + private async Task> ProcessResults(IEnumerable items) { - var retVal = new List(); + var retVal = new List(); + var settings = await _customization.GetSettingsAsync(); foreach (var tvMazeSearch in items) { - retVal.Add(ProcessResult(tvMazeSearch)); + var result = await ProcessResult(tvMazeSearch); + if (result == null || settings.HideAvailableFromDiscover && result.Available) + { + continue; + } + retVal.Add(result); } return retVal; } - private SearchTvShowViewModel ProcessResult(T tvMazeSearch) + private async Task ProcessResult(T tvMazeSearch) { - return _mapper.Map(tvMazeSearch); + var item = _mapper.Map(tvMazeSearch); + + await RunSearchRules(item); + return item; } private async Task ProcessResult(SearchFullInfoTvShowViewModel item) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 47088b894..71331c51d 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -18,7 +18,7 @@ public static void CheckForUnairedEpisodes(SearchTvShowViewModel search) // If we have all the episodes for this season, then this season is available if (season.Episodes.All(x => x.Available)) { - season.SeasonAvailable = true; + season.SeasonAvailable = true; } } if (search.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index 16847630b..4fbdf50f1 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -22,12 +22,10 @@ namespace Ombi.Controllers.V2 { public class SearchController : V2Controller { - public SearchController(IMultiSearchEngine multiSearchEngine, ITvSearchEngine tvSearchEngine, + public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv, IMusicSearchEngineV2 musicEngine, IRottenTomatoesApi rottenTomatoesApi) { _multiSearchEngine = multiSearchEngine; - _tvSearchEngine = tvSearchEngine; - _tvSearchEngine.ResultLimit = 20; _movieEngineV2 = v2Movie; _movieEngineV2.ResultLimit = 20; _tvEngineV2 = v2Tv; @@ -38,7 +36,6 @@ public SearchController(IMultiSearchEngine multiSearchEngine, ITvSearchEngine tv private readonly IMultiSearchEngine _multiSearchEngine; private readonly IMovieEngineV2 _movieEngineV2; private readonly ITVSearchEngineV2 _tvEngineV2; - private readonly ITvSearchEngine _tvSearchEngine; private readonly IMusicSearchEngineV2 _musicEngine; private readonly IRottenTomatoesApi _rottenTomatoesApi; @@ -258,19 +255,6 @@ public async Task> UpcomingMovies(int currentP return await _movieEngineV2.UpcomingMovies(currentPosition, amountToLoad); } - /// - /// Returns Popular Tv Shows - /// - /// We use Trakt.tv as the Provider - /// - [HttpGet("tv/popular")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesDefaultResponseType] - public async Task> PopularTv() - { - return await _tvSearchEngine.Popular(); - } - /// /// Returns Popular Tv Shows /// @@ -281,33 +265,7 @@ public async Task> PopularTv() [ProducesDefaultResponseType] public async Task> PopularTv(int currentPosition, int amountToLoad) { - return await _tvSearchEngine.Popular(currentPosition, amountToLoad); - } - - /// - /// Returns Popular Tv Shows - /// - /// We use Trakt.tv as the Provider - /// - [HttpGet("tv/popular/{currentPosition}/{amountToLoad}/images")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesDefaultResponseType] - public async Task> PopularTvWithImages(int currentPosition, int amountToLoad) - { - return await _tvSearchEngine.Popular(currentPosition, amountToLoad, true); - } - - /// - /// Returns most Anticipated tv shows. - /// - /// We use Trakt.tv as the Provider - /// - [HttpGet("tv/anticipated")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesDefaultResponseType] - public async Task> AnticipatedTv() - { - return await _tvSearchEngine.Anticipated(); + return await _tvEngineV2.Popular(currentPosition, amountToLoad); } /// @@ -320,22 +278,7 @@ public async Task> AnticipatedTv() [ProducesDefaultResponseType] public async Task> AnticipatedTv(int currentPosition, int amountToLoad) { - return await _tvSearchEngine.Anticipated(currentPosition, amountToLoad); - } - - - /// - /// Returns Most watched shows. - /// - /// We use Trakt.tv as the Provider - /// - [HttpGet("tv/mostwatched")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesDefaultResponseType] - [Obsolete("This method is obsolete, Trakt API no longer supports this")] - public async Task> MostWatched() - { - return await _tvSearchEngine.Popular(); + return await _tvEngineV2.Anticipated(currentPosition, amountToLoad); } /// @@ -349,21 +292,9 @@ public async Task> MostWatched() [Obsolete("This method is obsolete, Trakt API no longer supports this")] public async Task> MostWatched(int currentPosition, int amountToLoad) { - return await _tvSearchEngine.Popular(currentPosition, amountToLoad); + return await _tvEngineV2.Popular(currentPosition, amountToLoad); } - /// - /// Returns trending shows - /// - /// We use Trakt.tv as the Provider - /// - [HttpGet("tv/trending")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesDefaultResponseType] - public async Task> Trending() - { - return await _tvSearchEngine.Trending(); - } /// /// Returns trending shows by page @@ -375,10 +306,9 @@ public async Task> Trending() [ProducesDefaultResponseType] public async Task> Trending(int currentPosition, int amountToLoad) { - return await _tvSearchEngine.Trending(currentPosition, amountToLoad); + return await _tvEngineV2.Trending(currentPosition, amountToLoad); } - /// /// Returns all the movies that is by the actor id /// diff --git a/tests/cypress/fixtures/api/v1/tv-search-extra-info.json b/tests/cypress/fixtures/api/v1/tv-search-extra-info.json new file mode 100644 index 000000000..82ed792ae --- /dev/null +++ b/tests/cypress/fixtures/api/v1/tv-search-extra-info.json @@ -0,0 +1,1147 @@ +{ + "title": "Game of Thrones", + "aliases": null, + "banner": "https://static.tvmaze.com/uploads/images/medium_portrait/190/476117.jpg", + "seriesId": 82, + "status": "Ended", + "firstAired": "2011-04-17", + "network": "HBO", + "networkId": "8", + "runtime": "60", + "genre": null, + "overview": "Based on the bestselling book series A Song of Ice and Fire by George R.R. Martin, this sprawling new HBO drama is set in a world where summers span decades and winters can last a lifetime. From the scheming south and the savage eastern lands, to the frozen north and ancient Wall that protects the realm from the mysterious darkness beyond, the powerful families of the Seven Kingdoms are locked in a battle for the Iron Throne. This is a story of duplicity and treachery, nobility and honor, conquest and triumph. In the Game of Thrones, you either win or you die.", + "lastUpdated": 0, + "airsDayOfWeek": null, + "airsTime": null, + "rating": "Ombi.Api.TvMaze.Models.Rating", + "siteRating": 0, + "trailer": null, + "homepage": null, + "seasonRequests": [ + { + "seasonNumber": 1, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Winter is Coming", + "airDate": "2011-04-18T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/18/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Kingsroad", + "airDate": "2011-04-25T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4953/game-of-thrones-1x02-the-kingsroad", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/25/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Lord Snow", + "airDate": "2011-05-02T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4954/game-of-thrones-1x03-lord-snow", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/02/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Cripples, Bastards, and Broken Things", + "airDate": "2011-05-09T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4955/game-of-thrones-1x04-cripples-bastards-and-broken-things", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/09/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Wolf and the Lion", + "airDate": "2011-05-16T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4956/game-of-thrones-1x05-the-wolf-and-the-lion", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/16/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "A Golden Crown", + "airDate": "2011-05-23T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4957/game-of-thrones-1x06-a-golden-crown", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/23/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "You Win or You Die", + "airDate": "2011-05-30T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4958/game-of-thrones-1x07-you-win-or-you-die", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/30/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Pointy End", + "airDate": "2011-06-06T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4959/game-of-thrones-1x08-the-pointy-end", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/06/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Baelor", + "airDate": "2011-06-13T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4960/game-of-thrones-1x09-baelor", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/13/2011 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Fire and Blood", + "airDate": "2011-06-20T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4961/game-of-thrones-1x10-fire-and-blood", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/20/2011 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 2, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "The North Remembers", + "airDate": "2012-04-02T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4962/game-of-thrones-2x01-the-north-remembers", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/02/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Night Lands", + "airDate": "2012-04-09T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4963/game-of-thrones-2x02-the-night-lands", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/09/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "What is Dead May Never Die", + "airDate": "2012-04-16T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4964/game-of-thrones-2x03-what-is-dead-may-never-die", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/16/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Garden of Bones", + "airDate": "2012-04-23T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4965/game-of-thrones-2x04-garden-of-bones", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/23/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Ghost of Harrenhal", + "airDate": "2012-04-30T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4966/game-of-thrones-2x05-the-ghost-of-harrenhal", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/30/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "The Old Gods and the New", + "airDate": "2012-05-07T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4967/game-of-thrones-2x06-the-old-gods-and-the-new", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/07/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "A Man Without Honor", + "airDate": "2012-05-14T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4968/game-of-thrones-2x07-a-man-without-honor", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/14/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Prince of Winterfell", + "airDate": "2012-05-21T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4969/game-of-thrones-2x08-the-prince-of-winterfell", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/21/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Blackwater", + "airDate": "2012-05-28T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4970/game-of-thrones-2x09-blackwater", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/28/2012 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Valar Morghulis", + "airDate": "2012-06-04T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4971/game-of-thrones-2x10-valar-morghulis", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/04/2012 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 3, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Valar Dohaeris", + "airDate": "2013-04-01T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4972/game-of-thrones-3x01-valar-dohaeris", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/01/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Dark Wings, Dark Words", + "airDate": "2013-04-08T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4973/game-of-thrones-3x02-dark-wings-dark-words", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/08/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Walk of Punishment", + "airDate": "2013-04-15T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4974/game-of-thrones-3x03-walk-of-punishment", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/15/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "And Now His Watch is Ended", + "airDate": "2013-04-22T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4975/game-of-thrones-3x04-and-now-his-watch-is-ended", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/22/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Kissed by Fire", + "airDate": "2013-04-29T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4976/game-of-thrones-3x05-kissed-by-fire", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/29/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "The Climb", + "airDate": "2013-05-06T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4977/game-of-thrones-3x06-the-climb", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/06/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Bear and the Maiden Fair", + "airDate": "2013-05-13T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4978/game-of-thrones-3x07-the-bear-and-the-maiden-fair", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/13/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "Second Sons", + "airDate": "2013-05-20T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4979/game-of-thrones-3x08-second-sons", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/20/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The Rains of Castamere", + "airDate": "2013-06-03T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4980/game-of-thrones-3x09-the-rains-of-castamere", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/03/2013 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Mhysa", + "airDate": "2013-06-10T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4981/game-of-thrones-3x10-mhysa", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/10/2013 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 4, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Two Swords", + "airDate": "2014-04-07T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4982/game-of-thrones-4x01-two-swords", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/07/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Lion and the Rose", + "airDate": "2014-04-14T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4983/game-of-thrones-4x02-the-lion-and-the-rose", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/14/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Breaker of Chains", + "airDate": "2014-04-21T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4984/game-of-thrones-4x03-breaker-of-chains", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/21/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Oathkeeper", + "airDate": "2014-04-28T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4985/game-of-thrones-4x04-oathkeeper", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/28/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "First of His Name", + "airDate": "2014-05-05T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4986/game-of-thrones-4x05-first-of-his-name", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/05/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "The Laws of Gods and Men", + "airDate": "2014-05-12T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4987/game-of-thrones-4x06-the-laws-of-gods-and-men", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/12/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "Mockingbird", + "airDate": "2014-05-19T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4988/game-of-thrones-4x07-mockingbird", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/19/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Mountain and the Viper", + "airDate": "2014-06-02T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4989/game-of-thrones-4x08-the-mountain-and-the-viper", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/02/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The Watchers on the Wall", + "airDate": "2014-06-09T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4990/game-of-thrones-4x09-the-watchers-on-the-wall", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/09/2014 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "The Children", + "airDate": "2014-06-16T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/4991/game-of-thrones-4x10-the-children", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/16/2014 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 5, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "The Wars to Come", + "airDate": "2015-04-13T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/116522/game-of-thrones-5x01-the-wars-to-come", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/13/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The House of Black and White", + "airDate": "2015-04-20T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/144328/game-of-thrones-5x02-the-house-of-black-and-white", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/20/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "High Sparrow", + "airDate": "2015-04-27T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/144329/game-of-thrones-5x03-high-sparrow", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/27/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Sons of the Harpy", + "airDate": "2015-05-04T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/144330/game-of-thrones-5x04-sons-of-the-harpy", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/04/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Kill the Boy", + "airDate": "2015-05-11T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/151777/game-of-thrones-5x05-kill-the-boy", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/11/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Unbowed, Unbent, Unbroken", + "airDate": "2015-05-18T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/152766/game-of-thrones-5x06-unbowed-unbent-unbroken", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/18/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Gift", + "airDate": "2015-05-25T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/153327/game-of-thrones-5x07-the-gift", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/25/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "Hardhome", + "airDate": "2015-06-01T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/155299/game-of-thrones-5x08-hardhome", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/01/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The Dance of Dragons", + "airDate": "2015-06-08T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/160040/game-of-thrones-5x09-the-dance-of-dragons", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/08/2015 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Mother's Mercy", + "airDate": "2015-06-15T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/162186/game-of-thrones-5x10-mothers-mercy", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/15/2015 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 6, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "The Red Woman", + "airDate": "2016-04-25T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/560813/game-of-thrones-6x01-the-red-woman", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/25/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Home", + "airDate": "2016-05-02T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/664672/game-of-thrones-6x02-home", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/02/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Oathbreaker", + "airDate": "2016-05-09T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/664673/game-of-thrones-6x03-oathbreaker", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/09/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Book of the Stranger", + "airDate": "2016-05-16T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/664674/game-of-thrones-6x04-book-of-the-stranger", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/16/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Door", + "airDate": "2016-05-23T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/664675/game-of-thrones-6x05-the-door", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/23/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Blood of My Blood", + "airDate": "2016-05-30T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/664676/game-of-thrones-6x06-blood-of-my-blood", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/30/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Broken Man", + "airDate": "2016-06-06T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/717449/game-of-thrones-6x07-the-broken-man", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/06/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "No One", + "airDate": "2016-06-13T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/729573/game-of-thrones-6x08-no-one", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/13/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Battle of the Bastards", + "airDate": "2016-06-20T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/729574/game-of-thrones-6x09-battle-of-the-bastards", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/20/2016 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "The Winds of Winter", + "airDate": "2016-06-27T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/729575/game-of-thrones-6x10-the-winds-of-winter", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "06/27/2016 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 7, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Dragonstone", + "airDate": "2017-07-17T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/937256/game-of-thrones-7x01-dragonstone", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "07/17/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Stormborn", + "airDate": "2017-07-24T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221410/game-of-thrones-7x02-stormborn", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "07/24/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "The Queen's Justice", + "airDate": "2017-07-31T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221411/game-of-thrones-7x03-the-queens-justice", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "07/31/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "The Spoils of War", + "airDate": "2017-08-07T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221412/game-of-thrones-7x04-the-spoils-of-war", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "08/07/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Eastwatch", + "airDate": "2017-08-14T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221413/game-of-thrones-7x05-eastwatch", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "08/14/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Beyond the Wall", + "airDate": "2017-08-21T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221414/game-of-thrones-7x06-beyond-the-wall", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "08/21/2017 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Dragon and the Wolf", + "airDate": "2017-08-28T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1221415/game-of-thrones-7x07-the-dragon-and-the-wolf", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "08/28/2017 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 8, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Winterfell", + "airDate": "2019-04-15T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1590943/game-of-thrones-8x01-winterfell", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/15/2019 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "A Knight of the Seven Kingdoms", + "airDate": "2019-04-22T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1623964/game-of-thrones-8x02-a-knight-of-the-seven-kingdoms", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/22/2019 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "The Long Night", + "airDate": "2019-04-29T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1623965/game-of-thrones-8x03-the-long-night", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/29/2019 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "The Last of the Starks", + "airDate": "2019-05-06T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1623966/game-of-thrones-8x04-the-last-of-the-starks", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/06/2019 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Bells", + "airDate": "2019-05-13T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1623967/game-of-thrones-8x05-the-bells", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/13/2019 02:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "The Iron Throne", + "airDate": "2019-05-20T02:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1623968/game-of-thrones-8x06-the-iron-throne", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "05/20/2019 02:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + } + ], + "requestAll": false, + "firstSeason": false, + "latestSeason": false, + "fullyAvailable": false, + "partlyAvailable": false, + "type": 0, + "backdropPath": null, + "id": 121361, + "approved": false, + "denied": null, + "deniedReason": null, + "requested": false, + "requestId": 0, + "available": false, + "plexUrl": null, + "embyUrl": null, + "jellyfinUrl": null, + "quality": null, + "imdbId": "tt0944947", + "theTvDbId": null, + "theMovieDbId": "121361", + "subscribed": false, + "showSubscribe": false +} \ No newline at end of file diff --git a/tests/cypress/support/index.ts b/tests/cypress/support/index.ts index e7b106186..4e067b3db 100644 --- a/tests/cypress/support/index.ts +++ b/tests/cypress/support/index.ts @@ -17,6 +17,7 @@ import './commands' import './request.commands'; import "cypress-real-events/support"; +import '@bahmutov/cy-api/support'; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/tests/cypress/tests/api/v1/tv-search.api.spec.ts b/tests/cypress/tests/api/v1/tv-search.api.spec.ts new file mode 100644 index 000000000..c228323c3 --- /dev/null +++ b/tests/cypress/tests/api/v1/tv-search.api.spec.ts @@ -0,0 +1,31 @@ +import { movieDetailsPage as Page } from "@/integration/page-objects"; + +describe("TV Search V1 API tests", () => { + beforeEach(() => { + cy.login(); + }); + + it("Get Extra TV Info", () => { + cy.api({url: '/api/v1/search/tv/info/121361', headers: { 'Authorization': 'Bearer ' + window.localStorage.getItem('id_token')} }) + .then((res) => { + expect(res.status).equal(200); + cy.fixture('api/v1/tv-search-extra-info').then(x => { + expect(res.body).deep.equal(x); + }) + }); + }); + + it("Popular TV", () => { + cy.api({url: '/api/v1/search/tv/popular', headers: { 'Authorization': 'Bearer ' + window.localStorage.getItem('id_token')} }) + .then((res) => { + expect(res.status).equal(200); + const body = res.body; + expect(body.length).is.greaterThan(0); + expect(body[0].title).is.not.null; + expect(body[0].id).is.not.null; + expect(body[0].id).to.be.an('number'); + }); + }); + + +}); diff --git a/tests/package.json b/tests/package.json index 850a2fe63..5c396d371 100644 --- a/tests/package.json +++ b/tests/package.json @@ -1,5 +1,6 @@ { "devDependencies": { + "@bahmutov/cy-api": "^1.5.0", "cypress": "6.8.0", "cypress-wait-until": "^1.7.1", "typescript": "^4.2.3" diff --git a/tests/tsconfig.json b/tests/tsconfig.json index 0c8f23ff6..e87d106fd 100644 --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es5", "lib": ["es2018", "dom"], - "types": ["cypress", "cypress-wait-until", "cypress-image-snapshot", "cypress-real-events"], + "types": ["cypress", "cypress-wait-until", "cypress-image-snapshot", "cypress-real-events", "@bahmutov/cy-api"], "baseUrl": "./cypress", "paths": { "@/*": ["./*"] diff --git a/tests/yarn.lock b/tests/yarn.lock index a271dcc79..49e11b23f 100644 --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@bahmutov/cy-api@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@bahmutov/cy-api/-/cy-api-1.5.0.tgz#e6569f1d0f3040e55f97cf151a16932bfb10dcc6" + integrity sha512-N1pBawxcwXyDpJx0qwd78k/6yFEyHWVC71N7n78Rnaegs3LR1Z0odZJrKurpb56JFaP4abNm6EONXEEi5boMmQ== + dependencies: + common-tags "1.8.0" + "@cypress/listr-verbose-renderer@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" @@ -330,7 +337,7 @@ commander@^5.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -common-tags@^1.8.0: +common-tags@1.8.0, common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==