From c547777df7b98a6098c79882d18bb52973bb9d85 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 16 Oct 2019 22:57:25 +0100 Subject: [PATCH 01/43] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae8417bae..a611b5b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## (unreleased) +## v3.0.4817 (2019-10-15) ### **New Features** From 2c8e50e9ffd48251f3bfeeef1eb2d48c215e6026 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 18 Oct 2019 10:14:08 +0100 Subject: [PATCH 02/43] Add SK lang --- src/Ombi/ClientApp/app/app.component.html | 9 ++++++--- src/Ombi/ClientApp/app/app.component.ts | 4 ++-- src/Ombi/wwwroot/translations/sk.json | 3 +++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/Ombi/wwwroot/translations/sk.json 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/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json new file mode 100644 index 000000000..544b7b4dd --- /dev/null +++ b/src/Ombi/wwwroot/translations/sk.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file From c1360ca51585757b182b1974c3e63e2c34dbff65 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:32:07 +0100 Subject: [PATCH 03/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 186 ++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/Ombi/wwwroot/translations/sk.json diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json new file mode 100644 index 000000000..7fabf59d9 --- /dev/null +++ b/src/Ombi/wwwroot/translations/sk.json @@ -0,0 +1,186 @@ +{ + "Login": { + "SignInButton": "Sign in", + "UsernamePlaceholder": "Username", + "PasswordPlaceholder": "Password", + "RememberMe": "Remember Me", + "ForgottenPassword": "Forgot your password?", + "Errors": { + "IncorrectCredentials": "Incorrect username or password" + } + }, + "Common": { + "ContinueButton": "Continue", + "Available": "Available", + "PartiallyAvailable": "Partially Available", + "Monitored": "Monitored", + "NotAvailable": "Not Available", + "ProcessingRequest": "Processing Request", + "PendingApproval": "Pending Approval", + "RequestDenied": "Request Denied", + "NotRequested": "Not Requested", + "Requested": "Requested", + "Request": "Request", + "Denied": "Denied", + "Approve": "Approve", + "PartlyAvailable": "Partly Available", + "Errors": { + "Validation": "Please check your entered values" + } + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Reset Password" + }, + "LandingPage": { + "OnlineHeading": "Currently Online", + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." + }, + "NavigationBar": { + "Search": "Search", + "Requests": "Requests", + "UserManagement": "User Management", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added" + }, + "Search": { + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season: {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By:", + "Status": "Status:", + "RequestStatus": "Request status:", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date:", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkAvailable": "Mark Available", + "Remove": "Remove", + "Deny": "Deny", + "Season": "Season:", + "GridTitle": "Title", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } + }, + "Issues": { + "Title": "Issues", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", + "Category": "Category", + "Status": "Status", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By" + }, + "Filter": { + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", + "FilterHeaderRequestStatus": "Status", + "Approved": "Approved", + "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" + } +} From 65895d541e965c2c6d12fe4545ef99dfea548170 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:41:48 +0100 Subject: [PATCH 04/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 7fabf59d9..0304fd926 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -1,43 +1,43 @@ { "Login": { - "SignInButton": "Sign in", - "UsernamePlaceholder": "Username", - "PasswordPlaceholder": "Password", - "RememberMe": "Remember Me", - "ForgottenPassword": "Forgot your password?", + "SignInButton": "Prihláste sa", + "UsernamePlaceholder": "Užívateľské meno", + "PasswordPlaceholder": "Heslo", + "RememberMe": "Zapamätať prihlásenie", + "ForgottenPassword": "Zabudli ste heslo?", "Errors": { - "IncorrectCredentials": "Incorrect username or password" + "IncorrectCredentials": "Nesprávne meno alebo heslo" } }, "Common": { - "ContinueButton": "Continue", - "Available": "Available", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Processing Request", - "PendingApproval": "Pending Approval", - "RequestDenied": "Request Denied", - "NotRequested": "Not Requested", - "Requested": "Requested", - "Request": "Request", - "Denied": "Denied", - "Approve": "Approve", - "PartlyAvailable": "Partly Available", + "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žiadavka", + "Denied": "Zamietnuté", + "Approve": "Schválené", + "PartlyAvailable": "Čiastočne dostupné", "Errors": { - "Validation": "Please check your entered values" + "Validation": "Skontrolujte zadaný obsah" } }, "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" + "EmailAddressPlaceholder": "Emailová adresa", + "ResetPasswordButton": "Nastaviť nové heslo" }, "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", - "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "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}} server offline z {{totalServers}}.", "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", "OfflineHeading": "Currently Offline", "OfflineParagraph": "The media server is currently offline.", From 22c824e9b05994ad6de913e2ed58eaee10743390 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:55:28 +0100 Subject: [PATCH 05/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 104 +++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 0304fd926..37da47913 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -37,33 +37,33 @@ "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}} server offline z {{totalServers}}.", - "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", - "OfflineHeading": "Currently Offline", - "OfflineParagraph": "The media server is currently offline.", - "CheckPageForUpdates": "Check this page for continuous site updates." + "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": "Search", - "Requests": "Requests", - "UserManagement": "User Management", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", + "Search": "Hľadať", + "Requests": "Požiadavky", + "UserManagement": "Správa užívateľov", + "Issues": "Problémy", + "Vote": "Hlasovať", + "Donate": "Prispieť!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", - "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added" + "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": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", + "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": "TV Shows", "MusicTab": "Music", "Suggestions": "Suggestions", @@ -119,42 +119,42 @@ "RootFolderOverride": "Root Folder Override:", "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "Season": "Season:", - "GridTitle": "Title", - "AirDate": "AirDate", - "GridStatus": "Status", - "ReportIssue": "Report Issue", + "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": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", + "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}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "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": "Issues", - "PendingTitle": "Pending Issues", - "InProgressTitle": "In Progress Issues", - "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Category": "Category", - "Status": "Status", - "Details": "Details", - "Description": "Description", + "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": "No Comments!", "MarkInProgress": "Mark In Progress", "MarkResolved": "Mark Resolved", From 9d1a53e1f3bcf00ad270d197cd391e6a4eb7862e Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:06:40 +0100 Subject: [PATCH 06/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 37da47913..23fa5dfd4 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -64,28 +64,28 @@ "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": "TV Shows", - "MusicTab": "Music", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "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": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "PopularMovies": "Populárne filmy", + "UpcomingMovies": "Blížiace sa filmy", + "TopRatedMovies": "Najlepšie hodnotené filmy", + "NowPlayingMovies": "Teraz prehrávané filmy", + "HomePage": "Úvodná stránka", + "Trailer": "Upútavka" }, "TvShows": { - "Popular": "Popular", + "Popular": "Populárne", "Trending": "Trending", "MostWatched": "Most Watched", "MostAnticipated": "Most Anticipated", @@ -155,26 +155,26 @@ "Status": "Stav", "Details": "Podrobnosti", "Description": "Popis", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By" + "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": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" + "ClearFilter": "Vymazať filter", + "FilterHeaderAvailability": "Dostupnosť", + "FilterHeaderRequestStatus": "Stav", + "Approved": "Schválené", + "PendingApproval": "Čaká na schválenie" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "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": "Movie: {{date}}", "MusicDue": "Music: {{date}}" From c1dc15c78af0ea418597dc1a486e32c7572371ad Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:13:35 +0100 Subject: [PATCH 07/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 62 +++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 23fa5dfd4..42b7a9fd3 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -78,7 +78,7 @@ "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", "Movies": { "PopularMovies": "Populárne filmy", - "UpcomingMovies": "Blížiace sa filmy", + "UpcomingMovies": "Očakávané filmy", "TopRatedMovies": "Najlepšie hodnotené filmy", "NowPlayingMovies": "Teraz prehrávané filmy", "HomePage": "Úvodná stránka", @@ -86,39 +86,39 @@ }, "TvShows": { "Popular": "Populárne", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + "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": "Requests", - "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By:", - "Status": "Status:", - "RequestStatus": "Request status:", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date:", - "QualityOverride": "Quality Override:", - "RootFolderOverride": "Root Folder Override:", - "ChangeRootFolder": "Root Folder", - "ChangeQualityProfile": "Quality Profile", + "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ť", From 1f9a31f4fef954fa8f6196665e2a7dd68b02b39b Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:31:51 +0100 Subject: [PATCH 08/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 42b7a9fd3..9b4f1221d 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -50,8 +50,8 @@ "Issues": "Problémy", "Vote": "Hlasovať", "Donate": "Prispieť!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", - "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", + "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}}", @@ -176,11 +176,11 @@ "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Hlasované", + "VotesTab": "Potrebné hlasovanie" } } From 371a48878c0252cca75a5b8738f8617dfd5c2fbb Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:53:16 +0100 Subject: [PATCH 09/43] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 9b4f1221d..d7c3e376a 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -20,7 +20,7 @@ "RequestDenied": "Požiadavka zamietnutá", "NotRequested": "Nepožiadané", "Requested": "Požiadané", - "Request": "Požiadavka", + "Request": "Požiadať", "Denied": "Zamietnuté", "Approve": "Schválené", "PartlyAvailable": "Čiastočne dostupné", From 5d73845951778335c587fd36bbb1f76804763d11 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 19 Oct 2019 00:00:13 +0100 Subject: [PATCH 10/43] Add the migration to the correct database... #3214 --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 12 +- .../20191018225833_PlexContentId.Designer.cs | 314 ++++++++++++++++++ .../External/20191018225833_PlexContentId.cs | 22 ++ .../External/ExternalContextModelSnapshot.cs | 4 +- 4 files changed, 347 insertions(+), 5 deletions(-) create mode 100644 src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs create mode 100644 src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 710c39595..f6d61b30d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -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) } ); @@ -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) } ); @@ -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("
    "); } 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"); From 3008cd124d8454024d1de6340497fd4f91d3e815 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 00:53:27 -0500 Subject: [PATCH 11/43] Add adult movie filtering --- src/Ombi.Api/Request.cs | 19 +-- .../Models/External/TheMovieDbSettings.cs | 9 ++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 122 ++++++++++++------ .../ClientApp/app/interfaces/ISettings.ts | 5 + .../app/services/settings.service.ts | 9 ++ .../ClientApp/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + .../themoviedb/themoviedb.component.html | 29 +++++ .../themoviedb/themoviedb.component.ts | 32 +++++ src/Ombi/Controllers/SettingsController.cs | 19 +++ 10 files changed, 187 insertions(+), 61 deletions(-) create mode 100644 src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts 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.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs new file mode 100644 index 000000000..562d9fc88 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Core.Settings.Models.External +{ + public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings + { + public bool ShowAdultMovies { get; set; } + + public string ExcludedKeywordIds { get; set; } + } +} diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 79ccc5bb7..7c24d4c60 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,31 +1,36 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; 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 +40,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 +51,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 +64,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 +74,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 +85,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 +94,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 +105,95 @@ 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) + 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); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> TopRated(string langageCode) + 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("vote_count.gte", "250"); + request.AddQueryString("sort_by", "vote_average.desc"); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> Upcoming(string langageCode) + 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); + request.AddQueryString("with_release_type", "2|3"); + 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")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> NowPlaying(string langageCode) + 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); + request.AddQueryString("with_release_type", "2|3"); + 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")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -166,7 +202,7 @@ 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); diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 75aaf7605..26892ca6e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -245,3 +245,8 @@ export interface IVoteSettings extends ISettings { musicVoteMax: number; tvShowVoteMax: number; } + +export interface ITheMovieDbSettings extends ISettings { + showAdultMovies: boolean; + excludedKeywordIds: string; +} diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index a80cfd772..8c7787b6d 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -32,6 +32,7 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + ITheMovieDbSettings, IUpdateSettings, IUserManagementSettings, IVoteSettings, @@ -301,6 +302,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/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6fb69dc27..4d672d622 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -36,6 +36,7 @@ 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 { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; @@ -80,6 +81,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] }, ]; @@ -135,6 +137,7 @@ const routes: Routes = [ NewsletterComponent, LidarrComponent, VoteComponent, + TheMovieDbComponent, FailedRequestsComponent, ], exports: [ diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index d58c96e2e..686f4c020 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
  • 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..afce968c2 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -0,0 +1,29 @@ + + +
    + The Movie Database +
    +
    +
    + + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    \ 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..e167d3009 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; + +import { ITheMovieDbSettings } from "../../interfaces"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./themoviedb.component.html", +}) +export class TheMovieDbComponent implements OnInit { + + public settings: ITheMovieDbSettings; + public advanced: boolean; + + constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } + + public ngOnInit() { + this.settingsService.getTheMovieDbSettings().subscribe(x => { + this.settings = x; + }); + } + + public save() { + 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/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index ebc2fbe66..6033ae2ca 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -659,6 +659,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. /// From 9154dbbe9b16eddc8422db4c81a231ecc00003c0 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 01:28:13 -0500 Subject: [PATCH 12/43] Fix TS import order --- src/Ombi/ClientApp/app/settings/settings.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 4d672d622..00328c778 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -36,12 +36,12 @@ 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 { TheMovieDbComponent } from "./themoviedb/themoviedb.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"; From 69c8736a5273bf3abd26be91210d6ce91fea1883 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 19:45:44 -0500 Subject: [PATCH 13/43] Fix search bar overlap on mobile --- .../app/search/moviesearch.component.html | 47 +++++++++------- .../app/search/search.component.scss | 2 +- .../app/search/tvsearch.component.html | 53 ++++++++++++------- src/Ombi/ClientApp/styles/base.scss | 21 ++++++++ 4 files changed, 84 insertions(+), 39 deletions(-) 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/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9c7756d8f..54d62c3cf 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; From 22d47512b692a4cac9d54f752ec445ee7bacd3cd Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Tue, 22 Oct 2019 12:12:20 -0500 Subject: [PATCH 14/43] Add comments to clarify filter decisions --- src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 32 ++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 7c24d4c60..b5f0a1596 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -133,11 +133,15 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/popular. + /// public async Task> PopularMovies(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); + request.AddQueryString("sort_by", "popularity.desc"); var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -147,13 +151,21 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/top_rated. + /// public async Task> TopRated(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); - request.AddQueryString("vote_count.gte", "250"); 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"); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -163,15 +175,24 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/upcoming. + /// public async Task> Upcoming(string langCode) { 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")); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -181,15 +202,24 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/now_playing. + /// public async Task> NowPlaying(string langCode) { 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")); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); From 23cceec6f90b04d5572e3e0113cd5029ebb80e46 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Oct 2019 08:50:46 +0100 Subject: [PATCH 15/43] Fixed potential null ref !wip --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index f6d61b30d..585ed42bb 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -715,7 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() } ); @@ -840,7 +840,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() } ); From 721ef47bb2a2d6798824fbeba59e58955c9fde3c Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Fri, 25 Oct 2019 01:56:56 -0500 Subject: [PATCH 16/43] Use tags and autocomplete for excluded keywords --- .../Models/External/TheMovieDbSettings.cs | 6 ++- src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 2 + src/Ombi.TheMovieDbApi/Models/Keyword.cs | 13 +++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 53 +++++++++++++------ src/Ombi/ClientApp/app/interfaces/IMovieDb.ts | 4 ++ .../ClientApp/app/interfaces/ISettings.ts | 2 +- src/Ombi/ClientApp/app/interfaces/index.ts | 1 + .../app/services/applications/index.ts | 1 + .../applications/themoviedb.service.ts | 25 +++++++++ .../ClientApp/app/settings/settings.module.ts | 5 +- .../themoviedb/themoviedb.component.html | 31 +++++++++-- .../themoviedb/themoviedb.component.ts | 47 ++++++++++++++-- src/Ombi/ClientApp/styles/base.scss | 8 +++ .../External/TheMovieDbController.cs | 38 +++++++++++++ src/Ombi/package.json | 1 + src/Ombi/yarn.lock | 15 ++++++ 16 files changed, 223 insertions(+), 29 deletions(-) create mode 100644 src/Ombi.TheMovieDbApi/Models/Keyword.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/IMovieDb.ts create mode 100644 src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts create mode 100644 src/Ombi/Controllers/External/TheMovieDbController.cs diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs index 562d9fc88..fe0c238d8 100644 --- a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -1,9 +1,11 @@ -namespace Ombi.Core.Settings.Models.External +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 string ExcludedKeywordIds { get; set; } + public List ExcludedKeywordIds { get; set; } } } 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 b5f0a1596..a55bdadeb 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -142,10 +143,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); request.AddQueryString("sort_by", "popularity.desc"); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -165,11 +163,8 @@ namespace Ombi.Api.TheMovieDb // 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"); - - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -193,10 +188,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -220,10 +212,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -237,6 +226,38 @@ namespace Ombi.Api.TheMovieDb 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/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/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 26892ca6e..d3dece200 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -248,5 +248,5 @@ export interface IVoteSettings extends ISettings { export interface ITheMovieDbSettings extends ISettings { showAdultMovies: boolean; - excludedKeywordIds: string; + 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/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/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/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 00328c778..377756e56 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"; @@ -99,6 +100,7 @@ const routes: Routes = [ NgbAccordionModule, AutoCompleteModule, CalendarModule, + TagInputModule, ClipboardModule, PipeModule, RadioButtonModule, @@ -159,6 +161,7 @@ const routes: Routes = [ NotificationMessageService, LidarrService, RequestRetryService, + TheMovieDbService, ], }) diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html index afce968c2..ccadc68ac 100644 --- a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -11,13 +11,34 @@
    -
    diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts index e167d3009..4fc9138a0 100644 --- a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -1,8 +1,16 @@ 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", @@ -10,17 +18,48 @@ import { SettingsService } from "../../services"; export class TheMovieDbComponent implements OnInit { public settings: ITheMovieDbSettings; - public advanced: boolean; + public excludedKeywords: IKeywordTag[]; - constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private tmdbService: TheMovieDbService) { } public ngOnInit() { - this.settingsService.getTheMovieDbSettings().subscribe(x => { - this.settings = x; + 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"); diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9c7756d8f..ce56d0033 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1010,6 +1010,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/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/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/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" From 35199a8b5e61b0b3ae45fbb64b46c1b4e301c960 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 29 Oct 2019 21:42:53 +0000 Subject: [PATCH 17/43] Fixed #3208 --- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index a8d77a71b..70ab6878d 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -108,6 +108,8 @@ namespace Ombi.Schedule.Jobs.Plex if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) { + Logger.LogInformation("Kicking off Plex Availability Checker"); + await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); Logger.LogInformation("Starting Metadata refresh"); // Just check what we send it await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); From d13a1865ea45314abb1bd9473d47ae7c5ab30398 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 2 Nov 2019 21:36:34 +0000 Subject: [PATCH 18/43] Fixed the error in the newsletter --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 585ed42bb..0443d06c2 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -715,7 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } ); @@ -840,7 +840,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } ); From 37aca4e42333116549044e587a38e309739aa50f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 2 Nov 2019 22:49:14 +0000 Subject: [PATCH 19/43] Got the new DB structure in place --- src/Ombi.DependencyInjection/IocExtensions.cs | 4 +- src/Ombi.Store/Context/IOmbiContext.cs | 44 --- src/Ombi.Store/Context/OmbiContext.cs | 46 +-- src/Ombi.Store/Context/OmbiSqliteContext.cs | 35 ++ src/Ombi.Store/Repository/AuditRepository.cs | 4 +- src/Ombi.Store/Repository/BaseRepository.cs | 2 +- .../Repository/EmbyContentRepository.cs | 4 +- .../Repository/ExternalRepository.cs | 4 +- .../NotificationTemplatesRepository.cs | 4 +- .../Repository/PlexContentRepository.cs | 4 +- src/Ombi.Store/Repository/Repository.cs | 4 +- .../Requests/ITvRequestRepository.cs | 2 +- .../Requests/MovieRequestRepository.cs | 4 +- .../Requests/MusicRequestRepository.cs | 4 +- .../Requests/TvRequestRepository.cs | 6 +- src/Ombi.Store/Repository/TokenRepository.cs | 6 +- src/Ombi.Store/Repository/UserRepository.cs | 4 +- src/Ombi/DatabaseExtensions.cs | 26 ++ src/Ombi/Ombi.csproj | 1 + src/Ombi/Program.cs | 302 +++++++++--------- src/Ombi/Startup.cs | 4 +- 21 files changed, 257 insertions(+), 257 deletions(-) delete mode 100644 src/Ombi.Store/Context/IOmbiContext.cs create mode 100644 src/Ombi.Store/Context/OmbiSqliteContext.cs create mode 100644 src/Ombi/DatabaseExtensions.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3d54e5a67..38cb51acd 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -135,11 +135,11 @@ namespace Ombi.DependencyInjection } public static void RegisterStore(this IServiceCollection services) { - 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(); diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs deleted file mode 100644 index a7fb3b47d..000000000 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ /dev/null @@ -1,44 +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; - -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 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/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 28b27107e..9b5c3b686 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -10,19 +10,28 @@ using Ombi.Store.Entities.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; } @@ -60,33 +69,6 @@ namespace Ombi.Store.Context 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/OmbiSqliteContext.cs b/src/Ombi.Store/Context/OmbiSqliteContext.cs new file mode 100644 index 000000000..9237ab3af --- /dev/null +++ b/src/Ombi.Store/Context/OmbiSqliteContext.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public sealed class OmbiSqliteContext : OmbiContext + { + private static bool _created; + public OmbiSqliteContext(DbContextOptions options) : base(options) + { + if (_created) return; + + + _created = true; + Database.SetCommandTimeout(60); + Database.Migrate(); + } + + 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); + } + } +} \ No newline at end of file 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..41a7eeb31 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) { 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/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 f08f7812f..1c6e4d302 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 2cea81200..2df4cac0f 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 6528f0969..823887ec4 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -8,14 +8,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) { 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/DatabaseExtensions.cs b/src/Ombi/DatabaseExtensions.cs new file mode 100644 index 000000000..82a0084da --- /dev/null +++ b/src/Ombi/DatabaseExtensions.cs @@ -0,0 +1,26 @@ +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Ombi.Helpers; +using Ombi.Store.Context; + +namespace Ombi +{ + public static class DatabaseExtensions + { + public static void ConfigureDatabases(this IServiceCollection services) + { + services.AddDbContext(ConfigureSqlite); + } + + private static void ConfigureSqlite(DbContextOptionsBuilder options) + { + var i = StoragePathSingleton.Instance; + if (string.IsNullOrEmpty(i.StoragePath)) + { + i.StoragePath = string.Empty; + } + options.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "Ombi.db")}"); + } + } +} \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 02e11c84b..a5a3ed68e 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -79,6 +79,7 @@ + diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index dd0baa8d4..7eecf0b8e 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -50,7 +50,7 @@ namespace Ombi instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings DeleteSchedules(); - CheckAndMigrate(); + //CheckAndMigrate(); var ctx = new SettingsContext(); var config = ctx.ApplicationConfigurations.ToList(); var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); @@ -132,156 +132,156 @@ namespace Ombi } } - /// - /// 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(); - - try - { - - using (var tran = settings.Database.BeginTransaction()) - { - if (ombi.Settings.Any() && !settings.Settings.Any()) - { - // OK migrate it! - var allSettings = ombi.Settings.ToList(); - settings.Settings.AddRange(allSettings); - doneGlobal = true; - } - - // Check for any application settings - - if (ombi.ApplicationConfigurations.Any() && !settings.ApplicationConfigurations.Any()) - { - // OK migrate it! - var allSettings = ombi.ApplicationConfigurations.ToList(); - settings.ApplicationConfigurations.AddRange(allSettings); - doneConfig = true; - } - - settings.SaveChanges(); - tran.Commit(); - } - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - - - 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(); - } - - // Now migrate all the external stuff - var external = new ExternalContext(); - - try - { - - using (var tran = external.Database.BeginTransaction()) - { - 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(); - } - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - } + ///// + ///// 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(); + + // try + // { + + // using (var tran = settings.Database.BeginTransaction()) + // { + // if (ombi.Settings.Any() && !settings.Settings.Any()) + // { + // // OK migrate it! + // var allSettings = ombi.Settings.ToList(); + // settings.Settings.AddRange(allSettings); + // doneGlobal = true; + // } + + // // Check for any application settings + + // if (ombi.ApplicationConfigurations.Any() && !settings.ApplicationConfigurations.Any()) + // { + // // OK migrate it! + // var allSettings = ombi.ApplicationConfigurations.ToList(); + // settings.ApplicationConfigurations.AddRange(allSettings); + // doneConfig = true; + // } + + // settings.SaveChanges(); + // tran.Commit(); + // } + // } + // catch (Exception e) + // { + // Console.WriteLine(e); + // throw; + // } + + + // 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(); + // } + + // // Now migrate all the external stuff + // var external = new ExternalContext(); + + // try + // { + + // using (var tran = external.Database.BeginTransaction()) + // { + // 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(); + // } + // } + // catch (Exception e) + // { + // Console.WriteLine(e); + // throw; + // } + //} public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index c353bcf6a..8820f7721 100755 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -73,7 +73,7 @@ namespace Ombi options.User.AllowedUserNameCharacters = string.Empty; }); - + services.ConfigureDatabases(); services.AddHealthChecks(); services.AddMemoryCache(); @@ -122,7 +122,7 @@ namespace Ombi app.UseQuartz().GetAwaiter().GetResult(); - var ctx = serviceProvider.GetService(); + var ctx = serviceProvider.GetService(); loggerFactory.AddSerilog(); app.UseHealthChecks("/health"); From 1a086e6f19b2420583afa5dad49217d3138f95ac Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 3 Nov 2019 00:02:10 +0000 Subject: [PATCH 20/43] Got MySql working --- .gitignore | 1 + .../Rule/Rules/Request/CanRequestRule.cs | 1 - src/Ombi.Schedule.Tests/OmbiQuartzTests.cs | 4 +- src/Ombi.Store/Context/OmbiContext.cs | 33 +- src/Ombi.Store/Context/OmbiMySqlContext.cs | 17 + src/Ombi.Store/Context/OmbiSqliteContext.cs | 17 - .../20191102235852_Inital.Designer.cs | 1061 +++++++++++++++++ .../OmbiMySql/20191102235852_Inital.cs | 1030 ++++++++++++++++ .../OmbiMySqlContextModelSnapshot.cs | 1059 ++++++++++++++++ .../20191102235658_Inital.Designer.cs | 1060 ++++++++++++++++ .../OmbiSqlite/20191102235658_Inital.cs | 1029 ++++++++++++++++ .../OmbiSqliteContextModelSnapshot.cs | 1058 ++++++++++++++++ src/Ombi.Store/Ombi.Store.csproj | 3 +- .../Requests/TvRequestRepository.cs | 13 - src/Ombi/Controllers/SearchController.cs | 2 +- src/Ombi/DatabaseExtensions.cs | 26 - src/Ombi/Extensions/DatabaseExtensions.cs | 106 ++ .../{ => Extensions}/StartupExtensions.cs | 0 .../SwaggerOperationFilter.cs | 0 src/Ombi/{ => Middleware}/ApiKeyMiddlewear.cs | 0 .../ErrorHandlingMiddlewear.cs | 0 src/Ombi/Startup.cs | 2 +- 22 files changed, 6443 insertions(+), 79 deletions(-) create mode 100644 src/Ombi.Store/Context/OmbiMySqlContext.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs delete mode 100644 src/Ombi/DatabaseExtensions.cs create mode 100644 src/Ombi/Extensions/DatabaseExtensions.cs rename src/Ombi/{ => Extensions}/StartupExtensions.cs (100%) rename src/Ombi/{ => Extensions}/SwaggerOperationFilter.cs (100%) rename src/Ombi/{ => Middleware}/ApiKeyMiddlewear.cs (100%) rename src/Ombi/{ => Middleware}/ErrorHandlingMiddlewear.cs (100%) 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/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.Schedule.Tests/OmbiQuartzTests.cs b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs index 6d00f8ef6..3c728300d 100644 --- a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs +++ b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs @@ -12,7 +12,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 +23,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.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 9b5c3b686..b6e23a377 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -12,12 +12,9 @@ namespace Ombi.Store.Context { public abstract class OmbiContext : IdentityDbContext { - private static bool _created; protected OmbiContext(DbContextOptions options) : base(options) { - if (_created) return; - _created = true; } /// @@ -33,15 +30,6 @@ namespace Ombi.Store.Context 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; } @@ -58,16 +46,25 @@ 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 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/OmbiMySqlContext.cs b/src/Ombi.Store/Context/OmbiMySqlContext.cs new file mode 100644 index 000000000..1437846e3 --- /dev/null +++ b/src/Ombi.Store/Context/OmbiMySqlContext.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public sealed class OmbiMySqlContext : OmbiContext + { + private static bool _created; + public OmbiMySqlContext(DbContextOptions options) : base(options) + { + if (_created) return; + _created = true; + + Database.Migrate(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiSqliteContext.cs b/src/Ombi.Store/Context/OmbiSqliteContext.cs index 9237ab3af..2ccfc1dac 100644 --- a/src/Ombi.Store/Context/OmbiSqliteContext.cs +++ b/src/Ombi.Store/Context/OmbiSqliteContext.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Ombi.Store.Entities; namespace Ombi.Store.Context { @@ -15,21 +14,5 @@ namespace Ombi.Store.Context Database.SetCommandTimeout(60); Database.Migrate(); } - - 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); - } } } \ No newline at end of file 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..2f368a735 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_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; + +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..ddd410a3f --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs @@ -0,0 +1,1030 @@ +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: "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: "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: "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: "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: "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.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_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/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs new file mode 100644 index 000000000..161e882ea --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -0,0 +1,1059 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +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.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.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs new file mode 100644 index 000000000..f61ff54f6 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs @@ -0,0 +1,1060 @@ +// +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.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..3365749d1 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -0,0 +1,1058 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +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/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/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index 823887ec4..8c6fc2461 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -105,13 +105,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); @@ -120,12 +113,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/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/DatabaseExtensions.cs b/src/Ombi/DatabaseExtensions.cs deleted file mode 100644 index 82a0084da..000000000 --- a/src/Ombi/DatabaseExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.IO; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Ombi.Helpers; -using Ombi.Store.Context; - -namespace Ombi -{ - public static class DatabaseExtensions - { - public static void ConfigureDatabases(this IServiceCollection services) - { - services.AddDbContext(ConfigureSqlite); - } - - private static void ConfigureSqlite(DbContextOptionsBuilder options) - { - var i = StoragePathSingleton.Instance; - if (string.IsNullOrEmpty(i.StoragePath)) - { - i.StoragePath = string.Empty; - } - options.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "Ombi.db")}"); - } - } -} \ No newline at end of file diff --git a/src/Ombi/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs new file mode 100644 index 000000000..541113046 --- /dev/null +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -0,0 +1,106 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Ombi.Helpers; +using Ombi.Store.Context; +using SQLitePCL; + +namespace Ombi.Extensions +{ + public static class DatabaseExtensions + { + + private const string SqliteDatabase = "Sqlite"; + private const string MySqlDatabase = "MySQL"; + + public static void ConfigureDatabases(this IServiceCollection services) + { + var i = StoragePathSingleton.Instance; + if (string.IsNullOrEmpty(i.StoragePath)) + { + i.StoragePath = string.Empty; + } + + var databaseFileLocation = Path.Combine(i.StoragePath, "database.json"); + var configuration = GetDatabaseConfiguration(databaseFileLocation, i.StoragePath); + + // 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; + } + } + + private static DatabaseConfiguration GetDatabaseConfiguration(string databaseFileLocation, string storagePath) + { + var configuration = new DatabaseConfiguration(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; + } + + private static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + { + SQLitePCL.Batteries.Init(); + SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); + + options.UseSqlite(config.ConnectionString); + } + + private static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + { + options.UseMySql(config.ConnectionString); + } + + private 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, "Settings.db")}"); + ExternalDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "External.db")}"); + } + public PerDatabaseConfiguration OmbiDatabase { get; set; } + public PerDatabaseConfiguration SettingsDatabase { get; set; } + public PerDatabaseConfiguration ExternalDatabase { get; set; } + } + + private 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/Startup.cs b/src/Ombi/Startup.cs index 8820f7721..3dd7f1136 100755 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -19,6 +19,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; @@ -98,7 +99,6 @@ namespace Ombi x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); }); - SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); services.AddCors(o => o.AddPolicy("MyPolicy", builder => { From 560c3c3eadfc18d8b6f1219d22a30ba56f7d4457 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 3 Nov 2019 21:53:22 +0000 Subject: [PATCH 21/43] Finished it! --- .../Rules/Request/SonarrCacheRequestRule.cs | 4 +- .../Rules/Search/SonarrCacheSearchRule.cs | 4 +- src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs | 4 +- src/Ombi.DependencyInjection/IocExtensions.cs | 8 +- .../Jobs/Couchpotato/CouchPotatoSync.cs | 4 +- .../Jobs/Lidarr/LidarrAlbumSync.cs | 4 +- .../Jobs/Lidarr/LidarrArtistSync.cs | 4 +- src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 4 +- .../Jobs/SickRage/SickRageSync.cs | 4 +- src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 4 +- src/Ombi.Store/Context/ExternalContext.cs | 43 +-- src/Ombi.Store/Context/IExternalContext.cs | 21 -- src/Ombi.Store/Context/ISettingsContext.cs | 11 - .../Context/MySql/ExternalMySqlContext.cs | 16 + .../Context/{ => MySql}/OmbiMySqlContext.cs | 3 +- .../Context/MySql/SettingsMySqlContext.cs | 16 + src/Ombi.Store/Context/OmbiContext.cs | 15 - src/Ombi.Store/Context/SettingsContext.cs | 35 +- .../Context/Sqlite/ExternalSqliteContext.cs | 17 + .../Context/{ => Sqlite}/OmbiSqliteContext.cs | 2 +- .../Context/Sqlite/SettingsSqliteContext.cs | 17 + src/Ombi.Store/Migration.txt | 4 +- .../20191103213915_Inital.Designer.cs | 315 ++++++++++++++++++ .../ExternalMySql/20191103213915_Inital.cs | 310 +++++++++++++++++ .../ExternalMySqlContextModelSnapshot.cs | 313 +++++++++++++++++ .../20191103205133_Inital.Designer.cs | 314 +++++++++++++++++ .../ExternalSqlite/20191103205133_Inital.cs | 309 +++++++++++++++++ .../ExternalSqliteContextModelSnapshot.cs | 312 +++++++++++++++++ .../20191102235852_Inital.Designer.cs | 1 + .../OmbiMySqlContextModelSnapshot.cs | 1 + .../20191102235658_Inital.Designer.cs | 1 + .../OmbiSqliteContextModelSnapshot.cs | 1 + .../20191103205915_Inital.Designer.cs | 51 +++ .../SettingsMySql/20191103205915_Inital.cs | 48 +++ .../SettingsMySqlContextModelSnapshot.cs | 49 +++ .../20191103205204_Inital.Designer.cs | 50 +++ .../SettingsSqlite/20191103205204_Inital.cs | 47 +++ .../SettingsSqliteContextModelSnapshot.cs | 48 +++ .../Repository/ApplicationConfigRepository.cs | 4 +- .../Repository/SettingsJsonRepository.cs | 4 +- src/Ombi/Extensions/DatabaseExtensions.cs | 40 ++- src/Ombi/Program.cs | 260 ++++----------- src/Ombi/Startup.cs | 4 +- 43 files changed, 2387 insertions(+), 339 deletions(-) delete mode 100644 src/Ombi.Store/Context/IExternalContext.cs delete mode 100644 src/Ombi.Store/Context/ISettingsContext.cs create mode 100644 src/Ombi.Store/Context/MySql/ExternalMySqlContext.cs rename src/Ombi.Store/Context/{ => MySql}/OmbiMySqlContext.cs (86%) create mode 100644 src/Ombi.Store/Context/MySql/SettingsMySqlContext.cs create mode 100644 src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs rename src/Ombi.Store/Context/{ => Sqlite}/OmbiSqliteContext.cs (91%) create mode 100644 src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20191103213915_Inital.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20191103205133_Inital.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs create mode 100644 src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/SettingsMySql/20191103205915_Inital.cs create mode 100644 src/Ombi.Store/Migrations/SettingsMySql/SettingsMySqlContextModelSnapshot.cs create mode 100644 src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/SettingsSqlite/20191103205204_Inital.cs create mode 100644 src/Ombi.Store/Migrations/SettingsSqlite/SettingsSqliteContextModelSnapshot.cs 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.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 38cb51acd..df0162c1a 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -136,12 +136,12 @@ namespace Ombi.DependencyInjection public static void RegisterStore(this IServiceCollection services) { //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(); services.AddScoped(); services.AddScoped(); 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/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 0d48efbc0..09bd787e7 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -17,7 +17,7 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAlbumSync : ILidarrAlbumSync { - public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, + public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, IBackgroundJobClient job, ILidarrAvailabilityChecker availability) { _lidarrSettings = lidarr; @@ -31,7 +31,7 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; private readonly IBackgroundJobClient _job; private readonly ILidarrAvailabilityChecker _availability; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs index 1602f28b5..317b5821e 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs @@ -18,7 +18,7 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrArtistSync : ILidarrArtistSync { - public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, + public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, IBackgroundJobClient background, ILidarrAlbumSync album) { _lidarrSettings = lidarr; @@ -32,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IExternalContext _ctx; + private readonly ExternalContext _ctx; private readonly IBackgroundJobClient _job; private readonly ILidarrAlbumSync _albumSync; 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.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/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/OmbiMySqlContext.cs b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs similarity index 86% rename from src/Ombi.Store/Context/OmbiMySqlContext.cs rename to src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs index 1437846e3..a0d11f76a 100644 --- a/src/Ombi.Store/Context/OmbiMySqlContext.cs +++ b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; -using Ombi.Store.Entities; -namespace Ombi.Store.Context +namespace Ombi.Store.Context.MySql { public sealed class OmbiMySqlContext : OmbiContext { 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 b6e23a377..4694f1151 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -50,21 +50,6 @@ namespace Ombi.Store.Context public DbSet UserNotificationPreferences { get; set; } public DbSet UserQualityProfileses { get; set; } public DbSet RequestQueue { get; set; } - 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..1ba8c8073 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -1,39 +1,32 @@ -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..4d159887f --- /dev/null +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -0,0 +1,17 @@ +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; + Database.SetCommandTimeout(60); + Database.Migrate(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs similarity index 91% rename from src/Ombi.Store/Context/OmbiSqliteContext.cs rename to src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs index 2ccfc1dac..e6e6f3186 100644 --- a/src/Ombi.Store/Context/OmbiSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Ombi.Store.Context +namespace Ombi.Store.Context.Sqlite { public sealed class OmbiSqliteContext : OmbiContext { diff --git a/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs new file mode 100644 index 000000000..b5f429853 --- /dev/null +++ b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs @@ -0,0 +1,17 @@ +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; + Database.SetCommandTimeout(60); + Database.Migrate(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Migration.txt b/src/Ombi.Store/Migration.txt index 3b54d72f5..5d1131a75 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 OmbiContext --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/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/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 index 2f368a735..f72e34766 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.Designer.cs @@ -5,6 +5,7 @@ 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 { diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 161e882ea..f7e598984 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -4,6 +4,7 @@ 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 { diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs index f61ff54f6..e5d2c302e 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20191102235658_Inital.Designer.cs @@ -5,6 +5,7 @@ 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 { diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 3365749d1..271c38300 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -4,6 +4,7 @@ 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 { 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/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/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/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs index 541113046..82daafff9 100644 --- a/src/Ombi/Extensions/DatabaseExtensions.cs +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -5,6 +5,8 @@ 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 @@ -12,8 +14,8 @@ namespace Ombi.Extensions public static class DatabaseExtensions { - private const string SqliteDatabase = "Sqlite"; - private const string MySqlDatabase = "MySQL"; + public const string SqliteDatabase = "Sqlite"; + public const string MySqlDatabase = "MySQL"; public static void ConfigureDatabases(this IServiceCollection services) { @@ -36,9 +38,29 @@ namespace Ombi.Extensions 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; + } } - private static DatabaseConfiguration GetDatabaseConfiguration(string databaseFileLocation, string storagePath) + public static DatabaseConfiguration GetDatabaseConfiguration(string databaseFileLocation, string storagePath) { var configuration = new DatabaseConfiguration(storagePath); if (File.Exists(databaseFileLocation)) @@ -55,7 +77,7 @@ namespace Ombi.Extensions return configuration; } - private static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + public static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config) { SQLitePCL.Batteries.Init(); SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); @@ -63,12 +85,12 @@ namespace Ombi.Extensions options.UseSqlite(config.ConnectionString); } - private static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config) + public static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config) { options.UseMySql(config.ConnectionString); } - private class DatabaseConfiguration + public class DatabaseConfiguration { public DatabaseConfiguration() { @@ -78,15 +100,15 @@ namespace Ombi.Extensions public DatabaseConfiguration(string defaultSqlitePath) { OmbiDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "Ombi.db")}"); - SettingsDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "Settings.db")}"); - ExternalDatabase = new PerDatabaseConfiguration(SqliteDatabase, $"Data Source={Path.Combine(defaultSqlitePath, "External.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; } } - private class PerDatabaseConfiguration + public class PerDatabaseConfiguration { public PerDatabaseConfiguration(string type, string connectionString) { diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 7eecf0b8e..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"; @@ -51,71 +56,79 @@ namespace Ombi // 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(); - } - 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()) + 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) { - ctx.SaveChanges(); - tran.Commit(); - } + url = new ApplicationConfiguration + { + Type = ConfigurationTypes.Url, + Value = "http://*:5000" + }; + using (var tran = settingsDb.Database.BeginTransaction()) + { + settingsDb.ApplicationConfigurations.Add(url); + settingsDb.SaveChanges(); + tran.Commit(); + } - urlValue = url.Value; - } + urlValue = url.Value; + } - if (dbBaseUrl == null) - { - if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + if (!url.Value.Equals(host)) { - dbBaseUrl = new ApplicationConfiguration - { - Type = ConfigurationTypes.BaseUrl, - Value = baseUrl - }; + url.Value = UrlArgs; - using (var tran = ctx.Database.BeginTransaction()) + using (var tran = settingsDb.Database.BeginTransaction()) { - ctx.ApplicationConfigurations.Add(dbBaseUrl); - ctx.SaveChanges(); + settingsDb.SaveChanges(); tran.Commit(); } + + urlValue = url.Value; } - } - else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) - { - dbBaseUrl.Value = baseUrl; - using (var tran = ctx.Database.BeginTransaction()) + if (dbBaseUrl == null) { - ctx.SaveChanges(); - tran.Commit(); + if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + { + dbBaseUrl = new ApplicationConfiguration + { + Type = ConfigurationTypes.BaseUrl, + Value = baseUrl + }; + + 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; - Console.WriteLine($"We are running on {urlValue}"); + using (var tran = settingsDb.Database.BeginTransaction()) + { + settingsDb.SaveChanges(); + tran.Commit(); + } + } + + Console.WriteLine($"We are running on {urlValue}"); - CreateWebHostBuilder(args).Build().Run(); + CreateWebHostBuilder(args).Build().Run(); + } } private static void DeleteSchedules() @@ -132,157 +145,6 @@ namespace Ombi } } - ///// - ///// 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(); - - // try - // { - - // using (var tran = settings.Database.BeginTransaction()) - // { - // if (ombi.Settings.Any() && !settings.Settings.Any()) - // { - // // OK migrate it! - // var allSettings = ombi.Settings.ToList(); - // settings.Settings.AddRange(allSettings); - // doneGlobal = true; - // } - - // // Check for any application settings - - // if (ombi.ApplicationConfigurations.Any() && !settings.ApplicationConfigurations.Any()) - // { - // // OK migrate it! - // var allSettings = ombi.ApplicationConfigurations.ToList(); - // settings.ApplicationConfigurations.AddRange(allSettings); - // doneConfig = true; - // } - - // settings.SaveChanges(); - // tran.Commit(); - // } - // } - // catch (Exception e) - // { - // Console.WriteLine(e); - // throw; - // } - - - // 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(); - // } - - // // Now migrate all the external stuff - // var external = new ExternalContext(); - - // try - // { - - // using (var tran = external.Database.BeginTransaction()) - // { - // 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(); - // } - // } - // catch (Exception e) - // { - // Console.WriteLine(e); - // throw; - // } - //} - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 3dd7f1136..f713fe31b 100755 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -192,10 +192,8 @@ namespace Ombi //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" } }; From 22bc7c99b78ef766ccbd40677f29c9b8e5ad293b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 3 Nov 2019 21:57:23 +0000 Subject: [PATCH 22/43] Fix for #3219 --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 0443d06c2..7c056e577 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -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 From 713c0de5f042f96a41f7dae565400fdf308ea670 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 4 Nov 2019 22:24:21 +0000 Subject: [PATCH 23/43] Fixed the issue where exisitng databases would now fail due to the DB structure changes --- src/Ombi.Store/Context/SettingsContext.cs | 2 ++ .../Context/Sqlite/ExternalSqliteContext.cs | 18 +++++++++++++++++- .../Context/Sqlite/OmbiSqliteContext.cs | 18 +++++++++++++++++- .../Context/Sqlite/SettingsSqliteContext.cs | 17 ++++++++++++++++- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index 1ba8c8073..9f6d52791 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -25,6 +25,8 @@ namespace Ombi.Store.Context public DbSet Settings { get; set; } public DbSet ApplicationConfigurations { get; set; } + + public void Seed() { using (var tran = Database.BeginTransaction()) diff --git a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs index 4d159887f..af30920aa 100644 --- a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore; +using System; +using Microsoft.EntityFrameworkCore; namespace Ombi.Store.Context.Sqlite { @@ -10,8 +11,23 @@ namespace Ombi.Store.Context.Sqlite 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 index e6e6f3186..5d6e29e31 100644 --- a/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore; +using System; +using Microsoft.EntityFrameworkCore; namespace Ombi.Store.Context.Sqlite { @@ -11,8 +12,23 @@ namespace Ombi.Store.Context.Sqlite _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 index b5f429853..19e155a71 100644 --- a/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore; +using System; +using Microsoft.EntityFrameworkCore; namespace Ombi.Store.Context.Sqlite { @@ -10,8 +11,22 @@ namespace Ombi.Store.Context.Sqlite 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 From f4933bfc26117fad1bd871dbe19295ce7ac181ed Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 5 Nov 2019 20:55:13 +0000 Subject: [PATCH 24/43] Fixed the migration for combined databases --- .../OmbiMySql/20191102235852_Inital.cs | 150 +--------------- .../OmbiMySqlContextModelSnapshot.cs | 163 ------------------ 2 files changed, 2 insertions(+), 311 deletions(-) diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs index ddd410a3f..8c8294301 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/20191102235852_Inital.cs @@ -73,28 +73,7 @@ namespace Ombi.Store.Migrations.OmbiMySql table.PrimaryKey("PK_Audit", 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: "IssueCategory", columns: table => new @@ -125,29 +104,6 @@ namespace Ombi.Store.Migrations.OmbiMySql table.PrimaryKey("PK_NotificationTemplates", 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: "RecentlyAddedLog", @@ -550,81 +506,6 @@ namespace Ombi.Store.Migrations.OmbiMySql onDelete: ReferentialAction.Restrict); }); - 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.CreateTable( name: "ChildRequests", columns: table => new @@ -837,11 +718,6 @@ namespace Ombi.Store.Migrations.OmbiMySql table: "ChildRequests", column: "RequestedUserId"); - migrationBuilder.CreateIndex( - name: "IX_EmbyEpisode_ParentId", - table: "EmbyEpisode", - column: "ParentId"); - migrationBuilder.CreateIndex( name: "IX_EpisodeRequests_SeasonId", table: "EpisodeRequests", @@ -882,16 +758,6 @@ namespace Ombi.Store.Migrations.OmbiMySql 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", @@ -951,9 +817,6 @@ namespace Ombi.Store.Migrations.OmbiMySql migrationBuilder.DropTable( name: "Audit"); - migrationBuilder.DropTable( - name: "EmbyEpisode"); - migrationBuilder.DropTable( name: "EpisodeRequests"); @@ -966,13 +829,7 @@ namespace Ombi.Store.Migrations.OmbiMySql migrationBuilder.DropTable( name: "NotificationUserId"); - migrationBuilder.DropTable( - name: "PlexEpisode"); - - migrationBuilder.DropTable( - name: "PlexSeasonsContent"); - - migrationBuilder.DropTable( + migrationBuilder.DropTable( name: "RecentlyAddedLog"); migrationBuilder.DropTable( @@ -999,9 +856,6 @@ namespace Ombi.Store.Migrations.OmbiMySql migrationBuilder.DropTable( name: "AspNetRoles"); - migrationBuilder.DropTable( - name: "EmbyContent"); - migrationBuilder.DropTable( name: "SeasonRequests"); diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index f7e598984..7952ce974 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -145,67 +145,6 @@ namespace Ombi.Store.Migrations.OmbiMySql 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") @@ -312,84 +251,6 @@ namespace Ombi.Store.Migrations.OmbiMySql 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") @@ -909,14 +770,6 @@ namespace Ombi.Store.Migrations.OmbiMySql .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") @@ -924,22 +777,6 @@ namespace Ombi.Store.Migrations.OmbiMySql .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") From 63b8b8882cea90ea5e19744a8f834b2dcaaa60d0 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 5 Nov 2019 21:18:25 +0000 Subject: [PATCH 25/43] Output some useful stuff to the about window regarding the databases --- .../ClientApp/app/interfaces/ISettings.ts | 7 ++++ .../app/settings/about/about.component.html | 38 +++++++++++++++++++ src/Ombi/Controllers/SettingsController.cs | 23 ++++++++--- src/Ombi/Extensions/DatabaseExtensions.cs | 25 ++++++------ src/Ombi/Models/AboutViewModel.cs | 7 ++++ 5 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index d3dece200..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 { 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/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 6033ae2ca..69dc08498 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -27,6 +27,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Api.Github; using Ombi.Core.Engine; +using Ombi.Extensions; using Ombi.Schedule; using Quartz; @@ -93,15 +94,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 +244,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 +442,7 @@ namespace Ombi.Controllers [HttpGet("Update")] public async Task UpdateSettings() { - var settings = await Get(); + var settings = await Get(); return Mapper.Map(settings); } @@ -586,7 +597,7 @@ namespace Ombi.Controllers Message = $"CRON Expression {body.Expression} is not valid" }; } - + model.Success = true; return model; } diff --git a/src/Ombi/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs index 82daafff9..2c6d13d06 100644 --- a/src/Ombi/Extensions/DatabaseExtensions.cs +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -19,14 +19,7 @@ namespace Ombi.Extensions public static void ConfigureDatabases(this IServiceCollection services) { - var i = StoragePathSingleton.Instance; - if (string.IsNullOrEmpty(i.StoragePath)) - { - i.StoragePath = string.Empty; - } - - var databaseFileLocation = Path.Combine(i.StoragePath, "database.json"); - var configuration = GetDatabaseConfiguration(databaseFileLocation, i.StoragePath); + var configuration = GetDatabaseConfiguration(); // Ombi db switch (configuration.OmbiDatabase.Type) @@ -60,9 +53,17 @@ namespace Ombi.Extensions } } - public static DatabaseConfiguration GetDatabaseConfiguration(string databaseFileLocation, string storagePath) + public static DatabaseConfiguration GetDatabaseConfiguration() { - var configuration = new DatabaseConfiguration(storagePath); + 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); @@ -94,7 +95,7 @@ namespace Ombi.Extensions { public DatabaseConfiguration() { - + } public DatabaseConfiguration(string defaultSqlitePath) @@ -119,7 +120,7 @@ namespace Ombi.Extensions // Used in Deserialization public PerDatabaseConfiguration() { - + } public string Type { get; set; } public string ConnectionString { get; set; } 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 From 47f323fcdd0740bf1a0aedceedd8b38265bf6377 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Nov 2019 15:51:19 +0000 Subject: [PATCH 26/43] Fixed an error with the newsletter with the new db structure --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 7c056e577..503410d82 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; @@ -66,7 +66,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly IPlexContentRepository _plex; private readonly IEmbyContentRepository _emby; - private readonly IRepository _recentlyAddedLog; + private readonly IExternalRepository _recentlyAddedLog; private readonly IMovieDbApi _movieApi; private readonly ITvMazeApi _tvApi; private readonly IEmailProvider _email; From 96e3e88261970441fc64144ec3c3dfd7cba02b2a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Nov 2019 22:22:53 +0000 Subject: [PATCH 27/43] Fixed the issues where the DB was being disposed too early --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 51 +++++++-------- src/Ombi.Core/Engine/TvRequestEngine.cs | 65 ++++++++++--------- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 1 - .../Jobs/Emby/EmbyContentSync.cs | 1 - .../Jobs/Emby/EmbyEpisodeSync.cs | 1 - .../Jobs/Ombi/Interfaces/IssuesPurge.cs | 1 - .../Jobs/Ombi/MediaDatabaseRefresh.cs | 1 - src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 7 +- .../Jobs/Ombi/RefreshMetadata.cs | 2 - .../Jobs/Plex/PlexAvailabilityChecker.cs | 2 - .../Jobs/Plex/PlexContentSync.cs | 1 - .../Jobs/Plex/PlexEpisodeSync.cs | 1 - .../Context/MySql/OmbiMySqlContext.cs | 5 ++ src/Ombi.Store/Repository/BaseRepository.cs | 40 ++++++------ .../Repository/IExternalRepository.cs | 2 +- src/Ombi.Store/Repository/IRepository.cs | 2 +- 16 files changed, 89 insertions(+), 94 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 456ba267a..51a1c14db 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; } @@ -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/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 796e2fe6a..28ab90a89 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -156,10 +156,10 @@ 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); + allRequests.ForEach(async r => { }); return new RequestsViewModel { @@ -194,7 +194,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 +217,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 +237,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 +256,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 +305,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 +324,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; } @@ -420,7 +421,7 @@ namespace Ombi.Core.Engine public async Task UpdateChildRequest(ChildRequests request) { - await TvRepository.UpdateChild(request); + await TvRepository.UpdateChild(request); return request; } @@ -438,14 +439,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) @@ -520,26 +521,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 +567,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) { @@ -597,7 +604,7 @@ namespace Ombi.Core.Engine 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 +657,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.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 9c92bc509..d713cab80 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -213,7 +213,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..2d4b168af 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -206,7 +206,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..90236aef8 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -156,7 +156,6 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { _settings?.Dispose(); - _repo?.Dispose(); } _disposed = true; } 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..9c1c8b638 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -99,7 +99,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 503410d82..32254f09a 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -66,7 +66,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly IPlexContentRepository _plex; private readonly IEmbyContentRepository _emby; - private readonly IExternalRepository _recentlyAddedLog; + private readonly IRepository _recentlyAddedLog; private readonly IMovieDbApi _movieApi; private readonly ITvMazeApi _tvApi; private readonly IEmailProvider _email; @@ -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; @@ -931,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/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 0ccb736dc..7766119cc 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -352,8 +352,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 72d7f5a2c..a2b1a56cf 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -193,8 +193,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 70ab6878d..f290f2dc9 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -650,7 +650,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..dcf5ea395 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -206,7 +206,6 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - _repo?.Dispose(); _settings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs index a0d11f76a..073a0ed1a 100644 --- a/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs +++ b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs @@ -12,5 +12,10 @@ namespace Ombi.Store.Context.MySql Database.Migrate(); } + + public override void Dispose() + { + base.Dispose(); + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 41a7eeb31..2df4d3467 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -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; - - if (disposing) - { - _ctx?.Dispose(); - } - - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + //private bool _disposed; + //// Protected implementation of Dispose pattern. + //protected virtual void Dispose(bool disposing) + //{ + // if (_disposed) + // return; + + // if (disposing) + // { + // _ctx?.Dispose(); + // } + + // _disposed = true; + //} + + //public void Dispose() + //{ + // Dispose(true); + // GC.SuppressFinalize(this); + //} } } \ No newline at end of file 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(); From 181bd5320249cdb305deb1b223cbc8b90bf1ffd7 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 10 Nov 2019 14:56:12 +0000 Subject: [PATCH 28/43] Fixed the notifications issue --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 10 +- src/Ombi.Core/Engine/MusicRequestEngine.cs | 8 +- src/Ombi.Core/Engine/TvRequestEngine.cs | 11 +-- src/Ombi.Core/Helpers/NotificationHelper.cs | 66 ++++++++----- src/Ombi.Core/Senders/INotificationHelper.cs | 17 ++-- src/Ombi.Core/Senders/MovieSender.cs | 2 +- src/Ombi.Core/Senders/MusicSender.cs | 2 +- src/Ombi.Core/Senders/TvSender.cs | 2 +- src/Ombi.DependencyInjection/IocExtensions.cs | 3 +- .../JobDataKeys.cs | 3 +- src/Ombi.Helpers/Ombi.Helpers.csproj | 1 + .../OmbiQuartz.cs | 10 +- .../Interfaces/INotificationService.cs | 7 +- src/Ombi.Notifications/NotificationService.cs | 99 +++++++------------ src/Ombi.Schedule/IocJobFactory.cs | 16 +-- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 13 +-- .../Jobs/Emby/EmbyEpisodeSync.cs | 1 + .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 10 +- .../Jobs/Plex/PlexAvailabilityChecker.cs | 10 +- src/Ombi.Schedule/OmbiScheduler.cs | 7 ++ src/Ombi.Schedule/QuartzJobRunner.cs | 27 +++++ src/Ombi/Controllers/IssuesController.cs | 10 +- 22 files changed, 184 insertions(+), 151 deletions(-) rename src/{Ombi.Schedule => Ombi.Helpers}/JobDataKeys.cs (52%) rename src/{Ombi.Schedule => Ombi.Helpers}/OmbiQuartz.cs (90%) create mode 100644 src/Ombi.Schedule/QuartzJobRunner.cs diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 51a1c14db..751cc9ebf 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -318,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 @@ -346,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) @@ -462,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 @@ -478,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 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 28ab90a89..74ba55d31 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -159,7 +159,6 @@ namespace Ombi.Core.Engine } await CheckForSubscription(shouldHide, allRequests); - allRequests.ForEach(async r => { }); return new RequestsViewModel { @@ -389,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); } @@ -412,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 @@ -500,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, @@ -585,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 @@ -600,7 +599,7 @@ 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) { 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/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 df0162c1a..c4e66c6f5 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -181,7 +181,8 @@ namespace Ombi.DependencyInjection public static void RegisterJobs(this IServiceCollection services) { - services.AddSingleton(provider => new IoCJobFactory(provider)); + services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); 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/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.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/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.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/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index d713cab80..ade23329d 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -31,6 +31,7 @@ using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -45,7 +46,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 +58,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 +101,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 +192,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 - })); + }); } } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 90236aef8..140d53b0a 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -34,6 +34,7 @@ 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; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index 340164bd5..bdc697773 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -18,7 +19,7 @@ namespace Ombi.Schedule.Jobs.Lidarr public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker { public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, - IBackgroundJobClient job, INotificationService notification) + IBackgroundJobClient job, INotificationHelper notification) { _cachedAlbums = albums; _requestRepository = requests; @@ -31,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Lidarr 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 +60,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/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index a2b1a56cf..78fce3949 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -19,7 +20,7 @@ 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, IBackgroundJobClient background, ILogger log) { _tvRepo = tvRequest; _repo = repo; @@ -32,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Plex private readonly ITvRequestRepository _tvRepo; private readonly IMovieRequestRepository _movieRepo; private readonly IPlexContentRepository _repo; - private readonly INotificationService _notificationService; + private readonly INotificationHelper _notificationService; private readonly IBackgroundJobClient _backgroundJobClient; private readonly ILogger _log; @@ -126,7 +127,8 @@ namespace Ombi.Schedule.Jobs.Plex // We have ful-fulled this request! child.Available = true; child.MarkedAsAvailable = DateTime.Now; - await _notificationService.Publish(new NotificationOptions + + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, @@ -170,7 +172,7 @@ namespace Ombi.Schedule.Jobs.Plex item.RequestId = movie.Id; _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); - await _notificationService.Publish(new NotificationOptions + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, 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/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index 3c8e9c719..72d82fc25 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -27,7 +27,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 +40,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 +152,7 @@ namespace Ombi.Controllers AddIssueNotificationSubstitutes(notificationModel, i, User.Identity.Name); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return i.Id; } @@ -239,7 +239,7 @@ namespace Ombi.Controllers notificationModel.Recipient = user.Email; } - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return await _issueComments.Add(newComment); } @@ -292,7 +292,7 @@ namespace Ombi.Controllers }; AddIssueNotificationSubstitutes(notificationModel, issue, issue.UserReported?.UserAlias ?? string.Empty); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); } From b41fcb467e76a03f3d8c76de65f9234e7b601f30 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 10 Nov 2019 15:05:01 +0000 Subject: [PATCH 29/43] Removed hangfire completly from Ombi --- src/Ombi.Core/Ombi.Core.csproj | 1 - src/Ombi.DependencyInjection/IocExtensions.cs | 2 -- src/Ombi.Schedule.Tests/OmbiQuartzTests.cs | 1 + .../PlexAvailabilityCheckerTests.cs | 8 ++--- src/Ombi.Schedule/IoCJobActivator.cs | 28 ---------------- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 2 -- .../Jobs/Emby/EmbyContentSync.cs | 3 -- .../Jobs/Emby/EmbyEpisodeSync.cs | 1 - .../Jobs/Lidarr/LidarrAlbumSync.cs | 7 ++-- .../Jobs/Lidarr/LidarrArtistSync.cs | 7 ++-- .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 7 +--- .../Ombi/Interfaces/IOmbiAutomaticUpdater.cs | 1 - .../Jobs/Ombi/MediaDatabaseRefresh.cs | 2 -- .../Jobs/Ombi/OmbiAutomaticUpdater.cs | 2 -- .../Jobs/Ombi/RefreshMetadata.cs | 4 --- .../Jobs/Plex/PlexAvailabilityChecker.cs | 7 +--- .../Jobs/Plex/PlexContentSync.cs | 1 - .../Jobs/Plex/PlexEpisodeSync.cs | 1 - src/Ombi.Schedule/Ombi.Schedule.csproj | 6 ---- src/Ombi/Controllers/IdentityController.cs | 6 ++-- src/Ombi/Controllers/IssuesController.cs | 3 -- src/Ombi/Controllers/JobController.cs | 4 --- src/Ombi/Controllers/SettingsController.cs | 3 -- src/Ombi/Ombi.csproj | 5 --- src/Ombi/Startup.cs | 33 +------------------ 25 files changed, 15 insertions(+), 130 deletions(-) delete mode 100644 src/Ombi.Schedule/IoCJobActivator.cs 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.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index c4e66c6f5..cec6bf4e3 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; @@ -183,7 +182,6 @@ namespace Ombi.DependencyInjection { services.AddSingleton(); services.AddSingleton(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs index 3c728300d..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 { 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/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index ade23329d..baeb3c5c5 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -28,11 +28,9 @@ using System; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Ombi; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 2d4b168af..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 diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 140d53b0a..1f67db4bc 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -29,7 +29,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.Core.Settings; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 09bd787e7..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; @@ -18,13 +17,12 @@ namespace Ombi.Schedule.Jobs.Lidarr public class LidarrAlbumSync : ILidarrAlbumSync { public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, - IBackgroundJobClient job, ILidarrAvailabilityChecker availability) + ILidarrAvailabilityChecker availability) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; - _job = job; _availability = availability; } @@ -32,7 +30,6 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; private readonly ExternalContext _ctx; - private readonly IBackgroundJobClient _job; 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 317b5821e..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; @@ -19,13 +18,12 @@ namespace Ombi.Schedule.Jobs.Lidarr public class LidarrArtistSync : ILidarrArtistSync { public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, - IBackgroundJobClient background, ILidarrAlbumSync album) + ILidarrAlbumSync album) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; - _job = background; _albumSync = album; } @@ -33,7 +31,6 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; private readonly ExternalContext _ctx; - private readonly IBackgroundJobClient _job; 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 bdc697773..37abd68a2 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -2,11 +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; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Store.Entities; @@ -18,20 +16,17 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker { - public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, - IBackgroundJobClient job, INotificationHelper 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 INotificationHelper _notificationService; public async Task Start() 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/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs index 9c1c8b638..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; 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 7766119cc..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; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 78fce3949..34643aa73 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -1,12 +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; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Store.Entities; @@ -20,13 +17,12 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationHelper notification, IBackgroundJobClient background, ILogger log) + INotificationHelper notification, ILogger log) { _tvRepo = tvRequest; _repo = repo; _movieRepo = movies; _notificationService = notification; - _backgroundJobClient = background; _log = log; } @@ -34,7 +30,6 @@ namespace Ombi.Schedule.Jobs.Plex private readonly IMovieRequestRepository _movieRepo; private readonly IPlexContentRepository _repo; private readonly INotificationHelper _notificationService; - private readonly IBackgroundJobClient _backgroundJobClient; private readonly ILogger _log; public async Task Execute(IJobExecutionContext job) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index f290f2dc9..ee16b1efd 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; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index dcf5ea395..fe23e9a9f 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; 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/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 72d82fc25..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 { 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/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 69dc08498..ed246806a 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; @@ -28,7 +26,6 @@ using Ombi.Store.Repository; using Ombi.Api.Github; using Ombi.Core.Engine; using Ombi.Extensions; -using Ombi.Schedule; using Quartz; namespace Ombi.Controllers diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index a5a3ed68e..b150b0244 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -65,11 +65,6 @@ - - - - - diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index f713fe31b..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; @@ -93,13 +89,6 @@ namespace Ombi services.AddSwagger(); services.AddAppSettingsValues(Configuration); - services.AddHangfire(x => - { - x.UseMemoryStorage(); - x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); - }); - - services.AddCors(o => o.AddPolicy("MyPolicy", builder => { builder.AllowAnyOrigin() @@ -176,19 +165,7 @@ 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(); @@ -233,12 +210,4 @@ namespace Ombi }); } } - - public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter - { - public bool Authorize(DashboardContext context) - { - return true; - } - } } From ef5a382a1e0b5c9dbd856eedbcbfc114378d464c Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 10 Nov 2019 19:31:33 +0000 Subject: [PATCH 30/43] Update login.component.ts Reduced oauth time --- src/Ombi/ClientApp/app/login/login.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 957ced058..4a7d554c9 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); + }, 3000); }); }); } From 53ecd7b95fe53d436f120fb3aeabd5e473419c6b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 12 Nov 2019 22:47:01 +0000 Subject: [PATCH 31/43] Fixed the issue where we couldn't always pick up stuff on the sync --- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 3 --- src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index ee16b1efd..d4cd7c040 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -109,9 +109,6 @@ namespace Ombi.Schedule.Jobs.Plex { Logger.LogInformation("Kicking off Plex Availability Checker"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); - Logger.LogInformation("Starting Metadata refresh"); - // Just check what we send it - await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); } 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); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index fe23e9a9f..b8829569e 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -9,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; @@ -54,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"); } From 0da0da7d86d167c874e9cc2cfb71637bca9ee6d7 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 12 Nov 2019 22:48:14 +0000 Subject: [PATCH 32/43] !changelog --- CHANGELOG.md | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a611b5b99..6febb6683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,77 @@ # Changelog -## v3.0.4817 (2019-10-15) +## (unreleased) + +### **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** @@ -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] From 93f5f94a1467269a008eacd8d4a7e54aa730744c Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 12 Nov 2019 22:52:44 +0000 Subject: [PATCH 33/43] !wip --- src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index b8829569e..2ba054aeb 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -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(IRefreshMetadata), "System"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } From 58cc49d607baac74812e7803ca0602d35f280a61 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Nov 2019 22:01:28 +0000 Subject: [PATCH 34/43] Fixed issues with the RequestId Migration #3244 #3253 #3249 --- .../Context/Sqlite/ExternalSqliteContext.cs | 9 +- src/Ombi.Store/Migration.txt | 2 +- .../20191113213617_RequestIdPatch.Designer.cs | 314 ++++++++++++++++++ .../20191113213617_RequestIdPatch.cs | 22 ++ .../ClientApp/app/login/login.component.ts | 2 +- 5 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs diff --git a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs index af30920aa..fe4a93586 100644 --- a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace Ombi.Store.Context.Sqlite @@ -13,7 +14,13 @@ namespace Ombi.Store.Context.Sqlite _created = true; Upgrade(); Database.SetCommandTimeout(60); - Database.Migrate(); + try + { + Database.Migrate(); + } + catch (SqliteException e) when (e.Message.Equals("duplicate column name: RequestId")) + { + } } diff --git a/src/Ombi.Store/Migration.txt b/src/Ombi.Store/Migration.txt index 5d1131a75..331299143 100644 --- a/src/Ombi.Store/Migration.txt +++ b/src/Ombi.Store/Migration.txt @@ -1,3 +1,3 @@ -dotnet ef migrations add Inital --context OmbiContext --startup-project ../Ombi/Ombi.csproj +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/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..2d0622d0f --- /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/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 4a7d554c9..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); - }, 3000); + }, 4000); }); }); } From 3bd9b18b33df0442a83a1acc76433d66560999e3 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 15 Nov 2019 22:47:51 +0000 Subject: [PATCH 35/43] Fixed the startup error --- src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs | 10 +++------- .../ExternalSqlite/20191113213617_RequestIdPatch.cs | 8 ++++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs index fe4a93586..adbf6e017 100644 --- a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -14,13 +14,9 @@ namespace Ombi.Store.Context.Sqlite _created = true; Upgrade(); Database.SetCommandTimeout(60); - try - { - Database.Migrate(); - } - catch (SqliteException e) when (e.Message.Equals("duplicate column name: RequestId")) - { - } + + Database.Migrate(); + } diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs index 2d0622d0f..29c1a4033 100644 --- a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs @@ -8,10 +8,10 @@ namespace Ombi.Store.Migrations.ExternalSqlite protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.AddColumn( - name: "RequestId", - table: "PlexServerContent", - nullable: true); + //migrationBuilder.AddColumn( + // name: "RequestId", + // table: "PlexServerContent", + // nullable: true); } protected override void Down(MigrationBuilder migrationBuilder) From faba87cdc62f3867ae78ee304d150a6c00b3785b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 20 Nov 2019 21:35:04 +0000 Subject: [PATCH 36/43] Fix for #3277 --- src/Ombi.Helpers.Tests/PlexHelperTests.cs | 2 + src/Ombi.Helpers/PlexHelper.cs | 88 +++++------------------ 2 files changed, 21 insertions(+), 69 deletions(-) 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.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; } From cdc002ecd73c1ac939c009981b0b96d6ac9dc157 Mon Sep 17 00:00:00 2001 From: Namaneo Date: Fri, 29 Nov 2019 16:05:14 +0100 Subject: [PATCH 37/43] Add webhook notification and API logic --- src/Ombi.Api.Webhook/IWebhookApi.cs | 10 ++ src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj | 15 +++ src/Ombi.Api.Webhook/WebhookApi.cs | 36 ++++++ .../Models/UI/WebhookNotificationViewModel.cs | 15 +++ .../Agents/Interfaces/IWebhookNotification.cs | 6 + .../Agents/WebhookNotification.cs | 116 ++++++++++++++++++ .../Models/Notifications/WebhookSettings.cs | 9 ++ src/Ombi.sln | 11 +- 8 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Api.Webhook/IWebhookApi.cs create mode 100644 src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj create mode 100644 src/Ombi.Api.Webhook/WebhookApi.cs create mode 100644 src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs create mode 100644 src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs create mode 100644 src/Ombi.Notifications/Agents/WebhookNotification.cs create mode 100644 src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs diff --git a/src/Ombi.Api.Webhook/IWebhookApi.cs b/src/Ombi.Api.Webhook/IWebhookApi.cs new file mode 100644 index 000000000..755c7c789 --- /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, IReadOnlyDictionary 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..509de2622 --- /dev/null +++ b/src/Ombi.Api.Webhook/WebhookApi.cs @@ -0,0 +1,36 @@ +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, IReadOnlyDictionary parameters) + { + var request = new Request("/", baseUrl, HttpMethod.Post); + request.AddHeader("Access-Token", accessToken); + request.ApplicationJsonContentType(); + + var body = parameters.ToDictionary( + x => _nameResolver.GetResolvedPropertyName(x.Key), + x => x.Value + ); + + request.AddJsonBody(body); + + await _api.Request(request); + } + } +} 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.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..fbbb1d352 --- /dev/null +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -0,0 +1,116 @@ +using System; +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 message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + var notification = new NotificationMessage + { + Message = message, + }; + 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 notification = new NotificationMessage + { + Data = parsed.Data, + }; + + await Send(notification, settings); + } + } +} 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.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} From 88f3f0f9f09b86efbb7e4475127c7d34854f08cc Mon Sep 17 00:00:00 2001 From: Namaneo Date: Fri, 29 Nov 2019 16:06:51 +0100 Subject: [PATCH 38/43] Integrate webhooks into existing notification mechanism --- src/Ombi.DependencyInjection/IocExtensions.cs | 3 ++ .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/LoggingEvents.cs | 1 + src/Ombi.Helpers/NotificationAgent.cs | 1 + src/Ombi.Mapping/Profiles/SettingsProfile.cs | 1 + .../Models/NotificationMessage.cs | 1 + .../NotificationMessageContent.cs | 5 +++- .../NotificationMessageResolver.cs | 2 +- .../Ombi.Notifications.csproj | 1 + .../Controllers/External/TesterController.cs | 28 ++++++++++++++++++- src/Ombi/Controllers/SettingsController.cs | 27 ++++++++++++++++++ 11 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index cec6bf4e3..f50417189 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -32,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; @@ -122,6 +123,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -173,6 +175,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); 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/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.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/Models/NotificationMessage.cs b/src/Ombi.Notifications/Models/NotificationMessage.cs index f14604d3f..d336d830e 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 IReadOnlyDictionary 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/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/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/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index ed246806a..df480865f 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -1007,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. /// From c8cdf0056756947615a752c6482dc2ea8c82c3f3 Mon Sep 17 00:00:00 2001 From: Namaneo Date: Fri, 29 Nov 2019 16:07:35 +0100 Subject: [PATCH 39/43] Add settings view for webhook configuration --- README.md | 1 + .../app/interfaces/INotificationSettings.ts | 5 ++ .../services/applications/tester.service.ts | 5 ++ .../app/services/settings.service.ts | 9 +++ .../notifications/webhook.component.html | 47 ++++++++++++++ .../notifications/webhook.component.ts | 64 +++++++++++++++++++ .../ClientApp/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + 8 files changed, 135 insertions(+) create mode 100644 src/Ombi/ClientApp/app/settings/notifications/webhook.component.html create mode 100644 src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts 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/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/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index af619d583..bf6801e66 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -12,6 +12,7 @@ import { IEmailNotificationSettings, IEmbyServer, IGotifyNotificationSettings, + IWebhookNotificationSettings, ILidarrSettings, IMattermostNotifcationSettings, IMobileNotificationTestSettings, @@ -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/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 8c7787b6d..dbf0d129c 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -15,6 +15,7 @@ import { IEmailNotificationSettings, IEmbySettings, IGotifyNotificationSettings, + IWebhookNotificationSettings, IIssueSettings, IJobSettings, IJobSettingsViewModel, @@ -192,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}); } 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..6773886f8 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html @@ -0,0 +1,47 @@ + + +
    +
    + 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..c72c59ed8 --- /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 { IWebhookNotificationSettings, INotificationTemplates, 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 377756e56..6fe8c7b30 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -29,6 +29,7 @@ import { MassEmailComponent } from "./massemail/massemail.component"; import { DiscordComponent } from "./notifications/discord.component"; import { EmailNotificationComponent } from "./notifications/emailnotification.component"; import { GotifyComponent } from "./notifications/gotify.component"; +import { WebhookComponent } from "./notifications/webhook.component"; import { MattermostComponent } from "./notifications/mattermost.component"; import { MobileComponent } from "./notifications/mobile.component"; import { NewsletterComponent } from "./notifications/newsletter.component"; @@ -67,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] }, @@ -124,6 +126,7 @@ const routes: Routes = [ MattermostComponent, PushbulletComponent, GotifyComponent, + WebhookComponent, UserManagementComponent, UpdateComponent, AboutComponent, diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 686f4c020..eb0f3f4bb 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -76,6 +76,7 @@
  • Mattermost
  • Telegram
  • Gotify
  • +
  • Webhook
  • From 78ac3984cb2c812a872521986b02c9a370609017 Mon Sep 17 00:00:00 2001 From: Namaneo Date: Sat, 30 Nov 2019 18:13:42 +0100 Subject: [PATCH 40/43] Fix lint issues on UI --- src/Ombi/ClientApp/app/services/applications/tester.service.ts | 2 +- src/Ombi/ClientApp/app/services/settings.service.ts | 2 +- .../ClientApp/app/settings/notifications/webhook.component.ts | 2 +- src/Ombi/ClientApp/app/settings/settings.module.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index bf6801e66..5b7a4cd63 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -12,7 +12,6 @@ import { IEmailNotificationSettings, IEmbyServer, IGotifyNotificationSettings, - IWebhookNotificationSettings, ILidarrSettings, IMattermostNotifcationSettings, IMobileNotificationTestSettings, @@ -25,6 +24,7 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + IWebhookNotificationSettings, } from "../../interfaces"; @Injectable() diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index dbf0d129c..17ba342aa 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -15,7 +15,6 @@ import { IEmailNotificationSettings, IEmbySettings, IGotifyNotificationSettings, - IWebhookNotificationSettings, IIssueSettings, IJobSettings, IJobSettingsViewModel, @@ -37,6 +36,7 @@ import { IUpdateSettings, IUserManagementSettings, IVoteSettings, + IWebhookNotificationSettings, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; diff --git a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts index c72c59ed8..d410b2b44 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { IWebhookNotificationSettings, INotificationTemplates, NotificationType } from "../../interfaces"; +import { INotificationTemplates, IWebhookNotificationSettings, NotificationType } from "../../interfaces"; import { TesterService } from "../../services"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6fe8c7b30..3f0979ea0 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -29,7 +29,6 @@ import { MassEmailComponent } from "./massemail/massemail.component"; import { DiscordComponent } from "./notifications/discord.component"; import { EmailNotificationComponent } from "./notifications/emailnotification.component"; import { GotifyComponent } from "./notifications/gotify.component"; -import { WebhookComponent } from "./notifications/webhook.component"; import { MattermostComponent } from "./notifications/mattermost.component"; import { MobileComponent } from "./notifications/mobile.component"; import { NewsletterComponent } from "./notifications/newsletter.component"; @@ -38,6 +37,7 @@ 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"; From 8ae98c91c1d944b01de1259455ff8c2372b67739 Mon Sep 17 00:00:00 2001 From: Namaneo Date: Sat, 30 Nov 2019 18:18:33 +0100 Subject: [PATCH 41/43] Minor updates related to Github's comments * Access-Token Header is not sent if it has not been configured (or left blank) * Access token is now also sent in URI string with "token" as key * NotificationType is manually added to the notification data (original data is cloned before to avoid conflict in case of re-usage by other notification handlers) --- src/Ombi.Api.Webhook/IWebhookApi.cs | 2 +- src/Ombi.Api.Webhook/WebhookApi.cs | 11 ++++++++--- src/Ombi.Notifications/Agents/WebhookNotification.cs | 5 ++++- src/Ombi.Notifications/Models/NotificationMessage.cs | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Ombi.Api.Webhook/IWebhookApi.cs b/src/Ombi.Api.Webhook/IWebhookApi.cs index 755c7c789..6a22a8b02 100644 --- a/src/Ombi.Api.Webhook/IWebhookApi.cs +++ b/src/Ombi.Api.Webhook/IWebhookApi.cs @@ -5,6 +5,6 @@ namespace Ombi.Api.Webhook { public interface IWebhookApi { - Task PushAsync(string endpoint, string accessToken, IReadOnlyDictionary parameters); + Task PushAsync(string endpoint, string accessToken, IDictionary parameters); } } \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/WebhookApi.cs b/src/Ombi.Api.Webhook/WebhookApi.cs index 509de2622..b794c3d2f 100644 --- a/src/Ombi.Api.Webhook/WebhookApi.cs +++ b/src/Ombi.Api.Webhook/WebhookApi.cs @@ -17,17 +17,22 @@ namespace Ombi.Api.Webhook private readonly IApi _api; - public async Task PushAsync(string baseUrl, string accessToken, IReadOnlyDictionary parameters) + public async Task PushAsync(string baseUrl, string accessToken, IDictionary parameters) { var request = new Request("/", baseUrl, HttpMethod.Post); - request.AddHeader("Access-Token", accessToken); - request.ApplicationJsonContentType(); + + if (!string.IsNullOrWhiteSpace(accessToken)) + { + request.AddQueryString("token", 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.Notifications/Agents/WebhookNotification.cs b/src/Ombi.Notifications/Agents/WebhookNotification.cs index fbbb1d352..05a9c3763 100644 --- a/src/Ombi.Notifications/Agents/WebhookNotification.cs +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Api.Webhook; @@ -105,9 +106,11 @@ namespace Ombi.Notifications.Agents return; } + var notificationData = parsed.Data.ToDictionary(x => x.Key, x => x.Value); + notificationData[nameof(NotificationType)] = type.ToString(); var notification = new NotificationMessage { - Data = parsed.Data, + Data = notificationData, }; await Send(notification, settings); diff --git a/src/Ombi.Notifications/Models/NotificationMessage.cs b/src/Ombi.Notifications/Models/NotificationMessage.cs index d336d830e..7ffd48e63 100644 --- a/src/Ombi.Notifications/Models/NotificationMessage.cs +++ b/src/Ombi.Notifications/Models/NotificationMessage.cs @@ -9,6 +9,6 @@ namespace Ombi.Notifications.Models public string To { get; set; } public Dictionary Other { get; set; } = new Dictionary(); - public IReadOnlyDictionary Data { get; set; } + public IDictionary Data { get; set; } } } \ No newline at end of file From 1176be7f20f92e67fd8ee9b5f7e81b34f882e1bc Mon Sep 17 00:00:00 2001 From: Namaneo Date: Sat, 30 Nov 2019 19:06:55 +0100 Subject: [PATCH 42/43] Add explanation tooltip on webhook settings view Also remove token from URI string: should be added by user in settings view --- src/Ombi.Api.Webhook/WebhookApi.cs | 1 - .../app/settings/notifications/webhook.component.html | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Api.Webhook/WebhookApi.cs b/src/Ombi.Api.Webhook/WebhookApi.cs index b794c3d2f..8b6b35ca0 100644 --- a/src/Ombi.Api.Webhook/WebhookApi.cs +++ b/src/Ombi.Api.Webhook/WebhookApi.cs @@ -23,7 +23,6 @@ namespace Ombi.Api.Webhook if (!string.IsNullOrWhiteSpace(accessToken)) { - request.AddQueryString("token", accessToken); request.AddHeader("Access-Token", accessToken); } diff --git a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html index 6773886f8..ed6eb43b9 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/webhook.component.html @@ -21,7 +21,9 @@
    - + The Application Token is required From 1ac37cd9ecceacaa434f4dfd3ed3f4e410e06c60 Mon Sep 17 00:00:00 2001 From: Namaneo Date: Sun, 1 Dec 2019 11:45:42 +0100 Subject: [PATCH 43/43] Improve webhook test to use more accurate payload --- src/Ombi.Notifications/Agents/WebhookNotification.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Notifications/Agents/WebhookNotification.cs b/src/Ombi.Notifications/Agents/WebhookNotification.cs index 05a9c3763..2339b6abf 100644 --- a/src/Ombi.Notifications/Agents/WebhookNotification.cs +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -89,11 +89,15 @@ namespace Ombi.Notifications.Agents protected override async Task Test(NotificationOptions model, WebhookSettings settings) { - var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + 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 { - Message = message, + Data = testData, }; + await Send(notification, settings); }