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 @@ namespace Ombi.Core 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.Store.Entities; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using System.Threading; +using TraktSharp.Entities; namespace Ombi.Core.Engine { @@ -51,18 +52,18 @@ namespace Ombi.Core.Engine 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 @@ namespace Ombi.Core.Engine 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 @@ namespace Ombi.Core.Engine 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 @@ namespace Ombi.Core.Engine 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 @@ namespace Ombi.Core.Engine 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 TraktSharp.Entities; using Microsoft.EntityFrameworkCore; using System.Threading; using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; namespace Ombi.Core.Engine.V2 { @@ -30,16 +31,18 @@ namespace Ombi.Core.Engine.V2 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 @@ namespace Ombi.Core.Engine.V2 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 @@ namespace Ombi.Core.Engine.V2 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 @@ namespace Ombi.Core.Rule.Rules.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/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 17d3ad776..c67ad1129 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -198,6 +198,7 @@ export class DiscoverCardComponent implements OnInit { this.result.url = updated.imdbId; this.result.overview = updated.overview; this.result.approved = updated.approved; + this.result.available = updated.fullyAvailable; this.fullyLoaded = true; } 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 @@ namespace Ombi.Controllers.V2 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 @@ namespace Ombi.Controllers.V2 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 @@ namespace Ombi.Controllers.V2 [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 @@ namespace Ombi.Controllers.V2 [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 @@ namespace Ombi.Controllers.V2 [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 @@ namespace Ombi.Controllers.V2 [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..03b894eb2 --- /dev/null +++ b/tests/cypress/fixtures/api/v1/tv-search-extra-info.json @@ -0,0 +1,1211 @@ +{ + "title": "Schitt's Creek", + "aliases": null, + "banner": "https://static.tvmaze.com/uploads/images/medium_portrait/279/697623.jpg", + "seriesId": 1775, + "status": "Ended", + "firstAired": "2015-01-13", + "network": "CBC", + "networkId": "36", + "runtime": "30", + "genre": null, + "overview": "Schitt's Creek centers on a formerly filthy rich video store magnate Johnny Rose, his soap star wife Moira, and their two kids, über-hipster son David and socialite daughter Alexis, who suddenly find themselves broke. They are forced to live in Schitt's Creek, a small depressing town they once bought as a joke.", + "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": "Our Cup Runneth Over", + "airDate": "2015-01-14T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153107/schitts-creek-1x01-our-cup-runneth-over", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/14/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Drip", + "airDate": "2015-01-14T01:30:00+00:00", + "url": "https://www.tvmaze.com/episodes/153108/schitts-creek-1x02-the-drip", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/14/2015 01:30:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Don't Worry, It's His Sister", + "airDate": "2015-01-21T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153109/schitts-creek-1x03-dont-worry-its-his-sister", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/21/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Bad Parents", + "airDate": "2015-01-28T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153110/schitts-creek-1x04-bad-parents", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/28/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Cabin", + "airDate": "2015-02-04T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153111/schitts-creek-1x05-the-cabin", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/04/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Wine and Roses", + "airDate": "2015-02-11T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153112/schitts-creek-1x06-wine-and-roses", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/11/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "Turkey Shoot", + "airDate": "2015-02-18T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153113/schitts-creek-1x07-turkey-shoot", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/18/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "Allez-Vous", + "airDate": "2015-02-25T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153114/schitts-creek-1x08-allez-vous", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/25/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Carl's Funeral", + "airDate": "2015-03-04T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153115/schitts-creek-1x09-carls-funeral", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/04/2015 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Honeymoon", + "airDate": "2015-03-11T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153116/schitts-creek-1x10-honeymoon", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/11/2015 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "Little Sister", + "airDate": "2015-03-18T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153117/schitts-creek-1x11-little-sister", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/18/2015 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "Surprise Party", + "airDate": "2015-03-25T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/153118/schitts-creek-1x12-surprise-party", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/25/2015 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 13, + "title": "Town for Sale", + "airDate": "2015-04-01T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/153119/schitts-creek-1x13-town-for-sale", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/01/2015 01:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 2, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Finding David", + "airDate": "2016-01-13T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/536724/schitts-creek-2x01-finding-david", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/13/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Family Dinner", + "airDate": "2016-01-13T01:30:00+00:00", + "url": "https://www.tvmaze.com/episodes/556373/schitts-creek-2x02-family-dinner", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/13/2016 01:30:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Jazzagals", + "airDate": "2016-01-20T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/556375/schitts-creek-2x03-jazzagals", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/20/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Estate Sale", + "airDate": "2016-01-27T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/560290/schitts-creek-2x04-estate-sale", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/27/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Bob's Bagels", + "airDate": "2016-02-03T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/560291/schitts-creek-2x05-bobs-bagels", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/03/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Moira vs. Town Council", + "airDate": "2016-02-10T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/589337/schitts-creek-2x06-moira-vs-town-council", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/10/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Candidate", + "airDate": "2016-02-17T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/589338/schitts-creek-2x07-the-candidate", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/17/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "Milk Money", + "airDate": "2016-02-24T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/589339/schitts-creek-2x08-milk-money", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/24/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Moira's Nudes", + "airDate": "2016-03-02T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/619485/schitts-creek-2x09-moiras-nudes", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/02/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Ronnie's Party", + "airDate": "2016-03-09T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/619536/schitts-creek-2x10-ronnies-party", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/09/2016 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "The Motel Guest", + "airDate": "2016-03-16T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/619538/schitts-creek-2x11-the-motel-guest", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/16/2016 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "Lawn Signs", + "airDate": "2016-03-23T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/619540/schitts-creek-2x12-lawn-signs", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/23/2016 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 13, + "title": "Happy Anniversary", + "airDate": "2016-03-30T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/668674/schitts-creek-2x13-happy-anniversary", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/30/2016 01:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 3, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Opening Night", + "airDate": "2017-01-11T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/989369/schitts-creek-3x01-opening-night", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/11/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Throuple", + "airDate": "2017-01-18T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032814/schitts-creek-3x02-the-throuple", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/18/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "New Car", + "airDate": "2017-01-25T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032816/schitts-creek-3x03-new-car", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/25/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Driving Test", + "airDate": "2017-02-01T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032817/schitts-creek-3x04-driving-test", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/01/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Rooms by the Hour", + "airDate": "2017-02-08T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032818/schitts-creek-3x05-rooms-by-the-hour", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/08/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Murder Mystery", + "airDate": "2017-02-15T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032819/schitts-creek-3x06-murder-mystery", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/15/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "General Store", + "airDate": "2017-02-22T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032820/schitts-creek-3x07-general-store", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/22/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "Motel Review", + "airDate": "2017-03-01T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032821/schitts-creek-3x08-motel-review", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/01/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The Affair", + "airDate": "2017-03-08T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032822/schitts-creek-3x09-the-affair", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/08/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Sebastien Raine", + "airDate": "2017-03-15T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032823/schitts-creek-3x10-sebastien-raine", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/15/2017 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "Stop Saying Lice!", + "airDate": "2017-03-22T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1032824/schitts-creek-3x11-stop-saying-lice", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/22/2017 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "Friends and Family", + "airDate": "2017-03-29T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1032825/schitts-creek-3x12-friends-and-family", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/29/2017 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 13, + "title": "Grad Night", + "airDate": "2017-04-05T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1032826/schitts-creek-3x13-grad-night", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/05/2017 01:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 4, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Dead Guy in Room 4", + "airDate": "2018-01-10T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1355590/schitts-creek-4x01-dead-guy-in-room-4", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/10/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Pregnancy Test", + "airDate": "2018-01-17T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1385778/schitts-creek-4x02-pregnancy-test", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/17/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "Asbestos Fest", + "airDate": "2018-01-24T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1385779/schitts-creek-4x03-asbestos-fest", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/24/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Girls' Night", + "airDate": "2018-01-31T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1385780/schitts-creek-4x04-girls-night", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/31/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "RIP Moira Rose", + "airDate": "2018-02-07T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1401392/schitts-creek-4x05-rip-moira-rose", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/07/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Open Mic", + "airDate": "2018-02-28T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1401393/schitts-creek-4x06-open-mic", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/28/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "The Barbecue", + "airDate": "2018-03-07T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1401394/schitts-creek-4x07-the-barbecue", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/07/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Jazzaguy", + "airDate": "2018-03-14T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1401395/schitts-creek-4x08-the-jazzaguy", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/14/2018 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The Olive Branch", + "airDate": "2018-03-21T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1401396/schitts-creek-4x09-the-olive-branch", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/21/2018 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Baby Sprinkle", + "airDate": "2018-03-28T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1401397/schitts-creek-4x10-baby-sprinkle", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/28/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "The Rollout", + "airDate": "2018-04-04T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1401398/schitts-creek-4x11-the-rollout", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/04/2018 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "Singles Week", + "airDate": "2018-04-11T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1401399/schitts-creek-4x12-singles-week", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/11/2018 01:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 5, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "The Crowening", + "airDate": "2019-01-09T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1557028/schitts-creek-5x01-the-crowening", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/09/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "Love Letters", + "airDate": "2019-01-16T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1577763/schitts-creek-5x02-love-letters", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/16/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "The Plant", + "airDate": "2019-01-23T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1586322/schitts-creek-5x03-the-plant", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/23/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "The Dress", + "airDate": "2019-01-30T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1586323/schitts-creek-5x04-the-dress", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/30/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "Housewarming", + "airDate": "2019-02-06T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1586324/schitts-creek-5x05-housewarming", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/06/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "Rock On!", + "airDate": "2019-02-13T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1600327/schitts-creek-5x06-rock-on", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/13/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "A Whisper of Desire", + "airDate": "2019-02-20T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1600328/schitts-creek-5x07-a-whisper-of-desire", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/20/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Hospies", + "airDate": "2019-02-27T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1600329/schitts-creek-5x08-the-hospies", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/27/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "The M.V.P.", + "airDate": "2019-03-06T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1600330/schitts-creek-5x09-the-mvp", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/06/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Roadkill", + "airDate": "2019-03-13T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1612418/schitts-creek-5x10-roadkill", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/13/2019 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "Meet the Parents", + "airDate": "2019-03-20T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1612419/schitts-creek-5x11-meet-the-parents", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/20/2019 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "The Roast", + "airDate": "2019-03-27T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1617469/schitts-creek-5x12-the-roast", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/27/2019 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 13, + "title": "The Hike", + "airDate": "2019-04-03T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1619543/schitts-creek-5x13-the-hike", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/03/2019 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 14, + "title": "Life Is a Cabaret", + "airDate": "2019-04-10T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1620060/schitts-creek-5x14-life-is-a-cabaret", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/10/2019 01:00:00", + "requestStatus": "", + "id": 0 + } + ], + "childRequestId": 0, + "childRequest": null, + "seasonAvailable": false, + "id": 0 + }, + { + "seasonNumber": 6, + "overview": null, + "episodes": [ + { + "episodeNumber": 1, + "title": "Smoke Signals", + "airDate": "2020-01-08T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1717547/schitts-creek-6x01-smoke-signals", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/08/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 2, + "title": "The Incident", + "airDate": "2020-01-15T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1783459/schitts-creek-6x02-the-incident", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/15/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 3, + "title": "The Job Interview", + "airDate": "2020-01-22T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1783460/schitts-creek-6x03-the-job-interview", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/22/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 4, + "title": "Maid of Honour", + "airDate": "2020-01-29T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1783461/schitts-creek-6x04-maid-of-honour", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "01/29/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 5, + "title": "The Premiere", + "airDate": "2020-02-05T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1783462/schitts-creek-6x05-the-premiere", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/05/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 6, + "title": "The Wingman", + "airDate": "2020-02-12T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1783463/schitts-creek-6x06-the-wingman", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/12/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 7, + "title": "Moira Rosé", + "airDate": "2020-02-19T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1800956/schitts-creek-6x07-moira-rose", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/19/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 8, + "title": "The Presidential Suite", + "airDate": "2020-02-26T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1800957/schitts-creek-6x08-the-presidential-suite", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "02/26/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 9, + "title": "Rebound", + "airDate": "2020-03-04T01:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1805635/schitts-creek-6x09-rebound", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/04/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 10, + "title": "Sunrise, Sunset", + "airDate": "2020-03-11T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1810289/schitts-creek-6x10-sunrise-sunset", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/11/2020 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 11, + "title": "The Bachelor Party", + "airDate": "2020-03-18T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1813833/schitts-creek-6x11-the-bachelor-party", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/18/2020 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 12, + "title": "The Pitch", + "airDate": "2020-03-25T00:00:00+00:00", + "url": "https://www.tvmaze.com/episodes/1816395/schitts-creek-6x12-the-pitch", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "03/25/2020 00:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 13, + "title": "Start Spreading the News", + "airDate": "2020-04-01T01:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1816396/schitts-creek-6x13-start-spreading-the-news", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/01/2020 01:00:00", + "requestStatus": "", + "id": 0 + }, + { + "episodeNumber": 14, + "title": "Happy Ending", + "airDate": "2020-04-08T00:00:00+01:00", + "url": "https://www.tvmaze.com/episodes/1816397/schitts-creek-6x14-happy-ending", + "available": false, + "approved": false, + "requested": false, + "seasonId": 0, + "season": null, + "airDateDisplay": "04/08/2020 00: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": 287247, + "approved": false, + "denied": null, + "deniedReason": null, + "requested": false, + "requestId": 0, + "available": false, + "plexUrl": null, + "embyUrl": null, + "jellyfinUrl": null, + "quality": null, + "imdbId": "tt3526078", + "theTvDbId": null, + "theMovieDbId": "287247", + "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..e957f5533 --- /dev/null +++ b/tests/cypress/tests/api/v1/tv-search.api.spec.ts @@ -0,0 +1,51 @@ +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/287247', 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("TV Basic Search", () => { + cy.api({url: '/api/v1/search/tv/Shitts Creek', headers: { 'Authorization': 'Bearer ' + window.localStorage.getItem('id_token')} }) + .then((res) => { + expect(res.status).equal(200); + const body = res.body; + expect(body[0].title).is.equal("Schitt's Creek") + expect(body[0].status).is.equal("Ended"); + expect(body[0].id).is.not.null; + expect(body[0].id).to.be.an('number'); + }); + }); + +const types = [ + 'popular', + 'trending', + 'anticipated', + 'mostwatched' + ]; + + types.forEach((type) => { + // derive test name from data + it(`${type} TV List`, () => { + cy.api({url: '/api/v1/search/tv/'+type, 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/cypress/tests/discover/discover-cards-requests.spec.ts b/tests/cypress/tests/discover/discover-cards-requests.spec.ts index 3688d524b..20ff542d1 100644 --- a/tests/cypress/tests/discover/discover-cards-requests.spec.ts +++ b/tests/cypress/tests/discover/discover-cards-requests.spec.ts @@ -227,6 +227,37 @@ describe("Discover Cards Requests Tests", () => { }); }); + it.only("Available TV (From Details Call) does not allow us to request", () => { + cy.intercept("GET", "**/search/Tv/popular/**").as("cardsResponse"); + window.localStorage.setItem("DiscoverOptions2", "3"); + + Page.visit(); + + cy.wait("@cardsResponse").then((res) => { + const body = res.response.body; + var expectedId = body[1].id; + cy.intercept("GET", "**/search/Tv/moviedb/"+expectedId, (req) => { + req.reply((res2) => { + const body = res2.body; + body.fullyAvailable = true; + res2.send(body); + }); + }).as("movieDbResponse"); + var title = body[1].title; + + + cy.wait("@movieDbResponse") + + const card = Page.popularCarousel.getCard(expectedId, true, DiscoverType.Popular); + card.title.realHover(); + + card.verifyTitle(title); + card.requestButton.should("not.exist"); + card.availabilityText.should("have.text", "Available"); + card.statusClass.should("have.class", "available"); + }); + }); + it("Not available TV allow admin to request", () => { cy.intercept("GET", "**/search/Tv/popular/**", (req) => { req.reply((res) => { 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==