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;
@ -77,13 +78,6 @@ namespace Ombi.Api
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,30 +163,72 @@ namespace Ombi.Api
TimeSpan.FromSeconds(5) TimeSpan.FromSeconds(5)
}); });
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) switch (type)
{ {
case EmbyMediaType.Movie: case EmbyMediaType.Movie:
return new EmbyInformation return new EmbyInformation
{ {
MovieInformation = policy.Execute(() => Api.ExecuteJson<EmbyMovieInformation>(request, baseUri)) MovieInformation = JsonConvert.DeserializeObject<EmbyMovieInformation>(response.Content)
}; };
case EmbyMediaType.Series: case EmbyMediaType.Series:
return new EmbyInformation return new EmbyInformation
{ {
SeriesInformation = SeriesInformation = JsonConvert.DeserializeObject<EmbySeriesInformation>(response.Content)
policy.Execute(() => Api.ExecuteJson<EmbySeriesInformation>(request, baseUri))
}; };
case EmbyMediaType.Music: case EmbyMediaType.Music:
break; break;
case EmbyMediaType.Episode: case EmbyMediaType.Episode:
return new EmbyInformation return new EmbyInformation
{ {
EpisodeInformation = EpisodeInformation = JsonConvert.DeserializeObject<EmbyEpisodeInformation>(response.Content)
policy.Execute(() => Api.ExecuteJson<EmbyEpisodeInformation>(request, baseUri))
}; };
default: default:
throw new ArgumentOutOfRangeException(nameof(type), type, null); throw new ArgumentOutOfRangeException(nameof(type), type, null);
} }
}
catch (Exception e)
{
Log.Error("Could not get the media item's information");
Log.Error(e);
Log.Debug("ResponseContent");
Log.Debug(response?.Content ?? "Empty");
Log.Debug("ResponseStatusCode");
Log.Debug(response?.StatusCode ?? HttpStatusCode.PreconditionFailed);
Log.Debug("ResponseError");
Log.Debug(response?.ErrorMessage ?? "No Error");
Log.Debug("ResponseException");
Log.Debug(response?.ErrorException ?? new Exception());
throw;
}
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,8 +91,10 @@ 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 obj = Api.Execute<TvMazeShow>(request, new Uri(Uri)); {
var result = Api.Execute(request, new Uri(Uri));
var obj = JsonConvert.DeserializeObject<TvMazeShow>(result.Content);
var episodes = EpisodeLookup(obj.id).ToList(); var episodes = EpisodeLookup(obj.id).ToList();
@ -106,6 +109,12 @@ namespace Ombi.Api
return obj; return obj;
} }
catch (Exception e)
{
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();
if (!string.IsNullOrEmpty(s.Ip))
{
s.Enable = true; s.Enable = true;
PlexSettings.SaveSettings(s); 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
@ -195,6 +197,9 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
sb.Append( sb.Append(
"<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
{ {
@ -223,6 +228,13 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
AddParagraph(sb, info.Overview); AddParagraph(sb, info.Overview);
} }
catch (RequestLimitExceededException limit)
{
// We have hit a limit, we need to now wait.
Thread.Sleep(TimeSpan.FromSeconds(10));
Log.Info(limit);
}
}
catch (Exception e) catch (Exception e)
{ {
Log.Error(e); Log.Error(e);

@ -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,12 +78,16 @@ 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 (plexSettings.Enable)
{
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip)) if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
{ {
return Response.AsJson(false); return Response.AsJson(false);
@ -94,7 +101,26 @@ namespace Ombi.UI.Modules
{ {
return Response.AsJson(false); return Response.AsJson(false);
} }
}
var emby = await EmbySettings.GetSettingsAsync();
if (emby.Enable)
{
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