diff --git a/Ombi.Core.Migration/Migrations/Version2210.cs b/Ombi.Core.Migration/Migrations/Version2210.cs deleted file mode 100644 index 94592174a..000000000 --- a/Ombi.Core.Migration/Migrations/Version2210.cs +++ /dev/null @@ -1,134 +0,0 @@ -#region Copyright - -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: Version1100.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 - -using System; -using System.Data; -using NLog; -using Ombi.Core.SettingModels; -using Ombi.Store; -using Ombi.Store.Models; -using Ombi.Store.Models.Emby; -using Ombi.Store.Models.Plex; -using Ombi.Store.Repository; -using Quartz.Collection; - -namespace Ombi.Core.Migration.Migrations -{ - [Migration(22100, "v2.21.0.0")] - public class Version2210 : BaseMigration, IMigration - { - public Version2210(IRepository log, - IRepository content, IRepository plexEp, IRepository embyContent, IRepository embyEp) - { - Log = log; - PlexContent = content; - PlexEpisodes = plexEp; - EmbyContent = embyContent; - EmbyEpisodes = embyEp; - } - - public int Version => 22100; - private IRepository Log { get; } - private IRepository PlexContent { get; } - private IRepository PlexEpisodes { get; } - private IRepository EmbyContent { get; } - private IRepository EmbyEpisodes { get; } - - public void Start(IDbConnection con) - { - UpdateRecentlyAdded(con); - UpdateSchema(con, Version); - - } - - private void UpdateRecentlyAdded(IDbConnection con) - { - - //Delete the recently added table, lets start again - Log.DeleteAll("RecentlyAddedLog"); - - - - // Plex - var plexAllContent = PlexContent.GetAll(); - var content = new HashSet(); - foreach (var plexContent in plexAllContent) - { - if(plexContent.Type == PlexMediaType.Artist) continue; - content.Add(new RecentlyAddedLog - { - AddedAt = DateTime.UtcNow, - ProviderId = plexContent.ProviderId - }); - } - Log.BatchInsert(content, "RecentlyAddedLog"); - - var plexEpisodeses = PlexEpisodes.GetAll(); - content.Clear(); - foreach (var ep in plexEpisodeses) - { - content.Add(new RecentlyAddedLog - { - AddedAt = DateTime.UtcNow, - ProviderId = ep.RatingKey - }); - } - Log.BatchInsert(content, "RecentlyAddedLog"); - - // Emby - content.Clear(); - var embyContent = EmbyContent.GetAll(); - foreach (var plexContent in embyContent) - { - content.Add(new RecentlyAddedLog - { - AddedAt = DateTime.UtcNow, - ProviderId = plexContent.EmbyId - }); - } - Log.BatchInsert(content, "RecentlyAddedLog"); - - var embyEpisodes = EmbyEpisodes.GetAll(); - content.Clear(); - foreach (var ep in embyEpisodes) - { - content.Add(new RecentlyAddedLog - { - AddedAt = DateTime.UtcNow, - ProviderId = ep.EmbyId - }); - } - Log.BatchInsert(content, "RecentlyAddedLog"); - - - } - - - } -} diff --git a/Ombi.Services/Jobs/PlexContentCacher.cs b/Ombi.Services/Jobs/PlexContentCacher.cs deleted file mode 100644 index d4f872fc2..000000000 --- a/Ombi.Services/Jobs/PlexContentCacher.cs +++ /dev/null @@ -1,438 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexAvailabilityChecker.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 - -using System; -using System.Collections.Generic; -using System.Linq; -using Dapper; -using NLog; -using Ombi.Api.Interfaces; -using Ombi.Api.Models.Plex; -using Ombi.Core; -using Ombi.Core.SettingModels; -using Ombi.Helpers; -using Ombi.Services.Interfaces; -using Ombi.Services.Models; -using Ombi.Store.Models; -using Ombi.Store.Models.Plex; -using Ombi.Store.Repository; -using Quartz; -using PlexMediaType = Ombi.Api.Models.Plex.PlexMediaType; - -namespace Ombi.Services.Jobs -{ - public class PlexContentCacher : IJob, IPlexContentCacher - { - public PlexContentCacher(ISettingsService plexSettings, IRequestService request, IPlexApi plex, ICacheProvider cache, - INotificationService notify, IJobRecord rec, IRepository users, IRepository repo, IPlexNotificationEngine e, IRepository content) - { - Plex = plexSettings; - RequestService = request; - PlexApi = plex; - Cache = cache; - Notification = notify; - Job = rec; - UserNotifyRepo = users; - EpisodeRepo = repo; - NotificationEngine = e; - PlexContent = content; - } - - private ISettingsService Plex { get; } - private IRepository EpisodeRepo { get; } - private IRequestService RequestService { get; } - private static Logger Log = LogManager.GetCurrentClassLogger(); - private IPlexApi PlexApi { get; } - private ICacheProvider Cache { get; } - private INotificationService Notification { get; } - private IJobRecord Job { get; } - private IRepository UserNotifyRepo { get; } - private INotificationEngine NotificationEngine { get; } - private IRepository PlexContent { get; } - - public void CacheContent() - { - var plexSettings = Plex.GetSettings(); - if (!plexSettings.Enable) - { - return; - } - if (!ValidateSettings(plexSettings)) - { - Log.Debug("Validation of the plex settings failed."); - return; - } - var libraries = CachedLibraries(plexSettings); - - if (libraries == null || !libraries.Any()) - { - Log.Debug("Did not find any libraries in Plex."); - return; - } - } - - - public List GetPlexMovies(List libs) - { - var settings = Plex.GetSettings(); - var movies = new List(); - if (libs != null) - { - var movieLibs = libs.Where(x => - x.Video.Any(y => - y.Type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in movieLibs) - { - movies.AddRange(lib.Video.Select(video => new PlexMovie - { - ReleaseYear = video.Year, - Title = video.Title, - ProviderId = video.ProviderId, - Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, video.RatingKey), - ItemId = video.RatingKey - })); - } - } - return movies; - } - - public List GetPlexTvShows(List libs) - { - var settings = Plex.GetSettings(); - var shows = new List(); - if (libs != null) - { - var withDir = libs.Where(x => x.Directory != null); - var tvLibs = withDir.Where(x => - x.Directory.Any(y => - y.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in tvLibs) - { - - shows.AddRange(lib.Directory.Select(x => new PlexTvShow // shows are in the directory list - { - Title = x.Title, - ReleaseYear = x.Year, - ProviderId = x.ProviderId, - Seasons = x.Seasons?.Select(d => PlexHelper.GetSeasonNumberFromTitle(d.Title)).ToArray(), - Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, x.RatingKey), - ItemId= x.RatingKey - - })); - } - } - return shows; - } - - - - - public List GetPlexAlbums(List libs) - { - var settings = Plex.GetSettings(); - var albums = new List(); - if (libs != null) - { - var albumLibs = libs.Where(x => - x.Directory.Any(y => - y.Type.Equals(PlexMediaType.Artist.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in albumLibs) - { - albums.AddRange(lib.Directory.Select(x => new PlexAlbum() - { - Title = x.Title, - ProviderId = x.ProviderId, - ReleaseYear = x.Year, - Artist = x.ParentTitle, - Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, x.RatingKey) - })); - } - } - return albums; - } - - - - private List CachedLibraries(PlexSettings plexSettings) - { - var results = new List(); - - if (!ValidateSettings(plexSettings)) - { - Log.Warn("The settings are not configured"); - return results; // don't error out here, just let it go! let it goo!!! - } - - try - { - results = GetLibraries(plexSettings); - if (plexSettings.AdvancedSearch) - { - Log.Debug("Going through all the items now"); - Log.Debug($"Item count {results.Count}"); - foreach (PlexSearch t in results) - { - foreach (Directory1 t1 in t.Directory) - { - var currentItem = t1; - var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, - currentItem.RatingKey); - - // Get the seasons for each show - if (currentItem.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)) - { - var seasons = PlexApi.GetSeasons(plexSettings.PlexAuthToken, plexSettings.FullUri, - currentItem.RatingKey); - - // We do not want "all episodes" this as a season - var filtered = seasons.Directory.Where(x => !x.Title.Equals("All episodes", StringComparison.CurrentCultureIgnoreCase)); - - t1.Seasons.AddRange(filtered); - } - - var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.Directory.Guid); - t1.ProviderId = providerId; - } - foreach (Video t1 in t.Video) - { - var currentItem = t1; - var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, - currentItem.RatingKey); - var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.Video.Guid); - t1.ProviderId = providerId; - } - } - } - if (results != null) - { - Log.Debug("done all that, moving onto the DB now"); - var movies = GetPlexMovies(results); - - // Time to destroy the plex movies from the DB - PlexContent.Custom(connection => - { - connection.Open(); - connection.Query("delete from PlexContent where type = @type", new { type = 0 }); - return new List(); - }); - - foreach (var m in movies) - { - if (string.IsNullOrEmpty(m.ProviderId)) - { - Log.Error("Provider Id on movie {0} is null",m.Title); - continue; - } - - // Check if it exists - var item = PlexContent.Custom(connection => - { - connection.Open(); - var media = connection.QueryFirstOrDefault("select * from PlexContent where ProviderId = @ProviderId and type = @type", new { m.ProviderId, type = 0 }); - connection.Dispose(); - return media; - }); - - if (item == null && !string.IsNullOrEmpty(m.ItemId)) - { - // Doesn't exist, insert it - PlexContent.Insert(new PlexContent - { - ProviderId = m.ProviderId, - ReleaseYear = m.ReleaseYear ?? string.Empty, - Title = m.Title, - Type = Store.Models.Plex.PlexMediaType.Movie, - Url = m.Url, - ItemId = m.ItemId, - AddedAt = DateTime.UtcNow, - }); - } - } - - Log.Debug("Done movies"); - var tv = GetPlexTvShows(results); - // Time to destroy the plex tv from the DB - PlexContent.Custom(connection => - { - connection.Open(); - connection.Query("delete from PlexContent where type = @type", new { type = 1 }); - return new List(); - }); - foreach (var t in tv) - { - if (string.IsNullOrEmpty(t.ProviderId)) - { - Log.Error("Provider Id on tv {0} is null", t.Title); - continue; - } - - - // Check if it exists - var item = PlexContent.Custom(connection => - { - connection.Open(); - var media = connection.QueryFirstOrDefault("select * from PlexContent where ProviderId = @ProviderId and type = @type", new { t.ProviderId, type = 1 }); - connection.Dispose(); - return media; - }); - - if (item == null && !string.IsNullOrEmpty(t.ItemId)) - { - PlexContent.Insert(new PlexContent - { - ProviderId = t.ProviderId, - ReleaseYear = t.ReleaseYear ?? string.Empty, - Title = t.Title, - Type = Store.Models.Plex.PlexMediaType.Show, - Url = t.Url, - Seasons = ByteConverterHelper.ReturnBytes(t.Seasons), - ItemId = t.ItemId, - AddedAt = DateTime.UtcNow, - }); - } - } - Log.Debug("Done TV"); - var albums = GetPlexAlbums(results); - // Time to destroy the plex movies from the DB - PlexContent.Custom(connection => - { - connection.Open(); - connection.Query("delete from PlexContent where type = @type", new { type = 2 }); - return new List(); - }); - - foreach (var a in albums) - { - if (string.IsNullOrEmpty(a.ProviderId)) - { - Log.Error("Provider Id on album {0} is null", a.Title); - continue; - } - - - // Check if it exists - var item = PlexContent.Custom(connection => - { - connection.Open(); - var media = connection.QueryFirstOrDefault("select * from PlexContent where ProviderId = @ProviderId and type = @type", new { a.ProviderId, type = 2 }); - connection.Dispose(); - return media; - }); - - if (item == null) - { - - PlexContent.Insert(new PlexContent - { - ProviderId = a.ProviderId, - ReleaseYear = a.ReleaseYear ?? string.Empty, - Title = a.Title, - Type = Store.Models.Plex.PlexMediaType.Artist, - Url = a.Url, - ItemId = "album", - AddedAt = DateTime.UtcNow, - }); - } - } - Log.Debug("Done albums"); - } - } - catch (Exception ex) - { - Log.Debug("Exception:"); - Log.Debug(ex); - Log.Error(ex, "Failed to obtain Plex libraries"); - } - - return results; - } - - private List GetLibraries(PlexSettings plexSettings) - { - Log.Debug("Getting Lib sections"); - var sections = PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri); - - Log.Debug("Going through sections now"); - var libs = new List(); - if (sections != null) - { - foreach (var dir in sections.Directories ?? new List()) - { - var lib = PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.Key); - if (lib != null) - { - Log.Debug("adding lib"); - libs.Add(lib); - } - } - } - - return libs; - } - - private bool ValidateSettings(PlexSettings plex) - { - if (plex.Enable) - { - if (plex?.Ip == null || plex?.PlexAuthToken == null) - { - Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token."); - return false; - } - } - return plex.Enable; - } - - public void Execute(IJobExecutionContext context) - { - - Job.SetRunning(true, JobNames.PlexCacher); - try - { - CacheContent(); - } - catch (Exception e) - { - Log.Error(e); - } - finally - { - Job.Record(JobNames.PlexCacher); - Job.SetRunning(false, JobNames.PlexCacher); - } - } - } -} \ No newline at end of file diff --git a/Ombi.Services/Jobs/RecentlyAddedNewsletter/EmbyRecentlyAddedNewsletter.cs b/Ombi.Services/Jobs/RecentlyAddedNewsletter/EmbyRecentlyAddedNewsletter.cs deleted file mode 100644 index 158d77f0d..000000000 --- a/Ombi.Services/Jobs/RecentlyAddedNewsletter/EmbyRecentlyAddedNewsletter.cs +++ /dev/null @@ -1,454 +0,0 @@ -#region Copyright - -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: RecentlyAddedModel.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 - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using Newtonsoft.Json; -using NLog; -using Ombi.Api; -using Ombi.Api.Interfaces; -using Ombi.Api.Models.Emby; -using Ombi.Core; -using Ombi.Core.SettingModels; -using Ombi.Services.Jobs.Templates; -using Ombi.Store.Models; -using Ombi.Store.Models.Emby; -using Ombi.Store.Repository; -using TMDbLib.Objects.Exceptions; -using EmbyMediaType = Ombi.Store.Models.Plex.EmbyMediaType; -using Polly; - -namespace Ombi.Services.Jobs.RecentlyAddedNewsletter -{ - public class EmbyAddedNewsletter : HtmlTemplateGenerator, IEmbyAddedNewsletter - { - public EmbyAddedNewsletter(IEmbyApi api, ISettingsService embySettings, - ISettingsService email, - ISettingsService newsletter, IRepository log, - IRepository embyContent, IRepository episodes) - { - Api = api; - EmbySettings = embySettings; - EmailSettings = email; - NewsletterSettings = newsletter; - Content = embyContent; - MovieApi = new TheMovieDbApi(); - TvApi = new TvMazeApi(); - Episodes = episodes; - RecentlyAddedLog = log; - } - - private IEmbyApi Api { get; } - private TheMovieDbApi MovieApi { get; } - private TvMazeApi TvApi { get; } - private ISettingsService EmbySettings { get; } - private ISettingsService EmailSettings { get; } - private ISettingsService NewsletterSettings { get; } - private IRepository Content { get; } - private IRepository Episodes { get; } - private IRepository RecentlyAddedLog { get; } - - private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - - public Newsletter GetNewsletter(bool test) - { - try - { - return GetHtml(test); - } - catch (Exception e) - { - Log.Error(e); - return null; - } - } - - private class EmbyRecentlyAddedModel - { - public EmbyInformation EmbyInformation { get; set; } - public EmbyContent EmbyContent { get; set; } - public List EpisodeInformation { get; set; } - } - - private Newsletter GetHtml(bool test) - { - var sb = new StringBuilder(); - var newsletter = new Newsletter(); - - var embySettings = EmbySettings.GetSettings(); - var embyContent = Content.GetAll().ToList(); - - var series = embyContent.Where(x => x.Type == EmbyMediaType.Series).ToList(); - var episodes = Episodes.GetAll().ToList(); - var movie = embyContent.Where(x => x.Type == EmbyMediaType.Movie).ToList(); - - var recentlyAdded = RecentlyAddedLog.GetAll().ToList(); - - var firstRun = !recentlyAdded.Any(); - - var filteredMovies = movie.Where(m => recentlyAdded.All(x => x.ProviderId != m.EmbyId)).ToList(); - var filteredEp = episodes.Where(m => recentlyAdded.All(x => x.ProviderId != m.EmbyId)).ToList(); - var filteredSeries = series.Where(m => recentlyAdded.All(x => x.ProviderId != m.EmbyId)).ToList(); - - var info = new List(); - foreach (var m in filteredMovies.OrderByDescending(x => x.AddedAt)) - { - var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => - Log.Error(exception, "Exception thrown when processing an emby movie for the newsletter, Retrying {0}", timespan)); - var result = policy.Execute(() => - { - var i = Api.GetInformation(m.EmbyId, Ombi.Api.Models.Emby.EmbyMediaType.Movie, - embySettings.ApiKey, embySettings.AdministratorId, embySettings.FullUri); - - return new EmbyRecentlyAddedModel - { - EmbyInformation = i, - EmbyContent = m - }; - }); - info.Add(result); - } - GenerateMovieHtml(info, sb); - newsletter.MovieCount = info.Count; - - info.Clear(); - - // Check if there are any epiosdes, then get the series info. - // Otherwise then just add the series to the newsletter - if (test && !filteredEp.Any() && episodes.Any()) - { - // if this is a test make sure we show something - filteredEp = episodes.Take(5).ToList(); - } - if (filteredEp.Any()) - { - var recentlyAddedModel = new List(); - foreach (var embyEpisodes in filteredEp) - { - try - { - var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => - Log.Error(exception, "Exception thrown when processing an emby episode for the newsletter, Retrying {0}", timespan)); - - policy.Execute(() => - { - // Find related series item - var relatedSeries = series.FirstOrDefault(x => x.EmbyId == embyEpisodes.ParentId); - - if (relatedSeries == null) - { - return; - } - - // Get series information - var i = Api.GetInformation(relatedSeries.EmbyId, Ombi.Api.Models.Emby.EmbyMediaType.Series, - embySettings.ApiKey, embySettings.AdministratorId, embySettings.FullUri); - - Thread.Sleep(200); - var episodeInfo = Api.GetInformation(embyEpisodes.EmbyId, - Ombi.Api.Models.Emby.EmbyMediaType.Episode, - embySettings.ApiKey, embySettings.AdministratorId, embySettings.FullUri); - - // Check if we already have this series - var existingSeries = recentlyAddedModel.FirstOrDefault(x => - x.EmbyInformation.SeriesInformation.Id.Equals(i.SeriesInformation.Id, - StringComparison.CurrentCultureIgnoreCase)); - - if (existingSeries != null) - { - existingSeries.EpisodeInformation.Add(episodeInfo.EpisodeInformation); - } - else - { - recentlyAddedModel.Add(new EmbyRecentlyAddedModel - { - EmbyInformation = i, - EpisodeInformation = new List() { episodeInfo.EpisodeInformation }, - EmbyContent = relatedSeries - }); - } - }); - - } - catch (JsonReaderException) - { - Log.Error("Failed getting information from Emby, we may have overloaded Emby's api... Waiting and we will skip this one and go to the next"); - Thread.Sleep(1000); - } - } - - info.AddRange(recentlyAddedModel); - } - else - { - foreach (var t in filteredSeries.OrderByDescending(x => x.AddedAt)) - { - - - var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => - Log.Error(exception, "Exception thrown when processing an emby series for the newsletter, Retrying {0}", timespan)); - var item = policy.Execute(() => - { - var i = Api.GetInformation(t.EmbyId, Ombi.Api.Models.Emby.EmbyMediaType.Series, - embySettings.ApiKey, embySettings.AdministratorId, embySettings.FullUri); - var model = new EmbyRecentlyAddedModel - { - EmbyContent = t, - EmbyInformation = i, - }; - return model; - }); - info.Add(item); - } - } - GenerateTvHtml(info, sb); - newsletter.TvCount = info.Count; - - - var template = new RecentlyAddedTemplate(); - var html = template.LoadTemplate(sb.ToString()); - Log.Debug("Loaded the template"); - - if (!test || firstRun) - { - foreach (var a in filteredMovies) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = a.EmbyId, - AddedAt = DateTime.UtcNow - }); - } - foreach (var a in filteredEp) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = a.EmbyId, - AddedAt = DateTime.UtcNow - }); - } - foreach (var s in filteredSeries) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = s.EmbyId, - AddedAt = DateTime.UtcNow - }); - } - } - - - var escapedHtml = new string(html.Where(c => !char.IsControl(c)).ToArray()); - Log.Debug(escapedHtml); - newsletter.Html = escapedHtml; - return newsletter; - - } - - private void GenerateMovieHtml(IEnumerable recentlyAddedMovies, StringBuilder sb) - { - var movies = recentlyAddedMovies?.ToList() ?? new List(); - if (!movies.Any()) - { - return; - } - var orderedMovies = movies.OrderByDescending(x => x.EmbyContent.AddedAt).Select(x => x.EmbyInformation.MovieInformation).ToList(); - sb.Append("

