From 868301f552f34191ad29a8882391962741e55e77 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 28 Jan 2017 16:54:48 +0000 Subject: [PATCH] Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435 --- Ombi.Api.Interfaces/IEmbyApi.cs | 16 + .../Ombi.Api.Interfaces.csproj | 1 + Ombi.Api.Models/Emby/EmbyConfiguration.cs | 47 +++ Ombi.Api.Models/Emby/EmbyImagetags.cs | 37 ++ Ombi.Api.Models/Emby/EmbyItem.cs | 47 +++ Ombi.Api.Models/Emby/EmbyItemContainer.cs | 37 ++ Ombi.Api.Models/Emby/EmbyMovieItem.cs | 59 +++ Ombi.Api.Models/Emby/EmbyPolicy.cs | 63 ++++ Ombi.Api.Models/Emby/EmbySeriesItem.cs | 56 +++ Ombi.Api.Models/Emby/EmbyUser.cs | 48 +++ Ombi.Api.Models/Emby/EmbyUserdata.cs | 42 +++ Ombi.Api.Models/Ombi.Api.Models.csproj | 9 + Ombi.Api/EmbyApi.cs | 138 +++++++ Ombi.Api/Ombi.Api.csproj | 4 + Ombi.Api/packages.config | 1 + Ombi.Core.Migration/Migrations/Version2200.cs | 11 +- Ombi.Core/Ombi.Core.csproj | 1 + Ombi.Core/Queue/TransientFaultQueue.cs | 2 +- Ombi.Core/SettingModels/EmbySettings.cs | 37 ++ Ombi.Core/SettingModels/PlexSettings.cs | 2 + .../PlexAvailabilityCheckerTests.cs | 4 +- Ombi.Services/Jobs/EmbyAvailabilityChecker.cs | 357 ++++++++++++++++++ .../Jobs/IEmbyAvailabilityChecker.cs | 24 ++ Ombi.Services/Jobs/JobNames.cs | 1 + Ombi.Services/Jobs/PlexAvailabilityChecker.cs | 13 +- Ombi.Services/Jobs/PlexContentCacher.cs | 11 +- Ombi.Services/Jobs/PlexUserChecker.cs | 2 +- Ombi.Services/Ombi.Services.csproj | 2 + Ombi.Store/Models/Emby/EmbyContent.cs | 43 +++ Ombi.Store/Models/Emby/EmbyEpisodes.cs | 43 +++ Ombi.Store/Models/Emby/EmbyMediaType.cs | 35 ++ Ombi.Store/Ombi.Store.csproj | 3 + Ombi.Store/SqlTables.sql | 25 ++ Ombi.UI/Modules/Admin/AdminModule.cs | 55 ++- Ombi.UI/Modules/ApplicationTesterModule.cs | 36 +- Ombi.UI/Modules/UserLoginModule.cs | 1 + Ombi.UI/NinjectModules/ApiModule.cs | 1 + Ombi.UI/NinjectModules/ServicesModule.cs | 3 + Ombi.UI/Ombi.UI.csproj | 4 + Ombi.UI/Startup.cs | 2 + Ombi.UI/Validators/EmbyValidator.cs | 42 +++ Ombi.UI/Views/Admin/Emby.cshtml | 146 +++++++ Ombi.UI/Views/Admin/Plex.cshtml | 2 + 43 files changed, 1495 insertions(+), 18 deletions(-) create mode 100644 Ombi.Api.Interfaces/IEmbyApi.cs create mode 100644 Ombi.Api.Models/Emby/EmbyConfiguration.cs create mode 100644 Ombi.Api.Models/Emby/EmbyImagetags.cs create mode 100644 Ombi.Api.Models/Emby/EmbyItem.cs create mode 100644 Ombi.Api.Models/Emby/EmbyItemContainer.cs create mode 100644 Ombi.Api.Models/Emby/EmbyMovieItem.cs create mode 100644 Ombi.Api.Models/Emby/EmbyPolicy.cs create mode 100644 Ombi.Api.Models/Emby/EmbySeriesItem.cs create mode 100644 Ombi.Api.Models/Emby/EmbyUser.cs create mode 100644 Ombi.Api.Models/Emby/EmbyUserdata.cs create mode 100644 Ombi.Api/EmbyApi.cs create mode 100644 Ombi.Core/SettingModels/EmbySettings.cs create mode 100644 Ombi.Services/Jobs/EmbyAvailabilityChecker.cs create mode 100644 Ombi.Services/Jobs/IEmbyAvailabilityChecker.cs create mode 100644 Ombi.Store/Models/Emby/EmbyContent.cs create mode 100644 Ombi.Store/Models/Emby/EmbyEpisodes.cs create mode 100644 Ombi.Store/Models/Emby/EmbyMediaType.cs create mode 100644 Ombi.UI/Validators/EmbyValidator.cs create mode 100644 Ombi.UI/Views/Admin/Emby.cshtml diff --git a/Ombi.Api.Interfaces/IEmbyApi.cs b/Ombi.Api.Interfaces/IEmbyApi.cs new file mode 100644 index 000000000..58ea0087b --- /dev/null +++ b/Ombi.Api.Interfaces/IEmbyApi.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using Ombi.Api.Models.Emby; + +namespace Ombi.Api.Interfaces +{ + public interface IEmbyApi + { + string ApiKey { get; } + + EmbyItemContainer GetAllMovies(string apiKey, string userId, Uri baseUri); + EmbyItemContainer GetAllShows(string apiKey, string userId, Uri baseUri); + List GetUsers(Uri baseUri, string apiKey); + EmbyItemContainer ViewLibrary(string apiKey, string userId, Uri baseUri); + } +} \ No newline at end of file diff --git a/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj b/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj index c8c1ca938..172c009e4 100644 --- a/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj +++ b/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj @@ -56,6 +56,7 @@ + diff --git a/Ombi.Api.Models/Emby/EmbyConfiguration.cs b/Ombi.Api.Models/Emby/EmbyConfiguration.cs new file mode 100644 index 000000000..4df656cce --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyConfiguration.cs @@ -0,0 +1,47 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyUser.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 EmbyConfiguration + { + public bool PlayDefaultAudioTrack { get; set; } + public bool DisplayMissingEpisodes { get; set; } + public bool DisplayUnairedEpisodes { get; set; } + public object[] GroupedFolders { get; set; } + public string SubtitleMode { get; set; } + public bool DisplayCollectionsView { get; set; } + public bool EnableLocalPassword { get; set; } + public object[] OrderedViews { get; set; } + public object[] LatestItemsExcludes { get; set; } + public bool HidePlayedInLatest { get; set; } + public bool RememberAudioSelections { get; set; } + public bool RememberSubtitleSelections { get; set; } + public bool EnableNextEpisodeAutoPlay { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyImagetags.cs b/Ombi.Api.Models/Emby/EmbyImagetags.cs new file mode 100644 index 000000000..cf36ae696 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyImagetags.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyLibrary.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 EmbyImagetags + { + public string Primary { get; set; } + public string Logo { get; set; } + public string Thumb { get; set; } + + public string Banner { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyItem.cs b/Ombi.Api.Models/Emby/EmbyItem.cs new file mode 100644 index 000000000..85d41ddf2 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyItem.cs @@ -0,0 +1,47 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyLibrary.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 EmbyLibrary + { + public string Name { get; set; } + public string ServerId { get; set; } + public string Id { get; set; } + public bool HasDynamicCategories { get; set; } + public string PlayAccess { get; set; } + public bool IsFolder { get; set; } + public string Type { get; set; } + public EmbyUserdata UserData { get; set; } + public int ChildCount { get; set; } + public string CollectionType { get; set; } + public string OriginalCollectionType { get; set; } + public EmbyImagetags ImageTags { get; set; } + public object[] BackdropImageTags { get; set; } + public string LocationType { get; set; } + } + +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyItemContainer.cs b/Ombi.Api.Models/Emby/EmbyItemContainer.cs new file mode 100644 index 000000000..10b8c0a71 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyItemContainer.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyItemContainer.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.Collections.Generic; + +namespace Ombi.Api.Models.Emby +{ + public class EmbyItemContainer + { + public List Items { get; set; } + public int TotalRecordCount { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyMovieItem.cs b/Ombi.Api.Models/Emby/EmbyMovieItem.cs new file mode 100644 index 000000000..5c4cc514f --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyMovieItem.cs @@ -0,0 +1,59 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyMovieItem.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; + +namespace Ombi.Api.Models.Emby +{ + public class EmbyMovieItem + { + public string Name { get; set; } + public string ServerId { get; set; } + public string Id { get; set; } + public string Container { get; set; } + public DateTime PremiereDate { get; set; } + public object[] ProductionLocations { get; set; } + public string OfficialRating { get; set; } + public float CommunityRating { get; set; } + public long RunTimeTicks { get; set; } + public string PlayAccess { get; set; } + public int ProductionYear { get; set; } + public bool IsPlaceHolder { get; set; } + public bool IsHD { get; set; } + public bool IsFolder { get; set; } + public string Type { get; set; } + public int LocalTrailerCount { get; set; } + public EmbyUserdata UserData { get; set; } + public string VideoType { get; set; } + public EmbyImagetags ImageTags { get; set; } + public string[] BackdropImageTags { get; set; } + public string LocationType { get; set; } + public string MediaType { get; set; } + public bool HasSubtitles { get; set; } + public int CriticRating { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyPolicy.cs b/Ombi.Api.Models/Emby/EmbyPolicy.cs new file mode 100644 index 000000000..5ffe07bce --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyPolicy.cs @@ -0,0 +1,63 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyUser.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 EmbyPolicy + { + public bool IsAdministrator { get; set; } + public bool IsHidden { get; set; } + public bool IsDisabled { get; set; } + public object[] BlockedTags { get; set; } + public bool EnableUserPreferenceAccess { get; set; } + public object[] AccessSchedules { get; set; } + public object[] BlockUnratedItems { get; set; } + public bool EnableRemoteControlOfOtherUsers { get; set; } + public bool EnableSharedDeviceControl { get; set; } + public bool EnableLiveTvManagement { get; set; } + public bool EnableLiveTvAccess { get; set; } + public bool EnableMediaPlayback { get; set; } + public bool EnableAudioPlaybackTranscoding { get; set; } + public bool EnableVideoPlaybackTranscoding { get; set; } + public bool EnablePlaybackRemuxing { get; set; } + public bool EnableContentDeletion { get; set; } + public bool EnableContentDownloading { get; set; } + public bool EnableSync { get; set; } + public bool EnableSyncTranscoding { get; set; } + public object[] EnabledDevices { get; set; } + public bool EnableAllDevices { get; set; } + public object[] EnabledChannels { get; set; } + public bool EnableAllChannels { get; set; } + public object[] EnabledFolders { get; set; } + public bool EnableAllFolders { get; set; } + public int InvalidLoginAttemptCount { get; set; } + public bool EnablePublicSharing { get; set; } + } + + +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbySeriesItem.cs b/Ombi.Api.Models/Emby/EmbySeriesItem.cs new file mode 100644 index 000000000..2c3674662 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbySeriesItem.cs @@ -0,0 +1,56 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbySeriesItem.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; + +namespace Ombi.Api.Models.Emby +{ + public class EmbySeriesItem + { + public string Name { get; set; } + public string ServerId { get; set; } + public string Id { get; set; } + public DateTime PremiereDate { get; set; } + public string OfficialRating { get; set; } + public float CommunityRating { get; set; } + public long RunTimeTicks { get; set; } + public string PlayAccess { get; set; } + public int ProductionYear { get; set; } + public bool IsFolder { get; set; } + public string Type { get; set; } + public int LocalTrailerCount { get; set; } + public EmbyUserdata UserData { get; set; } + public int ChildCount { get; set; } + public string Status { get; set; } + public string AirTime { get; set; } + public string[] AirDays { get; set; } + public EmbyImagetags ImageTags { get; set; } + public string[] BackdropImageTags { get; set; } + public string LocationType { get; set; } + public DateTime EndDate { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyUser.cs b/Ombi.Api.Models/Emby/EmbyUser.cs new file mode 100644 index 000000000..9ebf75731 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyUser.cs @@ -0,0 +1,48 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyUser.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; + +namespace Ombi.Api.Models.Emby +{ + public class EmbyUser + { + public string Name { get; set; } + public string ServerId { get; set; } + public string ConnectUserName { get; set; } + public string ConnectUserId { get; set; } + public string ConnectLinkType { get; set; } + public string Id { get; set; } + public bool HasPassword { get; set; } + public bool HasConfiguredPassword { get; set; } + public bool HasConfiguredEasyPassword { get; set; } + public DateTime LastLoginDate { get; set; } + public DateTime LastActivityDate { get; set; } + public EmbyConfiguration Configuration { get; set; } + public EmbyPolicy Policy { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Emby/EmbyUserdata.cs b/Ombi.Api.Models/Emby/EmbyUserdata.cs new file mode 100644 index 000000000..fe86591d0 --- /dev/null +++ b/Ombi.Api.Models/Emby/EmbyUserdata.cs @@ -0,0 +1,42 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyLibrary.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; + +namespace Ombi.Api.Models.Emby +{ + public class EmbyUserdata + { + public int PlaybackPositionTicks { get; set; } + public int PlayCount { get; set; } + public bool IsFavorite { get; set; } + public bool Played { get; set; } + public string Key { get; set; } + public DateTime LastPlayedDate { get; set; } + public int UnplayedItemCount { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Ombi.Api.Models.csproj b/Ombi.Api.Models/Ombi.Api.Models.csproj index 39df12460..1e71a7008 100644 --- a/Ombi.Api.Models/Ombi.Api.Models.csproj +++ b/Ombi.Api.Models/Ombi.Api.Models.csproj @@ -49,6 +49,15 @@ + + + + + + + + + diff --git a/Ombi.Api/EmbyApi.cs b/Ombi.Api/EmbyApi.cs new file mode 100644 index 000000000..151ae020a --- /dev/null +++ b/Ombi.Api/EmbyApi.cs @@ -0,0 +1,138 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyApi.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 NLog; +using Ombi.Api.Interfaces; +using Ombi.Api.Models.Emby; +using RestSharp; + +namespace Ombi.Api +{ + public class EmbyApi : IEmbyApi + { + public string ApiKey => "4aa083121ab646bfa38aa5f7196056cf"; + + public EmbyApi() + { + Api = new ApiRequest(); + } + + private ApiRequest Api { get; } + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + /// + /// Returns all users from the Emby Instance + /// + /// + /// + public List GetUsers(Uri baseUri, string apiKey) + { + var request = new RestRequest + { + Resource = "emby/users", + Method = Method.GET + }; + + AddHeaders(request, ApiKey); + + var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetUsers for Emby, Retrying {0}", timespan), new[] { + TimeSpan.FromSeconds (1), + TimeSpan.FromSeconds(5) + }); + + var obj = policy.Execute(() => Api.ExecuteJson>(request, baseUri)); + + return obj; + } + + public EmbyItemContainer ViewLibrary(string apiKey, string userId, Uri baseUri) + { + var request = new RestRequest + { + Resource = "emby/users/{userId}/items", + Method = Method.GET + }; + + request.AddUrlSegment("userId", userId); + AddHeaders(request, ApiKey); + + var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling ViewLibrary for Emby, Retrying {0}", timespan), new[] { + TimeSpan.FromSeconds (1), + TimeSpan.FromSeconds(5) + }); + + var obj = policy.Execute(() => Api.ExecuteJson>(request, baseUri)); + + return obj; + } + + public EmbyItemContainer GetAllMovies(string apiKey, string userId, Uri baseUri) + { + return GetAll("Movie", apiKey, userId, baseUri); + } + + public EmbyItemContainer GetAllShows(string apiKey, string userId, Uri baseUri) + { + return GetAll("Series", apiKey, userId, baseUri); + } + + private EmbyItemContainer GetAll(string type, string apiKey, string userId, Uri baseUri) + { + var request = new RestRequest + { + Resource = "emby/users/{userId}/items", + Method = Method.GET + }; + + request.AddUrlSegment("userId", userId); + request.AddQueryParameter("Recursive", true.ToString()); + request.AddQueryParameter("IncludeItemTypes", type); + + AddHeaders(request, ApiKey); + + + var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetAll({1}) for Emby, Retrying {0}", timespan, type), new[] { + TimeSpan.FromSeconds (1), + TimeSpan.FromSeconds(5) + }); + + var obj = policy.Execute(() => Api.ExecuteJson>(request, baseUri)); + + return obj; + } + + + private static void AddHeaders(IRestRequest req, string apiKey) + { + req.AddHeader("X-MediaBrowser-Token", apiKey); + req.AddHeader("Accept", "application/json"); + req.AddHeader("Content-Type", "application/json"); + } + } +} \ No newline at end of file diff --git a/Ombi.Api/Ombi.Api.csproj b/Ombi.Api/Ombi.Api.csproj index b9e674cc2..c9d00b030 100644 --- a/Ombi.Api/Ombi.Api.csproj +++ b/Ombi.Api/Ombi.Api.csproj @@ -70,10 +70,14 @@ ..\packages\TraktApiSharp.0.8.0\lib\portable-net45+netcore45+wpa81\TraktApiSharp.dll True + + ..\packages\WebSocket4Net.0.14.1\lib\net45\WebSocket4Net.dll + + diff --git a/Ombi.Api/packages.config b/Ombi.Api/packages.config index a20220585..b21cb47a8 100644 --- a/Ombi.Api/packages.config +++ b/Ombi.Api/packages.config @@ -9,4 +9,5 @@ + \ No newline at end of file diff --git a/Ombi.Core.Migration/Migrations/Version2200.cs b/Ombi.Core.Migration/Migrations/Version2200.cs index a28f852de..d4ffc4042 100644 --- a/Ombi.Core.Migration/Migrations/Version2200.cs +++ b/Ombi.Core.Migration/Migrations/Version2200.cs @@ -36,23 +36,32 @@ namespace Ombi.Core.Migration.Migrations [Migration(22000, "v2.20.0.0")] public class Version2200 : BaseMigration, IMigration { - public Version2200(ISettingsService custom) + public Version2200(ISettingsService custom, ISettingsService ps) { Customization = custom; + PlexSettings = ps; } public int Version => 22000; private ISettingsService Customization { get; set; } + private ISettingsService PlexSettings { get; set; } private static Logger Logger = LogManager.GetCurrentClassLogger(); public void Start(IDbConnection con) { + UpdatePlexSettings(); //UpdateCustomSettings(); Turned off the migration for now until the search has been improved on. //UpdateSchema(con, Version); } + private void UpdatePlexSettings() + { + var s = PlexSettings.GetSettings(); + s.Enable = true; + PlexSettings.SaveSettings(s); + } private void UpdateCustomSettings() { var settings = Customization.GetSettings(); diff --git a/Ombi.Core/Ombi.Core.csproj b/Ombi.Core/Ombi.Core.csproj index f3f05b9da..9866e6fb0 100644 --- a/Ombi.Core/Ombi.Core.csproj +++ b/Ombi.Core/Ombi.Core.csproj @@ -123,6 +123,7 @@ + diff --git a/Ombi.Core/Queue/TransientFaultQueue.cs b/Ombi.Core/Queue/TransientFaultQueue.cs index 11eb1bd5a..fcb8338d4 100644 --- a/Ombi.Core/Queue/TransientFaultQueue.cs +++ b/Ombi.Core/Queue/TransientFaultQueue.cs @@ -105,7 +105,7 @@ namespace Ombi.Core.Queue public IEnumerable GetQueue() { var items = RequestQueue.GetAll(); - + return items; } diff --git a/Ombi.Core/SettingModels/EmbySettings.cs b/Ombi.Core/SettingModels/EmbySettings.cs new file mode 100644 index 000000000..42344cddd --- /dev/null +++ b/Ombi.Core/SettingModels/EmbySettings.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: CouchPotatoSettings.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.Core.SettingModels +{ + public sealed class EmbySettings : ExternalSettings + { + public bool Enable { get; set; } + public string ApiKey { get; set; } + public string AdministratorId { get; set; } + public bool EnableEpisodeSearching { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Core/SettingModels/PlexSettings.cs b/Ombi.Core/SettingModels/PlexSettings.cs index b40b69018..91f95fe2e 100644 --- a/Ombi.Core/SettingModels/PlexSettings.cs +++ b/Ombi.Core/SettingModels/PlexSettings.cs @@ -33,6 +33,8 @@ namespace Ombi.Core.SettingModels { AdvancedSearch = true; } + + public bool Enable { get; set; } public bool AdvancedSearch { get; set; } public bool EnableTvEpisodeSearching { get; set; } diff --git a/Ombi.Services.Tests/PlexAvailabilityCheckerTests.cs b/Ombi.Services.Tests/PlexAvailabilityCheckerTests.cs index 1097bfb67..47b9e5007 100644 --- a/Ombi.Services.Tests/PlexAvailabilityCheckerTests.cs +++ b/Ombi.Services.Tests/PlexAvailabilityCheckerTests.cs @@ -249,7 +249,7 @@ // }); // CacheMock.Setup(x => x.Get>(CacheKeys.PlexLibaries)).Returns(cachedMovies); // SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create()); -// var movies = Checker.GetPlexMovies(); +// var movies = Checker.GetEmbyMovies(); // Assert.That(movies.Any(x => x.ProviderId == "1212")); // } @@ -267,7 +267,7 @@ // }); // SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create()); // CacheMock.Setup(x => x.Get>(CacheKeys.PlexLibaries)).Returns(cachedTv); -// var movies = Checker.GetPlexTvShows(); +// var movies = Checker.GetEmbyTvShows(); // Assert.That(movies.Any(x => x.ProviderId == "1212")); // } diff --git a/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs b/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs new file mode 100644 index 000000000..2a77718f0 --- /dev/null +++ b/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs @@ -0,0 +1,357 @@ +#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 System.Threading.Tasks; +using Dapper; +using NLog; +using Ombi.Api.Interfaces; +using Ombi.Api.Models.Plex; +using Ombi.Core; +using Ombi.Core.Models; +using Ombi.Core.SettingModels; +using Ombi.Helpers; +using Ombi.Services.Interfaces; +using Ombi.Services.Models; +using Ombi.Store; +using Ombi.Store.Models; +using Ombi.Store.Models.Emby; +using Ombi.Store.Models.Plex; +using Ombi.Store.Repository; +using Quartz; +using PlexMediaType = Ombi.Api.Models.Plex.PlexMediaType; + +namespace Ombi.Services.Jobs +{ + public class EmbyAvailabilityChecker : IJob, IEmbyAvailabilityChecker + { + public EmbyAvailabilityChecker(ISettingsService embySettings, IRequestService request, IEmbyApi emby, ICacheProvider cache, + INotificationService notify, IJobRecord rec, IRepository users, IRepository repo, INotificationEngine e, IRepository content) + { + Emby = embySettings; + RequestService = request; + EmbyApi = emby; + Cache = cache; + Notification = notify; + Job = rec; + UserNotifyRepo = users; + EpisodeRepo = repo; + NotificationEngine = e; + EmbyContent = content; + } + + private ISettingsService Emby { get; } + private IRepository EpisodeRepo { get; } + private IRequestService RequestService { get; } + private static Logger Log = LogManager.GetCurrentClassLogger(); + private IEmbyApi EmbyApi { get; } + private ICacheProvider Cache { get; } + private INotificationService Notification { get; } + private IJobRecord Job { get; } + private IRepository UserNotifyRepo { get; } + private INotificationEngine NotificationEngine { get; } + private IRepository EmbyContent { get; } + + public void CheckAndUpdateAll() + { + var embySettings = Emby.GetSettings(); + + if (!ValidateSettings(embySettings)) + { + Log.Debug("Validation of the Emby settings failed."); + return; + } + + var content = EmbyContent.GetAll().ToList(); + + var movies = GetEmbyMovies(content).ToArray(); + var shows = GetEmbyTvShows(content).ToArray(); + var albums = GetEmbyMusic(content).ToArray(); + + var requests = RequestService.GetAll(); + var requestedModels = requests as RequestedModel[] ?? requests.Where(x => !x.Available).ToArray(); + + if (!requestedModels.Any()) + { + Log.Debug("There are no requests to check."); + return; + } + + var modifiedModel = new List(); + foreach (var r in requestedModels) + { + var releaseDate = r.ReleaseDate == DateTime.MinValue ? string.Empty : r.ReleaseDate.ToString("yyyy"); + bool matchResult; + + switch (r.Type) + { + case RequestType.Movie: + matchResult = IsMovieAvailable(movies, r.Title, releaseDate, r.ImdbId); + break; + case RequestType.TvShow: + if (!embySettings.EnableEpisodeSearching) + { + matchResult = IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList); + } + else + { + matchResult = r.Episodes.Any() ? + r.Episodes.All(x => IsEpisodeAvailable(r.TvDbId, x.SeasonNumber, x.EpisodeNumber)) : + IsTvShowAvailable(shows, r.Title, releaseDate, r.TvDbId, r.SeasonList); + } + break; + case RequestType.Album: + //matchResult = IsAlbumAvailable(albums, r.Title, r.ReleaseDate.Year.ToString(), r.ArtistName); // TODO Emby + matchResult = false; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + + if (matchResult) + { + r.Available = true; + modifiedModel.Add(r); + continue; + } + + } + + Log.Debug("Requests that will be updated count {0}", modifiedModel.Count); + + if (modifiedModel.Any()) + { + NotificationEngine.NotifyUsers(modifiedModel, embySettings.ApiKey, NotificationType.RequestAvailable); // TODO Emby + RequestService.BatchUpdate(modifiedModel); + } + } + + public IEnumerable GetEmbyMovies(IEnumerable content) + { + return content.Where(x => x.Type == EmbyMediaType.Movie); + } + + public bool IsMovieAvailable(EmbyContent[] embyMovies, string title, string year, string providerId) + { + var movie = GetMovie(embyMovies, title, year, providerId); + return movie != null; + } + + public EmbyContent GetMovie(EmbyContent[] embyMovies, string title, string year, string providerId) + { + if (embyMovies.Length == 0) + { + return null; + } + foreach (var movie in embyMovies) + { + if (string.IsNullOrEmpty(movie.Title) || movie.PremierDate == DateTime.MinValue) + { + continue; + } + + if (!string.IsNullOrEmpty(movie.ProviderId) && + movie.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) + { + return movie; + } + + if (movie.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && + movie.PremierDate.Year.ToString().Equals(year, StringComparison.CurrentCultureIgnoreCase)) + { + return movie; + } + } + return null; + } + + public IEnumerable GetEmbyTvShows(IEnumerable content) + { + return content.Where(x => x.Type == EmbyMediaType.Series); + } + + public bool IsTvShowAvailable(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null) + { + var show = GetTvShow(embyShows, title, year, providerId, seasons); + return show != null; + } + + + public EmbyContent GetTvShow(EmbyContent[] embyShows, string title, string year, string providerId, + int[] seasons = null) + { + foreach (var show in embyShows) + { + //if (show.ProviderId == providerId && seasons != null) // TODO Emby + //{ + // var showSeasons = ByteConverterHelper.ReturnObject(show.Seasons); + // if (seasons.Any(season => showSeasons.Contains(season))) + // { + // return show; + // } + // return null; + //} + if (!string.IsNullOrEmpty(show.ProviderId) && + show.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) + { + return show; + } + + if (show.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && + show.PremierDate.Year.ToString().Equals(year, StringComparison.CurrentCultureIgnoreCase)) + { + return show; + } + } + return null; + } + + public bool IsEpisodeAvailable(string theTvDbId, int season, int episode) + { + var ep = EpisodeRepo.Custom( + connection => + { + connection.Open(); + var result = connection.Query("select * from EmbyEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId }); + + return result; + }).ToList(); + + if (!ep.Any()) + { + Log.Info("Episode cache info is not available. tvdbid: {0}, season: {1}, episode: {2}", theTvDbId, season, episode); + return false; + } + foreach (var result in ep) + { + if (result.ProviderId.Equals(theTvDbId) && result.EpisodeNumber == episode && result.SeasonNumber == season) + { + return true; + } + } + return false; + } + + /// + /// Gets the episode's db in the cache. + /// + /// + public async Task> GetEpisodes() + { + var episodes = await EpisodeRepo.GetAllAsync(); + if (episodes == null) + { + return new HashSet(); + } + return episodes; + } + + /// + /// Gets the episode's stored in the db and then filters on the TheTvDBId. + /// + /// The tv database identifier. + /// + public async Task> GetEpisodes(int theTvDbId) + { + var ep = await EpisodeRepo.CustomAsync(async connection => + { + connection.Open(); + var result = await connection.QueryAsync("select * from EmbyEpisodes where ProviderId = @ProviderId", new { ProviderId = theTvDbId }); + + return result; + }); + + var embyEpisodes = ep as EmbyEpisodes[] ?? ep.ToArray(); + if (!embyEpisodes.Any()) + { + Log.Info("Episode db info is not available."); + return new List(); + } + + return embyEpisodes; + } + + public IEnumerable GetEmbyMusic(IEnumerable content) + { + return content.Where(x => x.Type == EmbyMediaType.Music); + } + + + private bool ValidateSettings(EmbySettings emby) + { + if (emby.Enable) + { + if (string.IsNullOrEmpty(emby?.Ip) || string.IsNullOrEmpty(emby?.ApiKey) || string.IsNullOrEmpty(emby?.AdministratorId)) + { + Log.Warn("A setting is null, Ensure Emby is configured correctly"); + return false; + } + } + return emby.Enable; + } + + public void Execute(IJobExecutionContext context) + { + + Job.SetRunning(true, JobNames.EmbyChecker); + try + { + CheckAndUpdateAll(); + } + catch (Exception e) + { + Log.Error(e); + } + finally + { + Job.Record(JobNames.EmbyChecker); + Job.SetRunning(false, JobNames.EmbyChecker); + } + } + + public void Start() + { + Job.SetRunning(true, JobNames.EmbyChecker); + try + { + CheckAndUpdateAll(); + } + catch (Exception e) + { + Log.Error(e); + } + finally + { + Job.Record(JobNames.EmbyChecker); + Job.SetRunning(false, JobNames.EmbyChecker); + } + } + } +} \ No newline at end of file diff --git a/Ombi.Services/Jobs/IEmbyAvailabilityChecker.cs b/Ombi.Services/Jobs/IEmbyAvailabilityChecker.cs new file mode 100644 index 000000000..a954064e7 --- /dev/null +++ b/Ombi.Services/Jobs/IEmbyAvailabilityChecker.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Store.Models.Emby; +using Quartz; + +namespace Ombi.Services.Jobs +{ + public interface IEmbyAvailabilityChecker + { + void CheckAndUpdateAll(); + void Execute(IJobExecutionContext context); + IEnumerable GetEmbyMovies(IEnumerable content); + IEnumerable GetEmbyMusic(IEnumerable content); + IEnumerable GetEmbyTvShows(IEnumerable content); + Task> GetEpisodes(); + Task> GetEpisodes(int theTvDbId); + EmbyContent GetMovie(EmbyContent[] embyMovies, string title, string year, string providerId); + EmbyContent GetTvShow(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null); + bool IsEpisodeAvailable(string theTvDbId, int season, int episode); + bool IsMovieAvailable(EmbyContent[] embyMovies, string title, string year, string providerId); + bool IsTvShowAvailable(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null); + void Start(); + } +} \ No newline at end of file diff --git a/Ombi.Services/Jobs/JobNames.cs b/Ombi.Services/Jobs/JobNames.cs index 8b663a8ae..61b546cc1 100644 --- a/Ombi.Services/Jobs/JobNames.cs +++ b/Ombi.Services/Jobs/JobNames.cs @@ -35,6 +35,7 @@ namespace Ombi.Services.Jobs public const string RadarrCacher = "Radarr Cacher"; public const string SrCacher = "SickRage Cacher"; public const string PlexChecker = "Plex Availability Cacher"; + public const string EmbyChecker = "Emby Availability Cacher"; public const string PlexCacher = "Plex Cacher"; public const string StoreCleanup = "Database Cleanup"; public const string RequestLimitReset = "Request Limit Reset"; diff --git a/Ombi.Services/Jobs/PlexAvailabilityChecker.cs b/Ombi.Services/Jobs/PlexAvailabilityChecker.cs index e205b5b1b..cd64a3b18 100644 --- a/Ombi.Services/Jobs/PlexAvailabilityChecker.cs +++ b/Ombi.Services/Jobs/PlexAvailabilityChecker.cs @@ -388,7 +388,7 @@ namespace Ombi.Services.Jobs 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)); + var filtered = seasons.Directory.Where(x => !x.Title.Equals("All episodes", StringComparison.CurrentCultureIgnoreCase)); t1.Seasons.AddRange(filtered); } @@ -447,12 +447,15 @@ namespace Ombi.Services.Jobs private bool ValidateSettings(PlexSettings plex) { - if (plex?.Ip == null || plex?.PlexAuthToken == null) + if (plex.Enable) { - Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token."); - return false; + 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 true; + return plex.Enable; } public void Execute(IJobExecutionContext context) diff --git a/Ombi.Services/Jobs/PlexContentCacher.cs b/Ombi.Services/Jobs/PlexContentCacher.cs index d21d26a8b..44ad9edd3 100644 --- a/Ombi.Services/Jobs/PlexContentCacher.cs +++ b/Ombi.Services/Jobs/PlexContentCacher.cs @@ -385,12 +385,15 @@ namespace Ombi.Services.Jobs private bool ValidateSettings(PlexSettings plex) { - if (plex?.Ip == null || plex?.PlexAuthToken == null) + if (plex.Enable) { - Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token."); - return false; + 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 true; + return plex.Enable; } public void Execute(IJobExecutionContext context) diff --git a/Ombi.Services/Jobs/PlexUserChecker.cs b/Ombi.Services/Jobs/PlexUserChecker.cs index 3303d1dcf..708648756 100644 --- a/Ombi.Services/Jobs/PlexUserChecker.cs +++ b/Ombi.Services/Jobs/PlexUserChecker.cs @@ -75,7 +75,7 @@ namespace Ombi.Services.Jobs try { var settings = PlexSettings.GetSettings(); - if (string.IsNullOrEmpty(settings.PlexAuthToken)) + if (string.IsNullOrEmpty(settings.PlexAuthToken) || !settings.Enable) { return; } diff --git a/Ombi.Services/Ombi.Services.csproj b/Ombi.Services/Ombi.Services.csproj index 6705cf939..dfe630a25 100644 --- a/Ombi.Services/Ombi.Services.csproj +++ b/Ombi.Services/Ombi.Services.csproj @@ -93,9 +93,11 @@ + + diff --git a/Ombi.Store/Models/Emby/EmbyContent.cs b/Ombi.Store/Models/Emby/EmbyContent.cs new file mode 100644 index 000000000..799487755 --- /dev/null +++ b/Ombi.Store/Models/Emby/EmbyContent.cs @@ -0,0 +1,43 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: Emby.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 Dapper.Contrib.Extensions; +using Ombi.Store.Models.Plex; + +namespace Ombi.Store.Models.Emby +{ + [Table(nameof(EmbyContent))] + public class EmbyContent : Entity + { + public string Title { get; set; } + public string EmbyId { get; set; } + public DateTime PremierDate { get; set; } + public string ProviderId { get; set; } + public EmbyMediaType Type { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Store/Models/Emby/EmbyEpisodes.cs b/Ombi.Store/Models/Emby/EmbyEpisodes.cs new file mode 100644 index 000000000..a1b900455 --- /dev/null +++ b/Ombi.Store/Models/Emby/EmbyEpisodes.cs @@ -0,0 +1,43 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: EmbyEpisodes.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 Dapper.Contrib.Extensions; + +namespace Ombi.Store.Models.Emby +{ + [Table(nameof(EmbyEpisodes))] + public class EmbyEpisodes : Entity + { + public string EpisodeTitle { get; set; } + public string ShowTitle { get; set; } + public string EmbyId { get; set; } + public int EpisodeNumber { get; set; } + public int SeasonNumber { get; set; } + public string ParentId { get; set; } + public string ProviderId { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Store/Models/Emby/EmbyMediaType.cs b/Ombi.Store/Models/Emby/EmbyMediaType.cs new file mode 100644 index 000000000..eaf2fac85 --- /dev/null +++ b/Ombi.Store/Models/Emby/EmbyMediaType.cs @@ -0,0 +1,35 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexMediaType .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.Store.Models.Plex +{ + public enum EmbyMediaType + { + Movie = 0, + Series = 1, + Music = 2 + } +} \ No newline at end of file diff --git a/Ombi.Store/Ombi.Store.csproj b/Ombi.Store/Ombi.Store.csproj index ea9ca2469..33298c6d1 100644 --- a/Ombi.Store/Ombi.Store.csproj +++ b/Ombi.Store/Ombi.Store.csproj @@ -65,11 +65,14 @@ + + + diff --git a/Ombi.Store/SqlTables.sql b/Ombi.Store/SqlTables.sql index 90116a206..82c58fa7c 100644 --- a/Ombi.Store/SqlTables.sql +++ b/Ombi.Store/SqlTables.sql @@ -164,4 +164,29 @@ CREATE TABLE IF NOT EXISTS PlexContent ); CREATE UNIQUE INDEX IF NOT EXISTS PlexContent_Id ON PlexContent (Id); +CREATE TABLE IF NOT EXISTS EmbyEpisodes +( + Id INTEGER PRIMARY KEY AUTOINCREMENT, + EpisodeTitle VARCHAR(100) NOT NULL, + ShowTitle VARCHAR(100) NOT NULL, + EmbyId VARCHAR(100) NOT NULL, + SeasonNumber INTEGER NOT NULL, + EpisodeNumber INTEGER NOT NULL, + ParentId VARCHAR(100) NOT NULL, + ProviderId VARCHAR(100) NOT NULL +); +CREATE UNIQUE INDEX IF NOT EXISTS EmbyEpisodes_Id ON EmbyEpisodes (Id); + +CREATE TABLE IF NOT EXISTS EmbyContent +( + Id INTEGER PRIMARY KEY AUTOINCREMENT, + Title VARCHAR(100) NOT NULL, + PremierDate VARCHAR(100) NOT NULL, + EmbyId VARCHAR(100) NOT NULL, + ProviderId VARCHAR(100) NOT NULL, + Type INTEGER NOT NULL +); +CREATE UNIQUE INDEX IF NOT EXISTS EmbyEpisodes_Id ON EmbyEpisodes (Id); + + COMMIT; \ No newline at end of file diff --git a/Ombi.UI/Modules/Admin/AdminModule.cs b/Ombi.UI/Modules/Admin/AdminModule.cs index 97a610441..effea7815 100644 --- a/Ombi.UI/Modules/Admin/AdminModule.cs +++ b/Ombi.UI/Modules/Admin/AdminModule.cs @@ -97,6 +97,8 @@ namespace Ombi.UI.Modules.Admin private IDiscordApi DiscordApi { get; } private ISettingsService RadarrSettings { get; } private IRadarrApi RadarrApi { get; } + private ISettingsService EmbySettings { get; } + private IEmbyApi EmbyApi { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); public AdminModule(ISettingsService prService, @@ -124,7 +126,8 @@ namespace Ombi.UI.Modules.Admin ISettingsService notifyService, IRecentlyAdded recentlyAdded, ISettingsService watcherSettings , ISettingsService discord, - IDiscordApi discordapi, ISettingsService settings, IRadarrApi radarrApi + IDiscordApi discordapi, ISettingsService settings, IRadarrApi radarrApi, + ISettingsService embySettings, IEmbyApi emby , ISecurityExtensions security) : base("admin", prService, security) { PrService = prService; @@ -160,7 +163,9 @@ namespace Ombi.UI.Modules.Admin DiscordApi = discordapi; RadarrSettings = settings; RadarrApi = radarrApi; - + EmbyApi = emby; + EmbySettings = embySettings; + Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx); Get["/"] = _ => Admin(); @@ -180,6 +185,10 @@ namespace Ombi.UI.Modules.Admin Get["/plex"] = _ => Plex(); Post["/plex", true] = async (x, ct) => await SavePlex(); + Get["/emby", true] = async (x, ct) => await Emby(); + Post["/emby", true] = async (x, ct) => await SaveEmby(); + + Get["/sonarr"] = _ => Sonarr(); Post["/sonarr"] = _ => SaveSonarr(); Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles(); @@ -438,6 +447,13 @@ namespace Ombi.UI.Modules.Admin return Response.AsJson(valid.SendJsonError()); } + var embySettings = await EmbySettings.GetSettingsAsync(); + + if (embySettings.Enable) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Emby is enabled, we cannot enable Plex and Emby" }); + } + if (string.IsNullOrEmpty(plexSettings.MachineIdentifier)) { //Lookup identifier @@ -453,6 +469,41 @@ namespace Ombi.UI.Modules.Admin : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); } + private async Task Emby() + { + var settings = await EmbySettings.GetSettingsAsync(); + + return View["Emby", settings]; + } + + private async Task SaveEmby() + { + var emby = this.Bind(); + var valid = this.Validate(emby); + if (!valid.IsValid) + { + return Response.AsJson(valid.SendJsonError()); + } + + var plexSettings = await PlexService.GetSettingsAsync(); + if (plexSettings.Enable) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Plex is enabled, we cannot enable Plex and Emby" }); + } + + // Get the users + var users = EmbyApi.GetUsers(emby.FullUri, emby.ApiKey); + // Find admin + var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator); + emby.AdministratorId = admin?.Id; + + var result = await EmbySettings.SaveSettingsAsync(emby); + + return Response.AsJson(result + ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Emby!" } + : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); + } + private Negotiator Sonarr() { var settings = SonarrService.GetSettings(); diff --git a/Ombi.UI/Modules/ApplicationTesterModule.cs b/Ombi.UI/Modules/ApplicationTesterModule.cs index a7608f547..5083239a9 100644 --- a/Ombi.UI/Modules/ApplicationTesterModule.cs +++ b/Ombi.UI/Modules/ApplicationTesterModule.cs @@ -46,7 +46,7 @@ namespace Ombi.UI.Modules public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi, ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService pr, ISecurityExtensions security, - IWatcherApi watcherApi, IRadarrApi radarrApi) : base("test", pr, security) + IWatcherApi watcherApi, IRadarrApi radarrApi, IEmbyApi emby) : base("test", pr, security) { this.RequiresAuthentication(); @@ -57,6 +57,7 @@ namespace Ombi.UI.Modules HeadphonesApi = hpApi; WatcherApi = watcherApi; RadarrApi = radarrApi; + Emby = emby; Post["/cp"] = _ => CouchPotatoTest(); Post["/sonarr"] = _ => SonarrTest(); @@ -66,6 +67,7 @@ namespace Ombi.UI.Modules Post["/headphones"] = _ => HeadphonesTest(); Post["/plexdb"] = _ => TestPlexDb(); Post["/watcher"] = _ => WatcherTest(); + Post["/emby"] = _ => EmbyTest(); } private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -76,6 +78,7 @@ namespace Ombi.UI.Modules private IHeadphonesApi HeadphonesApi { get; } private IWatcherApi WatcherApi { get; } private IRadarrApi RadarrApi { get; } + private IEmbyApi Emby { get; set; } private Response CouchPotatoTest() { @@ -213,7 +216,7 @@ namespace Ombi.UI.Modules : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." }); } - catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. + catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. { Log.Warn("Exception thrown when attempting to get Plex's status: "); Log.Warn(e); @@ -225,6 +228,35 @@ namespace Ombi.UI.Modules return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); } } + private Response EmbyTest() + { + var emby = this.Bind(); + var valid = this.Validate(emby); + if (!valid.IsValid) + { + return Response.AsJson(valid.SendJsonError()); + } + + try + { + var status = Emby.GetUsers(emby?.FullUri, emby?.ApiKey); + return status != null + ? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to Emby successfully!" }) + : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Emby, please check your settings." }); + + } + catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. + { + Log.Warn("Exception thrown when attempting to get Emby's users: "); + Log.Warn(e); + var message = $"Could not connect to Emby, please check your settings. Exception Message: {e.Message}"; + if (e.InnerException != null) + { + message = $"Could not connect to Emby, please check your settings. Exception Message: {e.InnerException.Message}"; + } + return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); + } + } private Response SickRageTest() { diff --git a/Ombi.UI/Modules/UserLoginModule.cs b/Ombi.UI/Modules/UserLoginModule.cs index 40fea430f..6ed0fc105 100644 --- a/Ombi.UI/Modules/UserLoginModule.cs +++ b/Ombi.UI/Modules/UserLoginModule.cs @@ -34,6 +34,7 @@ using Nancy; using Nancy.Extensions; using Nancy.Linker; using NLog; +using Ombi.Api; using Ombi.Api.Interfaces; using Ombi.Api.Models.Plex; using Ombi.Core; diff --git a/Ombi.UI/NinjectModules/ApiModule.cs b/Ombi.UI/NinjectModules/ApiModule.cs index 1a45764c7..8ca7c5dbd 100644 --- a/Ombi.UI/NinjectModules/ApiModule.cs +++ b/Ombi.UI/NinjectModules/ApiModule.cs @@ -50,6 +50,7 @@ namespace Ombi.UI.NinjectModules Bind().To(); Bind().To(); Bind().To(); + Bind().To(); } } } \ No newline at end of file diff --git a/Ombi.UI/NinjectModules/ServicesModule.cs b/Ombi.UI/NinjectModules/ServicesModule.cs index edafddb03..31ad2c1d2 100644 --- a/Ombi.UI/NinjectModules/ServicesModule.cs +++ b/Ombi.UI/NinjectModules/ServicesModule.cs @@ -58,6 +58,9 @@ namespace Ombi.UI.NinjectModules Bind().To(); Bind().To(); Bind().To(); + + Bind().To(); + Bind().To(); Bind().To(); diff --git a/Ombi.UI/Ombi.UI.csproj b/Ombi.UI/Ombi.UI.csproj index 24fa57f52..6e7096ba6 100644 --- a/Ombi.UI/Ombi.UI.csproj +++ b/Ombi.UI/Ombi.UI.csproj @@ -295,6 +295,7 @@ + @@ -803,6 +804,9 @@ Always + + Always + web.config diff --git a/Ombi.UI/Startup.cs b/Ombi.UI/Startup.cs index ff8590da4..73ef53250 100644 --- a/Ombi.UI/Startup.cs +++ b/Ombi.UI/Startup.cs @@ -31,6 +31,7 @@ using Ninject; using Ninject.Planning.Bindings.Resolvers; using Ninject.Syntax; using NLog; +using Ombi.Api; using Ombi.Api.Interfaces; using Ombi.Core; using Ombi.Core.Migration; @@ -83,6 +84,7 @@ namespace Ombi.UI var scheduler = new Scheduler(); + // Reset any jobs running var jobSettings = kernel.Get>(); var all = jobSettings.GetAll(); diff --git a/Ombi.UI/Validators/EmbyValidator.cs b/Ombi.UI/Validators/EmbyValidator.cs new file mode 100644 index 000000000..84fed40dd --- /dev/null +++ b/Ombi.UI/Validators/EmbyValidator.cs @@ -0,0 +1,42 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SonarrValidator.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 FluentValidation; +using Ombi.Core.SettingModels; + +namespace Ombi.UI.Validators +{ + public class EmbyValidator : AbstractValidator + { + public EmbyValidator() + { + RuleFor(request => request.Ip).NotNull().WithMessage("You must specify a IP/Host name."); + RuleFor(request => request.Port).NotNull().WithMessage("You must specify a Port."); + RuleFor(request => request.ApiKey).NotNull().WithMessage("You must specify a Api Key."); + } + } +} \ No newline at end of file diff --git a/Ombi.UI/Views/Admin/Emby.cshtml b/Ombi.UI/Views/Admin/Emby.cshtml new file mode 100644 index 000000000..f0b05c979 --- /dev/null +++ b/Ombi.UI/Views/Admin/Emby.cshtml @@ -0,0 +1,146 @@ +@using Ombi.UI.Helpers +@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase +@Html.Partial("Shared/Partial/_Sidebar") +@{ + int port; + if (Model.Port == 0) + { + port = 8096; + } + else + { + port = Model.Port; + } +} +
+
+
+ Emby Settings + + @Html.Checkbox(Model.Enable, "Enable", "Enabled") +
+ +
+ +
+
+ +
+ + +
+ +
+
+
+
+ + @if (Model.Ssl) + { + + } + else + { + + } + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/Ombi.UI/Views/Admin/Plex.cshtml b/Ombi.UI/Views/Admin/Plex.cshtml index 4157d4bfb..50ee63e19 100644 --- a/Ombi.UI/Views/Admin/Plex.cshtml +++ b/Ombi.UI/Views/Admin/Plex.cshtml @@ -17,6 +17,8 @@
Plex Settings @**@ @*TODO*@ + + @Html.Checkbox(Model.Enable, "Enable", "Enable")