Added a bunch of categories for tv search similar to what we have for movies.

pull/963/head
Jamie.Rees 8 years ago
parent 7cbea541ce
commit 9886c40499

@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using TraktApiSharp.Enums;
using TraktApiSharp.Objects.Get.Shows;
using TraktApiSharp.Objects.Get.Shows.Common;
namespace Ombi.Api.Interfaces
{
public interface ITraktApi
{
Task<IEnumerable<TraktMostAnticipatedShow>> GetAnticipatedShows(int? page = default(int?), int? limitPerPage = default(int?));
Task<IEnumerable<TraktMostWatchedShow>> GetMostWatchesShows(TraktTimePeriod period = null, int? page = default(int?), int? limitPerPage = default(int?));
Task<IEnumerable<TraktShow>> GetPopularShows(int? page = default(int?), int? limitPerPage = default(int?));
Task<IEnumerable<TraktTrendingShow>> GetTrendingShows(int? page = default(int?), int? limitPerPage = default(int?));
}
}

@ -31,6 +31,10 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath> <HintPath>..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -43,6 +47,10 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="TraktApiSharp, Version=0.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TraktApiSharp.0.8.0\lib\portable-net45+netcore45+wpa81\TraktApiSharp.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="IApiRequest.cs" /> <Compile Include="IApiRequest.cs" />
@ -58,6 +66,7 @@
<Compile Include="IPushoverApi.cs" /> <Compile Include="IPushoverApi.cs" />
<Compile Include="ISickRageApi.cs" /> <Compile Include="ISickRageApi.cs" />
<Compile Include="ISonarrApi.cs" /> <Compile Include="ISonarrApi.cs" />
<Compile Include="ITraktApi.cs" />
<Compile Include="IWatcherApi.cs" /> <Compile Include="IWatcherApi.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="RestSharp" version="105.2.3" targetFramework="net45" /> <package id="RestSharp" version="105.2.3" targetFramework="net45" />
<package id="TraktApiSharp" version="0.8.0" targetFramework="net45" />
</packages> </packages>

@ -66,12 +66,17 @@
<HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath> <HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="TraktApiSharp, Version=0.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TraktApiSharp.0.8.0\lib\portable-net45+netcore45+wpa81\TraktApiSharp.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ApiRequest.cs" /> <Compile Include="ApiRequest.cs" />
<Compile Include="DiscordApi.cs" /> <Compile Include="DiscordApi.cs" />
<Compile Include="NetflixRouletteApi.cs" /> <Compile Include="NetflixRouletteApi.cs" />
<Compile Include="RadarrApi.cs" /> <Compile Include="RadarrApi.cs" />
<Compile Include="TraktApi.cs" />
<Compile Include="WatcherApi.cs" /> <Compile Include="WatcherApi.cs" />
<Compile Include="MusicBrainzApi.cs" /> <Compile Include="MusicBrainzApi.cs" />
<Compile Include="SlackApi.cs" /> <Compile Include="SlackApi.cs" />

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ombi.Api.Interfaces;
using Ombi.Helpers;
using TraktApiSharp;
using TraktApiSharp.Enums;
using TraktApiSharp.Objects.Get.Shows;
using TraktApiSharp.Objects.Get.Shows.Common;
using TraktApiSharp.Requests.Params;
namespace Ombi.Api
{
public class TraktApi : ITraktApi
{
private TraktClient Client { get; }
private static readonly string Encrypted = "z/56wM/oEkkCWEvSIZCrzQyUvvqmafQ3njqf0UNK5xuKbNYh5Wz8ocoG2QDa5y1DBkozLaKsGxORmAB1XUvwbnom8DVNo9gE++9GTuwxmGlLDD318PXpRmYmpKqNwFSKRZgF6ewiY9qR4t3iG0pGQwPA08FK3+H7kpOKAGJNR9RMDP9wwB6Vl4DuOiZb9/DETjzZ+/zId0ZqimrbN+PLrg==";
private readonly string _apiKey = StringCipher.Decrypt(Encrypted, "ApiKey");
public TraktApi()
{
Client = new TraktClient(_apiKey);
}
public async Task<IEnumerable<TraktShow>> GetPopularShows(int? page = null, int? limitPerPage = null)
{
var popular = await Client.Shows.GetPopularShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
return popular.Items;
}
public async Task<IEnumerable<TraktTrendingShow>> GetTrendingShows(int? page = null, int? limitPerPage = null)
{
var trendingShowsTop10 = await Client.Shows.GetTrendingShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
return trendingShowsTop10.Items;
}
public async Task<IEnumerable<TraktMostAnticipatedShow>> GetAnticipatedShows(int? page = null, int? limitPerPage = null)
{
var anticipatedShows = await Client.Shows.GetMostAnticipatedShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
return anticipatedShows.Items;
}
public async Task<IEnumerable<TraktMostWatchedShow>> GetMostWatchesShows(TraktTimePeriod period = null, int? page = null, int? limitPerPage = null)
{
var anticipatedShows = await Client.Shows.GetMostWatchedShowsAsync(period ?? TraktTimePeriod.Monthly, new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
return anticipatedShows.Items;
}
}
}

@ -8,4 +8,5 @@
<package id="RestSharp" version="105.2.3" targetFramework="net45" /> <package id="RestSharp" version="105.2.3" targetFramework="net45" />
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" /> <package id="System.Net.Http" version="4.0.0" targetFramework="net45" />
<package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" /> <package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" />
<package id="TraktApiSharp" version="0.8.0" targetFramework="net45" />
</packages> </packages>

@ -46,5 +46,12 @@ namespace Ombi.Helpers
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime; return dtDateTime;
} }
public static long ToJavascriptTimestamp(this DateTime input)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var time = input.Subtract(new TimeSpan(epoch.Ticks));
return (long)(time.Ticks / 10000);
}
} }
} }