New Movies:



"); - sb.Append( - ""); - 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 - { - - 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(""); - sb.Append( - "
"); - - 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()) - { - AddParagraph(sb, - $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); - } - - AddParagraph(sb, info.Overview); - } - catch (Exception limit) - { - // We have hit a limit, we need to now wait. - Thread.Sleep(TimeSpan.FromSeconds(10)); - Log.Info(limit); - } - } - catch (Exception e) - { - Log.Error(e); - Log.Error("Error for movie with IMDB Id = {0}", movie.ProviderIds.Imdb); - } - finally - { - EndLoopHtml(sb); - } - - } - sb.Append("


"); - } - - private class TvModel - { - public EmbySeriesInformation Series { get; set; } - public List Episodes { get; set; } - } - private void GenerateTvHtml(IEnumerable recenetlyAddedTv, StringBuilder sb) - { - var tv = recenetlyAddedTv?.ToList() ?? new List(); - - if (!tv.Any()) - { - return; - } - var orderedTv = tv.OrderByDescending(x => x.EmbyContent.AddedAt).ToList(); - - // TV - sb.Append("

New Episodes:



"); - sb.Append( - ""); - foreach (var t in orderedTv) - { - var seriesItem = t.EmbyInformation.SeriesInformation; - var relatedEpisodes = t.EpisodeInformation; - var endLoop = false; - - try - { - var info = TvApi.ShowLookupByTheTvDbId(int.Parse(seriesItem.ProviderIds.Tvdb)); - if (info == null) continue; - - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.Replace("http", "https"); // Always use the Https banners - } - AddImageInsideTable(sb, banner); - - sb.Append(""); - sb.Append( - "
"); - - var title = $"{seriesItem.Name} {seriesItem.PremiereDate.Year}"; - - Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); - Header(sb, 3, title); - EndTag(sb, "a"); - - if (relatedEpisodes != null) - { - var results = relatedEpisodes.GroupBy(p => p.ParentIndexNumber, - (key, g) => new - { - ParentIndexNumber = key, - IndexNumber = g.ToList() - } - ); - // Group the episodes - foreach (var embyEpisodeInformation in results.OrderBy(x => x.ParentIndexNumber)) - { - var epSb = new StringBuilder(); - var orderedEpisodes = embyEpisodeInformation.IndexNumber.OrderBy(x => x.IndexNumber).ToList(); - for (var i = 0; i < orderedEpisodes.Count; i++) - { - var ep = orderedEpisodes[i]; - if (i < embyEpisodeInformation.IndexNumber.Count - 1) - { - epSb.Append($"{ep.IndexNumber},"); - } - else - { - epSb.Append(ep.IndexNumber); - } - } - AddParagraph(sb, $"Season: {embyEpisodeInformation.ParentIndexNumber}, Episode: {epSb}"); - } - } - - if (info.genres.Any()) - { - AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); - } - - AddParagraph(sb, string.IsNullOrEmpty(seriesItem.Overview) ? info.summary : seriesItem.Overview); - endLoop = true; - } - catch (Exception e) - { - Log.Error(e); - } - finally - { - if (endLoop) - EndLoopHtml(sb); - } - } - sb.Append("


