Merge pull request #1138 from tidusjar/dev

Dev
pull/1186/head
Jamie 8 years ago committed by GitHub
commit f1535edb5b

@ -14,5 +14,6 @@ namespace Ombi.Api.Interfaces
EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri); EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri);
EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri); EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri);
EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri); EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri);
EmbySystemInfo GetSystemInformation(string apiKey, Uri baseUrl);
} }
} }

@ -0,0 +1,63 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbySystemInfo.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
namespace Ombi.Api.Models.Emby
{
public class EmbySystemInfo
{
public string SystemUpdateLevel { get; set; }
public string OperatingSystemDisplayName { get; set; }
public bool SupportsRunningAsService { get; set; }
public string MacAddress { get; set; }
public bool HasPendingRestart { get; set; }
public bool SupportsLibraryMonitor { get; set; }
public object[] InProgressInstallations { get; set; }
public int WebSocketPortNumber { get; set; }
public object[] CompletedInstallations { get; set; }
public bool CanSelfRestart { get; set; }
public bool CanSelfUpdate { get; set; }
public object[] FailedPluginAssemblies { get; set; }
public string ProgramDataPath { get; set; }
public string ItemsByNamePath { get; set; }
public string CachePath { get; set; }
public string LogPath { get; set; }
public string InternalMetadataPath { get; set; }
public string TranscodingTempPath { get; set; }
public int HttpServerPortNumber { get; set; }
public bool SupportsHttps { get; set; }
public int HttpsPortNumber { get; set; }
public bool HasUpdateAvailable { get; set; }
public bool SupportsAutoRunAtStartup { get; set; }
public string EncoderLocationType { get; set; }
public string SystemArchitecture { get; set; }
public string LocalAddress { get; set; }
public string WanAddress { get; set; }
public string ServerName { get; set; }
public string Version { get; set; }
public string OperatingSystem { get; set; }
public string Id { get; set; }
}
}

@ -71,6 +71,7 @@
<Compile Include="Emby\EmbySeriesItem.cs" /> <Compile Include="Emby\EmbySeriesItem.cs" />
<Compile Include="Emby\EmbySeriesstudioinfo.cs" /> <Compile Include="Emby\EmbySeriesstudioinfo.cs" />
<Compile Include="Emby\EmbyStudio.cs" /> <Compile Include="Emby\EmbyStudio.cs" />
<Compile Include="Emby\EmbySystemInfo.cs" />
<Compile Include="Emby\EmbyUser.cs" /> <Compile Include="Emby\EmbyUser.cs" />
<Compile Include="Emby\EmbyUserdata.cs" /> <Compile Include="Emby\EmbyUserdata.cs" />
<Compile Include="Emby\EmbyMovieInformation.cs" /> <Compile Include="Emby\EmbyMovieInformation.cs" />

@ -27,6 +27,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Net;
using System.Xml.Serialization; using System.Xml.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
@ -76,14 +77,7 @@ namespace Ombi.Api
var client = new RestClient { BaseUrl = baseUri }; var client = new RestClient { BaseUrl = baseUri };
var response = client.Execute(request); var response = client.Execute(request);
if (response.ErrorException != null)
{
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info.";
throw new ApiRequestException(message, response.ErrorException);
}
return response; return response;
} }