@ -72,6 +72,25 @@ $(function () {
moviesInTheaters(); moviesInTheaters();
}); });
// TV DropDown
$('#popularShows').on('click', function (e) {
e.preventDefault();
popularShows();
});
$('#trendingShows').on('click', function (e) {
e.preventDefault();
trendingTv();
});
$('#mostWatchedShows').on('click', function (e) {
e.preventDefault();
mostwatchedTv();
});
$('#anticipatedShows').on('click', function (e) {
e.preventDefault();
anticipatedTv();
});
// Type in TV search // Type in TV search
$("#tvSearchContent").on("input", function () { $("#tvSearchContent").on("input", function () {
if (searchTimer) { if (searchTimer) {
@ -293,6 +312,23 @@ $(function () {
getMovies(url); getMovies(url);
} }
function popularShows() {
var url = createBaseUrl(base, '/search/tv/popular');
getTvShows(url, true);
}
function anticipatedTv() {
var url = createBaseUrl(base, '/search/tv/anticipated');
getTvShows(url, true);
}
function trendingTv() {
var url = createBaseUrl(base, '/search/tv/trending');
getTvShows(url, true);
}
function mostwatchedTv() {
var url = createBaseUrl(base, '/search/tv/mostwatched');
getTvShows(url, true);
}
function getMovies(url) { function getMovies(url) {
resetMovies(); resetMovies();
@ -323,10 +359,10 @@ $(function () {
var query = $("#tvSearchContent").val(); var query = $("#tvSearchContent").val();
var url = createBaseUrl(base, '/search/tv/'); var url = createBaseUrl(base, '/search/tv/');
query ? getTvShows(url + query) : resetTvShows(); query ? getTvShows(url + query, false) : resetTvShows();
} }
function getTvShows(url) { function getTvShows(url, loadImage) {
resetTvShows(); resetTvShows();
$('#tvSearchButton').attr("class", "fa fa-spinner fa-spin"); $('#tvSearchButton').attr("class", "fa fa-spinner fa-spin");
@ -338,7 +374,9 @@ $(function () {
$("#tvList").append(html); $("#tvList").append(html);
checkNetflix(context.title, context.id); checkNetflix(context.title, context.id);
if (loadImage) {
getTvPoster(result.id);
}
}); });
} }
else { else {
@ -406,6 +444,16 @@ $(function () {
}); });
}; };
function getTvPoster(theTvDbId) {
var url = createBaseUrl(base, '/search/tv/poster/');
$.ajax(url + theTvDbId).success(function (result) {
if (result) {
$('#' + theTvDbId + "imgDiv").html(" <img class='img-responsive' src='" + result + "' width='150' alt='poster'>");
}
});
};
function buildMovieContext(result) { function buildMovieContext(result) {
var date = new Date(result.releaseDate); var date = new Date(result.releaseDate);
var year = date.getFullYear(); var year = date.getFullYear();
@ -432,6 +480,7 @@ $(function () {
var date = new Date(result.firstAired); var date = new Date(result.firstAired);
var year = date.getFullYear(); var year = date.getFullYear();
var context = { var context = {
status : result.status,
posterPath: result.banner, posterPath: result.banner,
id: result.id, id: result.id,
title: result.seriesName, title: result.seriesName,
@ -448,7 +497,9 @@ $(function () {
tvPartialAvailable: result.tvPartialAvailable, tvPartialAvailable: result.tvPartialAvailable,
disableTvRequestsByEpisode: result.disableTvRequestsByEpisode, disableTvRequestsByEpisode: result.disableTvRequestsByEpisode,
disableTvRequestsBySeason: result.disableTvRequestsBySeason, disableTvRequestsBySeason: result.disableTvRequestsBySeason,
enableTvRequestsForOnlySeries: result.enableTvRequestsForOnlySeries enableTvRequestsForOnlySeries: result.enableTvRequestsForOnlySeries,
trailer: result.trailer,
homepage: result.homepage
}; };
return context; return context;

@ -58,5 +58,20 @@ namespace Ombi.UI.Models
public bool DisableTvRequestsByEpisode { get; set; } public bool DisableTvRequestsByEpisode { get; set; }
public bool DisableTvRequestsBySeason { get; set; } public bool DisableTvRequestsBySeason { get; set; }
public bool EnableTvRequestsForOnlySeries { get; set; } public bool EnableTvRequestsForOnlySeries { get; set; }
/// <summary>
/// This is used from the Trakt API
/// </summary>
/// <value>
/// The trailer.
/// </value>
public string Trailer { get; set; }
/// <summary>
/// This is used from the Trakt API
/// </summary>
/// <value>
/// The trailer.
/// </value>
public string Homepage { get; set; }
} }
} }

@ -58,6 +58,7 @@ using Ombi.Store.Repository;
using Ombi.UI.Helpers; using Ombi.UI.Helpers;
using Ombi.UI.Models; using Ombi.UI.Models;
using TMDbLib.Objects.General; using TMDbLib.Objects.General;
using TraktApiSharp.Objects.Get.Shows;
using Action = Ombi.Helpers.Analytics.Action; using Action = Ombi.Helpers.Analytics.Action;
using EpisodesModel = Ombi.Store.EpisodesModel; using EpisodesModel = Ombi.Store.EpisodesModel;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions; using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
@ -76,7 +77,7 @@ namespace Ombi.UI.Modules
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth, ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth,
IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email, IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content, IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content,
ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher) ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher, ITraktApi traktApi)
: base("search", prSettings, security) : base("search", prSettings, security)
{ {
Auth = auth; Auth = auth;
@ -109,6 +110,7 @@ namespace Ombi.UI.Modules
MovieSender = movieSender; MovieSender = movieSender;
WatcherCacher = watcherCacher; WatcherCacher = watcherCacher;
RadarrCacher = radarrCacher; RadarrCacher = radarrCacher;
TraktApi = traktApi;
Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad(); Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad();
@ -120,6 +122,13 @@ namespace Ombi.UI.Modules
Get["movie/upcoming", true] = async (x, ct) => await UpcomingMovies(); Get["movie/upcoming", true] = async (x, ct) => await UpcomingMovies();
Get["movie/playing", true] = async (x, ct) => await CurrentlyPlayingMovies(); Get["movie/playing", true] = async (x, ct) => await CurrentlyPlayingMovies();
Get["tv/popular", true] = async (x, ct) => await ProcessShows(ShowSearchType.Popular);
Get["tv/trending", true] = async (x, ct) => await ProcessShows(ShowSearchType.Trending);
Get["tv/mostwatched", true] = async (x, ct) => await ProcessShows(ShowSearchType.MostWatched);
Get["tv/anticipated", true] = async (x, ct) => await ProcessShows(ShowSearchType.Anticipated);
Get["tv/poster/{id}"] = p => GetTvPoster((int)p.id);
Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId); Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId);
Post["request/tv", true] = Post["request/tv", true] =
async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons); async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
@ -129,6 +138,7 @@ namespace Ombi.UI.Modules
Get["/seasons"] = x => GetSeasons(); Get["/seasons"] = x => GetSeasons();
Get["/episodes", true] = async (x, ct) => await GetEpisodes(); Get["/episodes", true] = async (x, ct) => await GetEpisodes();
} }
private ITraktApi TraktApi { get; }
private IWatcherCacher WatcherCacher { get; } private IWatcherCacher WatcherCacher { get; }
private IMovieSender MovieSender { get; } private IMovieSender MovieSender { get; }
private IRepository<PlexContent> PlexContentRepository { get; } private IRepository<PlexContent> PlexContentRepository { get; }
@ -190,6 +200,17 @@ namespace Ombi.UI.Modules
return await ProcessMovies(MovieSearchType.Search, searchTerm); return await ProcessMovies(MovieSearchType.Search, searchTerm);
} }
private Response GetTvPoster(int theTvDbId)
{
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
var banner = result.image?.medium;
if (!string.IsNullOrEmpty(banner))
{
banner = banner.Replace("http", "https"); // Always use the Https banners
}
return banner;
}
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm) private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
{ {
List<MovieResult> apiMovies; List<MovieResult> apiMovies;
@ -322,6 +343,186 @@ namespace Ombi.UI.Modules
return true; return true;
} }
private async Task<Response> ProcessShows(ShowSearchType type)
{
var shows = new List<SearchTvShowViewModel>();
var prSettings = await PrService.GetSettingsAsync();
switch (type)
{
case ShowSearchType.Popular:
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "Popular", Username, CookieHelper.GetAnalyticClientId(Cookies));
var popularShows = await TraktApi.GetPopularShows();
foreach (var popularShow in popularShows)
{
var theTvDbId = int.Parse(popularShow.Ids.Tvdb.ToString());
var model = new SearchTvShowViewModel
{
FirstAired = popularShow.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
Id = theTvDbId,
ImdbId = popularShow.Ids.Imdb,
Network = popularShow.Network,
Overview = popularShow.Overview.RemoveHtml(),
Rating = popularShow.Rating.ToString(),
Runtime = popularShow.Runtime.ToString(),
SeriesName = popularShow.Title,
Status = popularShow.Status.DisplayName,
DisableTvRequestsByEpisode = prSettings.DisableTvRequestsByEpisode,
DisableTvRequestsBySeason = prSettings.DisableTvRequestsBySeason,
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason),
Trailer = popularShow.Trailer,
Homepage = popularShow.Homepage
};
shows.Add(model);
}
shows = await MapToTvModel(shows, prSettings);
break;
case ShowSearchType.Anticipated:
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "Anticipated", Username, CookieHelper.GetAnalyticClientId(Cookies));
var anticipated = await TraktApi.GetAnticipatedShows();
foreach (var anticipatedShow in anticipated)
{
var show = anticipatedShow.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var model = new SearchTvShowViewModel
{
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
Id = theTvDbId,
ImdbId = show.Ids.Imdb,
Network = show.Network ?? string.Empty,
Overview = show.Overview?.RemoveHtml() ?? string.Empty,
Rating = show.Rating.ToString(),
Runtime = show.Runtime.ToString(),
SeriesName = show.Title,
Status = show.Status?.DisplayName ?? string.Empty,
DisableTvRequestsByEpisode = prSettings.DisableTvRequestsByEpisode,
DisableTvRequestsBySeason = prSettings.DisableTvRequestsBySeason,
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason),
Trailer = show.Trailer,
Homepage = show.Homepage
};
shows.Add(model);
}
shows = await MapToTvModel(shows, prSettings);
break;
case ShowSearchType.MostWatched:
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "MostWatched", Username, CookieHelper.GetAnalyticClientId(Cookies));
var mostWatched = await TraktApi.GetMostWatchesShows();
foreach (var watched in mostWatched)
{
var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var model = new SearchTvShowViewModel
{
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
Id = theTvDbId,
ImdbId = show.Ids.Imdb,
Network = show.Network,
Overview = show.Overview.RemoveHtml(),
Rating = show.Rating.ToString(),
Runtime = show.Runtime.ToString(),
SeriesName = show.Title,
Status = show.Status.DisplayName,
DisableTvRequestsByEpisode = prSettings.DisableTvRequestsByEpisode,
DisableTvRequestsBySeason = prSettings.DisableTvRequestsBySeason,
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason),
Trailer = show.Trailer,
Homepage = show.Homepage
};
shows.Add(model);
}
shows = await MapToTvModel(shows, prSettings);
break;
case ShowSearchType.Trending:
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "Trending", Username, CookieHelper.GetAnalyticClientId(Cookies));
var trending = await TraktApi.GetTrendingShows();
foreach (var watched in trending)
{
var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var model = new SearchTvShowViewModel
{
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
Id = theTvDbId,
ImdbId = show.Ids.Imdb,
Network = show.Network,
Overview = show.Overview.RemoveHtml(),
Rating = show.Rating.ToString(),
Runtime = show.Runtime.ToString(),
SeriesName = show.Title,
Status = show.Status.DisplayName,
DisableTvRequestsByEpisode = prSettings.DisableTvRequestsByEpisode,
DisableTvRequestsBySeason = prSettings.DisableTvRequestsBySeason,
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason),
Trailer = show.Trailer,
Homepage = show.Homepage
};
shows.Add(model);
}
shows = await MapToTvModel(shows, prSettings);
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
return Response.AsJson(shows);
}
private async Task<List<SearchTvShowViewModel>> MapToTvModel(List<SearchTvShowViewModel> shows, PlexRequestSettings prSettings)
{
var plexSettings = await PlexService.GetSettingsAsync();
var providerId = string.Empty;
// Get the requests
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.TvShow);
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
var dbTv = distinctResults.ToDictionary(x => x.ProviderId);
// Check the external applications
var sonarrCached = SonarrCacher.QueuedIds().ToList();
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
var content = PlexContentRepository.GetAll();
var plexTvShows = Checker.GetPlexTvShows(content).ToList();
foreach (var show in shows)
{
if (plexSettings.AdvancedSearch)
{
providerId = show.Id.ToString();
}
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4),
providerId);
if (plexShow != null)
{
show.Available = true;
show.PlexUrl = plexShow.Url;
}
else
{
if (dbTv.ContainsKey(show.Id))
{
var dbt = dbTv[show.Id];
show.Requested = true;
show.Episodes = dbt.Episodes.ToList();
show.Approved = dbt.Approved;
}
if (sonarrCached.Select(x => x.TvdbId).Contains(show.Id) || sickRageCache.Contains(show.Id))
// compare to the sonarr/sickrage db
{
show.Requested = true;
}
}
}
return shows;
}
private async Task<Response> SearchTvShow(string searchTerm) private async Task<Response> SearchTvShow(string searchTerm)
{ {
@ -1401,5 +1602,13 @@ namespace Ombi.UI.Modules
return false; return false;
} }
} }
private enum ShowSearchType
{
Popular,
Anticipated,
MostWatched,
Trending
}
} }
} }