"); - } - - - - - private void EndLoopHtml(StringBuilder sb) - { - //NOTE: BR have to be in TD's as per html spec or it will be put outside of the table... - //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag - sb.Append("
"); - sb.Append("
"); - sb.Append("
"); - sb.Append(""); - sb.Append(""); - } - - } -} \ No newline at end of file diff --git a/Ombi.Services/Jobs/RecentlyAddedNewsletter/PlexRecentlyAddedNewsletter.cs b/Ombi.Services/Jobs/RecentlyAddedNewsletter/PlexRecentlyAddedNewsletter.cs deleted file mode 100644 index ca88b4c2b..000000000 --- a/Ombi.Services/Jobs/RecentlyAddedNewsletter/PlexRecentlyAddedNewsletter.cs +++ /dev/null @@ -1,425 +0,0 @@ -#region Copyright - -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: RecentlyAddedModel.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 - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using NLog; -using Ombi.Api; -using Ombi.Api.Interfaces; -using Ombi.Api.Models.Emby; -using Ombi.Api.Models.Plex; -using Ombi.Core; -using Ombi.Core.SettingModels; -using Ombi.Helpers; -using Ombi.Services.Jobs.Templates; -using Ombi.Store.Models; -using Ombi.Store.Models.Plex; -using Ombi.Store.Repository; -using TMDbLib.Objects.Exceptions; -using PlexMediaType = Ombi.Store.Models.Plex.PlexMediaType; - -namespace Ombi.Services.Jobs.RecentlyAddedNewsletter -{ - public class - PlexRecentlyAddedNewsletter : HtmlTemplateGenerator, IPlexNewsletter - { - public PlexRecentlyAddedNewsletter(IPlexApi api, ISettingsService plexSettings, - ISettingsService email, - ISettingsService newsletter, IRepository log, - IRepository embyContent, IRepository episodes) - { - Api = api; - PlexSettings = plexSettings; - EmailSettings = email; - NewsletterSettings = newsletter; - Content = embyContent; - MovieApi = new TheMovieDbApi(); - TvApi = new TvMazeApi(); - Episodes = episodes; - RecentlyAddedLog = log; - } - - private IPlexApi Api { get; } - private TheMovieDbApi MovieApi { get; } - private TvMazeApi TvApi { get; } - private ISettingsService PlexSettings { get; } - private ISettingsService EmailSettings { get; } - private ISettingsService NewsletterSettings { get; } - private IRepository Content { get; } - private IRepository Episodes { get; } - private IRepository RecentlyAddedLog { get; } - - private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - - public Newsletter GetNewsletter(bool test) - { - try - { - return GetHtml(test); - } - catch (Exception e) - { - Log.Error(e); - return null; - } - } - - private class PlexRecentlyAddedModel - { - public PlexMetadata Metadata { get; set; } - public PlexContent Content { get; set; } - public List EpisodeMetadata { get; set; } - } - - private Newsletter GetHtml(bool test) - { - var sb = new StringBuilder(); - var newsletter = new Newsletter(); - var plexSettings = PlexSettings.GetSettings(); - - var plexContent = Content.GetAll().ToList(); - - var series = plexContent.Where(x => x.Type == PlexMediaType.Show).ToList(); - var episodes = Episodes.GetAll().ToList(); - var movie = plexContent.Where(x => x.Type == PlexMediaType.Movie).ToList(); - - var recentlyAdded = RecentlyAddedLog.GetAll().ToList(); - - var firstRun = !recentlyAdded.Any(); - - var filteredMovies = movie.Where(m => recentlyAdded.All(x => x.ProviderId != m.ProviderId)).ToList(); - var filteredEp = episodes.Where(m => recentlyAdded.All(x => x.ProviderId != m.RatingKey)).ToList(); - var filteredSeries = series.Where(x => recentlyAdded.All(c => c.ProviderId != x.ProviderId)).ToList(); - - var info = new List(); - - if (test && !filteredMovies.Any()) - { - // if this is a test make sure we show something - filteredMovies = movie.Take(5).ToList(); - } - foreach (var m in filteredMovies.OrderByDescending(x => x.AddedAt)) - { - var i = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, m.ItemId); - if (i.Video == null) - { - continue; - } - info.Add(new PlexRecentlyAddedModel - { - Metadata = i, - Content = m - }); - } - GenerateMovieHtml(info, sb); - newsletter.MovieCount = info.Count; - - info.Clear(); - if (test && !filteredEp.Any() && episodes.Any()) - { - // if this is a test make sure we show something - filteredEp = episodes.Take(5).ToList(); - } - if (filteredEp.Any()) - { - var recentlyAddedModel = new List(); - foreach (var plexEpisodes in filteredEp) - { - // Find related series item - var relatedSeries = series.FirstOrDefault(x => x.ProviderId == plexEpisodes.ProviderId); - - if (relatedSeries == null) - { - continue; - } - - // Get series information - var i = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, relatedSeries.ItemId); - - var episodeInfo = Api.GetEpisodeMetaData(plexSettings.PlexAuthToken, plexSettings.FullUri, plexEpisodes.RatingKey); - // Check if we already have this series - var existingSeries = recentlyAddedModel.FirstOrDefault(x => - x.Metadata.Directory.RatingKey == i.Directory.RatingKey); - - if (existingSeries != null) - { - existingSeries.EpisodeMetadata.Add(episodeInfo); - } - else - { - recentlyAddedModel.Add(new PlexRecentlyAddedModel - { - Metadata = i, - EpisodeMetadata = new List() { episodeInfo }, - Content = relatedSeries - }); - } - } - - info.AddRange(recentlyAddedModel); - } - else - { - if (test && !filteredSeries.Any()) - { - // if this is a test make sure we show something - filteredSeries = series.Take(5).ToList(); - } - foreach (var t in filteredSeries.OrderByDescending(x => x.AddedAt)) - { - var i = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, t.ItemId); - if (i.Directory == null) - { - continue; - - } - - info.Add(new PlexRecentlyAddedModel - { - Metadata = i, - Content = t - }); - } - } - GenerateTvHtml(info, sb); - newsletter.TvCount = info.Count; - - var template = new RecentlyAddedTemplate(); - var html = template.LoadTemplate(sb.ToString()); - Log.Debug("Loaded the template"); - - if (!test || firstRun) - { - foreach (var a in filteredMovies) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = a.ProviderId, - AddedAt = DateTime.UtcNow - }); - } - foreach (var a in filteredEp) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = a.RatingKey, - AddedAt = DateTime.UtcNow - }); - } - foreach (var a in filteredSeries) - { - RecentlyAddedLog.Insert(new RecentlyAddedLog - { - ProviderId = a.ProviderId, - AddedAt = DateTime.UtcNow - }); - } - } - - var escapedHtml = new string(html.Where(c => !char.IsControl(c)).ToArray()); - Log.Debug(escapedHtml); - newsletter.Html = escapedHtml; - return newsletter; - } - - private void GenerateMovieHtml(IEnumerable recentlyAddedMovies, StringBuilder sb) - { - var movies = recentlyAddedMovies?.ToList() ?? new List(); - if (!movies.Any()) - { - return; - } - var orderedMovies = movies.OrderByDescending(x => x.Content.AddedAt).ToList(); - sb.Append("