@ -33,6 +33,7 @@ using NLog;
using Ombi.Api.Interfaces; using Ombi.Api.Interfaces;
using Ombi.Api.Models.Emby; using Ombi.Api.Models.Emby;
using Ombi.Helpers; using Ombi.Helpers;
using Polly;
using RestSharp; using RestSharp;
namespace Ombi.Api namespace Ombi.Api
@ -71,6 +72,26 @@ namespace Ombi.Api
return obj; return obj;
} }
public EmbySystemInfo GetSystemInformation(string apiKey, Uri baseUrl)
{
var request = new RestRequest
{
Resource = "emby/System/Info",
Method = Method.GET
};
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetSystemInformation for Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<EmbySystemInfo>(request, baseUrl));
return obj;
}
public EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri) public EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri)
{ {
var request = new RestRequest var request = new RestRequest
@ -142,29 +163,71 @@ namespace Ombi.Api
TimeSpan.FromSeconds(5) TimeSpan.FromSeconds(5)
}); });
switch (type) IRestResponse response = null;
try
{
switch (type)
{
case EmbyMediaType.Movie:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
case EmbyMediaType.Series:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
case EmbyMediaType.Music:
break;
case EmbyMediaType.Episode:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
var info = new EmbyInformation();
switch (type)
{
case EmbyMediaType.Movie:
return new EmbyInformation
{
MovieInformation = JsonConvert.DeserializeObject<EmbyMovieInformation>(response.Content)
};
case EmbyMediaType.Series:
return new EmbyInformation
{
SeriesInformation = JsonConvert.DeserializeObject<EmbySeriesInformation>(response.Content)
};
case EmbyMediaType.Music:
break;
case EmbyMediaType.Episode:
return new EmbyInformation
{
EpisodeInformation = JsonConvert.DeserializeObject<EmbyEpisodeInformation>(response.Content)
};
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
catch (Exception e)
{ {
case EmbyMediaType.Movie: Log.Error("Could not get the media item's information");
return new EmbyInformation Log.Error(e);
{ Log.Debug("ResponseContent");
MovieInformation = policy.Execute(() => Api.ExecuteJson<EmbyMovieInformation>(request, baseUri)) Log.Debug(response?.Content ?? "Empty");
}; Log.Debug("ResponseStatusCode");
case EmbyMediaType.Series: Log.Debug(response?.StatusCode ?? HttpStatusCode.PreconditionFailed);
return new EmbyInformation
{ Log.Debug("ResponseError");
SeriesInformation = Log.Debug(response?.ErrorMessage ?? "No Error");
policy.Execute(() => Api.ExecuteJson<EmbySeriesInformation>(request, baseUri)) Log.Debug("ResponseException");
}; Log.Debug(response?.ErrorException ?? new Exception());
case EmbyMediaType.Music:
break;
case EmbyMediaType.Episode:
return new EmbyInformation throw;
{
EpisodeInformation =
policy.Execute(() => Api.ExecuteJson<EmbyEpisodeInformation>(request, baseUri))
};
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
} }
return new EmbyInformation(); return new EmbyInformation();
} }

@ -28,6 +28,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json;
using NLog; using NLog;
using Ombi.Api.Models.Tv; using Ombi.Api.Models.Tv;
using RestSharp; using RestSharp;
@ -90,21 +91,29 @@ namespace Ombi.Api
}; };
request.AddUrlSegment("id", theTvDbId.ToString()); request.AddUrlSegment("id", theTvDbId.ToString());
request.AddHeader("Content-Type", "application/json"); request.AddHeader("Content-Type", "application/json");
try
{
var result = Api.Execute(request, new Uri(Uri));
var obj = JsonConvert.DeserializeObject<TvMazeShow>(result.Content);
var obj = Api.Execute<TvMazeShow>(request, new Uri(Uri)); var episodes = EpisodeLookup(obj.id).ToList();
var episodes = EpisodeLookup(obj.id).ToList();
foreach (var e in episodes) foreach (var e in episodes)
{
obj.Season.Add(new TvMazeCustomSeason
{ {
SeasonNumber = e.season, obj.Season.Add(new TvMazeCustomSeason
EpisodeNumber = e.number {
}); SeasonNumber = e.season,
EpisodeNumber = e.number
});
}
return obj;
} }
catch (Exception e)
return obj; {
Log.Error(e);
return null;
}
} }
public List<TvMazeSeasons> GetSeasons(int id) public List<TvMazeSeasons> GetSeasons(int id)

