diff --git a/.gitignore b/.gitignore index 587f09568..dbf0d54e0 100644 --- a/.gitignore +++ b/.gitignore @@ -246,3 +246,4 @@ _Pvt_Extensions # Ignore local vscode config *.vscode +/src/Ombi/database.json diff --git a/CHANGELOG.md b/CHANGELOG.md index ae8417bae..6febb6683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,77 @@ ### **New Features** +- Update login.component.ts. [Jamie] + +- Update CHANGELOG.md. [Jamie] + +- Updated SlackNotification.cs. [Tim] + +### **Fixes** + +- Fixed the issue where we couldn't always pick up stuff on the sync. [tidusjar] + +- Removed hangfire completly from Ombi. [tidusjar] + +- Fixed the notifications issue. [tidusjar] + +- Fixed the issues where the DB was being disposed too early. [tidusjar] + +- Fixed an error with the newsletter with the new db structure. [tidusjar] + +- Output some useful stuff to the about window regarding the databases. [tidusjar] + +- Fixed the migration for combined databases. [tidusjar] + +- Fixed the issue where exisitng databases would now fail due to the DB structure changes. [tidusjar] + +- Finished it! [tidusjar] + +- Got MySql working. [tidusjar] + +- Got the new DB structure in place. [tidusjar] + +- Fix for #3219. [tidusjar] + +- Fixed the error in the newsletter. [tidusjar] + +- Fixed #3208. [tidusjar] + +- Use tags and autocomplete for excluded keywords. [Taylor Buchanan] + +- Add comments to clarify filter decisions. [Taylor Buchanan] + +- Fix TS import order. [Taylor Buchanan] + +- Add adult movie filtering. [Taylor Buchanan] + +- Fix search bar overlap on mobile. [Taylor Buchanan] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- Add SK lang. [Jamie Rees] + +- Add the migration to the correct database... #3214. [tidusjar] + +- Hopefully provide a fix now for #2998 Theory is that the refresh metadata was using stale data and then overriding the availbility that just happened on that media item. [tidusjar] + + +## v3.0.4817 (2019-10-12) + +### **New Features** + - Added better support for Jellyfin, we will now auto detect if it's a jellyfin server after pressing the discover button. [tidusjar] - Update aspnetcore.yml. [Jamie] @@ -34,6 +105,8 @@ ### **Fixes** +- Gitchangelog. [tidusjar] + - Fixed #3078. [tidusjar] - Fixes issue #3195 The new string extension method ToHttpsUrl ensures that URLs starting with "https" are no longer turned into "httpss" The commit also replaces all occurances of the error prone .Replace("http", "https") in the whole solution. [msdeibel] diff --git a/README.md b/README.md index e8e269e7f..e9415432d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Supported notifications: * Pushover * Mattermost * Telegram +* Webhook ### The difference between Version 3 and 2 diff --git a/src/Ombi.Api.Webhook/IWebhookApi.cs b/src/Ombi.Api.Webhook/IWebhookApi.cs new file mode 100644 index 000000000..6a22a8b02 --- /dev/null +++ b/src/Ombi.Api.Webhook/IWebhookApi.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Ombi.Api.Webhook +{ + public interface IWebhookApi + { + Task PushAsync(string endpoint, string accessToken, IDictionary parameters); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj b/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj new file mode 100644 index 000000000..321c1f333 --- /dev/null +++ b/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + 3.0.0.0 + 3.0.0.0 + + + + + + + + + \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/WebhookApi.cs b/src/Ombi.Api.Webhook/WebhookApi.cs new file mode 100644 index 000000000..8b6b35ca0 --- /dev/null +++ b/src/Ombi.Api.Webhook/WebhookApi.cs @@ -0,0 +1,40 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Ombi.Api.Webhook +{ + public class WebhookApi : IWebhookApi + { + private static readonly CamelCasePropertyNamesContractResolver _nameResolver = new CamelCasePropertyNamesContractResolver(); + + public WebhookApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + + public async Task PushAsync(string baseUrl, string accessToken, IDictionary parameters) + { + var request = new Request("/", baseUrl, HttpMethod.Post); + + if (!string.IsNullOrWhiteSpace(accessToken)) + { + request.AddHeader("Access-Token", accessToken); + } + + var body = parameters.ToDictionary( + x => _nameResolver.GetResolvedPropertyName(x.Key), + x => x.Value + ); + + request.ApplicationJsonContentType(); + request.AddJsonBody(body); + + await _api.Request(request); + } + } +} diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index fd888d0d2..918e189fe 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -93,24 +93,7 @@ namespace Ombi.Api public void AddQueryString(string key, string value) { if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return; - - var builder = new UriBuilder(FullUri); - var startingTag = string.Empty; - var hasQuery = false; - if (string.IsNullOrEmpty(builder.Query)) - { - startingTag = "?"; - } - else - { - hasQuery = true; - startingTag = builder.Query.Contains("?") ? "&" : "?"; - } - builder.Query = hasQuery - ? $"{builder.Query}{startingTag}{key}={value}" - : $"{startingTag}{key}={value}"; - - _modified = builder.Uri; + _modified = FullUri.AddQueryParameter(key, value); } public void AddJsonBody(object obj) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 456ba267a..751cc9ebf 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -188,11 +188,7 @@ namespace Ombi.Core.Engine var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count) .ToListAsync(); - requests.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, requests); return new RequestsViewModel { Collection = requests, @@ -251,26 +247,30 @@ namespace Ombi.Core.Engine allRequests = await MovieRepository.GetWithUser().ToListAsync(); } - allRequests.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, allRequests); + return allRequests; } - private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List movieRequests) { - if (shouldHide.UserId == x.RequestedUserId) - { - x.ShowSubscribe = false; - } - else + var requestIds = movieRequests.Select(x => x.Id); + var sub = await _subscriptionRepository.GetAll().Where(s => + s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) + .ToListAsync(); + foreach (var x in movieRequests) { - x.ShowSubscribe = true; - var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => - s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.Movie); - x.Subscribed = sub != null; + x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id); + x.Subscribed = hasSub != null; + } } } @@ -293,11 +293,8 @@ namespace Ombi.Core.Engine } var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList(); - results.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, results); + return results; } @@ -321,7 +318,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = denyReason; // We are denying a request - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MovieRepository.Update(request); return new RequestEngineResult @@ -349,7 +346,7 @@ namespace Ombi.Core.Engine var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); if (canNotify.Success) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); } if (request.Approved) @@ -465,7 +462,7 @@ namespace Ombi.Core.Engine request.Available = true; request.MarkedAsAvailable = DateTime.Now; - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MovieRepository.Update(request); return new RequestEngineResult @@ -481,8 +478,8 @@ namespace Ombi.Core.Engine var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (result.Success) - { - NotificationHelper.NewRequest(model); + { + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog @@ -493,7 +490,7 @@ namespace Ombi.Core.Engine RequestType = RequestType.Movie, }); - return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id}; + return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id }; } public async Task GetRemainingRequests(OmbiUser user) @@ -533,7 +530,7 @@ namespace Ombi.Core.Engine return new RequestQuotaCountModel() { - HasLimit = true, + HasLimit = true, Limit = limit, Remaining = count, NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index 8457de515..ce69cb0b3 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -314,7 +314,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = reason; // We are denying a request - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MusicRepository.Update(request); return new RequestEngineResult @@ -342,7 +342,7 @@ namespace Ombi.Core.Engine var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); if (canNotify.Success) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); } if (request.Approved) @@ -469,7 +469,7 @@ namespace Ombi.Core.Engine request.Available = true; request.MarkedAsAvailable = DateTime.Now; - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MusicRepository.Update(request); return new RequestEngineResult @@ -486,7 +486,7 @@ namespace Ombi.Core.Engine var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (result.Success) { - NotificationHelper.NewRequest(model); + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 796e2fe6a..74ba55d31 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -156,10 +156,9 @@ namespace Ombi.Core.Engine .ThenInclude(x => x.Episodes) .OrderByDescending(x => x.ChildRequests.Select(y => y.RequestedDate).FirstOrDefault()) .Skip(position).Take(count).ToListAsync(); - - } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + } + await CheckForSubscription(shouldHide, allRequests); return new RequestsViewModel { @@ -194,7 +193,8 @@ namespace Ombi.Core.Engine { return new RequestsViewModel(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + + await CheckForSubscription(shouldHide, allRequests); return new RequestsViewModel { @@ -216,7 +216,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.Get().ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -236,7 +236,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.GetLite().ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -255,7 +255,7 @@ namespace Ombi.Core.Engine request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync(); } - await CheckForSubscription(shouldHide, request); + await CheckForSubscription(shouldHide, new List{request}); return request; } @@ -304,7 +304,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -323,7 +323,7 @@ namespace Ombi.Core.Engine } var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync(); - results.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, results); return results; } @@ -388,7 +388,7 @@ namespace Ombi.Core.Engine if (request.Approved) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); // Autosend await TvSender.Send(request); } @@ -411,7 +411,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = reason; await TvRepository.UpdateChild(request); - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); return new RequestEngineResult { Result = true @@ -420,7 +420,7 @@ namespace Ombi.Core.Engine public async Task UpdateChildRequest(ChildRequests request) { - await TvRepository.UpdateChild(request); + await TvRepository.UpdateChild(request); return request; } @@ -438,14 +438,14 @@ namespace Ombi.Core.Engine // Delete the parent TvRepository.Db.TvRequests.Remove(parent); } - + await TvRepository.Db.SaveChangesAsync(); } public async Task RemoveTvRequest(int requestId) { var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId); - await TvRepository.Delete(request); + await TvRepository.Delete(request); } public async Task UserHasRequest(string userId) @@ -499,7 +499,7 @@ namespace Ombi.Core.Engine } } await TvRepository.UpdateChild(request); - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); return new RequestEngineResult { Result = true, @@ -520,26 +520,32 @@ namespace Ombi.Core.Engine } } - private async Task CheckForSubscription(HideResult shouldHide, TvRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List x) { - foreach (var tv in x.ChildRequests) + foreach (var tvRequest in x) { - await CheckForSubscription(shouldHide, tv); + await CheckForSubscription(shouldHide, tvRequest.ChildRequests); } } - private async Task CheckForSubscription(HideResult shouldHide, ChildRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List childRequests) { - if (shouldHide.UserId == x.RequestedUserId) + var sub = _subscriptionRepository.GetAll(); + var childIds = childRequests.Select(x => x.Id); + var relevantSubs = await sub.Where(s => + s.UserId == shouldHide.UserId && childIds.Contains(s.Id) && s.RequestType == RequestType.TvShow).ToListAsync(); + foreach (var x in childRequests) { - x.ShowSubscribe = false; - } - else - { - x.ShowSubscribe = true; - var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => - s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.TvShow); - x.Subscribed = sub != null; + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var result = relevantSubs.FirstOrDefault(s => s.RequestId == x.Id); + x.Subscribed = result != null; + } } } @@ -560,7 +566,7 @@ namespace Ombi.Core.Engine return await AfterRequest(model.ChildRequests.FirstOrDefault()); } - private static List SortEpisodes(List items) + private static List SortEpisodes(List items) { foreach (var value in items) { @@ -578,7 +584,7 @@ namespace Ombi.Core.Engine var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (sendRuleResult.Success) { - NotificationHelper.NewRequest(model); + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog @@ -593,11 +599,11 @@ namespace Ombi.Core.Engine if (model.Approved) { // Autosend - NotificationHelper.Notify(model, NotificationType.RequestApproved); + await NotificationHelper.Notify(model, NotificationType.RequestApproved); var result = await TvSender.Send(model); if (result.Success) { - return new RequestEngineResult { Result = true, RequestId = model.Id}; + return new RequestEngineResult { Result = true, RequestId = model.Id }; } return new RequestEngineResult { @@ -650,10 +656,10 @@ namespace Ombi.Core.Engine DateTime oldestRequestedAt = await log.OrderBy(x => x.RequestDate) .Select(x => x.RequestDate) .FirstOrDefaultAsync(); - + return new RequestQuotaCountModel() { - HasLimit = true, + HasLimit = true, Limit = limit, Remaining = count, NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), diff --git a/src/Ombi.Core/Helpers/NotificationHelper.cs b/src/Ombi.Core/Helpers/NotificationHelper.cs index 1615b24f7..f94e8f0db 100644 --- a/src/Ombi.Core/Helpers/NotificationHelper.cs +++ b/src/Ombi.Core/Helpers/NotificationHelper.cs @@ -1,5 +1,6 @@ using System; -using Hangfire; +using System.Collections.Generic; +using System.Threading.Tasks; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -9,13 +10,7 @@ namespace Ombi.Core { public class NotificationHelper : INotificationHelper { - public NotificationHelper(INotificationService service) - { - NotificationService = service; - } - private INotificationService NotificationService { get; } - - public void NewRequest(FullBaseRequest model) + public async Task NewRequest(FullBaseRequest model) { var notificationModel = new NotificationOptions { @@ -24,11 +19,13 @@ namespace Ombi.Core NotificationType = NotificationType.NewRequest, RequestType = model.RequestType }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); - + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void NewRequest(ChildRequests model) + public async Task NewRequest(ChildRequests model) { var notificationModel = new NotificationOptions { @@ -36,11 +33,14 @@ namespace Ombi.Core DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest, RequestType = model.RequestType - }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + }; + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void NewRequest(AlbumRequest model) + public async Task NewRequest(AlbumRequest model) { var notificationModel = new NotificationOptions { @@ -48,12 +48,15 @@ namespace Ombi.Core DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest, RequestType = model.RequestType - }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + }; + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(MovieRequests model, NotificationType type) + public async Task Notify(MovieRequests model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -63,10 +66,13 @@ namespace Ombi.Core RequestType = model.RequestType, Recipient = model.RequestedUser?.Email ?? string.Empty }; - - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(ChildRequests model, NotificationType type) + public async Task Notify(ChildRequests model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -76,10 +82,13 @@ namespace Ombi.Core RequestType = model.RequestType, Recipient = model.RequestedUser?.Email ?? string.Empty }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(AlbumRequest model, NotificationType type) + public async Task Notify(AlbumRequest model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -90,7 +99,18 @@ namespace Ombi.Core Recipient = model.RequestedUser?.Email ?? string.Empty }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); + } + + public async Task Notify(NotificationOptions model) + { + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, model} + }); } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs b/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs new file mode 100644 index 000000000..533de1d6b --- /dev/null +++ b/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs @@ -0,0 +1,15 @@ + +using System.Collections.Generic; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + /// + /// The view model for the notification settings page + /// + /// + public class WebhookNotificationViewModel : WebhookSettings + { + } +} diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 790aa8500..8ffbd514a 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -11,7 +11,6 @@ - diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index b54c8b4fb..213aa94c8 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; -using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; namespace Ombi.Core.Rule.Rules.Request diff --git a/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs index 625407f3c..e734fe4a6 100644 --- a/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs @@ -7,12 +7,12 @@ namespace Ombi.Core.Rule.Rules.Request { public class SonarrCacheRequestRule : BaseRequestRule, IRules { - public SonarrCacheRequestRule(IExternalContext ctx) + public SonarrCacheRequestRule(ExternalContext ctx) { _ctx = ctx; } - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public Task Execute(BaseRequest obj) { diff --git a/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs b/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs index 03bdbe091..24f2712d7 100644 --- a/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs @@ -34,12 +34,12 @@ namespace Ombi.Core.Rule.Rules.Search { public class SonarrCacheSearchRule : BaseSearchRule, IRules { - public SonarrCacheSearchRule(IExternalContext ctx) + public SonarrCacheSearchRule(ExternalContext ctx) { _ctx = ctx; } - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public Task Execute(SearchViewModel obj) { diff --git a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs index 7eac05d56..ca7ccb6ce 100644 --- a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs @@ -10,12 +10,12 @@ namespace Ombi.Core.Rule.Rules { public class SonarrCacheRule { - public SonarrCacheRule(IExternalContext ctx) + public SonarrCacheRule(ExternalContext ctx) { _ctx = ctx; } - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public async Task Execute(BaseRequest obj) { diff --git a/src/Ombi.Core/Senders/INotificationHelper.cs b/src/Ombi.Core/Senders/INotificationHelper.cs index 4ba47d761..70947a57e 100644 --- a/src/Ombi.Core/Senders/INotificationHelper.cs +++ b/src/Ombi.Core/Senders/INotificationHelper.cs @@ -1,16 +1,19 @@ -using Ombi.Core.Models.Requests; +using System.Threading.Tasks; +using Ombi.Core.Models.Requests; using Ombi.Helpers; +using Ombi.Notifications.Models; using Ombi.Store.Entities.Requests; namespace Ombi.Core { public interface INotificationHelper { - void NewRequest(FullBaseRequest model); - void NewRequest(ChildRequests model); - void NewRequest(AlbumRequest model); - void Notify(MovieRequests model, NotificationType type); - void Notify(ChildRequests model, NotificationType type); - void Notify(AlbumRequest model, NotificationType type); + Task NewRequest(FullBaseRequest model); + Task NewRequest(ChildRequests model); + Task NewRequest(AlbumRequest model); + Task Notify(MovieRequests model, NotificationType type); + Task Notify(ChildRequests model, NotificationType type); + Task Notify(AlbumRequest model, NotificationType type); + Task Notify(NotificationOptions model); } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 567df43b5..c9aa5e4f2 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -95,7 +95,7 @@ namespace Ombi.Core.Senders Type = RequestType.Movie, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 04544c6be..e4bf27855 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -65,7 +65,7 @@ namespace Ombi.Core.Senders Type = RequestType.Album, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 3a3e34745..5cf28fa8a 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -128,7 +128,7 @@ namespace Ombi.Core.Senders Type = RequestType.TvShow, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3d54e5a67..f50417189 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -1,6 +1,5 @@ using System.Diagnostics.CodeAnalysis; using System.Security.Principal; -using Hangfire; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; @@ -33,6 +32,7 @@ using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; using Ombi.Api.Gotify; +using Ombi.Api.Webhook; using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; @@ -123,6 +123,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -135,13 +136,13 @@ namespace Ombi.DependencyInjection } public static void RegisterStore(this IServiceCollection services) { - services.AddDbContext(); - services.AddDbContext(); - services.AddDbContext(); + //services.AddDbContext(); + //services.AddDbContext(); + //services.AddDbContext(); - services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 - services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 - services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 + //services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 + //services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 + //services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -174,6 +175,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -181,8 +183,8 @@ namespace Ombi.DependencyInjection public static void RegisterJobs(this IServiceCollection services) { - services.AddSingleton(provider => new IoCJobFactory(provider)); - services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index ec905e718..0d3f8652b 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -35,6 +35,7 @@ + diff --git a/src/Ombi.Helpers.Tests/PlexHelperTests.cs b/src/Ombi.Helpers.Tests/PlexHelperTests.cs index 8ecb3fa0a..ef1119f9f 100644 --- a/src/Ombi.Helpers.Tests/PlexHelperTests.cs +++ b/src/Ombi.Helpers.Tests/PlexHelperTests.cs @@ -39,6 +39,8 @@ namespace Ombi.Helpers.Tests yield return new TestCaseData("com.plexapp.agents.agent47://tt2543456?lang=en", ProviderIdType.Imdb).Returns("tt2543456").SetName("Unknown IMDB agent"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/1/1?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/999/999?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent, large episode and season"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021/2/1?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv episode"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv show"); } } diff --git a/src/Ombi.Schedule/JobDataKeys.cs b/src/Ombi.Helpers/JobDataKeys.cs similarity index 52% rename from src/Ombi.Schedule/JobDataKeys.cs rename to src/Ombi.Helpers/JobDataKeys.cs index 46d2dee2a..e0e2f7451 100644 --- a/src/Ombi.Schedule/JobDataKeys.cs +++ b/src/Ombi.Helpers/JobDataKeys.cs @@ -1,7 +1,8 @@ -namespace Ombi.Schedule +namespace Ombi.Helpers { public class JobDataKeys { public const string RecentlyAddedSearch = "recentlyAddedSearch"; + public const string NotificationOptions = nameof(NotificationOptions); } } \ No newline at end of file diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index 0723800ab..bfa452c13 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -33,6 +33,7 @@ namespace Ombi.Helpers public static EventId PushoverNotification => new EventId(4005); public static EventId TelegramNotifcation => new EventId(4006); public static EventId GotifyNotification => new EventId(4007); + public static EventId WebhookNotification => new EventId(4008); public static EventId TvSender => new EventId(5000); public static EventId SonarrSender => new EventId(5001); diff --git a/src/Ombi.Helpers/NotificationAgent.cs b/src/Ombi.Helpers/NotificationAgent.cs index 18f28105a..7544d033d 100644 --- a/src/Ombi.Helpers/NotificationAgent.cs +++ b/src/Ombi.Helpers/NotificationAgent.cs @@ -11,5 +11,6 @@ Mattermost = 6, Mobile = 7, Gotify = 8, + Webhook = 9, } } \ No newline at end of file diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index 5dedaff61..8af8b9861 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Ombi.Schedule/OmbiQuartz.cs b/src/Ombi.Helpers/OmbiQuartz.cs similarity index 90% rename from src/Ombi.Schedule/OmbiQuartz.cs rename to src/Ombi.Helpers/OmbiQuartz.cs index 715bb187b..7979bc2a7 100644 --- a/src/Ombi.Schedule/OmbiQuartz.cs +++ b/src/Ombi.Helpers/OmbiQuartz.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Ombi.Helpers; using Quartz; using Quartz.Impl; using Quartz.Spi; -namespace Ombi.Schedule +namespace Ombi.Helpers { public class OmbiQuartz { @@ -78,7 +77,12 @@ namespace Ombi.Schedule { await Scheduler.TriggerJob(new JobKey(jobName, group)); } - + + public static async Task TriggerJob(string jobName, string group, IDictionary data) + { + await Scheduler.TriggerJob(new JobKey(jobName, group), new JobDataMap(data)); + } + public static async Task Start() { await Scheduler.Start(); diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index de61b8740..a25c3b14a 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -33,14 +33,15 @@ namespace Ombi.Helpers { public class PlexHelper { - private const string ImdbMatchExpression = "tt([0-9]{1,10})"; - private const string TvDbIdMatchExpression = "//[0-9]+/([0-9]{1,3})/([0-9]{1,3})"; + private const string ImdbMatchExpression = "tt([0-9]{1,10})"; + private const string TvDbIdMatchExpression = "//[0-9]+/?([0-9]{1,3})/?([0-9]{1,3})"; public static ProviderId GetProviderIdFromPlexGuid(string guid) { //com.plexapp.agents.thetvdb://269586/2/8?lang=en //com.plexapp.agents.themoviedb://390043?lang=en //com.plexapp.agents.imdb://tt2543164?lang=en + // https://github.com/tidusjar/Ombi/issues/3277 if (string.IsNullOrEmpty(guid)) { return new ProviderId(); @@ -55,7 +56,7 @@ namespace Ombi.Helpers { TheTvDb = guidSplit[1] }; - } else + } if (guid.Contains("themoviedb", CompareOptions.IgnoreCase)) { return new ProviderId @@ -63,7 +64,6 @@ namespace Ombi.Helpers TheMovieDb = guidSplit[1] }; } - else if (guid.Contains("imdb", CompareOptions.IgnoreCase)) { return new ProviderId @@ -71,72 +71,29 @@ namespace Ombi.Helpers ImdbId = guidSplit[1] }; } - else + + var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled); + var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled); + var imdbMatch = imdbRegex.IsMatch(guid); + if (imdbMatch) { - var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled); - var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled); - var imdbMatch = imdbRegex.IsMatch(guid); - if (imdbMatch) - { - return new ProviderId - { - ImdbId = guidSplit[1] - }; - } - else + return new ProviderId { - // Check if it matches the TvDb pattern - var tvdbMatch = tvdbRegex.IsMatch(guid); - if (tvdbMatch) - { - return new ProviderId - { - TheTvDb = guidSplit[1] - }; - } - } + ImdbId = guidSplit[1] + }; } - } - return new ProviderId(); - } - public static EpisodeModelHelper GetSeasonsAndEpisodesFromPlexGuid(string guid) - { - var ep = new EpisodeModelHelper(); - //com.plexapp.agents.thetvdb://269586/2/8?lang=en - //com.plexapp.agents.themoviedb://390043?lang=en - //com.plexapp.agents.imdb://tt2543164?lang=en - if (string.IsNullOrEmpty(guid)) - return null; - try - { - var guidSplit = guid.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries); - if (guidSplit.Length > 2) + // Check if it matches the TvDb pattern + var tvdbMatch = tvdbRegex.IsMatch(guid); + if (tvdbMatch) { - if (guid.Contains("thetvdb", CompareOptions.IgnoreCase)) - { - ep.ProviderId = new ProviderId {TheTvDb = guidSplit[1]}; - } - if (guid.Contains("themoviedb", CompareOptions.IgnoreCase)) - { - ep.ProviderId = new ProviderId { TheMovieDb = guidSplit[1] }; - - } - if (guid.Contains("imdb", CompareOptions.IgnoreCase)) + return new ProviderId { - ep.ProviderId = new ProviderId { ImdbId = guidSplit[1] }; - - } - ep.SeasonNumber = int.Parse(guidSplit[2]); - ep.EpisodeNumber = int.Parse(guidSplit[3]); + TheTvDb = guidSplit[1] + }; } - return ep; - - } - catch (Exception) - { - return ep; } + return new ProviderId(); } public static string GetPlexMediaUrl(string machineId, int mediaId) @@ -147,13 +104,6 @@ namespace Ombi.Helpers } } - public class EpisodeModelHelper - { - public ProviderId ProviderId { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } - } - public class ProviderId { public string TheTvDb { get; set; } diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs index f460ce78b..3562b8ac2 100644 --- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs +++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs @@ -20,6 +20,7 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs new file mode 100644 index 000000000..303229878 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface IWebhookNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/WebhookNotification.cs b/src/Ombi.Notifications/Agents/WebhookNotification.cs new file mode 100644 index 000000000..2339b6abf --- /dev/null +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -0,0 +1,123 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Webhook; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class WebhookNotification : BaseNotification, IWebhookNotification + { + public WebhookNotification(IWebhookApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "WebhookNotification"; + + private IWebhookApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(WebhookSettings settings) + { + return settings.Enabled && !string.IsNullOrEmpty(settings.WebhookUrl); + } + + protected override async Task NewRequest(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + + protected override async Task NewIssue(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, WebhookSettings settings) + { + try + { + await Api.PushAsync(settings.WebhookUrl, settings.ApplicationToken, model.Data); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.WebhookNotification, e, "Failed to send webhook notification"); + } + } + + protected override async Task Test(NotificationOptions model, WebhookSettings settings) + { + var c = new NotificationMessageCurlys(); + + var testData = c.Curlys.ToDictionary(x => x.Key, x => x.Value); + testData[nameof(NotificationType)] = NotificationType.Test.ToString(); + var notification = new NotificationMessage + { + Data = testData, + }; + + await Send(notification, settings); + } + + private async Task Run(NotificationOptions model, WebhookSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Webhook, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Webhook}"); + return; + } + + var notificationData = parsed.Data.ToDictionary(x => x.Key, x => x.Value); + notificationData[nameof(NotificationType)] = type.ToString(); + var notification = new NotificationMessage + { + Data = notificationData, + }; + + await Send(notification, settings); + } + } +} diff --git a/src/Ombi.Notifications/Interfaces/INotificationService.cs b/src/Ombi.Notifications/Interfaces/INotificationService.cs index f8731b4af..f6a3761c3 100644 --- a/src/Ombi.Notifications/Interfaces/INotificationService.cs +++ b/src/Ombi.Notifications/Interfaces/INotificationService.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using Ombi.Notifications; using Ombi.Notifications.Models; +using Quartz; namespace Ombi.Core.Notifications { - public interface INotificationService + public interface INotificationService : IJob { - Task Publish(NotificationOptions model); - Task Publish(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings); - Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type); + } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Models/NotificationMessage.cs b/src/Ombi.Notifications/Models/NotificationMessage.cs index f14604d3f..7ffd48e63 100644 --- a/src/Ombi.Notifications/Models/NotificationMessage.cs +++ b/src/Ombi.Notifications/Models/NotificationMessage.cs @@ -9,5 +9,6 @@ namespace Ombi.Notifications.Models public string To { get; set; } public Dictionary Other { get; set; } = new Dictionary(); + public IDictionary Data { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageContent.cs b/src/Ombi.Notifications/NotificationMessageContent.cs index 37f7504e9..901b3bcb2 100644 --- a/src/Ombi.Notifications/NotificationMessageContent.cs +++ b/src/Ombi.Notifications/NotificationMessageContent.cs @@ -1,4 +1,6 @@ -namespace Ombi.Notifications +using System.Collections.Generic; + +namespace Ombi.Notifications { public class NotificationMessageContent { @@ -6,5 +8,6 @@ public string Subject { get; set; } public string Message { get; set; } public string Image { get; set; } + public IReadOnlyDictionary Data { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageResolver.cs b/src/Ombi.Notifications/NotificationMessageResolver.cs index 451ef1b55..fe6102eda 100644 --- a/src/Ombi.Notifications/NotificationMessageResolver.cs +++ b/src/Ombi.Notifications/NotificationMessageResolver.cs @@ -47,7 +47,7 @@ namespace Ombi.Notifications body = ReplaceFields(bodyFields, parameters, body); subject = ReplaceFields(subjectFields, parameters, subject); - return new NotificationMessageContent { Message = body ?? string.Empty, Subject = subject ?? string.Empty}; + return new NotificationMessageContent { Message = body ?? string.Empty, Subject = subject ?? string.Empty, Data = parameters }; } public IEnumerable ProcessConditions(IEnumerable conditionalFields, IReadOnlyDictionary parameters) diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index c2985a21b..8a24382aa 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -7,78 +7,46 @@ using Microsoft.Extensions.Logging; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; +using Quartz; namespace Ombi.Notifications { public class NotificationService : INotificationService { + private readonly IServiceProvider _provider; + public NotificationService(IServiceProvider provider, ILogger log) { + _provider = provider; Log = log; NotificationAgents = new List(); - - var baseSearchType = typeof(BaseNotification<>).Name; - - var ass = typeof(NotificationService).GetTypeInfo().Assembly; - - foreach (var ti in ass.DefinedTypes) - { - if (ti?.BaseType?.Name == baseSearchType) - { - var type = ti?.AsType(); - var ctors = type.GetConstructors(); - var ctor = ctors.FirstOrDefault(); - - var services = new List(); - foreach (var param in ctor.GetParameters()) - { - services.Add(provider.GetService(param.ParameterType)); - } - - var item = Activator.CreateInstance(type, services.ToArray()); - NotificationAgents.Add((INotification)item); - } - } + PopulateAgents(); } - + private List NotificationAgents { get; } private ILogger Log { get; } - /// ^ + /// /// Sends a notification to the user. This one is used in normal notification scenarios /// - /// The model. + /// The model. /// - public async Task Publish(NotificationOptions model) + public async Task Execute(IJobExecutionContext context) { - var notificationTasks = new List(); - + JobDataMap dataMap = context.MergedJobDataMap; + var model = (NotificationOptions)dataMap.Get(JobDataKeys.NotificationOptions); + foreach (var agent in NotificationAgents) { - notificationTasks.Add(NotifyAsync(agent,model)); + await NotifyAsync(agent, model); } - await Task.WhenAll(notificationTasks).ConfigureAwait(false); } - /// - /// Sends a notification to the user, this is usually for testing the settings. - /// - /// The model. - /// The settings. - /// - public async Task Publish(NotificationOptions model, Settings.Settings.Models.Settings settings) - { - var notificationTasks = NotificationAgents.Select(notification => NotifyAsync(notification, model, settings)); - - await Task.WhenAll(notificationTasks).ConfigureAwait(false); - } - - private async Task NotifyAsync(INotification notification, NotificationOptions model) { try { - await notification.NotifyAsync(model).ConfigureAwait(false); + await notification.NotifyAsync(model); } catch (Exception ex) { @@ -86,26 +54,31 @@ namespace Ombi.Notifications } } - - private async Task NotifyAsync(INotification notification, NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings) + + private void PopulateAgents() { - if (model.RequestId == 0) - { - throw new ArgumentException("RequestId is not set"); - } - try - { - await notification.NotifyAsync(model, settings).ConfigureAwait(false); - } - catch (Exception ex) + var baseSearchType = typeof(BaseNotification<>).Name; + + var ass = typeof(NotificationService).GetTypeInfo().Assembly; + + foreach (var ti in ass.DefinedTypes) { - throw new InvalidOperationException(ex.Message); - } - } + if (ti?.BaseType?.Name == baseSearchType) + { + var type = ti?.AsType(); + var ctors = type.GetConstructors(); + var ctor = ctors.FirstOrDefault(); - public async Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type) - { - await type.NotifyAsync(model, settings); + var services = new List(); + foreach (var param in ctor.GetParameters()) + { + services.Add(_provider.GetService(param.ParameterType)); + } + + var item = Activator.CreateInstance(type, services.ToArray()); + NotificationAgents.Add((INotification)item); + } + } } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 3fa4b4830..5d63fbc1a 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs index 6d00f8ef6..b5d94c15f 100644 --- a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs +++ b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Quartz; using System.Threading; using System.Threading.Tasks; +using Ombi.Helpers; namespace Ombi.Schedule.Tests { @@ -12,7 +13,7 @@ namespace Ombi.Schedule.Tests [Test] [Ignore("Cannot get this to work")] - public async Task Test() + public Task Test() { var scheduleMock = new Mock(); scheduleMock.Setup(x => x.TriggerJob(It.IsAny(), @@ -23,6 +24,8 @@ namespace Ombi.Schedule.Tests scheduleMock.Verify(x => x.TriggerJob(It.Is(j => j.Name == "ABC"), default(CancellationToken)), Times.Once); + + return Task.CompletedTask; } } public class QuartzMock : OmbiQuartz diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index 028c044b7..b91ab59f6 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Castle.Components.DictionaryAdapter; -using Hangfire; using Moq; using NUnit.Framework; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Schedule.Jobs.Plex; using Ombi.Store.Entities; @@ -25,15 +25,15 @@ namespace Ombi.Schedule.Tests _repo = new Mock(); _tv = new Mock(); _movie = new Mock(); - _notify = new Mock(); - Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, new Mock().Object, null); + _notify = new Mock(); + Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null); } private Mock _repo; private Mock _tv; private Mock _movie; - private Mock _notify; + private Mock _notify; private PlexAvailabilityChecker Checker; [Test] diff --git a/src/Ombi.Schedule/IoCJobActivator.cs b/src/Ombi.Schedule/IoCJobActivator.cs deleted file mode 100644 index 787ef8b6d..000000000 --- a/src/Ombi.Schedule/IoCJobActivator.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Hangfire; -using Microsoft.Extensions.DependencyInjection; - -namespace Ombi.Schedule -{ - public class IoCJobActivator : JobActivator - { - private readonly IServiceProvider _container; - public IoCJobActivator(IServiceProvider container) - { - _container = container; - } - - public override object ActivateJob(Type type) - { - var scopeFactory = _container.GetService(); - var scope = scopeFactory.CreateScope(); - var scopedContainer = scope.ServiceProvider; - - var interfaceType = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault(); - var implementation = scopedContainer.GetRequiredService(interfaceType); - return implementation; - } - } -} \ No newline at end of file diff --git a/src/Ombi.Schedule/IocJobFactory.cs b/src/Ombi.Schedule/IocJobFactory.cs index 795c1fec5..abb458e39 100644 --- a/src/Ombi.Schedule/IocJobFactory.cs +++ b/src/Ombi.Schedule/IocJobFactory.cs @@ -7,26 +7,18 @@ namespace Ombi.Schedule { public class IoCJobFactory : IJobFactory { - private readonly IServiceProvider _factory; - - public IoCJobFactory(IServiceProvider factory) + private readonly IServiceProvider _serviceProvider; + public IoCJobFactory(IServiceProvider serviceProvider) { - _factory = factory; + _serviceProvider = serviceProvider; } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { - var scopeFactory = _factory.GetService(); - var scope = scopeFactory.CreateScope(); - var scopedContainer = scope.ServiceProvider; - - var implementation = scopedContainer.GetRequiredService(bundle.JobDetail.JobType) as IJob; - return implementation; + return _serviceProvider.GetRequiredService(); } public void ReturnJob(IJob job) { - var disposable = job as IDisposable; - disposable?.Dispose(); } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs index 5c3cf342a..f85563670 100644 --- a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs +++ b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs @@ -43,7 +43,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato public class CouchPotatoSync : ICouchPotatoSync { public CouchPotatoSync(ISettingsService cpSettings, - ICouchPotatoApi api, ILogger log, IExternalContext ctx) + ICouchPotatoApi api, ILogger log, ExternalContext ctx) { _settings = cpSettings; _api = api; @@ -55,7 +55,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato private readonly ISettingsService _settings; private readonly ICouchPotatoApi _api; private readonly ILogger _log; - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public async Task Execute(IJobExecutionContext job) { diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 9c92bc509..baeb3c5c5 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -28,10 +28,9 @@ using System; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Core.Notifications; +using Ombi.Core; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Ombi; @@ -45,7 +44,7 @@ namespace Ombi.Schedule.Jobs.Emby public class EmbyAvaliabilityChecker : IEmbyAvaliabilityChecker { public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m, - INotificationService n, ILogger log) + INotificationHelper n, ILogger log) { _repo = repo; _tvRepo = t; @@ -57,7 +56,7 @@ namespace Ombi.Schedule.Jobs.Emby private readonly ITvRequestRepository _tvRepo; private readonly IMovieRequestRepository _movieRepo; private readonly IEmbyContentRepository _repo; - private readonly INotificationService _notificationService; + private readonly INotificationHelper _notificationService; private readonly ILogger _log; public async Task Execute(IJobExecutionContext job) @@ -100,14 +99,14 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); - BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = movie.Id, RequestType = RequestType.Movie, Recipient = recipient, - })); + }); } } await _movieRepo.Save(); @@ -191,14 +190,14 @@ namespace Ombi.Schedule.Jobs.Emby // We have fulfulled this request! child.Available = true; child.MarkedAsAvailable = DateTime.Now; - BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = child.Id, RequestType = RequestType.TvShow, Recipient = child.RequestedUser.Email - })); + }); } } @@ -213,7 +212,6 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { - _movieRepo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 362840203..34e697726 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -2,18 +2,15 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Api.Emby.Models.Movie; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; -using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using Serilog; using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType; namespace Ombi.Schedule.Jobs.Emby @@ -206,7 +203,6 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { _settings?.Dispose(); - _repo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 69ebdc42c..1f67db4bc 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -29,11 +29,11 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; @@ -156,7 +156,6 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { _settings?.Dispose(); - _repo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 0d48efbc0..f094d3f90 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; @@ -17,22 +16,20 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAlbumSync : ILidarrAlbumSync { - public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, - IBackgroundJobClient job, ILidarrAvailabilityChecker availability) + public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, + ILidarrAvailabilityChecker availability) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; - _job = job; _availability = availability; } private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IExternalContext _ctx; - private readonly IBackgroundJobClient _job; + private readonly ExternalContext _ctx; private readonly ILidarrAvailabilityChecker _availability; public async Task CacheContent() @@ -87,7 +84,7 @@ namespace Ombi.Schedule.Jobs.Lidarr _logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Lidarr Album"); } - _job.Enqueue(() => _availability.Start()); + await _availability.Start(); } } catch (Exception) diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs index 1602f28b5..61200d0e4 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; @@ -18,22 +17,20 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrArtistSync : ILidarrArtistSync { - public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, - IBackgroundJobClient background, ILidarrAlbumSync album) + public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, + ILidarrAlbumSync album) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; - _job = background; _albumSync = album; } private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IExternalContext _ctx; - private readonly IBackgroundJobClient _job; + private readonly ExternalContext _ctx; private readonly ILidarrAlbumSync _albumSync; public async Task Execute(IJobExecutionContext job) @@ -84,7 +81,7 @@ namespace Ombi.Schedule.Jobs.Lidarr _logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Lidarr"); } - _job.Enqueue(() => _albumSync.CacheContent()); + await _albumSync.CacheContent(); } } catch (Exception) diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index 340164bd5..37abd68a2 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Core.Notifications; +using Ombi.Core; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Store.Entities; @@ -17,21 +16,18 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker { - public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, - IBackgroundJobClient job, INotificationService notification) + public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, INotificationHelper notification) { _cachedAlbums = albums; _requestRepository = requests; _logger = log; - _job = job; _notificationService = notification; } private readonly IMusicRequestRepository _requestRepository; private readonly IRepository _cachedAlbums; private readonly ILogger _logger; - private readonly IBackgroundJobClient _job; - private readonly INotificationService _notificationService; + private readonly INotificationHelper _notificationService; public async Task Start() { @@ -59,14 +55,15 @@ namespace Ombi.Schedule.Jobs.Lidarr _logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient); - _job.Enqueue(() => _notificationService.Publish(new NotificationOptions + + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = albumRequest.Id, RequestType = RequestType.Album, Recipient = recipient, - })); + }); } } } diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs index 484700c85..85765b6c6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using Hangfire.Server; namespace Ombi.Schedule.Jobs.Ombi { diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs index 6a16aad70..e7b7f2633 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs @@ -49,7 +49,6 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _issuesRepository?.Dispose(); _settings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs index cf8cbd831..6915b025d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -1,8 +1,6 @@ using System; using System.Threading.Tasks; -using Hangfire; using Microsoft.Extensions.Logging; -using Ombi.Api.Plex; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -99,7 +97,6 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plexRepo?.Dispose(); _settings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 710c39595..32254f09a 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -37,7 +37,7 @@ namespace Ombi.Schedule.Jobs.Ombi IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, UserManager um, ISettingsService newsletter, ILogger log, - ILidarrApi lidarrApi, IRepository albumCache, ISettingsService lidarrSettings, + ILidarrApi lidarrApi, IExternalRepository albumCache, ISettingsService lidarrSettings, ISettingsService ombiSettings, ISettingsService plexSettings, ISettingsService embySettings) { _plex = plex; @@ -78,7 +78,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly UserManager _userManager; private readonly ILogger _log; private readonly ILidarrApi _lidarrApi; - private readonly IRepository _lidarrAlbumRepository; + private readonly IExternalRepository _lidarrAlbumRepository; private readonly ISettingsService _lidarrSettings; private readonly ISettingsService _plexSettings; private readonly ISettingsService _embySettings; @@ -200,7 +200,7 @@ namespace Ombi.Schedule.Jobs.Ombi continue; } // BCC the messages - message.Bcc.Add(new MailboxAddress(user.Email, user.Email)); + message.Bcc.Add(new MailboxAddress(user.Email.Trim(), user.Email.Trim())); } // Send the email @@ -714,7 +714,8 @@ namespace Ombi.Schedule.Jobs.Ombi (key, g) => new { SeasonNumber = key, - Episodes = g.ToList() + Episodes = g.ToList(), + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } ); @@ -724,7 +725,8 @@ namespace Ombi.Schedule.Jobs.Ombi { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); + var episodeAirDate = epInformation.EpisodeAirDate; + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); finalsb.Append("
"); } @@ -837,7 +839,8 @@ namespace Ombi.Schedule.Jobs.Ombi (key, g) => new { SeasonNumber = key, - Episodes = g.ToList() + Episodes = g.ToList(), + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } ); @@ -847,7 +850,8 @@ namespace Ombi.Schedule.Jobs.Ombi { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); + var episodeAirDate = epInformation.EpisodeAirDate; + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); finalsb.Append("
"); } @@ -927,12 +931,9 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plex?.Dispose(); - _emby?.Dispose(); _newsletterSettings?.Dispose(); _customizationSettings?.Dispose(); _emailSettings.Dispose(); - _recentlyAddedLog.Dispose(); _templateRepo?.Dispose(); _userManager?.Dispose(); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs index 82187ed50..a6a7c5c76 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs @@ -9,8 +9,6 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; -using Hangfire; -using Hangfire.Server; using Microsoft.Extensions.Logging; using Ombi.Core.Processor; using Ombi.Core.Settings; diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 0ccb736dc..3cc16952f 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Api.TheMovieDb; @@ -11,8 +9,6 @@ using Ombi.Api.TvMaze; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; -using Ombi.Schedule.Jobs.Emby; -using Ombi.Schedule.Jobs.Plex; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; @@ -352,8 +348,6 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plexRepo?.Dispose(); - _embyRepo?.Dispose(); _plexSettings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 6b556bc0e..a1bd29443 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Core.Notifications; +using Ombi.Core; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Plex.Models; @@ -20,21 +18,19 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationService notification, IBackgroundJobClient background, ILogger log) + INotificationHelper notification, ILogger log) { _tvRepo = tvRequest; _repo = repo; _movieRepo = movies; _notificationService = notification; - _backgroundJobClient = background; _log = log; } private readonly ITvRequestRepository _tvRepo; private readonly IMovieRequestRepository _movieRepo; private readonly IPlexContentRepository _repo; - private readonly INotificationService _notificationService; - private readonly IBackgroundJobClient _backgroundJobClient; + private readonly INotificationHelper _notificationService; private readonly ILogger _log; public async Task Execute(IJobExecutionContext job) @@ -215,8 +211,6 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - _movieRepo?.Dispose(); - _repo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index a8d77a71b..d4cd7c040 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Plex; @@ -108,9 +107,8 @@ namespace Ombi.Schedule.Jobs.Plex if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) { - Logger.LogInformation("Starting Metadata refresh"); - // Just check what we send it - await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); + Logger.LogInformation("Kicking off Plex Availability Checker"); + await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } Logger.LogInformation("Finished Plex Content Cacher, with processed content: {0}, episodes: {1}. Recently Added Scan: {2}", processedContent?.Content?.Count() ?? 0, processedContent?.Episodes?.Count() ?? 0, recentlyAddedSearch); @@ -648,7 +646,6 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { Plex?.Dispose(); - Repo?.Dispose(); EpisodeSync?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 7414294be..2ba054aeb 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Plex; @@ -10,6 +9,7 @@ using Ombi.Api.Plex.Models; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; +using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -55,7 +55,7 @@ namespace Ombi.Schedule.Jobs.Plex _log.LogError(LoggingEvents.Cacher, e, "Caching Episodes Failed"); } - + //await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } @@ -206,7 +206,6 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - _repo?.Dispose(); _settings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 56499aea6..56a97b0ab 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -17,7 +17,7 @@ namespace Ombi.Schedule.Jobs.Radarr { public class RadarrSync : IRadarrSync { - public RadarrSync(ISettingsService radarr, IRadarrApi radarrApi, ILogger log, IExternalContext ctx) + public RadarrSync(ISettingsService radarr, IRadarrApi radarrApi, ILogger log, ExternalContext ctx) { RadarrSettings = radarr; RadarrApi = radarrApi; @@ -29,7 +29,7 @@ namespace Ombi.Schedule.Jobs.Radarr private ISettingsService RadarrSettings { get; } private IRadarrApi RadarrApi { get; } private ILogger Logger { get; } - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1); diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs index b6cca4c78..fbf594281 100644 --- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs +++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs @@ -17,7 +17,7 @@ namespace Ombi.Schedule.Jobs.SickRage { public class SickRageSync : ISickRageSync { - public SickRageSync(ISettingsService s, ISickRageApi api, ILogger l, IExternalContext ctx) + public SickRageSync(ISettingsService s, ISickRageApi api, ILogger l, ExternalContext ctx) { _settings = s; _api = api; @@ -29,7 +29,7 @@ namespace Ombi.Schedule.Jobs.SickRage private readonly ISettingsService _settings; private readonly ISickRageApi _api; private readonly ILogger _log; - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public async Task Execute(IJobExecutionContext job) { diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index f375ef064..e8707cc3a 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -20,7 +20,7 @@ namespace Ombi.Schedule.Jobs.Sonarr { public class SonarrSync : ISonarrSync { - public SonarrSync(ISettingsService s, ISonarrApi api, ILogger l, IExternalContext ctx) + public SonarrSync(ISettingsService s, ISonarrApi api, ILogger l, ExternalContext ctx) { _settings = s; _api = api; @@ -32,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Sonarr private readonly ISettingsService _settings; private readonly ISonarrApi _api; private readonly ILogger _log; - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; public async Task Execute(IJobExecutionContext job) { diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index 14d3c5197..82111d45d 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -10,12 +10,6 @@ - - - - - - diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index cfe3bbf27..ac095b354 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; +using Ombi.Core.Notifications; using Ombi.Core.Settings; +using Ombi.Helpers; using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Couchpotato; using Ombi.Schedule.Jobs.Emby; @@ -53,6 +55,7 @@ namespace Ombi.Schedule await AddEmby(s); await AddDvrApps(s); await AddSystem(s); + await AddNotifications(s); // Run Quartz await OmbiQuartz.Start(); @@ -93,5 +96,9 @@ namespace Ombi.Schedule await OmbiQuartz.Instance.AddJob(nameof(IEmbyAvaliabilityChecker), "Emby", null); await OmbiQuartz.Instance.AddJob(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s)); } + private static async Task AddNotifications(JobSettings s) + { + await OmbiQuartz.Instance.AddJob(nameof(INotificationService), "Notifications", null); + } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/QuartzJobRunner.cs b/src/Ombi.Schedule/QuartzJobRunner.cs new file mode 100644 index 000000000..2a8a39db0 --- /dev/null +++ b/src/Ombi.Schedule/QuartzJobRunner.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Quartz; + +namespace Ombi.Schedule +{ + public class QuartzJobRunner : IJob + { + private readonly IServiceProvider _serviceProvider; + public QuartzJobRunner(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task Execute(IJobExecutionContext context) + { + using (var scope = _serviceProvider.CreateScope()) + { + var jobType = context.JobDetail.JobType; + var job = scope.ServiceProvider.GetRequiredService(jobType) as IJob; + + await job.Execute(context); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs new file mode 100644 index 000000000..fe0c238d8 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Ombi.Core.Settings.Models.External +{ + public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings + { + public bool ShowAdultMovies { get; set; } + + public List ExcludedKeywordIds { get; set; } + } +} diff --git a/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs new file mode 100644 index 000000000..1c304e84c --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class WebhookSettings : Settings + { + public bool Enabled { get; set; } + public string WebhookUrl { get; set; } + public string ApplicationToken { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index 19cb77fc4..99ec4cb5f 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -5,16 +5,22 @@ using Ombi.Store.Entities; namespace Ombi.Store.Context { - public sealed class ExternalContext : DbContext, IExternalContext + public abstract class ExternalContext : DbContext { - private static bool _created; - public ExternalContext() + protected ExternalContext(DbContextOptions options) : base(options) { - if (_created) return; - _created = true; - Database.SetCommandTimeout(60); - Database.Migrate(); + } + + /// + /// This allows a sub class to call the base class 'DbContext' non typed constructor + /// This is need because instances of the subclasses will use a specific typed DbContextOptions + /// which can not be converted into the parameter in the above constructor + /// + /// + protected ExternalContext(DbContextOptions options) + : base(options) + { } public DbSet PlexServerContent { get; set; } @@ -32,16 +38,6 @@ namespace Ombi.Store.Context public DbSet SickRageCache { get; set; } public DbSet SickRageEpisodeCache { get; set; } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - var i = StoragePathSingleton.Instance; - if (string.IsNullOrEmpty(i.StoragePath)) - { - i.StoragePath = string.Empty; - } - optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "OmbiExternal.db")}"); - } - protected override void OnModelCreating(ModelBuilder builder) { builder.Entity().HasMany(x => x.Episodes) @@ -57,18 +53,5 @@ namespace Ombi.Store.Context base.OnModelCreating(builder); } - - - public void Seed() - { - // VACUUM; - Database.ExecuteSqlCommand("VACUUM;"); - - using (var tran = Database.BeginTransaction()) - { - SaveChanges(); - tran.Commit(); - } - } } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/IExternalContext.cs b/src/Ombi.Store/Context/IExternalContext.cs deleted file mode 100644 index 3f5d79a79..000000000 --- a/src/Ombi.Store/Context/IExternalContext.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Ombi.Store.Entities; - -namespace Ombi.Store.Context -{ - public interface IExternalContext : IDbContext - { - DbSet CouchPotatoCache { get; set; } - DbSet EmbyContent { get; set; } - DbSet EmbyEpisode { get; set; } - DbSet LidarrAlbumCache { get; set; } - DbSet LidarrArtistCache { get; set; } - DbSet PlexEpisode { get; set; } - DbSet PlexServerContent { get; set; } - DbSet RadarrCache { get; set; } - DbSet SickRageCache { get; set; } - DbSet SickRageEpisodeCache { get; set; } - DbSet SonarrCache { get; set; } - DbSet SonarrEpisodeCache { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs deleted file mode 100644 index b93c16be9..000000000 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Ombi.Store.Entities; -using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository.Requests; - -namespace Ombi.Store.Context -{ - public interface IOmbiContext : IDbContext - { - - //DbSet PlexServerContent { get; set; } - //DbSet PlexEpisode { get; set; } - DbSet Settings { get; set; } - //DbSet RadarrCache { get; set; } - //DbSet EmbyContent { get; set; } - //DbSet EmbyEpisode { get; set; } - DbSet NotificationTemplates { get; set; } - DbSet ApplicationConfigurations { get; set; } - DbSet Votes { get; set; } - void Seed(); - DbSet Audit { get; set; } - DbSet MovieRequests { get; set; } - DbSet AlbumRequests { get; set; } - DbSet TvRequests { get; set; } - DbSet ChildRequests { get; set; } - DbSet EpisodeRequests { get; set; } - DbSet Issues { get; set; } - DbSet IssueCategories { get; set; } - DbSet Tokens { get; set; } - DbSet SonarrCache { get; set; } - //DbSet SonarrEpisodeCache { get; set; } - //DbSet CouchPotatoCache { get; set; } - //DbSet SickRageCache { get; set; } - //DbSet LidarrArtistCache { get; set; } - //DbSet LidarrAlbumCache { get; set; } - //DbSet SickRageEpisodeCache { get; set; } - DbSet RequestLogs { get; set; } - DbSet RecentlyAddedLogs { get; set; } - DbSet RequestSubscription { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Store/Context/ISettingsContext.cs b/src/Ombi.Store/Context/ISettingsContext.cs deleted file mode 100644 index 3c209c68a..000000000 --- a/src/Ombi.Store/Context/ISettingsContext.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Ombi.Store.Entities; - -namespace Ombi.Store.Context -{ - public interface ISettingsContext : IDbContext - { - DbSet ApplicationConfigurations { get; set; } - DbSet Settings { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Store/Context/MySql/ExternalMySqlContext.cs b/src/Ombi.Store/Context/MySql/ExternalMySqlContext.cs new file mode 100644 index 000000000..6b569d591 --- /dev/null +++ b/src/Ombi.Store/Context/MySql/ExternalMySqlContext.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.MySql +{ + public sealed class ExternalMySqlContext : ExternalContext + { + private static bool _created; + public ExternalMySqlContext(DbContextOptions options) : base(options) + { + if (_created) return; + + _created = true; + Database.Migrate(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs new file mode 100644 index 000000000..073a0ed1a --- /dev/null +++ b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.MySql +{ + public sealed class OmbiMySqlContext : OmbiContext + { + private static bool _created; + public OmbiMySqlContext(DbContextOptions options) : base(options) + { + if (_created) return; + _created = true; + + Database.Migrate(); + } + + public override void Dispose() + { + base.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/MySql/SettingsMySqlContext.cs b/src/Ombi.Store/Context/MySql/SettingsMySqlContext.cs new file mode 100644 index 000000000..cc450e715 --- /dev/null +++ b/src/Ombi.Store/Context/MySql/SettingsMySqlContext.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.MySql +{ + public sealed class SettingsMySqlContext : SettingsContext + { + private static bool _created; + public SettingsMySqlContext(DbContextOptions options) : base(options) + { + if (_created) return; + + _created = true; + Database.Migrate(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index f7ce09aa4..2b145c7f2 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -11,29 +11,26 @@ using Ombi.Store.Repository.Requests; namespace Ombi.Store.Context { - public sealed class OmbiContext : IdentityDbContext, IOmbiContext + public abstract class OmbiContext : IdentityDbContext { - private static bool _created; - public OmbiContext() + protected OmbiContext(DbContextOptions options) : base(options) { - if (_created) return; + } - _created = true; - Database.SetCommandTimeout(60); - Database.Migrate(); + /// + /// This allows a sub class to call the base class 'DbContext' non typed constructor + /// This is need because instances of the subclasses will use a specific typed DbContextOptions + /// which can not be converted into the parameter in the above constructor + /// + /// + protected OmbiContext(DbContextOptions options) + : base(options) + { } + public DbSet NotificationTemplates { get; set; } - public DbSet ApplicationConfigurations { get; set; } - public DbSet PlexServerContent { get; set; } - public DbSet PlexSeasonsContent { get; set; } - public DbSet PlexEpisode { get; set; } - public DbSet Settings { get; set; } - public DbSet RadarrCache { get; set; } - public DbSet CouchPotatoCache { get; set; } - public DbSet EmbyContent { get; set; } - public DbSet EmbyEpisode { get; set; } public DbSet MovieRequests { get; set; } public DbSet AlbumRequests { get; set; } @@ -51,44 +48,11 @@ namespace Ombi.Store.Context public DbSet Audit { get; set; } public DbSet Tokens { get; set; } - public DbSet SonarrCache { get; set; } - public DbSet LidarrArtistCache { get; set; } - public DbSet LidarrAlbumCache { get; set; } - public DbSet SonarrEpisodeCache { get; set; } - public DbSet SickRageCache { get; set; } - public DbSet SickRageEpisodeCache { get; set; } public DbSet RequestSubscription { get; set; } public DbSet UserNotificationPreferences { get; set; } public DbSet UserQualityProfileses { get; set; } public DbSet RequestQueue { get; set; } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - var i = StoragePathSingleton.Instance; - if (string.IsNullOrEmpty(i.StoragePath)) - { - i.StoragePath = string.Empty; - } - optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "Ombi.db")}"); - } - - protected override void OnModelCreating(ModelBuilder builder) - { - builder.Entity().HasMany(x => x.Episodes) - .WithOne(x => x.Series) - .HasPrincipalKey(x => x.Key) - .HasForeignKey(x => x.GrandparentKey); - - builder.Entity() - .HasOne(p => p.Series) - .WithMany(b => b.Episodes) - .HasPrincipalKey(x => x.EmbyId) - .HasForeignKey(p => p.ParentId); - - base.OnModelCreating(builder); - } - - public void Seed() { diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index 48ef0e6c7..9f6d52791 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -1,39 +1,34 @@ -using System.IO; -using System.Linq; +using System.Linq; using Microsoft.EntityFrameworkCore; -using Ombi.Helpers; using Ombi.Store.Entities; namespace Ombi.Store.Context { - public sealed class SettingsContext : DbContext, ISettingsContext + public abstract class SettingsContext : DbContext { - private static bool _created; - public SettingsContext() + protected SettingsContext(DbContextOptions options) : base(options) { - if (_created) return; - _created = true; - Database.SetCommandTimeout(60); - Database.Migrate(); } - - public DbSet Settings { get; set; } - public DbSet ApplicationConfigurations { get; set; } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + /// + /// This allows a sub class to call the base class 'DbContext' non typed constructor + /// This is need because instances of the subclasses will use a specific typed DbContextOptions + /// which can not be converted into the parameter in the above constructor + /// + /// + protected SettingsContext(DbContextOptions options) + : base(options) { - var i = StoragePathSingleton.Instance; - if (string.IsNullOrEmpty(i.StoragePath)) - { - i.StoragePath = string.Empty; - } - optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "OmbiSettings.db")}"); } + public DbSet Settings { get; set; } + public DbSet ApplicationConfigurations { get; set; } + + + public void Seed() { - using (var tran = Database.BeginTransaction()) { // Add the tokens diff --git a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs new file mode 100644 index 000000000..adbf6e017 --- /dev/null +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.Sqlite +{ + public sealed class ExternalSqliteContext : ExternalContext + { + private static bool _created; + public ExternalSqliteContext(DbContextOptions options) : base(options) + { + if (_created) return; + + _created = true; + Upgrade(); + Database.SetCommandTimeout(60); + + Database.Migrate(); + + } + + + private void Upgrade() + { + try + { + Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + VALUES('20191103205133_Inital', '2.2.6-servicing-10079'); "); + } + catch (Exception) + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs new file mode 100644 index 000000000..5d6e29e31 --- /dev/null +++ b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs @@ -0,0 +1,34 @@ +using System; +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.Sqlite +{ + public sealed class OmbiSqliteContext : OmbiContext + { + private static bool _created; + public OmbiSqliteContext(DbContextOptions options) : base(options) + { + if (_created) return; + + + _created = true; + Upgrade(); + Database.SetCommandTimeout(60); + Database.Migrate(); + } + + + private void Upgrade() + { + try + { + Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + VALUES('20191102235658_Inital', '2.2.6-servicing-10079'); "); + } + catch (Exception) + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs new file mode 100644 index 000000000..19e155a71 --- /dev/null +++ b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.EntityFrameworkCore; + +namespace Ombi.Store.Context.Sqlite +{ + public sealed class SettingsSqliteContext : SettingsContext + { + private static bool _created; + public SettingsSqliteContext(DbContextOptions options) : base(options) + { + if (_created) return; + + _created = true; + Upgrade(); + Database.SetCommandTimeout(60); + Database.Migrate(); + } + + private void Upgrade() + { + try + { + Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + VALUES('20191103205204_Inital', '2.2.6-servicing-10079'); "); + } + catch (Exception) + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Migration.txt b/src/Ombi.Store/Migration.txt index 3b54d72f5..331299143 100644 --- a/src/Ombi.Store/Migration.txt +++ b/src/Ombi.Store/Migration.txt @@ -1 +1,3 @@ -dotnet ef migrations add Inital --context OmbiContext --startup-project ../Ombi/Ombi.csproj \ No newline at end of file +dotnet ef migrations add Inital --context OmbiSqliteContext --startup-project ../Ombi/Ombi.csproj + +If running migrations for any db provider other than Sqlite, then ensure the database.json is pointing at the correct DB type \ No newline at end of file diff --git a/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs new file mode 100644 index 000000000..cba04a14c --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations.External +{ + [DbContext(typeof(ExternalContext))] + [Migration("20191018225833_PlexContentId")] + partial class PlexContentId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs new file mode 100644 index 000000000..5d5e33dce --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.External +{ + public partial class PlexContentId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestId", + table: "PlexServerContent", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestId", + table: "PlexServerContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs index 4e97b5514..77ef6b080 100644 --- a/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations.External { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -194,6 +194,8 @@ namespace Ombi.Store.Migrations.External b.Property("ReleaseYear"); + b.Property("RequestId"); + b.Property("TheMovieDbId"); b.Property("Title"); diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.Designer.cs new file mode 100644 index 000000000..3975c306f --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.Designer.cs @@ -0,0 +1,315 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20191103213915_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.cs b/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.cs new file mode 100644 index 000000000..b6dc51a01 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.cs @@ -0,0 +1,310 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CouchPotatoCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TheMovieDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CouchPotatoCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + EmbyId = table.Column(nullable: false), + Type = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Url = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyContent", x => x.Id); + table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId); + }); + + migrationBuilder.CreateTable( + name: "LidarrAlbumCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ArtistId = table.Column(nullable: false), + ForeignAlbumId = table.Column(nullable: true), + TrackCount = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + Monitored = table.Column(nullable: false), + Title = table.Column(nullable: true), + PercentOfTracks = table.Column(nullable: false), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "LidarrArtistCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ArtistId = table.Column(nullable: false), + ArtistName = table.Column(nullable: true), + ForeignArtistId = table.Column(nullable: true), + Monitored = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrArtistCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PlexServerContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + ReleaseYear = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true), + Key = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + Quality = table.Column(nullable: true), + RequestId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexServerContent", x => x.Id); + table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "RadarrCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TheMovieDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RadarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + EmbyId = table.Column(nullable: true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + ParentId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false), + TvDbId = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyEpisode", x => x.Id); + table.ForeignKey( + name: "FK_EmbyEpisode_EmbyContent_ParentId", + column: x => x.ParentId, + principalTable: "EmbyContent", + principalColumn: "EmbyId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PlexEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Key = table.Column(nullable: false), + Title = table.Column(nullable: true), + ParentKey = table.Column(nullable: false), + GrandparentKey = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexEpisode", x => x.Id); + table.ForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + column: x => x.GrandparentKey, + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlexSeasonsContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + PlexContentId = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + SeasonKey = table.Column(nullable: false), + ParentKey = table.Column(nullable: false), + PlexServerContentId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexSeasonsContent", x => x.Id); + table.ForeignKey( + name: "FK_PlexSeasonsContent_PlexServerContent_PlexServerContentId", + column: x => x.PlexServerContentId, + principalTable: "PlexServerContent", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EmbyEpisode_ParentId", + table: "EmbyEpisode", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_PlexEpisode_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey"); + + migrationBuilder.CreateIndex( + name: "IX_PlexSeasonsContent_PlexServerContentId", + table: "PlexSeasonsContent", + column: "PlexServerContentId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CouchPotatoCache"); + + migrationBuilder.DropTable( + name: "EmbyEpisode"); + + migrationBuilder.DropTable( + name: "LidarrAlbumCache"); + + migrationBuilder.DropTable( + name: "LidarrArtistCache"); + + migrationBuilder.DropTable( + name: "PlexEpisode"); + + migrationBuilder.DropTable( + name: "PlexSeasonsContent"); + + migrationBuilder.DropTable( + name: "RadarrCache"); + + migrationBuilder.DropTable( + name: "SickRageCache"); + + migrationBuilder.DropTable( + name: "SickRageEpisodeCache"); + + migrationBuilder.DropTable( + name: "SonarrCache"); + + migrationBuilder.DropTable( + name: "SonarrEpisodeCache"); + + migrationBuilder.DropTable( + name: "EmbyContent"); + + migrationBuilder.DropTable( + name: "PlexServerContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs new file mode 100644 index 000000000..c9ca6fc74 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -0,0 +1,313 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + partial class ExternalMySqlContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.Designer.cs new file mode 100644 index 000000000..0aae33972 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20191103205133_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.cs new file mode 100644 index 000000000..35b56b638 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.cs @@ -0,0 +1,309 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CouchPotatoCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TheMovieDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CouchPotatoCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + EmbyId = table.Column(nullable: false), + Type = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Url = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyContent", x => x.Id); + table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId); + }); + + migrationBuilder.CreateTable( + name: "LidarrAlbumCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArtistId = table.Column(nullable: false), + ForeignAlbumId = table.Column(nullable: true), + TrackCount = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + Monitored = table.Column(nullable: false), + Title = table.Column(nullable: true), + PercentOfTracks = table.Column(nullable: false), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "LidarrArtistCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArtistId = table.Column(nullable: false), + ArtistName = table.Column(nullable: true), + ForeignArtistId = table.Column(nullable: true), + Monitored = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrArtistCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PlexServerContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ReleaseYear = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true), + Key = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + Quality = table.Column(nullable: true), + RequestId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexServerContent", x => x.Id); + table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "RadarrCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TheMovieDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RadarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + EmbyId = table.Column(nullable: true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + ParentId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false), + TvDbId = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyEpisode", x => x.Id); + table.ForeignKey( + name: "FK_EmbyEpisode_EmbyContent_ParentId", + column: x => x.ParentId, + principalTable: "EmbyContent", + principalColumn: "EmbyId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PlexEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Key = table.Column(nullable: false), + Title = table.Column(nullable: true), + ParentKey = table.Column(nullable: false), + GrandparentKey = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexEpisode", x => x.Id); + table.ForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + column: x => x.GrandparentKey, + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlexSeasonsContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PlexContentId = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + SeasonKey = table.Column(nullable: false), + ParentKey = table.Column(nullable: false), + PlexServerContentId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexSeasonsContent", x => x.Id); + table.ForeignKey( + name: "FK_PlexSeasonsContent_PlexServerContent_PlexServerContentId", + column: x => x.PlexServerContentId, + principalTable: "PlexServerContent", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EmbyEpisode_ParentId", + table: "EmbyEpisode", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_PlexEpisode_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey"); + + migrationBuilder.CreateIndex( + name: "IX_PlexSeasonsContent_PlexServerContentId", + table: "PlexSeasonsContent", + column: "PlexServerContentId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CouchPotatoCache"); + + migrationBuilder.DropTable( + name: "EmbyEpisode"); + + migrationBuilder.DropTable( + name: "LidarrAlbumCache"); + + migrationBuilder.DropTable( + name: "LidarrArtistCache"); + + migrationBuilder.DropTable( + name: "PlexEpisode"); + + migrationBuilder.DropTable( + name: "PlexSeasonsContent"); + + migrationBuilder.DropTable( + name: "RadarrCache"); + + migrationBuilder.DropTable( + name: "SickRageCache"); + + migrationBuilder.DropTable( + name: "SickRageEpisodeCache"); + + migrationBuilder.DropTable( + name: "SonarrCache"); + + migrationBuilder.DropTable( + name: "SonarrEpisodeCache"); + + migrationBuilder.DropTable( + name: "EmbyContent"); + + migrationBuilder.DropTable( + name: "PlexServerContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs new file mode 100644 index 000000000..0183e897c --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20191113213617_RequestIdPatch")] + partial class RequestIdPatch + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs new file mode 100644 index 000000000..29c1a4033 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs @@ -0,0 +1,22 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class RequestIdPatch : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + //migrationBuilder.AddColumn( + // name: "RequestId", + // table: "PlexServerContent", + // nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs new file mode 100644 index 000000000..86e292e2f --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs @@ -0,0 +1,312 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + partial class ExternalSqliteContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs new file mode 100644 index 000000000..f72e34766 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs @@ -0,0 +1,1062 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20191102235852_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs new file mode 100644 index 000000000..8c8294301 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs @@ -0,0 +1,884 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + Alias = table.Column(nullable: true), + UserType = table.Column(nullable: false), + ProviderUserId = table.Column(nullable: true), + LastLoggedIn = table.Column(nullable: true), + EmbyConnectUserId = table.Column(nullable: true), + MovieRequestLimit = table.Column(nullable: true), + EpisodeRequestLimit = table.Column(nullable: true), + MusicRequestLimit = table.Column(nullable: true), + UserAccessToken = table.Column(nullable: true), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Audit", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + DateTime = table.Column(nullable: false), + Description = table.Column(nullable: true), + AuditType = table.Column(nullable: false), + AuditArea = table.Column(nullable: false), + User = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Audit", x => x.Id); + }); + + + migrationBuilder.CreateTable( + name: "IssueCategory", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IssueCategory", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "NotificationTemplates", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + NotificationType = table.Column(nullable: false), + Agent = table.Column(nullable: false), + Subject = table.Column(nullable: true), + Message = table.Column(nullable: true), + Enabled = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_NotificationTemplates", x => x.Id); + }); + + + migrationBuilder.CreateTable( + name: "RecentlyAddedLog", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Type = table.Column(nullable: false), + ContentType = table.Column(nullable: false), + ContentId = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: true), + SeasonNumber = table.Column(nullable: true), + AlbumId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RecentlyAddedLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RequestQueue", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + RequestId = table.Column(nullable: false), + Type = table.Column(nullable: false), + Dts = table.Column(nullable: false), + Error = table.Column(nullable: true), + Completed = table.Column(nullable: true), + RetryCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestQueue", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TvRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TvDbId = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + QualityOverride = table.Column(nullable: true), + RootFolder = table.Column(nullable: true), + Overview = table.Column(nullable: true), + Title = table.Column(nullable: true), + PosterPath = table.Column(nullable: true), + Background = table.Column(nullable: true), + ReleaseDate = table.Column(nullable: false), + Status = table.Column(nullable: true), + TotalSeasons = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TvRequests", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + RoleId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AlbumRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ForeignAlbumId = table.Column(nullable: true), + ForeignArtistId = table.Column(nullable: true), + Disk = table.Column(nullable: true), + Cover = table.Column(nullable: true), + Rating = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + ArtistName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AlbumRequests", x => x.Id); + table.ForeignKey( + name: "FK_AlbumRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(nullable: false), + ProviderKey = table.Column(nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(nullable: false), + Name = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "MovieRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + Overview = table.Column(nullable: true), + PosterPath = table.Column(nullable: true), + ReleaseDate = table.Column(nullable: false), + DigitalReleaseDate = table.Column(nullable: true), + Status = table.Column(nullable: true), + Background = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: false), + IssueId = table.Column(nullable: true), + RootPathOverride = table.Column(nullable: false), + QualityOverride = table.Column(nullable: false), + LangCode = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_MovieRequests", x => x.Id); + table.ForeignKey( + name: "FK_MovieRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "NotificationUserId", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + PlayerId = table.Column(nullable: true), + UserId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_NotificationUserId", x => x.Id); + table.ForeignKey( + name: "FK_NotificationUserId_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "RequestLog", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestDate = table.Column(nullable: false), + RequestId = table.Column(nullable: false), + EpisodeCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestLog", x => x.Id); + table.ForeignKey( + name: "FK_RequestLog_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "RequestSubscription", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: true), + RequestId = table.Column(nullable: false), + RequestType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestSubscription", x => x.Id); + table.ForeignKey( + name: "FK_RequestSubscription_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Tokens", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Token = table.Column(nullable: true), + UserId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Tokens", x => x.Id); + table.ForeignKey( + name: "FK_Tokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "UserNotificationPreferences", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: true), + Agent = table.Column(nullable: false), + Enabled = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserNotificationPreferences", x => x.Id); + table.ForeignKey( + name: "FK_UserNotificationPreferences_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "UserQualityProfiles", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: true), + SonarrQualityProfileAnime = table.Column(nullable: false), + SonarrRootPathAnime = table.Column(nullable: false), + SonarrRootPath = table.Column(nullable: false), + SonarrQualityProfile = table.Column(nullable: false), + RadarrRootPath = table.Column(nullable: false), + RadarrQualityProfile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserQualityProfiles", x => x.Id); + table.ForeignKey( + name: "FK_UserQualityProfiles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Votes", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + RequestId = table.Column(nullable: false), + VoteType = table.Column(nullable: false), + RequestType = table.Column(nullable: false), + UserId = table.Column(nullable: true), + Date = table.Column(nullable: false), + Deleted = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Votes", x => x.Id); + table.ForeignKey( + name: "FK_Votes_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "ChildRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ParentRequestId = table.Column(nullable: false), + IssueId = table.Column(nullable: true), + SeriesType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChildRequests", x => x.Id); + table.ForeignKey( + name: "FK_ChildRequests_TvRequests_ParentRequestId", + column: x => x.ParentRequestId, + principalTable: "TvRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ChildRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Issues", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Title = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + ProviderId = table.Column(nullable: true), + RequestId = table.Column(nullable: true), + Subject = table.Column(nullable: true), + Description = table.Column(nullable: true), + IssueCategoryId = table.Column(nullable: false), + Status = table.Column(nullable: false), + ResovledDate = table.Column(nullable: true), + UserReportedId = table.Column(nullable: true), + IssueId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Issues", x => x.Id); + table.ForeignKey( + name: "FK_Issues_IssueCategory_IssueCategoryId", + column: x => x.IssueCategoryId, + principalTable: "IssueCategory", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Issues_ChildRequests_IssueId", + column: x => x.IssueId, + principalTable: "ChildRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Issues_MovieRequests_IssueId", + column: x => x.IssueId, + principalTable: "MovieRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Issues_AspNetUsers_UserReportedId", + column: x => x.UserReportedId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "SeasonRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + SeasonNumber = table.Column(nullable: false), + ChildRequestId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SeasonRequests", x => x.Id); + table.ForeignKey( + name: "FK_SeasonRequests_ChildRequests_ChildRequestId", + column: x => x.ChildRequestId, + principalTable: "ChildRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IssueComments", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(nullable: true), + Comment = table.Column(nullable: true), + IssuesId = table.Column(nullable: true), + Date = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IssueComments", x => x.Id); + table.ForeignKey( + name: "FK_IssueComments_Issues_IssuesId", + column: x => x.IssuesId, + principalTable: "Issues", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_IssueComments_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EpisodeRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + EpisodeNumber = table.Column(nullable: false), + Title = table.Column(nullable: true), + AirDate = table.Column(nullable: false), + Url = table.Column(nullable: true), + Available = table.Column(nullable: false), + Approved = table.Column(nullable: false), + Requested = table.Column(nullable: false), + SeasonId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EpisodeRequests", x => x.Id); + table.ForeignKey( + name: "FK_EpisodeRequests_SeasonRequests_SeasonId", + column: x => x.SeasonId, + principalTable: "SeasonRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AlbumRequests_RequestedUserId", + table: "AlbumRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ChildRequests_ParentRequestId", + table: "ChildRequests", + column: "ParentRequestId"); + + migrationBuilder.CreateIndex( + name: "IX_ChildRequests_RequestedUserId", + table: "ChildRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_EpisodeRequests_SeasonId", + table: "EpisodeRequests", + column: "SeasonId"); + + migrationBuilder.CreateIndex( + name: "IX_IssueComments_IssuesId", + table: "IssueComments", + column: "IssuesId"); + + migrationBuilder.CreateIndex( + name: "IX_IssueComments_UserId", + table: "IssueComments", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_IssueCategoryId", + table: "Issues", + column: "IssueCategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_IssueId", + table: "Issues", + column: "IssueId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_UserReportedId", + table: "Issues", + column: "UserReportedId"); + + migrationBuilder.CreateIndex( + name: "IX_MovieRequests_RequestedUserId", + table: "MovieRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_NotificationUserId_UserId", + table: "NotificationUserId", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_RequestLog_UserId", + table: "RequestLog", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_RequestSubscription_UserId", + table: "RequestSubscription", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_SeasonRequests_ChildRequestId", + table: "SeasonRequests", + column: "ChildRequestId"); + + migrationBuilder.CreateIndex( + name: "IX_Tokens_UserId", + table: "Tokens", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserNotificationPreferences_UserId", + table: "UserNotificationPreferences", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserQualityProfiles_UserId", + table: "UserQualityProfiles", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Votes_UserId", + table: "Votes", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AlbumRequests"); + + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "Audit"); + + migrationBuilder.DropTable( + name: "EpisodeRequests"); + + migrationBuilder.DropTable( + name: "IssueComments"); + + migrationBuilder.DropTable( + name: "NotificationTemplates"); + + migrationBuilder.DropTable( + name: "NotificationUserId"); + + migrationBuilder.DropTable( + name: "RecentlyAddedLog"); + + migrationBuilder.DropTable( + name: "RequestLog"); + + migrationBuilder.DropTable( + name: "RequestQueue"); + + migrationBuilder.DropTable( + name: "RequestSubscription"); + + migrationBuilder.DropTable( + name: "Tokens"); + + migrationBuilder.DropTable( + name: "UserNotificationPreferences"); + + migrationBuilder.DropTable( + name: "UserQualityProfiles"); + + migrationBuilder.DropTable( + name: "Votes"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "SeasonRequests"); + + migrationBuilder.DropTable( + name: "Issues"); + + migrationBuilder.DropTable( + name: "PlexServerContent"); + + migrationBuilder.DropTable( + name: "IssueCategory"); + + migrationBuilder.DropTable( + name: "ChildRequests"); + + migrationBuilder.DropTable( + name: "MovieRequests"); + + migrationBuilder.DropTable( + name: "TvRequests"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs new file mode 100644 index 000000000..7952ce974 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -0,0 +1,897 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + partial class OmbiMySqlContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs new file mode 100644 index 000000000..e5d2c302e --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs @@ -0,0 +1,1061 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20191102235658_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.cs new file mode 100644 index 000000000..64de994ed --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.cs @@ -0,0 +1,1029 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + Alias = table.Column(nullable: true), + UserType = table.Column(nullable: false), + ProviderUserId = table.Column(nullable: true), + LastLoggedIn = table.Column(nullable: true), + EmbyConnectUserId = table.Column(nullable: true), + MovieRequestLimit = table.Column(nullable: true), + EpisodeRequestLimit = table.Column(nullable: true), + MusicRequestLimit = table.Column(nullable: true), + UserAccessToken = table.Column(nullable: true), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Audit", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DateTime = table.Column(nullable: false), + Description = table.Column(nullable: true), + AuditType = table.Column(nullable: false), + AuditArea = table.Column(nullable: false), + User = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Audit", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + EmbyId = table.Column(nullable: false), + Type = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Url = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyContent", x => x.Id); + table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId); + }); + + migrationBuilder.CreateTable( + name: "IssueCategory", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IssueCategory", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "NotificationTemplates", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + NotificationType = table.Column(nullable: false), + Agent = table.Column(nullable: false), + Subject = table.Column(nullable: true), + Message = table.Column(nullable: true), + Enabled = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_NotificationTemplates", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PlexServerContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ReleaseYear = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true), + Key = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + Quality = table.Column(nullable: true), + RequestId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexServerContent", x => x.Id); + table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "RecentlyAddedLog", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Type = table.Column(nullable: false), + ContentType = table.Column(nullable: false), + ContentId = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: true), + SeasonNumber = table.Column(nullable: true), + AlbumId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RecentlyAddedLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RequestQueue", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RequestId = table.Column(nullable: false), + Type = table.Column(nullable: false), + Dts = table.Column(nullable: false), + Error = table.Column(nullable: true), + Completed = table.Column(nullable: true), + RetryCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestQueue", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TvRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TvDbId = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + QualityOverride = table.Column(nullable: true), + RootFolder = table.Column(nullable: true), + Overview = table.Column(nullable: true), + Title = table.Column(nullable: true), + PosterPath = table.Column(nullable: true), + Background = table.Column(nullable: true), + ReleaseDate = table.Column(nullable: false), + Status = table.Column(nullable: true), + TotalSeasons = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TvRequests", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AlbumRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ForeignAlbumId = table.Column(nullable: true), + ForeignArtistId = table.Column(nullable: true), + Disk = table.Column(nullable: true), + Cover = table.Column(nullable: true), + Rating = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + ArtistName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AlbumRequests", x => x.Id); + table.ForeignKey( + name: "FK_AlbumRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(nullable: false), + ProviderKey = table.Column(nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(nullable: false), + Name = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "MovieRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + Overview = table.Column(nullable: true), + PosterPath = table.Column(nullable: true), + ReleaseDate = table.Column(nullable: false), + DigitalReleaseDate = table.Column(nullable: true), + Status = table.Column(nullable: true), + Background = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: false), + IssueId = table.Column(nullable: true), + RootPathOverride = table.Column(nullable: false), + QualityOverride = table.Column(nullable: false), + LangCode = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_MovieRequests", x => x.Id); + table.ForeignKey( + name: "FK_MovieRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "NotificationUserId", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PlayerId = table.Column(nullable: true), + UserId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_NotificationUserId", x => x.Id); + table.ForeignKey( + name: "FK_NotificationUserId_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "RequestLog", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestDate = table.Column(nullable: false), + RequestId = table.Column(nullable: false), + EpisodeCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestLog", x => x.Id); + table.ForeignKey( + name: "FK_RequestLog_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "RequestSubscription", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + RequestId = table.Column(nullable: false), + RequestType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestSubscription", x => x.Id); + table.ForeignKey( + name: "FK_RequestSubscription_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Tokens", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Token = table.Column(nullable: true), + UserId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Tokens", x => x.Id); + table.ForeignKey( + name: "FK_Tokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "UserNotificationPreferences", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + Agent = table.Column(nullable: false), + Enabled = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserNotificationPreferences", x => x.Id); + table.ForeignKey( + name: "FK_UserNotificationPreferences_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "UserQualityProfiles", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + SonarrQualityProfileAnime = table.Column(nullable: false), + SonarrRootPathAnime = table.Column(nullable: false), + SonarrRootPath = table.Column(nullable: false), + SonarrQualityProfile = table.Column(nullable: false), + RadarrRootPath = table.Column(nullable: false), + RadarrQualityProfile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserQualityProfiles", x => x.Id); + table.ForeignKey( + name: "FK_UserQualityProfiles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Votes", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RequestId = table.Column(nullable: false), + VoteType = table.Column(nullable: false), + RequestType = table.Column(nullable: false), + UserId = table.Column(nullable: true), + Date = table.Column(nullable: false), + Deleted = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Votes", x => x.Id); + table.ForeignKey( + name: "FK_Votes_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EmbyEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + EmbyId = table.Column(nullable: true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + ParentId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false), + TvDbId = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyEpisode", x => x.Id); + table.ForeignKey( + name: "FK_EmbyEpisode_EmbyContent_ParentId", + column: x => x.ParentId, + principalTable: "EmbyContent", + principalColumn: "EmbyId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PlexEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Key = table.Column(nullable: false), + Title = table.Column(nullable: true), + ParentKey = table.Column(nullable: false), + GrandparentKey = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexEpisode", x => x.Id); + table.ForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + column: x => x.GrandparentKey, + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlexSeasonsContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PlexContentId = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + SeasonKey = table.Column(nullable: false), + ParentKey = table.Column(nullable: false), + PlexServerContentId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexSeasonsContent", x => x.Id); + table.ForeignKey( + name: "FK_PlexSeasonsContent_PlexServerContent_PlexServerContentId", + column: x => x.PlexServerContentId, + principalTable: "PlexServerContent", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "ChildRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + Approved = table.Column(nullable: false), + MarkedAsApproved = table.Column(nullable: false), + RequestedDate = table.Column(nullable: false), + Available = table.Column(nullable: false), + MarkedAsAvailable = table.Column(nullable: true), + RequestedUserId = table.Column(nullable: true), + Denied = table.Column(nullable: true), + MarkedAsDenied = table.Column(nullable: false), + DeniedReason = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + RequestedByAlias = table.Column(nullable: true), + ParentRequestId = table.Column(nullable: false), + IssueId = table.Column(nullable: true), + SeriesType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChildRequests", x => x.Id); + table.ForeignKey( + name: "FK_ChildRequests_TvRequests_ParentRequestId", + column: x => x.ParentRequestId, + principalTable: "TvRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ChildRequests_AspNetUsers_RequestedUserId", + column: x => x.RequestedUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Issues", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + RequestType = table.Column(nullable: false), + ProviderId = table.Column(nullable: true), + RequestId = table.Column(nullable: true), + Subject = table.Column(nullable: true), + Description = table.Column(nullable: true), + IssueCategoryId = table.Column(nullable: false), + Status = table.Column(nullable: false), + ResovledDate = table.Column(nullable: true), + UserReportedId = table.Column(nullable: true), + IssueId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Issues", x => x.Id); + table.ForeignKey( + name: "FK_Issues_IssueCategory_IssueCategoryId", + column: x => x.IssueCategoryId, + principalTable: "IssueCategory", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Issues_ChildRequests_IssueId", + column: x => x.IssueId, + principalTable: "ChildRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Issues_MovieRequests_IssueId", + column: x => x.IssueId, + principalTable: "MovieRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Issues_AspNetUsers_UserReportedId", + column: x => x.UserReportedId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "SeasonRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SeasonNumber = table.Column(nullable: false), + ChildRequestId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SeasonRequests", x => x.Id); + table.ForeignKey( + name: "FK_SeasonRequests_ChildRequests_ChildRequestId", + column: x => x.ChildRequestId, + principalTable: "ChildRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IssueComments", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + Comment = table.Column(nullable: true), + IssuesId = table.Column(nullable: true), + Date = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IssueComments", x => x.Id); + table.ForeignKey( + name: "FK_IssueComments_Issues_IssuesId", + column: x => x.IssuesId, + principalTable: "Issues", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_IssueComments_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EpisodeRequests", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EpisodeNumber = table.Column(nullable: false), + Title = table.Column(nullable: true), + AirDate = table.Column(nullable: false), + Url = table.Column(nullable: true), + Available = table.Column(nullable: false), + Approved = table.Column(nullable: false), + Requested = table.Column(nullable: false), + SeasonId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EpisodeRequests", x => x.Id); + table.ForeignKey( + name: "FK_EpisodeRequests_SeasonRequests_SeasonId", + column: x => x.SeasonId, + principalTable: "SeasonRequests", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AlbumRequests_RequestedUserId", + table: "AlbumRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ChildRequests_ParentRequestId", + table: "ChildRequests", + column: "ParentRequestId"); + + migrationBuilder.CreateIndex( + name: "IX_ChildRequests_RequestedUserId", + table: "ChildRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_EmbyEpisode_ParentId", + table: "EmbyEpisode", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_EpisodeRequests_SeasonId", + table: "EpisodeRequests", + column: "SeasonId"); + + migrationBuilder.CreateIndex( + name: "IX_IssueComments_IssuesId", + table: "IssueComments", + column: "IssuesId"); + + migrationBuilder.CreateIndex( + name: "IX_IssueComments_UserId", + table: "IssueComments", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_IssueCategoryId", + table: "Issues", + column: "IssueCategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_IssueId", + table: "Issues", + column: "IssueId"); + + migrationBuilder.CreateIndex( + name: "IX_Issues_UserReportedId", + table: "Issues", + column: "UserReportedId"); + + migrationBuilder.CreateIndex( + name: "IX_MovieRequests_RequestedUserId", + table: "MovieRequests", + column: "RequestedUserId"); + + migrationBuilder.CreateIndex( + name: "IX_NotificationUserId_UserId", + table: "NotificationUserId", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_PlexEpisode_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey"); + + migrationBuilder.CreateIndex( + name: "IX_PlexSeasonsContent_PlexServerContentId", + table: "PlexSeasonsContent", + column: "PlexServerContentId"); + + migrationBuilder.CreateIndex( + name: "IX_RequestLog_UserId", + table: "RequestLog", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_RequestSubscription_UserId", + table: "RequestSubscription", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_SeasonRequests_ChildRequestId", + table: "SeasonRequests", + column: "ChildRequestId"); + + migrationBuilder.CreateIndex( + name: "IX_Tokens_UserId", + table: "Tokens", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserNotificationPreferences_UserId", + table: "UserNotificationPreferences", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserQualityProfiles_UserId", + table: "UserQualityProfiles", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Votes_UserId", + table: "Votes", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AlbumRequests"); + + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "Audit"); + + migrationBuilder.DropTable( + name: "EmbyEpisode"); + + migrationBuilder.DropTable( + name: "EpisodeRequests"); + + migrationBuilder.DropTable( + name: "IssueComments"); + + migrationBuilder.DropTable( + name: "NotificationTemplates"); + + migrationBuilder.DropTable( + name: "NotificationUserId"); + + migrationBuilder.DropTable( + name: "PlexEpisode"); + + migrationBuilder.DropTable( + name: "PlexSeasonsContent"); + + migrationBuilder.DropTable( + name: "RecentlyAddedLog"); + + migrationBuilder.DropTable( + name: "RequestLog"); + + migrationBuilder.DropTable( + name: "RequestQueue"); + + migrationBuilder.DropTable( + name: "RequestSubscription"); + + migrationBuilder.DropTable( + name: "Tokens"); + + migrationBuilder.DropTable( + name: "UserNotificationPreferences"); + + migrationBuilder.DropTable( + name: "UserQualityProfiles"); + + migrationBuilder.DropTable( + name: "Votes"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "EmbyContent"); + + migrationBuilder.DropTable( + name: "SeasonRequests"); + + migrationBuilder.DropTable( + name: "Issues"); + + migrationBuilder.DropTable( + name: "PlexServerContent"); + + migrationBuilder.DropTable( + name: "IssueCategory"); + + migrationBuilder.DropTable( + name: "ChildRequests"); + + migrationBuilder.DropTable( + name: "MovieRequests"); + + migrationBuilder.DropTable( + name: "TvRequests"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs new file mode 100644 index 000000000..271c38300 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -0,0 +1,1059 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + partial class OmbiSqliteContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.Designer.cs b/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.Designer.cs new file mode 100644 index 000000000..1e56e9109 --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.Designer.cs @@ -0,0 +1,51 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.SettingsMySql +{ + [DbContext(typeof(SettingsMySqlContext))] + [Migration("20191103205915_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.cs b/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.cs new file mode 100644 index 000000000..1639ed945 --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.SettingsMySql +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicationConfiguration", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Type = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationConfiguration", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "GlobalSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Content = table.Column(nullable: true), + SettingsName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GlobalSettings", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicationConfiguration"); + + migrationBuilder.DropTable( + name: "GlobalSettings"); + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsMySql/SettingsMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/SettingsMySql/SettingsMySqlContextModelSnapshot.cs new file mode 100644 index 000000000..a3dab1d12 --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsMySql/SettingsMySqlContextModelSnapshot.cs @@ -0,0 +1,49 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.SettingsMySql +{ + [DbContext(typeof(SettingsMySqlContext))] + partial class SettingsMySqlContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.Designer.cs b/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.Designer.cs new file mode 100644 index 000000000..7cd132758 --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.Designer.cs @@ -0,0 +1,50 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.SettingsSqlite +{ + [DbContext(typeof(SettingsSqliteContext))] + [Migration("20191103205204_Inital")] + partial class Inital + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.cs b/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.cs new file mode 100644 index 000000000..c4883a99b --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.SettingsSqlite +{ + public partial class Inital : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicationConfiguration", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Type = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationConfiguration", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "GlobalSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Content = table.Column(nullable: true), + SettingsName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GlobalSettings", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicationConfiguration"); + + migrationBuilder.DropTable( + name: "GlobalSettings"); + } + } +} diff --git a/src/Ombi.Store/Migrations/SettingsSqlite/SettingsSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/SettingsSqlite/SettingsSqliteContextModelSnapshot.cs new file mode 100644 index 000000000..17b521507 --- /dev/null +++ b/src/Ombi.Store/Migrations/SettingsSqlite/SettingsSqliteContextModelSnapshot.cs @@ -0,0 +1,48 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.SettingsSqlite +{ + [DbContext(typeof(SettingsSqliteContext))] + partial class SettingsSqliteContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index dd13d5ea7..a5cc7b1ab 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -15,9 +15,10 @@ + - + diff --git a/src/Ombi.Store/Repository/ApplicationConfigRepository.cs b/src/Ombi.Store/Repository/ApplicationConfigRepository.cs index 31ec3313c..c05b91b45 100644 --- a/src/Ombi.Store/Repository/ApplicationConfigRepository.cs +++ b/src/Ombi.Store/Repository/ApplicationConfigRepository.cs @@ -8,12 +8,12 @@ namespace Ombi.Store.Repository { public class ApplicationConfigRepository : IApplicationConfigRepository { - public ApplicationConfigRepository(ISettingsContext ctx) + public ApplicationConfigRepository(SettingsContext ctx) { Ctx = ctx; } - private ISettingsContext Ctx { get; } + private SettingsContext Ctx { get; } public Task GetAsync(ConfigurationTypes type) { diff --git a/src/Ombi.Store/Repository/AuditRepository.cs b/src/Ombi.Store/Repository/AuditRepository.cs index 858cd0eaf..2892e3e84 100644 --- a/src/Ombi.Store/Repository/AuditRepository.cs +++ b/src/Ombi.Store/Repository/AuditRepository.cs @@ -9,12 +9,12 @@ namespace Ombi.Store.Repository { public class AuditRepository : IAuditRepository { - public AuditRepository(IOmbiContext ctx) + public AuditRepository(OmbiContext ctx) { Ctx = ctx; } - private IOmbiContext Ctx { get; } + private OmbiContext Ctx { get; } public async Task Record(AuditType type, AuditArea area, string description) diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 14b871a12..2df4d3467 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -13,7 +13,7 @@ using Polly; namespace Ombi.Store.Repository { - public class BaseRepository : IRepository where T : Entity where U : IDbContext + public class BaseRepository : IRepository where T : Entity where U : DbContext { public BaseRepository(U ctx) { @@ -107,25 +107,25 @@ namespace Ombi.Store.Repository } - private bool _disposed; - // Protected implementation of Dispose pattern. - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; + //private bool _disposed; + //// Protected implementation of Dispose pattern. + //protected virtual void Dispose(bool disposing) + //{ + // if (_disposed) + // return; - if (disposing) - { - _ctx?.Dispose(); - } + // if (disposing) + // { + // _ctx?.Dispose(); + // } - _disposed = true; - } + // _disposed = true; + //} - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + //public void Dispose() + //{ + // Dispose(true); + // GC.SuppressFinalize(this); + //} } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index 2ada709ab..f8743e30f 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -38,12 +38,12 @@ namespace Ombi.Store.Repository public class EmbyContentRepository : ExternalRepository, IEmbyContentRepository { - public EmbyContentRepository(IExternalContext db):base(db) + public EmbyContentRepository(ExternalContext db):base(db) { Db = db; } - private IExternalContext Db { get; } + private ExternalContext Db { get; } public async Task GetByImdbId(string imdbid) diff --git a/src/Ombi.Store/Repository/ExternalRepository.cs b/src/Ombi.Store/Repository/ExternalRepository.cs index d7494afd4..7c0551b8c 100644 --- a/src/Ombi.Store/Repository/ExternalRepository.cs +++ b/src/Ombi.Store/Repository/ExternalRepository.cs @@ -3,9 +3,9 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class ExternalRepository : BaseRepository, IExternalRepository where T : Entity + public class ExternalRepository : BaseRepository, IExternalRepository where T : Entity { - public ExternalRepository(IExternalContext ctx) : base(ctx) + public ExternalRepository(ExternalContext ctx) : base(ctx) { } } diff --git a/src/Ombi.Store/Repository/IExternalRepository.cs b/src/Ombi.Store/Repository/IExternalRepository.cs index de8b6db67..b22cb5ea8 100644 --- a/src/Ombi.Store/Repository/IExternalRepository.cs +++ b/src/Ombi.Store/Repository/IExternalRepository.cs @@ -9,7 +9,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IExternalRepository : IDisposable where T : Entity + public interface IExternalRepository where T : Entity { Task Find(object key); IQueryable GetAll(); diff --git a/src/Ombi.Store/Repository/IRepository.cs b/src/Ombi.Store/Repository/IRepository.cs index 810b586a3..fd7dcc86d 100644 --- a/src/Ombi.Store/Repository/IRepository.cs +++ b/src/Ombi.Store/Repository/IRepository.cs @@ -9,7 +9,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IRepository : IDisposable where T : Entity + public interface IRepository where T : Entity { Task Find(object key); IQueryable GetAll(); diff --git a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs index 8f3968dc0..b226f9e08 100644 --- a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs +++ b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs @@ -11,12 +11,12 @@ namespace Ombi.Store.Repository { public class NotificationTemplatesRepository : INotificationTemplatesRepository { - public NotificationTemplatesRepository(IOmbiContext ctx) + public NotificationTemplatesRepository(OmbiContext ctx) { Db = ctx; } - private IOmbiContext Db { get; } + private OmbiContext Db { get; } public IQueryable All() { diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 37275a47c..1d53874a1 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -39,12 +39,12 @@ namespace Ombi.Store.Repository public class PlexServerContentRepository : ExternalRepository, IPlexContentRepository { - public PlexServerContentRepository(IExternalContext db) : base(db) + public PlexServerContentRepository(ExternalContext db) : base(db) { Db = db; } - private IExternalContext Db { get; } + private ExternalContext Db { get; } public async Task ContentExists(string providerId) diff --git a/src/Ombi.Store/Repository/Repository.cs b/src/Ombi.Store/Repository/Repository.cs index 9d49ded58..fd634e29a 100644 --- a/src/Ombi.Store/Repository/Repository.cs +++ b/src/Ombi.Store/Repository/Repository.cs @@ -3,9 +3,9 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class Repository : BaseRepository, IRepository where T : Entity + public class Repository : BaseRepository, IRepository where T : Entity { - public Repository(IOmbiContext ctx) : base(ctx) + public Repository(OmbiContext ctx) : base(ctx) { } } diff --git a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs index 10c7ace68..56fdb6fba 100644 --- a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs @@ -8,7 +8,7 @@ namespace Ombi.Store.Repository.Requests { public interface ITvRequestRepository { - IOmbiContext Db { get; } + OmbiContext Db { get; } Task Add(TvRequests request); Task AddChild(ChildRequests request); Task Delete(TvRequests request); diff --git a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs index 0b826c1fc..bbf52c7f0 100644 --- a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs @@ -11,12 +11,12 @@ namespace Ombi.Store.Repository.Requests { public class MovieRequestRepository : Repository, IMovieRequestRepository { - public MovieRequestRepository(IOmbiContext ctx) : base(ctx) + public MovieRequestRepository(OmbiContext ctx) : base(ctx) { Db = ctx; } - private IOmbiContext Db { get; } + private OmbiContext Db { get; } public async Task GetRequestAsync(int theMovieDbId) { diff --git a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs index 971d53b39..95f855ef6 100644 --- a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs @@ -11,12 +11,12 @@ namespace Ombi.Store.Repository.Requests { public class MusicRequestRepository : Repository, IMusicRequestRepository { - public MusicRequestRepository(IOmbiContext ctx) : base(ctx) + public MusicRequestRepository(OmbiContext ctx) : base(ctx) { Db = ctx; } - private IOmbiContext Db { get; } + private OmbiContext Db { get; } public Task GetRequestAsync(string foreignAlbumId) { diff --git a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index 7cf727414..985f464fd 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -9,14 +9,14 @@ using Ombi.Store.Entities.Requests; namespace Ombi.Store.Repository.Requests { - public class TvRequestRepository : BaseRepository, ITvRequestRepository + public class TvRequestRepository : BaseRepository, ITvRequestRepository { - public TvRequestRepository(IOmbiContext ctx) : base(ctx) + public TvRequestRepository(OmbiContext ctx) : base(ctx) { Db = ctx; } - public IOmbiContext Db { get; } + public OmbiContext Db { get; } public async Task GetRequestAsync(int tvDbId) { @@ -123,13 +123,6 @@ namespace Ombi.Store.Repository.Requests await InternalSaveChanges(); } - public async Task Add(TvRequests request) - { - await Db.TvRequests.AddAsync(request); - await InternalSaveChanges(); - return request; - } - public async Task AddChild(ChildRequests request) { await Db.ChildRequests.AddAsync(request); @@ -138,12 +131,6 @@ namespace Ombi.Store.Repository.Requests return request; } - public async Task Delete(TvRequests request) - { - Db.TvRequests.Remove(request); - await InternalSaveChanges(); - } - public async Task DeleteChild(ChildRequests request) { Db.ChildRequests.Remove(request); diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index 622e32997..cceb8cdec 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -12,13 +12,13 @@ namespace Ombi.Store.Repository { public class SettingsJsonRepository : ISettingsRepository { - public SettingsJsonRepository(ISettingsContext ctx, ICacheService mem) + public SettingsJsonRepository(SettingsContext ctx, ICacheService mem) { Db = ctx; _cache = mem; } - private ISettingsContext Db { get; } + private SettingsContext Db { get; } private readonly ICacheService _cache; public GlobalSettings Insert(GlobalSettings entity) diff --git a/src/Ombi.Store/Repository/TokenRepository.cs b/src/Ombi.Store/Repository/TokenRepository.cs index 4e35b0aa8..300cc10ff 100644 --- a/src/Ombi.Store/Repository/TokenRepository.cs +++ b/src/Ombi.Store/Repository/TokenRepository.cs @@ -8,14 +8,14 @@ using Ombi.Helpers; namespace Ombi.Store.Repository { - public class TokenRepository : BaseRepository, ITokenRepository + public class TokenRepository : BaseRepository, ITokenRepository { - public TokenRepository(IOmbiContext db) : base(db) + public TokenRepository(OmbiContext db) : base(db) { Db = db; } - private IOmbiContext Db { get; } + private OmbiContext Db { get; } public async Task CreateToken(Tokens token) { diff --git a/src/Ombi.Store/Repository/UserRepository.cs b/src/Ombi.Store/Repository/UserRepository.cs index d3217aea1..c85e083ad 100644 --- a/src/Ombi.Store/Repository/UserRepository.cs +++ b/src/Ombi.Store/Repository/UserRepository.cs @@ -36,12 +36,12 @@ namespace Ombi.Store.Repository { //public class UserRepository : IUserRepository //{ - // public UserRepository(IOmbiContext ctx) + // public UserRepository(OmbiContext ctx) // { // Db = ctx; // } - // private IOmbiContext Db { get; } + // private OmbiContext Db { get; } // public async Task GetUser(string username) // { diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 43d8b02c1..16ff4ce92 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -21,5 +21,7 @@ namespace Ombi.Api.TheMovieDb Task GetTVInfo(string themoviedbid); Task> SearchByActor(string searchTerm, string langCode); Task GetActorMovieCredits(int actorId, string langCode); + Task> SearchKeyword(string searchTerm); + Task GetKeyword(int keywordId); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/Keyword.cs b/src/Ombi.TheMovieDbApi/Models/Keyword.cs new file mode 100644 index 000000000..770eebc94 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/Keyword.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; + +namespace Ombi.Api.TheMovieDb.Models +{ + public sealed class Keyword + { + [DataMember(Name = "id")] + public int Id { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + } +} diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 79ccc5bb7..a55bdadeb 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,31 +1,37 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using AutoMapper; +using Nito.AsyncEx; using Ombi.Api.TheMovieDb.Models; -using Ombi.Helpers; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; using Ombi.TheMovieDbApi.Models; namespace Ombi.Api.TheMovieDb { public class TheMovieDbApi : IMovieDbApi { - public TheMovieDbApi(IMapper mapper, IApi api) + public TheMovieDbApi(IMapper mapper, IApi api, ISettingsService settingsService) { Api = api; Mapper = mapper; + Settings = new AsyncLazy(() => settingsService.GetSettingsAsync()); } + private const string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; + private const string BaseUri ="http://api.themoviedb.org/3/"; private IMapper Mapper { get; } - private readonly string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; - private static readonly string BaseUri ="http://api.themoviedb.org/3/"; private IApi Api { get; } + private AsyncLazy Settings { get; } public async Task GetMovieInformation(int movieId) { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); var result = await Api.Request(request); @@ -35,7 +41,7 @@ namespace Ombi.Api.TheMovieDb public async Task Find(string externalId, ExternalSource source) { var request = new Request($"find/{externalId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); request.AddQueryString("external_source", source.ToString()); @@ -46,9 +52,11 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchByActor(string searchTerm, string langCode) { var request = new Request($"search/person", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); var result = await Api.Request>(request); return result; @@ -57,8 +65,8 @@ namespace Ombi.Api.TheMovieDb public async Task GetActorMovieCredits(int actorId, string langCode) { var request = new Request($"person/{actorId}/movie_credits", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); var result = await Api.Request(request); return result; @@ -67,8 +75,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchTv(string searchTerm) { var request = new Request($"search/tv", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); AddRetry(request); var result = await Api.Request>(request); @@ -78,7 +86,7 @@ namespace Ombi.Api.TheMovieDb public async Task GetTvExternals(int theMovieDbId) { var request = new Request($"/tv/{theMovieDbId}/external_ids", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); @@ -87,9 +95,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SimilarMovies(int movieId, string langCode) { var request = new Request($"movie/{movieId}/similar", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request>(request); @@ -99,65 +106,113 @@ namespace Ombi.Api.TheMovieDb public async Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en") { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("append_to_response", "videos,release_dates"); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("append_to_response", "videos,release_dates"); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request(request); return Mapper.Map(result); } - public async Task> SearchMovie(string searchTerm, int? year, string langageCode) + public async Task> SearchMovie(string searchTerm, int? year, string langCode) { var request = new Request($"search/movie", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); if (year.HasValue && year.Value > 0) { - request.FullUri = request.FullUri.AddQueryParameter("year", year.Value.ToString()); + request.AddQueryString("year", year.Value.ToString()); } + + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> PopularMovies(string langageCode) + /// + /// Maintains filter parity with /movie/popular. + /// + public async Task> PopularMovies(string langCode) { - var request = new Request($"movie/popular", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("sort_by", "popularity.desc"); + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> TopRated(string langageCode) + /// + /// Maintains filter parity with /movie/top_rated. + /// + public async Task> TopRated(string langCode) { - var request = new Request($"movie/top_rated", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("sort_by", "vote_average.desc"); + + // `vote_count` consideration isn't explicitly documented, but using only the `sort_by` filter + // does not provide the same results as `/movie/top_rated`. This appears to be adequate enough + // to filter out extremely high-rated movies due to very little votes + request.AddQueryString("vote_count.gte", "250"); + + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> Upcoming(string langageCode) + /// + /// Maintains filter parity with /movie/upcoming. + /// + public async Task> Upcoming(string langCode) { - var request = new Request($"movie/upcoming", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + + // Release types "2 or 3" explicitly stated as used in docs + request.AddQueryString("with_release_type", "2|3"); + + // The date range being used in `/movie/upcoming` isn't documented, but we infer it is + // an offset from today based on the minimum and maximum date they provide in the output + var startDate = DateTime.Today.AddDays(7); + request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); + + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> NowPlaying(string langageCode) + /// + /// Maintains filter parity with /movie/now_playing. + /// + public async Task> NowPlaying(string langCode) { - var request = new Request($"movie/now_playing", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + + // Release types "2 or 3" explicitly stated as used in docs + request.AddQueryString("with_release_type", "2|3"); + + // The date range being used in `/movie/now_playing` isn't documented, but we infer it is + // an offset from today based on the minimum and maximum date they provide in the output + var today = DateTime.Today; + request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); + + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -166,11 +221,43 @@ namespace Ombi.Api.TheMovieDb public async Task GetTVInfo(string themoviedbid) { var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); } + + public async Task> SearchKeyword(string searchTerm) + { + var request = new Request("search/keyword", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + AddRetry(request); + + var result = await Api.Request>(request); + return result.results ?? new List(); + } + + public async Task GetKeyword(int keywordId) + { + var request = new Request($"keyword/{keywordId}", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + AddRetry(request); + + var keyword = await Api.Request(request); + return keyword == null || keyword.Id == 0 ? null : keyword; + } + + private async Task AddDiscoverMovieSettings(Request request) + { + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + if (settings.ExcludedKeywordIds?.Any() == true) + { + request.AddQueryString("without_keywords", string.Join(",", settings.ExcludedKeywordIds)); + } + } + private static void AddRetry(Request request) { request.Retry = true; diff --git a/src/Ombi.sln b/src/Ombi.sln index f4f683c11..e71c1a30c 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2027 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.87 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}" EndProject @@ -100,6 +100,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Helpers.Tests", "Ombi. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Gotify", "Ombi.Api.Gotify\Ombi.Api.Gotify.csproj", "{105EA346-766E-45B8-928B-DE6991DCB7EB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Webhook", "Ombi.Api.Webhook\Ombi.Api.Webhook.csproj", "{E2186FDA-D827-4781-8663-130AC382F12C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -262,6 +264,10 @@ Global {105EA346-766E-45B8-928B-DE6991DCB7EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {105EA346-766E-45B8-928B-DE6991DCB7EB}.Release|Any CPU.ActiveCfg = Release|Any CPU {105EA346-766E-45B8-928B-DE6991DCB7EB}.Release|Any CPU.Build.0 = Release|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -300,6 +306,7 @@ Global {4FA21A20-92F4-462C-B929-2C517A88CC56} = {9293CA11-360A-4C20-A674-B9E794431BF5} {CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {105EA346-766E-45B8-928B-DE6991DCB7EB} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {E2186FDA-D827-4781-8663-130AC382F12C} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 08c153f31..d0d4e2a81 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -127,6 +127,9 @@
  • English
  • +
  • + Español +
  • Français
  • @@ -139,9 +142,6 @@
  • Italiano
  • -
  • - Español -
  • Nederlands
  • @@ -157,6 +157,9 @@
  • Svenska
  • +
  • + Slovak +
  • diff --git a/src/Ombi/ClientApp/app/app.component.ts b/src/Ombi/ClientApp/app/app.component.ts index 7005f147c..3c235ba1a 100644 --- a/src/Ombi/ClientApp/app/app.component.ts +++ b/src/Ombi/ClientApp/app/app.component.ts @@ -43,13 +43,13 @@ export class AppComponent implements OnInit { __webpack_public_path__ = base + "/dist/"; } - this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sv", "no", "pl", "pt"]); + this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sk", "sv", "no", "pl", "pt"]); // this language will be used as a fallback when a translation isn't found in the current language this.translate.setDefaultLang("en"); // See if we can match the supported langs with the current browser lang const browserLang: string = translate.getBrowserLang(); - this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sv|no|pl|pt/) ? browserLang : "en"); + this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sk|sv|no|pl|pt/) ? browserLang : "en"); } public ngOnInit() { diff --git a/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts b/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts new file mode 100644 index 000000000..63443ae4c --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts @@ -0,0 +1,4 @@ +export interface IMovieDbKeyword { + id: number; + name: string; +} diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index 5472a6c7c..bda18c4ed 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -101,6 +101,11 @@ export interface IGotifyNotificationSettings extends INotificationSettings { priority: number; } +export interface IWebhookNotificationSettings extends INotificationSettings { + webhookUrl: string; + applicationToken: string; +} + export interface IMattermostNotifcationSettings extends INotificationSettings { webhookUrl: string; username: string; diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 75aaf7605..4af153535 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -192,6 +192,13 @@ export interface IAbout { osDescription: string; processArchitecture: string; applicationBasePath: string; + ombiDatabaseType: string; + externalDatabaseType: string; + settingsDatabaseType: string; + ombiConnectionString: string; + externalConnectionString: string; + settingsConnectionString: string; + storagePath: string; } export interface ICouchPotatoSettings extends IExternalSettings { @@ -245,3 +252,8 @@ export interface IVoteSettings extends ISettings { musicVoteMax: number; tvShowVoteMax: number; } + +export interface ITheMovieDbSettings extends ISettings { + showAdultMovies: boolean; + excludedKeywordIds: number[]; +} diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index e1cf823e8..24eac0093 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -3,6 +3,7 @@ export * from "./ICouchPotato"; export * from "./IImages"; export * from "./IMediaServerStatus"; export * from "./INotificationSettings"; +export * from "./IMovieDb"; export * from "./IPlex"; export * from "./IRadarr"; export * from "./IRequestEngineResult"; diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 957ced058..a5896a373 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -145,7 +145,7 @@ export class LoginComponent implements OnDestroy, OnInit { this.pinTimer = setInterval(() => { this.notify.info("Authenticating", "Loading... Please Wait"); this.getPinResult(x.pinId); - }, 10000); + }, 4000); }); }); } diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index ed669e0f5..30507d004 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -1,30 +1,41 @@ 
    + +
    + + + +
    +
    +
    - +
    -
    - - - +
    +
    -
    + +
    + +
    +
    diff --git a/src/Ombi/ClientApp/app/search/search.component.scss b/src/Ombi/ClientApp/app/search/search.component.scss index b8339bd82..52ff70f0b 100644 --- a/src/Ombi/ClientApp/app/search/search.component.scss +++ b/src/Ombi/ClientApp/app/search/search.component.scss @@ -3,7 +3,7 @@ padding-top: 5% } .form-control-search { - width: 77%; + padding-right: 165px; } } diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 5975abb0d..86ee7c24c 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -1,32 +1,44 @@ 
    diff --git a/src/Ombi/ClientApp/app/services/applications/index.ts b/src/Ombi/ClientApp/app/services/applications/index.ts index 295a53415..28edca151 100644 --- a/src/Ombi/ClientApp/app/services/applications/index.ts +++ b/src/Ombi/ClientApp/app/services/applications/index.ts @@ -7,3 +7,4 @@ export * from "./tester.service"; export * from "./plexoauth.service"; export * from "./plextv.service"; export * from "./lidarr.service"; +export * from "./themoviedb.service"; diff --git a/src/Ombi/ClientApp/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index af619d583..5b7a4cd63 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -24,6 +24,7 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + IWebhookNotificationSettings, } from "../../interfaces"; @Injectable() @@ -48,6 +49,10 @@ export class TesterService extends ServiceHelpers { return this.http.post(`${this.url}gotify`, JSON.stringify(settings), { headers: this.headers }); } + public webhookTest(settings: IWebhookNotificationSettings): Observable { + return this.http.post(`${this.url}webhook`, JSON.stringify(settings), { headers: this.headers }); + } + public mattermostTest(settings: IMattermostNotifcationSettings): Observable { return this.http.post(`${this.url}mattermost`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts b/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts new file mode 100644 index 000000000..0b5d83278 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts @@ -0,0 +1,25 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient, HttpErrorResponse, HttpParams } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { empty, Observable, throwError } from "rxjs"; +import { catchError } from "rxjs/operators"; + +import { IMovieDbKeyword } from "../../interfaces"; +import { ServiceHelpers } from "../service.helpers"; + +@Injectable() +export class TheMovieDbService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/TheMovieDb", platformLocation); + } + + public getKeywords(searchTerm: string): Observable { + const params = new HttpParams().set("searchTerm", searchTerm); + return this.http.get(`${this.url}/Keywords`, {headers: this.headers, params}); + } + + public getKeyword(keywordId: number): Observable { + return this.http.get(`${this.url}/Keywords/${keywordId}`, { headers: this.headers }) + .pipe(catchError((error: HttpErrorResponse) => error.status === 404 ? empty() : throwError(error))); + } +} diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index a80cfd772..17ba342aa 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -32,9 +32,11 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + ITheMovieDbSettings, IUpdateSettings, IUserManagementSettings, IVoteSettings, + IWebhookNotificationSettings, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -191,6 +193,14 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/gotify`, JSON.stringify(settings), { headers: this.headers }); } + public getWebhookNotificationSettings(): Observable { + return this.http.get(`${this.url}/notifications/webhook`, { headers: this.headers }); + } + public saveWebhookNotificationSettings(settings: IWebhookNotificationSettings): Observable { + return this.http + .post(`${this.url}/notifications/webhook`, JSON.stringify(settings), { headers: this.headers }); + } + public getSlackNotificationSettings(): Observable { return this.http.get(`${this.url}/notifications/slack`, {headers: this.headers}); } @@ -301,6 +311,14 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/vote`, JSON.stringify(settings), {headers: this.headers}); } + public getTheMovieDbSettings(): Observable { + return this.http.get(`${this.url}/themoviedb`, {headers: this.headers}); + } + + public saveTheMovieDbSettings(settings: ITheMovieDbSettings) { + return this.http.post(`${this.url}/themoviedb`, JSON.stringify(settings), {headers: this.headers}); + } + public getNewsletterSettings(): Observable { return this.http.get(`${this.url}/notifications/newsletter`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/about/about.component.html b/src/Ombi/ClientApp/app/settings/about/about.component.html index fc1efde3f..79560a3c3 100644 --- a/src/Ombi/ClientApp/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/app/settings/about/about.component.html @@ -98,6 +98,44 @@ {{about.applicationBasePath}} + + + + Storage Path + + + {{about.storagePath}} + + + + + + Ombi Database + + + {{about.ombiDatabaseType}} - {{about.ombiConnectionString}} + + + + + + + External Database + + + {{about.externalDatabaseType}} - {{about.externalConnectionString}} + + + + + + + Settings Database + + + {{about.settingsDatabaseType}} - {{about.settingsConnectionString}} + +
    diff --git a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html new file mode 100644 index 000000000..ed6eb43b9 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html @@ -0,0 +1,49 @@ + + +
    +
    + Webhook Notifications +
    +
    + +
    +
    + + +
    +
    + +
    + + + + The Webhook URL is required +
    + +
    + + + + The Application Token is required +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts new file mode 100644 index 000000000..d410b2b44 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts @@ -0,0 +1,64 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { INotificationTemplates, IWebhookNotificationSettings, NotificationType } from "../../interfaces"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./webhook.component.html", +}) +export class WebhookComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getWebhookNotificationSettings().subscribe(x => { + this.form = this.fb.group({ + enabled: [x.enabled], + webhookUrl: [x.webhookUrl, [Validators.required]], + applicationToken: [x.applicationToken], + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + + this.settingsService.saveWebhookNotificationSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Webhook settings"); + } else { + this.notificationService.success("There was an error when saving the Webhook settings"); + } + }); + + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.webhookTest(form.value).subscribe(x => { + if (x) { + this.notificationService.success("Successfully sent a Webhook message"); + } else { + this.notificationService.error("There was an error when sending the Webhook message. Please check your settings"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6fb69dc27..3f0979ea0 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -3,13 +3,14 @@ import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; import { NgbAccordionModule, NgbModule } from "@ng-bootstrap/ng-bootstrap"; +import { TagInputModule } from "ngx-chips"; import { ClipboardModule } from "ngx-clipboard"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; import { CouchPotatoService, EmbyService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, - RequestRetryService, SonarrService, TesterService, ValidationService, + RequestRetryService, SonarrService, TesterService, TheMovieDbService, ValidationService, } from "../services"; import { PipeModule } from "../pipes/pipe.module"; @@ -36,11 +37,13 @@ import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; import { SlackComponent } from "./notifications/slack.component"; import { TelegramComponent } from "./notifications/telegram.component"; +import { WebhookComponent } from "./notifications/webhook.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; import { SickRageComponent } from "./sickrage/sickrage.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; +import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { UpdateComponent } from "./update/update.component"; import { UserManagementComponent } from "./usermanagement/usermanagement.component"; import { VoteComponent } from "./vote/vote.component"; @@ -65,6 +68,7 @@ const routes: Routes = [ { path: "Pushover", component: PushoverComponent, canActivate: [AuthGuard] }, { path: "Pushbullet", component: PushbulletComponent, canActivate: [AuthGuard] }, { path: "Gotify", component: GotifyComponent, canActivate: [AuthGuard] }, + { path: "Webhook", component: WebhookComponent, canActivate: [AuthGuard] }, { path: "Mattermost", component: MattermostComponent, canActivate: [AuthGuard] }, { path: "UserManagement", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "Update", component: UpdateComponent, canActivate: [AuthGuard] }, @@ -80,6 +84,7 @@ const routes: Routes = [ { path: "Newsletter", component: NewsletterComponent, canActivate: [AuthGuard] }, { path: "Lidarr", component: LidarrComponent, canActivate: [AuthGuard] }, { path: "Vote", component: VoteComponent, canActivate: [AuthGuard] }, + { path: "TheMovieDb", component: TheMovieDbComponent, canActivate: [AuthGuard] }, { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, ]; @@ -97,6 +102,7 @@ const routes: Routes = [ NgbAccordionModule, AutoCompleteModule, CalendarModule, + TagInputModule, ClipboardModule, PipeModule, RadioButtonModule, @@ -120,6 +126,7 @@ const routes: Routes = [ MattermostComponent, PushbulletComponent, GotifyComponent, + WebhookComponent, UserManagementComponent, UpdateComponent, AboutComponent, @@ -135,6 +142,7 @@ const routes: Routes = [ NewsletterComponent, LidarrComponent, VoteComponent, + TheMovieDbComponent, FailedRequestsComponent, ], exports: [ @@ -156,6 +164,7 @@ const routes: Routes = [ NotificationMessageService, LidarrService, RequestRetryService, + TheMovieDbService, ], }) diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index d58c96e2e..eb0f3f4bb 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -13,6 +13,7 @@
  • User Importer
  • Authentication
  • Vote
  • +
  • The Movie Database
  • @@ -75,6 +76,7 @@
  • Mattermost
  • Telegram
  • Gotify
  • +
  • Webhook
  • diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html new file mode 100644 index 000000000..ccadc68ac --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -0,0 +1,50 @@ + + +
    + The Movie Database +
    +
    +
    + + +
    +
    + +
    + + + + + {{item.id}} +  ({{item.name}}) + + + + + + +
    + +
    +
    + +
    +
    +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts new file mode 100644 index 000000000..4fc9138a0 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -0,0 +1,71 @@ +import { Component, OnInit } from "@angular/core"; +import { empty, of } from "rxjs"; + +import { ITheMovieDbSettings } from "../../interfaces"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; +import { TheMovieDbService } from "../../services"; + +interface IKeywordTag { + id: number; + name: string; + initial: boolean; +} + +@Component({ + templateUrl: "./themoviedb.component.html", +}) +export class TheMovieDbComponent implements OnInit { + + public settings: ITheMovieDbSettings; + public excludedKeywords: IKeywordTag[]; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private tmdbService: TheMovieDbService) { } + + public ngOnInit() { + this.settingsService.getTheMovieDbSettings().subscribe(settings => { + this.settings = settings; + this.excludedKeywords = settings.excludedKeywordIds + ? settings.excludedKeywordIds.map(id => ({ + id, + name: "", + initial: true, + })) + : []; + }); + } + + public autocompleteKeyword = (text: string) => this.tmdbService.getKeywords(text); + + public onAddingKeyword = (tag: string | IKeywordTag) => { + if (typeof tag === "string") { + const id = Number(tag); + return isNaN(id) ? empty() : this.tmdbService.getKeyword(id); + } else { + return of(tag); + } + } + + public onKeywordSelect = (keyword: IKeywordTag) => { + if (keyword.initial) { + this.tmdbService.getKeyword(keyword.id) + .subscribe(k => { + keyword.name = k.name; + keyword.initial = false; + }); + } + } + + public save() { + this.settings.excludedKeywordIds = this.excludedKeywords.map(k => k.id); + this.settingsService.saveTheMovieDbSettings(this.settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved The Movie Database settings"); + } else { + this.notificationService.success("There was an error when saving The Movie Database settings"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9c7756d8f..764b245ea 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -389,6 +389,27 @@ $border-radius: 10px; padding-right: 105px; } +.search-button-container { + margin-top: 10px; + text-align: center; +} + +@media (max-width: 450px) { + .form-control-search { + padding-right: 0 !important; + } + + .search-button-container-inline { + display: none; + } +} + +@media (min-width: 450px) { + .search-button-container { + display: none; + } +} + .input-group-addon .btn-group { position: absolute; right: 45px; @@ -1010,6 +1031,14 @@ a > h4:hover { width:300px; } +.ng2-tag-input.dark input { + background: transparent; + color: white; +} + +.ng2-tag-input .fa-cloud-download { + margin-right: 5px; +} ::ng-deep ngb-accordion > div.card > div.card-header { padding:0px; diff --git a/src/Ombi/Controllers/External/TesterController.cs b/src/Ombi/Controllers/External/TesterController.cs index 2894542f6..48a8e89db 100644 --- a/src/Ombi/Controllers/External/TesterController.cs +++ b/src/Ombi/Controllers/External/TesterController.cs @@ -40,7 +40,7 @@ namespace Ombi.Controllers.External IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification, - ILidarrApi lidarrApi, IGotifyNotification gotifyNotification) + ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWebhookNotification webhookNotification) { Service = service; DiscordNotification = notification; @@ -62,6 +62,7 @@ namespace Ombi.Controllers.External MobileNotification = mobileNotification; LidarrApi = lidarrApi; GotifyNotification = gotifyNotification; + WebhookNotification = webhookNotification; } private INotificationService Service { get; } @@ -71,6 +72,7 @@ namespace Ombi.Controllers.External private ISlackNotification SlackNotification { get; } private IPushoverNotification PushoverNotification { get; } private IGotifyNotification GotifyNotification { get; } + private IWebhookNotification WebhookNotification { get; } private IMattermostNotification MattermostNotification { get; } private IPlexApi PlexApi { get; } private IRadarrApi RadarrApi { get; } @@ -181,6 +183,30 @@ namespace Ombi.Controllers.External } + /// + /// Sends a test message to configured webhook using the provided settings + /// + /// The settings. + /// + [HttpPost("webhook")] + public bool Webhook([FromBody] WebhookSettings settings) + { + try + { + settings.Enabled = true; + WebhookNotification.NotifyAsync( + new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings); + + return true; + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test your webhook"); + return false; + } + + } + /// /// Sends a test message to mattermost using the provided settings /// diff --git a/src/Ombi/Controllers/External/TheMovieDbController.cs b/src/Ombi/Controllers/External/TheMovieDbController.cs new file mode 100644 index 000000000..714831633 --- /dev/null +++ b/src/Ombi/Controllers/External/TheMovieDbController.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Mvc; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Attributes; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Ombi.Controllers.External +{ + [Admin] + [ApiV1] + [Produces("application/json")] + public sealed class TheMovieDbController : Controller + { + public TheMovieDbController(IMovieDbApi tmdbApi) => TmdbApi = tmdbApi; + + private IMovieDbApi TmdbApi { get; } + + /// + /// Searches for keywords matching the specified term. + /// + /// The search term. + [HttpGet("Keywords")] + public async Task> GetKeywords([FromQuery]string searchTerm) => + await TmdbApi.SearchKeyword(searchTerm); + + /// + /// Gets the keyword matching the specified ID. + /// + /// The keyword ID. + [HttpGet("Keywords/{keywordId}")] + public async Task GetKeywords(int keywordId) + { + var keyword = await TmdbApi.GetKeyword(keywordId); + return keyword == null ? NotFound() : (IActionResult)Ok(keyword); + } + } +} diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index e531ee6bc..76ff4565c 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using AutoMapper; -using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -860,7 +859,7 @@ namespace Ombi.Controllers [HttpPost("welcomeEmail")] [PowerUser] - public void SendWelcomeEmail([FromBody] UserViewModel user) + public async Task SendWelcomeEmail([FromBody] UserViewModel user) { var ombiUser = new OmbiUser { @@ -868,7 +867,8 @@ namespace Ombi.Controllers Email = user.EmailAddress, UserName = user.UserName }; - BackgroundJob.Enqueue(() => WelcomeEmail.SendEmail(ombiUser)); + await WelcomeEmail.SendEmail(ombiUser); + return Ok(); } [HttpGet("accesstoken")] diff --git a/src/Ombi/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index 3c8e9c719..d31aec647 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -6,17 +6,14 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System.Collections.Generic; using System.Linq; -using Hangfire; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Ombi.Attributes; using Ombi.Core; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Models; using Ombi.Notifications.Models; using Ombi.Store.Entities; -using StackExchange.Profiling.Helpers; namespace Ombi.Controllers { @@ -27,7 +24,7 @@ namespace Ombi.Controllers public class IssuesController : ControllerBase { public IssuesController(IRepository categories, IRepository issues, IRepository comments, - UserManager userManager, INotificationService notify) + UserManager userManager, INotificationHelper notify) { _categories = categories; _issues = issues; @@ -40,7 +37,7 @@ namespace Ombi.Controllers private readonly IRepository _issues; private readonly IRepository _issueComments; private readonly UserManager _userManager; - private readonly INotificationService _notification; + private readonly INotificationHelper _notification; /// /// Get's all categories @@ -152,7 +149,7 @@ namespace Ombi.Controllers AddIssueNotificationSubstitutes(notificationModel, i, User.Identity.Name); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return i.Id; } @@ -239,7 +236,7 @@ namespace Ombi.Controllers notificationModel.Recipient = user.Email; } - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return await _issueComments.Add(newComment); } @@ -292,7 +289,7 @@ namespace Ombi.Controllers }; AddIssueNotificationSubstitutes(notificationModel, issue, issue.UserReported?.UserAlias ?? string.Empty); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); } diff --git a/src/Ombi/Controllers/JobController.cs b/src/Ombi/Controllers/JobController.cs index 4171c2fa8..ab4dba5a1 100644 --- a/src/Ombi/Controllers/JobController.cs +++ b/src/Ombi/Controllers/JobController.cs @@ -1,13 +1,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; -using Ombi.Api.Service; using Ombi.Attributes; using Ombi.Helpers; -using Ombi.Schedule; using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Ombi; diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index d5b5e3098..9f043ac8e 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -150,7 +150,7 @@ namespace Ombi.Controllers /// /// Returns similar movies to the movie id passed in /// - /// ID of the movie + /// the movie /// /// We use TheMovieDb as the Movie Provider /// diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index ebc2fbe66..df480865f 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -7,10 +7,8 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using AutoMapper; -using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using NCrontab; using Ombi.Api.Emby; using Ombi.Attributes; using Ombi.Core.Models.UI; @@ -27,7 +25,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Api.Github; using Ombi.Core.Engine; -using Ombi.Schedule; +using Ombi.Extensions; using Quartz; namespace Ombi.Controllers @@ -93,15 +91,25 @@ namespace Ombi.Controllers [HttpGet("about")] public AboutViewModel About() { + var dbConfiguration = DatabaseExtensions.GetDatabaseConfiguration(); + var storage = StoragePathSingleton.Instance; var model = new AboutViewModel { FrameworkDescription = RuntimeInformation.FrameworkDescription, OsArchitecture = RuntimeInformation.OSArchitecture.ToString(), OsDescription = RuntimeInformation.OSDescription, ProcessArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), - ApplicationBasePath =Directory.GetCurrentDirectory() + ApplicationBasePath = Directory.GetCurrentDirectory(), + ExternalConnectionString = dbConfiguration.ExternalDatabase.ConnectionString, + ExternalDatabaseType = dbConfiguration.ExternalDatabase.Type, + OmbiConnectionString = dbConfiguration.OmbiDatabase.ConnectionString, + OmbiDatabaseType = dbConfiguration.OmbiDatabase.Type, + SettingsConnectionString = dbConfiguration.SettingsDatabase.ConnectionString, + SettingsDatabaseType = dbConfiguration.SettingsDatabase.Type, + StoragePath = storage.StoragePath.HasValue() ? storage.StoragePath : "None Specified" }; - + + var version = AssemblyHelper.GetRuntimeVersion(); var productArray = version.Split('-'); model.Version = productArray[0]; @@ -233,8 +241,8 @@ namespace Ombi.Controllers [AllowAnonymous] public async Task GetDefaultLanguage() { - var s = await Get(); - return s.DefaultLanguageCode; + var s = await Get(); + return s.DefaultLanguageCode; } /// @@ -431,7 +439,7 @@ namespace Ombi.Controllers [HttpGet("Update")] public async Task UpdateSettings() { - var settings = await Get(); + var settings = await Get(); return Mapper.Map(settings); } @@ -586,7 +594,7 @@ namespace Ombi.Controllers Message = $"CRON Expression {body.Expression} is not valid" }; } - + model.Success = true; return model; } @@ -659,6 +667,25 @@ namespace Ombi.Controllers return vote.Enabled; } + /// + /// Save The Movie DB settings. + /// + /// The settings. + [HttpPost("themoviedb")] + public async Task TheMovieDbSettings([FromBody]TheMovieDbSettings settings) + { + return await Save(settings); + } + + /// + /// Get The Movie DB settings. + /// + [HttpGet("themoviedb")] + public async Task TheMovieDbSettings() + { + return await Get(); + } + /// /// Saves the email notification settings. /// @@ -980,6 +1007,33 @@ namespace Ombi.Controllers return model; } + /// + /// Saves the webhook notification settings. + /// + /// The model. + /// + [HttpPost("notifications/webhook")] + public async Task WebhookNotificationSettings([FromBody] WebhookNotificationViewModel model) + { + var settings = Mapper.Map(model); + var result = await Save(settings); + + return result; + } + + /// + /// Gets the webhook notification settings. + /// + /// + [HttpGet("notifications/webhook")] + public async Task WebhookNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + return model; + } + /// /// Saves the Newsletter notification settings. /// diff --git a/src/Ombi/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs new file mode 100644 index 000000000..2c6d13d06 --- /dev/null +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -0,0 +1,129 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Ombi.Helpers; +using Ombi.Store.Context; +using Ombi.Store.Context.MySql; +using Ombi.Store.Context.Sqlite; +using SQLitePCL; + +namespace Ombi.Extensions +{ + public static class DatabaseExtensions + { + + public const string SqliteDatabase = "Sqlite"; + public const string MySqlDatabase = "MySQL"; + + public static void ConfigureDatabases(this IServiceCollection services) + { + var configuration = GetDatabaseConfiguration(); + + // Ombi db + switch (configuration.OmbiDatabase.Type) + { + case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureSqlite(x, configuration.OmbiDatabase)); + break; + case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureMySql(x, configuration.OmbiDatabase)); + break; + } + + switch (configuration.ExternalDatabase.Type) + { + case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureSqlite(x, configuration.ExternalDatabase)); + break; + case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureMySql(x, configuration.ExternalDatabase)); + break; + } + + switch (configuration.SettingsDatabase.Type) + { + case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureSqlite(x, configuration.SettingsDatabase)); + break; + case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): + services.AddDbContext(x => ConfigureMySql(x, configuration.SettingsDatabase)); + break; + } + } + + public static DatabaseConfiguration GetDatabaseConfiguration() + { + var i = StoragePathSingleton.Instance; + if (string.IsNullOrEmpty(i.StoragePath)) + { + i.StoragePath = string.Empty; + } + + var databaseFileLocation = Path.Combine(i.StoragePath, "database.json"); + + var configuration = new DatabaseConfiguration(i.StoragePath); + if (File.Exists(databaseFileLocation)) + { + var databaseJson = File.ReadAllText(databaseFileLocation); + if (string.IsNullOrEmpty(databaseJson)) + { + throw new Exception("Found 'database.json' but it was empty!"); + } + + configuration = JsonConvert.DeserializeObject(databaseJson); + } + + return configuration; + } + + public static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + { + SQLitePCL.Batteries.Init(); + SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); + + options.UseSqlite(config.ConnectionString); + } + + public static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + { + options.UseMySql(config.ConnectionString); + } + + public class DatabaseConfiguration + { + public DatabaseConfiguration() + { + + } + + public DatabaseConfiguration(string defaultSqlitePath) + { + OmbiDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "Ombi.db")}"); + SettingsDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiSettings.db")}"); + ExternalDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "OmbiExternal.db")}"); + } + public PerDatabaseConfiguration OmbiDatabase { get; set; } + public PerDatabaseConfiguration SettingsDatabase { get; set; } + public PerDatabaseConfiguration ExternalDatabase { get; set; } + } + + public class PerDatabaseConfiguration + { + public PerDatabaseConfiguration(string type, string connectionString) + { + Type = type; + ConnectionString = connectionString; + } + + // Used in Deserialization + public PerDatabaseConfiguration() + { + + } + public string Type { get; set; } + public string ConnectionString { get; set; } + } + } +} \ No newline at end of file diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/Extensions/StartupExtensions.cs similarity index 100% rename from src/Ombi/StartupExtensions.cs rename to src/Ombi/Extensions/StartupExtensions.cs diff --git a/src/Ombi/SwaggerOperationFilter.cs b/src/Ombi/Extensions/SwaggerOperationFilter.cs similarity index 100% rename from src/Ombi/SwaggerOperationFilter.cs rename to src/Ombi/Extensions/SwaggerOperationFilter.cs diff --git a/src/Ombi/ApiKeyMiddlewear.cs b/src/Ombi/Middleware/ApiKeyMiddlewear.cs similarity index 100% rename from src/Ombi/ApiKeyMiddlewear.cs rename to src/Ombi/Middleware/ApiKeyMiddlewear.cs diff --git a/src/Ombi/ErrorHandlingMiddlewear.cs b/src/Ombi/Middleware/ErrorHandlingMiddlewear.cs similarity index 100% rename from src/Ombi/ErrorHandlingMiddlewear.cs rename to src/Ombi/Middleware/ErrorHandlingMiddlewear.cs diff --git a/src/Ombi/Models/AboutViewModel.cs b/src/Ombi/Models/AboutViewModel.cs index 457cbd44d..93bac4d0c 100644 --- a/src/Ombi/Models/AboutViewModel.cs +++ b/src/Ombi/Models/AboutViewModel.cs @@ -9,5 +9,12 @@ public string OsDescription { get; set; } public string ProcessArchitecture { get; set; } public string ApplicationBasePath { get; set; } + public string OmbiDatabaseType { get; set; } + public string ExternalDatabaseType { get; set; } + public string SettingsDatabaseType { get; set; } + public string OmbiConnectionString { get; set; } + public string ExternalConnectionString { get; set; } + public string SettingsConnectionString { get; set; } + public string StoragePath { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 02e11c84b..b150b0244 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -65,11 +65,6 @@ - - - - - @@ -79,6 +74,7 @@ + diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index dd0baa8d4..8841d1fa8 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -9,13 +9,18 @@ using CommandLine; using CommandLine.Text; using Microsoft.AspNetCore; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Ombi.Extensions; using Ombi.Helpers; +using Ombi.Store.Context.MySql; +using Ombi.Store.Context.Sqlite; namespace Ombi { public class Program { private static string UrlArgs { get; set; } + public static void Main(string[] args) { Console.Title = "Ombi"; @@ -50,236 +55,93 @@ namespace Ombi instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings DeleteSchedules(); - CheckAndMigrate(); - var ctx = new SettingsContext(); - var config = ctx.ApplicationConfigurations.ToList(); - var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); - var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); - if (url == null) - { - url = new ApplicationConfiguration - { - Type = ConfigurationTypes.Url, - Value = "http://*:5000" - }; - using (var tran = ctx.Database.BeginTransaction()) - { - ctx.ApplicationConfigurations.Add(url); - ctx.SaveChanges(); - tran.Commit(); - } + //CheckAndMigrate(); - urlValue = url.Value; - } - if (!url.Value.Equals(host)) + var services = new ServiceCollection(); + services.ConfigureDatabases(); + using (var provider = services.BuildServiceProvider()) { - url.Value = UrlArgs; + var settingsDb = provider.GetRequiredService(); - using (var tran = ctx.Database.BeginTransaction()) - { - ctx.SaveChanges(); - tran.Commit(); - } - - urlValue = url.Value; - } - - if (dbBaseUrl == null) - { - if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + var config = settingsDb.ApplicationConfigurations.ToList(); + var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); + var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); + if (url == null) { - dbBaseUrl = new ApplicationConfiguration + url = new ApplicationConfiguration { - Type = ConfigurationTypes.BaseUrl, - Value = baseUrl + Type = ConfigurationTypes.Url, + Value = "http://*:5000" }; - - using (var tran = ctx.Database.BeginTransaction()) + using (var tran = settingsDb.Database.BeginTransaction()) { - ctx.ApplicationConfigurations.Add(dbBaseUrl); - ctx.SaveChanges(); + settingsDb.ApplicationConfigurations.Add(url); + settingsDb.SaveChanges(); tran.Commit(); } - } - } - else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) - { - dbBaseUrl.Value = baseUrl; - using (var tran = ctx.Database.BeginTransaction()) - { - ctx.SaveChanges(); - tran.Commit(); + urlValue = url.Value; } - } - Console.WriteLine($"We are running on {urlValue}"); - - CreateWebHostBuilder(args).Build().Run(); - } - - private static void DeleteSchedules() - { - try - { - if (File.Exists("Schedules.db")) + if (!url.Value.Equals(host)) { - File.Delete("Schedules.db"); - } - } - catch (Exception) - { - } - } + url.Value = UrlArgs; - /// - /// This is to remove the Settings from the Ombi.db to the "new" - /// OmbiSettings.db - /// - /// Ombi is hitting a limitation with SQLite where there is a lot of database activity - /// and SQLite does not handle concurrency at all, causing db locks. - /// - /// Splitting it all out into it's own DB helps with this. - /// - private static void CheckAndMigrate() - { - var doneGlobal = false; - var doneConfig = false; - var ombi = new OmbiContext(); - var settings = new SettingsContext(); + using (var tran = settingsDb.Database.BeginTransaction()) + { + settingsDb.SaveChanges(); + tran.Commit(); + } - try - { + urlValue = url.Value; + } - using (var tran = settings.Database.BeginTransaction()) + if (dbBaseUrl == null) { - if (ombi.Settings.Any() && !settings.Settings.Any()) + if (baseUrl.HasValue() && baseUrl.StartsWith("/")) { - // OK migrate it! - var allSettings = ombi.Settings.ToList(); - settings.Settings.AddRange(allSettings); - doneGlobal = true; - } + dbBaseUrl = new ApplicationConfiguration + { + Type = ConfigurationTypes.BaseUrl, + Value = baseUrl + }; - // Check for any application settings + using (var tran = settingsDb.Database.BeginTransaction()) + { + settingsDb.ApplicationConfigurations.Add(dbBaseUrl); + settingsDb.SaveChanges(); + tran.Commit(); + } + } + } + else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) + { + dbBaseUrl.Value = baseUrl; - if (ombi.ApplicationConfigurations.Any() && !settings.ApplicationConfigurations.Any()) + using (var tran = settingsDb.Database.BeginTransaction()) { - // OK migrate it! - var allSettings = ombi.ApplicationConfigurations.ToList(); - settings.ApplicationConfigurations.AddRange(allSettings); - doneConfig = true; + settingsDb.SaveChanges(); + tran.Commit(); } - - settings.SaveChanges(); - tran.Commit(); } - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } + Console.WriteLine($"We are running on {urlValue}"); - using (var tran = ombi.Database.BeginTransaction()) - { - // Now delete the old stuff - if (doneGlobal) - ombi.Database.ExecuteSqlCommand("DELETE FROM GlobalSettings"); - if (doneConfig) - ombi.Database.ExecuteSqlCommand("DELETE FROM ApplicationConfiguration"); - tran.Commit(); + CreateWebHostBuilder(args).Build().Run(); } + } - // Now migrate all the external stuff - var external = new ExternalContext(); - + private static void DeleteSchedules() + { try { - - using (var tran = external.Database.BeginTransaction()) + if (File.Exists("Schedules.db")) { - if (ombi.PlexEpisode.Any()) - { - external.PlexEpisode.AddRange(ombi.PlexEpisode.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM PlexEpisode"); - } - - if (ombi.PlexSeasonsContent.Any()) - { - external.PlexSeasonsContent.AddRange(ombi.PlexSeasonsContent.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM PlexSeasonsContent"); - } - - if (ombi.PlexServerContent.Any()) - { - external.PlexServerContent.AddRange(ombi.PlexServerContent.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM PlexServerContent"); - } - - if (ombi.EmbyEpisode.Any()) - { - external.EmbyEpisode.AddRange(ombi.EmbyEpisode.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyEpisode"); - } - - if (ombi.EmbyContent.Any()) - { - external.EmbyContent.AddRange(ombi.EmbyContent.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyContent"); - } - - if (ombi.RadarrCache.Any()) - { - external.RadarrCache.AddRange(ombi.RadarrCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM RadarrCache"); - } - - if (ombi.SonarrCache.Any()) - { - external.SonarrCache.AddRange(ombi.SonarrCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM SonarrCache"); - } - - if (ombi.LidarrAlbumCache.Any()) - { - external.LidarrAlbumCache.AddRange(ombi.LidarrAlbumCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrAlbumCache"); - } - - if (ombi.LidarrArtistCache.Any()) - { - external.LidarrArtistCache.AddRange(ombi.LidarrArtistCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrArtistCache"); - } - - if (ombi.SickRageEpisodeCache.Any()) - { - external.SickRageEpisodeCache.AddRange(ombi.SickRageEpisodeCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageEpisodeCache"); - } - - if (ombi.SickRageCache.Any()) - { - external.SickRageCache.AddRange(ombi.SickRageCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageCache"); - } - - if (ombi.CouchPotatoCache.Any()) - { - external.CouchPotatoCache.AddRange(ombi.CouchPotatoCache.ToList()); - ombi.Database.ExecuteSqlCommand("DELETE FROM CouchPotatoCache"); - } - - external.SaveChanges(); - tran.Commit(); + File.Delete("Schedules.db"); } } - catch (Exception e) + catch (Exception) { - Console.WriteLine(e); - throw; } } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index c353bcf6a..56e19bb11 100755 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -2,10 +2,6 @@ using System.IO; using AutoMapper; using AutoMapper.EquivalencyExpression; -using Hangfire; -using Hangfire.Dashboard; -using Hangfire.MemoryStorage; -using Hangfire.SQLite; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpOverrides; @@ -19,6 +15,7 @@ using Microsoft.Extensions.Logging; using Ombi.Core.Authentication; using Ombi.Core.Settings; using Ombi.DependencyInjection; +using Ombi.Extensions; using Ombi.Helpers; using Ombi.Mapping; using Ombi.Schedule; @@ -73,7 +70,7 @@ namespace Ombi options.User.AllowedUserNameCharacters = string.Empty; }); - + services.ConfigureDatabases(); services.AddHealthChecks(); services.AddMemoryCache(); @@ -92,14 +89,6 @@ namespace Ombi services.AddSwagger(); services.AddAppSettingsValues(Configuration); - services.AddHangfire(x => - { - x.UseMemoryStorage(); - x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); - }); - - SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); - services.AddCors(o => o.AddPolicy("MyPolicy", builder => { builder.AllowAnyOrigin() @@ -122,7 +111,7 @@ namespace Ombi app.UseQuartz().GetAwaiter().GetResult(); - var ctx = serviceProvider.GetService(); + var ctx = serviceProvider.GetService(); loggerFactory.AddSerilog(); app.UseHealthChecks("/health"); @@ -176,26 +165,12 @@ namespace Ombi app.UsePathBase(settings.BaseUrl); } - app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); - if (env.IsDevelopment()) - { - app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire", - new DashboardOptions - { - Authorization = new[] { new HangfireAuthorizationFilter() } - }); - } - - GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 3 }); - - // Setup the scheduler + // Setup the scheduler //var jobSetup = app.ApplicationServices.GetService(); //jobSetup.Setup(); ctx.Seed(); - var settingsctx = serviceProvider.GetService(); - var externalctx = serviceProvider.GetService(); + var settingsctx = serviceProvider.GetService(); settingsctx.Seed(); - externalctx.Seed(); var provider = new FileExtensionContentTypeProvider { Mappings = { [".map"] = "application/octet-stream" } }; @@ -235,12 +210,4 @@ namespace Ombi }); } } - - public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter - { - public bool Authorize(DashboardContext context) - { - return true; - } - } } diff --git a/src/Ombi/package.json b/src/Ombi/package.json index acd432418..47ddb1fd2 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -63,6 +63,7 @@ "natives": "1.1.6", "ng2-cookies": "^1.0.12", "ngx-bootstrap": "^3.1.4", + "ngx-chips": "^2.1.0", "ngx-clipboard": "^11.1.1", "ngx-editor": "^4.1.0", "ngx-infinite-scroll": "^6.0.1", diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json new file mode 100644 index 000000000..d7c3e376a --- /dev/null +++ b/src/Ombi/wwwroot/translations/sk.json @@ -0,0 +1,186 @@ +{ + "Login": { + "SignInButton": "Prihláste sa", + "UsernamePlaceholder": "Užívateľské meno", + "PasswordPlaceholder": "Heslo", + "RememberMe": "Zapamätať prihlásenie", + "ForgottenPassword": "Zabudli ste heslo?", + "Errors": { + "IncorrectCredentials": "Nesprávne meno alebo heslo" + } + }, + "Common": { + "ContinueButton": "Pokračovať", + "Available": "Dostupné", + "PartiallyAvailable": "Čiastočne dostupné", + "Monitored": "Sledované", + "NotAvailable": "Nie je k dispozícii", + "ProcessingRequest": "Spracovávanie požiadavky", + "PendingApproval": "Čaká na schválenie", + "RequestDenied": "Požiadavka zamietnutá", + "NotRequested": "Nepožiadané", + "Requested": "Požiadané", + "Request": "Požiadať", + "Denied": "Zamietnuté", + "Approve": "Schválené", + "PartlyAvailable": "Čiastočne dostupné", + "Errors": { + "Validation": "Skontrolujte zadaný obsah" + } + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Emailová adresa", + "ResetPasswordButton": "Nastaviť nové heslo" + }, + "LandingPage": { + "OnlineHeading": "Momentálne online", + "OnlineParagraph": "Mediálny server je momentálne online", + "PartiallyOnlineHeading": "Čiastočne online", + "PartiallyOnlineParagraph": "Mediálny server je momentálne online.", + "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} serverov offline z {{totalServers}}.", + "SingleServerUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", + "OfflineHeading": "Momentálne offline", + "OfflineParagraph": "Mediálny server je momentálne offline.", + "CheckPageForUpdates": "Prezrite túto stránku pre aktualizácie." + }, + "NavigationBar": { + "Search": "Hľadať", + "Requests": "Požiadavky", + "UserManagement": "Správa užívateľov", + "Issues": "Problémy", + "Vote": "Hlasovať", + "Donate": "Prispieť!", + "DonateLibraryMaintainer": "Darovať správcovi knižnice", + "DonateTooltip": "Takto som presvedčil svoju manželku, aby mi umožnila tráviť svoj voľný čas vývojom Ombi ;)", + "UpdateAvailableTooltip": "K dispozícii je aktualizácia!", + "Settings": "Nastavenie", + "Welcome": "Vitaj {{username}}", + "UpdateDetails": "Aktualizovať údaje", + "Logout": "Odhlásiť sa", + "OpenMobileApp": "Otvoriť mobilnú aplikáciu", + "RecentlyAdded": "Nedávno pridané" + }, + "Search": { + "Title": "Hľadať", + "Paragraph": "Chcete sledovať niečo, čo v súčasnosti nie je k dispozícii? Žiadny problém. Vyhľadajte to nižšie a požiadajte o to!", + "MoviesTab": "Filmy", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "Suggestions": "Návrhy", + "NoResults": "Ľutujeme, nenašli sme žiadne výsledky!", + "DigitalDate": "Online vydanie: {{date}}", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ViewOnPlex": "Zobraziť na Plex", + "ViewOnEmby": "Zobraziť na Emby", + "RequestAdded": "Žiadosť o {{title}} bola úspešne pridaná", + "Similar": "Podobné", + "Refine": "Filtrovať", + "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", + "Movies": { + "PopularMovies": "Populárne filmy", + "UpcomingMovies": "Očakávané filmy", + "TopRatedMovies": "Najlepšie hodnotené filmy", + "NowPlayingMovies": "Teraz prehrávané filmy", + "HomePage": "Úvodná stránka", + "Trailer": "Upútavka" + }, + "TvShows": { + "Popular": "Populárne", + "Trending": "Trendy", + "MostWatched": "Najsledovanejšie", + "MostAnticipated": "Najočakávanejšie", + "Results": "Výsledky", + "AirDate": "Dátum vysielania:", + "AllSeasons": "Všetky série", + "FirstSeason": "Prvá séria", + "LatestSeason": "Posledná séria", + "Select": "Vybrať ...", + "SubmitRequest": "Poslať žiadosť", + "Season": "Séria: {{seasonNumber}}", + "SelectAllInSeason": "Vybrať všetko v danej sérii {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Požiadavky", + "Paragraph": "Nižšie nájdete svoje a všetky ďalšie žiadosti, ako aj stav ich sťahovania a schvaľovania.", + "MoviesTab": "Filmy", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "RequestedBy": "Vyžiadané od:", + "Status": "Stav:", + "RequestStatus": "Stav požiadavky:", + "Denied": " Zamietnuté:", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ReleaseDate": "Vydané: {{date}}", + "TheatricalReleaseSort": "Kino vydanie", + "DigitalRelease": "Online vydanie: {{date}}", + "RequestDate": "Dátum požiadavky:", + "QualityOverride": "Prepísanie kvality:", + "RootFolderOverride": "Prepísanie Root priečinku:", + "ChangeRootFolder": "Koreňový priečinok", + "ChangeQualityProfile": "Profil kvality", + "MarkUnavailable": "Označiť nedostupné", + "MarkAvailable": "Označiť dostupné", + "Remove": "Odstrániť", + "Deny": "Odmietnuť", + "Season": "Séria:", + "GridTitle": "Názov", + "AirDate": "Dátum vysielania", + "GridStatus": "Stav", + "ReportIssue": "Nahlásiť problém", + "Filter": "Filter", + "Sort": "Triediť", + "SeasonNumberHeading": "Séria: {seasonNumber}", + "SortTitleAsc": "Názov ▲", + "SortTitleDesc": "Názov ▼", + "SortRequestDateAsc": "Dátum požiadavky ▲", + "SortRequestDateDesc": "Dátum požiadavky ▼", + "SortStatusAsc": "Stav ▲", + "SortStatusDesc": "Stav ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} zostávajúce žiadosti", + "NextDays": "Ďalšia žiadosť bude pridaná o {{time}} dní", + "NextHours": "Ďalšia žiadosť bude pridaná o {{time}} hodín", + "NextMinutes": "Ďalšia žiadosť bude pridaná o {{time}} minút", + "NextMinute": "Ďalšia žiadosť bude pridaná o {{time}} minútu" + } + }, + "Issues": { + "Title": "Problémy", + "PendingTitle": "Nevyriešené problémy", + "InProgressTitle": "Riešené problémy", + "ResolvedTitle": "Vyiešené problémy", + "ColumnTitle": "Názov", + "Category": "Kategória", + "Status": "Stav", + "Details": "Podrobnosti", + "Description": "Popis", + "NoComments": "Žiadne komentáre!", + "MarkInProgress": "Označiť ako prebiehajúce", + "MarkResolved": "Označiť ako vyriešené", + "SendMessageButton": "Odoslať", + "Subject": "Predmet", + "Comments": "Komentáre", + "WriteMessagePlaceholder": "Napíšte správu sem...", + "ReportedBy": "Nahlásené od" + }, + "Filter": { + "ClearFilter": "Vymazať filter", + "FilterHeaderAvailability": "Dostupnosť", + "FilterHeaderRequestStatus": "Stav", + "Approved": "Schválené", + "PendingApproval": "Čaká na schválenie" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} zostávajúce", + "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", + "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", + "TvDue": "TV: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Hlasované", + "VotesTab": "Potrebné hlasovanie" + } +} diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index 3f35f5f50..d68dca944 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -4183,10 +4183,25 @@ ng2-cookies@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc" +ng2-material-dropdown@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/ng2-material-dropdown/-/ng2-material-dropdown-0.11.0.tgz#27a402ef3cbdcaf6791ef4cfd4b257e31db7546f" + integrity sha512-wptBo09qKecY0QPTProAThrc4A3ajJTcHE9LTpCG5XZZUhXLBzhnGK8OW33TN8A+K/jqcs7OB74ppYJiqs3nhQ== + dependencies: + tslib "^1.9.0" + ngx-bootstrap@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.1.4.tgz#5105c0227da3b51a1972d04efa1504a79474fd57" +ngx-chips@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ngx-chips/-/ngx-chips-2.1.0.tgz#aa299bcf40dc3e1f6288bf1d29e2fdfe9a132ed3" + integrity sha512-OQV4dTfD3nXm5d2mGKUSgwOtJOaMnZ4F+lwXOtd7DWRSUne0JQWwoZNHdOpuS6saBGhqCPDAwq6KxdR5XSgZUQ== + dependencies: + ng2-material-dropdown "0.11.0" + tslib "^1.9.0" + ngx-clipboard@^11.1.1: version "11.1.9" resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-11.1.9.tgz#a391853dc49e436de407260863a2c814d73a9332"