@ -49,6 +49,7 @@ namespace Ombi.UI.NinjectModules
Bind<INetflixApi>().To<NetflixRouletteApi>(); Bind<INetflixApi>().To<NetflixRouletteApi>();
Bind<IDiscordApi>().To<DiscordApi>(); Bind<IDiscordApi>().To<DiscordApi>();
Bind<IRadarrApi>().To<RadarrApi>(); Bind<IRadarrApi>().To<RadarrApi>();
Bind<ITraktApi>().To<TraktApi>();
} }
} }
} }

@ -206,6 +206,10 @@
<HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath> <HintPath>..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="TraktApiSharp, Version=0.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TraktApiSharp.0.8.0\lib\portable-net45+netcore45+wpa81\TraktApiSharp.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Authentication\CustomAuthenticationConfiguration.cs" /> <Compile Include="Authentication\CustomAuthenticationConfiguration.cs" />

@ -75,9 +75,20 @@
<!-- TV tab --> <!-- TV tab -->
<div role="tabpanel" class="tab-pane" id="TvShowTab"> <div role="tabpanel" class="tab-pane" id="TvShowTab">
<div class="input-group"> <div class="input-group">
<input id="tvSearchContent" type="text" class="form-control form-control-custom form-control-search"> <input id="tvSearchContent" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons">
<div class="input-group-addon"> <div class="input-group-addon">
<i id="tvSearchButton" class="fa fa-search"></i> <div class="btn-group">
<a href="#" class="btn btn-sm btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
@UI.Search_Suggestions
<i class="fa fa-chevron-down"></i>
</a>
<ul class="dropdown-menu">
<li><a id="popularShows" href="#">Popular Shows</a></li>
<li><a id="trendingShows" href="#">Trending Shows</a></li>
<li><a id="mostWatchedShows" href="#">Most Watched Shows</a></li>
<li><a id="anticipatedShows" href="#">Most Anticipated Shows</a></li>
</ul>
</div><i id="tvSearchButton" class="fa fa-search"></i>
</div> </div>
</div> </div>
<br /> <br />
@ -106,10 +117,10 @@
</div> </div>
} }
<!-- Movie and TV Results template --> <!-- Movie and TV Results template -->
<script id="search-template" type="text/x-handlebars-template"> <script id="search-template" type="text/x-handlebars-template">
<div class="row"> <div class="row">
<div class="col-sm-2"> <div id="{{id}}imgDiv" class="col-sm-2">
{{#if_eq type "movie"}} {{#if_eq type "movie"}}
{{#if posterPath}} {{#if posterPath}}
@ -134,6 +145,15 @@
<h4>{{title}} ({{year}})</h4> <h4>{{title}} ({{year}})</h4>
</a> </a>
{{/if_eq}} {{/if_eq}}
{{#if status}}
<span class="label label-info" target="_blank">{{status}}</span>
{{/if}}
{{#if homepage}}
<a href="{{homepage}}" target="_blank"><span class="label label-info">HomePage</span></a>
{{/if}}
{{#if trailer}}
<a href="{{trailer}}" target="_blank"><span class="label label-info">Trailer</span></a>
{{/if}}
{{#if available}} {{#if available}}
<span class="label label-success">@UI.Search_Available_on_plex</span> <span class="label label-success">@UI.Search_Available_on_plex</span>
{{else}} {{else}}
@ -230,11 +250,11 @@
</div> </div>
<hr /> <hr />
</script> </script>
<!-- Music Results template --> <!-- Music Results template -->
<script id="music-template" type="text/x-handlebars-template"> <script id="music-template" type="text/x-handlebars-template">
<div class="row"> <div class="row">
<div id="{{id}}imageDiv" class="col-sm-2"> <div id="{{id}}imageDiv" class="col-sm-2">
{{#if coverArtUrl}} {{#if coverArtUrl}}
@ -277,9 +297,9 @@
</div> </div>
<hr /> <hr />
</script> </script>
<div class="modal fade" id="seasonsModal"> <div class="modal fade" id="seasonsModal">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@ -297,9 +317,9 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="episodesModal"> <div class="modal fade" id="episodesModal">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content col-md-12"> <div class="modal-content col-md-12">
<div class="modal-header"> <div class="modal-header">
@ -319,10 +339,10 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="issuesModal"> <div class="modal fade" id="issuesModal">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@ -343,27 +363,27 @@
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<script id="seasons-template" type="text/x-handlebars-template"> <script id="seasons-template" type="text/x-handlebars-template">
<div class="form-group"> <div class="form-group">
<div class="checkbox"> <div class="checkbox">
<input type="checkbox" class="selectedSeasons" id="{{id}}" name="{{id}}"><label for="{{id}}">@UI.Search_Season {{id}}</label> <input type="checkbox" class="selectedSeasons" id="{{id}}" name="{{id}}"><label for="{{id}}">@UI.Search_Season {{id}}</label>
</div> </div>
</div> </div>
</script> </script>
<script id="seasonNumber-template" type="text/x-handlebars-template"> <script id="seasonNumber-template" type="text/x-handlebars-template">
<div id="seasonNumber{{seasonNumber}}" class="col-md-12"> <div id="seasonNumber{{seasonNumber}}" class="col-md-12">
<strong>@UI.Search_Season {{seasonNumber}}</strong> <strong>@UI.Search_Season {{seasonNumber}}</strong>
</div> </div>
</script> </script>
<script id="episode-template" type="text/x-handlebars-template"> <script id="episode-template" type="text/x-handlebars-template">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<div class="checkbox" style="margin-bottom:0px; margin-top:0px;"> <div class="checkbox" style="margin-bottom:0px; margin-top:0px;">
{{#if_eq requested true}} {{#if_eq requested true}}
@ -374,6 +394,6 @@
</div> </div>
</div> </div>
</script> </script>
@Html.LoadSearchAssets() @Html.LoadSearchAssets()

@ -53,4 +53,5 @@
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net45" /> <package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net45" />
<package id="System.Text.RegularExpressions" version="4.0.0" targetFramework="net45" /> <package id="System.Text.RegularExpressions" version="4.0.0" targetFramework="net45" />
<package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" /> <package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" />
<package id="TraktApiSharp" version="0.8.0" targetFramework="net45" />
</packages> </packages>
Loading…
Cancel
Save