New Movies:



"); - sb.Append( - ""); - 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 - { - - var imdbId = PlexHelper.GetProviderIdFromPlexGuid(movie.Metadata.Video.Guid); - 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(""); - sb.Append( - "
"); - - 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()) - { - AddParagraph(sb, - $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); - } - - 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) - { - Log.Error(e); - Log.Error("Error for movie with IMDB Id = {0}", movie.Metadata.Video.Guid); - } - finally - { - EndLoopHtml(sb); - } - - } - sb.Append("


"); - } - - private class TvModel - { - public EmbySeriesInformation Series { get; set; } - public List Episodes { get; set; } - } - private void GenerateTvHtml(IEnumerable recenetlyAddedTv, StringBuilder sb) - { - var tv = recenetlyAddedTv?.ToList() ?? new List(); - - if (!tv.Any()) - { - return; - } - var orderedTv = tv.OrderByDescending(x => x.Content.AddedAt).ToList(); - - // TV - sb.Append("

New Episodes:



"); - sb.Append( - ""); - foreach (var t in orderedTv) - { - var relatedEpisodes = t.EpisodeMetadata ?? new List(); - - try - { - var info = TvApi.ShowLookupByTheTvDbId(int.Parse(PlexHelper.GetProviderIdFromPlexGuid(t?.Metadata?.Directory?.Guid ?? string.Empty))); - - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.Replace("http", "https"); // Always use the Https banners - } - AddImageInsideTable(sb, banner); - - sb.Append(""); - sb.Append( - "
"); - - var title = $"{t.Content.Title} {t.Content.ReleaseYear}"; - - Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); - Header(sb, 3, title); - EndTag(sb, "a"); - - // Group by the ParentIndex (season number) - var results = relatedEpisodes.GroupBy(p => p.Video.FirstOrDefault()?.ParentIndex, - (key, g) => new - { - ParentIndexNumber = key, - IndexNumber = g.ToList() - } - ); - // Group the episodes - foreach (var epInformation in results.OrderBy(x => x.ParentIndexNumber)) - { - var orderedEpisodes = epInformation.IndexNumber.OrderBy(x => Convert.ToInt32(x.Video.FirstOrDefault().Index)).ToList(); - var epSb = new StringBuilder(); - for (var i = 0; i < orderedEpisodes.Count; i++) - { - var ep = orderedEpisodes[i]; - if (i < orderedEpisodes.Count - 1) - { - epSb.Append($"{ep.Video.FirstOrDefault().Index},"); - } - else - { - epSb.Append($"{ep.Video.FirstOrDefault().Index}"); - } - - } - AddParagraph(sb, $"Season: {epInformation.ParentIndexNumber}, Episode: {epSb}"); - } - - if (info.genres.Any()) - { - AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); - } - - AddParagraph(sb, string.IsNullOrEmpty(t.Metadata.Directory.Summary) ? t.Metadata.Directory.Summary : info.summary); - } - catch (Exception e) - { - Log.Error(e); - } - finally - { - EndLoopHtml(sb); - } - } - sb.Append("