@ -181,7 +181,7 @@ namespace Ombi.Core.Migration.Migrations
try try
{ {
var settings = PlexSettings.GetSettings(); var settings = PlexSettings.GetSettings();
if (string.IsNullOrEmpty(settings.PlexAuthToken)) if (string.IsNullOrEmpty(settings.PlexAuthToken) || !settings.Enable)
{ {
return; return;
} }

@ -62,6 +62,7 @@ namespace Ombi.Core.Migration.Migrations
private void UpdateApplicationSettings() private void UpdateApplicationSettings()
{ {
var plex = PlexRequestSettings.GetSettings(); var plex = PlexRequestSettings.GetSettings();
var jobSettings = Jobs.GetSettings(); var jobSettings = Jobs.GetSettings();
var newsLetter = NewsletterSettings.GetSettings(); var newsLetter = NewsletterSettings.GetSettings();

@ -68,8 +68,11 @@ namespace Ombi.Core.Migration.Migrations
{ {
#if !DEBUG #if !DEBUG
var s = PlexSettings.GetSettings(); var s = PlexSettings.GetSettings();
s.Enable = true; if (!string.IsNullOrEmpty(s.Ip))
PlexSettings.SaveSettings(s); {
s.Enable = true;
PlexSettings.SaveSettings(s);
}
#endif #endif
} }
private void UpdateCustomSettings() private void UpdateCustomSettings()

@ -31,6 +31,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using NLog; using NLog;
using Ombi.Api; using Ombi.Api;
using Ombi.Api.Interfaces; using Ombi.Api.Interfaces;
@ -41,6 +42,7 @@ using Ombi.Services.Jobs.Templates;
using Ombi.Store.Models; using Ombi.Store.Models;
using Ombi.Store.Models.Emby; using Ombi.Store.Models.Emby;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using TMDbLib.Objects.Exceptions;
using EmbyMediaType = Ombi.Store.Models.Plex.EmbyMediaType; using EmbyMediaType = Ombi.Store.Models.Plex.EmbyMediaType;
namespace Ombi.Services.Jobs.RecentlyAddedNewsletter namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
@ -79,7 +81,7 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
{ {
try try
{ {
return GetHtml(test); return GetHtml(test);
} }
catch (Exception e) catch (Exception e)
{ {
@ -196,32 +198,42 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
"<table border=\"0\" cellpadding=\"0\" align=\"center\" cellspacing=\"0\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\" width=\"100%\">"); "<table border=\"0\" cellpadding=\"0\" align=\"center\" cellspacing=\"0\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\" width=\"100%\">");
foreach (var movie in orderedMovies) foreach (var movie in orderedMovies)
{ {
// We have a try within a try so we can catch the rate limit without ending the loop (finally block)
try try
{ {
try
var imdbId = movie.ProviderIds.Imdb;
var info = MovieApi.GetMovieInformation(imdbId).Result;
if (info == null)
{ {
throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi");
}
AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
sb.Append("<tr>"); var imdbId = movie.ProviderIds.Imdb;
sb.Append( var info = MovieApi.GetMovieInformation(imdbId).Result;
"<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">"); if (info == null)
{
throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi");
}
AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/"); sb.Append("<tr>");
Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}"); sb.Append(
EndTag(sb, "a"); "<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/");
Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}");
EndTag(sb, "a");
if (info.Genres.Any()) if (info.Genres.Any())
{
AddParagraph(sb,
$"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}");
}
AddParagraph(sb, info.Overview);
}
catch (RequestLimitExceededException limit)
{ {
AddParagraph(sb, // We have hit a limit, we need to now wait.
$"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); Thread.Sleep(TimeSpan.FromSeconds(10));
Log.Info(limit);
} }
AddParagraph(sb, info.Overview);
} }
catch (Exception e) catch (Exception e)
{ {
@ -260,8 +272,8 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
{ {
var seriesItem = t.EmbyInformation.SeriesInformation; var seriesItem = t.EmbyInformation.SeriesInformation;
var relatedEpisodes = t.EpisodeInformation; var relatedEpisodes = t.EpisodeInformation;
try try
{ {
var info = TvApi.ShowLookupByTheTvDbId(int.Parse(seriesItem.ProviderIds.Tvdb)); var info = TvApi.ShowLookupByTheTvDbId(int.Parse(seriesItem.ProviderIds.Tvdb));
@ -328,8 +340,8 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
sb.Append("</table><br /><br />"); sb.Append("</table><br /><br />");
} }
private void EndLoopHtml(StringBuilder sb) private void EndLoopHtml(StringBuilder sb)
{ {

@ -145,7 +145,7 @@ namespace Ombi.UI.Modules
Deleted = issue.Deleted, Deleted = issue.Deleted,
Type = issue.Type, Type = issue.Type,
ProviderId = issue.ProviderId, ProviderId = issue.ProviderId,
PosterUrl = issue.PosterUrl, PosterUrl = issue.PosterUrl.Contains("https://image.tmdb.org/t/p/w150/") ? issue.PosterUrl : $"https://image.tmdb.org/t/p/w150/{issue.PosterUrl}",
Id = issue.Id Id = issue.Id
}; };
return View["Details", m]; return View["Details", m];

@ -40,12 +40,15 @@ namespace Ombi.UI.Modules
public class LandingPageModule : BaseModule public class LandingPageModule : BaseModule
{ {
public LandingPageModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<LandingPageSettings> landing, public LandingPageModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<LandingPageSettings> landing,
ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security) : base("landing", settingsService, security) ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security, ISettingsService<EmbySettings> emby,
IEmbyApi embyApi) : base("landing", settingsService, security)
{ {
LandingSettings = landing; LandingSettings = landing;
PlexSettings = ps; PlexSettings = ps;
PlexApi = pApi; PlexApi = pApi;
Linker = linker; Linker = linker;
EmbySettings = emby;
EmbyApi = embyApi;
Get["LandingPageIndex","/", true] = async (x, ct) => Get["LandingPageIndex","/", true] = async (x, ct) =>
{ {
@ -75,26 +78,49 @@ namespace Ombi.UI.Modules
private ISettingsService<LandingPageSettings> LandingSettings { get; } private ISettingsService<LandingPageSettings> LandingSettings { get; }
private ISettingsService<PlexSettings> PlexSettings { get; } private ISettingsService<PlexSettings> PlexSettings { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IPlexApi PlexApi { get; } private IPlexApi PlexApi { get; }
private IEmbyApi EmbyApi { get; }
private IResourceLinker Linker { get; } private IResourceLinker Linker { get; }
private async Task<Response> CheckStatus() private async Task<Response> CheckStatus()
{ {
var plexSettings = await PlexSettings.GetSettingsAsync(); var plexSettings = await PlexSettings.GetSettingsAsync();
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip)) if (plexSettings.Enable)
{ {
return Response.AsJson(false); if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
} {
try return Response.AsJson(false);
{ }
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri); try
return Response.AsJson(status != null); {
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri);
return Response.AsJson(status != null);
}
catch (Exception)
{
return Response.AsJson(false);
}
} }
catch (Exception)
var emby = await EmbySettings.GetSettingsAsync();
if (emby.Enable)
{ {
return Response.AsJson(false); if (string.IsNullOrEmpty(emby.AdministratorId) || string.IsNullOrEmpty(emby.Ip))
{
return Response.AsJson(false);
}
try
{
var status = EmbyApi.GetSystemInformation(emby.ApiKey, emby.FullUri);
return Response.AsJson(status?.Version != null);
}
catch (Exception)
{
return Response.AsJson(false);
}
} }
return Response.AsJson(false);
} }
} }
} }

@ -437,6 +437,11 @@ namespace Ombi.UI.Modules
{ {
var show = anticipatedShow.Show; var show = anticipatedShow.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString()); var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel var model = new SearchTvShowViewModel
{ {
@ -466,6 +471,12 @@ namespace Ombi.UI.Modules
{ {
var show = watched.Show; var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString()); var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel var model = new SearchTvShowViewModel
{ {
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"), FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
@ -494,6 +505,12 @@ namespace Ombi.UI.Modules
{ {
var show = watched.Show; var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString()); var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel var model = new SearchTvShowViewModel
{ {
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"), FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),

@ -18,7 +18,7 @@
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<img src="https://image.tmdb.org/t/p/w150/@Model.PosterUrl" /> <img src="@Model.PosterUrl" />
</div> </div>
<div class="col-md-9"> <div class="col-md-9">
<h4>Issues For "@Model.Title"</h4> <h4>Issues For "@Model.Title"</h4>

Loading…
Cancel
Save