"); - } - - - - - private void EndLoopHtml(StringBuilder sb) - { - //NOTE: BR have to be in TD's as per html spec or it will be put outside of the table... - //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag - sb.Append("
"); - sb.Append("
"); - sb.Append("
"); - sb.Append(""); - sb.Append(""); - } - - } -} \ No newline at end of file diff --git a/Ombi.UI/Views/About/About.cshtml b/Ombi.UI/Views/About/About.cshtml deleted file mode 100644 index ad65912c0..000000000 --- a/Ombi.UI/Views/About/About.cshtml +++ /dev/null @@ -1,227 +0,0 @@ -@using Ombi.UI.Helpers -@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase -@Html.Partial("Shared/Partial/_Sidebar") -@Html.LoadAsset("/Content/helpers/bootbox.min.js", true) - -
-
- About -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Application Version: - - @Model.ApplicationVersion -
- OS: - - @Model.Os -
- System Version: - - @Model.SystemVersion -
- Branch: - - @Model.Branch -
- Log Level: - - @Model.LogLevel -
- Database Location: - - @Model.DbLocation -
- Running Directory: - - @Model.RunningDir -
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
- Github - - https://github.com/tidusjar/Ombi -
- Forums - - https://forums.ombi.io/ -
- Wiki - - https://github.com/tidusjar/Ombi/wiki -
- Issues - - https://github.com/tidusjar/Ombi/issues -
- Chat - - https://gitter.im/tidusjar/Ombi -
- Feature Requests - - https://feathub.com/tidusjar/Ombi -
-
- @if (Model.OAuthEnabled) - { -
-
- -
-
- - } - else - { -
-
- -
-
- } - - -
-
- - \ No newline at end of file