From 6d7274a94ea24343f32fc028984bd3fd5d5f2ee3 Mon Sep 17 00:00:00 2001 From: Maxence Lecanu Date: Tue, 25 Jan 2022 09:45:42 +0100 Subject: [PATCH 001/210] fix(frontend): add link on logo text * feat(frontend): add link on logo text * fix(frontend): display logo-link only if an url is set Co-authored-by: Maxence Lecanu --- src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html | 7 ++++++- src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html index 85abdbf0a..f35a8f612 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html @@ -3,7 +3,12 @@ [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)"> - {{applicationName}} + + {{applicationName}} + + + {{applicationName}} + diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss index e83ae2d66..80a00c6bb 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss @@ -165,6 +165,15 @@ display: flex; white-space: normal; word-break: break-word; + + .application-name-link { + text-decoration: none; + color: inherit; + + &:active, &:hover, &:focus { + color: inherit; + } + } } .outer-profile { From 6b2cf23a5cab3080503fb0447c2317211c03d1f2 Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Tue, 25 Jan 2022 08:46:00 +0000 Subject: [PATCH 002/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6b785e94f..5a1aec978 100644 --- a/README.md +++ b/README.md @@ -594,6 +594,13 @@ Here are some of the features Ombi has: Matt + + + LMaxence +
+ Maxence Lecanu +
+ AliMickey @@ -621,15 +628,15 @@ Here are some of the features Ombi has:
Rob Gökemeijer
- + + sambartik
Samuel Bartík
- - + seancallinan @@ -664,15 +671,15 @@ Here are some of the features Ombi has:
Tom McClellan
- + + Torkiliuz
Torkil
- - + bybeet @@ -707,15 +714,15 @@ Here are some of the features Ombi has:
Camjac251
- + + distaula
Michael DiStaula
- - + baikunz @@ -750,15 +757,15 @@ Here are some of the features Ombi has:
Sirmarv
- + + tdorsey
Tdorsey
- - + thegame3202 From cc55d3fcf41dabdcc1d85f8eceb5e3aa050197eb Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 25 Jan 2022 08:46:25 +0000 Subject: [PATCH 003/210] =?UTF-8?q?chore:=20=F0=9F=8C=90=20Translations=20?= =?UTF-8?q?Update=20(#4476)=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] --- src/Ombi/wwwroot/translations/es.json | 88 +++++++++++++-------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 8bf684664..a09d958d0 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -38,7 +38,7 @@ "Update": "Actualización", "tvShow": "Programa de televisión", "movie": "Película", - "album": "Album" + "album": "Álbum" }, "PasswordReset": { "EmailAddressPlaceholder": "Correo electrónico", @@ -204,7 +204,7 @@ "Approved": "Los elementos seleccionados ha sido aprobados correctamente" }, "SuccessfullyApproved": "Se ha aprobado con éxito", - "SuccessfullyDeleted": "Request successfully deleted", + "SuccessfullyDeleted": "Solicitud eliminada con éxito", "NowAvailable": "La solicitud está disponible", "NowUnavailable": "La solicitud no está disponible", "SuccessfullyReprocessed": "La solicitud ha sido procesada correctamente", @@ -214,21 +214,21 @@ "NeedToSelectEpisodes": "¡Necesitas seleccionar algunos episodios!", "RequestAddedSuccessfully": "La solicitud de {{title}} se ha añadido correctamente", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", + "AlreadyRequested": "Ya se ha solicitado", "EpisodesAlreadyRequested": "We already have episodes requested from this series", "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "RequestDoesNotExist": "Esta petición no existe", "ChildRequestDoesNotExist": "Child Request does not exist", "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", + "NoPermissionsRequestTV": "No tienes permiso para solicitar un Programa de televisión", + "NoPermissionsRequestAlbum": "No tienes permiso para solicitar un Álbum", + "MovieRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de películas!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", + "Notify": "Notificar", + "RemoveNotification": "Eliminar notificación", "SuccessfulNotify": "You will now be notified for title {{title}}", "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", "CouldntNotify": "Couldn't notify title {{title}}" @@ -317,7 +317,7 @@ "Rumored": "Rumored", "Planned": "Planificado", "In Production": "En Producción", - "Post Production": "Post Production", + "Post Production": "Post-Producción", "Released": "En cines", "Running": "Running", "Returning Series": "Returning Series", @@ -331,18 +331,18 @@ "Quality": "Calidad:", "RootFolderOverride": "Root Folder Override:", "QualityOverride": "Quality Override:", - "Network": "Network:", + "Network": "Cadena:", "GenresLabel": "Géneros:", "Genres": "Géneros", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "FirstAired": "Emitido por primera vez:", + "TheatricalRelease": "Lanzamiento:", + "DigitalRelease": "Estreno Digital:", + "Votes": "Votos:", + "Runtime": "Duración:", "Minutes": "{{runtime}} Minutos", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Revenue": "Ingresos:", + "Budget": "Presupuesto:", + "Keywords": "Palabras clave/Etiquetas:", "Casts": { "CastTitle": "Enviar pantalla" }, @@ -350,22 +350,22 @@ "AllSeasonsTooltip": "Esto solicitará cada temporada para este programa", "FirstSeasonTooltip": "Esto solo solicitará la primera temporada para este programa", "LatestSeasonTooltip": "Esto solo solicitará la última temporada para este programa", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "NoEpisodes": "Lamentablemente, no hay datos de episodio para este programa de televisión todavía!", + "SeasonNumber": "Temporada {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", + "SonarrConfiguration": "Configuración de Sonarr", + "RadarrConfiguration": "Configuración de Radarr", + "RequestOnBehalf": "Solicitar en nombre de", + "PleaseSelectUser": "Seleccione un usuario", "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "RequestedBy": "Solicitado por:", "RequestedByOn": "Solicitado por {{user}} el {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Fecha de solicitud:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", "Music": { - "Type": "Type:", - "Country": "Country:", + "Type": "Tipo:", + "Country": "País:", "StartDate": "Start Date:", "EndDate": "EndDate:" } @@ -375,7 +375,7 @@ "TrendingTab": "Tendencias", "UpcomingTab": "Próximamente", "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "RecentlyRequestedTab": "Solicitudes recientes", "Movies": "Películas", "Combined": "Combinado", "Tv": "TV", @@ -391,36 +391,36 @@ "Writer": "Guionistas", "ExecProducer": "Productor ejecutivo" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "¡Lo sentimos, nada coincide con tu búsqueda!" }, "UserPreferences": { "Welcome": "Bienvenido {{username}}!", "OmbiLanguage": "Idioma", "DarkMode": "Modo Oscuro", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", + "Updated": "Actualizado correctamente", + "StreamingCountry": "País de emisión", + "StreamingCountryDescription": "Este es el código de país desde el que mostraremos información de emisión. Si estás en España, por favor selecciona ES y tendrás información relacionada con la emisión en España.", + "LanguageDescription": "Este es el idioma en el que desea mostrar la interfaz de Ombi.", "MobileQRCode": "Mobile QR Code", "LegacyApp": "Launch Legacy App", "NoQrCode": "Please contact your administrator to enable QR codes", "UserType": "User Type:", - "ChangeDetails": "Change Details", + "ChangeDetails": "Modificar mis datos", "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", + "CurrentPassword": "Contraseña actual", + "EmailAddress": "Correo electrónico", + "NewPassword": "Nueva Contraseña", + "NewPasswordConfirm": "Confirmar contraseña", + "Security": "Seguridad", + "Profile": "Perfil", + "UpdatedYourInformation": "Información actualizada", "Unsubscribed": "No suscrito!" }, "UserTypeLabel": { "1": "Usuario local", "2": "Usuario de Plex", "3": "Usuario de Emby", - "4": "Emby Connect User", + "4": "Conectar usuario de Emby", "5": "Usuario de Jellyfin" }, "Paginator": { From 32ee4e88ec05bf610150933974408fbe95ccd7bd Mon Sep 17 00:00:00 2001 From: Qiming Chen Date: Mon, 31 Jan 2022 11:21:56 -0800 Subject: [PATCH 004/210] fix: fix swagger api key auth (#4483) [no ci] --- src/Ombi/Extensions/StartupExtensions.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Ombi/Extensions/StartupExtensions.cs b/src/Ombi/Extensions/StartupExtensions.cs index e3253045a..296339dd0 100644 --- a/src/Ombi/Extensions/StartupExtensions.cs +++ b/src/Ombi/Extensions/StartupExtensions.cs @@ -41,6 +41,21 @@ namespace Ombi Type = SecuritySchemeType.ApiKey }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + } + }, + new string[] {} + } + }); + c.CustomSchemaIds(x => x.FullName); try From 0ff0a704ff40d0a0f9339d9e0c863a630a7b41bd Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Mon, 31 Jan 2022 21:15:31 +0100 Subject: [PATCH 005/210] =?UTF-8?q?refactor(newsletter):=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F=20Media=20servers=20+=20newsletter=20refactoring=20(#?= =?UTF-8?q?4463)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Abstract media servers content into interfaces * Media server entities into abstract classes * Abstract media server content repository * First pass at newsletter refactoring * Minor code clean up * Attempt at abstracting repositories (WIP) * Fixed cast issue * Corrected the other properties * A step towards newsletter refactoring * Clean up leftovers * Fix broken episodes db interaction * Save absolute URL for Plex content Let's be consistent with Emby and Jellyfin * Fix broken integration with Plex libraries * Fix error when multiple media servers configured * Fix newsletter being sent if no movies or episodes * Fix broken tests * Remove unneccesary logs * Expose stored media server URL No need to recalculate it + Plex URL was broken due to an earlier change * Remove unused variable * Remove obsolete tests URLs are now fetched from database directly * Retro-compatibility for Plex content URL Solves URL for media synced before absolute URL was saved in PlexServerContent * chore: added some obsoletes * fix: removed the unsub link when not present Co-authored-by: tidusjar --- src/.idea/.idea.Ombi/.idea/contentModel.xml | 4 +- src/Ombi.Api.Emby/Models/EmbyMediaType.cs | 10 - .../Models/JellyfinMediaType.cs | 10 - .../Request/ExistingPlexRequestRuleTests.cs | 4 +- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 65 +- .../Search/JellyfinAvailabilityRuleTests.cs | 35 +- src/Ombi.Core/Engine/RecentlyAddedEngine.cs | 30 +- .../Rules/Request/ExistingPlexRequestRule.cs | 2 +- .../Rules/Search/AvailabilityRuleHelper.cs | 66 +- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 21 +- .../Rules/Search/JellyfinAvailabilityRule.cs | 22 +- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 22 +- src/Ombi.Helpers/PlexHelper.cs | 4 +- .../NewsletterTemplate.cs | 2 + .../Templates/NewsletterTemplate.html | 2 +- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 2 +- .../Jobs/Emby/EmbyContentSync.cs | 10 +- .../Jellyfin/JellyfinAvaliabilityChecker.cs | 2 +- .../Jobs/Jellyfin/JellyfinContentSync.cs | 8 +- .../Jobs/Ombi/HtmlTemplateGenerator.cs | 17 +- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 872 ++++-------------- .../Jobs/Ombi/RefreshMetadata.cs | 12 +- .../Jobs/Plex/PlexAvailabilityChecker.cs | 5 +- .../Jobs/Plex/PlexContentSync.cs | 22 +- .../Jobs/Plex/PlexEpisodeSync.cs | 2 +- src/Ombi.Store/Context/ExternalContext.cs | 15 +- src/Ombi.Store/Entities/EmbyContent.cs | 33 +- src/Ombi.Store/Entities/EmbyEpisode.cs | 26 +- src/Ombi.Store/Entities/Entity.cs | 2 +- src/Ombi.Store/Entities/IEntity.cs | 10 + .../Entities/IMediaServerContent.cs | 57 ++ src/Ombi.Store/Entities/JellyfinContent.cs | 34 +- src/Ombi.Store/Entities/JellyfinEpisode.cs | 26 +- src/Ombi.Store/Entities/MediaServerContent.cs | 47 + src/Ombi.Store/Entities/PlexEpisode.cs | 32 +- src/Ombi.Store/Entities/PlexServerContent.cs | 29 +- .../Repository/EmbyContentRepository.cs | 25 +- .../Repository/IEmbyContentRepository.cs | 13 +- .../Repository/IExternalRepository.cs | 3 +- .../Repository/IJellyfinContentRepository.cs | 13 +- .../IMediaServerContentRepository.cs | 18 + .../Repository/IPlexContentRepository.cs | 9 +- src/Ombi.Store/Repository/IRepository.cs | 3 +- .../Repository/JellyfinContentRepository.cs | 27 +- .../Repository/MediaServerRepository.cs | 25 + .../Repository/PlexContentRepository.cs | 35 +- 46 files changed, 590 insertions(+), 1143 deletions(-) delete mode 100644 src/Ombi.Api.Emby/Models/EmbyMediaType.cs delete mode 100644 src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs create mode 100644 src/Ombi.Store/Entities/IEntity.cs create mode 100644 src/Ombi.Store/Entities/IMediaServerContent.cs create mode 100644 src/Ombi.Store/Entities/MediaServerContent.cs create mode 100644 src/Ombi.Store/Repository/IMediaServerContentRepository.cs create mode 100644 src/Ombi.Store/Repository/MediaServerRepository.cs diff --git a/src/.idea/.idea.Ombi/.idea/contentModel.xml b/src/.idea/.idea.Ombi/.idea/contentModel.xml index 4affa7aee..438274536 100644 --- a/src/.idea/.idea.Ombi/.idea/contentModel.xml +++ b/src/.idea/.idea.Ombi/.idea/contentModel.xml @@ -929,7 +929,7 @@ - + @@ -1876,7 +1876,7 @@ - + diff --git a/src/Ombi.Api.Emby/Models/EmbyMediaType.cs b/src/Ombi.Api.Emby/Models/EmbyMediaType.cs deleted file mode 100644 index 7b33f8972..000000000 --- a/src/Ombi.Api.Emby/Models/EmbyMediaType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ombi.Api.Emby.Models -{ - public enum EmbyMediaType - { - Movie = 0, - Series = 1, - Music = 2, - Episode = 3 - } -} \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs b/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs deleted file mode 100644 index 2c4f75be0..000000000 --- a/src/Ombi.Api.Jellyfin/Models/JellyfinMediaType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ombi.Api.Jellyfin.Models -{ - public enum JellyfinMediaType - { - Movie = 0, - Series = 1, - Music = 2, - Episode = 3 - } -} \ No newline at end of file diff --git a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs index f5a362303..3cabfa438 100644 --- a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs @@ -182,11 +182,11 @@ namespace Ombi.Core.Tests.Rule.Request { new PlexServerContent { - Type = PlexMediaTypeEntity.Show, + Type = MediaType.Series, TheMovieDbId = "1", Title = "Test", ReleaseYear = "2001", - Episodes = new List + Episodes = new List { new PlexEpisode { diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 132f51e49..0e455418a 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; @@ -18,12 +19,14 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); + LoggerMock = new Mock>(); SettingsMock = new Mock>(); - Rule = new EmbyAvailabilityRule(ContextMock.Object, SettingsMock.Object); + Rule = new EmbyAvailabilityRule(ContextMock.Object, LoggerMock.Object, SettingsMock.Object); } private EmbyAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } + private Mock> LoggerMock { get; set; } private Mock> SettingsMock { get; set; } [Test] @@ -44,66 +47,6 @@ namespace Ombi.Core.Tests.Rule.Search Assert.True(search.Available); } - [Test] - public async Task Movie_Has_Custom_Url_When_Specified_In_Settings() - { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings - { - Enable = true, - Servers = new List - { - new EmbyServers - { - ServerHostname = "http://test.com/", - ServerId = "8" - } - } - }); - ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent - { - ProviderId = "123", - EmbyId = 1.ToString(), - }); - var search = new SearchMovieViewModel() - { - TheMovieDbId = "123", - }; - var result = await Rule.Execute(search); - - Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("http://test.com/web/index.html#!/item?id=1&serverId=8")); - } - - [Test] - public async Task Movie_Uses_Default_Url_When() - { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings - { - Enable = true, - Servers = new List - { - new EmbyServers - { - ServerHostname = string.Empty, - ServerId = "8" - } - } - }); - ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent - { - ProviderId = "123", - EmbyId = 1.ToString() - }); - var search = new SearchMovieViewModel() - { - TheMovieDbId = "123", - }; - var result = await Rule.Execute(search); - - Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("https://app.emby.media/web/index.html#!/item?id=1&serverId=8")); - } - [Test] public async Task Movie_ShouldBe_NotAvailable_WhenNotFoundInEmby() { diff --git a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs index 1b838f102..b733b0b2b 100644 --- a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; @@ -18,12 +19,14 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); + LoggerMock = new Mock>(); SettingsMock = new Mock>(); - Rule = new JellyfinAvailabilityRule(ContextMock.Object, SettingsMock.Object); + Rule = new JellyfinAvailabilityRule(ContextMock.Object, LoggerMock.Object, SettingsMock.Object); } private JellyfinAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } + private Mock> LoggerMock { get; set; } private Mock> SettingsMock { get; set; } [Test] @@ -44,36 +47,6 @@ namespace Ombi.Core.Tests.Rule.Search Assert.True(search.Available); } - [Test] - public async Task Movie_Has_Custom_Url_When_Specified_In_Settings() - { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings - { - Enable = true, - Servers = new List - { - new JellyfinServers - { - ServerHostname = "http://test.com/", - ServerId = "8" - } - } - }); - ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent - { - ProviderId = "123", - JellyfinId = 1.ToString(), - }); - var search = new SearchMovieViewModel() - { - TheMovieDbId = "123", - }; - var result = await Rule.Execute(search); - - Assert.True(result.Success); - Assert.That(search.JellyfinUrl, Is.EqualTo("http://test.com/web/index.html#!/details?id=1&serverId=8")); - } - [Test] public async Task Movie_Uses_Default_Url_When() { diff --git a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs index d597ec80b..25aba5547 100644 --- a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs +++ b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs @@ -30,26 +30,26 @@ namespace Ombi.Core.Engine public IEnumerable GetRecentlyAddedMovies(DateTime from, DateTime to) { - var plexMovies = _plex.GetAll().Where(x => x.Type == PlexMediaTypeEntity.Movie && x.AddedAt > from && x.AddedAt < to); - var embyMovies = _emby.GetAll().Where(x => x.Type == EmbyMediaType.Movie && x.AddedAt > from && x.AddedAt < to); - var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == JellyfinMediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var plexMovies = _plex.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var embyMovies = _emby.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); + var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == MediaType.Movie && x.AddedAt > from && x.AddedAt < to); return GetRecentlyAddedMovies(plexMovies, embyMovies, jellyfinMovies).Take(30); } public IEnumerable GetRecentlyAddedMovies() { - var plexMovies = _plex.GetAll().Where(x => x.Type == PlexMediaTypeEntity.Movie); - var embyMovies = _emby.GetAll().Where(x => x.Type == EmbyMediaType.Movie); - var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == JellyfinMediaType.Movie); + var plexMovies = _plex.GetAll().Where(x => x.Type == MediaType.Movie); + var embyMovies = _emby.GetAll().Where(x => x.Type == MediaType.Movie); + var jellyfinMovies = _jellyfin.GetAll().Where(x => x.Type == MediaType.Movie); return GetRecentlyAddedMovies(plexMovies, embyMovies, jellyfinMovies); } public IEnumerable GetRecentlyAddedTv(DateTime from, DateTime to, bool groupBySeason) { - var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show && x.AddedAt > from && x.AddedAt < to); - var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == EmbyMediaType.Series && x.AddedAt > from && x.AddedAt < to); - var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == JellyfinMediaType.Series && x.AddedAt > from && x.AddedAt < to); + var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); + var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); + var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series && x.AddedAt > from && x.AddedAt < to); return GetRecentlyAddedTv(plexTv, embyTv, jellyfinTv, groupBySeason).Take(30); } @@ -57,9 +57,9 @@ namespace Ombi.Core.Engine public IEnumerable GetRecentlyAddedTv(bool groupBySeason) { - var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); - var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == EmbyMediaType.Series); - var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == JellyfinMediaType.Series); + var plexTv = _plex.GetAll().Include(x => x.Seasons).Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); + var embyTv = _emby.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); + var jellyfinTv = _jellyfin.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); return GetRecentlyAddedTv(plexTv, embyTv, jellyfinTv, groupBySeason); } @@ -76,7 +76,7 @@ namespace Ombi.Core.Engine { continue; } - if (p.Type == PlexMediaTypeEntity.Movie) + if (p.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { @@ -114,7 +114,7 @@ namespace Ombi.Core.Engine { continue; } - if (e.Type == EmbyMediaType.Movie) + if (e.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { @@ -152,7 +152,7 @@ namespace Ombi.Core.Engine { continue; } - if (e.Type == JellyfinMediaType.Movie) + if (e.Type == MediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs index ef38fb973..40be1c73e 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs @@ -32,7 +32,7 @@ namespace Ombi.Core.Rule.Rules.Request { var tvRequest = (ChildRequests) obj; - var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); + var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == MediaType.Series); // We need to do a check on the TVDBId var anyMovieDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TheMovieDbId.Length > 0 && x.TheMovieDbId == tvRequest.Id.ToString()); if (anyMovieDbMatches == null) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index fe062e851..630e4ac81 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -46,10 +46,10 @@ namespace Ombi.Core.Rule.Rules.Search } } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log) + public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + SeasonRequests season, IMediaServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log) { - PlexEpisode epExists = null; + IMediaServerEpisode epExists = null; try { @@ -79,66 +79,6 @@ namespace Ombi.Core.Rule.Rules.Search log.LogError(e, "Exception thrown when attempting to check if something is available"); } - if (epExists != null) - { - episode.Available = true; - } - } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, EmbyContent item, bool useTheMovieDb, bool useTvDb) - { - EmbyEpisode epExists = null; - if (useImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId); - } - - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId); - } - - if (useTvDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId); - } - - if (epExists != null) - { - episode.Available = true; - } - } - public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, JellyfinContent item, bool useTheMovieDb, bool useTvDb) - { - JellyfinEpisode epExists = null; - if (useImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId); - } - - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId); - } - - if (useTvDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId); - } - if (epExists != null) { episode.Available = true; diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 7f6718a6b..e7a629854 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; @@ -13,13 +14,15 @@ namespace Ombi.Core.Rule.Rules.Search { public class EmbyAvailabilityRule : BaseSearchRule, IRules { - public EmbyAvailabilityRule(IEmbyContentRepository repo, ISettingsService s) + public EmbyAvailabilityRule(IEmbyContentRepository repo, ILogger log, ISettingsService s) { EmbyContentRepository = repo; + Log = log; EmbySettings = s; } private IEmbyContentRepository EmbyContentRepository { get; } + private ILogger Log { get; } private ISettingsService EmbySettings { get; } public async Task Execute(SearchViewModel obj) @@ -64,19 +67,7 @@ namespace Ombi.Core.Rule.Rules.Search if (item != null) { obj.Available = true; - var s = await EmbySettings.GetSettingsAsync(); - if (s.Enable) - { - var server = s.Servers.FirstOrDefault(); - if ((server?.ServerHostname ?? string.Empty).HasValue()) - { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, server?.ServerHostname); - } - else - { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, null); - } - } + obj.EmbyUrl = item.Url; if (obj.Type == RequestType.TvShow) { @@ -89,7 +80,7 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log); } } } diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index c51645112..95a2da80b 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; @@ -13,13 +14,15 @@ namespace Ombi.Core.Rule.Rules.Search { public class JellyfinAvailabilityRule : BaseSearchRule, IRules { - public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ISettingsService s) + public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ILogger log, ISettingsService s) { JellyfinContentRepository = repo; + Log = log; JellyfinSettings = s; } private IJellyfinContentRepository JellyfinContentRepository { get; } + private ILogger Log { get; } private ISettingsService JellyfinSettings { get; } public async Task Execute(SearchViewModel obj) @@ -78,20 +81,7 @@ namespace Ombi.Core.Rule.Rules.Search useTheMovieDb = true; } obj.Available = true; - var s = await JellyfinSettings.GetSettingsAsync(); - if (s.Enable) - { - var server = s.Servers.FirstOrDefault(x => x.ServerHostname != null); - if ((server?.ServerHostname ?? string.Empty).HasValue()) - { - obj.JellyfinUrl = JellyfinHelper.GetJellyfinMediaUrl(item.JellyfinId, server?.ServerId, server?.ServerHostname); - } - else - { - var firstServer = s.Servers?.FirstOrDefault(); - obj.JellyfinUrl = JellyfinHelper.GetJellyfinMediaUrl(item.JellyfinId, firstServer.ServerId, firstServer.FullUri); - } - } + obj.JellyfinUrl = item.Url; if (obj.Type == RequestType.TvShow) { @@ -104,7 +94,7 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log); } } } diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 42e97f5f7..4c05e0fe1 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -33,7 +33,7 @@ namespace Ombi.Core.Rule.Rules.Search var useId = false; var useTvDb = false; - PlexMediaTypeEntity type = ConvertType(obj.Type); + MediaType type = ConvertType(obj.Type); if (obj.ImdbId.HasValue()) { @@ -90,9 +90,17 @@ namespace Ombi.Core.Rule.Rules.Search useTheMovieDb = true; } obj.Available = true; - obj.PlexUrl = PlexHelper.BuildPlexMediaUrl(item.Url, host); + if (item.Url.StartsWith("http")) + { + obj.PlexUrl = item.Url; + } + else + { + // legacy content + obj.PlexUrl = PlexHelper.BuildPlexMediaUrl(item.Url, host); + } obj.Quality = item.Quality; - + if (obj.Type == RequestType.TvShow) { var search = (SearchTvShowViewModel)obj; @@ -115,12 +123,12 @@ namespace Ombi.Core.Rule.Rules.Search return Success(); } - private PlexMediaTypeEntity ConvertType(RequestType type) => + private MediaType ConvertType(RequestType type) => type switch { - RequestType.Movie => PlexMediaTypeEntity.Movie, - RequestType.TvShow => PlexMediaTypeEntity.Show, - _ => PlexMediaTypeEntity.Movie, + RequestType.Movie => MediaType.Movie, + RequestType.TvShow => MediaType.Series, + _ => MediaType.Movie, }; } } \ No newline at end of file diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index 3e5aeff70..6827d0f74 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -104,11 +104,11 @@ namespace Ombi.Helpers return new ProviderId(); } - public static string GetPlexMediaUrl(string machineId, int mediaId) + public static string GetPlexMediaUrl(string machineId, int mediaId, string plexHost) { var url = $"web/#!/server/{machineId}/details?key=%2flibrary%2Fmetadata%2F{mediaId}"; - return url; + return BuildPlexMediaUrl(url, plexHost); } public static string BuildPlexMediaUrl(string savedUrl, string plexHost) diff --git a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs index ef31dfc4c..aeaeb40c6 100644 --- a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs +++ b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs @@ -30,6 +30,7 @@ namespace Ombi.Notifications.Templates private const string TableLocation = "{@RECENTLYADDED}"; private const string IntroText = "{@INTRO}"; private const string Unsubscribe = "{@UNSUBSCRIBE}"; + private const string UnsubscribeText = "{@UNSUBSCRIBETEXT}"; public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink) @@ -41,6 +42,7 @@ namespace Ombi.Notifications.Templates sb.Replace(DateKey, DateTime.Now.ToString("f")); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink); + sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : "Unsubscrible"); return sb.ToString(); } diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 71666ba67..befb4dfa3 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -453,7 +453,7 @@ - Unsubscribe + {@UNSUBSCRIBETEXT} diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 608d6cb82..852530be4 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -124,7 +124,7 @@ namespace Ombi.Schedule.Jobs.Emby var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = embyEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 154ae784f..cb7eaefd3 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -16,7 +16,7 @@ using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType; +using MediaType = Ombi.Store.Entities.MediaType; namespace Ombi.Schedule.Jobs.Emby { @@ -165,10 +165,10 @@ namespace Ombi.Schedule.Jobs.Emby ImdbId = tvShow.ProviderIds?.Imdb, TheMovieDbId = tvShow.ProviderIds?.Tmdb, Title = tvShow.Name, - Type = EmbyMediaType.Series, + Type = MediaType.Series, EmbyId = tvShow.Id, Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow + AddedAt = DateTime.UtcNow, }); } else @@ -255,10 +255,10 @@ namespace Ombi.Schedule.Jobs.Emby ImdbId = movieInfo.ProviderIds.Imdb, TheMovieDbId = movieInfo.ProviderIds?.Tmdb, Title = movieInfo.Name, - Type = EmbyMediaType.Movie, + Type = MediaType.Movie, EmbyId = movieInfo.Id, Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow, + AddedAt = DateTime.UtcNow }); } else diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 1a621ebce..125b27fc3 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -151,7 +151,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = jellyfinEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index e8de12bd2..60ee42210 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -14,7 +14,7 @@ using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using JellyfinMediaType = Ombi.Store.Entities.JellyfinMediaType; +using MediaType = Ombi.Store.Entities.MediaType; namespace Ombi.Schedule.Jobs.Jellyfin { @@ -143,7 +143,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin ImdbId = tvShow.ProviderIds?.Imdb, TheMovieDbId = tvShow.ProviderIds?.Tmdb, Title = tvShow.Name, - Type = JellyfinMediaType.Series, + Type = MediaType.Series, JellyfinId = tvShow.Id, Url = JellyfinHelper.GetJellyfinMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname), AddedAt = DateTime.UtcNow @@ -223,10 +223,10 @@ namespace Ombi.Schedule.Jobs.Jellyfin ImdbId = movieInfo.ProviderIds.Imdb, TheMovieDbId = movieInfo.ProviderIds?.Tmdb, Title = movieInfo.Name, - Type = JellyfinMediaType.Movie, + Type = MediaType.Movie, JellyfinId = movieInfo.Id, Url = JellyfinHelper.GetJellyfinMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow, + AddedAt = DateTime.UtcNow }); } else diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 54d1d1133..9d49fe2f1 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -5,7 +5,8 @@ namespace Ombi.Schedule.Jobs.Ombi { public abstract class HtmlTemplateGenerator { - protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url) + protected StringBuilder sb; + protected virtual void AddBackgroundInsideTable(string url) { sb.Append(""); sb.AppendFormat("", url); @@ -14,14 +15,14 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); } - protected virtual void AddPosterInsideTable(StringBuilder sb, string url) + protected virtual void AddPosterInsideTable(string url) { sb.Append(""); sb.Append("
"); sb.AppendFormat("", url); } - protected virtual void AddMediaServerUrl(StringBuilder sb, string mediaurl, string url) + protected virtual void AddMediaServerUrl(string mediaurl, string url) { if (url.HasValue()) { @@ -41,14 +42,14 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); } - protected virtual void AddInfoTable(StringBuilder sb) + protected virtual void AddInfoTable() { sb.Append( ""); @@ -645,7 +485,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); @@ -656,10 +496,10 @@ namespace Ombi.Schedule.Jobs.Ombi return sb.ToString(); } - private async Task ProcessPlexMovies(IQueryable plexContentToSend, StringBuilder sb, string defaultLanguageCode, string mediaServerUrl) + private async Task ProcessMovies(ICollection plexContentToSend, string defaultLanguageCode) { int count = 0; - var ordered = plexContentToSend.OrderByDescending(x => x.AddedAt); + var ordered = plexContentToSend; foreach (var content in ordered) { int.TryParse(content.TheMovieDbId, out var movieDbId); @@ -668,23 +508,23 @@ namespace Ombi.Schedule.Jobs.Ombi continue; } var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId, defaultLanguageCode); - var mediaurl = PlexHelper.BuildPlexMediaUrl(content.Url, mediaServerUrl); + var mediaurl = content.Url; if (info == null) { continue; } try { - CreateMovieHtmlContent(sb, info, mediaurl); + CreateMovieHtmlContent(info, mediaurl); count += 1; } catch (Exception e) { - _log.LogError(e, "Error when Processing Plex Movies {0}", info.Title); + _log.LogError(e, "Error when Processing Movies {0}", info.Title); } finally { - EndLoopHtml(sb); + EndLoopHtml(); } if (count == 2) @@ -695,7 +535,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } } - private async Task ProcessAlbums(HashSet albumsToSend, StringBuilder sb) + private async Task ProcessAlbums(HashSet albumsToSend) { var settings = await _lidarrSettings.GetSettingsAsync(); int count = 0; @@ -709,7 +549,7 @@ namespace Ombi.Schedule.Jobs.Ombi } try { - CreateAlbumHtmlContent(sb, info); + CreateAlbumHtmlContent(info); count += 1; } catch (Exception e) @@ -718,60 +558,7 @@ namespace Ombi.Schedule.Jobs.Ombi } finally { - EndLoopHtml(sb); - } - - if (count == 2) - { - count = 0; - sb.Append(""); - sb.Append(""); - } - } - } - - private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl) - { - int count = 0; - var ordered = embyContent.OrderByDescending(x => x.AddedAt); - foreach (var content in ordered) - { - var theMovieDbId = content.TheMovieDbId; - if (!content.TheMovieDbId.HasValue()) - { - var imdbId = content.ImdbId; - var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - var result = findResult.movie_results?.FirstOrDefault(); - if (result == null) - { - continue; - } - - theMovieDbId = result.id.ToString(); - } - - var mediaurl = content.Url; - if (customUrl.HasValue()) - { - mediaurl = customUrl; - } - var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode); - if (info == null) - { - continue; - } - try - { - CreateMovieHtmlContent(sb, info, mediaurl); - count += 1; - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Emby Movies {0}", info.Title); - } - finally - { - EndLoopHtml(sb); + EndLoopHtml(); } if (count == 2) @@ -783,66 +570,13 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task ProcessJellyfinMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl) + private void CreateMovieHtmlContent(MovieResponseDto info, string mediaurl) { - int count = 0; - var ordered = embyContent.OrderByDescending(x => x.AddedAt); - foreach (var content in ordered) - { - var theMovieDbId = content.TheMovieDbId; - if (!content.TheMovieDbId.HasValue()) - { - var imdbId = content.ImdbId; - var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - var result = findResult.movie_results?.FirstOrDefault(); - if (result == null) - { - continue; - } + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}"); + AddPosterInsideTable($"https://image.tmdb.org/t/p/original{info.PosterPath}"); - theMovieDbId = result.id.ToString(); - } - - var mediaurl = content.Url; - if (customUrl.HasValue()) - { - mediaurl = customUrl; - } - var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode); - if (info == null) - { - continue; - } - try - { - CreateMovieHtmlContent(sb, info, mediaurl); - count += 1; - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Jellyfin Movies {0}", info.Title); - } - finally - { - EndLoopHtml(sb); - } - - if (count == 2) - { - count = 0; - sb.Append(""); - sb.Append(""); - } - } - } - - private void CreateMovieHtmlContent(StringBuilder sb, MovieResponseDto info, string mediaurl) - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}"); - AddPosterInsideTable(sb, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); - - AddMediaServerUrl(sb, mediaurl, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); - AddInfoTable(sb); + AddMediaServerUrl(mediaurl, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); + AddInfoTable(); var releaseDate = string.Empty; try @@ -856,7 +590,7 @@ namespace Ombi.Schedule.Jobs.Ombi // Swallow, couldn't parse the date } - AddTitle(sb, $"https://www.imdb.com/title/{info.ImdbId}/", $"{info.Title} {releaseDate}"); + AddTitle($"https://www.imdb.com/title/{info.ImdbId}/", $"{info.Title} {releaseDate}"); var summary = info.Overview; if (summary.Length > 280) @@ -864,16 +598,15 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddParagraph(sb, summary); + AddParagraph(summary); if (info.Genres.Any()) { - AddGenres(sb, - $"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + AddGenres($"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } } - private void CreateAlbumHtmlContent(StringBuilder sb, AlbumLookup info) + private void CreateAlbumHtmlContent(AlbumLookup info) { var cover = info.images .FirstOrDefault(x => x.coverType.Equals("cover", StringComparison.InvariantCultureIgnoreCase))?.url; @@ -881,21 +614,21 @@ namespace Ombi.Schedule.Jobs.Ombi { cover = info.remoteCover; } - AddBackgroundInsideTable(sb, cover); + AddBackgroundInsideTable(cover); var disk = info.images .FirstOrDefault(x => x.coverType.Equals("disc", StringComparison.InvariantCultureIgnoreCase))?.url; if (disk.IsNullOrEmpty()) { disk = info.remoteCover; } - AddPosterInsideTable(sb, disk); + AddPosterInsideTable(disk); - AddMediaServerUrl(sb, string.Empty, string.Empty); - AddInfoTable(sb); + AddMediaServerUrl(string.Empty, string.Empty); + AddInfoTable(); var releaseDate = $"({info.releaseDate.Year})"; - AddTitle(sb, string.Empty, $"{info.title} {releaseDate}"); + AddTitle(string.Empty, $"{info.title} {releaseDate}"); var summary = info.artist?.artistName ?? string.Empty; if (summary.Length > 280) @@ -903,29 +636,28 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddParagraph(sb, summary); + AddParagraph(summary); - AddGenres(sb, $"Type: {info.albumType}"); + AddGenres($"Type: {info.albumType}"); } - private async Task ProcessPlexTv(HashSet plexContent, StringBuilder sb, string languageCode, string serverHostname) + private async Task ProcessTv(IEnumerable episodes, string languageCode) { - var series = new List(); - foreach (var plexEpisode in plexContent) + var series = new List(); + foreach (var episode in episodes) { - var alreadyAdded = series.FirstOrDefault(x => x.Key == plexEpisode.Series.Key); - if (alreadyAdded != null) + var existingSeries = episode.SeriesIsIn(series); + if (existingSeries != null) { - var episodeExists = alreadyAdded.Episodes.Any(x => x.Key == plexEpisode.Key); - if (!episodeExists) + if (!episode.IsIn(existingSeries)) { - alreadyAdded.Episodes.Add(plexEpisode); + existingSeries.Episodes.Add(episode); } } else { - plexEpisode.Series.Episodes = new List { plexEpisode }; - series.Add(plexEpisode.Series); + episode.Series.Episodes = new List { episode }; + series.Add(episode.Series); } } @@ -979,17 +711,17 @@ namespace Ombi.Schedule.Jobs.Ombi if (tvInfo != null && tvInfo.backdrop_path.HasValue()) { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); } else { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); + AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w1280/"); } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, PlexHelper.BuildPlexMediaUrl(t.Url, serverHostname), banner); - AddInfoTable(sb); + AddPosterInsideTable(banner); + AddMediaServerUrl(t.Url, banner); + AddInfoTable(); - AddTvTitle(sb, info, tvInfo); + AddTvTitle(info, tvInfo); // Group by the season number var results = t.Episodes.GroupBy(p => p.SeasonNumber, @@ -1012,7 +744,7 @@ namespace Ombi.Schedule.Jobs.Ombi finalsb.Append("
"); } - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); + AddTvEpisodesSummaryGenres(finalsb.ToString(), tvInfo); } catch (Exception e) @@ -1021,215 +753,7 @@ namespace Ombi.Schedule.Jobs.Ombi } finally { - EndLoopHtml(sb); - count += 1; - } - - if (count == 2) - { - count = 0; - sb.Append("
"); - sb.Append(""); - } - } - } - - - - private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb, string languageCode, string serverUrl) - { - var series = new List(); - foreach (var episode in embyContent) - { - var alreadyAdded = series.FirstOrDefault(x => x.EmbyId == episode.Series.EmbyId); - if (alreadyAdded != null) - { - alreadyAdded.Episodes.Add(episode); - } - else - { - episode.Series.Episodes = new List - { - episode - }; - series.Add(episode.Series); - } - } - - int count = 0; - var orderedTv = series.OrderByDescending(x => x.AddedAt); - foreach (var t in orderedTv) - { - if (!t.TvDbId.HasValue()) - { - continue; - } - - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - - try - { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.ToHttpsUrl(); // Always use the Https banners - } - - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) - { - - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); - } - else - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); - } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner); - AddInfoTable(sb); - - AddTvTitle(sb, info, tvInfo); - - // Group by the season number - var results = t.Episodes?.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) - { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } - - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); - - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Emby TV {0}", t.Title); - } - finally - { - EndLoopHtml(sb); - count += 1; - } - - if (count == 2) - { - count = 0; - sb.Append("
"); - sb.Append(""); - } - } - } - - private async Task ProcessJellyfinTv(HashSet jellyfinContent, StringBuilder sb, string languageCode, string serverUrl) - { - var series = new List(); - foreach (var episode in jellyfinContent) - { - var alreadyAdded = series.FirstOrDefault(x => x.JellyfinId == episode.Series.JellyfinId); - if (alreadyAdded != null) - { - alreadyAdded.Episodes.Add(episode); - } - else - { - episode.Series.Episodes = new List - { - episode - }; - series.Add(episode.Series); - } - } - - int count = 0; - var orderedTv = series.OrderByDescending(x => x.AddedAt); - foreach (var t in orderedTv) - { - if (!t.TvDbId.HasValue()) - { - continue; - } - - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - - try - { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) - { - banner = banner.ToHttpsUrl(); // Always use the Https banners - } - - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) - { - - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); - } - else - { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/"); - } - AddPosterInsideTable(sb, banner); - AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner); - AddInfoTable(sb); - - AddTvTitle(sb, info, tvInfo); - - // Group by the season number - var results = t.Episodes?.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) - { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } - - AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo); - - } - catch (Exception e) - { - _log.LogError(e, "Error when processing Jellyfin TV {0}", t.Title); - } - finally - { - EndLoopHtml(sb); + EndLoopHtml(); count += 1; } @@ -1242,7 +766,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private void AddTvTitle(StringBuilder sb, Api.TvMaze.Models.TvMazeShow info, TvInfo tvInfo) + private void AddTvTitle(Api.TvMaze.Models.TvMazeShow info, TvInfo tvInfo) { var title = ""; if (!String.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) @@ -1253,10 +777,10 @@ namespace Ombi.Schedule.Jobs.Ombi { title = $"{tvInfo.name}"; } - AddTitle(sb, $"https://www.imdb.com/title/{info.externals.imdb}/", title); + AddTitle($"https://www.imdb.com/title/{info.externals.imdb}/", title); } - private void AddTvEpisodesSummaryGenres(StringBuilder sb, string episodes, TvInfo tvInfo) + private void AddTvEpisodesSummaryGenres(string episodes, TvInfo tvInfo) { var summary = tvInfo.overview; if (summary.Length > 280) @@ -1264,15 +788,15 @@ namespace Ombi.Schedule.Jobs.Ombi summary = summary.Remove(280); summary = summary + "...

"; } - AddTvParagraph(sb, episodes, summary); + AddTvParagraph(episodes, summary); if (tvInfo.genres.Any()) { - AddGenres(sb, $"Genres: {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); + AddGenres($"Genres: {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); } } - private void EndLoopHtml(StringBuilder sb) + private void EndLoopHtml() { //NOTE: BR have to be in TD's as per html spec or it will be put outside of the table... //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index a24d07da0..2421d5af0 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -116,12 +116,12 @@ namespace Ombi.Schedule.Jobs.Ombi { // Ensure we check that we have not linked this item to a request var allMovies = await _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); + x.Type == MediaType.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); await StartPlexMovies(allMovies); // Now Tv var allTv = await _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Show && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); await StartPlexTv(allTv); } @@ -178,7 +178,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyTv() { var allTv = await _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); foreach (var show in allTv) { @@ -213,7 +213,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartJellyfinTv() { var allTv = await _jellyfinRepo.GetAll().Where(x => - x.Type == JellyfinMediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); + x.Type == MediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); foreach (var show in allTv) { @@ -278,7 +278,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyMovies(EmbySettings settings) { var allMovies = await _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); + x.Type == MediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); foreach (var movie in allMovies) { movie.ImdbId.HasValue(); @@ -333,7 +333,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartJellyfinMovies(JellyfinSettings settings) { var allMovies = await _jellyfinRepo.GetAll().Where(x => - x.Type == JellyfinMediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); + x.Type == MediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); foreach (var movie in allMovies) { movie.ImdbId.HasValue(); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 7a05f794b..74dc4aa96 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -86,7 +86,7 @@ namespace Ombi.Schedule.Jobs.Plex var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; - IQueryable seriesEpisodes = null; + IQueryable seriesEpisodes = null; if (useImdb) { seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); @@ -105,8 +105,7 @@ namespace Ombi.Schedule.Jobs.Plex { // Let's try and match the series by name seriesEpisodes = plexEpisodes.Where(x => - x.Series.Title == child.Title && - x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); + x.Series.Title == child.Title); } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 3289c5a24..df96457d0 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -226,7 +226,7 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.SaveChangesAsync(); if (content.Metadata != null) { - var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps); + var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, (IQueryable)allEps); episodesProcessed.AddRange(episodesAdded.Select(x => x.Id)); } } @@ -301,7 +301,7 @@ namespace Ombi.Schedule.Jobs.Plex { var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title && x.ReleaseYear == movie.year.ToString() - && x.Type == PlexMediaTypeEntity.Movie); + && x.Type == MediaType.Movie); // The rating key keeps changing //var existing = await Repo.GetByKey(movie.ratingKey); if (existing != null) @@ -349,9 +349,9 @@ namespace Ombi.Schedule.Jobs.Plex AddedAt = DateTime.Now, Key = movie.ratingKey, ReleaseYear = movie.year.ToString(), - Type = PlexMediaTypeEntity.Movie, + Type = MediaType.Movie, Title = movie.title, - Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, movie.ratingKey), + Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, movie.ratingKey, servers.ServerHostname), Seasons = new List(), Quality = movie.Media?.FirstOrDefault()?.videoResolution ?? string.Empty }; @@ -411,7 +411,7 @@ namespace Ombi.Schedule.Jobs.Plex // Let's try and match var existingContent = await Repo.GetFirstContentByCustom(x => x.Title == show.title && x.ReleaseYear == show.year.ToString() - && x.Type == PlexMediaTypeEntity.Show); + && x.Type == MediaType.Series); // Just double check the rating key, since this is our unique constraint var existingKey = await Repo.GetByKey(show.ratingKey); @@ -463,7 +463,7 @@ namespace Ombi.Schedule.Jobs.Plex Repo.DeleteWithoutSave(existingContent); // Because we have changed the rating key, we need to change all children too - var episodeToChange = Repo.GetAllEpisodes().Where(x => x.GrandparentKey == oldKey); + var episodeToChange = Repo.GetAllEpisodes().Cast().Where(x => x.GrandparentKey == oldKey); if (episodeToChange.Any()) { foreach (var e in episodeToChange) @@ -553,9 +553,9 @@ namespace Ombi.Schedule.Jobs.Plex AddedAt = DateTime.Now, Key = show.ratingKey, ReleaseYear = show.year.ToString(), - Type = PlexMediaTypeEntity.Show, + Type = MediaType.Series, Title = show.title, - Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey), + Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey, servers.ServerHostname), Seasons = new List() }; await GetProviderIds(showMetadata, item); @@ -567,19 +567,19 @@ namespace Ombi.Schedule.Jobs.Plex if (item.ImdbId.HasValue()) { existingImdb = await Repo.GetAll().AnyAsync(x => - x.ImdbId == item.ImdbId && x.Type == PlexMediaTypeEntity.Show); + x.ImdbId == item.ImdbId && x.Type == MediaType.Series); } if (item.TheMovieDbId.HasValue()) { existingMovieDbId = await Repo.GetAll().AnyAsync(x => - x.TheMovieDbId == item.TheMovieDbId && x.Type == PlexMediaTypeEntity.Show); + x.TheMovieDbId == item.TheMovieDbId && x.Type == MediaType.Series); } if (item.TvDbId.HasValue()) { existingTvDbId = await Repo.GetAll().AnyAsync(x => - x.TvDbId == item.TvDbId && x.Type == PlexMediaTypeEntity.Show); + x.TvDbId == item.TvDbId && x.Type == MediaType.Series); } if (existingImdb || existingTvDbId || existingMovieDbId) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 50c5d1f39..4a088ca7b 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -113,7 +113,7 @@ namespace Ombi.Schedule.Jobs.Plex { var currentPosition = 0; var resultCount = settings.EpisodeBatchSize == 0 ? 150 : settings.EpisodeBatchSize; - var currentEpisodes = _repo.GetAllEpisodes(); + var currentEpisodes = _repo.GetAllEpisodes().Cast(); var episodes = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition, resultCount); _log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Total Epsiodes found for {episodes.MediaContainer.librarySectionTitle} = {episodes.MediaContainer.totalSize}"); diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index ce121fe10..b6f8d6485 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using Microsoft.EntityFrameworkCore; using Ombi.Helpers; using Ombi.Store.Entities; @@ -42,20 +43,20 @@ namespace Ombi.Store.Context protected override void OnModelCreating(ModelBuilder builder) { - builder.Entity().HasMany(x => x.Episodes) - .WithOne(x => x.Series) + builder.Entity().HasMany(x => (ICollection) x.Episodes) + .WithOne(x => (PlexServerContent) x.Series) .HasPrincipalKey(x => x.Key) .HasForeignKey(x => x.GrandparentKey); builder.Entity() - .HasOne(p => p.Series) - .WithMany(b => b.Episodes) + .HasOne(p => (EmbyContent) p.Series) + .WithMany(b => (ICollection) b.Episodes) .HasPrincipalKey(x => x.EmbyId) .HasForeignKey(p => p.ParentId); builder.Entity() - .HasOne(p => p.Series) - .WithMany(b => b.Episodes) + .HasOne(p => (JellyfinContent) p.Series) + .WithMany(b => (ICollection) b.Episodes) .HasPrincipalKey(x => x.JellyfinId) .HasForeignKey(p => p.ParentId); diff --git a/src/Ombi.Store/Entities/EmbyContent.cs b/src/Ombi.Store/Entities/EmbyContent.cs index 348573f28..08118b6df 100644 --- a/src/Ombi.Store/Entities/EmbyContent.cs +++ b/src/Ombi.Store/Entities/EmbyContent.cs @@ -32,40 +32,13 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("EmbyContent")] - public class EmbyContent : Entity + public class EmbyContent : MediaServerContent { - public string Title { get; set; } - /// - /// OBSOLETE, Cannot delete due to DB migration issues with SQLite - /// + [Obsolete("Cannot delete due to DB migration issues with SQLite")] public string ProviderId { get; set; } public string EmbyId { get; set; } - public EmbyMediaType Type { get; set; } - public DateTime AddedAt { get; set; } - - public string ImdbId { get; set; } - public string TheMovieDbId { get; set; } - public string TvDbId { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby; } - public enum EmbyMediaType - { - Movie = 0, - Series = 1, - Music = 2 - } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/EmbyEpisode.cs b/src/Ombi.Store/Entities/EmbyEpisode.cs index e4e5b6a4b..97fdb09b1 100644 --- a/src/Ombi.Store/Entities/EmbyEpisode.cs +++ b/src/Ombi.Store/Entities/EmbyEpisode.cs @@ -26,18 +26,16 @@ #endregion using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; -using Microsoft.EntityFrameworkCore.Metadata; +using System.Linq; namespace Ombi.Store.Entities { [Table("EmbyEpisode")] - public class EmbyEpisode : Entity + public class EmbyEpisode : MediaServerEpisode { - public string Title { get; set; } public string EmbyId { get; set; } - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } public string ParentId { get; set; } /// /// NOT USED @@ -47,7 +45,23 @@ namespace Ombi.Store.Entities public string TvDbId { get; set; } public string ImdbId { get; set; } public string TheMovieDbId { get; set; } + [NotMapped] + public EmbyContent EmbySeries + { + get => (EmbyContent)Series; + set => Series = value; + } + + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.EmbyId == this.EmbySeries.EmbyId); + } + + public override bool IsIn(IMediaServerContent content) + { + return content.Episodes.Cast().Any(x => x.EmbyId == this.EmbyId); + } - public EmbyContent Series { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Entity.cs b/src/Ombi.Store/Entities/Entity.cs index 8e1cd2887..fac70de91 100644 --- a/src/Ombi.Store/Entities/Entity.cs +++ b/src/Ombi.Store/Entities/Entity.cs @@ -2,7 +2,7 @@ namespace Ombi.Store.Entities { - public abstract class Entity + public abstract class Entity: IEntity { [Key] public int Id { get; set; } diff --git a/src/Ombi.Store/Entities/IEntity.cs b/src/Ombi.Store/Entities/IEntity.cs new file mode 100644 index 000000000..004d214f1 --- /dev/null +++ b/src/Ombi.Store/Entities/IEntity.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Ombi.Store.Entities +{ + public interface IEntity + { + [Key] + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/IMediaServerContent.cs b/src/Ombi.Store/Entities/IMediaServerContent.cs new file mode 100644 index 000000000..25e4d5f50 --- /dev/null +++ b/src/Ombi.Store/Entities/IMediaServerContent.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + public interface IMediaServerContent: IEntity + { + public string Title { get; set; } + public string ImdbId { get; set; } + public string TvDbId { get; set; } + public string TheMovieDbId { get; set; } + public MediaType Type { get; set; } + public RecentlyAddedType RecentlyAddedType{ get; } + + public string Url { get; set; } + + public ICollection Episodes { get; set; } + + public DateTime AddedAt { get; set; } + + [NotMapped] + public bool HasImdb => !string.IsNullOrEmpty(ImdbId); + + [NotMapped] + public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); + + [NotMapped] + public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + } + + public interface IMediaServerEpisode + { + public int EpisodeNumber { get; set; } + public int SeasonNumber { get; set; } + public string Title { get; set; } + /// + /// The Season key + /// + /// + /// The parent key. + /// + + + public IMediaServerContent Series { get; set; } + public IMediaServerContent SeriesIsIn(ICollection content); + public bool IsIn(IMediaServerContent content); + } + + public enum MediaType + { + Movie = 0, + Series = 1, + Music = 2, + Episode = 3 + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/JellyfinContent.cs b/src/Ombi.Store/Entities/JellyfinContent.cs index 857457bde..b2bb63959 100644 --- a/src/Ombi.Store/Entities/JellyfinContent.cs +++ b/src/Ombi.Store/Entities/JellyfinContent.cs @@ -32,40 +32,14 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("JellyfinContent")] - public class JellyfinContent : Entity + public class JellyfinContent : MediaServerContent { - public string Title { get; set; } - /// - /// OBSOLETE, Cannot delete due to DB migration issues with SQLite - /// + + [Obsolete("Cannot delete due to DB migration issues with SQLite")] public string ProviderId { get; set; } public string JellyfinId { get; set; } - public JellyfinMediaType Type { get; set; } - public DateTime AddedAt { get; set; } - - public string ImdbId { get; set; } - public string TheMovieDbId { get; set; } - public string TvDbId { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin; } - public enum JellyfinMediaType - { - Movie = 0, - Series = 1, - Music = 2 - } } diff --git a/src/Ombi.Store/Entities/JellyfinEpisode.cs b/src/Ombi.Store/Entities/JellyfinEpisode.cs index f2c2f820d..1c0ac423e 100644 --- a/src/Ombi.Store/Entities/JellyfinEpisode.cs +++ b/src/Ombi.Store/Entities/JellyfinEpisode.cs @@ -26,18 +26,17 @@ #endregion using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using Microsoft.EntityFrameworkCore.Metadata; namespace Ombi.Store.Entities { [Table("JellyfinEpisode")] - public class JellyfinEpisode : Entity + public class JellyfinEpisode : MediaServerEpisode { - public string Title { get; set; } public string JellyfinId { get; set; } - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } public string ParentId { get; set; } /// /// NOT USED @@ -47,7 +46,22 @@ namespace Ombi.Store.Entities public string TvDbId { get; set; } public string ImdbId { get; set; } public string TheMovieDbId { get; set; } - - public JellyfinContent Series { get; set; } + [NotMapped] + public JellyfinContent JellyfinSeries + { + get => (JellyfinContent)Series; + set => Series = value; + } + + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.JellyfinId == this.JellyfinSeries.JellyfinId); + } + + public override bool IsIn(IMediaServerContent content) + { + return content.Episodes.Cast().Any(x => x.JellyfinId == this.JellyfinId); + } } } diff --git a/src/Ombi.Store/Entities/MediaServerContent.cs b/src/Ombi.Store/Entities/MediaServerContent.cs new file mode 100644 index 000000000..3bccfea06 --- /dev/null +++ b/src/Ombi.Store/Entities/MediaServerContent.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations.Schema; +using Ombi.Store.Repository; + +namespace Ombi.Store.Entities +{ + public abstract class MediaServerContent: Entity, IMediaServerContent + { + public string Title { get; set; } + public string ImdbId { get; set; } + public string TvDbId { get; set; } + public string TheMovieDbId { get; set; } + public MediaType Type { get; set; } + + public string Url { get; set; } + + public ICollection Episodes { get; set; } + + public DateTime AddedAt { get; set; } + + [NotMapped] + public bool HasImdb => !string.IsNullOrEmpty(ImdbId); + + [NotMapped] + public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); + + [NotMapped] + public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + + [NotMapped] + public abstract RecentlyAddedType RecentlyAddedType { get; } + } + + public abstract class MediaServerEpisode: Entity, IMediaServerEpisode + { + public int EpisodeNumber { get; set; } + public int SeasonNumber { get; set; } + public string Title { get; set; } + + public IMediaServerContent Series { get; set; } + + public abstract IMediaServerContent SeriesIsIn(ICollection content); + public abstract bool IsIn(IMediaServerContent content); + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/PlexEpisode.cs b/src/Ombi.Store/Entities/PlexEpisode.cs index 3acca8f3b..ac482d7ac 100644 --- a/src/Ombi.Store/Entities/PlexEpisode.cs +++ b/src/Ombi.Store/Entities/PlexEpisode.cs @@ -1,30 +1,38 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; namespace Ombi.Store.Entities { [Table("PlexEpisode")] - public class PlexEpisode : Entity + public class PlexEpisode : MediaServerEpisode { - public int EpisodeNumber { get; set; } - public int SeasonNumber { get; set; } public int Key { get; set; } // RatingKey - public string Title { get; set; } - /// - /// The Season key - /// /// /// The parent key. /// public int ParentKey { get; set; } - /// - /// The Series key - /// /// /// The grandparent key. /// public int GrandparentKey { get; set; } + [NotMapped] + public PlexServerContent PlexSeries + { + get => (PlexServerContent)Series; + set => Series = value; + } + public override IMediaServerContent SeriesIsIn(ICollection content) + { + return content.OfType().FirstOrDefault( + x => x.Key == this.PlexSeries.Key); + } + + public override bool IsIn(IMediaServerContent content) + { + return content.Episodes.Cast().Any(x => x.Key == this.Key); + } - public PlexServerContent Series { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index f8e0e01d4..cba02c68c 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -32,37 +32,20 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { [Table("PlexServerContent")] - public class PlexServerContent : Entity + public class PlexServerContent : MediaServerContent { - public string Title { get; set; } public string ReleaseYear { get; set; } - public string ImdbId { get; set; } - public string TvDbId { get; set; } - public string TheMovieDbId { get; set; } - public PlexMediaTypeEntity Type { get; set; } - - public string Url { get; set; } - - public ICollection Episodes { get; set; } public ICollection Seasons { get; set; } /// /// Plex's internal ID for this item /// public int Key { get; set; } - public DateTime AddedAt { get; set; } public string Quality { get; set; } public int? RequestId { get; set; } - - [NotMapped] - public bool HasImdb => !string.IsNullOrEmpty(ImdbId); - - [NotMapped] - public bool HasTvDb => !string.IsNullOrEmpty(TvDbId); - - [NotMapped] - public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); + + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Plex; } [Table("PlexSeasonsContent")] @@ -73,10 +56,4 @@ namespace Ombi.Store.Entities public int SeasonKey { get; set; } public int ParentKey { get; set; } } - - public enum PlexMediaTypeEntity - { - Movie = 0, - Show = 1 - } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index f8743e30f..19bab7f76 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -35,17 +35,13 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class EmbyContentRepository : ExternalRepository, IEmbyContentRepository + public class EmbyContentRepository : MediaServerContentRepository, IEmbyContentRepository { public EmbyContentRepository(ExternalContext db):base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task GetByImdbId(string imdbid) { return await Db.EmbyContent.FirstOrDefaultAsync(x => x.ImdbId == imdbid); @@ -69,20 +65,20 @@ namespace Ombi.Store.Repository return await Db.EmbyContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.EmbyId == embyId); } - public async Task Update(EmbyContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.EmbyContent.Update(existingContent); + Db.EmbyContent.Update((EmbyContent)existingContent); await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.EmbyEpisode.AsQueryable(); } - public async Task Add(EmbyEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.EmbyEpisode.AddAsync(content); + await Db.EmbyEpisode.AddAsync((EmbyEpisode)content); await InternalSaveChanges(); return content; } @@ -91,16 +87,17 @@ namespace Ombi.Store.Repository return await Db.EmbyEpisode.FirstOrDefaultAsync(x => x.EmbyId == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.EmbyEpisode.AddRange(content); + Db.EmbyEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } - public void UpdateWithoutSave(EmbyContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.EmbyContent.Update(existingContent); + Db.EmbyContent.Update((EmbyContent)existingContent); } + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby; } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IEmbyContentRepository.cs b/src/Ombi.Store/Repository/IEmbyContentRepository.cs index a893e9aca..c171fef20 100644 --- a/src/Ombi.Store/Repository/IEmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/IEmbyContentRepository.cs @@ -6,19 +6,16 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IEmbyContentRepository : IRepository + public interface IEmbyContentRepository : IMediaServerContentRepository { + Task GetByEmbyId(string embyId); + Task GetEpisodeByEmbyId(string key); + + // TODO: merge these with IJellyfinContentRepository IQueryable Get(); Task GetByTheMovieDbId(string mov); Task GetByTvDbId(string tv); Task GetByImdbId(string imdbid); - Task GetByEmbyId(string embyId); - Task Update(EmbyContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(EmbyEpisode content); - Task GetEpisodeByEmbyId(string key); - Task AddRange(IEnumerable content); - void UpdateWithoutSave(EmbyContent existingContent); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IExternalRepository.cs b/src/Ombi.Store/Repository/IExternalRepository.cs index b22cb5ea8..ec7b27769 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 where T : Entity + public interface IExternalRepository where T : IEntity { Task Find(object key); IQueryable GetAll(); @@ -25,6 +25,5 @@ namespace Ombi.Store.Repository where TEntity : class; Task ExecuteSql(string sql); - DbSet _db { get; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IJellyfinContentRepository.cs b/src/Ombi.Store/Repository/IJellyfinContentRepository.cs index ff1f2d7dc..30efa1a17 100644 --- a/src/Ombi.Store/Repository/IJellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/IJellyfinContentRepository.cs @@ -6,19 +6,16 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IJellyfinContentRepository : IRepository + public interface IJellyfinContentRepository : IMediaServerContentRepository { + Task GetByJellyfinId(string jellyfinId); + Task GetEpisodeByJellyfinId(string key); + + // TODO: merge these with IEmbyContentRepository IQueryable Get(); Task GetByTheMovieDbId(string mov); Task GetByTvDbId(string tv); Task GetByImdbId(string imdbid); - Task GetByJellyfinId(string jellyfinId); - Task Update(JellyfinContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(JellyfinEpisode content); - Task GetEpisodeByJellyfinId(string key); - Task AddRange(IEnumerable content); - void UpdateWithoutSave(JellyfinContent existingContent); } } diff --git a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs new file mode 100644 index 000000000..73cc00fde --- /dev/null +++ b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public interface IMediaServerContentRepository : IExternalRepository + where Content : IMediaServerContent + { + RecentlyAddedType RecentlyAddedType{ get; } + Task Update(IMediaServerContent existingContent); + IQueryable GetAllEpisodes(); + Task Add(IMediaServerEpisode content); + Task AddRange(IEnumerable content); + void UpdateWithoutSave(IMediaServerContent existingContent); + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IPlexContentRepository.cs b/src/Ombi.Store/Repository/IPlexContentRepository.cs index 38c013cb1..f3c6d0ae2 100644 --- a/src/Ombi.Store/Repository/IPlexContentRepository.cs +++ b/src/Ombi.Store/Repository/IPlexContentRepository.cs @@ -8,23 +8,18 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IPlexContentRepository : IExternalRepository + public interface IPlexContentRepository : IMediaServerContentRepository { Task ContentExists(string providerId); Task Get(string providerId, ProviderType type); - Task GetByType(string providerId, ProviderType type, PlexMediaTypeEntity plexType); + Task GetByType(string providerId, ProviderType type, MediaType mediaType); Task GetByKey(int key); - Task Update(PlexServerContent existingContent); - IQueryable GetAllEpisodes(); - Task Add(PlexEpisode content); Task GetEpisodeByKey(int key); - Task AddRange(IEnumerable content); IEnumerable GetWhereContentByCustom(Expression> predicate); Task GetFirstContentByCustom(Expression> predicate); Task DeleteEpisode(PlexEpisode content); void DeleteWithoutSave(PlexServerContent content); void DeleteWithoutSave(PlexEpisode content); Task UpdateRange(IEnumerable existingContent); - void UpdateWithoutSave(PlexServerContent existingContent); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IRepository.cs b/src/Ombi.Store/Repository/IRepository.cs index b93b07d45..a6142462f 100644 --- a/src/Ombi.Store/Repository/IRepository.cs +++ b/src/Ombi.Store/Repository/IRepository.cs @@ -10,7 +10,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IRepository where T : Entity + public interface IRepository where T : IEntity { Task Find(object key); Task Find(object key, CancellationToken cancellationToken); @@ -27,6 +27,5 @@ namespace Ombi.Store.Repository where TEntity : class; Task ExecuteSql(string sql); - DbSet _db { get; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/JellyfinContentRepository.cs b/src/Ombi.Store/Repository/JellyfinContentRepository.cs index 2b84adb00..28cdcfae8 100644 --- a/src/Ombi.Store/Repository/JellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/JellyfinContentRepository.cs @@ -35,17 +35,13 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class JellyfinContentRepository : ExternalRepository, IJellyfinContentRepository + public class JellyfinContentRepository : MediaServerContentRepository, IJellyfinContentRepository { public JellyfinContentRepository(ExternalContext db):base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task GetByImdbId(string imdbid) { return await Db.JellyfinContent.FirstOrDefaultAsync(x => x.ImdbId == imdbid); @@ -69,20 +65,20 @@ namespace Ombi.Store.Repository return await Db.JellyfinContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.JellyfinId == jellyfinId); } - public async Task Update(JellyfinContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.JellyfinContent.Update(existingContent); + Db.JellyfinContent.Update((JellyfinContent)existingContent); await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.JellyfinEpisode.AsQueryable(); } - public async Task Add(JellyfinEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.JellyfinEpisode.AddAsync(content); + await Db.JellyfinEpisode.AddAsync((JellyfinEpisode)content); await InternalSaveChanges(); return content; } @@ -91,16 +87,17 @@ namespace Ombi.Store.Repository return await Db.JellyfinEpisode.FirstOrDefaultAsync(x => x.JellyfinId == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.JellyfinEpisode.AddRange(content); + Db.JellyfinEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } - public void UpdateWithoutSave(JellyfinContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.JellyfinContent.Update(existingContent); + Db.JellyfinContent.Update((JellyfinContent)existingContent); } - + + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin; } } diff --git a/src/Ombi.Store/Repository/MediaServerRepository.cs b/src/Ombi.Store/Repository/MediaServerRepository.cs new file mode 100644 index 000000000..0f458ee2b --- /dev/null +++ b/src/Ombi.Store/Repository/MediaServerRepository.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Store.Context; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public abstract class MediaServerContentRepository : ExternalRepository, IMediaServerContentRepository where T : MediaServerContent + { + protected ExternalContext Db { get; } + public abstract RecentlyAddedType RecentlyAddedType { get; } + + public MediaServerContentRepository(ExternalContext db) : base(db) + { + Db = db; + } + + public abstract Task Update(IMediaServerContent existingContent); + public abstract IQueryable GetAllEpisodes(); + public abstract Task Add(IMediaServerEpisode content); + public abstract Task AddRange(IEnumerable content); + public abstract void UpdateWithoutSave(IMediaServerContent existingContent); + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 31b3bad11..b99ba157f 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -37,17 +37,13 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class PlexServerContentRepository : ExternalRepository, IPlexContentRepository + public class PlexServerContentRepository : MediaServerContentRepository, IPlexContentRepository { - + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Plex; public PlexServerContentRepository(ExternalContext db) : base(db) { - Db = db; } - private ExternalContext Db { get; } - - public async Task ContentExists(string providerId) { var any = await Db.PlexServerContent.AnyAsync(x => x.ImdbId == providerId); @@ -79,16 +75,16 @@ namespace Ombi.Store.Repository return null; } - public async Task GetByType(string providerId, ProviderType type, PlexMediaTypeEntity plexType) + public async Task GetByType(string providerId, ProviderType type, MediaType mediaType) { switch (type) { case ProviderType.ImdbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.ImdbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.ImdbId == providerId && x.Type == mediaType); case ProviderType.TheMovieDbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TheMovieDbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TheMovieDbId == providerId && x.Type == mediaType); case ProviderType.TvDbId: - return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TvDbId == providerId && x.Type == plexType); + return await Db.PlexServerContent.FirstOrDefaultAsync(x => x.TvDbId == providerId && x.Type == mediaType); default: break; } @@ -114,14 +110,14 @@ namespace Ombi.Store.Repository .FirstOrDefaultAsync(predicate); } - public async Task Update(PlexServerContent existingContent) + public override async Task Update(IMediaServerContent existingContent) { - Db.PlexServerContent.Update(existingContent); + Db.PlexServerContent.Update((PlexServerContent)existingContent); await InternalSaveChanges(); } - public void UpdateWithoutSave(PlexServerContent existingContent) + public override void UpdateWithoutSave(IMediaServerContent existingContent) { - Db.PlexServerContent.Update(existingContent); + Db.PlexServerContent.Update((PlexServerContent)existingContent); } public async Task UpdateRange(IEnumerable existingContent) @@ -130,7 +126,7 @@ namespace Ombi.Store.Repository await InternalSaveChanges(); } - public IQueryable GetAllEpisodes() + public override IQueryable GetAllEpisodes() { return Db.PlexEpisode.Include(x => x.Series).AsQueryable(); } @@ -145,9 +141,9 @@ namespace Ombi.Store.Repository Db.PlexEpisode.Remove(content); } - public async Task Add(PlexEpisode content) + public override async Task Add(IMediaServerEpisode content) { - await Db.PlexEpisode.AddAsync(content); + await Db.PlexEpisode.AddAsync((PlexEpisode)content); await InternalSaveChanges(); return content; } @@ -162,10 +158,11 @@ namespace Ombi.Store.Repository { return await Db.PlexEpisode.FirstOrDefaultAsync(x => x.Key == key); } - public async Task AddRange(IEnumerable content) + public override async Task AddRange(IEnumerable content) { - Db.PlexEpisode.AddRange(content); + Db.PlexEpisode.AddRange((IEnumerable)content); await InternalSaveChanges(); } + } } \ No newline at end of file From 6c55806bcb50797b25dbdb4f7e3eab6e3e1ce88c Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Mon, 31 Jan 2022 20:15:49 +0000 Subject: [PATCH 006/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5a1aec978..9c0b7dba2 100644 --- a/README.md +++ b/README.md @@ -615,21 +615,28 @@ Here are some of the features Ombi has: Nathan Miller +
+ + - + + + - + + + - + + + - + diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 59aabe873..f965625f6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -16,6 +16,7 @@ using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Hubs; +using Ombi.I18n.Resources; using Ombi.Notifications; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; @@ -440,7 +441,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (movies.Any() && !settings.DisableMovies) { - sb.Append("

New Movies



"); + sb.Append($"

{Texts.NewMovies}



"); sb.Append( "
"); sb.Append(""); } - protected virtual void AddTitle(StringBuilder sb, string url, string title) + protected virtual void AddTitle( string url, string title) { sb.Append(""); sb.Append(""); } - protected virtual void AddParagraph(StringBuilder sb, string text) + protected virtual void AddParagraph(string text) { sb.Append(""); sb.Append(""); } - protected virtual void AddTvParagraph(StringBuilder sb, string episodes, string summary) + protected virtual void AddTvParagraph(string episodes, string summary) { sb.Append(""); sb.Append(""); } - protected virtual void AddGenres(StringBuilder sb, string text) + protected virtual void AddGenres(string text) { sb.Append(""); sb.Append(""); @@ -604,7 +458,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); @@ -59,7 +60,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); @@ -68,7 +69,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); @@ -78,7 +79,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 7752d298d..49101c52a 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -1,18 +1,13 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -using MailKit; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MimeKit; -using Ombi.Api.CouchPotato.Models; using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; using Ombi.Api.TheMovieDb; @@ -30,7 +25,6 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Org.BouncyCastle.Utilities.Collections; using Quartz; using ContentType = Ombi.Store.Entities.ContentType; @@ -74,9 +68,9 @@ namespace Ombi.Schedule.Jobs.Ombi _refreshMetadata = refreshMetadata; } - private readonly IPlexContentRepository _plex; - private readonly IEmbyContentRepository _emby; - private readonly IJellyfinContentRepository _jellyfin; + private readonly IMediaServerContentRepository _plex; + private readonly IMediaServerContentRepository _emby; + private readonly IMediaServerContentRepository _jellyfin; private readonly IRepository _recentlyAddedLog; private readonly IMovieDbApi _movieApi; private readonly ITvMazeApi _tvApi; @@ -122,88 +116,37 @@ namespace Ombi.Schedule.Jobs.Ombi try { + var plexSettings = await _plexSettings.GetSettingsAsync(); + var embySettings = await _embySettings.GetSettingsAsync(); + var jellyfinSettings = await _jellyfinSettings.GetSettingsAsync(); var customization = await _customizationSettings.GetSettingsAsync(); - // Get the Content - var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); - var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var jellyfinContent = _jellyfin.GetAll().Include(x => x.Episodes).AsNoTracking(); - var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable); - - var addedLog = _recentlyAddedLog.GetAll().ToList(); - - HashSet addedPlexMovieLogIds, addedEmbyMoviesLogIds, addedJellyfinMoviesLogIds; - HashSet addedAlbumLogIds; - GetRecentlyAddedMoviesData(addedLog, out addedPlexMovieLogIds, out addedEmbyMoviesLogIds, out addedJellyfinMoviesLogIds, out addedAlbumLogIds); - var addedPlexEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode); - var addedEmbyEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); - var addedJellyfinEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Episode); + var moviesContents = new List(); + var seriesContents = new List(); + if (plexSettings.Enable) + { + moviesContents.AddRange(await GetMoviesContent(_plex, test)); + seriesContents.AddRange(GetSeriesContent(_plex, test)); + } + if (embySettings.Enable) + { + moviesContents.AddRange(await GetMoviesContent(_emby, test)); + seriesContents.AddRange(GetSeriesContent(_emby, test)); + } + if (jellyfinSettings.Enable) + { + moviesContents.AddRange(await GetMoviesContent(_jellyfin, test)); + seriesContents.AddRange(GetSeriesContent(_jellyfin, test)); + } + var albumsContents = GetMusicContent(_lidarrAlbumRepository, test); - // Filter out the ones that we haven't sent yet - var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var jellyfinContentLocalDataset = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var plexContentMoviesToSend = plexContentLocalDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var embyContentMoviesToSend = embyContentLocalDataset.Where(x => !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var jellyfinContentMoviesToSend = jellyfinContentLocalDataset.Where(x => !addedJellyfinMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); - var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); - _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); - _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); - _log.LogInformation("Jellyfin Movies to send: {0}", jellyfinContentMoviesToSend.Count()); - _log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count()); + var body = await BuildHtml(moviesContents, seriesContents, albumsContents, settings); - // Find the movies that do not yet have MovieDbIds - var needsMovieDbPlex = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var needsMovieDbJellyfin = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); - var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex); - var newEmbyMovies = await GetMoviesWithoutId(addedEmbyMoviesLogIds, needsMovieDbEmby); - var newJellyfinMovies = await GetMoviesWithoutId(addedJellyfinMoviesLogIds, needsMovieDbJellyfin); - plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet(); - embyContentMoviesToSend = embyContentMoviesToSend.Union(newEmbyMovies).ToHashSet(); - jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.Union(newJellyfinMovies).ToHashSet(); - - plexContentMoviesToSend = plexContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - embyContentMoviesToSend = embyContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); - - var plexEpisodesToSend = - FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); - var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), - addedEmbyEpisodesLogIds); - var jellyfinEpisodesToSend = FilterJellyfinEpisodes(_jellyfin.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), - addedJellyfinEpisodesLogIds); - - _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); - _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); - _log.LogInformation("Jellyfin Episodes to send: {0}", jellyfinEpisodesToSend.Count()); - var plexSettings = await _plexSettings.GetSettingsAsync(); - var embySettings = await _embySettings.GetSettingsAsync(); - var jellyfinSettings = await _jellyfinSettings.GetSettingsAsync(); - var body = string.Empty; - if (test) + if (body.IsNullOrEmpty()) { - var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var jellyfinm = jellyfinContent.Where(x => x.Type == JellyfinMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); - var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - var jellyfint = _jellyfin.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - body = await BuildHtml(plexm, embym, jellyfinm, plext, embyt, jellyfint, lidarr, settings, embySettings, jellyfinSettings, plexSettings); - } - else - { - body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), jellyfinContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, jellyfinEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, jellyfinSettings, plexSettings); - if (body.IsNullOrEmpty()) - { - return; - } + return; } if (!test) @@ -223,7 +166,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (!users.Any()) { return; - } + } var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); @@ -258,84 +201,8 @@ namespace Ombi.Schedule.Jobs.Ombi // Now add all of this to the Recently Added log var recentlyAddedLog = new HashSet(); - foreach (var p in plexContentMoviesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), - }); - - } - - foreach (var p in plexEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - foreach (var e in embyContentMoviesToSend) - { - if (e.Type == EmbyMediaType.Movie) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Emby, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), - }); - } - } - - foreach (var p in embyEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Emby, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - - foreach (var e in jellyfinContentMoviesToSend) - { - if (e.Type == JellyfinMediaType.Movie) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Jellyfin, - ContentType = ContentType.Parent, - ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), - }); - } - } - - foreach (var p in jellyfinEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Jellyfin, - ContentType = ContentType.Episode, - ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } - + AddToRecentlyAddedLog(moviesContents, recentlyAddedLog); + AddToRecentlyAddedLog(seriesContents, recentlyAddedLog); await _recentlyAddedLog.AddRange(recentlyAddedLog); } else @@ -375,79 +242,148 @@ namespace Ombi.Schedule.Jobs.Ombi .SendAsync(NotificationHub.NotificationEvent, "Newsletter Finished"); } - private void GetRecentlyAddedMoviesData(List addedLog, out HashSet addedPlexMovieLogIds, out HashSet addedEmbyMoviesLogIds, out HashSet addedJellyfinMoviesLogIds, out HashSet addedAlbumLogIds) + private void AddToRecentlyAddedLog(ICollection moviesContents, + HashSet recentlyAddedLog) { - var plexParent = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).ToList(); - addedPlexMovieLogIds = plexParent != null && plexParent.Any() ? (plexParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); - - var embyParent = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent); - addedEmbyMoviesLogIds = embyParent != null && embyParent.Any() ? (embyParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); - - var jellyFinParent = addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Parent); - addedJellyfinMoviesLogIds = jellyFinParent != null && jellyFinParent.Any() ? (jellyFinParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); + foreach (var p in moviesContents) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = p.RecentlyAddedType, + ContentType = ContentType.Parent, + ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), + }); + } + } + private void AddToRecentlyAddedLog(ICollection episodes, + HashSet recentlyAddedLog) + { + foreach (var p in episodes) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = p.Series.RecentlyAddedType, + ContentType = ContentType.Episode, + ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), + EpisodeNumber = p.EpisodeNumber, + SeasonNumber = p.SeasonNumber + }); + } + } + private void GetRecentlyAddedMoviesData(List addedLog, out HashSet addedAlbumLogIds) + { var lidarrParent = addedLog.Where(x => x.Type == RecentlyAddedType.Lidarr && x.ContentType == ContentType.Album); addedAlbumLogIds = lidarrParent != null && lidarrParent.Any() ? (lidarrParent?.Select(x => x.AlbumId)?.ToHashSet() ?? new HashSet()) : new HashSet(); } - public static string GenerateUnsubscribeLink(string applicationUrl, string id) + private async Task> GetMoviesContent(IMediaServerContentRepository repository, bool test) where T : class, IMediaServerContent { - if (!applicationUrl.HasValue() || !id.HasValue()) + IQueryable content = repository.GetAll().Include(x => x.Episodes).AsNoTracking().Where(x => x.Type == MediaType.Movie).OrderByDescending(x => x.AddedAt); + var localDataset = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + + HashSet moviesToSend; + if (test) { - return string.Empty; + moviesToSend = content.Take(10).ToHashSet(); } - - if (!applicationUrl.EndsWith('/')) + else { - applicationUrl += '/'; + // Filter out the ones that we haven't sent yet + var parent = _recentlyAddedLog.GetAll().Where(x => x.Type == repository.RecentlyAddedType + && x.ContentType == ContentType.Parent).ToList(); + var addedMovieLogIds = parent != null && parent.Any() ? (parent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet()) : new HashSet(); + moviesToSend = localDataset.Where(x => !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); + _log.LogInformation("Movies to send: {0}", moviesToSend.Count()); + + // Find the movies that do not yet have MovieDbIds + var needsMovieDb = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var newMovies = await GetMoviesWithoutId(addedMovieLogIds, needsMovieDb, repository); + moviesToSend = moviesToSend.Union(newMovies).ToHashSet(); } - var b = new UriBuilder($"{applicationUrl}unsubscribe/{id}"); - return b.ToString(); + + _log.LogInformation("Movies to send: {0}", moviesToSend.Count()); + return moviesToSend.DistinctBy(x => x.Id).ToHashSet(); } - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) + private HashSet GetSeriesContent(IMediaServerContentRepository repository, bool test) where T : class, IMediaServerContent { - foreach (var movie in needsMovieDbPlex) + var content = repository.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).AsNoTracking(); + + HashSet episodesToSend; + if (test) { - var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id.ToString(); + var count = repository.GetAllEpisodes().Count(); + episodesToSend = content.Take(10).ToHashSet(); + } + else + { + // Filter out the ones that we haven't sent yet + var addedEpisodesLogIds = + _recentlyAddedLog.GetAll().Where(x => x.Type == repository.RecentlyAddedType && x.ContentType == ContentType.Episode); + episodesToSend = + FilterEpisodes(content, addedEpisodesLogIds); } - var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); - // Filter them out now - return result.ToHashSet(); + _log.LogInformation("Episodes to send: {0}", episodesToSend.Count()); + return episodesToSend; + } + private HashSet GetMusicContent(IExternalRepository repository, bool test) + { + + var lidarrContent = repository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable); - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) + HashSet albumsToSend; + if (test) + { + albumsToSend = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); + } + else + { + // Filter out the ones that we haven't sent yet + var addedLog = _recentlyAddedLog.GetAll().ToList(); + HashSet addedAlbumLogIds; + GetRecentlyAddedMoviesData(addedLog, out addedAlbumLogIds); + albumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); + } + _log.LogInformation("Albums to send: {0}", albumsToSend.Count()); + return albumsToSend; + + } + + public static string GenerateUnsubscribeLink(string applicationUrl, string id) { - foreach (var movie in needsMovieDbPlex) + if (!applicationUrl.HasValue() || !id.HasValue()) { - var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id.ToString(); + return string.Empty; } - var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); - // Filter them out now - return result.ToHashSet(); + if (!applicationUrl.EndsWith('/')) + { + applicationUrl += '/'; + } + var b = new UriBuilder($"{applicationUrl}unsubscribe/{id}"); + return b.ToString(); } - private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbJellyfin) + private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDb, IMediaServerContentRepository repository) where T : class, IMediaServerContent { - foreach (var movie in needsMovieDbJellyfin) + foreach (var movie in needsMovieDb) { var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id.ToString(); } - var result = needsMovieDbJellyfin.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - await UpdateTheMovieDbId(result); + var result = needsMovieDb.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + await UpdateTheMovieDbId(result, repository); // Filter them out now return result.ToHashSet(); } - private async Task UpdateTheMovieDbId(IEnumerable content) + private async Task UpdateTheMovieDbId(IEnumerable content, IMediaServerContentRepository repository) where T : class, IMediaServerContent { foreach (var movie in content) { @@ -455,45 +391,15 @@ namespace Ombi.Schedule.Jobs.Ombi { continue; } - var entity = await _plex.Find(movie.Id); + var entity = await repository.Find(movie.Id); if (entity == null) { return; } entity.TheMovieDbId = movie.TheMovieDbId; - _plex.UpdateWithoutSave(entity); - } - await _plex.SaveChangesAsync(); - } - - private async Task UpdateTheMovieDbId(IEnumerable content) - { - foreach (var movie in content) - { - if (!movie.HasTheMovieDb) - { - continue; - } - var entity = await _emby.Find(movie.Id); - entity.TheMovieDbId = movie.TheMovieDbId; - _emby.UpdateWithoutSave(entity); + repository.UpdateWithoutSave(entity); } - await _plex.SaveChangesAsync(); - } - - private async Task UpdateTheMovieDbId(IEnumerable content) - { - foreach (var movie in content) - { - if (!movie.HasTheMovieDb) - { - continue; - } - var entity = await _jellyfin.Find(movie.Id); - entity.TheMovieDbId = movie.TheMovieDbId; - _jellyfin.UpdateWithoutSave(entity); - } - await _plex.SaveChangesAsync(); + await repository.SaveChangesAsync(); } public async Task Execute(IJobExecutionContext job) @@ -502,43 +408,9 @@ namespace Ombi.Schedule.Jobs.Ombi await Start(newsletterSettings, false); } - private HashSet FilterPlexEpisodes(IEnumerable source, IEnumerable recentlyAdded) - { - var itemsToReturn = new HashSet(); - foreach (var ep in source.Where(x => x.Series.HasTvDb)) - { - var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); - if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) - { - continue; - } - - itemsToReturn.Add(ep); - } - - return itemsToReturn; - } - - private HashSet FilterEmbyEpisodes(IEnumerable source, IEnumerable recentlyAdded) - { - var itemsToReturn = new HashSet(); - foreach (var ep in source.Where(x => x.Series.HasTvDb)) - { - var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); - if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) - { - continue; - } - - itemsToReturn.Add(ep); - } - - return itemsToReturn; - } - - private HashSet FilterJellyfinEpisodes(IEnumerable source, IEnumerable recentlyAdded) + private HashSet FilterEpisodes(IEnumerable source, IEnumerable recentlyAdded) { - var itemsToReturn = new HashSet(); + var itemsToReturn = new HashSet(); foreach (var ep in source.Where(x => x.Series.HasTvDb)) { var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); @@ -563,17 +435,13 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, IQueryable jellyfinContentToSend, - HashSet plexEpisodes, HashSet embyEp, HashSet jellyfinEp, HashSet albums, NewsletterSettings settings, EmbySettings embySettings, JellyfinSettings jellyfinSettings, - PlexSettings plexSettings) + private async Task BuildHtml(ICollection movies, + IEnumerable episodes, HashSet albums, NewsletterSettings settings) { var ombiSettings = await _ombiSettings.GetSettingsAsync(); - var sb = new StringBuilder(); + sb = new StringBuilder(); - var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie); - var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); - var jellyfinMovies = jellyfinContentToSend.Where(x => x.Type == JellyfinMediaType.Movie); - if ((plexMovies.Any() || embyMovies.Any() || jellyfinMovies.Any()) && !settings.DisableMovies) + if (movies.Any() && !settings.DisableMovies) { sb.Append("

New Movies



"); sb.Append( @@ -582,21 +450,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); sb.Append(""); sb.Append(""); - if (plexSettings.Enable) - { - await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty); - } - - if (embySettings.Enable) - { - await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - - if (jellyfinSettings.Enable) - { - await ProcessJellyfinMovies(jellyfinMovies, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - + await ProcessMovies(movies, ombiSettings.DefaultLanguageCode); sb.Append(""); sb.Append("
"); sb.Append("
"); } - if ((plexEpisodes.Any() || embyEp.Any() || jellyfinEp.Any()) && !settings.DisableTv) + if (episodes.Any() && !settings.DisableTv) { sb.Append("

New TV



"); sb.Append( @@ -613,21 +467,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); sb.Append(""); sb.Append(""); - if (plexSettings.Enable) - { - await ProcessPlexTv(plexEpisodes, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty); - } - - if (embySettings.Enable) - { - await ProcessEmbyTv(embyEp, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - - if (jellyfinSettings.Enable) - { - await ProcessJellyfinTv(jellyfinEp, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty); - } - + await ProcessTv(episodes, ombiSettings.DefaultLanguageCode); sb.Append(""); sb.Append("
"); sb.Append("
"); sb.Append(""); sb.Append(""); - await ProcessAlbums(albums, sb); + await ProcessAlbums(albums); sb.Append(""); sb.Append("
"); sb.Append("
+ + cqxmzz +
+ Qiming Chen +
+
randallbruder
Randall Bruder
-
rob1998
Rob Gökemeijer
-
sambartik @@ -664,15 +671,15 @@ Here are some of the features Ombi has:
Tim Trott
-
tombomb
Tom McClellan
-
Torkiliuz @@ -707,15 +714,15 @@ Here are some of the features Ombi has:
Blake Drumm
-
camjac251
Camjac251
-
distaula @@ -750,15 +757,15 @@ Here are some of the features Ombi has:
Patrick Weber
-
sir-marv
Sirmarv
-
tdorsey From fbac49e2ed3590209af56b004a909165d1a5d441 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 31 Jan 2022 20:20:19 +0000 Subject: [PATCH 007/210] chore(release): :rocket: v4.10.2 (#4484) merge [skip ci] Co-authored-by: Conventional Changelog Action --- CHANGELOG.md | 14 ++++---------- version.json | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44be4a73c..17dad0980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.10.2](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.2) (2022-01-22) + + + ## [4.10.1](https://github.com/Ombi-app/Ombi/compare/v4.10.0...v4.10.1) (2022-01-22) @@ -370,13 +374,3 @@ -## [4.2.4](https://github.com/Ombi-app/Ombi/compare/v4.2.3...v4.2.4) (2021-10-13) - - -### Bug Fixes - -* **#4344:** :bug: Fixed an issue where we errored on Plex Episode Scan ([cd5532f](https://github.com/Ombi-app/Ombi/commit/cd5532fa8f7ebbfaf942841398672bafb9a405d4)) -* **#4345:** :bug: Fixed the issue where denied requests we not appearing correctly ([5a2f652](https://github.com/Ombi-app/Ombi/commit/5a2f652a28f5699dd667afef8dde129817e53392)) - - - diff --git a/version.json b/version.json index 069458b57..ed926cdfb 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.10.1" + "version": "4.10.2" } \ No newline at end of file From aacdb4cb2a2951b662f7f368a028c63ab22e931a Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Mon, 31 Jan 2022 20:23:47 +0000 Subject: [PATCH 008/210] chore(release): :rocket: v4.10.3 --- CHANGELOG.md | 8 +++++++- version.json | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17dad0980..163422bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ -## [4.10.2](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.2) (2022-01-22) +## [4.10.3](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.3) (2022-01-31) + + +### Bug Fixes + +* fix swagger api key auth ([#4483](https://github.com/Ombi-app/Ombi/issues/4483)) [no ci] ([32ee4e8](https://github.com/Ombi-app/Ombi/commit/32ee4e88ec05bf610150933974408fbe95ccd7bd)) +* **frontend:** add link on logo text ([6d7274a](https://github.com/Ombi-app/Ombi/commit/6d7274a94ea24343f32fc028984bd3fd5d5f2ee3)) diff --git a/version.json b/version.json index ed926cdfb..55747f7f1 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.10.2" + "version": "4.10.3" } \ No newline at end of file From 09897747122e1b17a8f4392057fb63bec32f3b6f Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:25:37 +0100 Subject: [PATCH 009/210] bug(newsletter): Drop TVMaze from Newsletter (#4486) #4444 * Stop using TVMaze in newsletter * Better logging when an item is not published --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 48 ++++++++++---------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 49101c52a..59aabe873 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -12,7 +12,6 @@ using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; -using Ombi.Api.TvMaze; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -33,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Ombi public class NewsletterJob : HtmlTemplateGenerator, INewsletterJob { public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IJellyfinContentRepository jellyfin, IRepository addedLog, - IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, + IMovieDbApi movieApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, UserManager um, ISettingsService newsletter, ILogger log, ILidarrApi lidarrApi, IExternalRepository albumCache, ISettingsService lidarrSettings, @@ -45,7 +44,6 @@ namespace Ombi.Schedule.Jobs.Ombi _jellyfin = jellyfin; _recentlyAddedLog = addedLog; _movieApi = movieApi; - _tvApi = tvApi; _email = email; _customizationSettings = custom; _templateRepo = templateRepo; @@ -73,7 +71,6 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly IMediaServerContentRepository _jellyfin; private readonly IRepository _recentlyAddedLog; private readonly IMovieDbApi _movieApi; - private readonly ITvMazeApi _tvApi; private readonly IEmailProvider _email; private readonly ISettingsService _customizationSettings; private readonly INotificationTemplatesRepository _templateRepo; @@ -264,7 +261,7 @@ namespace Ombi.Schedule.Jobs.Ombi recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, - Type = p.Series.RecentlyAddedType, + Type = p.Series.RecentlyAddedType, ContentType = ContentType.Episode, ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), EpisodeNumber = p.EpisodeNumber, @@ -311,7 +308,7 @@ namespace Ombi.Schedule.Jobs.Ombi private HashSet GetSeriesContent(IMediaServerContentRepository repository, bool test) where T : class, IMediaServerContent { var content = repository.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).AsNoTracking(); - + HashSet episodesToSend; if (test) { @@ -505,12 +502,14 @@ namespace Ombi.Schedule.Jobs.Ombi int.TryParse(content.TheMovieDbId, out var movieDbId); if (movieDbId <= 0) { + _log.LogWarning($"{content.Title} does not have a TMDB ID, it won't be published."); continue; } var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId, defaultLanguageCode); var mediaurl = content.Url; if (info == null) { + _log.LogWarning($"TMDB does not know movie {content.Title}, it won't be published."); continue; } try @@ -674,6 +673,8 @@ namespace Ombi.Schedule.Jobs.Ombi var externals = await _movieApi.GetTvExternals(movieId); if (externals == null || externals.tvdb_id <= 0) { + // needed later for recently added log + _log.LogWarning($"{t.Title} has no TVDB ID, it won't be published."); continue; } t.TvDbId = externals.tvdb_id.ToString(); @@ -692,23 +693,17 @@ namespace Ombi.Schedule.Jobs.Ombi } - int.TryParse(t.TvDbId, out var tvdbId); - var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); - if (info == null) - { - continue; - } - try { - var banner = info.image?.original; - if (!string.IsNullOrEmpty(banner)) + var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); + if (tvInfo == null) { - banner = banner.ToHttpsUrl(); // Always use the Https banners + _log.LogWarning($"TMDB does not know series {t.Title}, it won't be published."); + continue; } - var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode); - if (tvInfo != null && tvInfo.backdrop_path.HasValue()) + + if (tvInfo.backdrop_path.HasValue()) { AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); @@ -717,11 +712,18 @@ namespace Ombi.Schedule.Jobs.Ombi { AddBackgroundInsideTable($"https://image.tmdb.org/t/p/w1280/"); } + + var banner = tvInfo.poster_path; + if (!string.IsNullOrEmpty(banner)) + { + banner = $"https://image.tmdb.org/t/p/w300/{banner?.TrimStart('/') ?? string.Empty}"; + }; AddPosterInsideTable(banner); AddMediaServerUrl(t.Url, banner); + AddInfoTable(); - AddTvTitle(info, tvInfo); + AddTvTitle(tvInfo); // Group by the season number var results = t.Episodes.GroupBy(p => p.SeasonNumber, @@ -766,18 +768,18 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private void AddTvTitle(Api.TvMaze.Models.TvMazeShow info, TvInfo tvInfo) + private void AddTvTitle(TvInfo tvInfo) { var title = ""; - if (!String.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) + if (!String.IsNullOrEmpty(tvInfo.first_air_date) && tvInfo.first_air_date.Length > 4) { - title = $"{tvInfo.name} ({info.premiered.Remove(4)})"; + title = $"{tvInfo.name} ({tvInfo.first_air_date.Remove(4)})"; } else { title = $"{tvInfo.name}"; } - AddTitle($"https://www.imdb.com/title/{info.externals.imdb}/", title); + AddTitle($"https://www.themoviedb.org/tv/{tvInfo.id}/", title); } private void AddTvEpisodesSummaryGenres(string episodes, TvInfo tvInfo) From 29063894fedeeaefebc6579524a01b508949768b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Feb 2022 16:36:08 +0000 Subject: [PATCH 010/210] chore: fix unit tests --- src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs | 2 +- src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs | 2 +- src/Ombi.Core/Services/RequestLimitService.cs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs index a28081ebc..5aaa624f9 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs @@ -494,7 +494,7 @@ namespace Ombi.Core.Tests.Engine MovieRequestLimitType = RequestLimitType.Month, Id = "id1" }; - var today = DateTime.UtcNow; + var today = new DateTime(2022,2,2,13,0,0); var firstDayOfMonth = new DateTime(today.Year, today.Month, 1); var log = new List { diff --git a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs index d79e70322..c23c15578 100644 --- a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs +++ b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs @@ -494,7 +494,7 @@ namespace Ombi.Core.Tests.Engine MusicRequestLimitType = RequestLimitType.Month, Id = "id1" }; - var today = DateTime.UtcNow; + var today = new DateTime(2022, 2, 2, 13, 0, 0); var firstDayOfMonth = new DateTime(today.Year, today.Month, 1); var log = new List { diff --git a/src/Ombi.Core/Services/RequestLimitService.cs b/src/Ombi.Core/Services/RequestLimitService.cs index 7a8ecd8f0..83a87c7e7 100644 --- a/src/Ombi.Core/Services/RequestLimitService.cs +++ b/src/Ombi.Core/Services/RequestLimitService.cs @@ -82,7 +82,7 @@ namespace Ombi.Core.Services } - return await CalculateBasicRemaingRequests(user, limit, user.MovieRequestLimitType ?? RequestLimitType.Day, log, now); + return await CalculateBasicRemaingRequests(limit, user.MovieRequestLimitType ?? RequestLimitType.Day, log, now); } public async Task GetRemainingMusicRequests(OmbiUser user, DateTime now = default) @@ -136,7 +136,7 @@ namespace Ombi.Core.Services }; } - return await CalculateBasicRemaingRequests(user, limit, user.MusicRequestLimitType ?? RequestLimitType.Day, log, now); + return await CalculateBasicRemaingRequests(limit, user.MusicRequestLimitType ?? RequestLimitType.Day, log, now); } private async Task GetUser() @@ -145,7 +145,7 @@ namespace Ombi.Core.Services return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); } - private static async Task CalculateBasicRemaingRequests(OmbiUser user, int limit, RequestLimitType type, IQueryable log, DateTime now) + private static async Task CalculateBasicRemaingRequests(int limit, RequestLimitType type, IQueryable log, DateTime now) { int count = 0; DateTime oldestRequestedAt = DateTime.Now; From 4f0bbfd451856bfa5f8aff41fa8c8516da580d2e Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Feb 2022 16:39:32 +0000 Subject: [PATCH 011/210] chore(release): :rocket: v4.10.4 --- CHANGELOG.md | 8 ++++---- version.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 163422bc6..08101f1d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.10.4](https://github.com/Ombi-app/Ombi/compare/v4.10.3...v4.10.4) (2022-02-01) + + + ## [4.10.3](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.3) (2022-01-31) @@ -376,7 +380,3 @@ -## [4.2.5](https://github.com/Ombi-app/Ombi/compare/v4.2.4...v4.2.5) (2021-10-14) - - - diff --git a/version.json b/version.json index 55747f7f1..dc8845852 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.10.3" + "version": "4.10.4" } \ No newline at end of file From b5ec5562435021ea4b8af07c9b64a3f7249b570a Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Tue, 1 Feb 2022 21:32:13 +0100 Subject: [PATCH 012/210] feat(newsletter): Started to localize the newsletter (#4485) * Abstract media servers content into interfaces * Media server entities into abstract classes * Abstract media server content repository * First pass at newsletter refactoring * Minor code clean up * Attempt at abstracting repositories (WIP) * Fixed cast issue * Corrected the other properties * A step towards newsletter refactoring * Clean up leftovers * Fix broken episodes db interaction * Save absolute URL for Plex content Let's be consistent with Emby and Jellyfin * Fix broken integration with Plex libraries * Fix error when multiple media servers configured * Fix newsletter being sent if no movies or episodes * Fix broken tests * Remove unneccesary logs * Allow for newsletter localization * Generate file in English * Fix unsubscribe text unlocalized by messy merge * Fix indentation Co-authored-by: tidusjar --- src/Ombi.Core/Ombi.Core.csproj | 1 + src/Ombi.I18n/Ombi.I18n.csproj | 30 ++++ src/Ombi.I18n/Resources/Texts.Designer.cs | 144 +++++++++++++++++ src/Ombi.I18n/Resources/Texts.fr.resx | 147 ++++++++++++++++++ src/Ombi.I18n/Resources/Texts.resx | 147 ++++++++++++++++++ .../NewsletterTemplate.cs | 5 +- .../Ombi.Notifications.Templates.csproj | 1 + .../Templates/NewsletterTemplate.html | 2 +- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 15 +- src/Ombi.Settings/Ombi.Settings.csproj | 1 + .../Settings/Models/OmbiSettings.cs | 14 +- 11 files changed, 496 insertions(+), 11 deletions(-) create mode 100644 src/Ombi.I18n/Ombi.I18n.csproj create mode 100644 src/Ombi.I18n/Resources/Texts.Designer.cs create mode 100644 src/Ombi.I18n/Resources/Texts.fr.resx create mode 100644 src/Ombi.I18n/Resources/Texts.resx diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 359792e0d..0f7ca6845 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -36,6 +36,7 @@ + diff --git a/src/Ombi.I18n/Ombi.I18n.csproj b/src/Ombi.I18n/Ombi.I18n.csproj new file mode 100644 index 000000000..f44037974 --- /dev/null +++ b/src/Ombi.I18n/Ombi.I18n.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + 3.0.0.0 + 3.0.0.0 + + + 8.0 + Debug;Release;NonUiBuild + + + + Always + + + + + True + True + Texts.resx + + + + + PublicResXFileCodeGenerator + Texts.Designer.cs + + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.Designer.cs b/src/Ombi.I18n/Resources/Texts.Designer.cs new file mode 100644 index 000000000..2f589c022 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.Designer.cs @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ombi.I18n.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Texts { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Texts() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ombi.I18n.Resources.Texts", typeof(Texts).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Type:. + /// + public static string AlbumTypeLabel { + get { + return ResourceManager.GetString("AlbumTypeLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Episodes:. + /// + public static string EpisodesLabel { + get { + return ResourceManager.GetString("EpisodesLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Genres:. + /// + public static string GenresLabel { + get { + return ResourceManager.GetString("GenresLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Albums. + /// + public static string NewAlbums { + get { + return ResourceManager.GetString("NewAlbums", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Movies. + /// + public static string NewMovies { + get { + return ResourceManager.GetString("NewMovies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New TV. + /// + public static string NewTV { + get { + return ResourceManager.GetString("NewTV", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Powered by. + /// + public static string PoweredBy { + get { + return ResourceManager.GetString("PoweredBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Season:. + /// + public static string SeasonLabel { + get { + return ResourceManager.GetString("SeasonLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsubscribe. + /// + public static string Unsubscribe { + get { + return ResourceManager.GetString("Unsubscribe", resourceCulture); + } + } + } +} diff --git a/src/Ombi.I18n/Resources/Texts.fr.resx b/src/Ombi.I18n/Resources/Texts.fr.resx new file mode 100644 index 000000000..ea90dda73 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.fr.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nouveaux Albums + + + Nouveaux Films + + + Nouvelles séries + + + Genres : + + + Type : + + + Saison : + + + Épisodes : + + + Propulsé par + + + Se désinscrire + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.resx b/src/Ombi.I18n/Resources/Texts.resx new file mode 100644 index 000000000..421371dcb --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs index aeaeb40c6..9d3b1632a 100644 --- a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs +++ b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using Ombi.I18n.Resources; namespace Ombi.Notifications.Templates { @@ -31,6 +32,7 @@ namespace Ombi.Notifications.Templates private const string IntroText = "{@INTRO}"; private const string Unsubscribe = "{@UNSUBSCRIBE}"; private const string UnsubscribeText = "{@UNSUBSCRIBETEXT}"; + private const string PoweredByText = "{@POWEREDBYTEXT}"; public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink) @@ -42,7 +44,8 @@ namespace Ombi.Notifications.Templates sb.Replace(DateKey, DateTime.Now.ToString("f")); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink); - sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : "Unsubscrible"); + sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : Texts.Unsubscribe); + sb.Replace(PoweredByText, Texts.PoweredBy); return sb.ToString(); } diff --git a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj index 33088a591..87a876caa 100644 --- a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj +++ b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj @@ -17,6 +17,7 @@ Always + \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index befb4dfa3..fdafdb609 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -458,7 +458,7 @@
- Powered by Ombi + {@POWEREDBYTEXT} Ombi
"); sb.Append(""); @@ -457,7 +458,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (episodes.Any() && !settings.DisableTv) { - sb.Append("

New TV



"); + sb.Append($"

{Texts.NewTV}



"); sb.Append( "
"); sb.Append(""); @@ -475,7 +476,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (albums.Any() && !settings.DisableMusic) { - sb.Append("

New Albums



"); + sb.Append($"

{Texts.NewAlbums}



"); sb.Append( "
"); sb.Append(""); @@ -601,7 +602,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (info.Genres.Any()) { - AddGenres($"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } } @@ -637,7 +638,7 @@ namespace Ombi.Schedule.Jobs.Ombi } AddParagraph(summary); - AddGenres($"Type: {info.albumType}"); + AddGenres($"{Texts.AlbumTypeLabel} {info.albumType}"); } private async Task ProcessTv(IEnumerable episodes, string languageCode) @@ -742,7 +743,7 @@ namespace Ombi.Schedule.Jobs.Ombi var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); + finalsb.Append($"{Texts.SeasonLabel} {epInformation.SeasonNumber} - {Texts.EpisodesLabel} {episodeString} {episodeAirDate}"); finalsb.Append("
"); } @@ -794,7 +795,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (tvInfo.genres.Any()) { - AddGenres($"Genres: {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); } } diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index b39c123e2..4b3aa4c60 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -18,6 +18,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs index ba460a2bd..e224b5c70 100644 --- a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs +++ b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs @@ -1,7 +1,10 @@ -namespace Ombi.Settings.Settings.Models +using Ombi.I18n.Resources; +using System.Globalization; +namespace Ombi.Settings.Settings.Models { public class OmbiSettings : Settings { + private string defaultLanguageCode = "en"; public string BaseUrl { get; set; } public bool CollectAnalyticData { get; set; } public bool Wizard { get; set; } @@ -9,7 +12,14 @@ public bool DoNotSendNotificationsForAutoApprove { get; set; } public bool HideRequestsUsers { get; set; } public bool DisableHealthChecks { get; set; } - public string DefaultLanguageCode { get; set; } = "en"; + public string DefaultLanguageCode + { + get => defaultLanguageCode; + set { + defaultLanguageCode = value; + Texts.Culture = new CultureInfo(value); + } + } public bool AutoDeleteAvailableRequests { get; set; } public int AutoDeleteAfterDays { get; set; } public Branch Branch { get; set; } From 290997bd357333f89dc59f677af32866851cacd3 Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Tue, 1 Feb 2022 20:32:32 +0000 Subject: [PATCH 013/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9c0b7dba2..97f61b650 100644 --- a/README.md +++ b/README.md @@ -129,17 +129,17 @@ Here are some of the features Ombi has:
+ - - + @@ -66,6 +66,14 @@ + + + + + @@ -92,4 +100,5 @@ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index 111c299c5..b3283bb73 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -59,6 +59,9 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.manageOwnRequests = this.auth.hasRole("ManageOwnRequests") if (this.isAdmin) { this.displayedColumns.unshift('select'); + this.displayedColumns.splice(4,0,'has4kRequest'); + } else if (this.auth.hasRole("Request4KMovie")) { + this.displayedColumns.splice(4,0,'has4kRequest'); } const defaultCount = this.storageService.get(this.storageKeyGridCount); const defaultSort = this.storageService.get(this.storageKey); @@ -139,7 +142,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: request.has4KRequest }; this.onOpenOptions.emit(data); } @@ -176,13 +179,17 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { }); } - public bulkApprove() { + public bulkApprove = () => this.bulkApproveInternal(false); + + public bulkApprove4K = () => this.bulkApproveInternal(true); + + private bulkApproveInternal(is4k: boolean) { if (this.selection.isEmpty()) { return; } let tasks = new Array>(); this.selection.selected.forEach((selected) => { - tasks.push(this.requestServiceV1.approveMovie({ id: selected.id })); + tasks.push(this.requestServiceV1.approveMovie({ id: selected.id, is4K: is4k })); }); this.isLoadingResults = true; @@ -199,4 +206,11 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.ngAfterViewInit(); }) } + + public getRequestDate(request: IMovieRequests) : Date { + if (new Date(request.requestedDate).getFullYear() === 1) { + return request.requestedDate4k; + } + return request.requestedDate; + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html index ac974ece8..b584cc0c5 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -5,6 +5,9 @@ {{'Requests.RequestPanel.Approve' | translate}} + + {{'Requests.RequestPanel.Approve4K' | translate}} + {{'Requests.RequestPanel.ChangeAvailability' | translate}} diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index aa98943ca..a37680bc2 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -4,7 +4,7 @@ import { MessageService, RequestService } from '../../../services'; import { IRequestEngineResult, RequestType } from '../../../interfaces'; import { UpdateType } from '../../models/UpdateType'; import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; +import { firstValueFrom, Observable } from 'rxjs'; @Component({ selector: 'request-options', @@ -15,7 +15,7 @@ export class RequestOptionsComponent { public RequestType = RequestType; constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any, - private requestService: RequestService, + private requestService: RequestService, private messageService: MessageService, private bottomSheetRef: MatBottomSheetRef, private translate: TranslateService) { } @@ -44,25 +44,34 @@ export class RequestOptionsComponent { public async approve() { if (this.data.type === RequestType.movie) { - await this.requestService.approveMovie({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveMovie({id: this.data.id, is4K: false})); } if (this.data.type === RequestType.tvShow) { - await this.requestService.approveChild({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveChild({id: this.data.id})); } if (this.data.type === RequestType.album) { - await this.requestService.approveAlbum({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.approveAlbum({id: this.data.id})); } this.bottomSheetRef.dismiss({type: UpdateType.Approve}); return; } + public async approve4K() { + if (this.data.type != RequestType.movie) { + return; + } + + await firstValueFrom(this.requestService.approveMovie({id: this.data.id, is4K: true})); + } + public async changeAvailability() { if (this.data.type === RequestType.movie) { - await this.requestService.markMovieAvailable({id: this.data.id}).toPromise(); + // TODO 4K + await firstValueFrom(this.requestService.markMovieAvailable({id: this.data.id, is4K: false})) } if (this.data.type === RequestType.album) { - await this.requestService.markAlbumAvailable({id: this.data.id}).toPromise(); + await firstValueFrom(this.requestService.markAlbumAvailable({id: this.data.id})); } this.bottomSheetRef.dismiss({type: UpdateType.Availability}); diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts index 351c5a794..e5bf34fa4 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts @@ -1,7 +1,6 @@ import { Component, ViewChild } from "@angular/core"; import { MatBottomSheet } from "@angular/material/bottom-sheet"; -import { MoviesGridComponent } from "./movies-grid/movies-grid.component"; import { RequestOptionsComponent } from "./options/request-options.component"; import { UpdateType } from "../models/UpdateType"; @@ -13,8 +12,8 @@ export class RequestsListComponent { constructor(private bottomSheet: MatBottomSheet) { } - public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean }) { - const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin } }); + public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean }) { + const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin, has4kRequest: event.has4kRequest } }); ref.afterDismissed().subscribe((result) => { if(!result) { diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts index 5e8521302..1d84fe3f0 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts @@ -1,14 +1,14 @@ -import { Component, AfterViewInit, ViewChild, Output, EventEmitter, ChangeDetectorRef, OnInit } from "@angular/core"; -import { IRequestsViewModel, IChildRequests } from "../../../interfaces"; -import { MatPaginator } from "@angular/material/paginator"; -import { MatSort } from "@angular/material/sort"; -import { merge, of as observableOf, Observable } from 'rxjs'; +import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, OnInit, Output, ViewChild } from "@angular/core"; +import { IChildRequests, IRequestsViewModel } from "../../../interfaces"; +import { Observable, merge, of as observableOf } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; -import { RequestServiceV2 } from "../../../services/requestV2.service"; import { AuthService } from "../../../auth/auth.service"; -import { StorageService } from "../../../shared/storage/storage-service"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; import { RequestFilterType } from "../../models/RequestFilterType"; +import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { StorageService } from "../../../shared/storage/storage-service"; @Component({ templateUrl: "./tv-grid.component.html", @@ -108,7 +108,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: false }; this.onOpenOptions.emit(data); } diff --git a/src/Ombi/ClientApp/src/app/services/feature.service.ts b/src/Ombi/ClientApp/src/app/services/feature.service.ts new file mode 100644 index 000000000..18a9cf86f --- /dev/null +++ b/src/Ombi/ClientApp/src/app/services/feature.service.ts @@ -0,0 +1,27 @@ +import { APP_BASE_HREF } from "@angular/common"; +import { Injectable, Inject } from "@angular/core"; + +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +import { IFeatureEnablement } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable({ providedIn: "root" }) +export class FeatureService extends ServiceHelpers { + constructor(http: HttpClient, @Inject(APP_BASE_HREF) href:string) { + super(http, "/api/v2/Features/", href); + } + + public getFeatures(): Observable { + return this.http.get(this.url, {headers: this.headers}); + } + + public enable(feature: IFeatureEnablement): Observable { + return this.http.post(`${this.url}enable`, JSON.stringify(feature), {headers: this.headers}); + } + + public disable(feature: IFeatureEnablement): Observable { + return this.http.post(`${this.url}disable`, JSON.stringify(feature), {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts index 433547b8f..62ff11aef 100644 --- a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts @@ -93,8 +93,8 @@ export class RequestServiceV2 extends ServiceHelpers { return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); } - public reprocessRequest(requestId: number, type: RequestType): Observable { - return this.http.post(`${this.url}reprocess/${type}/${requestId}`, undefined, { headers: this.headers }); + public reprocessRequest(requestId: number, type: RequestType, is4K: boolean): Observable { + return this.http.post(`${this.url}reprocess/${type}/${requestId}/${is4K}`, undefined, { headers: this.headers }); } public requestMovieCollection(collectionId: number): Observable { diff --git a/src/Ombi/ClientApp/src/app/services/settings.service.ts b/src/Ombi/ClientApp/src/app/services/settings.service.ts index 3f4409d0c..4758c8382 100644 --- a/src/Ombi/ClientApp/src/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/src/app/services/settings.service.ts @@ -39,6 +39,7 @@ import { IVoteSettings, ITwilioSettings, IWebhookNotificationSettings, + IRadarrCombined, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -101,11 +102,11 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/Sonarr`, JSON.stringify(settings), {headers: this.headers}); } - public getRadarr(): Observable { - return this.http.get(`${this.url}/Radarr`, {headers: this.headers}); + public getRadarr(): Observable { + return this.http.get(`${this.url}/Radarr`, {headers: this.headers}); } - public saveRadarr(settings: IRadarrSettings): Observable { + public saveRadarr(settings: IRadarrCombined): Observable { return this.http.post(`${this.url}/Radarr`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.html b/src/Ombi/ClientApp/src/app/settings/features/features.component.html new file mode 100644 index 000000000..4eb975cfe --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.html @@ -0,0 +1,20 @@ + + +
+ Features + +
+
+
+
+
+ +
+
+

{{feature.name}}

+
+
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.scss b/src/Ombi/ClientApp/src/app/settings/features/features.component.scss new file mode 100644 index 000000000..658d13101 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.scss @@ -0,0 +1,5 @@ +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} diff --git a/src/Ombi/ClientApp/src/app/settings/features/features.component.ts b/src/Ombi/ClientApp/src/app/settings/features/features.component.ts new file mode 100644 index 000000000..75a155b6c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/features/features.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; + +import { FeaturesFacade } from "../../state/features"; +import { IFeatureEnablement } from "../../interfaces"; +import { MatSlideToggleChange } from "@angular/material/slide-toggle"; +import { firstValueFrom } from "rxjs"; + +@Component({ + templateUrl: "./features.component.html", + styleUrls: ["./features.component.scss"] +}) +export class FeaturesComponent implements OnInit { + + public features: IFeatureEnablement[]; + + constructor(private readonly featuresFacade: FeaturesFacade) { } + + public async ngOnInit() { + this.featuresFacade.features$().subscribe(x => { + this.features = x; + }); + + } + + public updateFeature(change: MatSlideToggleChange, feature: IFeatureEnablement) { + if (change.checked) { + firstValueFrom(this.featuresFacade.enable(feature)); + } else { + firstValueFrom(this.featuresFacade.disable(feature)); + } + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html new file mode 100644 index 000000000..2dbf6869d --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html @@ -0,0 +1,101 @@ +
+
+
+
+
+ Enable +
+
+ Scan for Availability +
+
+ + Do not search for Movies + +
+
+
+
+
+
+
+ +
+ + Hostname or IP + + + + Port + + + + SSL + +
+
+
+ + API key + + +
+
+ + Base URL + + +
+
+
+ +
+
+ +
+
+ + Quality Profiles + + + {{quality.name}} + + + + +
+
+
+ +
+
+ + Default Root Folder + + + {{folder.path}} + + + + +
+
+ + Default Minimum Availability + + + {{min.name}} + + + +
+
+
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss new file mode 100644 index 000000000..bf4c9e420 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss @@ -0,0 +1,21 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +.row { + display: block; +} + +.top-spacing { + margin-top: 10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts new file mode 100644 index 000000000..f426f273b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts @@ -0,0 +1,92 @@ +import { ChangeDetectionStrategy, Component, OnInit } from "@angular/core"; +import { ControlContainer, FormGroup, Validators } from "@angular/forms"; + +import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder, IRadarrSettings } from "../../../interfaces"; +import { TesterService, NotificationService, RadarrService } from "../../../services"; + + +@Component({ + selector: "ombi-settings-radarr-form", + templateUrl: "./radarr-form.component.html", + styleUrls: ["./radarr-form.component.scss"], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RadarrFormComponent implements OnInit { + + public qualities: IRadarrProfile[]; + public rootFolders: IRadarrRootFolder[]; + public minimumAvailabilityOptions: IMinimumAvailability[]; + public profilesRunning: boolean; + public rootFoldersRunning: boolean; + public form: FormGroup; + + constructor(private radarrService: RadarrService, + private notificationService: NotificationService, + private testerService: TesterService, + private controlContainer: ControlContainer) { } + + public ngOnInit() { + this.form = this.controlContainer.control; + // this.toggleValidators(); + + this.qualities = []; + this.qualities.push({ name: "Please Select", id: -1 }); + + this.rootFolders = []; + this.rootFolders.push({ path: "Please Select", id: -1 }); + this.minimumAvailabilityOptions = [ + { name: "Announced", value: "Announced" }, + { name: "In Cinemas", value: "InCinemas" }, + { name: "Physical / Web", value: "Released" }, + ]; + } + + public toggleValidators() { + const enabled = this.form.controls.enabled.value as boolean; + this.form.controls.apiKey.setValidators(enabled ? [Validators.required] : null); + this.form.controls.defaultQualityProfile.setValidators(enabled ? [Validators.required] : null); + this.form.controls.defaultRootPath.setValidators(enabled ? [Validators.required] : null); + this.form.controls.ip.setValidators(enabled ? [Validators.required] : null); + this.form.controls.port.setValidators(enabled ? [Validators.required] : null); + this.form.controls.minimumAvailability.setValidators(enabled ? [Validators.required] : null); + } + + public getProfiles(form: FormGroup) { + this.profilesRunning = true; + this.radarrService.getQualityProfiles(form.value).subscribe(x => { + this.qualities = x; + this.qualities.unshift({ name: "Please Select", id: -1 }); + + this.profilesRunning = false; + this.notificationService.success("Successfully retrieved the Quality Profiles"); + }); + } + + public getRootFolders(form: FormGroup) { + this.rootFoldersRunning = true; + this.radarrService.getRootFolders(form.value).subscribe(x => { + this.rootFolders = x; + this.rootFolders.unshift({ path: "Please Select", id: -1 }); + + this.rootFoldersRunning = false; + this.notificationService.success("Successfully retrieved the Root Folders"); + }); + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + const settings = form.value; + this.testerService.radarrTest(settings).subscribe(result => { + if (result.isValid) { + this.notificationService.success("Successfully connected to Radarr!"); + } else if (result.expectedSubDir) { + this.notificationService.error("Your Radarr Base URL must be set to " + result.expectedSubDir); + } else { + this.notificationService.error("We could not connect to Radarr!"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html index b6d30998a..724beccf1 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html @@ -4,107 +4,30 @@ Radarr Settings
-
-
-
-
- Enable -
-
- Scan for Availability -
-
- - Do not search for Movies - -
-
-
-
-
-
-
- -
- - Hostname or IP - - - - Port - - - - SSL - -
-
-
- - API key - - -
-
- - Base URL - - -
-
-
- -
-
- -
-
- - Quality Profiles - - - {{quality.name}} - - - -
-
-
- -
-
- - Default Root Folder - - - {{folder.path}} - - - + + + + + + + + + + -
-
- - Default Minimum Availability - - - {{min.name}} - - - -
-
-
-
-
-
- -
-
- -
-
+ + +
+
diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts index 9e787b406..1e2925f13 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts @@ -1,12 +1,9 @@ import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { FormBuilder, FormGroup } from "@angular/forms"; -import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; -import { IRadarrSettings } from "../../interfaces"; -import { RadarrService } from "../../services"; -import { TesterService } from "../../services"; -import { NotificationService } from "../../services"; -import { SettingsService } from "../../services"; +import { IMinimumAvailability, IRadarrCombined, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; +import { NotificationService, SettingsService } from "../../services"; +import { FeaturesFacade } from "../../state/features/features.facade"; @Component({ templateUrl: "./radarr.component.html", @@ -20,102 +17,67 @@ export class RadarrComponent implements OnInit { public profilesRunning: boolean; public rootFoldersRunning: boolean; public form: FormGroup; + public is4kEnabled: boolean = false; constructor(private settingsService: SettingsService, - private radarrService: RadarrService, private notificationService: NotificationService, - private fb: FormBuilder, - private testerService: TesterService) { } + private featureFacade: FeaturesFacade, + private fb: FormBuilder) { } public ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.settingsService.getRadarr() .subscribe(x => { - this.form = this.fb.group({ - enabled: [x.enabled], - apiKey: [x.apiKey, [Validators.required]], - defaultQualityProfile: [+x.defaultQualityProfile, [Validators.required]], - defaultRootPath: [x.defaultRootPath, [Validators.required]], - ssl: [x.ssl], - subDir: [x.subDir], - ip: [x.ip, [Validators.required]], - port: [x.port, [Validators.required]], - addOnly: [x.addOnly], - minimumAvailability: [x.minimumAvailability, [Validators.required]], - scanForAvailability: [x.scanForAvailability] + radarr: this.fb.group({ + enabled: [x.radarr.enabled], + apiKey: [x.radarr.apiKey], + defaultQualityProfile: [+x.radarr.defaultQualityProfile], + defaultRootPath: [x.radarr.defaultRootPath], + ssl: [x.radarr.ssl], + subDir: [x.radarr.subDir], + ip: [x.radarr.ip], + port: [x.radarr.port], + addOnly: [x.radarr.addOnly], + minimumAvailability: [x.radarr.minimumAvailability], + scanForAvailability: [x.radarr.scanForAvailability] + }), + radarr4K: this.fb.group({ + enabled: [x.radarr4K.enabled], + apiKey: [x.radarr4K.apiKey], + defaultQualityProfile: [+x.radarr4K.defaultQualityProfile], + defaultRootPath: [x.radarr4K.defaultRootPath], + ssl: [x.radarr4K.ssl], + subDir: [x.radarr4K.subDir], + ip: [x.radarr4K.ip], + port: [x.radarr4K.port], + addOnly: [x.radarr4K.addOnly], + minimumAvailability: [x.radarr4K.minimumAvailability], + scanForAvailability: [x.radarr4K.scanForAvailability] + }), }); - - if (x.defaultQualityProfile) { - this.getProfiles(this.form); - } - if (x.defaultRootPath) { - this.getRootFolders(this.form); - } }); - - this.qualities = []; - this.qualities.push({ name: "Please Select", id: -1 }); - - this.rootFolders = []; - this.rootFolders.push({ path: "Please Select", id: -1 }); - this.minimumAvailabilityOptions = [ - { name: "Announced", value: "Announced" }, - { name: "In Cinemas", value: "InCinemas" }, - { name: "Physical / Web", value: "Released" }, - ]; - } - public getProfiles(form: FormGroup) { - this.profilesRunning = true; - this.radarrService.getQualityProfiles(form.value).subscribe(x => { - this.qualities = x; - this.qualities.unshift({ name: "Please Select", id: -1 }); - this.profilesRunning = false; - this.notificationService.success("Successfully retrieved the Quality Profiles"); - }); - } - - public getRootFolders(form: FormGroup) { - this.rootFoldersRunning = true; - this.radarrService.getRootFolders(form.value).subscribe(x => { - this.rootFolders = x; - this.rootFolders.unshift({ path: "Please Select", id: -1 }); - - this.rootFoldersRunning = false; - this.notificationService.success("Successfully retrieved the Root Folders"); - }); - } - - public test(form: FormGroup) { + public onSubmit(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); return; } - const settings = form.value; - this.testerService.radarrTest(settings).subscribe(result => { - if (result.isValid) { - this.notificationService.success("Successfully connected to Radarr!"); - } else if (result.expectedSubDir) { - this.notificationService.error("Your Radarr Base URL must be set to " + result.expectedSubDir); - } else { - this.notificationService.error("We could not connect to Radarr!"); - } - }); - } + const radarrForm = form.controls.radarr as FormGroup; + const radarr4KForm = form.controls.radarr4K as FormGroup; -public onSubmit(form: FormGroup) { - if (form.invalid) { - this.notificationService.error("Please check your entered values"); + if (radarrForm.controls.enabled.value && (radarrForm.controls.defaultQualityProfile.value === -1 || radarrForm.controls.defaultRootPath.value === "Please Select")) { + this.notificationService.error("Please check your entered values for Radarr"); return; } - if (form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") { - this.notificationService.error("Please check your entered values"); + if (radarr4KForm.controls.enabled.value && (radarr4KForm.controls.defaultQualityProfile.value === -1 || radarr4KForm.controls.defaultRootPath.value === "Please Select")) { + this.notificationService.error("Please check your entered values for Radarr 4K"); return; } - const settings = form.value; + const settings = form.value; this.settingsService.saveRadarr(settings).subscribe(x => { if (x) { this.notificationService.success("Successfully saved Radarr settings"); diff --git a/src/Ombi/ClientApp/src/app/settings/settings.module.ts b/src/Ombi/ClientApp/src/app/settings/settings.module.ts index b486e5b26..144322194 100644 --- a/src/Ombi/ClientApp/src/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/src/app/settings/settings.module.ts @@ -1,76 +1,88 @@ -import { CommonModule } from "@angular/common"; -import { NgModule } from "@angular/core"; +import { + CouchPotatoService, + EmbyService, + FileDownloadService, + IssuesService, + JellyfinService, + JobService, + LidarrService, + MobileService, + NotificationMessageService, + PlexService, + RadarrService, + RequestRetryService, + SonarrService, + SystemService, + TesterService, + TheMovieDbService, + ValidationService +} from "../services"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -// import { TagInputModule } from "ngx-chips"; -import { ClipboardModule } from "ngx-clipboard"; +import { AboutComponent } from "./about/about.component"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; -import { - CouchPotatoService, EmbyService, JellyfinService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, - RequestRetryService, SonarrService, TesterService, ValidationService, SystemService, FileDownloadService, TheMovieDbService -} from "../services"; - -import { PipeModule } from "../pipes/pipe.module"; -import { AboutComponent } from "./about/about.component"; import { AuthenticationComponent } from "./authentication/authentication.component"; +import {AutoCompleteModule} from "primeng/autocomplete"; +import {CalendarModule} from "primeng/calendar"; +import { ClipboardModule } from "ngx-clipboard"; +import { CloudMobileComponent } from "./notifications/cloudmobile.coponent"; +import { CloudMobileService } from "../services/cloudmobile.service"; +import { CommonModule } from "@angular/common"; import { CouchPotatoComponent } from "./couchpotato/couchpotato.component"; import { CustomizationComponent } from "./customization/customization.component"; +import {DialogModule} from "primeng/dialog"; +import { DiscordComponent } from "./notifications/discord.component"; import { DogNzbComponent } from "./dognzb/dognzb.component"; +import { EmailNotificationComponent } from "./notifications/emailnotification.component"; import { EmbyComponent } from "./emby/emby.component"; -import { JellyfinComponent } from "./jellyfin/jellyfin.component"; import { FailedRequestsComponent } from "./failedrequests/failedrequests.component"; +import { FeaturesComponent } from "./features/features.component"; +import { GotifyComponent } from "./notifications/gotify.component"; +import { HubService } from "../services/hub.service"; +import {InputSwitchModule} from "primeng/inputswitch"; +import {InputTextModule} from "primeng/inputtext"; import { IssuesComponent } from "./issues/issues.component"; +import { JellyfinComponent } from "./jellyfin/jellyfin.component"; import { JobsComponent } from "./jobs/jobs.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LidarrComponent } from "./lidarr/lidarr.component"; +import { LogsComponent } from "./logs/logs.component"; 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 { MatDialogModule } from "@angular/material/dialog"; +import { MatMenuModule } from "@angular/material/menu"; import { MattermostComponent } from "./notifications/mattermost.component"; +import {MenuModule} from "primeng/menu"; import { MobileComponent } from "./notifications/mobile.component"; import { NewsletterComponent } from "./notifications/newsletter.component"; +import { NgModule } from "@angular/core"; import { NotificationTemplate } from "./notifications/notificationtemplate.component"; -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 { PipeModule } from "../pipes/pipe.module"; import { PlexComponent } from "./plex/plex.component"; +import { PushbulletComponent } from "./notifications/pushbullet.component"; +import { PushoverComponent } from "./notifications/pushover.component"; import { RadarrComponent } from "./radarr/radarr.component"; +import { RadarrFormComponent } from "./radarr/components/radarr-form.component"; +import {RadioButtonModule} from "primeng/radiobutton"; +import { SettingsMenuComponent } from "./settingsmenu.component"; +import { SharedModule } from "../shared/shared.module"; import { SickRageComponent } from "./sickrage/sickrage.component"; +import { SlackComponent } from "./notifications/slack.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; +import { TelegramComponent } from "./notifications/telegram.component"; import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; +import {TooltipModule} from "primeng/tooltip"; +import { TwilioComponent } from "./notifications/twilio/twilio.component"; import { UpdateComponent } from "./update/update.component"; +import { UpdateDialogComponent } from "./about/update-dialog.component"; +import { UpdateService } from "../services/update.service"; import { UserManagementComponent } from "./usermanagement/usermanagement.component"; import { VoteComponent } from "./vote/vote.component"; -import { WikiComponent } from "./wiki.component"; - -import { SettingsMenuComponent } from "./settingsmenu.component"; - -import {AutoCompleteModule } from "primeng/autocomplete"; -import {CalendarModule } from "primeng/calendar"; -import {InputSwitchModule } from "primeng/inputswitch"; -import {InputTextModule } from "primeng/inputtext"; -import {DialogModule } from "primeng/dialog"; -import {MenuModule } from "primeng/menu"; -import {RadioButtonModule } from "primeng/radiobutton"; -import {TooltipModule } from "primeng/tooltip"; - -import { MatMenuModule } from "@angular/material/menu"; -import { SharedModule } from "../shared/shared.module"; -import { HubService } from "../services/hub.service"; -import { LogsComponent } from "./logs/logs.component"; -import { TwilioComponent } from "./notifications/twilio/twilio.component"; +import { WebhookComponent } from "./notifications/webhook.component"; import { WhatsAppComponent } from "./notifications/twilio/whatsapp.component"; -import { CloudMobileComponent } from "./notifications/cloudmobile.coponent"; -import { CloudMobileService } from "../services/cloudmobile.service"; -import { UpdateService } from "../services/update.service"; -import { MatDialogModule } from "@angular/material/dialog"; -import { UpdateDialogComponent } from "./about/update-dialog.component"; +import { WikiComponent } from "./wiki.component"; const routes: Routes = [ { path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] }, @@ -109,6 +121,7 @@ const routes: Routes = [ { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, { path: "Logs", component: LogsComponent, canActivate: [AuthGuard] }, { path: "CloudMobile", component: CloudMobileComponent, canActivate: [AuthGuard] }, + { path: "Features", component: FeaturesComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -145,6 +158,7 @@ const routes: Routes = [ SonarrComponent, SlackComponent, RadarrComponent, + RadarrFormComponent, EmailNotificationComponent, NotificationTemplate, PushoverComponent, @@ -172,6 +186,7 @@ const routes: Routes = [ LogsComponent, TwilioComponent, WhatsAppComponent, + FeaturesComponent, CloudMobileComponent, UpdateDialogComponent, ], diff --git a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html index bd6949ebb..bcbe7bd3a 100644 --- a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html @@ -2,6 +2,7 @@ + diff --git a/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts b/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts new file mode 100644 index 000000000..3fa4cad56 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts @@ -0,0 +1,36 @@ +import { Directive, Input, OnInit, TemplateRef, ViewContainerRef } from "@angular/core"; +import { AuthService } from "../../auth/auth.service"; + +@Directive({ + selector: '[permission]', +}) +export class RoleDirective implements OnInit { + private roleName: string; + + private isHidden = true; + + @Input() public set permission(val: string) { + if (val) { + this.roleName = val; + this.updateView(); + } + } + + public constructor(private templateRef: TemplateRef, private viewContainer: ViewContainerRef, private auth: AuthService) {} + + public ngOnInit(): void { + this.updateView(); + } + + private updateView(): void { + if (this.auth.hasRole(this.roleName) || this.auth.hasRole("admin")) { + if (this.isHidden) { + this.viewContainer.createEmbeddedView(this.templateRef); + this.isHidden = false; + } + } else { + this.viewContainer.clear(); + this.isHidden = true; + } + } +} diff --git a/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts b/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts new file mode 100644 index 000000000..15cea8923 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core'; +import { RoleDirective } from './role-directive'; + +@NgModule({ + declarations: [RoleDirective], + exports: [RoleDirective], +}) +export class RoleModule {} diff --git a/src/Ombi/ClientApp/src/app/shared/shared.module.ts b/src/Ombi/ClientApp/src/app/shared/shared.module.ts index 01d70f1c6..f14eb43f2 100644 --- a/src/Ombi/ClientApp/src/app/shared/shared.module.ts +++ b/src/Ombi/ClientApp/src/app/shared/shared.module.ts @@ -43,6 +43,7 @@ import { TheMovieDbService } from "../services"; import { TranslateModule } from "@ngx-translate/core"; import { TruncateModule } from "@yellowspot/ng-truncate"; import { WatchProvidersSelectComponent } from "./components/watch-providers-select/watch-providers-select.component"; +import { RoleModule } from "./role-directive/role.module"; @NgModule({ declarations: [ @@ -56,6 +57,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele WatchProvidersSelectComponent, ], imports: [ + RoleModule, SidebarModule, ReactiveFormsModule, FormsModule, @@ -91,6 +93,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele PipeModule, ], exports: [ + RoleModule, TranslateModule, CommonModule, FormsModule, diff --git a/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts b/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts index 57b3f5908..5261183c3 100644 --- a/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts +++ b/src/Ombi/ClientApp/src/app/state/customization/customization.state.ts @@ -6,7 +6,6 @@ import { ICustomizationSettings } from "../../interfaces"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs"; import { SettingsService } from "../../services"; -import { produce } from 'immer'; import { tap } from "rxjs/operators"; @State({ diff --git a/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts b/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts new file mode 100644 index 000000000..2324259f3 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features-initializer.ts @@ -0,0 +1,10 @@ +import { APP_INITIALIZER } from "@angular/core"; +import { FeaturesFacade } from "./features.facade"; +import { Observable } from "rxjs"; + +export const FEATURES_INITIALIZER = { + provide: APP_INITIALIZER, + useFactory: (featureFacade: FeaturesFacade) => (): Observable => featureFacade.loadFeatures(), + multi: true, + deps: [FeaturesFacade], +}; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.actions.ts b/src/Ombi/ClientApp/src/app/state/features/features.actions.ts new file mode 100644 index 000000000..fcb517828 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.actions.ts @@ -0,0 +1,15 @@ +import { IFeatureEnablement } from "../../interfaces"; + +export class LoadFeatures { + public static readonly type = '[Features] LoadAll'; +} +export class EnableFeature { + public static readonly type = '[Features] Enable'; + + constructor(public feature: IFeatureEnablement) { } +} +export class DisableFeature { + public static readonly type = '[Features] Disable'; + + constructor(public feature: IFeatureEnablement) { } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.facade.ts b/src/Ombi/ClientApp/src/app/state/features/features.facade.ts new file mode 100644 index 000000000..10e229eba --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.facade.ts @@ -0,0 +1,26 @@ +import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions"; + +import { FeaturesSelectors } from "./features.selectors"; +import { IFeatureEnablement } from "../../interfaces"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { Store } from "@ngxs/store"; + +@Injectable({ + providedIn: 'root', +}) +export class FeaturesFacade { + + public constructor(private store: Store) {} + + public features$ = (): Observable => this.store.select(FeaturesSelectors.features); + + public enable = (feature: IFeatureEnablement): Observable => this.store.dispatch(new EnableFeature(feature)); + + public disable = (feature: IFeatureEnablement): Observable => this.store.dispatch(new DisableFeature(feature)); + + public loadFeatures = (): Observable => this.store.dispatch(new LoadFeatures()); + + public is4kEnabled = (): boolean => this.store.selectSnapshot(FeaturesSelectors.is4kEnabled); + +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts b/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts new file mode 100644 index 000000000..143dfb875 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.selectors.ts @@ -0,0 +1,18 @@ +import { ICustomizationSettings, IFeatureEnablement } from "../../interfaces"; + +import { FEATURES_STATE_TOKEN } from "./types"; +import { Selector } from "@ngxs/store"; + +export class FeaturesSelectors { + + @Selector([FEATURES_STATE_TOKEN]) + public static features(features: IFeatureEnablement[]): IFeatureEnablement[] { + return features; + } + + @Selector([FeaturesSelectors.features]) + public static is4kEnabled(features: IFeatureEnablement[]): boolean { + return features.filter(x => x.name === "Movie4KRequests")[0].enabled; + } + +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/features.state.ts b/src/Ombi/ClientApp/src/app/state/features/features.state.ts new file mode 100644 index 000000000..4e014db7c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/features.state.ts @@ -0,0 +1,40 @@ +import { Action, State, StateContext } from "@ngxs/store"; +import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions"; + +import { FEATURES_STATE_TOKEN } from "./types"; +import { FeatureService } from "../../services/feature.service"; +import { IFeatureEnablement } from "../../interfaces"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { tap } from "rxjs/operators"; + +@State({ + name: FEATURES_STATE_TOKEN +}) +@Injectable() +export class FeatureState { + constructor(private featuresService: FeatureService) { } + + @Action(LoadFeatures) + public load({ setState }: StateContext): Observable { + return this.featuresService.getFeatures().pipe( + tap(features => + setState(features) + ) + ); + } + + @Action(EnableFeature) + public enable({ setState }: StateContext, { feature }: EnableFeature): Observable { + return this.featuresService.enable(feature).pipe( + tap((result) => setState(result)) + ); + } + + @Action(DisableFeature) + public disable({ setState }: StateContext, { feature }: DisableFeature): Observable { + return this.featuresService.disable(feature).pipe( + tap((result) => setState(result)) + ); + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/state/features/index.ts b/src/Ombi/ClientApp/src/app/state/features/index.ts new file mode 100644 index 000000000..e0fec5274 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/index.ts @@ -0,0 +1,4 @@ +export * from './features.state'; +export * from './features.actions'; +export * from './features.facade'; +export * from './features.selectors'; diff --git a/src/Ombi/ClientApp/src/app/state/features/types.ts b/src/Ombi/ClientApp/src/app/state/features/types.ts new file mode 100644 index 000000000..d8fdc09a1 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/state/features/types.ts @@ -0,0 +1,4 @@ +import { IFeatureEnablement } from "../../interfaces"; +import { StateToken } from "@ngxs/store"; + +export const FEATURES_STATE_TOKEN = new StateToken('featureEnablement'); \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts index c772b86aa..bc6319198 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts @@ -6,6 +6,7 @@ import { IdentityService, MessageService, RadarrService, SettingsService, Sonarr import { Clipboard } from '@angular/cdk/clipboard'; import { CustomizationFacade } from "../state/customization"; import { Location } from "@angular/common"; +import { FeaturesFacade } from "../state/features/features.facade"; @Component({ templateUrl: "./usermanagement-user.component.html", @@ -36,7 +37,6 @@ export class UserManagementUserComponent implements OnInit { constructor(private identityService: IdentityService, private notificationService: MessageService, - private readonly settingsService: SettingsService, private router: Router, private route: ActivatedRoute, private sonarrService: SonarrService, @@ -44,23 +44,33 @@ export class UserManagementUserComponent implements OnInit { private clipboard: Clipboard, private location: Location, private customizationFacade: CustomizationFacade, + private featureFacade: FeaturesFacade, ) { this.route.params.subscribe((params: any) => { if(params.id) { this.userId = params.id; this.edit = true; - this.identityService.getUserById(this.userId).subscribe(x => { - this.user = x; - }); } }); } public ngOnInit() { + const is4KEnabled = this.featureFacade.is4kEnabled(); + this.identityService.getUserById(this.userId).subscribe(x => { + this.user = x; + if (!is4KEnabled) { + this.user.claims = this.user.claims.filter(x => x.value !== "Request4KMovie"); + } + }); this.requestLimitTypes = [RequestLimitType.Day, RequestLimitType.Week, RequestLimitType.Month]; this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x); - this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + this.identityService.getAllAvailableClaims().subscribe(x => { + this.availableClaims = x; + if (!is4KEnabled) { + this.availableClaims = this.availableClaims.filter(y => y.value !== "Request4KMovie"); + } + }); if(this.edit) { this.identityService.getNotificationPreferencesForUser(this.userId).subscribe(x => this.notificationPreferences = x); } else { diff --git a/src/Ombi/Controllers/V1/IdentityController.cs b/src/Ombi/Controllers/V1/IdentityController.cs index fded4cacc..7ef7b8561 100644 --- a/src/Ombi/Controllers/V1/IdentityController.cs +++ b/src/Ombi/Controllers/V1/IdentityController.cs @@ -46,57 +46,36 @@ namespace Ombi.Controllers.V1 [ApiController] public class IdentityController : Controller { - public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager rm, IEmailProvider prov, + public IdentityController(OmbiUserManager user, + RoleManager rm, + IEmailProvider prov, ISettingsService s, ISettingsService c, ISettingsService ombiSettings, IWelcomeEmail welcome, - IMovieRequestRepository m, - ITvRequestRepository t, ILogger l, IPlexApi plexApi, ISettingsService settings, - IRepository requestLog, - IRepository issues, - IRepository issueComments, - IRepository notificationRepository, - IRepository subscriptionRepository, ISettingsService umSettings, IRepository notificationPreferences, IRepository userProfiles, - IMusicRequestRepository musicRepo, - IMovieRequestEngine movieRequestEngine, - ITvRequestEngine tvRequestEngine, - IMusicRequestEngine musicEngine, IUserDeletionEngine deletionEngine, IRequestLimitService requestLimitService, ICacheService cacheService) { UserManager = user; - Mapper = mapper; RoleManager = rm; EmailProvider = prov; EmailSettings = s; CustomizationSettings = c; WelcomeEmail = welcome; - MovieRepo = m; - MusicRepo = musicRepo; - TvRepo = t; _log = l; _plexApi = plexApi; _plexSettings = settings; - _issuesRepository = issues; - _requestLogRepository = requestLog; - _issueCommentsRepository = issueComments; OmbiSettings = ombiSettings; - _requestSubscriptionRepository = subscriptionRepository; - _notificationRepository = notificationRepository; _userManagementSettings = umSettings; - TvRequestEngine = tvRequestEngine; - MovieRequestEngine = movieRequestEngine; _userNotificationPreferences = notificationPreferences; _userQualityProfiles = userProfiles; - MusicRequestEngine = musicEngine; _deletionEngine = deletionEngine; _requestLimitService = requestLimitService; _cacheService = cacheService; @@ -108,27 +87,15 @@ namespace Ombi.Controllers.V1 private readonly ICacheService _cacheService; private RoleManager RoleManager { get; } - private IMapper Mapper { get; } private IEmailProvider EmailProvider { get; } private ISettingsService EmailSettings { get; } private ISettingsService CustomizationSettings { get; } private readonly ISettingsService _userManagementSettings; private ISettingsService OmbiSettings { get; } private IWelcomeEmail WelcomeEmail { get; } - private IMovieRequestRepository MovieRepo { get; } - private ITvRequestRepository TvRepo { get; } - private IMovieRequestEngine MovieRequestEngine { get; } - private IMusicRequestEngine MusicRequestEngine { get; } - private ITvRequestEngine TvRequestEngine { get; } - private IMusicRequestRepository MusicRepo { get; } private readonly ILogger _log; private readonly IPlexApi _plexApi; private readonly ISettingsService _plexSettings; - private readonly IRepository _issuesRepository; - private readonly IRepository _issueCommentsRepository; - private readonly IRepository _requestLogRepository; - private readonly IRepository _notificationRepository; - private readonly IRepository _requestSubscriptionRepository; private readonly IRepository _userNotificationPreferences; private readonly IRepository _userQualityProfiles; @@ -258,6 +225,8 @@ namespace Ombi.Controllers.V1 await CreateRole(OmbiRoles.ReceivesNewsletter); await CreateRole(OmbiRoles.ManageOwnRequests); await CreateRole(OmbiRoles.EditCustomPage); + await CreateRole(OmbiRoles.EditCustomPage); + await CreateRole(OmbiRoles.Request4KMovie); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/V1/RequestController.cs b/src/Ombi/Controllers/V1/RequestController.cs index cc686b506..1220c3afc 100644 --- a/src/Ombi/Controllers/V1/RequestController.cs +++ b/src/Ombi/Controllers/V1/RequestController.cs @@ -165,7 +165,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task ApproveMovie([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.ApproveMovieById(model.Id); + return await MovieRequestEngine.ApproveMovieById(model.Id, model.Is4K); } /// @@ -177,7 +177,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkMovieAvailable([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.MarkAvailable(model.Id); + return await MovieRequestEngine.MarkAvailable(model.Id, model.Is4K); } /// @@ -189,7 +189,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkMovieUnAvailable([FromBody] MovieUpdateModel model) { - return await MovieRequestEngine.MarkUnavailable(model.Id); + return await MovieRequestEngine.MarkUnavailable(model.Id, model.Is4K); } /// @@ -201,7 +201,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task DenyMovie([FromBody] DenyMovieModel model) { - return await MovieRequestEngine.DenyMovieById(model.Id, model.Reason); + return await MovieRequestEngine.DenyMovieById(model.Id, model.Reason, model.Is4K); } /// @@ -403,7 +403,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkTvAvailable([FromBody] TvUpdateModel model) { - return await TvRequestEngine.MarkAvailable(model.Id); + return await TvRequestEngine.MarkAvailable(model.Id, false); } /// @@ -415,7 +415,7 @@ namespace Ombi.Controllers.V1 [PowerUser] public async Task MarkTvUnAvailable([FromBody] TvUpdateModel model) { - return await TvRequestEngine.MarkUnavailable(model.Id); + return await TvRequestEngine.MarkUnavailable(model.Id, false); } /// diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index fcd4bb1a4..ff4dea913 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -403,9 +403,13 @@ namespace Ombi.Controllers.V1 /// /// [HttpGet("radarr")] - public async Task RadarrSettings() + public async Task RadarrSettings() { - return await Get(); + return new RadarrCombinedModel + { + Radarr = await Get(), + Radarr4K = await Get(), + }; } /// @@ -474,9 +478,11 @@ namespace Ombi.Controllers.V1 /// The settings. /// [HttpPost("radarr")] - public async Task RadarrSettings([FromBody]RadarrSettings settings) + public async Task RadarrSettings([FromBody]RadarrCombinedModel settings) { - var result = await Save(settings); + var radarrResult = await Save(settings.Radarr); + var radarr4kResult = await Save(settings.Radarr4K); + var result = radarr4kResult && radarrResult; if (result) { _cache.Remove(CacheKeys.RadarrRootProfiles); diff --git a/src/Ombi/Controllers/V2/FeaturesController.cs b/src/Ombi/Controllers/V2/FeaturesController.cs new file mode 100644 index 000000000..16c512b8c --- /dev/null +++ b/src/Ombi/Controllers/V2/FeaturesController.cs @@ -0,0 +1,88 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Attributes; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace Ombi.Controllers.V2 +{ + public class FeaturesController : V2Controller + { + private readonly ISettingsService _features; + + public FeaturesController(ISettingsService features) => _features = features; + + [HttpGet] + [AllowAnonymous] + public async Task> GetFeatures() + { + var features = await _features.GetSettingsAsync(); + return PopulateFeatures(features?.Features ?? new List()); + } + + [HttpPost("enable")] + [Admin] + public async Task> Enable([FromBody] FeatureEnablement feature) + { + var featureSettings = await _features.GetSettingsAsync(); + var features = PopulateFeatures(featureSettings?.Features ?? new List()); + var featureToUpdate = features.First(x => x.Name.Equals(feature.Name)); + featureToUpdate.Enabled = true; + + featureSettings.Features = features; + + await _features.SaveSettingsAsync(featureSettings); + + return PopulateFeatures(featureSettings?.Features ?? new List()); + } + + [HttpPost("disable")] + [Admin] + public async Task> Disable([FromBody] FeatureEnablement feature) + { + var featureSettings = await _features.GetSettingsAsync(); + var features = PopulateFeatures(featureSettings?.Features ?? new List()); + var featureToUpdate = features.First(x => x.Name.Equals(feature.Name)); + featureToUpdate.Enabled = false; + + featureSettings.Features = features; + + await _features.SaveSettingsAsync(featureSettings); + + return PopulateFeatures(featureSettings?.Features ?? new List()); + } + + + private List PopulateFeatures(List existingFeatures) + { + var supported = GetSupportedFeatures().ToList(); + if (supported.Count == existingFeatures.Count) + { + return existingFeatures; + } + var diff = supported.Except(existingFeatures.Select(x => x.Name)); + + foreach (var feature in diff) + { + existingFeatures.Add(new FeatureEnablement + { + Name = feature + }); + } + return existingFeatures; + } + + private IEnumerable GetSupportedFeatures() + { + FieldInfo[] fieldInfos = typeof(FeatureNames).GetFields(BindingFlags.Public | + BindingFlags.Static | BindingFlags.FlattenHierarchy); + + return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(string)).Select(x => (string)x.GetValue(x)); + } + } +} diff --git a/src/Ombi/Controllers/V2/RequestsController.cs b/src/Ombi/Controllers/V2/RequestsController.cs index 9f26e95bf..45a060b15 100644 --- a/src/Ombi/Controllers/V2/RequestsController.cs +++ b/src/Ombi/Controllers/V2/RequestsController.cs @@ -203,15 +203,15 @@ namespace Ombi.Controllers.V2 } [PowerUser] - [HttpPost("reprocess/{type}/{requestId}")] - public async Task ReProcessRequest(RequestType type, int requestId) + [HttpPost("reprocess/{type}/{requestId}/{is4K}")] + public async Task ReProcessRequest(RequestType type, int requestId, bool? is4K) { switch (type) { case RequestType.TvShow: - return Ok(await _tvRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted)); + return Ok(await _tvRequestEngine.ReProcessRequest(requestId, false, HttpContext.RequestAborted)); case RequestType.Movie: - return Ok(await _movieRequestEngine.ReProcessRequest(requestId, HttpContext.RequestAborted)); + return Ok(await _movieRequestEngine.ReProcessRequest(requestId, is4K ?? false, HttpContext.RequestAborted)); } return BadRequest(); diff --git a/src/Ombi/Models/MovieUpdateModel.cs b/src/Ombi/Models/MovieUpdateModel.cs index db52d4f2b..72638db98 100644 --- a/src/Ombi/Models/MovieUpdateModel.cs +++ b/src/Ombi/Models/MovieUpdateModel.cs @@ -29,5 +29,6 @@ namespace Ombi.Core.Models.Requests public class MovieUpdateModel { public int Id { get; set; } + public bool Is4K { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 1f10c1058..5f836c27f 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -95,6 +95,7 @@ + diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index a6d9cb25a..d0e282dce 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continue", "Available": "Available", + "Available4K": "Available 4K", "Approved": "Approved", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Partially Available", "Monitored": "Monitored", @@ -24,8 +26,10 @@ "RequestDenied": "Request Denied", "NotRequested": "Not Requested", "Requested": "Requested", + "Requested4K": "Requested 4K", "Search":"Search", "Request": "Request", + "Request4K": "Request 4K", "Denied": "Denied", "Approve": "Approve", "PartlyAvailable": "Partly Available", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", "MarkUnavailable": "Mark Unavailable", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Mark Available", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Remove", "Deny": "Deny", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Season", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete":"Delete Request", "Approve":"Approve Request", + "Approve4K":"Approve 4K Request", "ChangeAvailability":"Mark Available", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Denied", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", @@ -363,6 +373,7 @@ "RequestDate": "Request Date:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", From 90171f9bb21692985aa6788989e796039d87315a Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Mon, 14 Feb 2022 22:11:56 +0000 Subject: [PATCH 038/210] chore(release): :rocket: v4.12.0 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd26fb210..16aa06aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [4.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14) + + +### Features + +* **radarr:** 4K Requests and Radarr 4K support ([ba88848](https://github.com/Ombi-app/Ombi/commit/ba88848866b0a9dedb1e79b55c4d81a0fd453843)) + + + ## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13) @@ -347,12 +356,3 @@ -## [4.3.1](https://github.com/Ombi-app/Ombi/compare/v4.3.0...v4.3.1) (2021-10-27) - - -### Bug Fixes - -* :bug: Hides no results message during search. ([#4375](https://github.com/Ombi-app/Ombi/issues/4375)) ([b819b0e](https://github.com/Ombi-app/Ombi/commit/b819b0e007e578bf3d8425f19591f87029c64d06)) - - - diff --git a/version.json b/version.json index 7235ac378..67680f822 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.8" + "version": "4.12.0" } \ No newline at end of file From ce175a8632af8884e723c6e974da645dc54185d4 Mon Sep 17 00:00:00 2001 From: Francesco Servida Date: Tue, 15 Feb 2022 22:08:48 +0100 Subject: [PATCH 039/210] Implemented basic header auth controller --- src/Ombi/Controllers/V1/TokenController.cs | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index f9ea57a5c..b8775c05b 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -272,5 +272,37 @@ namespace Ombi.Controllers.V1 return ip; } + + [HttpPost("header_auth")] + [ProducesResponseType(401)] + public async Task HeaderAuth() + { + string username = null; + + // Check if Header Auth is enabled and Proxy IP is trusted + // TODO + // var ombiSettings = await repo.GetSettingsAsync(); + // END TODO + + + if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey("X-Remote-User")) + { + username = Request.HttpContext.Request.Headers["X-Remote-User"].ToString(); + + // Check if user exists + var user = await _userManager.FindByNameAsync(username); + if (user == null) + { + return new UnauthorizedResult(); + } + + return await CreateToken(true, user); + } + else + { + return new UnauthorizedResult(); + + } + } } } From d4e748fd2fc40386ad3d0475f6df6f67280c78eb Mon Sep 17 00:00:00 2001 From: Francesco Servida Date: Tue, 15 Feb 2022 23:24:13 +0100 Subject: [PATCH 040/210] Implemented Settings Interface and Models --- .../ClientApp/src/app/auth/auth.service.ts | 4 + .../ClientApp/src/app/interfaces/ISettings.ts | 2 + .../src/app/login/login.component.ts | 30 ++++- .../authentication.component.html | 121 ++++++++++-------- .../authentication.component.ts | 4 +- src/Ombi/Controllers/V1/TokenController.cs | 34 +++-- 6 files changed, 126 insertions(+), 69 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/auth/auth.service.ts b/src/Ombi/ClientApp/src/app/auth/auth.service.ts index afc0a2491..ad1ff32ac 100644 --- a/src/Ombi/ClientApp/src/app/auth/auth.service.ts +++ b/src/Ombi/ClientApp/src/app/auth/auth.service.ts @@ -28,6 +28,10 @@ export class AuthService extends ServiceHelpers { return this.http.post(`${this.url}/requirePassword`, JSON.stringify(login), { headers: this.headers }); } + public headerAuth(): Observable { + return this.http.post(`${this.url}/header_auth`, {}, { headers: this.headers }); + } + public getToken() { return this.jwtHelperService.tokenGetter(); } diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 8bf2755ec..1dc94f261 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -238,6 +238,8 @@ export interface IAuthenticationSettings extends ISettings { requireNonAlphanumeric: boolean; requireUppercase: boolean; enableOAuth: boolean; + enableHeaderAuth: boolean; + headerAuthVariable: string; } export interface ICustomPage extends ISettings { diff --git a/src/Ombi/ClientApp/src/app/login/login.component.ts b/src/Ombi/ClientApp/src/app/login/login.component.ts index 235e31a8e..132554f4f 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.ts +++ b/src/Ombi/ClientApp/src/app/login/login.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, Inject } from "@angular/core"; +import { Component, OnDestroy, OnInit, Inject } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; @@ -106,7 +106,7 @@ export class LoginComponent implements OnDestroy, OnInit { this.settingsService .getAuthentication() - .subscribe((x) => (this.authenticationSettings = x)); + .subscribe((x) => { this.authenticationSettings = x; this.headerAuth(); }); this.settingsService.getClientId().subscribe((x) => (this.clientId = x)); this.images.getRandomBackground().subscribe((x) => { this.background = this.sanitizer.bypassSecurityTrustStyle( @@ -121,7 +121,6 @@ export class LoginComponent implements OnDestroy, OnInit { if (base.length > 1) { this.baseUrl = base; } - this.translate .get("Login.Errors.IncorrectCredentials") .subscribe((x) => (this.errorBody = x)); @@ -255,6 +254,31 @@ export class LoginComponent implements OnDestroy, OnInit { ); } + public headerAuth() { + + if (this.authenticationSettings.enableHeaderAuth) { + this.authService.headerAuth().subscribe( + (x) => { + this.store.save("id_token", x.access_token); + + if (this.authService.loggedIn()) { + this.ngOnDestroy(); + this.router.navigate(["/"]); + } else { + this.notify.open(this.errorBody, "OK", { + duration: 3000, + }); + } + }, + (err) => { + this.notify.open(this.errorBody, "OK", { + duration: 3000000, + }); + } + ); + } + } + public ngOnDestroy() { clearInterval(this.timer); clearInterval(this.pinTimer); diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html index 7bc6a4e80..bde67e1c7 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html @@ -1,66 +1,81 @@ - +
Authentication
-
-
- - Allow users to login without a password -
-
+
+
+ + Allow users to login without a password + +
+
-
-
- Enable Plex OAuth -
-
+
+
+ Enable Plex OAuth +
+
- +
+ +
+ +
+
-
-
-
-
-
- +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
--> + +
+
+
+
+
+
-
\ No newline at end of file +
diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts index 6f140f8af..386711c4f 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup } from "@angular/forms"; import { NotificationService } from "../../services"; @@ -26,6 +26,8 @@ export class AuthenticationComponent implements OnInit { requireNonAlphanumeric: [x.requireNonAlphanumeric], requireUppercase: [x.requireUppercase], enableOAuth: [x.enableOAuth], + enableHeaderAuth: [x.enableHeaderAuth], + headerAuthVariable: [x.headerAuthVariable], }); }); } diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index b8775c05b..66cc66acf 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -16,6 +16,8 @@ using Ombi.Models.External; using Ombi.Models.Identity; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; namespace Ombi.Controllers.V1 { @@ -25,13 +27,14 @@ namespace Ombi.Controllers.V1 public class TokenController : ControllerBase { public TokenController(OmbiUserManager um, IOptions ta, ITokenRepository token, - IPlexOAuthManager oAuthManager, ILogger logger) + IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth) { _userManager = um; _tokenAuthenticationOptions = ta.Value; _token = token; _plexOAuthManager = oAuthManager; _log = logger; + _authSettings = auth; } private readonly TokenAuthentication _tokenAuthenticationOptions; @@ -39,6 +42,7 @@ namespace Ombi.Controllers.V1 private readonly OmbiUserManager _userManager; private readonly IPlexOAuthManager _plexOAuthManager; private readonly ILogger _log; + private readonly ISettingsService _authSettings; /// /// Gets the token. @@ -283,25 +287,31 @@ namespace Ombi.Controllers.V1 // TODO // var ombiSettings = await repo.GetSettingsAsync(); // END TODO + var authSettings = await _authSettings.GetSettingsAsync(); + _log.LogInformation("Logging with header: " + authSettings.HeaderAuthVariable); + if (authSettings.HeaderAuthVariable != null) + { + if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey(authSettings.HeaderAuthVariable)) + { + username = Request.HttpContext.Request.Headers[authSettings.HeaderAuthVariable].ToString(); + // Check if user exists + var user = await _userManager.FindByNameAsync(username); + if (user == null) + { + return new UnauthorizedResult(); + } - if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey("X-Remote-User")) - { - username = Request.HttpContext.Request.Headers["X-Remote-User"].ToString(); - - // Check if user exists - var user = await _userManager.FindByNameAsync(username); - if (user == null) + return await CreateToken(true, user); + } + else { return new UnauthorizedResult(); } - - return await CreateToken(true, user); - } + } else { return new UnauthorizedResult(); - } } } From 5ddda3c39e408eb9208db15081774e083e5fdb2f Mon Sep 17 00:00:00 2001 From: Francesco Servida Date: Tue, 15 Feb 2022 23:27:02 +0100 Subject: [PATCH 041/210] Implemented Settings in Model --- src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs index f6736e7c5..a72708123 100644 --- a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs @@ -13,5 +13,8 @@ namespace Ombi.Settings.Settings.Models public bool RequireNonAlphanumeric { get; set; } public bool RequireUppercase { get; set; } public bool EnableOAuth { get; set; } // Plex OAuth + public bool EnableHeaderAuth { get; set; } // Header SSO + public string HeaderAuthVariable { get; set; } // Header SSO + } } \ No newline at end of file From df2092d5e39d0707541af015934f6836d865a67c Mon Sep 17 00:00:00 2001 From: Francesco Servida Date: Tue, 15 Feb 2022 23:40:23 +0100 Subject: [PATCH 042/210] Implemented check for header auth enabled also in backend --- src/Ombi/Controllers/V1/TokenController.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index 66cc66acf..67f0e1189 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -283,13 +283,9 @@ namespace Ombi.Controllers.V1 { string username = null; - // Check if Header Auth is enabled and Proxy IP is trusted - // TODO - // var ombiSettings = await repo.GetSettingsAsync(); - // END TODO var authSettings = await _authSettings.GetSettingsAsync(); _log.LogInformation("Logging with header: " + authSettings.HeaderAuthVariable); - if (authSettings.HeaderAuthVariable != null) + if (authSettings.HeaderAuthVariable != null && authSettings.EnableHeaderAuth) { if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey(authSettings.HeaderAuthVariable)) { From 87cb9903db30e1dead25ee8c5ea34305eb084a03 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Feb 2022 09:10:20 +0000 Subject: [PATCH 043/210] fix(requests): :bug: Fixed the issue where Approving a 4K Request wouldn't send it to the correct 4K radarr instance #4509 --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 2 +- src/Ombi/.vscode/settings.json | 3 ++- .../components/movie/movie-details.component.ts | 6 +++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 2a29196b2..6d7ca236c 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -640,7 +640,7 @@ namespace Ombi.Core.Engine private async Task ProcessSendingMovie(MovieRequests request, bool is4K) { - if (request.Approved) + if (is4K ? request.Approved4K : request.Approved) { var result = await Sender.Send(request, is4K); if (result.Success && result.Sent) diff --git a/src/Ombi/.vscode/settings.json b/src/Ombi/.vscode/settings.json index f8ea48b8f..d77b3a0ae 100644 --- a/src/Ombi/.vscode/settings.json +++ b/src/Ombi/.vscode/settings.json @@ -21,6 +21,7 @@ "issues", "emby", "availability-rules", - "details" + "details", + "requests" ] } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index 4ea0a50d1..c040fe4e0 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -120,7 +120,11 @@ export class MovieDetailsComponent implements OnInit{ } else { const result = await firstValueFrom(this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: this.translate.currentLang, requestOnBehalf: userId, qualityPathOverride: undefined, rootFolderOverride: undefined, is4KRequest: is4K })); if (result.result) { - this.movie.requested = true; + if (is4K) { + this.movie.has4KRequest = true; + } else { + this.movie.requested = true; + } this.movie.requestId = result.requestId; this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.movie.title }), "Ok"); From 2fb5591323c0dba66a9d7d4b0884d18cd94dcc35 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 16 Feb 2022 09:18:23 +0000 Subject: [PATCH 044/210] chore(release): :rocket: v4.12.1 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16aa06aa2..04d9d8416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.12.1](https://github.com/Ombi-app/Ombi/compare/v4.12.0...v4.12.1) (2022-02-16) + + +### Bug Fixes + +* **requests:** :bug: Fixed the issue where Approving a 4K Request wouldn't send it to the correct 4K radarr instance ([87cb990](https://github.com/Ombi-app/Ombi/commit/87cb9903db30e1dead25ee8c5ea34305eb084a03)), closes [#4509](https://github.com/Ombi-app/Ombi/issues/4509) + + + # [4.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14) @@ -347,12 +356,3 @@ -## [4.3.2](https://github.com/Ombi-app/Ombi/compare/v4.3.1...v4.3.2) (2021-11-02) - - -### Bug Fixes - -* **translations:** 🌐 Localization - Ensuring all of the app including backend are localized [#4366](https://github.com/Ombi-app/Ombi/issues/4366) ([5e140ab](https://github.com/Ombi-app/Ombi/commit/5e140ab6183b887a7665f5e870eb0bd05d487ace)) - - - diff --git a/version.json b/version.json index 67680f822..397cacc2d 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.0" + "version": "4.12.1" } \ No newline at end of file From c0189dad478ea375beda61ba3bee3f029a39b8e5 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Feb 2022 16:30:42 +0000 Subject: [PATCH 045/210] fix(requests): :bug: Fixed the approve 4k option on the requests list not working as expected --- .../ClientApp/src/app/interfaces/IRequestModel.ts | 1 + .../components/movies-grid/movies-grid.component.ts | 12 +++++++++++- .../options/request-options.component.html | 4 ++-- .../components/options/request-options.component.ts | 2 ++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts index 1ccbd355b..130a97c1c 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts @@ -22,6 +22,7 @@ export interface IMovieRequests extends IFullBaseRequest { denied4K: boolean; deniedReason4K: string; requestedDate4k: Date; + requestedDate: Date; // For the UI rootPathOverrideTitle: string; diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index b3283bb73..984994016 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -142,10 +142,20 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: request.has4KRequest }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: request.has4KRequest, hasRegularRequest: this.checkDate(request.requestedDate) }; this.onOpenOptions.emit(data); } + private checkDate(date: Date|string): boolean { + if (date instanceof String) { + return new Date(date).getFullYear() > 1; + } + if (date instanceof Date) { + return date.getFullYear() > 1; + } + return false; + } + public switchFilter(type: RequestFilterType) { this.currentFilter = type; this.ngAfterViewInit(); diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html index b584cc0c5..72c0cdce3 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -2,10 +2,10 @@ {{'Requests.RequestPanel.Delete' | translate}} - + {{'Requests.RequestPanel.Approve' | translate}} - + {{'Requests.RequestPanel.Approve4K' | translate}} diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index a37680bc2..673f978e7 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -63,6 +63,8 @@ export class RequestOptionsComponent { } await firstValueFrom(this.requestService.approveMovie({id: this.data.id, is4K: true})); + this.bottomSheetRef.dismiss({type: UpdateType.Approve}); + return; } public async changeAvailability() { From e21ee35012abea711d735605993d235f3617484c Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 16 Feb 2022 16:36:29 +0000 Subject: [PATCH 046/210] chore(release): :rocket: v4.12.2 --- CHANGELOG.md | 13 +++++++++---- version.json | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04d9d8416..040dbc4a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.12.2](https://github.com/Ombi-app/Ombi/compare/v4.12.1...v4.12.2) (2022-02-16) + + +### Bug Fixes + +* **requests:** :bug: Fixed the approve 4k option on the requests list not working as expected ([c0189da](https://github.com/Ombi-app/Ombi/commit/c0189dad478ea375beda61ba3bee3f029a39b8e5)) + + + ## [4.12.1](https://github.com/Ombi-app/Ombi/compare/v4.12.0...v4.12.1) (2022-02-16) @@ -352,7 +361,3 @@ -## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05) - - - diff --git a/version.json b/version.json index 397cacc2d..ed73c8a2c 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.1" + "version": "4.12.2" } \ No newline at end of file From ae8783dfc4678b245b8af6d726531179f2323bf4 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Feb 2022 21:20:01 +0000 Subject: [PATCH 047/210] bug(requests): :bug: Fixed the requests lists, they now will show the status for 4K and regular requests --- .../Engine/MovieRequestEngineTests.cs | 649 ++++++++++++++---- src/Ombi.Core/Engine/MovieRequestEngine.cs | 37 +- 2 files changed, 544 insertions(+), 142 deletions(-) diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs index 9b12e0b01..8c37aaa9a 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs @@ -1,135 +1,514 @@ -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; -//using Moq; -//using NUnit.Framework; -//using Ombi.Core.Engine; -//using Ombi.Core.Models.Requests; -//using Ombi.Store.Entities.Requests; -//using Ombi.Store.Repository; -//using Assert = Xunit.Assert; - -//namespace Ombi.Core.Tests.Engine -//{ -// [TestFixture] -// public class MovieRequestEngineTests -// { -// public MovieRequestEngineTests() -// { -// RequestService = new Mock(); -// var requestService = new RequestService(null, RequestService.Object); -// Engine = new MovieRequestEngine(null, requestService, null, null, null, null, null, null); -// } - -// private MovieRequestEngine Engine { get; } -// private Mock RequestService { get; } - -// [Test] -// public async Task GetNewRequests_Should_ReturnEmpty_WhenThereAreNoNewRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// }; - -// var r = DbHelper.GetQueryable(requests[0], requests[1]); -// RequestService.Setup(x => x.Get()).Returns(r); - -// var result = await Engine.GetNewRequests(); - -// Assert.False(result.Any()); -// } - -// [Test] -// public async Task GetNewRequests_Should_ReturnOnlyNewRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); - -// var result = await Engine.GetNewRequests(); - -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.False(x.Available); -// Assert.False(x.Approved); -// }); -// } - -// [Test] -// public async Task GetApprovedRequests_Should_ReturnEmpty_WhenThereAreNoApprovedRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); - -// var result = await Engine.GetApprovedRequests(); - -// Assert.False(result.Any()); -// } - -// [Test] -// public async Task GetApprovedRequests_Should_ReturnOnlyApprovedRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); - -// var result = await Engine.GetApprovedRequests(); - -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.False(x.Available); -// Assert.True(x.Approved); -// }); -// } - -// [Test] -// public async Task GetAvailableRequests_Should_ReturnEmpty_WhenThereAreNoAvailableRequests() -// { -// var requests = new List -// { -// new MovieRequests { Approved = true }, -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); - -// var result = await Engine.GetAvailableRequests(); - -// Assert.False(result.Any()); -// } - -// [Test] -// public async Task GetAvailableRequests_Should_ReturnOnlyAvailableRequests_WhenThereAreMultipleRequests() -// { -// var requests = new List -// { -// new MovieRequests { Available = true }, -// new MovieRequests { Approved = true }, -// new MovieRequests(), -// }; -// RequestService.Setup(x => x.Get()).Returns(requests.AsQueryable); - -// var result = await Engine.GetAvailableRequests(); - -// Assert.Single(result); -// Assert.All(result, x => -// { -// Assert.True(x.Available); -// Assert.False(x.Approved); -// }); -// } -// } -//} \ No newline at end of file +using MockQueryable.Moq; +using Moq; +using Moq.AutoMock; +using NUnit.Framework; +using Ombi.Core.Authentication; +using Ombi.Core.Engine; +using Ombi.Core.Models.Requests; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using Ombi.Test.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Tests.Engine +{ + [TestFixture] + public class MovieRequestEngineTests + { + private MovieRequestEngine _subject; + private Mock _repoMock; + private AutoMocker _mocker; + + [SetUp] + public void Setup() + { + _mocker = new AutoMocker(); + var userManager = MockHelper.MockUserManager(new List { new OmbiUser { NormalizedUserName = "TEST", Id = "a" } }); + userManager.Setup(x => x.IsInRoleAsync(It.IsAny(), It.IsAny())).ReturnsAsync(true); + var principle = new Mock(); + var identity = new Mock(); + identity.Setup(x => x.Name).Returns("Test"); + principle.Setup(x => x.Identity).Returns(identity.Object); + + _repoMock = new Mock(); + var requestServiceMock = new Mock(); + requestServiceMock.Setup(x => x.MovieRequestService).Returns(_repoMock.Object); + + _mocker.Use(principle.Object); + _mocker.Use(userManager.Object); + _mocker.Use(requestServiceMock); + + _subject = _mocker.CreateInstance(); + var list = DbHelper.GetQueryableMockDbSet(new RequestSubscription()); + _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List().AsQueryable().BuildMock().Object); + } + + [Test] + public async Task GetRequestByStatus_PendingRequests_Non4K() + { + var movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.PendingApproval); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(4)); + } + + [Test] + public async Task GetRequestByStatus_PendingRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.PendingApproval); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(4)); + } + + + [Test] + public async Task GetRequestByStatus_PendingRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.PendingApproval); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(4)); + } + + + [Test] + public async Task GetRequestByStatus_ProcessingRequests_Non4K() + { + var movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.ProcessingRequest); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + } + + [Test] + public async Task GetRequestByStatus_ProcessingRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.ProcessingRequest); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + } + + + [Test] + public async Task GetRequestByStatus_ProcessingRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.ProcessingRequest); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(4)); + } + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_Non4K() + { + List movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + } + + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + } + + + [Test] + public async Task GetRequestByStatus_AvailableRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Available = true, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Available); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(1)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(2)); + } + + [Test] + public async Task GetRequestByStatus_DeniedRequests_Non4K() + { + List movies = RegularRequestData(); + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", Models.Requests.RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(3)); + } + + [Test] + public async Task GetRequestByStatus_DeniedRequests_4K() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.MinValue + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(1)); + Assert.That(result.Collection.First().Id, Is.EqualTo(3)); + } + + + [Test] + public async Task GetRequestByStatus_DeniedRequests_Both4K_And_Regular() + { + var movies = new List + { + new MovieRequests + { + Id= 1, + Available = true, + Approved = false, + Approved4K = true, + Has4KRequest = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved4K = false, + Available4K = true, + Denied = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 3, + Denied4K = true, + Has4KRequest = true, + RequestedDate = DateTime.MinValue + }, + new MovieRequests + { + Id = 4, + Has4KRequest = true, + Approved4K = false, + Approved = true, + Available4K = false, + Denied4K = false, + RequestedDate = DateTime.Now + } + }; + _repoMock.Setup(x => x.GetWithUser()).Returns(movies.AsQueryable()); + + var result = await _subject.GetRequestsByStatus(10, 0, "id", "asc", RequestStatus.Denied); + + Assert.That(result.Total, Is.EqualTo(2)); + Assert.That(result.Collection.First().Id, Is.EqualTo(2)); + Assert.That(result.Collection.ToArray()[1].Id, Is.EqualTo(3)); + } + + private static List RegularRequestData() + { + return new List + { + new MovieRequests + { + Id= 1, + Approved = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 2, + Approved = false, + Available = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 3, + Denied = true, + RequestedDate = DateTime.Now + }, + new MovieRequests + { + Id = 4, + Approved = false, + RequestedDate = DateTime.Now + } + }; + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 6d7ca236c..498cf3e0b 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -321,21 +321,44 @@ namespace Ombi.Core.Engine switch (status) { case RequestStatus.PendingApproval: - allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + allRequests = allRequests.Where(x => + (x.RequestedDate != DateTime.MinValue && !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + || + (x.Has4KRequest && !x.Approved4K && !x.Available4K && (!x.Denied4K.HasValue || !x.Denied4K.Value)) + ); break; case RequestStatus.ProcessingRequest: - allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + allRequests = allRequests.Where(x => + (x.RequestedDate != DateTime.MinValue && x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + || + (x.Has4KRequest && x.Approved4K && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)) + ); break; case RequestStatus.Available: - allRequests = allRequests.Where(x => x.Available); + allRequests = allRequests.Where(x => x.Available || x.Available4K); break; case RequestStatus.Denied: - allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available); + allRequests = allRequests.Where(x => + (x.Denied.HasValue && x.Denied.Value && !x.Available) + || + (x.Has4KRequest && x.Denied4K.HasValue && x.Denied4K.Value && !x.Available4K) + ); break; default: break; } + var requests = allRequests.ToList(); + var total = requests.Count; + if (total == 0) + { + return new RequestsViewModel + { + Collection = Enumerable.Empty(), + Total = total + }; + } + var prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(sortProperty, true); if (sortProperty.Contains('.')) @@ -348,11 +371,11 @@ namespace Ombi.Core.Engine //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); } - // TODO fix this so we execute this on the server - var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) ? allRequests.ToList().OrderBy(x => prop.GetValue(x)).ToList() : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); - var total = requests.Count(); + + // TODO fix this so we execute this on the server requests = requests.Skip(position).Take(count).ToList(); await CheckForSubscription(shouldHide, requests); From 5e29b0535b49f6851d4fc1f303b2841c35cf3652 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 16 Feb 2022 21:23:23 +0000 Subject: [PATCH 048/210] chore(release): :rocket: v4.12.3 --- CHANGELOG.md | 18 ++++-------------- version.json | 2 +- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 040dbc4a1..f4a7b3df6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.12.3](https://github.com/Ombi-app/Ombi/compare/v4.12.2...v4.12.3) (2022-02-16) + + + ## [4.12.2](https://github.com/Ombi-app/Ombi/compare/v4.12.1...v4.12.2) (2022-02-16) @@ -347,17 +351,3 @@ -# [4.4.0](https://github.com/Ombi-app/Ombi/compare/v4.3.3...v4.4.0) (2021-11-06) - - -### Bug Fixes - -* **request-list:** :bug: Fixed an issue where the request options were not appearing for Music requests ([c0406a2](https://github.com/Ombi-app/Ombi/commit/c0406a2ddebafb03d98ed25cdf7d89dc9a600c7d)) - - -### Features - -* **mass-email:** :sparkles: Added the ability to configure the Mass Email, we can now send BCC and we are less likely to be rate limited when not using bcc [#4377](https://github.com/Ombi-app/Ombi/issues/4377) ([ca655ae](https://github.com/Ombi-app/Ombi/commit/ca655ae57042dec44106a2f2ef5ba2e6f1019ee4)) - - - diff --git a/version.json b/version.json index ed73c8a2c..5295df539 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.2" + "version": "4.12.3" } \ No newline at end of file From a6d0bf83afecb5e7c421b453f3f4f7bfa71df7dc Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 17 Feb 2022 09:15:21 +0000 Subject: [PATCH 049/210] refactor(upgrades): Upgraded to Angular 13 and other dependency upgrades * feat: angular 13 upgrade * refactor: updated more packages * refactor: upgraded more packages * fix: fixed an issue where TheMovieDb exclude dropdown wasn't resetting itself --- src/Ombi/.vscode/settings.json | 3 +- src/Ombi/ClientApp/.gitignore | 1 + src/Ombi/ClientApp/package.json | 59 +- .../src/app/services/filedownload.service.ts | 6 + .../themoviedb/themoviedb.component.ts | 1 + .../ClientApp/src/app/shared/shared.module.ts | 5 +- src/Ombi/ClientApp/src/typings/globals.d.ts | 3 +- src/Ombi/ClientApp/yarn.lock | 5390 +++++++---------- 8 files changed, 2335 insertions(+), 3133 deletions(-) diff --git a/src/Ombi/.vscode/settings.json b/src/Ombi/.vscode/settings.json index d77b3a0ae..0ac92f4ba 100644 --- a/src/Ombi/.vscode/settings.json +++ b/src/Ombi/.vscode/settings.json @@ -23,5 +23,6 @@ "availability-rules", "details", "requests" - ] + ], + "rpc.enabled": true } diff --git a/src/Ombi/ClientApp/.gitignore b/src/Ombi/ClientApp/.gitignore index e1f679be2..043e30f6d 100644 --- a/src/Ombi/ClientApp/.gitignore +++ b/src/Ombi/ClientApp/.gitignore @@ -17,6 +17,7 @@ *.launch .settings/ *.sublime-workspace +.angular # IDE - VSCode .vscode/* diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index 7ee4f64e5..80a9842b4 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -9,35 +9,34 @@ }, "private": true, "dependencies": { - "@angular/animations": "^12.2.10", - "@angular/cdk": "^12.2.9", - "@angular/common": "^12.2.10", - "@angular/compiler": "^12.2.10", - "@angular/core": "^12.2.10", - "@angular/forms": "^12.2.10", - "@angular/localize": "^12.2.10", - "@angular/material": "^12.2.9", - "@angular/platform-browser": "^12.2.10", - "@angular/platform-browser-dynamic": "^12.2.10", - "@angular/platform-server": "^12.2.10", - "@angular/router": "^12.2.10", + "@angular/animations": "^13.2.0", + "@angular/cdk": "^13.2.0", + "@angular/common": "^13.2.0", + "@angular/compiler": "^13.2.0", + "@angular/core": "^13.2.0", + "@angular/forms": "^13.2.0", + "@angular/localize": "^13.2.0", + "@angular/material": "^13.2.0", + "@angular/platform-browser": "^13.2.0", + "@angular/platform-browser-dynamic": "^13.2.0", + "@angular/platform-server": "^13.2.0", + "@angular/router": "^13.2.0", "@angularclass/hmr": "^3.0.0", "@aspnet/signalr": "^1.1.0", "@auth0/angular-jwt": "^5.0.2", - "@fortawesome/fontawesome-free": "^5.15.4", + "@fortawesome/fontawesome-free": "^6.0.0", "@fullcalendar/core": "^4.2.0", "@fullcalendar/daygrid": "^4.4.0", "@fullcalendar/interaction": "^4.2.0", - "@ngu/carousel": "^3.0.2", - "@ngx-translate/core": "^13.0.0", - "@ngx-translate/http-loader": "^6.0.0", - "@ngxs/devtools-plugin": "^3.7.2", - "@ngxs/store": "^3.7.2", - "@types/jquery": "^3.3.29", - "@yellowspot/ng-truncate": "^1.4.0", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@ngxs/devtools-plugin": "^3.7.3", + "@ngxs/store": "^3.7.3", + "@types/jquery": "^3.5.13", + "@yellowspot/ng-truncate": "^2.0.0", "angular-bootstrap-md": "^7.5.4", "angular-router-loader": "^0.8.5", - "angularx-qrcode": "^11.0.0", + "angularx-qrcode": "^13.0.3", "bootstrap": "^4.2.1", "chart.js": "2.9.4", "core-js": "^2.5.4", @@ -51,11 +50,11 @@ "ngx-clipboard": "^12.1.0", "ngx-infinite-scroll": "^9.0.0", "ngx-moment": "^3.0.1", - "ngx-order-pipe": "^2.1.1", + "ngx-order-pipe": "^2.2.0", "popper.js": "^1.14.3", - "primeicons": "^4.1.0", - "primeng": "^12.2.0", - "rxjs": "^7.4.0", + "primeicons": "^5.0.0", + "primeng": "^13.2.0", + "rxjs": "^7.5.4", "sass-recursive-map-merge": "^1.0.1", "store": "^2.0.12", "ts-md5": "^1.2.7", @@ -64,15 +63,15 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~12.2.10", - "@angular/cli": "~12.2.10", - "@angular/compiler-cli": "^12.2.10", - "@angular/language-service": "^12.2.10", + "@angular-devkit/build-angular": "~13.2.0", + "@angular/cli": "~13.2.0", + "@angular/compiler-cli": "^13.2.0", + "@angular/language-service": "^13.2.0", "@types/jasmine": "~3.6.7", "@types/jasminewd2": "~2.0.8", "@types/node": "^16.10.9", "codelyzer": "^6.0.1", - "typescript": "~4.3.4" + "typescript": "~4.5.5" }, "optionalDependencies": { "protractor": "~5.4.0", diff --git a/src/Ombi/ClientApp/src/app/services/filedownload.service.ts b/src/Ombi/ClientApp/src/app/services/filedownload.service.ts index 59cc00def..88e7cd441 100644 --- a/src/Ombi/ClientApp/src/app/services/filedownload.service.ts +++ b/src/Ombi/ClientApp/src/app/services/filedownload.service.ts @@ -1,3 +1,9 @@ +// https://github.com/microsoft/TypeScript/issues/45612 +declare global { + interface Navigator { + msSaveOrOpenBlob: (blob: Blob) => void + } +} import { APP_BASE_HREF } from "@angular/common"; import { Injectable, Inject } from "@angular/core"; diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 21a47637c..427905902 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -113,6 +113,7 @@ export class TheMovieDbComponent implements OnInit { if (value) { return this.tmdbService.getKeywords(value); } + return []; }) ) .subscribe((r) => (this.filteredTags = r)); diff --git a/src/Ombi/ClientApp/src/app/shared/shared.module.ts b/src/Ombi/ClientApp/src/app/shared/shared.module.ts index f14eb43f2..87ea0051c 100644 --- a/src/Ombi/ClientApp/src/app/shared/shared.module.ts +++ b/src/Ombi/ClientApp/src/app/shared/shared.module.ts @@ -37,13 +37,12 @@ import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTreeModule } from '@angular/material/tree'; import { MomentModule } from "ngx-moment"; import { NgModule } from "@angular/core"; -import { SidebarModule } from "primeng/sidebar"; import { PipeModule } from "../pipes/pipe.module"; -import { TheMovieDbService } from "../services"; +import { RoleModule } from "./role-directive/role.module"; +import { SidebarModule } from "primeng/sidebar"; import { TranslateModule } from "@ngx-translate/core"; import { TruncateModule } from "@yellowspot/ng-truncate"; import { WatchProvidersSelectComponent } from "./components/watch-providers-select/watch-providers-select.component"; -import { RoleModule } from "./role-directive/role.module"; @NgModule({ declarations: [ diff --git a/src/Ombi/ClientApp/src/typings/globals.d.ts b/src/Ombi/ClientApp/src/typings/globals.d.ts index a52f87871..e30f97cb1 100644 --- a/src/Ombi/ClientApp/src/typings/globals.d.ts +++ b/src/Ombi/ClientApp/src/typings/globals.d.ts @@ -3,4 +3,5 @@ declare var __webpack_public_path__: any; // declare module "*.json" { // const value: any; // export default value; -// } \ No newline at end of file +// } + diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index 5cff8378d..0d40276b0 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -2,286 +2,277 @@ # yarn lockfile v1 -"@ampproject/remapping@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-1.0.1.tgz#1398e73e567c2a7992df6554c15bb94a89b68ba2" - integrity sha512-Ta9bMA3EtUHDaZJXqUoT5cn/EecwOp+SXpKJqxDbDuMbLvEMu6YTyDDuvTWeStODfdmXyfMo7LymQyPkN3BicA== +"@ampproject/remapping@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-1.1.1.tgz#e220d0a5288b07afd6392a584d15921839e9da32" + integrity sha512-YVAcA4DKLOj296CF5SrQ8cYiMRiUGc2sqFpLxsDGWE34suHqhGP/5yMsDHKsrh8hs8I5TiRVXNwKPWQpX3iGjw== dependencies: - "@jridgewell/resolve-uri" "1.0.0" + "@jridgewell/resolve-uri" "^3.0.3" sourcemap-codec "1.4.8" -"@angular-devkit/architect@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1202.10.tgz#6aae8e97ea209949507443cd9c414be94d258813" - integrity sha512-/sLgtXaFsNouxub5M/bQ2sBkiMIlPubuz6QMh+pA2jia82vJ3hcRMt4AnJTXuXpVY+aew4FiG0i9nt/8HETQsw== +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@angular-devkit/architect@0.1302.3": + version "0.1302.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1302.3.tgz#0e71cc2d737be6828d4072f53872aa2b17940870" + integrity sha512-0m8jMKrFfIqsYt33zTUwSmyekyfuS67hna08RQ6USjzWQSE3z4S8ulCUARSjM6AzdMblX+whfy56nJUpT17NSA== dependencies: - "@angular-devkit/core" "12.2.10" + "@angular-devkit/core" "13.2.3" rxjs "6.6.7" -"@angular-devkit/build-angular@~12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-12.2.10.tgz#aef9d1ab44e9f83dd8cd5625d7d10eaf81dd0e74" - integrity sha512-MuViuSmXmB67Wge3NpyfY2aAU4O4K+BbcHj1W1k1A9WTx/Hyh6jR6Zgwy/EsNh64zjdUg/Jlg/oHxIVabsWfvQ== - dependencies: - "@ampproject/remapping" "1.0.1" - "@angular-devkit/architect" "0.1202.10" - "@angular-devkit/build-optimizer" "0.1202.10" - "@angular-devkit/build-webpack" "0.1202.10" - "@angular-devkit/core" "12.2.10" - "@babel/core" "7.14.8" - "@babel/generator" "7.14.8" - "@babel/helper-annotate-as-pure" "7.14.5" - "@babel/plugin-proposal-async-generator-functions" "7.14.7" - "@babel/plugin-transform-async-to-generator" "7.14.5" - "@babel/plugin-transform-runtime" "7.14.5" - "@babel/preset-env" "7.14.8" - "@babel/runtime" "7.14.8" - "@babel/template" "7.14.5" - "@discoveryjs/json-ext" "0.5.3" - "@jsdevtools/coverage-istanbul-loader" "3.0.5" - "@ngtools/webpack" "12.2.10" +"@angular-devkit/build-angular@~13.2.0": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-13.2.3.tgz#03d9bb0f3a620a9125c2794e801c7071a9fea7e7" + integrity sha512-cZ2gRcMRgW3t1WCeP+2D/wmr2M+BR/RICAh0wL9irIdypWAzIFt3Z2+2R/HmgAAxoEkdUMIfB9AnkYmwRVgFeA== + dependencies: + "@ampproject/remapping" "1.1.1" + "@angular-devkit/architect" "0.1302.3" + "@angular-devkit/build-webpack" "0.1302.3" + "@angular-devkit/core" "13.2.3" + "@babel/core" "7.16.12" + "@babel/generator" "7.16.8" + "@babel/helper-annotate-as-pure" "7.16.7" + "@babel/plugin-proposal-async-generator-functions" "7.16.8" + "@babel/plugin-transform-async-to-generator" "7.16.8" + "@babel/plugin-transform-runtime" "7.16.10" + "@babel/preset-env" "7.16.11" + "@babel/runtime" "7.16.7" + "@babel/template" "7.16.7" + "@discoveryjs/json-ext" "0.5.6" + "@ngtools/webpack" "13.2.3" ansi-colors "4.1.1" - babel-loader "8.2.2" + babel-loader "8.2.3" + babel-plugin-istanbul "6.1.1" browserslist "^4.9.1" - cacache "15.2.0" - caniuse-lite "^1.0.30001032" + cacache "15.3.0" circular-dependency-plugin "5.2.2" - copy-webpack-plugin "9.0.1" - core-js "3.16.0" - critters "0.0.10" - css-loader "6.2.0" - css-minimizer-webpack-plugin "3.0.2" - esbuild-wasm "0.13.4" - find-cache-dir "3.3.1" - glob "7.1.7" + copy-webpack-plugin "10.2.1" + core-js "3.20.3" + critters "0.0.16" + css-loader "6.5.1" + esbuild-wasm "0.14.14" + glob "7.2.0" https-proxy-agent "5.0.0" - inquirer "8.1.2" + inquirer "8.2.0" + jsonc-parser "3.0.0" karma-source-map-support "1.4.0" - less "4.1.1" - less-loader "10.0.1" - license-webpack-plugin "2.3.20" - loader-utils "2.0.0" - mini-css-extract-plugin "2.2.1" + less "4.1.2" + less-loader "10.2.0" + license-webpack-plugin "4.0.1" + loader-utils "3.2.0" + mini-css-extract-plugin "2.5.3" minimatch "3.0.4" - open "8.2.1" + open "8.4.0" ora "5.4.1" parse5-html-rewriting-stream "6.0.1" - piscina "3.1.0" - postcss "8.3.6" + piscina "3.2.0" + postcss "8.4.5" postcss-import "14.0.2" - postcss-loader "6.1.1" - postcss-preset-env "6.7.0" + postcss-loader "6.2.1" + postcss-preset-env "7.2.3" regenerator-runtime "0.13.9" - resolve-url-loader "4.0.0" + resolve-url-loader "5.0.0" rxjs "6.6.7" - sass "1.36.0" - sass-loader "12.1.0" + sass "1.49.0" + sass-loader "12.4.0" semver "7.3.5" - source-map-loader "3.0.0" - source-map-support "0.5.19" - style-loader "3.2.1" - stylus "0.54.8" - stylus-loader "6.1.0" - terser "5.7.1" - terser-webpack-plugin "5.1.4" + source-map-loader "3.0.1" + source-map-support "0.5.21" + stylus "0.56.0" + stylus-loader "6.2.0" + terser "5.10.0" text-table "0.2.0" tree-kill "1.2.2" - tslib "2.3.0" - webpack "5.50.0" - webpack-dev-middleware "5.0.0" - webpack-dev-server "3.11.2" + tslib "2.3.1" + webpack "5.67.0" + webpack-dev-middleware "5.3.0" + webpack-dev-server "4.7.3" webpack-merge "5.8.0" - webpack-subresource-integrity "1.5.2" + webpack-subresource-integrity "5.1.0" optionalDependencies: - esbuild "0.13.4" + esbuild "0.14.14" -"@angular-devkit/build-optimizer@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.10.tgz#f72c76e873e10139e95633d0ac3c4c8112d3f40b" - integrity sha512-NcFEtj4Vfc7gXJtXEVf1mnpk0CJ0htlkm/LbidPcs1PEQbJ/yDgZ44fO+53Pt6NzLmsmPHXOmRzN7O6HkxolPA== +"@angular-devkit/build-webpack@0.1302.3": + version "0.1302.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1302.3.tgz#a1b43f0d61048e91d25f43e2ec14c1545b070655" + integrity sha512-+JYH1lWU0UOjaWYxpoR2VLsdcb6nG9Gv+M1gH+kT0r2sAKOFaHnrksbOvca3EhDoaMa2b9LSGEE0OcSHWnN+eQ== dependencies: - source-map "0.7.3" - tslib "2.3.0" - typescript "4.3.5" - -"@angular-devkit/build-webpack@0.1202.10": - version "0.1202.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1202.10.tgz#ad92b8865623092951b4fddf6f603661f7910865" - integrity sha512-xGSy12g+wa/qeYOaPGkeoJp3zatlS+HZxECtw0Up3ES85Ewrx9PvraexHSuRxnkuBQykRORKf6WbPt/WYIAVGQ== - dependencies: - "@angular-devkit/architect" "0.1202.10" + "@angular-devkit/architect" "0.1302.3" rxjs "6.6.7" -"@angular-devkit/core@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-12.2.10.tgz#3da62eceef3904f92cd3f860618b4ae513029ce2" - integrity sha512-0qhmS7Qvl0hiRVTHxEC/ipFAfzYofPstw0ZITDpEMw+pgHlOZolOlnFrv8LyOXWNqlSIH5fS9D3WF7Hpm7ApYA== +"@angular-devkit/core@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-13.2.3.tgz#a5770c7a5e50d1b09e5a41ccb7cf0af140a9e168" + integrity sha512-/47RA8qmWzeS60xSdaprIn1MiSv0Iw83t0M9/ENH7irFS5vMAq62NCcwiWXH59pZmvvLbF+7xy/RgYUZLr4nHQ== dependencies: - ajv "8.6.2" - ajv-formats "2.1.0" + ajv "8.9.0" + ajv-formats "2.1.1" fast-json-stable-stringify "2.1.0" magic-string "0.25.7" rxjs "6.6.7" source-map "0.7.3" -"@angular-devkit/schematics@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-12.2.10.tgz#b8d4031053fd76d93caa7f33aeeb67383e37f0ab" - integrity sha512-oQ2EWdkEDE+eAttHeviXsvBi85PsntQT+IffjKUZdbQU+Leuk/pKUpTeea1YosU1p4Cz3PKYF+P/Nl5Jy3B7IQ== +"@angular-devkit/schematics@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-13.2.3.tgz#c2acb68ba798f4ab115bee73f078d98f5b20d21c" + integrity sha512-+dyC4iKV0huvpjiuz4uyjLNK3FsCIp/Ghv5lXvhG6yok/dCAubsJItJOxi6G16aVCzG/E9zbsDfm9fNMyVOkgQ== dependencies: - "@angular-devkit/core" "12.2.10" + "@angular-devkit/core" "13.2.3" + jsonc-parser "3.0.0" + magic-string "0.25.7" ora "5.4.1" rxjs "6.6.7" -"@angular/animations@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-12.2.10.tgz#c6610fc7b2021451c46dcfe27bd4fcc8e3789e08" - integrity sha512-K1WT3m/StW5a4SE9wKT+D7eteyWK+MW3pAwFPaKH8EU9k6dItlLr3jWZsve5w2u/GLSnrOMGJNU/JmTfskV9LA== +"@angular/animations@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.2.2.tgz#b6af6962a721d73a3832d6f4891dc644bee50ed7" + integrity sha512-qX8LAMuCJaueHBVyuwKtqunx96G0Dr26k7y5Z03VTcscYst4Ib4V2d4i5dwn3HS82DehFdO86cm3Hi2PqE/qww== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/cdk@^12.2.9": - version "12.2.9" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-12.2.9.tgz#f39e4d7cdb3568ad8e1d412e3500772e2d4c605c" - integrity sha512-9Wgj69iGAZ4teQqW/zPbVg2RGna+m9i3v0zkWGx/+Uo95rikJCUZBQM4bfeOe+bSJrS77jV5EisBWG7ayNUSzQ== +"@angular/cdk@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-13.2.2.tgz#4d41b1da6e92e3bc80d28aabe2049fa7ca40f5b1" + integrity sha512-cT5DIaz+NI9IGb3X61Wh26+L6zdRcOXT1BP37iRbK2Qa2qM8/0VNeK6hrBBIblyoHKR/WUmRlS8XYf6mmArpZw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" optionalDependencies: parse5 "^5.0.0" -"@angular/cli@~12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-12.2.10.tgz#73062d433434b7b25073863940d82e4e6f7fa924" - integrity sha512-gx2XlOUjAAYyJBBIz4QkgsLLRMdFTQbcOR41/Yv0kgpR6AStrOWhz7tpYPbU6vWMjehpuTaWv4NE5eGjwVTZqg== +"@angular/cli@~13.2.0": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-13.2.3.tgz#4a1694025bf0ac589aeaec17a6ba560647cf07b0" + integrity sha512-QsakxpdQuO67u4fQNuOASqabYUO9gJb/5CpUGpWbuBzru0/9CMEF1CtXoF4EoDiwa5sJMirz3SJMKhtzFlv1cQ== dependencies: - "@angular-devkit/architect" "0.1202.10" - "@angular-devkit/core" "12.2.10" - "@angular-devkit/schematics" "12.2.10" - "@schematics/angular" "12.2.10" + "@angular-devkit/architect" "0.1302.3" + "@angular-devkit/core" "13.2.3" + "@angular-devkit/schematics" "13.2.3" + "@schematics/angular" "13.2.3" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" - debug "4.3.2" + debug "4.3.3" ini "2.0.0" - inquirer "8.1.2" + inquirer "8.2.0" jsonc-parser "3.0.0" npm-package-arg "8.1.5" npm-pick-manifest "6.1.1" - open "8.2.1" + open "8.4.0" ora "5.4.1" - pacote "11.3.5" - resolve "1.20.0" + pacote "12.0.3" + resolve "1.22.0" semver "7.3.5" symbol-observable "4.0.0" uuid "8.3.2" -"@angular/common@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-12.2.10.tgz#1298fc0d7becfdf5368676ceb01a7df97331d412" - integrity sha512-7IjD0frrKG/nt3/fo4mKDH0Tx5Nn8f2G8Ks/aq6xnJssy/V841COjua0ZyfPOkPS1r0VEaQJB5ieqMrp2T6MWg== +"@angular/common@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.2.2.tgz#3c787a53acf69633902e804c141c39a3455d85d3" + integrity sha512-56C/bheNLKtTCyQUZCiYtKbBIZN9jj6rjFILPtJCGls3cBCxp7t9tIdoLiQG/wVQRmaxdj1ioLT+sCWz7mLtQw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/compiler-cli@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-12.2.10.tgz#c6b19af123d5772a8a53ac7872401fdc726f7b57" - integrity sha512-cPWxNMwPTM7IsEBxMrh4yY9XZi4gZRv7EmKWOfBw6hiW0SEmthIQWOvCaoL5CPsdUhInNxXWvwAoFggk/tfJ5g== +"@angular/compiler-cli@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-13.2.2.tgz#f2c4c207fdbcc274c7a153b3506c3b8f99fc6f59" + integrity sha512-tuOIcEEKVIht+mKrj0rtX3I8gc+ByPjzpCZhFQRggxM6xbKJIToO1zERbEGKrZ+sUJ6BB5KLvscDy+Pddy3b8w== dependencies: "@babel/core" "^7.8.6" - "@babel/types" "^7.8.6" - canonical-path "1.0.0" chokidar "^3.0.0" convert-source-map "^1.5.1" dependency-graph "^0.11.0" magic-string "^0.25.0" - minimist "^1.2.0" reflect-metadata "^0.1.2" semver "^7.0.0" - source-map "^0.6.1" sourcemap-codec "^1.4.8" - tslib "^2.2.0" - yargs "^17.0.0" + tslib "^2.3.0" + yargs "^17.2.1" "@angular/compiler@9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5" integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== -"@angular/compiler@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-12.2.10.tgz#7da81b341f90e779d29f7f96c82c93e57f84c02e" - integrity sha512-5fuzX8P74z28CRYTamsZgsdUyh0c53shytZYfa0cGFXyV8VD/r8AMIyQ4y7Y5Fmt4Nr+65EVeYb3sI7IzYiueg== +"@angular/compiler@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.2.2.tgz#89999576906f4d65b58ecff38666c71809ddee45" + integrity sha512-XXQtB0/e7pR2LPrHmpEiTU72SX4xxHGy91vYWIj1JCjSn0fYF7vtHzSJPXDvkbnkNow/PXXzJJYaU1ctdMZPcA== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" "@angular/core@9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e" integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== -"@angular/core@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-12.2.10.tgz#899f5b6e44c33790640d04df2a6981b622a9e6d7" - integrity sha512-xG1IbmEAV7gWpiY2MSFc87MlmB3yff8/TAlSE8Tj2ZFzb1lFjeFnrZ1y50Hi2AcVyX/KA1mx/RyJ0M7fmQ1ayw== +"@angular/core@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.2.2.tgz#30d2cd6ed3d74d90071c135def7163b12137eb7f" + integrity sha512-zpctw0BxIVOsRFnckchK15SD1L8tzhf5GzwIDaM6+VylDQj1uYkm8mvAjJTQZyUuApomoFet2Rfj7XQPV+cNSQ== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/forms@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-12.2.10.tgz#c1a2f6f07354d56d78dc1dfc1f9ff92750ea4daa" - integrity sha512-ntTJOaLeH+7th5W4LEm3/yHsBvaFpfRgn0Uc88Th8p2gvorqCgpJMWogJIx/yESNolSFItY6k/x7kjuMBgm9mA== +"@angular/forms@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-13.2.2.tgz#cdc4f249a85160eab003104d7050f8797a2038a7" + integrity sha512-T61W4Ay9X9qhxjc6lLqpNFeHrGKwg2mqdsZ3zIm/c7oKo37mgl9TB5kkrtnS+205r3N2hF4ICnGFZ4a/egUP/g== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/language-service@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-12.2.10.tgz#051d92813185535c7b1c496f4306f10a729b335e" - integrity sha512-o9KY39+1bw9xB6vsMWAbcPFWNdTQ/6TSKyQkmAyYca7T6LlNOe/qWln2655ZFPhyG6d9R8nbTi3X0MhMP+H7xQ== +"@angular/language-service@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-13.2.2.tgz#4de8742dc7603a331cb39be065f5a30d0bdc0fad" + integrity sha512-2P5+wRsbHgpI2rVeFwnsLWxyntUiw8kG9Tqh5BkVDqtQovbYtzFiaMkf5TFz/g938JBBgeRQzvXr1kQhEidAWQ== -"@angular/localize@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-12.2.10.tgz#25bab8bc6e8b247e83a7146df4dbf39b73d0ecfe" - integrity sha512-YTvDYvhjo+qakuLdyWTpgz7Hd4nzmCLdzk/P2a46SiYWG4i/ShBmfkhJNAgZfVnnM6oSt15z/VCgB31lS7JrYg== +"@angular/localize@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-13.2.2.tgz#a19ee864e362baf1d538d56b9021e7d71d7293c9" + integrity sha512-W/deDIxAFlv0euq7hxYPRCvj2DtDTsid5mRqyjEaVr+eYaLPnD8EElZuKuQEDeo7rWkCjljEpBrFsXwC5FZ8cw== dependencies: - "@babel/core" "7.8.3" - glob "7.1.7" - yargs "^17.0.0" + "@babel/core" "7.8.6" + glob "7.2.0" + yargs "^17.2.1" -"@angular/material@^12.2.9": - version "12.2.9" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-12.2.9.tgz#b4a1e138c7fd2341bd27aa6012b4738f61b5ad2d" - integrity sha512-+eM67RF038S56m3wsj37h0PyyRD18cQ8V2zmKG1UezH0nnosbmCAwzH9BfcNiIB+/V+k5QMJ/JVu5MjDQqX37w== +"@angular/material@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-13.2.2.tgz#d673f68b0c9357ada2ee82ffeaf11f10f5d49b27" + integrity sha512-YAjPp2+/wuEOPfkAxdRVdbWHiK4P3DgMZa9qP/NizN2lTXNrftEfD09ZlPIFMZRnnExezJ2LnO7eyELpc1VSKg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-browser-dynamic@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.10.tgz#c30ef29587a09fbcfd0d9921b64ce264e6650893" - integrity sha512-CLYHCdTCzpxvMwITRBLlUoa44orDdogMaQfKIMEQsWrynf+zGZKYe5chAut9P/A54PVPUtKeQrfEVFjmbdYR2w== +"@angular/platform-browser-dynamic@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.2.2.tgz#9a50fb79b96b62c13e65c996727542c5174e9246" + integrity sha512-lj6xwat0StLp+ROFqXU62upwHQhlxaQi0djhrS+DGKUK0Xu9bkBeaSCfBFgS78jPm1SwL8Xztu9/vuDAHLRrqw== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-browser@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-12.2.10.tgz#402132b528f6dc0235c5571cdf0f29ef1a79277a" - integrity sha512-2pYoscOJijbqFsnYpKX6o4ojt4XfZiNhODTf9RDOPVKjVqFsRNVThg76kdKtN+N8q6N1z4I01x6aX4EeWqQqIA== +"@angular/platform-browser@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.2.2.tgz#e603c32c3550970211b004df3e227e0d2b5088cd" + integrity sha512-M7gWC8fFCPc/CRcHCzqe/j7WzwAUMeKt9vwlK633XnesHBoqZdYgbb3YHHc6WPVU0YI09Nb/Hm5sezEKmjUmPg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" -"@angular/platform-server@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-12.2.10.tgz#8e11dea472db244c2fa71ec0d08911d52151b3b5" - integrity sha512-g2m2/+e+6mxbvMYICe+1zDP/KGMwmf9gu/fz+I9UFpGuAx4S7eBL/GCII2gnrrbavZ2vxczY0Ff4JU7AEBrGug== +"@angular/platform-server@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-13.2.2.tgz#706c9cef4cec156f3e9874963f868530e67e6d3d" + integrity sha512-v17/E9hWY5/MgUjk+E+aNUNZ/wmhHb08RyeKvvUKhx8Xb24hRiMdjA9yMkt1UsjOGJUIeZ8s5nn6xRiRc3t+9A== dependencies: domino "^2.1.2" - tslib "^2.2.0" + tslib "^2.3.0" xhr2 "^0.2.0" -"@angular/router@^12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-12.2.10.tgz#53d64ce59a65cde096e4a0125b117b6040d08fa8" - integrity sha512-e9sqOdLNF3pVRZPZtD6OdvERdTWKP7Et8Mz4OSNT8GEe6SctRAaptTAqY09AGpi4BO2+LsxVBERYfhZw9bZ2bA== +"@angular/router@^13.2.0": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-13.2.2.tgz#ba637da8963e5905520622f02357c4eda2f3da68" + integrity sha512-dt2b9/kGJAkmOqUmUD3aKlp4pGpdqLwB0zmhUYF3ktNEcQaPf4ZjWT/4jhy09gFL+TKOHG5OQW9GxBbhWI4bSg== dependencies: - tslib "^2.2.0" + tslib "^2.3.0" "@angularclass/hmr@^3.0.0": version "3.0.0" @@ -316,25 +307,37 @@ dependencies: "@babel/highlight" "^7.14.5" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0": +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== -"@babel/core@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010" - integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.14.8" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-module-transforms" "^7.14.8" - "@babel/helpers" "^7.14.8" - "@babel/parser" "^7.14.8" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.14.8" - "@babel/types" "^7.14.8" +"@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + +"@babel/core@7.16.12": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.12" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -342,18 +345,18 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/core@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" - integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== +"@babel/core@7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.6.tgz#27d7df9258a45c2e686b6f18b6c659e563aa4636" + integrity sha512-Sheg7yEJD51YHAvLEV/7Uvw95AeWqYPL3Vk3zGujJKIhJ+8oLw2ALaf3hbucILhKsgSoADOvtKRJuNVdcJkOrg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.3" - "@babel/helpers" "^7.8.3" - "@babel/parser" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/generator" "^7.8.6" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.6" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -363,7 +366,28 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.7.5", "@babel/core@^7.8.6": +"@babel/core@^7.12.3": + version "7.17.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.4.tgz#a22f1ae8999122873b3d18865e98c7a3936b8c8b" + integrity sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/core@^7.8.6": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10" integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og== @@ -384,16 +408,16 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070" - integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg== +"@babel/generator@7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== dependencies: - "@babel/types" "^7.14.8" + "@babel/types" "^7.16.8" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.14.8", "@babel/generator@^7.15.4", "@babel/generator@^7.15.8", "@babel/generator@^7.8.3": +"@babel/generator@^7.15.4", "@babel/generator@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== @@ -402,29 +426,38 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" - integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== +"@babel/generator@^7.16.8", "@babel/generator@^7.17.3", "@babel/generator@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@7.16.7", "@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== dependencies: - "@babel/types" "^7.14.5" + "@babel/types" "^7.16.7" -"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4": +"@babel/helper-annotate-as-pure@^7.14.5": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835" integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA== dependencies: "@babel/types" "^7.15.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f" - integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== dependencies: - "@babel/helper-explode-assignable-expression" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.14.5", "@babel/helper-compilation-targets@^7.15.4": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== @@ -434,17 +467,28 @@ browserslist "^4.16.6" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e" - integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw== +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": + version "7.17.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" + integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.14.5": version "7.14.5" @@ -454,10 +498,18 @@ "@babel/helper-annotate-as-pure" "^7.14.5" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" + integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + regexpu-core "^5.0.1" + +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -468,14 +520,21 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c" - integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g== +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4": +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== @@ -484,6 +543,15 @@ "@babel/template" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-get-function-arity@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" @@ -491,6 +559,13 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-hoist-variables@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" @@ -498,6 +573,13 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-member-expression-to-functions@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" @@ -505,14 +587,28 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4": +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== dependencies: "@babel/types" "^7.15.4" -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.14.8", "@babel/helper-module-transforms@^7.15.4", "@babel/helper-module-transforms@^7.15.8": +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2" integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg== @@ -526,6 +622,20 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.6" +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" @@ -533,21 +643,33 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== -"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f" - integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ== +"@babel/helper-plugin-utils@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-remap-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" + integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-wrap-function" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4": +"@babel/helper-replace-supers@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== @@ -557,6 +679,17 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-simple-access@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" @@ -564,12 +697,19 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb" - integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A== +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" "@babel/helper-split-export-declaration@^7.15.4": version "7.15.4" @@ -578,27 +718,44 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== -"@babel/helper-wrap-function@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7" - integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw== +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helper-wrap-function@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" + integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== dependencies: - "@babel/helper-function-name" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" -"@babel/helpers@^7.14.8", "@babel/helpers@^7.15.4", "@babel/helpers@^7.8.3": +"@babel/helpers@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== @@ -607,6 +764,15 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/helpers@^7.16.7", "@babel/helpers@^7.17.2", "@babel/helpers@^7.8.4": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + "@babel/highlight@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" @@ -616,150 +782,170 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8", "@babel/parser@^7.8.3": +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.14.7", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/parser@^7.15.4", "@babel/parser@^7.15.8": version "7.15.8" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e" - integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-async-generator-functions@7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz#784a48c3d8ed073f65adcf30b57bcbf6c8119ace" - integrity sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" - "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" -"@babel/plugin-proposal-async-generator-functions@^7.14.7": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz#a3100f785fab4357987c4223ab1b02b599048403" - integrity sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA== +"@babel/plugin-proposal-async-generator-functions@7.16.8", "@babel/plugin-proposal-async-generator-functions@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" + integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.15.4" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== +"@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-class-static-block@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7" - integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA== +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" + integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== +"@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.14.7": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz#ef68050c8703d07b25af402cb96cf7f34a68ed11" - integrity sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg== +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" + integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/compat-data" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-transform-parameters" "^7.16.7" -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== +"@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== +"@babel/plugin-proposal-private-methods@^7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" + integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.10" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-private-property-in-object@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5" - integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA== +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-create-class-features-plugin" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": +"@babel/plugin-proposal-unicode-property-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== @@ -865,64 +1051,73 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-async-to-generator@7.14.5", "@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== +"@babel/plugin-transform-async-to-generator@7.16.8", "@babel/plugin-transform-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" + integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.14.5": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-classes@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1" - integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg== +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== +"@babel/plugin-transform-destructuring@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" + integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": +"@babel/plugin-transform-dotall-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== @@ -930,226 +1125,228 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2" - integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA== +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== +"@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1" - integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA== +"@babel/plugin-transform-modules-commonjs@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== dependencies: - "@babel/helper-module-transforms" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.15.4" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132" - integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw== +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== dependencies: - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.4" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.7": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" + integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.14.5", "@babel/plugin-transform-parameters@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62" - integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ== +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== +"@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-runtime@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz#30491dad49c6059f8f8fa5ee8896a0089e987523" - integrity sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg== +"@babel/plugin-transform-runtime@7.16.10": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.10.tgz#53d9fd3496daedce1dd99639097fa5d14f4c7c2c" + integrity sha512-9nwTiqETv2G7xI4RvXHNfpGdr8pAA+Q/YtN3yLK7OoK7n9OibVm/xymJ838a9A6E/IciOLPj82lZk0fW6O4O7w== dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-spread@^7.14.6": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz#79d5aa27f68d700449b2da07691dfa32d2f6d468" - integrity sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/preset-env@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.8.tgz#254942f5ca80ccabcfbb2a9f524c74bca574005b" - integrity sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg== - dependencies: - "@babel/compat-data" "^7.14.7" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-async-generator-functions" "^7.14.7" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.14.5" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.14.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.14.5" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/preset-env@7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" + integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + dependencies: + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.11" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -1164,50 +1361,50 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.14.5" - "@babel/plugin-transform-classes" "^7.14.5" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.14.5" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.14.5" - "@babel/plugin-transform-modules-systemjs" "^7.14.5" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.7" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.14.5" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.14.6" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.14.8" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.15.0" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" semver "^6.3.0" -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1215,10 +1412,10 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" - integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== +"@babel/runtime@7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== dependencies: regenerator-runtime "^0.13.4" @@ -1229,16 +1426,16 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" - integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== +"@babel/template@7.16.7", "@babel/template@^7.16.7", "@babel/template@^7.8.6": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.14.5" - "@babel/types" "^7.14.5" + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/template@^7.14.5", "@babel/template@^7.15.4", "@babel/template@^7.8.3": +"@babel/template@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== @@ -1247,7 +1444,7 @@ "@babel/parser" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.8", "@babel/traverse@^7.15.4", "@babel/traverse@^7.8.3": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== @@ -1262,7 +1459,23 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6": +"@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.8.6": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.4.4", "@babel/types@^7.8.6": version "7.15.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== @@ -1270,20 +1483,40 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== +"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" -"@discoveryjs/json-ext@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" - integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== +"@cordobo/qrcode@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@cordobo/qrcode/-/qrcode-1.5.0.tgz#fe430514bad73413cd9e4bf4bdd4698353d82217" + integrity sha512-aZ5n3MYw10t4v68EGvRGE1DL7iWfAiTUy4MSZRoqjHTRYdjX40sYgJf48NZa6zZeXVuJOEB/1Ni9KzS+C/EC0w== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^17.3.1" + +"@csstools/postcss-progressive-custom-properties@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.2.0.tgz#7d53b773de50874c3885918dcb10cac97bf66ed5" + integrity sha512-YLpFPK5OaLIRKZhUfnrZPT9s9cmtqltIOg7W6jPcxmiDpnZ4lk+odfufZttOAgcg6IHWvNLgcITSLpJxIQB/qQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@discoveryjs/json-ext@0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" + integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== -"@fortawesome/fontawesome-free@^5.15.4": - version "5.15.4" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5" - integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg== +"@fortawesome/fontawesome-free@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.0.0.tgz#6f3bd8e42997c7d536a1246877ed8bcd4f005a54" + integrity sha512-6LB4PYBST1Rx40klypw1SmSDArjFOcfBf2LeX9Zg5EKJT2eXiyiJq+CyBYKeXyK0sXS2FsCJWSPr/luyhuvh0Q== "@fullcalendar/core@^4.2.0": version "4.4.2" @@ -1305,64 +1538,77 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + "@istanbuljs/schema@^0.1.2": version "0.1.3" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jridgewell/resolve-uri@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-1.0.0.tgz#3fdf5798f0b49e90155896f6291df186eac06c83" - integrity sha512-9oLAnygRMi8Q5QkYEU4XWK04B+nuoXoxjRvRxgjuChkLZFBja0YPSgdZ7dZtwhncLBcQe/I/E+fLuk5qxcYVJA== - -"@jsdevtools/coverage-istanbul-loader@3.0.5": +"@jridgewell/resolve-uri@^3.0.3": version "3.0.5" - resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz#2a4bc65d0271df8d4435982db4af35d81754ee26" - integrity sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA== + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== dependencies: - convert-source-map "^1.7.0" - istanbul-lib-instrument "^4.0.3" - loader-utils "^2.0.0" - merge-source-map "^1.1.0" - schema-utils "^2.7.0" + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" -"@ngtools/webpack@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-12.2.10.tgz#38d4a5ee9cc39012e9ba2f987f6c1c07b132b19e" - integrity sha512-8ptz2WqEeqFLOMbiYJ6x6XARjzWIrCHzRzpGwvKS28L5iMWeYuvX2EB48uKkMFy/8RJ0SkwyAJkFClPNJvDfrQ== +"@ngtools/webpack@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-13.2.3.tgz#a4434eb5e2ec3cc04d7f714f20d5203114563f33" + integrity sha512-wooUZiV92QyoeFxkhqIwH/cfiAAAn+l8fEEuaaEIfJtpjpbShvvlboEVsqb28soeGiFJfLcmsZM3mUFgsG4QBQ== -"@ngu/carousel@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@ngu/carousel/-/carousel-3.0.2.tgz#e0349e32344655a63fce82c580560365a06c09fd" - integrity sha512-EGvCs0LoStIKJoJfQWGeEs1RYHOgxZiSiqi6Thr7F9NVPvJkkwxlSh40uA6AQoWIv6WWhhNr1Imrbp27NZGs6Q== +"@ngu/carousel@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@ngu/carousel/-/carousel-4.0.0.tgz#928937168010b36946135d86a1a90a8417a0634c" + integrity sha512-/L54YCTMxEZ98BwEWu3cCmH5FkQ2uG6eyw3EANp7D2QOPwry20/5YRWYjp7OkMOVTQ/nOL/pI4na0wJ/qfWD2A== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngx-translate/core@^13.0.0": - version "13.0.0" - resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-13.0.0.tgz#60547cb8a0845a2a0abfde6b0bf5ec6516a63fd6" - integrity sha512-+tzEp8wlqEnw0Gc7jtVRAJ6RteUjXw6JJR4O65KlnxOmJrCGPI0xjV/lKRnQeU0w4i96PQs/jtpL921Wrb7PWg== +"@ngx-translate/core@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-14.0.0.tgz#af421d0e1a28376843f0fed375cd2fae7630a5ff" + integrity sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngx-translate/http-loader@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-6.0.0.tgz#041393ab5753f50ecf64262d624703046b8c7570" - integrity sha512-LCekn6qCbeXWlhESCxU1rAbZz33WzDG0lI7Ig0pYC1o5YxJWrkU9y3Y4tNi+jakQ7R6YhTR2D3ox6APxDtA0wA== +"@ngx-translate/http-loader@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz#905f38d8d13342621516635bf480ff9a4f73e9fc" + integrity sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA== dependencies: - tslib "^2.0.0" + tslib "^2.3.0" -"@ngxs/devtools-plugin@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@ngxs/devtools-plugin/-/devtools-plugin-3.7.2.tgz#995424e5faf48df55a1b54b9e1b36ce9c47c1d52" - integrity sha512-kRuOx1GPXHHZZAeQMm1J1msTZxjgiAUY4NR7bzaQPn+UwSY2OgGEsd8driMM5YSTF1hOjcFHinaLCM1vmu8FmQ== +"@ngxs/devtools-plugin@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@ngxs/devtools-plugin/-/devtools-plugin-3.7.3.tgz#0f8724ae15aabea4170b00edd632c594de16bd65" + integrity sha512-zkF2OyZKyXW8s/+WZZJgLbWpEguoDAA+EG9qWa/jlysRicYGDVCNZyoxZre4V9BkjwHvY+dQzcDHX4/Ng+Rf5w== dependencies: tslib "^1.9.0" -"@ngxs/store@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@ngxs/store/-/store-3.7.2.tgz#1088b0669adc382d36ca7ae8438c603e55879b42" - integrity sha512-1cnAjHOGCovfvhjtcAWBajrMXos97Un3c8ekKoS8FIHnq3aQOzY/ePspDRNi9kTcuBJ/r/xl097JC1ssEuNbyg== +"@ngxs/store@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@ngxs/store/-/store-3.7.3.tgz#74e2878d527fc12dace343ce43fd79fa1a2645af" + integrity sha512-JjATXC7FsxxQu2SaayP/iLe4O+5/RkRov3/J7WkaQmV6/JWFNkkdOwbEa6pDbh/po0JO7DHHMk3huIUNpDu67g== dependencies: tslib "^1.9.0" @@ -1437,14 +1683,14 @@ dependencies: infer-owner "^1.0.4" -"@npmcli/run-script@^1.8.2": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7" - integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== +"@npmcli/run-script@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-2.0.0.tgz#9949c0cab415b17aaac279646db4f027d6f1e743" + integrity sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig== dependencies: "@npmcli/node-gyp" "^1.0.2" "@npmcli/promise-spawn" "^1.3.2" - node-gyp "^7.1.0" + node-gyp "^8.2.0" read-package-json-fast "^2.0.1" "@scarf/scarf@^1.1.0": @@ -1452,13 +1698,13 @@ resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.1.tgz#d8b9f20037b3a37dbf8dcdc4b3b72f9285bfce35" integrity sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ== -"@schematics/angular@12.2.10": - version "12.2.10" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-12.2.10.tgz#c640be969ea7588da14ee5c4d58a6a2ce63b97e6" - integrity sha512-hjOWrC/RlZ97oYWO92f5VRu6LDzPHnowDcyGDGvI9wCrfipL4Y7Is6LgFAiVZxCHdRz71MCnES1IXSj5w6UuBA== +"@schematics/angular@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-13.2.3.tgz#600bbe21bff5b090aaee17ba726410ee1328b40b" + integrity sha512-jloooGC7eco9AKxlIMMqFRptJYzZ0jNRBStWOp2dCISg6rmOKqpxbsHLtYFQIT1PnlomSxtKDAgYGQMDi9zhXw== dependencies: - "@angular-devkit/core" "12.2.10" - "@angular-devkit/schematics" "12.2.10" + "@angular-devkit/core" "13.2.3" + "@angular-devkit/schematics" "13.2.3" jsonc-parser "3.0.0" "@tootallnate/once@1": @@ -1466,10 +1712,40 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" "@types/eslint-scope@^3.7.0": version "3.7.1" @@ -1492,12 +1768,30 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== -"@types/glob@^7.1.1": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" - integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.28" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" + integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-proxy@^1.17.8": + version "1.17.8" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" + integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== dependencies: - "@types/minimatch" "*" "@types/node" "*" "@types/jasmine@*": @@ -1517,22 +1811,22 @@ dependencies: "@types/jasmine" "*" -"@types/jquery@^3.3.29": - version "3.5.7" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.7.tgz#07614671f79c6ad70633bb2d8977f01cea242e27" - integrity sha512-Why+9t1KuqWtIqYKtbk6wgWbE1PjyXJOyGkpmTUh0RX5p4HL7nnRuBkjAO9P2r9tGQP6bLWxl77jRLew3V5xXg== +"@types/jquery@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.13.tgz#5482d3ee325d5862f77a91c09369ae0a5b082bf3" + integrity sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg== dependencies: "@types/sizzle" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== -"@types/minimatch@*": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== "@types/node@*", "@types/node@^16.10.9": version "16.10.9" @@ -1549,29 +1843,59 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU= +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "@types/selenium-webdriver@^3.0.0": version "3.0.19" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.19.tgz#28ecede76f15b13553b4e86074d4cf9a0bbe49c4" integrity sha512-OFUilxQg+rWL2FMxtmIgCkUDlJB6pskkpvmew7yeXfzzsOBb5rc+y2+DjHm+r3r1ZPPcJefK3DveNSYWGiy68g== +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*": + version "1.13.10" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" + integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/sizzle@*": version "2.3.3" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== -"@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" -"@types/webpack-sources@^0.1.5": - version "0.1.9" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.9.tgz#da69b06eb34f6432e6658acb5a6893c55d983920" - integrity sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new== +"@types/ws@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" + integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== dependencies: "@types/node" "*" - "@types/source-list-map" "*" - source-map "^0.6.1" "@webassemblyjs/ast@1.11.1": version "1.11.1" @@ -1709,12 +2033,12 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@yellowspot/ng-truncate@^1.4.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-1.7.0.tgz#36c0dd73f4f8cd2a35c881c97f31fe6c492d1598" - integrity sha512-UX1BqaGuY4H9hc+2u+OSR2jb4mzrtPW2tw+c1ca0er7PZJvWbNuXsKc1Hop2l8BMvddjEfRyCCe6I30zptC2Yg== +"@yellowspot/ng-truncate@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-2.0.0.tgz#e210fa537975ed454227b65befaa7866e7ef6f73" + integrity sha512-OzUPzcBLgC30gD1sqCgzOGDmZXlviJ51mr3C4HAEF70m9mSzFeCeiGpcJ8f7/SXSWkaMPs+Ar4xcFF4ZKtbFrA== dependencies: - tslib "^1.9.0" + tslib "^2.0.0" abab@^2.0.5: version "2.0.5" @@ -1780,6 +2104,15 @@ agentkeepalive@^4.1.3: depd "^1.1.2" humanize-ms "^1.2.1" +agentkeepalive@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.0.tgz#616ce94ccb41d1a39a45d203d8076fe98713062d" + integrity sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw== + dependencies: + debug "^4.1.0" + depd "^1.1.2" + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1788,34 +2121,36 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-formats@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.0.tgz#96eaf83e38d32108b66d82a9cb0cfa24886cdfeb" - integrity sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q== +ajv-formats@2.1.1, ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" -ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: +ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@8.6.2: - version "8.6.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571" - integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@8.9.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" + integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^6.1.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1835,10 +2170,15 @@ ajv@^8.0.0: require-from-string "^2.0.2" uri-js "^4.2.2" -alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" angular-bootstrap-md@^7.5.4: version "7.5.4" @@ -1854,24 +2194,19 @@ angular-router-loader@^0.8.5: dependencies: loader-utils "^1.0.2" -angularx-qrcode@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-11.0.0.tgz#03f1ccdd34c99fa1fa9f5666febb0b903e3c6881" - integrity sha512-qg6g288LO9daqBP5GCHewy9W0IMW7jDMEaAiklA1za0UhjCj6VH1Agydr4JVp7RMkw1LsLapFhWsVSYqrWaERA== +angularx-qrcode@^13.0.3: + version "13.0.3" + resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-13.0.3.tgz#6f632163027354391bcb0e5eaa7da473593a2fa5" + integrity sha512-KzalrRy2MczdApSq29k2TBOml6taQ7NqdgZDNgPSQBd5/27+l3xHkOkhhDOmGruSyCcT2KdB8qeOT/6K48c+xw== dependencies: - qrcode "1.4.2" - tslib "^2.0.0" + "@cordobo/qrcode" "1.5.0" + tslib "^2.3.0" ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1879,10 +2214,10 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-html@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== ansi-regex@^2.0.0: version "2.1.1" @@ -1894,22 +2229,22 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1923,14 +2258,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -1949,18 +2276,18 @@ app-root-path@^3.0.0: resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== +are-we-there-yet@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" + integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== dependencies: delegates "^1.0.0" - readable-stream "^2.0.6" + readable-stream "^3.6.0" argparse@^1.0.7: version "1.0.10" @@ -1977,21 +2304,6 @@ aria-query@^3.0.0: ast-types-flow "0.0.7" commander "^2.11.0" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2014,16 +2326,16 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -2041,21 +2353,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - ast-types-flow@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -2078,18 +2380,17 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.6.1: - version "9.8.8" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" - integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== +autoprefixer@^10.4.2: + version "10.4.2" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" + integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001109" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001297" + fraction.js "^4.1.2" normalize-range "^0.1.2" - num2fraction "^1.2.2" - picocolors "^0.2.1" - postcss "^7.0.32" - postcss-value-parser "^4.1.0" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" aws-sign2@~0.7.0: version "0.7.0" @@ -2108,10 +2409,10 @@ axobject-query@2.0.2: dependencies: ast-types-flow "0.0.7" -babel-loader@8.2.2: - version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" - integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== +babel-loader@8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== dependencies: find-cache-dir "^3.3.1" loader-utils "^1.4.0" @@ -2125,29 +2426,40 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== +babel-plugin-istanbul@6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" - integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.16.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" balanced-match@^1.0.0: version "1.0.2" @@ -2159,19 +2471,6 @@ base64-js@^1.2.0, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -2189,23 +2488,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -2268,22 +2555,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2291,7 +2562,7 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.6, browserslist@^4.17.3, browserslist@^4.6.4, browserslist@^4.9.1: +browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.9.1: version "4.17.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.4.tgz#72e2508af2a403aec0a49847ef31bd823c57ead4" integrity sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ== @@ -2302,6 +2573,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 node-releases "^2.0.0" picocolors "^1.0.0" +browserslist@^4.17.5, browserslist@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + browserstack@^1.5.1: version "1.6.1" resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" @@ -2347,30 +2629,7 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@15.2.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.2.0.tgz#73af75f77c58e72d8c630a7a2858cb18ef523389" - integrity sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cacache@^15.0.5, cacache@^15.2.0: +cacache@15.3.0, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: version "15.3.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== @@ -2394,21 +2653,6 @@ cacache@^15.0.5, cacache@^15.2.0: tar "^6.0.2" unique-filename "^1.1.1" -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2422,30 +2666,20 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001265: +caniuse-lite@^1.0.30001265: version "1.0.30001267" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001267.tgz#b1cf2937175afc0570e4615fc2d2f9069fa0ed30" integrity sha512-r1mjTzAuJ9W8cPBGbbus8E0SKcUP7gn03R14Wk8FlAlqhH9hroy9nLqmpuXlfKEw/oILW+FGz47ipXV2O7x8lg== -canonical-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" - integrity sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg== +caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001299: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== caseless@~0.12.0: version "0.12.0" @@ -2523,24 +2757,20 @@ chartjs-color@^2.1.0: optionalDependencies: fsevents "~2.3.2" -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" optionalDependencies: - fsevents "^1.2.7" + fsevents "~2.3.2" chownr@^2.0.0: version "2.0.0" @@ -2557,16 +2787,6 @@ circular-dependency-plugin@5.2.2: resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz#39e836079db1d3cf2f988dc48c5188a44058b600" integrity sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ== -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2598,15 +2818,6 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2667,14 +2878,6 @@ codelyzer@^6.0.1: tslib "^1.10.0" zone.js "~0.10.3" -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2699,15 +2902,15 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colord@^2.0.1, colord@^2.6: - version "2.8.0" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.8.0.tgz#64fb7aa03de7652b5a39eee50271a104c2783b12" - integrity sha512-kNkVV4KFta3TYQv0bzs4xNwLaeag261pxgzGQSh4cQ1rEhYjcTJfFRP0SDlbhLONg0eSoLzrDd79PosjbltufA== +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colorette@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +colorette@^2.0.10: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -2721,17 +2924,12 @@ commander@^2.11.0, commander@^2.12.1, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -2766,7 +2964,7 @@ connect-history-api-fallback@^1.6.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= @@ -2812,36 +3010,30 @@ copy-anything@^2.0.1: dependencies: is-what "^3.12.0" -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-webpack-plugin@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz#b71d21991599f61a4ee00ba79087b8ba279bbb59" - integrity sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw== +copy-webpack-plugin@10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.1.tgz#115a41f913070ac236a1b576066204cbf35341a1" + integrity sha512-nr81NhCAIpAWXGCK5thrKmfCQ6GDY0L5RN0U+BnIn/7Us55+UCex5ANNsNKmIVtDRnk0Ecf+/kzp9SUVrrBMLg== dependencies: - fast-glob "^3.2.5" - glob-parent "^6.0.0" - globby "^11.0.3" + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" normalize-path "^3.0.0" - p-limit "^3.1.0" - schema-utils "^3.0.0" + schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.15.0, core-js-compat@^3.16.2: - version "3.18.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.3.tgz#e0e7e87abc55efb547e7fa19169e45fa9df27a67" - integrity sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw== +core-js-compat@^3.20.2, core-js-compat@^3.21.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" + integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== dependencies: - browserslist "^4.17.3" + browserslist "^4.19.1" semver "7.0.0" -core-js@3.16.0: - version "3.16.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.0.tgz#1d46fb33720bc1fa7f90d20431f36a5540858986" - integrity sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g== +core-js@3.20.3: + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.3.tgz#c710d0a676e684522f3db4ee84e5e18a9d11d69a" + integrity sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag== core-js@^2.5.4: version "2.6.12" @@ -2869,15 +3061,16 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -critters@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.10.tgz#edd0e962fc5af6c4adb6dbf1a71bae2d3f917000" - integrity sha512-p5VKhP1803+f+0Jq5P03w1SbiHtpAKm+1EpJHkiPxQPq0Vu9QLZHviJ02GRrWi0dlcJqrmzMWInbwp4d22RsGw== +critters@0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" + integrity sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A== dependencies: chalk "^4.1.0" - css "^3.0.0" + css-select "^4.2.0" parse5 "^6.0.1" parse5-htmlparser2-tree-adapter "^6.0.1" + postcss "^8.3.7" pretty-bytes "^5.3.0" cross-spawn@^6.0.0: @@ -2891,37 +3084,33 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: - postcss "^7.0.5" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" -css-color-names@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67" - integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA== - -css-declaration-sorter@^6.0.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz#e9852e4cf940ba79f509d9425b137d1f94438dc2" - integrity sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA== +css-blank-pseudo@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" + integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== dependencies: - timsort "^0.3.0" + postcss-selector-parser "^6.0.9" -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== +css-has-pseudo@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" + integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" + postcss-selector-parser "^6.0.9" -css-loader@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.2.0.tgz#9663d9443841de957a3cb9bcea2eda65b3377071" - integrity sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g== +css-loader@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" + integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== dependencies: icss-utils "^5.1.0" postcss "^8.2.15" @@ -2932,43 +3121,21 @@ css-loader@6.2.0: postcss-value-parser "^4.1.0" semver "^7.3.5" -css-minimizer-webpack-plugin@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.0.2.tgz#8fadbdf10128cb40227bff275a4bb47412534245" - integrity sha512-B3I5e17RwvKPJwsxjjWcdgpU/zqylzK1bPVghcmpFHRL48DXiBgrtqz1BJsn68+t/zzaLp9kYAaEDvQ7GyanFQ== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - p-limit "^3.0.2" - postcss "^8.3.5" - schema-utils "^3.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-parse@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" - integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= - dependencies: - css "^2.0.0" +css-prefers-color-scheme@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" + integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== - dependencies: - postcss "^7.0.5" - -css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== +css-select@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" css-selector-tokenizer@^0.7.0, css-selector-tokenizer@^0.7.1: version "0.7.3" @@ -2978,29 +3145,11 @@ css-selector-tokenizer@^0.7.0, css-selector-tokenizer@^0.7.1: cssesc "^3.0.0" fastparse "^1.1.2" -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^5.0.0: +css-what@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== -css@^2.0.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - css@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" @@ -3017,78 +3166,16 @@ cssauron@^1.4.0: dependencies: through X.X.X -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== +cssdb@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-5.1.0.tgz#ec728d5f5c0811debd0820cbebda505d43003400" + integrity sha512-/vqjXhv1x9eGkE/zO6o8ZOI7dgdZbLVLUGyVRbPgk6YipXbW87YzUCcO+Jrmi5bwJlAH6oD+MNeZyRgXea1GZw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-default@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.4.tgz#359943bf00c5c8e05489f12dd25f3006f2c1cbd2" - integrity sha512-sPpQNDQBI3R/QsYxQvfB4mXeEcWuw0wGtKtmS5eg8wudyStYMgKOQT39G07EbW1LB56AOYrinRS9f0ig4Y3MhQ== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^2.0.1" - postcss-calc "^8.0.0" - postcss-colormin "^5.2.0" - postcss-convert-values "^5.0.1" - postcss-discard-comments "^5.0.1" - postcss-discard-duplicates "^5.0.1" - postcss-discard-empty "^5.0.1" - postcss-discard-overridden "^5.0.1" - postcss-merge-longhand "^5.0.2" - postcss-merge-rules "^5.0.2" - postcss-minify-font-values "^5.0.1" - postcss-minify-gradients "^5.0.2" - postcss-minify-params "^5.0.1" - postcss-minify-selectors "^5.1.0" - postcss-normalize-charset "^5.0.1" - postcss-normalize-display-values "^5.0.1" - postcss-normalize-positions "^5.0.1" - postcss-normalize-repeat-style "^5.0.1" - postcss-normalize-string "^5.0.1" - postcss-normalize-timing-functions "^5.0.1" - postcss-normalize-unicode "^5.0.1" - postcss-normalize-url "^5.0.2" - postcss-normalize-whitespace "^5.0.1" - postcss-ordered-values "^5.0.2" - postcss-reduce-initial "^5.0.1" - postcss-reduce-transforms "^5.0.1" - postcss-svgo "^5.0.2" - postcss-unique-selectors "^5.0.1" - -cssnano-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2" - integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ== - -cssnano@^5.0.6: - version "5.0.8" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.8.tgz#39ad166256980fcc64faa08c9bb18bb5789ecfa9" - integrity sha512-Lda7geZU0Yu+RZi2SGpjYuQz4HI4/1Y+BhdD0jL7NXAQ5larCzVn+PUGuZbDMYz904AXXCOgO5L1teSvgu7aFg== - dependencies: - cssnano-preset-default "^5.1.4" - is-resolvable "^1.1.0" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - damerau-levenshtein@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -3101,20 +3188,27 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.2, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" +debug@4.3.3, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3122,13 +3216,6 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3151,13 +3238,12 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" + execa "^5.0.0" defaults@^1.0.3: version "1.0.3" @@ -3178,28 +3264,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - del@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -3213,18 +3277,19 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" delayed-stream@~1.0.0: version "1.0.0" @@ -3319,12 +3384,19 @@ domhandler@^4.2.0: dependencies: domelementtype "^2.2.0" +domhandler@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== + dependencies: + domelementtype "^2.2.0" + domino@^2.1.2: version "2.1.6" resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.6.tgz#fe4ace4310526e5e7b9d12c7de01b7f485a57ffe" integrity sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ== -domutils@^2.6.0: +domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3351,10 +3423,10 @@ electron-to-chromium@^1.3.867: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.868.tgz#ed835023b57ecf0ba63dfe7d50e16b53758ab1da" integrity sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +electron-to-chromium@^1.4.17: + version "1.4.71" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" + integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== emoji-regex@^8.0.0: version "8.0.0" @@ -3366,6 +3438,11 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encode-utf8@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3385,10 +3462,10 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.8.0: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^5.8.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" + integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3408,7 +3485,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -errno@^0.1.1, errno@^0.1.3: +errno@^0.1.1: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== @@ -3422,10 +3499,10 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-module-lexer@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d" - integrity sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw== +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== es6-promise@^4.0.3: version "4.2.8" @@ -3439,112 +3516,124 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -esbuild-android-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9" - integrity sha512-elDJt+jNyoHFId0/dKsuVYUPke3EcquIyUwzJCH17a3ERglN3A9aMBI5zbz+xNZ+FbaDNdpn0RaJHCFLbZX+fA== - -esbuild-darwin-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.4.tgz#7a3e66c8e1271b650541b25eed65c84f3564a69d" - integrity sha512-zJQGyHRAdZUXlRzbN7W+7ykmEiGC+bq3Gc4GxKYjjWTgDRSEly98ym+vRNkDjXwXYD3gGzSwvH35+MiHAtWvLA== - -esbuild-darwin-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.4.tgz#793feca6032b2a57ef291eb9b2d33768d60a49d6" - integrity sha512-r8oYvAtqSGq8HNTZCAx4TdLE7jZiGhX9ooGi5AQAey37MA6XNaP8ZNlw9OCpcgpx3ryU2WctXwIqPzkHO7a8dg== - -esbuild-freebsd-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.4.tgz#294aec3c2cf4b41fb6900212fc9c33dd8fbbb4a2" - integrity sha512-u9DRGkn09EN8+lCh6z7FKle7awi17PJRBuAKdRNgSo5ZrH/3m+mYaJK2PR2URHMpAfXiwJX341z231tSdVe3Yw== - -esbuild-freebsd-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.4.tgz#09fe66c751c12f9b976976b1d83f3de594cb2787" - integrity sha512-q3B2k68Uf6gfjATjcK16DqxvjqRQkHL8aPoOfj4op+lSqegdXvBacB1d8jw8PxbWJ8JHpdTLdAVUYU80kotQXA== - -esbuild-linux-32@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.4.tgz#a9f0793d7bcc9cef4f4ffa4398c525877fba5839" - integrity sha512-UUYJPHSiKAO8KoN3Ls/iZtgDLZvK5HarES96aolDPWZnq9FLx4dIHM/x2z4Rxv9IYqQ/DxlPoE2Co1UPBIYYeA== - -esbuild-linux-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.4.tgz#c0d0b4c9d62e3bbf8bdf2cece37403aa6d60fc2e" - integrity sha512-+RnohAKiiUW4UHLGRkNR1AnENW1gCuDWuygEtd4jxTNPIoeC7lbXGor7rtgjj9AdUzFgOEvAXyNNX01kJ8NueQ== - -esbuild-linux-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.4.tgz#1292d97bfa64a08d12728f8a7837bf92776c779b" - integrity sha512-+A188cAdd6QuSRxMIwRrWLjgphQA0LDAQ/ECVlrPVJwnx+1i64NjDZivoqPYLOTkSPIKntiWwMhhf0U5/RrPHQ== - -esbuild-linux-arm@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.4.tgz#186cd9b8885ac132b9953a4a0afe668168debd10" - integrity sha512-BH5gKve4jglS7UPSsfwHSX79I5agC/lm4eKoRUEyo8lwQs89frQSRp2Xup+6SFQnxt3md5EsKcd2Dbkqeb3gPA== - -esbuild-linux-mips64le@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.4.tgz#42049bf72bc586817b4a51cc9e32148d13e5e807" - integrity sha512-0xkwtPaUkG5xMTFGaQPe1AadSe5QAiQuD4Gix1O9k5Xo/U8xGIkw9UFUTvfEUeu71vFb6ZgsIacfP1NLoFjWNw== - -esbuild-linux-ppc64le@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.4.tgz#adf1ce2ef2302757c4383887da6ac4dd25be9d4f" - integrity sha512-E1+oJPP7A+j23GPo3CEpBhGwG1bni4B8IbTA3/3rvzjURwUMZdcN3Fhrz24rnjzdLSHmULtOE4VsbT42h1Om4Q== - -esbuild-openbsd-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.4.tgz#1c8122101898c52a20c8786935cf3eb7a19b83b4" - integrity sha512-xEkI1o5HYxDzbv9jSox0EsDxpwraG09SRiKKv0W8pH6O3bt+zPSlnoK7+I7Q69tkvONkpIq5n2o+c55uq0X7cw== - -esbuild-sunos-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.4.tgz#4ec95faa14a60f295fe485bebffefff408739337" - integrity sha512-bjXUMcODMnB6hQicLBBmmnBl7OMDyVpFahKvHGXJfDChIi5udiIRKCmFUFIRn+AUAKVlfrofRKdyPC7kBsbvGQ== - -esbuild-wasm@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.13.4.tgz#9ae8ec5234cc651b2d74b23d4adac984055cff1c" - integrity sha512-2dN7njr9/2QzKLqbTEgXr73vDbSqffdJMv4EfaMQoy04cej0owbGHH5apPgED0wN9I5e7sBT0/Q81tVy3wQBlA== - -esbuild-windows-32@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.4.tgz#3182c380487b797b04d0ec2c80c2945666869080" - integrity sha512-z4CH07pfyVY0XF98TCsGmLxKCl0kyvshKDbdpTekW9f2d+dJqn5mmoUyWhpSVJ0SfYWJg86FoD9nMbbaMVyGdg== - -esbuild-windows-64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.4.tgz#b9e995f92d81f433a04f33611e603e82f9232e69" - integrity sha512-uVL11vORRPjocGLYam67rwFLd0LvkrHEs+JG+1oJN4UD9MQmNGZPa4gBHo6hDpF+kqRJ9kXgQSeDqUyRy0tj/Q== - -esbuild-windows-arm64@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.4.tgz#fb239532f07b764d158f4cc787178ef4c6fadb5c" - integrity sha512-vA6GLvptgftRcDcWngD5cMlL4f4LbL8JjU2UMT9yJ0MT5ra6hdZNFWnOeOoEtY4GtJ6OjZ0i+81sTqhAB0fMkg== - -esbuild@0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.4.tgz#ce2deb56c4fb360938311cbfc67f8e467bb6841b" - integrity sha512-wMA5eUwpavTBiNl+It6j8OQuKVh69l6z4DKDLzoTIqC+gChnPpcmqdA8WNHptUHRnfyML+mKEQPlW7Mybj8gHg== +esbuild-android-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.14.tgz#3705f32f209deeb11c275af47c298c8783dd5f0c" + integrity sha512-be/Uw6DdpQiPfula1J4bdmA+wtZ6T3BRCZsDMFB5X+k0Gp8TIh9UvmAcqvKNnbRAafSaXG3jPCeXxDKqnc8hFQ== + +esbuild-darwin-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.14.tgz#c07e4eae6d938300a2d330ea82494c55bcea84e5" + integrity sha512-BEexYmjWafcISK8cT6O98E3TfcLuZL8DKuubry6G54n2+bD4GkoRD6HYUOnCkfl2p7jodA+s4369IjSFSWjtHg== + +esbuild-darwin-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.14.tgz#a8631e13a51a6f784fb0906e2a64c6ab53988755" + integrity sha512-tnBKm41pDOB1GtZ8q/w26gZlLLRzVmP8fdsduYjvM+yFD7E2DLG4KbPAqFMWm4Md9B+DitBglP57FY7AznxbTg== + +esbuild-freebsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.14.tgz#c280c2b944746b27ee6c6487c2691865c90bed2e" + integrity sha512-Q9Rx6sgArOHalQtNwAaIzJ6dnQ8A+I7f/RsQsdkS3JrdzmnlFo8JEVofTmwVQLoIop7OKUqIVOGP4PoQcwfVMA== + +esbuild-freebsd-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.14.tgz#aa4e21276efcf20e5ab2487e91ca1d789573189b" + integrity sha512-TJvq0OpLM7BkTczlyPIphcvnwrQwQDG1HqxzoYePWn26SMUAlt6wrLnEvxdbXAvNvDLVzG83kA+JimjK7aRNBA== + +esbuild-linux-32@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.14.tgz#3db4d929239203ce38a9060d5419ac6a6d28846c" + integrity sha512-h/CrK9Baimt5VRbu8gqibWV7e1P9l+mkanQgyOgv0Ng3jHT1NVFC9e6rb1zbDdaJVmuhWX5xVliUA5bDDCcJeg== + +esbuild-linux-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.14.tgz#f880026254c1f565a7a10fdebb7cff9b083a127d" + integrity sha512-IC+wAiIg/egp5OhQp4W44D9PcBOH1b621iRn1OXmlLzij9a/6BGr9NMIL4CRwz4j2kp3WNZu5sT473tYdynOuQ== + +esbuild-linux-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.14.tgz#a34bc3076e50b109c3b8c8bad9c146e35942322b" + integrity sha512-6QVul3RI4M5/VxVIRF/I5F+7BaxzR3DfNGoqEVSCZqUbgzHExPn+LXr5ly1C7af2Kw4AHpo+wDqx8A4ziP9avw== + +esbuild-linux-arm@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.14.tgz#231ffd12fef69ee06365d4c94b69850e4830e927" + integrity sha512-gxpOaHOPwp7zSmcKYsHrtxabScMqaTzfSQioAMUaB047YiMuDBzqVcKBG8OuESrYkGrL9DDljXr/mQNg7pbdaQ== + +esbuild-linux-mips64le@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.14.tgz#bd00570e3a30422224b732c7a5f262146c357403" + integrity sha512-4Jl5/+xoINKbA4cesH3f4R+q0vltAztZ6Jm8YycS8lNhN1pgZJBDxWfI6HUMIAdkKlIpR1PIkA9aXQgZ8sxFAg== + +esbuild-linux-ppc64le@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.14.tgz#430609413fd9e04d9def4e3f06726b031b23d825" + integrity sha512-BitW37GxeebKxqYNl4SVuSdnIJAzH830Lr6Mkq3pBHXtzQay0vK+IeOR/Ele1GtNVJ+/f8wYM53tcThkv5SC5w== + +esbuild-linux-s390x@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.14.tgz#2f0d8cbfe53cf3cb97f6372549a41a8051dbd689" + integrity sha512-vLj6p76HOZG3wfuTr5MyO3qW5iu8YdhUNxuY+tx846rPo7GcKtYSPMusQjeVEfZlJpSYoR+yrNBBxq+qVF9zrw== + +esbuild-netbsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.14.tgz#3e44de35e1add7e9582f3c0d2558d86aafbc813b" + integrity sha512-fn8looXPQhpVqUyCBWUuPjesH+yGIyfbIQrLKG05rr1Kgm3rZD/gaYrd3Wpmf5syVZx70pKZPvdHp8OTA+y7cQ== + +esbuild-openbsd-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.14.tgz#04710ef1d01cd9f15d54f50d20b5a3778f8306a2" + integrity sha512-HdAnJ399pPff3SKbd8g+P4o5znseni5u5n5rJ6Z7ouqOdgbOwHe2ofZbMow17WMdNtz1IyOZk2Wo9Ve6/lZ4Rg== + +esbuild-sunos-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.14.tgz#8e583dd92c5c7ac4303ddc37f588e44211e04e19" + integrity sha512-bmDHa99ulsGnYlh/xjBEfxoGuC8CEG5OWvlgD+pF7bKKiVTbtxqVCvOGEZeoDXB+ja6AvHIbPxrEE32J+m5nqQ== + +esbuild-wasm@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.14.14.tgz#d4c8d5fc405939a2234a31abf00967dfd1da1caa" + integrity sha512-qTjK4MWnYtQHCMGg2qDUqeFYXfVvYq5qJkQTIsOV4VZCknoYePVaDTG9ygEB9Ct0kc0DWs7IrS6Ja+GjY62Kzw== + +esbuild-windows-32@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.14.tgz#6d293ddfb71229f21cc13d85d5d2f43e8131693b" + integrity sha512-6tVooQcxJCNenPp5GHZBs/RLu31q4B+BuF4MEoRxswT+Eq2JGF0ZWDRQwNKB8QVIo3t6Svc5wNGez+CwKNQjBg== + +esbuild-windows-64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.14.tgz#08a36844b69542f8ec1cb33a5ddcea02b9d0b2e8" + integrity sha512-kl3BdPXh0/RD/dad41dtzj2itMUR4C6nQbXQCyYHHo4zoUoeIXhpCrSl7BAW1nv5EFL8stT1V+TQVXGZca5A2A== + +esbuild-windows-arm64@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.14.tgz#ca747ce4066d5b8a79dbe48fe6ecd92d202e5366" + integrity sha512-dCm1wTOm6HIisLanmybvRKvaXZZo4yEVrHh1dY0v582GThXJOzuXGja1HIQgV09RpSHYRL3m4KoUBL00l6SWEg== + +esbuild@0.14.14: + version "0.14.14" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.14.tgz#3b99f20d628013c3e2ae90e67687e03f1d6eb071" + integrity sha512-aiK4ddv+uui0k52OqSHu4xxu+SzOim7Rlz4i25pMEiC8rlnGU0HJ9r+ZMfdWL5bzifg+nhnn7x4NSWTeehYblg== optionalDependencies: - esbuild-android-arm64 "0.13.4" - esbuild-darwin-64 "0.13.4" - esbuild-darwin-arm64 "0.13.4" - esbuild-freebsd-64 "0.13.4" - esbuild-freebsd-arm64 "0.13.4" - esbuild-linux-32 "0.13.4" - esbuild-linux-64 "0.13.4" - esbuild-linux-arm "0.13.4" - esbuild-linux-arm64 "0.13.4" - esbuild-linux-mips64le "0.13.4" - esbuild-linux-ppc64le "0.13.4" - esbuild-openbsd-64 "0.13.4" - esbuild-sunos-64 "0.13.4" - esbuild-windows-32 "0.13.4" - esbuild-windows-64 "0.13.4" - esbuild-windows-arm64 "0.13.4" + esbuild-android-arm64 "0.14.14" + esbuild-darwin-64 "0.14.14" + esbuild-darwin-arm64 "0.14.14" + esbuild-freebsd-64 "0.14.14" + esbuild-freebsd-arm64 "0.14.14" + esbuild-linux-32 "0.14.14" + esbuild-linux-64 "0.14.14" + esbuild-linux-arm "0.14.14" + esbuild-linux-arm64 "0.14.14" + esbuild-linux-mips64le "0.14.14" + esbuild-linux-ppc64le "0.14.14" + esbuild-linux-s390x "0.14.14" + esbuild-netbsd-64 "0.14.14" + esbuild-openbsd-64 "0.14.14" + esbuild-sunos-64 "0.14.14" + esbuild-windows-32 "0.14.14" + esbuild-windows-64 "0.14.14" + esbuild-windows-arm64 "0.14.14" escalade@^3.1.1: version "3.1.1" @@ -3641,24 +3730,26 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -3695,21 +3786,6 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3724,20 +3800,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3748,15 +3810,15 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.5: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3795,21 +3857,6 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3830,15 +3877,6 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-cache-dir@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" @@ -3855,7 +3893,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -3863,21 +3901,11 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - follow-redirects@^1.0.0: version "1.14.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3911,12 +3939,10 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" +fraction.js@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" + integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== fresh@0.5.2: version "0.5.2" @@ -3940,14 +3966,6 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -3969,19 +3987,20 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= +gauge@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.1.tgz#82984bc08c90357d60b0a46c03a296beb1affec4" + integrity sha512-zJ4jePUHR8cceduZ53b6temRalyGpkC2Kc2r3ecNphmL+uWNoJ3YcOcUjpbG6WwoE/Ef6/+aEZz63neI2WIa1Q== dependencies: - aproba "^1.0.3" + ansi-regex "^5.0.1" + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" + has-unicode "^2.0.1" signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -3993,7 +4012,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -4007,6 +4026,11 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.1" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4014,10 +4038,10 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== getpass@^0.1.1: version "0.1.7" @@ -4026,14 +4050,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -4041,7 +4057,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.0: +glob-parent@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -4053,19 +4069,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.2.0, glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -4082,18 +4086,30 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globby@^11.0.3: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== +globby@^11.0.1: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -4106,22 +4122,16 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -4169,42 +4179,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-unicode@^2.0.0: +has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -4243,10 +4222,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== +html-entities@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" + integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== http-cache-semantics@^4.1.0: version "4.1.0" @@ -4304,17 +4283,27 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +http-proxy-middleware@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" + integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" -http-proxy@^1.17.0: +http-proxy@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== @@ -4348,6 +4337,11 @@ https-proxy-agent@^2.2.1: agent-base "^4.3.0" debug "^3.1.0" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -4362,7 +4356,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.2: +iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -4379,17 +4373,17 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== +ignore-walk@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-4.0.1.tgz#fc840e8346cf88a3a9380c5b17933cd8f4d39fa3" + integrity sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw== dependencies: minimatch "^3.0.4" -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.9, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== image-size@~0.5.0: version "0.5.5" @@ -4406,6 +4400,11 @@ immer@^9.0.6: resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -4414,14 +4413,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4432,11 +4423,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -4470,10 +4456,10 @@ ini@^1.3.4: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.2.tgz#65b204d2cd7fb63400edd925dfe428bafd422e3d" - integrity sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q== +inquirer@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" + integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -4483,59 +4469,32 @@ inquirer@8.1.2: figures "^3.0.0" lodash "^4.17.21" mute-stream "0.0.8" - ora "^5.3.0" + ora "^5.4.1" run-async "^2.4.0" rxjs "^7.2.0" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: +ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== is-arguments@^1.0.4: version "1.1.1" @@ -4550,13 +4509,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -4564,11 +4516,6 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-core-module@^2.2.0: version "2.7.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" @@ -4576,19 +4523,12 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: - kind-of "^6.0.0" + has "^1.0.3" is-date-object@^1.0.1: version "1.0.5" @@ -4597,42 +4537,12 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= @@ -4654,14 +4564,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4678,13 +4581,6 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4695,7 +4591,7 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= -is-path-cwd@^2.0.0: +is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== @@ -4707,13 +4603,6 @@ is-path-in-cwd@^1.0.0: dependencies: is-path-inside "^1.0.0" -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -4721,14 +4610,17 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -4743,16 +4635,16 @@ is-regex@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -4768,16 +4660,6 @@ is-what@^3.12.0: resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -4785,29 +4667,17 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: +isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= @@ -4817,19 +4687,20 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz#36786d4d82aad2ea5911007e255e2da6b5f80d86" - integrity sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g== +istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== +istanbul-lib-instrument@^5.0.4: + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== dependencies: - "@babel/core" "^7.7.5" + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" + istanbul-lib-coverage "^3.2.0" semver "^6.3.0" jasmine-core@~2.8.0: @@ -4851,7 +4722,7 @@ jasminewd2@^2.1.0: resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" integrity sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4= -jest-worker@^27.0.2, jest-worker@^27.0.6: +jest-worker@^27.0.6: version "27.2.5" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.2.5.tgz#ed42865661959488aa020e8a325df010597c36d4" integrity sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw== @@ -4923,11 +4794,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -4979,31 +4845,7 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -5013,6 +4855,11 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +klona@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -5020,21 +4867,21 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -less-loader@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-10.0.1.tgz#c05aaba68d00400820275f21c2ad87cb9fa9923f" - integrity sha512-Crln//HpW9M5CbtdfWm3IO66Cvx1WhZQvNybXgfB2dD/6Sav9ppw+IWqs/FQKPBFO4B6X0X28Z0WNznshgwUzA== +less-loader@10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-10.2.0.tgz#97286d8797dc3dc05b1d16b0ecec5f968bdd4e32" + integrity sha512-AV5KHWvCezW27GT90WATaDnfXBv99llDbtaj4bshq6DvAihMdNjaPDcUMa6EXKLRF+P2opFenJp89BXg91XLYg== dependencies: klona "^2.0.4" -less@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/less/-/less-4.1.1.tgz#15bf253a9939791dc690888c3ff424f3e6c7edba" - integrity sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw== +less@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0" + integrity sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA== dependencies: copy-anything "^2.0.1" parse-node-version "^1.0.1" - tslib "^1.10.0" + tslib "^2.3.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" @@ -5044,13 +4891,12 @@ less@4.1.1: needle "^2.5.2" source-map "~0.6.0" -license-webpack-plugin@2.3.20: - version "2.3.20" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz#f51fb674ca31519dbedbe1c7aabc036e5a7f2858" - integrity sha512-AHVueg9clOKACSHkhmEI+PCC9x8+qsQVuKECZD3ETxETK5h/PCv5/MUzyG1gm8OMcip/s1tcNxqo9Qb7WhjGsg== +license-webpack-plugin@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-4.0.1.tgz#957930fa595f5b65aa0b21bfd2c19644486f3d9f" + integrity sha512-SQum9mg3BgnY5BK+2KYl4W7pk9b26Q8tW2lTsO6tidD0/Ds9ksdXvp3ip2s9LqDjj5gtBMyWRfOPZptWj4PfCg== dependencies: - "@types/webpack-sources" "^0.1.5" - webpack-sources "^1.2.0" + webpack-sources "^3.0.0" lie@~3.3.0: version "3.3.0" @@ -5059,11 +4905,6 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -lilconfig@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd" - integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg== - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -5074,14 +4915,10 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== -loader-utils@2.0.0, loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" +loader-utils@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" + integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== loader-utils@^1.0.2, loader-utils@^1.4.0: version "1.4.0" @@ -5092,6 +4929,15 @@ loader-utils@^1.0.2, loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5112,17 +4958,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.21: +lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5135,11 +4971,6 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -loglevel@^1.6.8: - version "1.7.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5147,6 +4978,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.3.1.tgz#7702e80694ec2bf19865567a469f2b081fcf53f5" + integrity sha512-nX1x4qUrKqwbIAhv4s9et4FIUVzNOpeY07bsjGUy8gwJrXH/wScImSQqXErmo/b2jZY2r0mohbLA9zVj7u1cNw== + luxon@^1.10.0, luxon@^1.21.3: version "1.28.0" resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" @@ -5179,7 +5015,29 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^9.0.1: +make-fetch-happen@^10.0.1: + version "10.0.3" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.0.3.tgz#94bbe675cf62a811dbab59668052388a078beaf2" + integrity sha512-CzarPHynPpHjhF5in/YapnO44rSZeYX5VCMfdXa99+gLwpbfFLh20CWa6dP/taV9Net9PWJwXNKtp/4ZTCQnag== + dependencies: + agentkeepalive "^4.2.0" + cacache "^15.3.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.3.1" + minipass "^3.1.6" + minipass-collect "^1.0.2" + minipass-fetch "^1.4.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^6.1.1" + ssri "^8.0.1" + +make-fetch-happen@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== @@ -5201,29 +5059,12 @@ make-fetch-happen@^9.0.1: socks-proxy-agent "^6.0.0" ssri "^8.0.0" -map-age-cleaner@^0.1.1, map-age-cleaner@^0.1.3: +map-age-cleaner@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== dependencies: - p-defer "^1.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + p-defer "^1.0.0" media-typer@0.3.0: version "0.3.0" @@ -5239,14 +5080,6 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -mem@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" - memfs@^3.2.2: version "3.3.0" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" @@ -5254,32 +5087,24 @@ memfs@^3.2.2: dependencies: fs-monkey "1.0.3" -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= +memfs@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" + integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" + fs-monkey "1.0.3" merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5289,26 +5114,7 @@ methods@^1.1.1, methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -5333,27 +5139,17 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" - integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== - -mini-css-extract-plugin@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.2.1.tgz#a44bbfc8ede9211f31474b91c4e8863bf52dd294" - integrity sha512-A0GBXpz8WIPgh2HfASJ0EeY8grd2dGxmC4R8uTujFJXZY7zFy0nvYSYW6SKCLKlz7y45BdHONfaxZQMIZpeF/w== +mini-css-extract-plugin@2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== dependencies: - schema-utils "^3.1.0" + schema-utils "^4.0.0" minimalistic-assert@^1.0.0: version "1.0.1" @@ -5379,7 +5175,7 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: +minipass-fetch@^1.3.2, minipass-fetch@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== @@ -5426,7 +5222,14 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: dependencies: yallist "^4.0.0" -minizlib@^2.0.0, minizlib@^2.1.1: +minipass@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -5434,14 +5237,6 @@ minizlib@^2.0.0, minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5449,7 +5244,7 @@ mkdirp@^0.5.1, mkdirp@^0.5.5: dependencies: minimist "^1.2.5" -mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -5504,37 +5299,15 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nanocolors@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" - integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== - -nanoid@^3.1.23, nanoid@^3.1.28: +nanoid@^3.1.28: version "3.1.30" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" +nanoid@^3.1.30, nanoid@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.0.tgz#5906f776fd886c66c24f3653e0c46fcb1d4ad6b0" + integrity sha512-JzxqqT5u/x+/KOFSd7JP15DOo9nOoHpx6DYatqIHUW2+flybkm+mdcraotSQR5WcnZr+qhGVh8Ted0KdfSMxlg== needle@^2.5.2: version "2.9.1" @@ -5550,6 +5323,11 @@ negotiator@0.6.2, negotiator@^0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -5583,10 +5361,10 @@ ngx-moment@^3.0.1: dependencies: tslib "^1.9.0" -ngx-order-pipe@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.1.1.tgz#981b7ff2fac20bc88a1e9922527e2e61da0ff4f1" - integrity sha512-yBaG0uYWsXBlmAuCYvBedKxl3kRUSXNXsMrD0m2E4tBA8I9TJSomucp5SHFlyfMQK8V6pjRGdz17Sjb9YwLhSg== +ngx-order-pipe@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.2.0.tgz#14ab50dfe0a679e5216138ff9a0820a83173a4fe" + integrity sha512-fym4A3j0XMqETskCm0tHUHQWCgB1p1MrIstFA3jCClJqNU9KjtQh/AE4C7srUkz9U3HIBIAN9D3ty2L9l/jvmA== dependencies: tslib "^2.0.0" @@ -5615,30 +5393,30 @@ node-addon-api@^3.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-forge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" + integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== node-gyp-build@^4.2.2: version "4.3.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-gyp@^7.1.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" - integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== +node-gyp@^8.2.0: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== dependencies: env-paths "^2.2.0" glob "^7.1.4" - graceful-fs "^4.2.3" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" nopt "^5.0.0" - npmlog "^4.1.2" - request "^2.88.2" + npmlog "^6.0.0" rimraf "^3.0.2" - semver "^7.3.2" - tar "^6.0.2" + semver "^7.3.5" + tar "^6.1.2" which "^2.0.2" node-releases@^2.0.0: @@ -5646,6 +5424,11 @@ node-releases@^2.0.0: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400" integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA== +node-releases@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -5653,13 +5436,6 @@ nopt@^5.0.0: dependencies: abbrev "1" -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5670,11 +5446,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -5694,7 +5465,7 @@ npm-normalize-package-bin@^1.0.1: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2: +npm-package-arg@8.1.5, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: version "8.1.5" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== @@ -5703,13 +5474,13 @@ npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-packa semver "^7.3.4" validate-npm-package-name "^3.0.0" -npm-packlist@^2.1.4: - version "2.2.2" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8" - integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg== +npm-packlist@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-3.0.0.tgz#0370df5cfc2fcc8f79b8f42b37798dd9ee32c2a9" + integrity sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ== dependencies: glob "^7.1.6" - ignore-walk "^3.0.3" + ignore-walk "^4.0.1" npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" @@ -5723,17 +5494,17 @@ npm-pick-manifest@6.1.1, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.1: npm-package-arg "^8.1.2" semver "^7.3.4" -npm-registry-fetch@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" - integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== +npm-registry-fetch@^12.0.0: + version "12.0.2" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz#ae583bb3c902a60dae43675b5e33b5b1f6159f1e" + integrity sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA== dependencies: - make-fetch-happen "^9.0.1" - minipass "^3.1.3" - minipass-fetch "^1.3.0" + make-fetch-happen "^10.0.1" + minipass "^3.1.6" + minipass-fetch "^1.4.1" minipass-json-stream "^1.0.1" - minizlib "^2.0.0" - npm-package-arg "^8.0.0" + minizlib "^2.1.2" + npm-package-arg "^8.1.5" npm-run-path@^2.0.0: version "2.0.2" @@ -5742,28 +5513,30 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17" + integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.0" + set-blocking "^2.0.0" -nth-check@^2.0.0: +nth-check@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== dependencies: boolbase "^1.0.0" -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -5774,20 +5547,11 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0: +object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.9.0: version "1.11.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" @@ -5806,13 +5570,6 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - object.assign@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -5823,13 +5580,6 @@ object.assign@^4.1.0: has-symbols "^1.0.1" object-keys "^1.1.1" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -5854,17 +5604,17 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" -open@8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/open/-/open-8.2.1.tgz#82de42da0ccbf429bc12d099dad2e0975e14e8af" - integrity sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ== +open@8.4.0, open@^8.0.9: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -5875,14 +5625,7 @@ opencollective-postinstall@^2.0.2: resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -ora@5.4.1, ora@^5.3.0: +ora@5.4.1, ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== @@ -5940,7 +5683,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -5961,11 +5704,6 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -5973,27 +5711,28 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== +p-retry@^4.5.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== dependencies: - retry "^0.12.0" + "@types/retry" "^0.12.0" + retry "^0.13.1" p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@11.3.5: - version "11.3.5" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" - integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== +pacote@12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.3.tgz#b6f25868deb810e7e0ddf001be88da2bcaca57c7" + integrity sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow== dependencies: "@npmcli/git" "^2.1.0" "@npmcli/installed-package-contents" "^1.0.6" "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^1.8.2" + "@npmcli/run-script" "^2.0.0" cacache "^15.0.5" chownr "^2.0.0" fs-minipass "^2.1.0" @@ -6001,9 +5740,9 @@ pacote@11.3.5: minipass "^3.1.3" mkdirp "^1.0.3" npm-package-arg "^8.0.1" - npm-packlist "^2.1.4" + npm-packlist "^3.0.0" npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" + npm-registry-fetch "^12.0.0" promise-retry "^2.0.1" read-package-json-fast "^2.0.1" rimraf "^3.0.2" @@ -6074,16 +5813,6 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6099,7 +5828,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -6109,7 +5838,12 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.6: +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -6166,10 +5900,10 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -piscina@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/piscina/-/piscina-3.1.0.tgz#2333636865b6cb69c5a370bbc499a98cabcf3e04" - integrity sha512-KTW4sjsCD34MHrUbx9eAAbuUSpVj407hQSgk/6Epkg0pbRBmv4a3UX7Sr8wxm9xYqQLnsN4mFOjqGDzHAdgKQg== +piscina@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/piscina/-/piscina-3.2.0.tgz#f5a1dde0c05567775690cccefe59d9223924d154" + integrity sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA== dependencies: eventemitter-asyncresource "^1.0.0" hdr-histogram-js "^2.0.1" @@ -6177,13 +5911,6 @@ piscina@3.1.0: optionalDependencies: nice-napi "^1.0.2" -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -6191,17 +5918,17 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pngjs@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== popper.js@^1.14.3: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== -portfinder@^1.0.26: +portfinder@^1.0.28: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== @@ -6210,188 +5937,105 @@ portfinder@^1.0.26: debug "^3.1.1" mkdirp "^0.5.5" -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== +postcss-attribute-case-insensitive@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz#39cbf6babf3ded1e4abf37d09d6eda21c644105c" + integrity sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ== dependencies: - postcss "^7.0.2" postcss-selector-parser "^6.0.2" -postcss-calc@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" - integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== +postcss-color-functional-notation@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz#f59ccaeb4ee78f1b32987d43df146109cc743073" + integrity sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ== dependencies: - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" + postcss-value-parser "^4.2.0" -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== +postcss-color-hex-alpha@^8.0.2: + version "8.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52" + integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw== dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" -postcss-color-gray@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== +postcss-color-rebeccapurple@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz#5d397039424a58a9ca628762eb0b88a61a66e079" + integrity sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" +postcss-custom-media@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz#1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1" + integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g== -postcss-color-mod-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== +postcss-custom-properties@^12.1.2: + version "12.1.4" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.4.tgz#e3d8a8000f28094453b836dff5132385f2862285" + integrity sha512-i6AytuTCoDLJkWN/MtAIGriJz3j7UX6bV7Z5t+KgFz+dwZS15/mlTJY1S0kRizlk6ba0V8u8hN50Fz5Nm7tdZw== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== +postcss-custom-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz#022839e41fbf71c47ae6e316cb0e6213012df5ef" + integrity sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q== dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-selector-parser "^6.0.4" -postcss-colormin@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.0.tgz#2b620b88c0ff19683f3349f4cf9e24ebdafb2c88" - integrity sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw== +postcss-dir-pseudo-class@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c" + integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw== dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-selector-parser "^6.0.9" -postcss-convert-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz#4ec19d6016534e30e3102fdf414e753398645232" - integrity sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg== +postcss-double-position-gradients@^3.0.4: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.0.tgz#a8614fb3a2a4b8877bffb8961b770e00322bbad1" + integrity sha512-oz73I08yMN3oxjj0s8mED1rG+uOYoK3H8N9RjQofyg52KBRNmePJKg3fVwTpL2U5ZFbCzXoZBsUD/CvZdlqE4Q== dependencies: - postcss-value-parser "^4.1.0" + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== +postcss-env-function@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.5.tgz#b9614d50abd91e4c88a114644a9766880dabe393" + integrity sha512-gPUJc71ji9XKyl0WSzAalBeEA/89kU+XpffpPxSaaaZ1c48OL36r1Ep5R6+9XAPkIiDlSvVAwP4io12q/vTcvA== dependencies: - postcss "^7.0.14" + postcss-value-parser "^4.2.0" -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== +postcss-focus-visible@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" + integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" + postcss-selector-parser "^6.0.9" -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== +postcss-focus-within@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" + integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" + postcss-selector-parser "^6.0.9" -postcss-dir-pseudo-class@^5.0.0: +postcss-font-variant@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-discard-comments@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" - integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== - -postcss-discard-duplicates@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" - integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== - -postcss-discard-empty@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" - integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== - -postcss-discard-overridden@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz#454b41f707300b98109a75005ca4ab0ff2743ac6" - integrity sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q== - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" - integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== - dependencies: - postcss "^7.0.2" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" + integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" +postcss-gap-properties@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60" + integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ== -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== +postcss-image-set-function@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9" + integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A== dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + postcss-value-parser "^4.2.0" postcss-import@14.0.2: version "14.0.2" @@ -6402,99 +6046,37 @@ postcss-import@14.0.2: read-cache "^1.0.0" resolve "^1.1.7" -postcss-initial@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" - integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== - dependencies: - postcss "^7.0.2" +postcss-initial@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42" + integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== +postcss-lab-function@^4.0.3: + version "4.1.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.1.1.tgz#8b37dfcb9ca4ff82bbe7192c7ba3cc2bccbc0ef1" + integrity sha512-j3Z0WQCimY2tMle++YcmygnnVbt6XdnrCV1FO2IpzaCSmtTF2oO8h4ZYUA1Q+QHYroIiaWPvNHt9uBR4riCksQ== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" -postcss-loader@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.1.1.tgz#58dd0a3accd9bc87cc52eff75244db578d11301a" - integrity sha512-lBmJMvRh1D40dqpWKr9Rpygwxn8M74U9uaCSeYGNKLGInbk9mXBt1ultHf2dH9Ghk6Ue4UXlXWwGMH9QdUJ5ug== +postcss-loader@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" + integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== dependencies: cosmiconfig "^7.0.0" - klona "^2.0.4" + klona "^2.0.5" semver "^7.3.5" -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== - dependencies: - postcss "^7.0.2" - -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== - dependencies: - postcss "^7.0.2" - -postcss-merge-longhand@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz#277ada51d9a7958e8ef8cf263103c9384b322a41" - integrity sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw== - dependencies: - css-color-names "^1.0.1" - postcss-value-parser "^4.1.0" - stylehacks "^5.0.1" - -postcss-merge-rules@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz#d6e4d65018badbdb7dcc789c4f39b941305d410a" - integrity sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^2.0.1" - postcss-selector-parser "^6.0.5" - vendors "^1.0.3" - -postcss-minify-font-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz#a90cefbfdaa075bd3dbaa1b33588bb4dc268addf" - integrity sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-minify-gradients@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.2.tgz#7c175c108f06a5629925d698b3c4cf7bd3864ee5" - integrity sha512-7Do9JP+wqSD6Prittitt2zDLrfzP9pqKs2EcLX7HJYxsxCOwrrcLt4x/ctQTsiOw+/8HYotAoqNkrzItL19SdQ== - dependencies: - colord "^2.6" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-minify-params@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz#371153ba164b9d8562842fdcd929c98abd9e5b6c" - integrity sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw== - dependencies: - alphanum-sort "^1.0.2" - browserslist "^4.16.0" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - uniqs "^2.0.0" +postcss-logical@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" + integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== -postcss-minify-selectors@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz#4385c845d3979ff160291774523ffa54eafd5a54" - integrity sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og== - dependencies: - alphanum-sort "^1.0.2" - postcss-selector-parser "^6.0.5" +postcss-media-minmax@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" + integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== postcss-modules-extract-imports@^3.0.0: version "3.0.0" @@ -6524,210 +6106,89 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== - dependencies: - postcss "^7.0.2" - -postcss-normalize-charset@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" - integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== - -postcss-normalize-display-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz#62650b965981a955dffee83363453db82f6ad1fd" - integrity sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-positions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz#868f6af1795fdfa86fbbe960dceb47e5f9492fe5" - integrity sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-normalize-repeat-style@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz#cbc0de1383b57f5bb61ddd6a84653b5e8665b2b5" - integrity sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-string@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz#d9eafaa4df78c7a3b973ae346ef0e47c554985b0" - integrity sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-normalize-timing-functions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz#8ee41103b9130429c6cbba736932b75c5e2cb08c" - integrity sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-unicode@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz#82d672d648a411814aa5bf3ae565379ccd9f5e37" - integrity sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA== - dependencies: - browserslist "^4.16.0" - postcss-value-parser "^4.1.0" - -postcss-normalize-url@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz#ddcdfb7cede1270740cf3e4dfc6008bd96abc763" - integrity sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ== - dependencies: - is-absolute-url "^3.0.3" - normalize-url "^6.0.1" - postcss-value-parser "^4.1.0" - -postcss-normalize-whitespace@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz#b0b40b5bcac83585ff07ead2daf2dcfbeeef8e9a" - integrity sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-ordered-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz#1f351426977be00e0f765b3164ad753dac8ed044" - integrity sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== - dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-initial@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz#9d6369865b0f6f6f6b165a0ef5dc1a4856c7e946" - integrity sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw== +postcss-nesting@^10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.1.2.tgz#2e5f811b3d75602ea18a95dd445bde5297145141" + integrity sha512-dJGmgmsvpzKoVMtDMQQG/T6FSqs6kDtUDirIfl4KnjMCiY9/ETX8jdKyCd20swSRAbUYkaBKV20pxkzxoOXLqQ== dependencies: - browserslist "^4.16.0" - caniuse-api "^3.0.0" + postcss-selector-parser "^6.0.8" -postcss-reduce-transforms@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz#93c12f6a159474aa711d5269923e2383cedcf640" - integrity sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA== - dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" +postcss-overflow-shorthand@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2" + integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg== -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" +postcss-page-break@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" + integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== -postcss-selector-matches@^4.0.0: +postcss-place@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9" + integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-preset-env@7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.2.3.tgz#01b9b6eea0ff16c27a3d514f10105d56363428a6" + integrity sha512-Ok0DhLfwrcNGrBn8sNdy1uZqWRk/9FId0GiQ39W4ILop5GHtjJs8bu1MY9isPwHInpVEPWjb4CEcEaSbBLpfwA== + dependencies: + autoprefixer "^10.4.2" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001299" + css-blank-pseudo "^3.0.2" + css-has-pseudo "^3.0.3" + css-prefers-color-scheme "^6.0.2" + cssdb "^5.0.0" + postcss-attribute-case-insensitive "^5.0.0" + postcss-color-functional-notation "^4.2.1" + postcss-color-hex-alpha "^8.0.2" + postcss-color-rebeccapurple "^7.0.2" + postcss-custom-media "^8.0.0" + postcss-custom-properties "^12.1.2" + postcss-custom-selectors "^6.0.0" + postcss-dir-pseudo-class "^6.0.3" + postcss-double-position-gradients "^3.0.4" + postcss-env-function "^4.0.4" + postcss-focus-visible "^6.0.3" + postcss-focus-within "^5.0.3" + postcss-font-variant "^5.0.0" + postcss-gap-properties "^3.0.2" + postcss-image-set-function "^4.0.4" + postcss-initial "^4.0.1" + postcss-lab-function "^4.0.3" + postcss-logical "^5.0.3" + postcss-media-minmax "^5.0.0" + postcss-nesting "^10.1.2" + postcss-overflow-shorthand "^3.0.2" + postcss-page-break "^3.0.4" + postcss-place "^7.0.3" + postcss-pseudo-class-any-link "^7.0.2" + postcss-replace-overflow-wrap "^4.0.0" + postcss-selector-not "^5.0.0" + +postcss-pseudo-class-any-link@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz#534eb1dadd9945eb07830dbcc06fb4d5d865b8e0" + integrity sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-replace-overflow-wrap@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-not@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" - integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" + integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== -postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: +postcss-selector-not@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz#ac5fc506f7565dd872f82f5314c0f81a05630dc7" + integrity sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ== dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" + balanced-match "^1.0.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5: +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.6" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== @@ -6735,55 +6196,43 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.2.tgz#bc73c4ea4c5a80fbd4b45e29042c34ceffb9257f" - integrity sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A== - dependencies: - postcss-value-parser "^4.1.0" - svgo "^2.3.0" - -postcss-unique-selectors@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz#3be5c1d7363352eff838bd62b0b07a0abad43bfc" - integrity sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w== +postcss-selector-parser@^6.0.8, postcss-selector-parser@^6.0.9: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== dependencies: - alphanum-sort "^1.0.2" - postcss-selector-parser "^6.0.5" - uniqs "^2.0.0" + cssesc "^3.0.0" + util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" +postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.3.6: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== +postcss@8.4.5: + version "8.4.5" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" + integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map-js "^0.6.2" + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^1.0.1" -postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" +postcss@^8.2.14, postcss@^8.3.7: + version "8.4.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== + dependencies: + nanoid "^3.2.0" + picocolors "^1.0.0" + source-map-js "^1.0.2" -postcss@^8.2.15, postcss@^8.3.5: +postcss@^8.2.15: version "8.3.9" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== @@ -6797,17 +6246,17 @@ pretty-bytes@^5.3.0: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== -primeicons@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-4.1.0.tgz#19eaef8ef5594b0006358ae64e738d03e167c9bb" - integrity sha512-uEv2pSPk1zQCfaB2VgnUfnUxxlGryYi+5rbdxmZBBt5v9S/pscIQYS5YDLxsQZ7D9jn5c76+Tx5wX/2J1nK6sA== +primeicons@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-5.0.0.tgz#73a0b6028a77c58a9eeb331ad13aaf085e8451ee" + integrity sha512-heygWF0X5HFI1otlZE62pp6ye7sZ8om78J9au2BRkg8O7Y8AHTZ9qKMRzchZUHLe8zUAvdi6hZzzm9XxgwIExw== -primeng@^12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/primeng/-/primeng-12.2.0.tgz#f42fd389722959319dc225ff7a08386bf828eef4" - integrity sha512-EKU6VRDPbE9VzPzP/XbSTT2oEBV/RVbREzgXENUIIYdEmaPpRao/j6MDnX6niKKBe7VWA50hf18djhSQgAsCOg== +primeng@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/primeng/-/primeng-13.2.0.tgz#cbcc7fbc55b1479435e978c5156228e6e853c278" + integrity sha512-6rnjfXu91B1bVAFoJdbGTD7e3EXeTabPLvAJlVOg7/YFPbvzvOKjdFKa+8zomSun7TJgDLJTEa1ijgjc9b+uiA== dependencies: - tslib "^2.1.0" + tslib "^2.3.0" process-nextick-args@~2.0.0: version "2.0.1" @@ -6874,11 +6323,6 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -6894,16 +6338,6 @@ q@^1.4.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qrcode@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.2.tgz#e7c82a60140916d666541043bd2b0b72ee4e38a6" - integrity sha512-eR6RgxFYPDFH+zFLTJKtoNP/RlsHANQb52AUmQ2bGDPMuUw7jJb0F+DNEgx7qQGIElrbFxWYMc0/B91zLZPF9Q== - dependencies: - dijkstrajs "^1.0.1" - isarray "^2.0.1" - pngjs "^3.3.0" - yargs "^13.2.4" - qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -6921,11 +6355,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -6973,7 +6402,7 @@ read-package-json-fast@^2.0.1: json-parse-even-better-errors "^2.3.0" npm-normalize-package-bin "^1.0.1" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.5, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -6986,7 +6415,7 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.4.0: +readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -6995,15 +6424,6 @@ readable-stream@^3.0.6, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -7016,6 +6436,13 @@ reflect-metadata@^0.1.2: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" @@ -7040,14 +6467,6 @@ regenerator-transform@^0.14.2: dependencies: "@babel/runtime" "^7.8.4" -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - regex-parser@^2.2.11: version "2.2.11" resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" @@ -7073,11 +6492,28 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.0.0" +regexpu-core@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" + integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + regjsgen@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== + regjsparser@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" @@ -7085,22 +6521,14 @@ regjsparser@^0.7.0: dependencies: jsesc "~0.5.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== + dependencies: + jsesc "~0.5.0" -request@^2.87.0, request@^2.88.0, request@^2.88.2: +request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -7141,50 +6569,42 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-url-loader@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57" - integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz#ee3142fb1f1e0d9db9524d539cfa166e9314f795" + integrity sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg== dependencies: adjust-sourcemap-loader "^4.0.0" convert-source-map "^1.7.0" loader-utils "^2.0.0" - postcss "^7.0.35" + postcss "^8.2.14" source-map "0.6.1" -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" -resolve@1.20.0, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.3.2: +resolve@^1.1.7, resolve@^1.14.2, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -7200,22 +6620,22 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -7257,13 +6677,20 @@ rxjs@6.6.7, rxjs@^6.5.3: dependencies: tslib "^1.9.0" -rxjs@^7.2.0, rxjs@^7.4.0: +rxjs@^7.2.0: version "7.4.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== dependencies: tslib "~2.1.0" +rxjs@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" + integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7274,22 +6701,15 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-loader@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.1.0.tgz#b73324622231009da6fba61ab76013256380d201" - integrity sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg== +sass-loader@12.4.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" + integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== dependencies: klona "^2.0.4" neo-async "^2.6.2" @@ -7299,12 +6719,14 @@ sass-recursive-map-merge@^1.0.1: resolved "https://registry.yarnpkg.com/sass-recursive-map-merge/-/sass-recursive-map-merge-1.0.1.tgz#d5460b9fe10df62d246ca27c48d823f25c2290cb" integrity sha512-OuDTGVGx2o2sPeaSgGob5s2Qf6LxoMU4LG7n6vCzNgfXyBz/y8tKzcEYdmvgyhjvGQVcGA1g2UJnP7WMmahuVg== -sass@1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.36.0.tgz#5912ef9d5d16714171ba11cb17edb274c4bbc07e" - integrity sha512-fQzEjipfOv5kh930nu3Imzq3ie/sGDc/4KtQMJlt7RRdrkQSfe37Bwi/Rf/gfuYHsIuE1fIlDMvpyMcEwjnPvg== +sass@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.0.tgz#65ec1b1d9a6bc1bae8d2c9d4b392c13f5d32c078" + integrity sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw== dependencies: chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" saucelabs@^1.5.0: version "1.5.0" @@ -7318,16 +6740,7 @@ sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^2.6.5, schema-utils@^2.7.0: +schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -7336,7 +6749,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -7345,6 +6758,16 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -7360,12 +6783,12 @@ selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: tmp "0.0.30" xml2js "^0.4.17" -selfsigned@^1.10.8: - version "1.10.11" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== +selfsigned@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" + integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== dependencies: - node-forge "^0.10.0" + node-forge "^1.2.0" semver-dsl@^1.0.1: version "1.0.1" @@ -7379,7 +6802,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -7445,7 +6868,7 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -7455,16 +6878,6 @@ set-immediate-shim@~1.0.1: resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -7489,11 +6902,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -7508,58 +6933,26 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + smart-buffer@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.2.tgz#4bc48c2da9ce4769f19dc723396b50f5c12330a3" - integrity sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ== - dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" - inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.3" - sockjs@^0.3.21: version "0.3.21" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" @@ -7578,6 +6971,15 @@ socks-proxy-agent@^6.0.0: debug "^4.3.1" socks "^2.6.1" +socks-proxy-agent@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" + integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + socks@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" @@ -7586,35 +6988,24 @@ socks@^2.6.1: ip "^1.1.5" smart-buffer "^4.1.0" -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-js@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== -source-map-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.0.tgz#f2a04ee2808ad01c774dea6b7d2639839f3b3049" - integrity sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw== +source-map-loader@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d" + integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA== dependencies: abab "^2.0.5" - iconv-lite "^0.6.2" - source-map-js "^0.6.2" - -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" + iconv-lite "^0.6.3" + source-map-js "^1.0.1" source-map-resolve@^0.6.0: version "0.6.0" @@ -7624,15 +7015,15 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.3, source-map-support@^0.5.5, source-map-support@~0.5.19, source-map-support@~0.5.20: +source-map-support@^0.5.3, source-map-support@^0.5.5, source-map-support@~0.5.20: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== @@ -7647,12 +7038,7 @@ source-map-support@~0.4.0: dependencies: source-map "^0.5.6" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -7695,13 +7081,6 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@^1.1.1, sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" @@ -7734,19 +7113,6 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -7766,24 +7132,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7792,6 +7141,14 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7820,13 +7177,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7834,45 +7184,42 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -style-loader@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.2.1.tgz#63cb920ec145c8669e9a50e92961452a1ef5dcde" - integrity sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg== - -stylehacks@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" - integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== - dependencies: - browserslist "^4.16.0" - postcss-selector-parser "^6.0.4" +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -stylus-loader@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-6.1.0.tgz#7a3a719a27cb2b9617896d6da28fda94c3ed9762" - integrity sha512-qKO34QCsOtSJrXxQQmXsPeaVHh6hMumBAFIoJTcsSr2VzrA6o/CW9HCGR8spCjzJhN8oKQHdj/Ytx0wwXyElkw== +stylus-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-6.2.0.tgz#0ba499e744e7fb9d9b3977784c8639728a7ced8c" + integrity sha512-5dsDc7qVQGRoc6pvCL20eYgRUxepZ9FpeK28XhdXaIPP6kXr6nI1zAAKFQgP5OBkOfKaURp4WUpJzspg1f01Gg== dependencies: - fast-glob "^3.2.5" + fast-glob "^3.2.7" klona "^2.0.4" normalize-path "^3.0.0" -stylus@0.54.8: - version "0.54.8" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147" - integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg== +stylus@0.56.0: + version "0.56.0" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.56.0.tgz#13fc85c48082db483c90d2530942fe8b0be988eb" + integrity sha512-Ev3fOb4bUElwWu4F9P9WjnnaSpc8XB9OFHSFZSKMFL1CE1oM+oFXWEgAqPmmZIyhBihuqIQlFsVTypiiS9RxeA== dependencies: - css-parse "~2.0.0" - debug "~3.1.0" + css "^3.0.0" + debug "^4.3.2" glob "^7.1.6" - mkdirp "~1.0.4" safer-buffer "^2.1.2" sax "~1.2.4" - semver "^6.3.0" source-map "^0.7.3" superagent@^3.8.3: @@ -7903,13 +7250,6 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -7924,18 +7264,10 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -svgo@^2.3.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.7.0.tgz#e164cded22f4408fe4978f082be80159caea1e2d" - integrity sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - nanocolors "^0.1.12" - stable "^0.1.8" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== symbol-observable@4.0.0: version "4.0.0" @@ -7947,7 +7279,7 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2, tar@^6.1.0: +tar@^6.0.2, tar@^6.1.0, tar@^6.1.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -7959,18 +7291,6 @@ tar@^6.0.2, tar@^6.1.0: mkdirp "^1.0.3" yallist "^4.0.0" -terser-webpack-plugin@5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz#c369cf8a47aa9922bd0d8a94fe3d3da11a7678a1" - integrity sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA== - dependencies: - jest-worker "^27.0.2" - p-limit "^3.1.0" - schema-utils "^3.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.0" - terser-webpack-plugin@^5.1.3: version "5.2.4" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz#ad1be7639b1cbe3ea49fab995cbe7224b31747a1" @@ -7983,16 +7303,16 @@ terser-webpack-plugin@^5.1.3: source-map "^0.6.1" terser "^5.7.2" -terser@5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784" - integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg== +terser@5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== dependencies: commander "^2.20.0" source-map "~0.7.2" - source-map-support "~0.5.19" + source-map-support "~0.5.20" -terser@^5.7.0, terser@^5.7.2: +terser@^5.7.2: version "5.9.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351" integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ== @@ -8001,6 +7321,15 @@ terser@^5.7.0, terser@^5.7.2: source-map "~0.7.2" source-map-support "~0.5.20" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -8016,11 +7345,6 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -8040,21 +7364,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -8062,16 +7371,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -8109,21 +7408,16 @@ ts-node@~5.0.1: source-map-support "^0.5.3" yn "^2.0.0" -tslib@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tslib@2.3.1, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" @@ -8188,10 +7482,15 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@4.3.5, typescript@~4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" - integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== +typed-assert@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/typed-assert/-/typed-assert-1.0.8.tgz#4bf9f1ce7f3f974d09c3afd7c68d12e1391a233c" + integrity sha512-5NkbXZUlmCE73Fs7gvkp1XXJWHYetPkg60QnQ2NXQmBYNFxbBr2zA8GCtaH4K2s2WhOmSlgiSTmrjrcm5tnM5g== + +typescript@~4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" @@ -8216,26 +7515,6 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -8255,19 +7534,6 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -8275,12 +7541,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse@^1.4.3, url-parse@^1.5.3: +url-parse@^1.4.3: version "1.5.3" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== @@ -8288,19 +7549,6 @@ url-parse@^1.4.3, url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -8333,11 +7581,6 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -vendors@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -8347,10 +7590,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -watchpack@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" - integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -8394,75 +7637,62 @@ webdriver-manager@^12.0.6: semver "^5.3.0" xml2js "^0.4.17" -webpack-dev-middleware@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz#0abe825275720e0a339978aea5f0b03b140c1584" - integrity sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw== +webpack-dev-middleware@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.0.tgz#8fc02dba6e72e1d373eca361623d84610f27be7c" + integrity sha512-MouJz+rXAm9B1OTOYaJnn6rtD/lWZPy2ufQCH3BPs8Rloh/Du6Jze4p7AeLYHkVi0giJnYLaSGDC7S+GM9arhg== dependencies: - colorette "^1.2.2" - mem "^8.1.1" + colorette "^2.0.10" memfs "^3.2.2" mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.0.0" + schema-utils "^4.0.0" -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== +webpack-dev-middleware@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" + integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" + colorette "^2.0.10" + memfs "^3.4.1" + mime-types "^2.1.31" range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@3.11.2: - version "3.11.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" - integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== - dependencies: - ansi-html "0.0.7" + schema-utils "^4.0.0" + +webpack-dev-server@4.7.3: + version "4.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz#4e995b141ff51fa499906eebc7906f6925d0beaa" + integrity sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/serve-index" "^1.9.1" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.2.2" + ansi-html-community "^0.0.8" bonjour "^3.5.0" - chokidar "^2.1.8" + chokidar "^3.5.2" + colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" + default-gateway "^6.0.3" + del "^6.0.0" express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.0" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + portfinder "^1.0.28" + schema-utils "^4.0.0" + selfsigned "^2.0.0" serve-index "^1.9.1" sockjs "^0.3.21" - sockjs-client "^1.5.0" spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" + strip-ansi "^7.0.0" + webpack-dev-middleware "^5.3.0" + ws "^8.1.0" webpack-merge@5.8.0: version "5.8.0" @@ -8472,30 +7702,22 @@ webpack-merge@5.8.0: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^1.2.0, webpack-sources@^1.3.0: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.1.tgz#251a7d9720d75ada1469ca07dbb62f3641a05b6d" - integrity sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA== +webpack-sources@^3.0.0, webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack-subresource-integrity@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz#e40b6578d3072e2d24104975249c52c66e9a743e" - integrity sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw== +webpack-subresource-integrity@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz#8b7606b033c6ccac14e684267cb7fb1f5c2a132a" + integrity sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q== dependencies: - webpack-sources "^1.3.0" + typed-assert "^1.0.8" -webpack@5.50.0: - version "5.50.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.50.0.tgz#5562d75902a749eb4d75131f5627eac3a3192527" - integrity sha512-hqxI7t/KVygs0WRv/kTgUW8Kl3YC81uyWQSo/7WUs5LsuRw0htH/fCwbVBGCuiX/t4s7qzjXFcf41O8Reiypag== +webpack@5.67.0: + version "5.67.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.67.0.tgz#cb43ca2aad5f7cc81c4cd36b626e6b819805dbfd" + integrity sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.50" @@ -8506,12 +7728,12 @@ webpack@5.50.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.0" - es-module-lexer "^0.7.1" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" json-parse-better-errors "^1.0.2" loader-runner "^4.2.0" mime-types "^2.1.27" @@ -8519,8 +7741,8 @@ webpack@5.50.0: schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.2.0" - webpack-sources "^3.2.0" + watchpack "^2.3.1" + webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" @@ -8548,19 +7770,19 @@ which@^1.2.9: dependencies: isexe "^2.0.0" -which@^2.0.2: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: - string-width "^1.0.2 || 2" + string-width "^1.0.2 || 2 || 3 || 4" wildcard@^2.0.0: version "2.0.0" @@ -8575,15 +7797,6 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -8598,13 +7811,18 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^6.0.0, ws@^6.2.1: +ws@^6.0.0: version "6.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== dependencies: async-limiter "~1.0.0" +ws@^8.1.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + xhr2@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.1.tgz#4e73adc4f9cfec9cbd2157f73efdce3a5f108a93" @@ -8623,7 +7841,7 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: +"y18n@^3.2.1 || ^4.0.0": version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== @@ -8638,7 +7856,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== @@ -8651,18 +7869,10 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== yargs@^12.0.5: version "12.0.5" @@ -8682,34 +7892,18 @@ yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.2.4, yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@^17.0.0: - version "17.2.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" - integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== +yargs@^17.2.1, yargs@^17.3.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== dependencies: cliui "^7.0.2" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.0.0" yn@^2.0.0: version "2.0.0" From 0398468db3487480da316362392f35f34078be2e Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 17 Feb 2022 09:19:11 +0000 Subject: [PATCH 050/210] chore(release): :rocket: v4.12.4 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a7b3df6..2eb880ac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.12.4](https://github.com/Ombi-app/Ombi/compare/v4.12.3...v4.12.4) (2022-02-17) + + + ## [4.12.3](https://github.com/Ombi-app/Ombi/compare/v4.12.2...v4.12.3) (2022-02-16) @@ -342,12 +346,3 @@ -# [4.6.0](https://github.com/Ombi-app/Ombi/compare/v4.4.0...v4.6.0) (2021-11-09) - - -### Features - -* :sparkles: Upgrade Ombi to .NET 6 ([#4390](https://github.com/Ombi-app/Ombi/issues/4390)) ([719eb7d](https://github.com/Ombi-app/Ombi/commit/719eb7dbe37b3a72d264e2f670067518eef70694)), closes [#4392](https://github.com/Ombi-app/Ombi/issues/4392) - - - diff --git a/version.json b/version.json index 5295df539..80bf16b12 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.3" + "version": "4.12.4" } \ No newline at end of file From bd441cb54fd77d6befb03fae321dc36c29f0de2e Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 21 Feb 2022 20:49:48 +0000 Subject: [PATCH 051/210] fix(emby): :bug: Fixed the emby content sync #4513 --- src/Ombi.Store/Repository/EmbyContentRepository.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index ddec14025..b4b04a494 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -98,7 +98,8 @@ namespace Ombi.Store.Repository public override Task UpdateRange(IEnumerable existingContent) { - Db.EmbyContent.UpdateRange((EmbyContent)existingContent); + var list = existingContent.ToList(); + Db.EmbyContent.UpdateRange((List)list); return InternalSaveChanges(); } From 2927504f0e0b4e7251e69b44e0e30c7ec9519980 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 21 Feb 2022 20:51:45 +0000 Subject: [PATCH 052/210] fix(emby): :bug: Fixed the emby content sync #4513 --- src/Ombi.Store/Repository/EmbyContentRepository.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index b4b04a494..df88d8292 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -98,8 +98,7 @@ namespace Ombi.Store.Repository public override Task UpdateRange(IEnumerable existingContent) { - var list = existingContent.ToList(); - Db.EmbyContent.UpdateRange((List)list); + Db.EmbyContent.UpdateRange((IEnumerable)existingContent); return InternalSaveChanges(); } From f2e6b5ca8202e504f5576806102cceb9b55680d1 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Mon, 21 Feb 2022 20:55:18 +0000 Subject: [PATCH 053/210] chore(release): :rocket: v4.12.5 --- CHANGELOG.md | 21 ++++++++++----------- version.json | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eb880ac3..f7cb488ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [4.12.5](https://github.com/Ombi-app/Ombi/compare/v4.12.4...v4.12.5) (2022-02-21) + + +### Bug Fixes + +* **emby:** :bug: Fixed the emby content sync [#4513](https://github.com/Ombi-app/Ombi/issues/4513) ([2927504](https://github.com/Ombi-app/Ombi/commit/2927504f0e0b4e7251e69b44e0e30c7ec9519980)) +* **emby:** :bug: Fixed the emby content sync [#4513](https://github.com/Ombi-app/Ombi/issues/4513) ([bd441cb](https://github.com/Ombi-app/Ombi/commit/bd441cb54fd77d6befb03fae321dc36c29f0de2e)) + + + ## [4.12.4](https://github.com/Ombi-app/Ombi/compare/v4.12.3...v4.12.4) (2022-02-17) @@ -335,14 +345,3 @@ -## [4.6.1](https://github.com/Ombi-app/Ombi/compare/v4.6.0...v4.6.1) (2021-11-10) - - -### Bug Fixes - -* :bug: Fixed the MySQL issue after .net 6 upgrade [#4393](https://github.com/Ombi-app/Ombi/issues/4393) ([fea7ff0](https://github.com/Ombi-app/Ombi/commit/fea7ff05139e9ff50c8097fa5389b4ef9ad21a15)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c6acb45](https://github.com/Ombi-app/Ombi/commit/c6acb45f8d3f371c0b4024c4272849d0d0cc867f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([18c220a](https://github.com/Ombi-app/Ombi/commit/18c220a0cd0d19e45a07d0c319da2b9512778a8a)) - - - diff --git a/version.json b/version.json index 80bf16b12..4b27f2563 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.4" + "version": "4.12.5" } \ No newline at end of file From 5c0556e6f44b8997a611f3a4d8e9e4e05d08bd13 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 22 Feb 2022 16:41:37 +0000 Subject: [PATCH 054/210] fix(emby/jellyfin): :bug: Fixed another issue where we were not correctly displaying the correct status' for movies --- src/Ombi.Api.Emby/EmbyApi.cs | 2 +- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 10 ++++---- .../Search/JellyfinAvailabilityRuleTests.cs | 24 ++++--------------- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 18 +++++++------- .../Rules/Search/JellyfinAvailabilityRule.cs | 17 ++++++------- .../Jobs/Emby/EmbyContentSync.cs | 5 +++- .../Jobs/Jellyfin/JellyfinContentSync.cs | 5 +++- src/Ombi/Ombi.csproj | 2 +- 8 files changed, 37 insertions(+), 46 deletions(-) diff --git a/src/Ombi.Api.Emby/EmbyApi.cs b/src/Ombi.Api.Emby/EmbyApi.cs index c12cdb716..a1791494d 100644 --- a/src/Ombi.Api.Emby/EmbyApi.cs +++ b/src/Ombi.Api.Emby/EmbyApi.cs @@ -221,7 +221,7 @@ namespace Ombi.Api.Emby request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview,MediaStreams" : "ProviderIds,MediaStreams"); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); if (!string.IsNullOrEmpty(parentIdFilder)) diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 95be538cd..e3ec6cffe 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -5,6 +5,7 @@ using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Rules.Search; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Store.Entities; @@ -20,19 +21,18 @@ namespace Ombi.Core.Tests.Rule.Search { ContextMock = new Mock(); LoggerMock = new Mock>(); - SettingsMock = new Mock>(); - Rule = new EmbyAvailabilityRule(ContextMock.Object, LoggerMock.Object, SettingsMock.Object); + FeatureMock = new Mock(); + Rule = new EmbyAvailabilityRule(ContextMock.Object, LoggerMock.Object, FeatureMock.Object); } private EmbyAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } private Mock> LoggerMock { get; set; } - private Mock> SettingsMock { get; set; } + private Mock FeatureMock { get; set; } [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { TheMovieDbId = "123", @@ -51,7 +51,6 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby_4K() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { TheMovieDbId = "123", @@ -71,7 +70,6 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby_Both() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { TheMovieDbId = "123", diff --git a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs index c0034afb7..6da5787b6 100644 --- a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs @@ -5,6 +5,7 @@ using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Rules.Search; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Store.Entities; @@ -20,19 +21,18 @@ namespace Ombi.Core.Tests.Rule.Search { ContextMock = new Mock(); LoggerMock = new Mock>(); - SettingsMock = new Mock>(); - Rule = new JellyfinAvailabilityRule(ContextMock.Object, LoggerMock.Object, SettingsMock.Object); + FeatureMock = new Mock(); + Rule = new JellyfinAvailabilityRule(ContextMock.Object, LoggerMock.Object, FeatureMock.Object); } private JellyfinAvailabilityRule Rule { get; set; } private Mock ContextMock { get; set; } private Mock> LoggerMock { get; set; } - private Mock> SettingsMock { get; set; } + private Mock FeatureMock { get; set; } [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", @@ -51,7 +51,6 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_4K() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", @@ -71,7 +70,6 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_Both() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", @@ -92,20 +90,6 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_Uses_Default_Url_When() { - SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings - { - Enable = true, - Servers = new List - { - new JellyfinServers - { - Ip = "8080", - Port = 9090, - ServerHostname = string.Empty, - ServerId = "8" - } - } - }); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 4bc42ad04..79158ee43 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -14,16 +14,17 @@ namespace Ombi.Core.Rule.Rules.Search { public class EmbyAvailabilityRule : BaseSearchRule, IRules { - public EmbyAvailabilityRule(IEmbyContentRepository repo, ILogger log, ISettingsService s) + private readonly IFeatureService _featureService; + + public EmbyAvailabilityRule(IEmbyContentRepository repo, ILogger log, IFeatureService featureService) { EmbyContentRepository = repo; Log = log; - EmbySettings = s; + _featureService = featureService; } private IEmbyContentRepository EmbyContentRepository { get; } private ILogger Log { get; } - private ISettingsService EmbySettings { get; } public async Task Execute(SearchViewModel obj) { @@ -68,13 +69,14 @@ namespace Ombi.Core.Rule.Rules.Search { if (obj is SearchMovieViewModel movie) { - if (item.Has4K) + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + + if (item.Has4K && is4kEnabled) { movie.Available4K = true; obj.EmbyUrl = item.Url; } - - if (item.Quality.HasValue()) + else { obj.Available = true; obj.EmbyUrl = item.Url; diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index f8c69c0f0..7cab89991 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -14,16 +14,17 @@ namespace Ombi.Core.Rule.Rules.Search { public class JellyfinAvailabilityRule : BaseSearchRule, IRules { - public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ILogger log, ISettingsService s) + private readonly IFeatureService _featureService; + + public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ILogger log, IFeatureService featureService) { JellyfinContentRepository = repo; Log = log; - JellyfinSettings = s; + _featureService = featureService; } private IJellyfinContentRepository JellyfinContentRepository { get; } private ILogger Log { get; } - private ISettingsService JellyfinSettings { get; } public async Task Execute(SearchViewModel obj) { @@ -82,13 +83,13 @@ namespace Ombi.Core.Rule.Rules.Search } if (obj is SearchMovieViewModel movie) { - if (item.Has4K) + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (item.Has4K && is4kEnabled) { movie.Available4K = true; obj.JellyfinUrl = item.Url; } - - if (item.Quality.HasValue()) + else { obj.Available = true; obj.EmbyUrl = item.Url; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 89baa7e9d..b4d61f93d 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -281,12 +281,15 @@ namespace Ombi.Schedule.Jobs.Emby } else { - if (!existingMovie.Quality.Equals(quality, StringComparison.InvariantCultureIgnoreCase)) + if (!quality.Equals(existingMovie?.Quality, StringComparison.InvariantCultureIgnoreCase)) { _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); existingMovie.Quality = has4K ? null : quality; existingMovie.Has4K = has4K; + // Probably could refactor here + // If a 4k movie comes in (we don't store the quality on 4k) + // it will always get updated even know it's not changed toUpdate.Add(existingMovie); } else diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index 10a6ae98c..060c974e7 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -245,12 +245,15 @@ namespace Ombi.Schedule.Jobs.Jellyfin } else { - if (!existingMovie.Quality.Equals(quality, StringComparison.InvariantCultureIgnoreCase)) + if (!quality.Equals(existingMovie?.Quality, StringComparison.InvariantCultureIgnoreCase)) { _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); existingMovie.Quality = has4K ? null : quality; existingMovie.Has4K = has4K; + // Probably could refactor here + // If a 4k movie comes in (we don't store the quality on 4k) + // it will always get updated even know it's not changed toUpdate.Add(existingMovie); } else diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 5f836c27f..3dbc377cf 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -105,7 +105,7 @@ - + From f3ea979b8bd77842780ce8e6928b16237dd779cf Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 22 Feb 2022 21:35:28 +0000 Subject: [PATCH 055/210] fix(mediaserver): fixed some more issues in the media server sync and availability checks --- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 3 +++ .../Rule/Search/JellyfinAvailabilityRuleTests.cs | 3 +++ .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 7 +++++++ .../Rules/Search/JellyfinAvailabilityRule.cs | 9 ++++++++- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 16 ++++++++++++++-- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 12 +++++++++++- 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index e3ec6cffe..484e872e2 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -8,6 +8,7 @@ using Ombi.Core.Rule.Rules.Search; using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -51,6 +52,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby_4K() { + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { TheMovieDbId = "123", @@ -70,6 +72,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby_Both() { + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { TheMovieDbId = "123", diff --git a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs index 6da5787b6..f56876e48 100644 --- a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs @@ -8,6 +8,7 @@ using Ombi.Core.Rule.Rules.Search; using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -51,6 +52,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_4K() { + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", @@ -70,6 +72,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_Both() { + FeatureMock.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { TheMovieDbId = "123", diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 79158ee43..d28f50cc0 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -82,6 +82,13 @@ namespace Ombi.Core.Rule.Rules.Search obj.EmbyUrl = item.Url; obj.Quality = item.Quality; } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; + } } else { diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index 7cab89991..f10ac4bdd 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -88,13 +88,20 @@ namespace Ombi.Core.Rule.Rules.Search { movie.Available4K = true; obj.JellyfinUrl = item.Url; - } + } else { obj.Available = true; obj.EmbyUrl = item.Url; obj.Quality = item.Quality; } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; + } } else { diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 1742f9f20..ab5b3a6c6 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -14,12 +16,15 @@ namespace Ombi.Core.Rule.Rules.Search public class PlexAvailabilityRule : BaseSearchRule, IRules { private readonly ISettingsService _plexSettings; + private readonly IFeatureService _featureService; - public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log, ISettingsService plexSettings) + public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log, ISettingsService plexSettings, + IFeatureService featureService) { PlexContentRepository = repo; Log = log; _plexSettings = plexSettings; + _featureService = featureService; } private IPlexContentRepository PlexContentRepository { get; } @@ -92,10 +97,17 @@ namespace Ombi.Core.Rule.Rules.Search if (obj is SearchMovieViewModel movie) { - if (item.Has4K) + var is4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + + if (item.Has4K && is4kEnabled) { movie.Available4K = true; } + else + { + obj.Available = true; + obj.Quality = item.Quality; + } if (item.Quality.HasValue()) { diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 04b28d6e7..71bc5dcf4 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -307,9 +307,13 @@ namespace Ombi.Schedule.Jobs.Plex // We need to see if this is a different quality, // We want to know if this is a 4k content for example var foundQualities = movie.Media?.Select(x => x.videoResolution); - + var qualitySaved = false; foreach (var quality in foundQualities) { + if (qualitySaved) + { + break; + } if (quality.Equals(existing.Quality)) { // We got it @@ -322,6 +326,12 @@ namespace Ombi.Schedule.Jobs.Plex Logger.LogDebug($"We already have movie {movie.title}, But found a 4K version!"); existing.Has4K = true; await Repo.Update(existing); + } + else + { + qualitySaved = true; + existing.Quality = quality; + await Repo.Update(existing); } } From e2be70dacfddcc2e21b7f5dc1cc26fae0d1d45bc Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 22 Feb 2022 21:40:11 +0000 Subject: [PATCH 056/210] chore(release): :rocket: v4.12.6 --- CHANGELOG.md | 19 ++++++++++--------- version.json | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7cb488ec..aedc795e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [4.12.6](https://github.com/Ombi-app/Ombi/compare/v4.12.5...v4.12.6) (2022-02-22) + + +### Bug Fixes + +* **emby/jellyfin:** :bug: Fixed another issue where we were not correctly displaying the correct status' for movies ([5c0556e](https://github.com/Ombi-app/Ombi/commit/5c0556e6f44b8997a611f3a4d8e9e4e05d08bd13)) +* **mediaserver:** fixed some more issues in the media server sync and availability checks ([f3ea979](https://github.com/Ombi-app/Ombi/commit/f3ea979b8bd77842780ce8e6928b16237dd779cf)) + + + ## [4.12.5](https://github.com/Ombi-app/Ombi/compare/v4.12.4...v4.12.5) (2022-02-21) @@ -336,12 +346,3 @@ -## [4.6.2](https://github.com/Ombi-app/Ombi/compare/v4.6.1...v4.6.2) (2021-11-10) - - -### Bug Fixes - -* **discover:** TV shows now display on the Actor Pages ([#4388](https://github.com/Ombi-app/Ombi/issues/4388)) ([6b716e7](https://github.com/Ombi-app/Ombi/commit/6b716e722076e3d1e6bf2097c5263645d5ea9edf)) - - - diff --git a/version.json b/version.json index 4b27f2563..5e1d14832 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.5" + "version": "4.12.6" } \ No newline at end of file From a9fb71b91973bf9ecc1802477ac00849ef4b51e3 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Feb 2022 19:29:05 +0000 Subject: [PATCH 057/210] bug(plex/jellyfin): :bug: Fixed an issue where updates for the syncs would not always save correctly --- src/Ombi.Store/Repository/JellyfinContentRepository.cs | 2 +- src/Ombi.Store/Repository/PlexContentRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Store/Repository/JellyfinContentRepository.cs b/src/Ombi.Store/Repository/JellyfinContentRepository.cs index 02acee5b0..c3451da62 100644 --- a/src/Ombi.Store/Repository/JellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/JellyfinContentRepository.cs @@ -100,7 +100,7 @@ namespace Ombi.Store.Repository public override Task UpdateRange(IEnumerable existingContent) { - Db.JellyfinContent.UpdateRange((JellyfinContent)existingContent); + Db.JellyfinContent.UpdateRange((IEnumerable)existingContent); return InternalSaveChanges(); } diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index be79d1a29..9ae5adce8 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -166,7 +166,7 @@ namespace Ombi.Store.Repository public override Task UpdateRange(IEnumerable existingContent) { - Db.PlexServerContent.UpdateRange((PlexServerContent)existingContent); + Db.PlexServerContent.UpdateRange((IEnumerable)existingContent); return InternalSaveChanges(); } } From 76f6d91c2581bf25cd73441b574c5a0b965e602f Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 23 Feb 2022 19:32:37 +0000 Subject: [PATCH 058/210] chore(release): :rocket: v4.12.7 --- CHANGELOG.md | 15 ++++----------- version.json | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aedc795e9..458904ef0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.12.7](https://github.com/Ombi-app/Ombi/compare/v4.12.6...v4.12.7) (2022-02-23) + + + ## [4.12.6](https://github.com/Ombi-app/Ombi/compare/v4.12.5...v4.12.6) (2022-02-22) @@ -335,14 +339,3 @@ -## [4.6.3](https://github.com/Ombi-app/Ombi/compare/v4.6.2...v4.6.3) (2021-11-11) - - -### Bug Fixes - -* **discover:** :bug: Display TV + movies on actor page in user language ([#4395](https://github.com/Ombi-app/Ombi/issues/4395)) ([fe635c7](https://github.com/Ombi-app/Ombi/commit/fe635c7106bc487ff879bdc8a73bab16cb389b97)) -* **permissions:** :bug: Improved the security around the role "Manage Own Requests" ([#4397](https://github.com/Ombi-app/Ombi/issues/4397)) ([334a32b](https://github.com/Ombi-app/Ombi/commit/334a32bca42f90198d9b720d2bdb710a583be47f)), closes [#4391](https://github.com/Ombi-app/Ombi/issues/4391) -* **search:** Fixed some cases where search wouldn't work correctly ([#4398](https://github.com/Ombi-app/Ombi/issues/4398)) ([4410790](https://github.com/Ombi-app/Ombi/commit/4410790bc096826bc11554098f846e3acb59589a)) - - - diff --git a/version.json b/version.json index 5e1d14832..b01a1dbdd 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.6" + "version": "4.12.7" } \ No newline at end of file From d6ae79ce9eddbd5b7b888ab1b9f7e342d9d9ff9e Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:10:22 +0100 Subject: [PATCH 059/210] feat(media-details): Add Trakt to social icons (#4522) [skip ci] --- .../shared/social-icons/social-icons.component.html | 3 +++ .../shared/social-icons/social-icons.component.scss | 10 ++++++++++ src/Ombi/wwwroot/images/trakt.svg | 1 + 3 files changed, 14 insertions(+) create mode 100644 src/Ombi/wwwroot/images/trakt.svg diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index 98bb999b2..d97bb4c02 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -17,6 +17,9 @@ + + + diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss index 1da3e6841..fd31c4b6f 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss @@ -4,6 +4,16 @@ a.media-icons:hover{ color:$ombi-active; } +a.media-icons:hover img{ + filter: sepia(100%) hue-rotate(190deg) saturate(500%) brightness(190%); +} + +a.media-icons img{ + filter: contrast(0) brightness(3); + height: 2em; + padding: 0; +} + button.admin-cog{ margin-left:40px; color:$ombi-active; diff --git a/src/Ombi/wwwroot/images/trakt.svg b/src/Ombi/wwwroot/images/trakt.svg new file mode 100644 index 000000000..782305d6a --- /dev/null +++ b/src/Ombi/wwwroot/images/trakt.svg @@ -0,0 +1 @@ + \ No newline at end of file From a9a60678e74d22fa7ba34051a2645db86b600b4a Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:11:18 +0100 Subject: [PATCH 060/210] fix(4k): Hide 'Has 4K Request' column list if 4k feature is disabled (#4521) [skip ci] --- .../movies-grid/movies-grid.component.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index 984994016..de3f8de39 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -13,6 +13,7 @@ import { RequestServiceV2 } from "../../../services/requestV2.service"; import { SelectionModel } from "@angular/cdk/collections"; import { StorageService } from "../../../shared/storage/storage-service"; import { TranslateService } from "@ngx-translate/core"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./movies-grid.component.html", @@ -26,6 +27,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { public displayedColumns: string[] = ['title', 'requestedUser.requestedBy', 'status', 'requestStatus','requestedDate', 'actions']; public gridCount: string = "15"; public isAdmin: boolean; + public is4kEnabled = false; public manageOwnRequests: boolean; public defaultSort: string = "requestedDate"; public defaultOrder: string = "desc"; @@ -49,7 +51,8 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef, private auth: AuthService, private storageService: StorageService, private requestServiceV1: RequestService, private notification: NotificationService, - private translateService: TranslateService) { + private translateService: TranslateService, + private featureFacade: FeaturesFacade) { this.userName = auth.claims().name; } @@ -59,10 +62,14 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.manageOwnRequests = this.auth.hasRole("ManageOwnRequests") if (this.isAdmin) { this.displayedColumns.unshift('select'); - this.displayedColumns.splice(4,0,'has4kRequest'); - } else if (this.auth.hasRole("Request4KMovie")) { - this.displayedColumns.splice(4,0,'has4kRequest'); + } + + this.is4kEnabled = this.featureFacade.is4kEnabled(); + if ((this.isAdmin || this.auth.hasRole("Request4KMovie")) + && this.is4kEnabled) { + this.displayedColumns.splice(4, 0, 'has4kRequest'); } + const defaultCount = this.storageService.get(this.storageKeyGridCount); const defaultSort = this.storageService.get(this.storageKey); const defaultOrder = this.storageService.get(this.storageKeyOrder); From 76882adf231f92e1cdd396239933c13467c112b3 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:11:47 +0100 Subject: [PATCH 061/210] fix(issues): Fix label ID in chatbox page (#4520) [skip ci] --- .../ClientApp/src/app/shared/chat-box/chat-box.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html index 39e87c48b..a8fc88578 100644 --- a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html @@ -1,7 +1,7 @@
-

{{ "Issues.UserManagement" | translate }}

+

{{ "NavigationBar.UserManagement" | translate }}

{{user}}

From 2ed8c48d128a69f0d144c5d332286dbf3b0bdf28 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:12:35 +0100 Subject: [PATCH 062/210] fix(tv): Display TV show as requested if all episodes are requested (#4518) [skip ci] --- .../src/app/media-details/components/tv/tv-details.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts index 845dac993..2d02dc63b 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts @@ -126,7 +126,7 @@ export class TvDetailsComponent implements OnInit { } public allEpisodesRequested(): boolean { - return this.tv.seasonRequests.every(e => e.episodes.every(x => x.approved)); + return this.tv.seasonRequests.every(e => e.episodes.every(x => x.approved || x.requested)); } private loadAdvancedInfo() { From e09435da455b12fc429f129372de31e0654da797 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:14:07 +0100 Subject: [PATCH 063/210] fix(localisation): Localize request types in notifications (#4516) [skip ci] --- src/Ombi.I18n/Resources/Texts.Designer.cs | 27 +++++++++++++++++++ src/Ombi.I18n/Resources/Texts.resx | 9 +++++++ .../NotificationMessageCurlys.cs | 5 +++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Ombi.I18n/Resources/Texts.Designer.cs b/src/Ombi.I18n/Resources/Texts.Designer.cs index 2f589c022..22991cf96 100644 --- a/src/Ombi.I18n/Resources/Texts.Designer.cs +++ b/src/Ombi.I18n/Resources/Texts.Designer.cs @@ -60,6 +60,15 @@ namespace Ombi.I18n.Resources { } } + /// + /// Looks up a localized string similar to Album. + /// + public static string Album { + get { + return ResourceManager.GetString("Album", resourceCulture); + } + } + /// /// Looks up a localized string similar to Type:. /// @@ -87,6 +96,15 @@ namespace Ombi.I18n.Resources { } } + /// + /// Looks up a localized string similar to Movie. + /// + public static string Movie { + get { + return ResourceManager.GetString("Movie", resourceCulture); + } + } + /// /// Looks up a localized string similar to New Albums. /// @@ -132,6 +150,15 @@ namespace Ombi.I18n.Resources { } } + /// + /// Looks up a localized string similar to TV Show. + /// + public static string TvShow { + get { + return ResourceManager.GetString("TvShow", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unsubscribe. /// diff --git a/src/Ombi.I18n/Resources/Texts.resx b/src/Ombi.I18n/Resources/Texts.resx index 421371dcb..fcfcebfff 100644 --- a/src/Ombi.I18n/Resources/Texts.resx +++ b/src/Ombi.I18n/Resources/Texts.resx @@ -144,4 +144,13 @@ Unsubscribe + + Album + + + Movie + + + TV Show + \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 924864c62..1e8469eac 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Humanizer; using Ombi.Helpers; +using Ombi.I18n.Resources; using Ombi.Notifications.Models; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; @@ -192,7 +193,9 @@ namespace Ombi.Notifications return requestType switch { null => string.Empty, - RequestType.TvShow => "TV Show", + RequestType.TvShow => Texts.TvShow, + RequestType.Album => Texts.Album, + RequestType.Movie => Texts.Movie, _ => requestType.Humanize() }; } From a3e97b31e2298d95e7deebd71268095b8ed5e9dc Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:17:37 +0100 Subject: [PATCH 064/210] feat(email-notifications): Add a link to Ombi details page in email notifications (#4517) [skip ci] --- .../EmailBasicTemplate.cs | 23 +++++++++++++++++-- .../IEmailBasicTemplate.cs | 2 +- .../Agents/EmailNotification.cs | 2 +- .../NotificationMessageContent.cs | 1 + .../NotificationMessageCurlys.cs | 22 ++++++++++++++++++ .../NotificationMessageResolver.cs | 1 + 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs index 455c2d182..4bac4b3d8 100644 --- a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs @@ -31,16 +31,35 @@ namespace Ombi.Notifications.Templates private const string DateKey = "{@DATENOW}"; private const string Logo = "{@LOGO}"; - public string LoadTemplate(string subject, string body, string imgsrc = default(string), string logo = default(string)) + public string LoadTemplate(string subject, string body, string imgsrc = default(string), string logo = default(string), string url = default(string)) { var sb = new StringBuilder(File.ReadAllText(TemplateLocation)); sb.Replace(SubjectKey, subject); sb.Replace(BodyKey, body); sb.Replace(DateKey, DateTime.Now.ToString("f")); - sb.Replace(Poster, string.IsNullOrEmpty(imgsrc) ? string.Empty : $"
"); + sb.Replace(Poster, GetPosterContent(imgsrc, url)); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); return sb.ToString(); } + + private string GetPosterContent(string imgsrc, string url) { + string posterContent; + + if (string.IsNullOrEmpty(imgsrc)) + { + posterContent = string.Empty; + } + else + { + posterContent = $"\"Poster\""; + if (!string.IsNullOrEmpty(url)) + { + posterContent = $"{posterContent}"; + } + posterContent = $""; + } + return posterContent; + } } } diff --git a/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs index 99d7c881a..0a68c0e6b 100644 --- a/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/IEmailBasicTemplate.cs @@ -2,7 +2,7 @@ { public interface IEmailBasicTemplate { - string LoadTemplate(string subject, string body, string img = default(string), string logo = default(string)); + string LoadTemplate(string subject, string body, string img = default(string), string logo = default(string), string url = default(string)); string TemplateLocation { get; } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index cb96fcdb6..92ec766c3 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -64,7 +64,7 @@ namespace Ombi.Notifications.Agents return null; } var email = new EmailBasicTemplate(); - var html = email.LoadTemplate(parsed.Subject, parsed.Message, parsed.Image, Customization.Logo); + var html = email.LoadTemplate(parsed.Subject, parsed.Message, parsed.Image, Customization.Logo, parsed.DetailsUrl); var message = new NotificationMessage diff --git a/src/Ombi.Notifications/NotificationMessageContent.cs b/src/Ombi.Notifications/NotificationMessageContent.cs index 901b3bcb2..7141bbedd 100644 --- a/src/Ombi.Notifications/NotificationMessageContent.cs +++ b/src/Ombi.Notifications/NotificationMessageContent.cs @@ -7,6 +7,7 @@ namespace Ombi.Notifications public bool Disabled { get; set; } public string Subject { get; set; } public string Message { get; set; } + public string DetailsUrl { get; set; } public string Image { get; set; } public IReadOnlyDictionary Data { get; set; } } diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 1e8469eac..7696c9c16 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -152,6 +152,7 @@ namespace Ombi.Notifications RequestId = req?.Id.ToString(); RequestedUser = req?.RequestedUser?.UserName; RequestedDate = req?.RequestedDate.ToString("D"); + DetailsUrl = GetDetailsUrl(s, req); if (Type.IsNullOrEmpty()) { @@ -217,6 +218,26 @@ namespace Ombi.Notifications } } + private string GetDetailsUrl(CustomizationSettings s, BaseRequest req) + { + if (string.IsNullOrEmpty(s.ApplicationUrl)) + { + return string.Empty; + } + + switch (req) + { + case MovieRequests movieRequest: + return $"{s.ApplicationUrl}/details/movie/{movieRequest.TheMovieDbId}"; + case ChildRequests tvRequest: + return $"{s.ApplicationUrl}/details/tv/{tvRequest.ParentRequest.ExternalProviderId}"; + case AlbumRequest albumRequest: + return $"{s.ApplicationUrl}/details/artist/{albumRequest.ForeignArtistId}"; + default: + return string.Empty; + } + } + private void CalculateRequestStatus(BaseRequest req) { RequestStatus = string.Empty; @@ -258,6 +279,7 @@ namespace Ombi.Notifications public string Year { get; set; } public string EpisodesList { get; set; } public string SeasonsList { get; set; } + public string DetailsUrl { get; set; } public string PosterImage { get; set; } public string ApplicationName { get; set; } public string ApplicationUrl { get; set; } diff --git a/src/Ombi.Notifications/NotificationMessageResolver.cs b/src/Ombi.Notifications/NotificationMessageResolver.cs index fe6102eda..5475f1a97 100644 --- a/src/Ombi.Notifications/NotificationMessageResolver.cs +++ b/src/Ombi.Notifications/NotificationMessageResolver.cs @@ -26,6 +26,7 @@ namespace Ombi.Notifications { var content = Resolve(notification.Message, notification.Subject, c.Curlys); content.Image = c.PosterImage; + content.DetailsUrl = c.DetailsUrl; return content; } From b90fc5fea771a83e6cf576c71a307066efd59ea4 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:18:06 +0100 Subject: [PATCH 065/210] fix(notifications): Remove generic admin email in favour of admins' email (#4519) This removes the generic admin email setting. Instead we use the email addresses set on the users' profile. Allows for notifications to many recipients in case of multiple admins. Email testing now sends the test email to the currently logged in user. --- .../Agents/EmailNotification.cs | 54 +++++++------------ src/Ombi.Notifications/BaseNotification.cs | 7 ++- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 2 +- .../EmailNotificationSettings.cs | 1 - .../app/interfaces/INotificationSettings.ts | 1 - .../emailnotification.component.html | 15 ------ .../emailnotification.component.ts | 1 - .../V1/External/TesterController.cs | 12 ++++- 8 files changed, 37 insertions(+), 56 deletions(-) diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index 92ec766c3..8f6de1aa3 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -47,7 +47,7 @@ namespace Ombi.Notifications.Agents return false; } } - if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.AdminEmail) || string.IsNullOrEmpty(settings.Port.ToString())) + if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.Port.ToString())) { return false; } @@ -73,26 +73,6 @@ namespace Ombi.Notifications.Agents Subject = parsed.Subject, }; - if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) - { - var isAdmin = bool.Parse(isAdminString); - if (isAdmin) - { - var user = _userManager.Users.FirstOrDefault(x => x.Id == model.UserId); - // Send to user - message.To = user.Email; - } - else - { - // Send to admin - message.To = settings.AdminEmail; - } - } - else - { - // Send to admin - message.To = settings.AdminEmail; - } return message; } @@ -138,9 +118,7 @@ namespace Ombi.Notifications.Agents message.Other.Add("PlainTextBody", plaintext); // Issues should be sent to admin - message.To = settings.AdminEmail; - - await Send(message, settings); + await SendToAdmins(message, settings); } protected override async Task IssueComment(NotificationOptions model, EmailNotificationSettings settings) @@ -154,18 +132,16 @@ namespace Ombi.Notifications.Agents var plaintext = await LoadPlainTextMessage(NotificationType.IssueComment, model, settings); message.Other.Add("PlainTextBody", plaintext); - if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) + if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString) && !bool.Parse(isAdminString)) { - var isAdmin = bool.Parse(isAdminString); - message.To = isAdmin ? model.Recipient : settings.AdminEmail; + await SendToAdmins(message, settings); } else { message.To = model.Recipient; + await Send(message, settings); } - - await Send(message, settings); } protected override async Task IssueResolved(NotificationOptions model, EmailNotificationSettings settings) @@ -204,9 +180,7 @@ namespace Ombi.Notifications.Agents var plaintext = await LoadPlainTextMessage(NotificationType.ItemAddedToFaultQueue, model, settings); message.Other.Add("PlainTextBody", plaintext); - // Issues resolved should be sent to the user - message.To = settings.AdminEmail; - await Send(message, settings); + await SendToAdmins(message, settings); } protected override async Task RequestDeclined(NotificationOptions model, EmailNotificationSettings settings) @@ -305,6 +279,19 @@ namespace Ombi.Notifications.Agents { await EmailProvider.Send(model, settings); } + + protected async Task SendToAdmins(NotificationMessage message, EmailNotificationSettings settings) + { + foreach (var recipient in (await GetAdminUsers()).DistinctBy(x => x.Email)) + { + if (recipient.Email.IsNullOrEmpty()) + { + continue; + } + message.To = recipient.Email; + await Send(message, settings); + } + } protected override async Task Test(NotificationOptions model, EmailNotificationSettings settings) { @@ -316,12 +303,11 @@ namespace Ombi.Notifications.Agents { Message = html, Subject = $"Ombi: Test", - To = settings.AdminEmail, }; message.Other.Add("PlainTextBody", "This is just a test! Success!"); - await Send(message, settings); + await SendToAdmins(message, settings); } } } diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index b52f0a0cd..97e2a676d 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -216,9 +216,14 @@ namespace Ombi.Notifications .FirstOrDefault(x => x.Agent == agent && x.UserId == userId); } - protected async Task> GetPrivilegedUsers() + protected async Task> GetAdminUsers() { IEnumerable recipients = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); + return recipients; + } + protected async Task> GetPrivilegedUsers() + { + IEnumerable recipients = await GetAdminUsers(); recipients = recipients.Concat(await _userManager.GetUsersInRoleAsync(OmbiRoles.PowerUser)); return recipients; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index dbb343126..a11a9ff80 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -844,7 +844,7 @@ namespace Ombi.Schedule.Jobs.Ombi return false; } } - if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.AdminEmail) || string.IsNullOrEmpty(settings.Port.ToString())) + if (string.IsNullOrEmpty(settings.Host) || string.IsNullOrEmpty(settings.Port.ToString())) { return false; } diff --git a/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs index 9ea8cc492..f63b77ae5 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/EmailNotificationSettings.cs @@ -10,7 +10,6 @@ public string SenderAddress { get; set; } public string Username { get; set; } public bool Authentication { get; set; } - public string AdminEmail { get; set; } public bool DisableTLS { get; set; } public bool DisableCertificateChecking { get; set; } } diff --git a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts index f2efc3f6f..460a970fe 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts @@ -12,7 +12,6 @@ export interface IEmailNotificationSettings extends INotificationSettings { senderName: string; username: string; authentication: boolean; - adminEmail: string; disableTLS: boolean; disableCertificateChecking: boolean; notificationTemplates: INotificationTemplates[]; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html index 5c24d21f2..7e95b0dfd 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html @@ -57,21 +57,6 @@ - -
- - Admin Email - - - Admin Email is required - - - Admin Email needs to be a valid email address - - -
- -
Username diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts index f880891a5..7673e2e1d 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts @@ -35,7 +35,6 @@ export class EmailNotificationComponent implements OnInit { senderAddress: [x.senderAddress, [Validators.required, Validators.email]], senderName: [x.senderName], username: [x.username], - adminEmail: [x.adminEmail, [Validators.required, Validators.email]], disableTLS: [x.disableTLS], disableCertificateChecking: [x.disableCertificateChecking], }); diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index 13bf44a1d..f18547e0f 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Security.Principal; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -48,7 +49,7 @@ namespace Ombi.Controllers.V1.External IPlexApi plex, IEmbyApiFactory emby, IRadarrV3Api radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification, - IJellyfinApi jellyfinApi) + IJellyfinApi jellyfinApi, IPrincipal user) { Service = service; DiscordNotification = notification; @@ -74,6 +75,7 @@ namespace Ombi.Controllers.V1.External UserManager = um; WebhookNotification = webhookNotification; _jellyfinApi = jellyfinApi; + UserPrinciple = user; } private INotificationService Service { get; } @@ -100,6 +102,7 @@ namespace Ombi.Controllers.V1.External private IWhatsAppApi WhatsAppApi { get; } private OmbiUserManager UserManager {get; } private readonly IJellyfinApi _jellyfinApi; + private IPrincipal UserPrinciple { get; } /// /// Sends a test message to discord using the provided settings @@ -283,7 +286,7 @@ namespace Ombi.Controllers.V1.External { Message = "This is just a test! Success!", Subject = $"Ombi: Test", - To = settings.AdminEmail, + To = (await GetCurrentUserAsync()).Email, }; message.Other.Add("PlainTextBody", "This is just a test! Success!"); @@ -298,6 +301,11 @@ namespace Ombi.Controllers.V1.External return true; } + private async Task GetCurrentUserAsync() + { + return await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == UserPrinciple.Identity.Name.ToUpper()); + } + /// /// Checks if we can connect to Plex with the provided settings /// From 7f7472e51ecad443be029146b6d9205570a2f9cf Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 25 Feb 2022 13:21:49 +0000 Subject: [PATCH 066/210] chore(release): :rocket: v4.13.0 --- CHANGELOG.md | 23 +++++++++++++++++++---- version.json | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 458904ef0..98bc04767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +# [4.13.0](https://github.com/Ombi-app/Ombi/compare/v4.12.7...v4.13.0) (2022-02-25) + + +### Bug Fixes + +* **4k:** Hide 'Has 4K Request' column list if 4k feature is disabled ([#4521](https://github.com/Ombi-app/Ombi/issues/4521)) ([a9a6067](https://github.com/Ombi-app/Ombi/commit/a9a60678e74d22fa7ba34051a2645db86b600b4a)) +* **issues:** Fix label ID in chatbox page ([#4520](https://github.com/Ombi-app/Ombi/issues/4520)) ([76882ad](https://github.com/Ombi-app/Ombi/commit/76882adf231f92e1cdd396239933c13467c112b3)) +* **localisation:** Localize request types in notifications ([#4516](https://github.com/Ombi-app/Ombi/issues/4516)) ([e09435d](https://github.com/Ombi-app/Ombi/commit/e09435da455b12fc429f129372de31e0654da797)) +* **notifications:** Remove generic admin email in favour of admins' email ([#4519](https://github.com/Ombi-app/Ombi/issues/4519)) ([b90fc5f](https://github.com/Ombi-app/Ombi/commit/b90fc5fea771a83e6cf576c71a307066efd59ea4)) +* **tv:** Display TV show as requested if all episodes are requested ([#4518](https://github.com/Ombi-app/Ombi/issues/4518)) ([2ed8c48](https://github.com/Ombi-app/Ombi/commit/2ed8c48d128a69f0d144c5d332286dbf3b0bdf28)) + + +### Features + +* **email-notifications:** Add a link to Ombi details page in email notifications ([#4517](https://github.com/Ombi-app/Ombi/issues/4517)) ([a3e97b3](https://github.com/Ombi-app/Ombi/commit/a3e97b31e2298d95e7deebd71268095b8ed5e9dc)) +* **media-details:** Add Trakt to social icons ([#4522](https://github.com/Ombi-app/Ombi/issues/4522)) ([d6ae79c](https://github.com/Ombi-app/Ombi/commit/d6ae79ce9eddbd5b7b888ab1b9f7e342d9d9ff9e)) + + + ## [4.12.7](https://github.com/Ombi-app/Ombi/compare/v4.12.6...v4.12.7) (2022-02-23) @@ -335,7 +354,3 @@ -## [4.6.4](https://github.com/Ombi-app/Ombi/compare/v4.6.3...v4.6.4) (2021-11-12) - - - diff --git a/version.json b/version.json index b01a1dbdd..b609ccf58 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.12.7" + "version": "4.13.0" } \ No newline at end of file From aaf77aea1e52c0764ca8470d6fed903b263c255a Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 25 Feb 2022 13:52:44 +0000 Subject: [PATCH 067/210] [skip ci] --- crowdin.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index 530225513..170fc200d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,6 +1,6 @@ -commit_message: "\UF09F8C90" +commit_message: "fix(translations): 🌐 New translations from Crowdin [skip ci]" append_commit_message: false -pull_request_title: "\UF09F8C90" +pull_request_title: "🌐 Translations Update" pull_request_labels: - translations files: From 6b66ef018d37a7b0e4192093d68d2fede9b5f5c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 25 Feb 2022 13:55:22 +0000 Subject: [PATCH 068/210] =?UTF-8?q?=F0=9F=8C=90=20Translations=20Update=20?= =?UTF-8?q?(#4523)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] --- src/Ombi.I18n/Resources/Texts.bg.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.cs.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.da.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.de.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.es.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.fr.resx | 43 ++- src/Ombi.I18n/Resources/Texts.hu.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.it.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.nl.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.no.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.pl.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.pt-BR.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.pt.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.ru.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.sk.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.sv.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.zh-TW.resx | 156 ++++++++ src/Ombi.I18n/Resources/Texts.zh.resx | 156 ++++++++ src/Ombi/wwwroot/translations/bg.json | 59 +-- src/Ombi/wwwroot/translations/cs.json | 23 +- src/Ombi/wwwroot/translations/da.json | 413 +++++++++++---------- src/Ombi/wwwroot/translations/de.json | 317 ++++++++-------- src/Ombi/wwwroot/translations/es.json | 11 + src/Ombi/wwwroot/translations/fr.json | 11 + src/Ombi/wwwroot/translations/hu.json | 11 + src/Ombi/wwwroot/translations/it.json | 11 + src/Ombi/wwwroot/translations/nl.json | 171 +++++---- src/Ombi/wwwroot/translations/no.json | 45 ++- src/Ombi/wwwroot/translations/pl.json | 295 +++++++-------- src/Ombi/wwwroot/translations/pt-BR.json | 446 +++++++++++++++++++++++ src/Ombi/wwwroot/translations/pt.json | 373 ++++++++++--------- src/Ombi/wwwroot/translations/ru.json | 39 +- src/Ombi/wwwroot/translations/sk.json | 11 + src/Ombi/wwwroot/translations/sv.json | 71 ++-- src/Ombi/wwwroot/translations/zh-TW.json | 446 +++++++++++++++++++++++ src/Ombi/wwwroot/translations/zh.json | 11 + 36 files changed, 4594 insertions(+), 865 deletions(-) create mode 100644 src/Ombi.I18n/Resources/Texts.bg.resx create mode 100644 src/Ombi.I18n/Resources/Texts.cs.resx create mode 100644 src/Ombi.I18n/Resources/Texts.da.resx create mode 100644 src/Ombi.I18n/Resources/Texts.de.resx create mode 100644 src/Ombi.I18n/Resources/Texts.es.resx create mode 100644 src/Ombi.I18n/Resources/Texts.hu.resx create mode 100644 src/Ombi.I18n/Resources/Texts.it.resx create mode 100644 src/Ombi.I18n/Resources/Texts.nl.resx create mode 100644 src/Ombi.I18n/Resources/Texts.no.resx create mode 100644 src/Ombi.I18n/Resources/Texts.pl.resx create mode 100644 src/Ombi.I18n/Resources/Texts.pt-BR.resx create mode 100644 src/Ombi.I18n/Resources/Texts.pt.resx create mode 100644 src/Ombi.I18n/Resources/Texts.ru.resx create mode 100644 src/Ombi.I18n/Resources/Texts.sk.resx create mode 100644 src/Ombi.I18n/Resources/Texts.sv.resx create mode 100644 src/Ombi.I18n/Resources/Texts.zh-TW.resx create mode 100644 src/Ombi.I18n/Resources/Texts.zh.resx create mode 100644 src/Ombi/wwwroot/translations/pt-BR.json create mode 100644 src/Ombi/wwwroot/translations/zh-TW.json diff --git a/src/Ombi.I18n/Resources/Texts.bg.resx b/src/Ombi.I18n/Resources/Texts.bg.resx new file mode 100644 index 000000000..81fa9fc9c --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.bg.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Жанрове: + + + Type: + + + Сезон: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.cs.resx b/src/Ombi.I18n/Resources/Texts.cs.resx new file mode 100644 index 000000000..f619ffb16 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.cs.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.da.resx b/src/Ombi.I18n/Resources/Texts.da.resx new file mode 100644 index 000000000..244fc97a7 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.da.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nye Album + + + Nye Film + + + Nye TV-Serier + + + Genre: + + + Type: + + + Sæson: + + + Episoder: + + + Drevet af + + + Afmeld + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.de.resx b/src/Ombi.I18n/Resources/Texts.de.resx new file mode 100644 index 000000000..a222d02b0 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.de.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Neue Alben + + + Neue Filme + + + Neue Serien + + + Genres: + + + Typ: + + + Staffel: + + + Episoden: + + + Powered by + + + Abbestellen + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.es.resx b/src/Ombi.I18n/Resources/Texts.es.resx new file mode 100644 index 000000000..e0412c48a --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.es.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nuevos Álbumes + + + Nuevas Películas + + + Series Nuevas + + + Géneros: + + + Tipo: + + + Temporada: + + + Episodios: + + + Desarrollado por + + + Anular Suscripción + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.fr.resx b/src/Ombi.I18n/Resources/Texts.fr.resx index ea90dda73..2b4cdffae 100644 --- a/src/Ombi.I18n/Resources/Texts.fr.resx +++ b/src/Ombi.I18n/Resources/Texts.fr.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -144,4 +144,13 @@ Se désinscrire + + Album + + + Film + + + Série + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.hu.resx b/src/Ombi.I18n/Resources/Texts.hu.resx new file mode 100644 index 000000000..4e7cebcfd --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.hu.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Műfaj: + + + Típus: + + + Évad: + + + Epizódok: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.it.resx b/src/Ombi.I18n/Resources/Texts.it.resx new file mode 100644 index 000000000..c418310b4 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.it.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nuovi Album + + + Nuovi Film + + + Nuove Serie + + + Generi: + + + Tipo: + + + Stagione: + + + Episodi: + + + Offerto da + + + Disiscriviti + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.nl.resx b/src/Ombi.I18n/Resources/Texts.nl.resx new file mode 100644 index 000000000..e785eb494 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.nl.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nieuwe albums + + + Nieuwe films + + + Nieuwe TV Series + + + Genres: + + + Type: + + + Seizoen: + + + Afleveringen: + + + Mogelijk gemaakt door + + + Uitschrijven + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.no.resx b/src/Ombi.I18n/Resources/Texts.no.resx new file mode 100644 index 000000000..bf0daa456 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.no.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Sesong: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pl.resx b/src/Ombi.I18n/Resources/Texts.pl.resx new file mode 100644 index 000000000..c8e5e5ee1 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pl.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nowy Album + + + Nowy film + + + Nowy telewizor + + + Gatunki: + + + Typ: + + + Sezon: + + + Odcinków: + + + Wspierane przez + + + Wypisać się + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pt-BR.resx b/src/Ombi.I18n/Resources/Texts.pt-BR.resx new file mode 100644 index 000000000..1dcd24317 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pt-BR.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Gêneros: + + + Type: + + + Temporada: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.pt.resx b/src/Ombi.I18n/Resources/Texts.pt.resx new file mode 100644 index 000000000..f619ffb16 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.pt.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.ru.resx b/src/Ombi.I18n/Resources/Texts.ru.resx new file mode 100644 index 000000000..357d1156c --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.ru.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Сезон: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.sk.resx b/src/Ombi.I18n/Resources/Texts.sk.resx new file mode 100644 index 000000000..8fb4b7157 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.sk.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Žánre: + + + Typ: + + + Séria: + + + Epizódy: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.sv.resx b/src/Ombi.I18n/Resources/Texts.sv.resx new file mode 100644 index 000000000..779be9937 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.sv.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + Genrer: + + + Type: + + + Säsong: + + + Episodes: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.zh-TW.resx b/src/Ombi.I18n/Resources/Texts.zh-TW.resx new file mode 100644 index 000000000..ca17c4bf6 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.zh-TW.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New Albums + + + New Movies + + + New TV + + + 流派 + + + 类型: + + + 季: + + + 集: + + + Powered by + + + Unsubscribe + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.zh.resx b/src/Ombi.I18n/Resources/Texts.zh.resx new file mode 100644 index 000000000..08fb2ec4f --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.zh.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 新专辑 + + + 新电影 + + + 新电视节目 + + + 流派 + + + 类型: + + + 季: + + + 集: + + + 技术支持: + + + 取消订阅 + + + Album + + + Movie + + + TV Show + + \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index 9242cd30a..789af74df 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Продължаване", "Available": "Налично", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Одобрени", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Частично налично", "Monitored": "Наблюдавано", @@ -24,8 +26,10 @@ "RequestDenied": "Заявката е отказана", "NotRequested": "Не е заявено", "Requested": "Заявено", + "Requested4K": "Requested 4K", "Search": "Търсене", "Request": "Заявка", + "Request4K": "Request 4K", "Denied": "Отказано", "Approve": "Одобряване", "PartlyAvailable": "Частично налично", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Основна папка", "ChangeQualityProfile": "Профил на качеството", "MarkUnavailable": "Означаване като неналично", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Означаване като налично", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Премахване", "Deny": "Отказване", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Причина за отхвърляне", "DeniedReason": "Причина за отхвърляне", "Season": "Сезон", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Изтриване на заявка", "Approve": "Одобряване на заявка", + "Approve4K": "Approve 4K Request", "ChangeAvailability": "Маркиране като налично", "Deleted": "Избраните елементи са изтрити успешно", "Approved": "Избраните елементи са одобрени успешно" @@ -212,7 +221,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Заявката за {{title}} е успешно добавена", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Отказано", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Препоръчани", "SimilarTitle": "Подобни", @@ -312,7 +322,7 @@ "QualityProfilesSelect": "Изберете профил на качеството", "RootFolderSelect": "Изберете основна папка", "LanguageProfileSelect": "Изберете езиков профил", - "Status": "Status:", + "Status": "Състояние:", "StatusValues": { "Rumored": "Rumored", "Planned": "Planned", @@ -326,23 +336,23 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Наличност:", "RequestStatus": "Състояние на заявката", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "Quality": "Качество:", + "RootFolderOverride": "Ръчно задаване на основната папка:", + "QualityOverride": "Ръчно задаване на качеството:", + "Network": "Мрежа:", + "GenresLabel": "Жанрове:", + "Genres": "Жанрове", + "FirstAired": "Първо излъчено:", + "TheatricalRelease": "Кино премиера:", + "DigitalRelease": "Дигитална версия:", + "Votes": "Гласове:", + "Runtime": "Продължителност:", "Minutes": "{{runtime}} Минути", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Revenue": "Приходи:", + "Budget": "Бюджет:", + "Keywords": "Ключови думи/тагове:", "Casts": { "CastTitle": "В ролите" }, @@ -351,18 +361,19 @@ "FirstSeasonTooltip": "Това ще заяви само първия сезон на това предаване", "LatestSeasonTooltip": "Това ще заяви само последния сезон на това предаване", "NoEpisodes": "За съжаление все още няма данни за епизоди на това предаване!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Сезон {{number}}" }, "SonarrConfiguration": "Конфигурация на Sonarr", "RadarrConfiguration": "Конфигурация на Radarr", "RequestOnBehalf": "Заявете от името на", "PleaseSelectUser": "Моля, изберете потребител", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "StreamingOn": "Поточното изпълнение е включено:", + "RequestedBy": "Заявено от:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", + "RequestDate": "Дата на заявка:", + "DeniedReason": "Причина за отхвърляне:", "ReProcessRequest": "Повтаряне на заявка", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", @@ -408,7 +419,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "Електронна поща", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index b3234f471..1f74f8127 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Pokračovat", "Available": "Dostupný", + "Available4K": "Available 4K", "Approved": "Schváleno", + "Approve4K": "Approve 4K", "Pending": "Čeká na vyřízení", "PartiallyAvailable": "Částečně dostupné", "Monitored": "Monitorováno", @@ -24,8 +26,10 @@ "RequestDenied": "Žádost zamítnuta", "NotRequested": "Nevyžádáno", "Requested": "Vyžádáno", + "Requested4K": "Requested 4K", "Search": "Hledat", "Request": "Žádost", + "Request4K": "Request 4K", "Denied": "Zamítnuto", "Approve": "Schválit", "PartlyAvailable": "Částečně k dispozici", @@ -60,7 +64,7 @@ }, "NavigationBar": { "Discover": "Discover", - "Search": "Search", + "Search": "Hledat", "Requests": "Requests", "UserManagement": "Users", "Issues": "Issues", @@ -91,7 +95,7 @@ "EveningWelcome": "Good evening!" }, "Search": { - "Title": "Search", + "Title": "Hledat", "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", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", "MarkUnavailable": "Mark Unavailable", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Mark Available", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Remove", "Deny": "Deny", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Season", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", + "Approve4K": "Approve 4K Request", "ChangeAvailability": "Mark Available", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" @@ -269,15 +278,15 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Vyžádáno", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { "ClearFilter": "Clear Filter", "FilterHeaderAvailability": "Availability", "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval", + "Approved": "Schváleno", + "PendingApproval": "Čeká na schválení", "WatchProviders": "Watch Providers", "Keywords": "Keywords" }, @@ -294,7 +303,8 @@ "VotesTab": "Votes Needed" }, "MediaDetails": { - "Denied": "Denied", + "Denied": "Zamítnuto", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", @@ -363,6 +373,7 @@ "RequestDate": "Request Date:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 1598df272..63869300b 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Brugernavn", "PasswordPlaceholder": "Adgangskode", "RememberMe": "Husk mig", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Log ind med {{appName}}", + "SignInWithPlex": "Log ind med Plex", "ForgottenPassword": "Glemt adgangskode?", "Errors": { "IncorrectCredentials": "Forkert brugernavn eller adgangskode" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Fortsæt", "Available": "Tilgængelig", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Tilgængelig 4K", + "Approved": "Godkendt", + "Approve4K": "Godkend 4K", + "Pending": "Afventer", "PartiallyAvailable": "Delvist tilgængelig", "Monitored": "Overvåget", "NotAvailable": "Ikke tilgængelig", @@ -24,20 +26,22 @@ "RequestDenied": "Anmodning afvist", "NotRequested": "Ikke anmodet", "Requested": "Anmodet", - "Search": "Search", + "Requested4K": "Anmodet 4K", + "Search": "Søg", "Request": "Anmod", + "Request4K": "Anmod 4K", "Denied": "Afvist", "Approve": "Godkendt", "PartlyAvailable": "Delvist tilgængelig", - "ViewDetails": "View Details", + "ViewDetails": "Vis detaljer", "Errors": { "Validation": "Tjek venligst dine indtastede værdier" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Annuller", + "Submit": "Send", + "Update": "Opdater", + "tvShow": "TV-Serier", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -56,10 +60,10 @@ "CheckPageForUpdates": "Tjek denne side for løbende opdateringer." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Siden blev ikke fundet" }, "NavigationBar": { - "Discover": "Discover", + "Discover": "Opdag", "Search": "Søg", "Requests": "Anmodninger", "UserManagement": "Brugeradministration", @@ -75,20 +79,20 @@ "Logout": "Log af", "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Senest tilføjet", - "ChangeTheme": "Change Theme", - "Calendar": "Calendar", - "UserPreferences": "Preferences", + "ChangeTheme": "Skift tema", + "Calendar": "Kalender", + "UserPreferences": "Præferencer", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Har du en god ny idé? Foreslå den her!", "Filter": { "Movies": "Film", "TvShows": "Tv-serier", "Music": "Musik", - "People": "People" + "People": "Personer" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Godmorgen!", + "AfternoonWelcome": "Godeftermiddag!", + "EveningWelcome": "Godaften!" }, "Search": { "Title": "Søg", @@ -96,19 +100,19 @@ "MoviesTab": "Film", "TvTab": "Tv-serier", "MusicTab": "Musik", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearch": "Du kan udfylde en eller flere af nedenstående for at opdage nye medier. Alle resultater er sorteret efter popularitet", + "AdvancedSearchHeader": "Avanceret Søgning", "Suggestions": "Forslag", "NoResults": "Beklager, vi fandt ingen resultater!", "DigitalDate": "Digital udgivelse: {{date}}", "TheatricalRelease": "Biografudgivelse: {{date}}", "ViewOnPlex": "Se på Plex", "ViewOnEmby": "Se på Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Afspil på Jellyfin", "RequestAdded": "{{title}} er anmodet med succes", "Similar": "Lignende", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "Refine": "Specificer", + "SearchBarPlaceholder": "Indtast her for at søge", "Movies": { "PopularMovies": "Populære film", "UpcomingMovies": "Kommende film", @@ -132,19 +136,19 @@ "Season": "Sæson {{seasonNumber}}", "SelectAllInSeason": "Vælg alle i sæson {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", - "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + "AdvancedSearchInstructions": "Vælg venligst hvilken type medier, du søger efter:", + "YearOfRelease": "Udgivelsesår", + "SearchGenre": "Søg efter genre", + "SearchKeyword": "Søg efter nøgleord", + "SearchProvider": "Søgemaskiner", + "KeywordSearchingDisclaimer": "Bemærk venligst, at Nøgleord-søgning ikke altid er pålideligt grundet de inkonsistente data i TheMovieDb" }, "Requests": { "Title": "Anmodninger", "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", "MoviesTab": "Film", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Kunstner", + "AlbumName": "Albumnavn", "TvTab": "Tv-serier", "MusicTab": "Musik", "RequestedBy": "Anmodet af", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Skift rodmappe", "ChangeQualityProfile": "Skift kvalitetsprofil", "MarkUnavailable": "Markér som utilgængelig", + "MarkUnavailable4K": "Marker Utilgængelig 4K", "MarkAvailable": "Markér som tilgængelig", + "MarkAvailable4K": "Marker Tilgængelig 4K", "Remove": "Fjern", "Deny": "Afvis", - "DenyReason": "Deny Reason", - "DeniedReason": "Denied Reason", + "Deny4K": "Afvis 4K", + "Has4KRequest": "Har 4K Anmodning", + "DenyReason": "Afvisningsårsag", + "DeniedReason": "Afvisningsårsag", "Season": "Sæson", "GridTitle": "Titel", "AirDate": "Sendt", @@ -187,60 +195,61 @@ "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle anmodninger", + "PendingRequests": "Afventende anmodninger", + "ProcessingRequests": "Behandler anmodninger", + "AvailableRequests": "Tilgængelige anmodninger", + "DeniedRequests": "Afviste anmodninger", + "RequestsToDisplay": "Anmodninger at vise", "RequestsTitle": "Titel", "Details": "Detaljer", - "Options": "Options", + "Options": "Indstillinger", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Slet Anmodning", + "Approve": "Godkend Andmodning", + "Approve4K": "Godkend 4K Anmodning", + "ChangeAvailability": "Markér som tilgængelig", + "Deleted": "De valgte elementer blev slettet", + "Approved": "De valgte elementer blev godkendt" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", - "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "SuccessfullyApproved": "Godkendt", + "SuccessfullyDeleted": "Anmodningen blev slettet", + "NowAvailable": "Anmodningen er nu tilgængelig", + "NowUnavailable": "Anmodningen er nu utilgængelig", + "SuccessfullyReprocessed": "Anmodningen blev genbehandlet", + "DeniedRequest": "Anmodningen blev afvist", + "RequestCollection": "Anmod Om Samling", + "CollectionSuccesfullyAdded": "Samlingen {{name}} er blevet tilføjet!", + "NeedToSelectEpisodes": "Du skal vælge nogle episoder!", + "RequestAddedSuccessfully": "{{title}} er anmodet med succes", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", - "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "AlreadyRequested": "Dette er allerede blevet anmodet om", + "EpisodesAlreadyRequested": "Vi har allerede episoder anmodet fra denne serie", + "NoPermissionsOnBehalf": "Du har ikke de korrekte tilladelser til at anmode på vegne af brugere!", + "NoPermissions": "Du har ikke de nødvendige tilladelser!", + "RequestDoesNotExist": "Anmodningen eksisterer ikke", + "ChildRequestDoesNotExist": "Child-anmodning eksisterer ikke", + "NoPermissionsRequestMovie": "Du har ikke tilladelse til at anmode om en film", + "NoPermissionsRequestTV": "Du har ikke tilladelse til at anmode om en tv-serie", + "NoPermissionsRequestAlbum": "Du har ikke tilladelse til at anmode om et album", + "MovieRequestQuotaExceeded": "Du har overskredet din film-anmodningskvote!", + "TvRequestQuotaExceeded": "Du har overskredet din episode-anmodningskvote!", + "AlbumRequestQuotaExceeded": "Du har overskredet din album-anmodningskvote!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "Notify": "Giv besked", + "RemoveNotification": "Fjern Notifikationer", + "SuccessfulNotify": "Du vil nu få besked om titlen {{title}}", + "SuccessfulUnNotify": "Du vil ikke længere få besked om titlen {{title}}", + "CouldntNotify": "Titlen {{title}} kunne ikke meddeles" }, "Issues": { "Title": "Problemer", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Problemer for {{title}}", "PendingTitle": "Afventende problemer", "InProgressTitle": "Igangværende probemer", "ResolvedTitle": "Løste problemer", "ColumnTitle": "Titel", - "Count": "Count", + "Count": "Antal", "Category": "Kategori", "Status": "Status", "Details": "Detaljer", @@ -254,23 +263,23 @@ "WriteMessagePlaceholder": "Indtast din besked her...", "ReportedBy": "Anmeldt af", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Rapporter en fejl", + "DescriptionPlaceholder": "Beskriv venligst problemet", + "TitlePlaceholder": "Kort titel på dit problem", + "SelectCategory": "Vælg kategori", + "IssueCreated": "Problemet er oprettet" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Der er uafklarede problemer", + "ResolvedDate": "Løst dato", + "CreatedDate": "Oprettet den", + "MarkedAsResolved": "Dette problem er nu blevet markeret som løst!", + "MarkedAsInProgress": "Dette problem er markeret som igangværende!", + "Delete": "Slet problem", + "DeletedIssue": "Problemet er slettet", "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", - "UserOnDate": "{{user}} on {{date}}" + "EnterYourMessage": "Indtast din besked", + "Requested": "Anmodet", + "UserOnDate": "{{user}} d. {{date}}" }, "Filter": { "ClearFilter": "Nulstil filter", @@ -278,8 +287,8 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Godkendt", "PendingApproval": "Afventer godkendelse", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "WatchProviders": "Vælg udbydere", + "Keywords": "Nøgleord" }, "UserManagment": { "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", @@ -295,141 +304,143 @@ }, "MediaDetails": { "Denied": "Afvist", + "Denied4K": "Afvist 4K", "Trailers": "Trailers", - "RecommendationsTitle": "Recommendations", + "RecommendationsTitle": "Anbefalinger", "SimilarTitle": "Lignende", - "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", + "VideosTitle": "Video", + "AlbumsTitle": "Album", + "RequestAllAlbums": "Anmod Om Alle Albums", + "ClearSelection": "Ryd valgte", + "RequestSelectedAlbums": "Anmod Om Valgte Album", + "ViewCollection": "Vis Samling", + "NotEnoughInfo": "Der er desværre ikke nok information om dette show endnu!", + "AdvancedOptions": "Avancerede Indstillinger", + "AutoApproveOptions": "Du kan konfigurere anmodningen her. Når du har anmodet, vil den blive sendt til dit DVR program og vil blive godkendt automatisk! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning for at springe over!", + "AutoApproveOptionsTv": "Du kan konfigurere anmodningen her. Når du har anmodet vil den blive sendt til dit DVR program og vil blive auto godkendt automatisk! Hvis anmodningen allerede er i Sonarr, vil vi ikke ændre root-mappen eller kvalitetsprofilen, hvis du indstiller den! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning om at springe over!", + "AutoApproveOptionsTvShort": "Du kan konfigurere anmodningen her. Når du har anmodet vil den blive sendt til dit DVR program og vil blive auto godkendt automatisk! Hvis anmodningen allerede er i Sonarr, vil vi ikke ændre root-mappen eller kvalitetsprofilen, hvis du indstiller den! Bemærk venligst, at dette er valgfrit. Tryk blot på Anmodning om at springe over!", + "QualityProfilesSelect": "Vælg En kvalitetsprofil", + "RootFolderSelect": "Vælg en root mappe", + "LanguageProfileSelect": "Vælg En Sprogprofil", "Status": "Status:", "StatusValues": { - "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", - "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Rumored": "Rygtet", + "Planned": "Planlagt", + "In Production": "I Produktion", + "Post Production": "Postproduktion", + "Released": "Udgivet", + "Running": "Aktiv", + "Returning Series": "Tilbagevendende Serier", + "Ended": "Afsluttet", + "Canceled": "Annulleret" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", - "RequestStatus": "Request Status", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "Seasons": "Sæsoner:", + "Episodes": "Episoder:", + "Availability": "Tilgængelighed:", + "RequestStatus": "Status for anmodning", + "Quality": "Kvalitet:", + "RootFolderOverride": "Tilsidesæt rodmappe:", + "QualityOverride": "Tilsidesæt kvalitet:", + "Network": "Netværk:", + "GenresLabel": "Genre:", + "Genres": "Genre", + "FirstAired": "Sendt første gang:", + "TheatricalRelease": "Biografudgivelse:", + "DigitalRelease": "Digital Udgivelse:", + "Votes": "Stemmer:", + "Runtime": "Spilletid:", + "Minutes": "{{runtime}} minutter", + "Revenue": "Indtægter:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Nøgleord/Tags:", "Casts": { - "CastTitle": "Cast" + "CastTitle": "Medvirkende" }, "EpisodeSelector": { - "AllSeasonsTooltip": "This will request every season for this show", - "FirstSeasonTooltip": "This will only request the First Season for this show", - "LatestSeasonTooltip": "This will only request the Latest Season for this show", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "AllSeasonsTooltip": "Dette vil anmode om hver sæson for denne tv-serie", + "FirstSeasonTooltip": "Dette vil kun anmode om den første sæson for denne tv-serie", + "LatestSeasonTooltip": "Dette vil kun anmode den seneste sæson for denne tv-serie", + "NoEpisodes": "Der er desværre ingen episode data for denne tv-serie endnu!", + "SeasonNumber": "Sæson {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "SonarrConfiguration": "Konfiguration Af Sonarr", + "RadarrConfiguration": "Konfiguration Af Radarr", + "RequestOnBehalf": "Anmod på vegne af", + "PleaseSelectUser": "Vælg venligst en bruger", + "StreamingOn": "Streaming På:", + "RequestedBy": "Anmodet af:", + "RequestedByOn": "Anmodet af {{user}} d. {{date}}", + "RequestDate": "Dato for anmodning:", + "DeniedReason": "Afvisningsårsag:", + "ReProcessRequest": "Anmodning Om Genbehandling", + "ReProcessRequest4K": "Genbehandling af 4K Anmodning", "Music": { "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" + "Country": "Land:", + "StartDate": "Startdato:", + "EndDate": "Slutdato:" } }, "Discovery": { "PopularTab": "Populære", "TrendingTab": "Aktuelle", - "UpcomingTab": "Upcoming", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "UpcomingTab": "Kommende", + "SeasonalTab": "Sæsonbestemt", + "RecentlyRequestedTab": "Anmodet For Nyligt", "Movies": "Film", - "Combined": "Combined", + "Combined": "Kombineret", "Tv": "TV", "CardDetails": { "Availability": "Tilgængelighed", - "Studio": "Studio", - "Network": "Network", - "UnknownNetwork": "Unknown", - "RequestStatus": "Request Status", - "Director": "Director", - "InCinemas": "In Cinemas", - "FirstAired": "First Aired", - "Writer": "Writer", - "ExecProducer": "Exec Producer" + "Studio": "Studie", + "Network": "TV-netværk", + "UnknownNetwork": "Ukendt", + "RequestStatus": "Status for anmodning", + "Director": "Instruktør", + "InCinemas": "I Biografer", + "FirstAired": "Sendt første gang", + "Writer": "Skribent", + "ExecProducer": "Producer" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Vi fandt desværre ikke noget, der matcher din søgning!" }, "UserPreferences": { "Welcome": "Velkommen til {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "OmbiLanguage": "Sprog", + "DarkMode": "Mørk tilstand", + "Updated": "Opdateret", + "StreamingCountry": "Streaming Land", + "StreamingCountryDescription": "Dette er den landekode, som vi vil vise streaming information for. Hvis du er i USA, skal du vælge USA, og du vil få amerikanske relaterede streaming oplysninger.", + "LanguageDescription": "Dette er det sprog du gerne vil have Ombi grænsefladen skal vises i.", + "MobileQRCode": "Mobil QR Code", + "LegacyApp": "Start Gammel App", + "NoQrCode": "Kontakt venligst din administrator for at få adgang til QR koder", + "UserType": "Brugertype:", + "ChangeDetails": "Ændre detaljer", + "NeedCurrentPassword": "Vi behøver din nuværende adgangskode for at bekræfte dine ændringer", + "CurrentPassword": "Nuværende adgangskode", + "EmailAddress": "E-mail-adresse", + "NewPassword": "Ny adgangskode", + "NewPasswordConfirm": "Bekræft ny adgangskode", + "Security": "Sikkerhed", + "Profile": "Profil", + "UpdatedYourInformation": "Dine informationer blev opdateret", + "Unsubscribed": "Afmeldt!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", - "3": "Emby User", - "4": "Emby Connect User", - "5": "Jellyfin User" + "1": "Lokal Bruger", + "2": "Plex Bruger", + "3": "Emby Bruger", + "4": "Forbind Emby Bruger", + "5": "Jellyfin Bruger" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Elementer per side:", + "nextPageLabel": "Næste side", + "previousPageLabel": "Forrige side", + "firstPageLabel": "Første side", + "lastPageLabel": "Sidste side", + "rangePageLabel1": "0 af {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} af {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 50e5d4abe..18c5450c7 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Weiter", "Available": "Verfügbar", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "In 4K verfügbar", + "Approved": "Genehmigt", + "Approve4K": "4K genehmigen", + "Pending": "steht aus", "PartiallyAvailable": "Teilweise verfügbar", "Monitored": "Überwacht", "NotAvailable": "Nicht verfügbar", @@ -24,8 +26,10 @@ "RequestDenied": "Anfrage abgelehnt", "NotRequested": "Nicht angefordert", "Requested": "Angefordert", - "Search": "Search", + "Requested4K": "In 4K angefragt", + "Search": "Suche", "Request": "Anfrage", + "Request4K": "In 4K anfragen", "Denied": "Abgelehnt", "Approve": "Genehmigen", "PartlyAvailable": "Teilweise verfügbar", @@ -33,9 +37,9 @@ "Errors": { "Validation": "Bitte überprüfen Sie die eingegebenen Werte" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", + "Cancel": "Abbrechen", + "Submit": "Senden", + "Update": "Aktualisierung", "tvShow": "TV-Serie", "movie": "Filme", "album": "Album" @@ -66,7 +70,7 @@ "Issues": "Probleme", "Vote": "Bewerten", "Donate": "Spenden!", - "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", + "DonateLibraryMaintainer": "Spende Sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", "UpdateAvailableTooltip": "Update verfügbar!", "Settings": "Einstellungen", @@ -79,12 +83,12 @@ "Calendar": "Kalneder", "UserPreferences": "Einstellungen", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Sie haben eine tolle neue Idee? Schlagen Sie sie hier vor!", "Filter": { "Movies": "Filme", "TvShows": "Serien", "Music": "Musik", - "People": "People" + "People": "Personen" }, "MorningWelcome": "Guten Morgen!", "AfternoonWelcome": "Guten Tag!", @@ -92,11 +96,11 @@ }, "Search": { "Title": "Suche", - "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", + "Paragraph": "Sie möchten etwas sehen, das nicht verfügbar ist? Kein Problem, benutzen Sie einfach das Suchfeld und fordern Sie es an!", "MoviesTab": "Filme", "TvTab": "Serien", "MusicTab": "Musik", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", + "AdvancedSearch": "Sie können die unten stehenden Felder ausfüllen, um neue Medien zu entdecken. Alle Ergebnisse sind nach Beliebtheit sortiert", "AdvancedSearchHeader": "Erweiterte Suche", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", @@ -119,32 +123,32 @@ }, "TvShows": { "Popular": "Beliebt", - "Trending": "im Trend", + "Trending": "Im Trend", "MostWatched": "Meist gesehen", "MostAnticipated": "Meist erwartet", "Results": "Ergebnisse", "AirDate": "Veröffentlicht am:", "AllSeasons": "Alle Staffeln", - "FirstSeason": "erste Staffel", - "LatestSeason": "aktuellste Staffel", + "FirstSeason": "Erste Staffel", + "LatestSeason": "Aktuellste Staffel", "Select": "Wähle...", "SubmitRequest": "Anfrage einreichen", "Season": "Staffel {{seasonNumber}}", "SelectAllInSeason": "Markiere alles in Staffel {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", - "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + "AdvancedSearchInstructions": "Bitte wählen Sie aus, welche Art von Medien Sie suchen:", + "YearOfRelease": "Erscheinungsjahr", + "SearchGenre": "Genre suchen", + "SearchKeyword": "Schlagwort suchen", + "SearchProvider": "Anbieter suchen", + "KeywordSearchingDisclaimer": "Bitte beachten Sie, dass die Schlagwortsuche aufgrund der inkonsistenten Daten in TheMovieDb sehr unpräzise ist" }, "Requests": { "Title": "Anfragen", "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", "MoviesTab": "Filme", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Künstler", + "AlbumName": "Albumname", "TvTab": "Serien", "MusicTab": "Musik", "RequestedBy": "Angefordert von", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Stammordner ändern", "ChangeQualityProfile": "Qualitätsprofil ändern", "MarkUnavailable": "Als Nicht verfügbar markieren", + "MarkUnavailable4K": "4K als nicht verfügbar markieren", "MarkAvailable": "Als verfügbar markieren", + "MarkAvailable4K": "4K als verfügbar markieren", "Remove": "Entfernen", "Deny": "Ablehnen", + "Deny4K": "4K ablehnen", + "Has4KRequest": "Hat eine 4K Anfrage", "DenyReason": "Ablehnungsgrund", - "DeniedReason": "Denied Reason", + "DeniedReason": "Ablehnungsgrund", "Season": "Staffel", "GridTitle": "Titel", "AirDate": "Erstausstrahlung", @@ -187,18 +195,19 @@ "NextMinutes": "Eine weitere Anfrage wird in {{time}} Minuten hinzugefügt", "NextMinute": "Eine weitere Anfrage wird in {{time}} Minute hinzugefügt" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle Anfragen", + "PendingRequests": "Ausstehende Anfragen", + "ProcessingRequests": "Anfrage wird bearbeitet", + "AvailableRequests": "Verfügbare Anfragen", + "DeniedRequests": "Abgelehnte Anfragen", + "RequestsToDisplay": "Anzuzeigende Anfragen", "RequestsTitle": "Titel", "Details": "Details", - "Options": "Options", + "Options": "Optionen", "RequestPanel": { - "Delete": "Delete Request", + "Delete": "Anfrage löschen", "Approve": "Anfrage genehmigen", + "Approve4K": "4K Anfrage genehmigen", "ChangeAvailability": "Als verfügbar markieren", "Deleted": "Ausgewählte Elemente erfolgreich gelöscht", "Approved": "Ausgewählte Elemente erfolgreich freigegeben" @@ -207,40 +216,40 @@ "SuccessfullyDeleted": "Anfrage erfolgreich gelöscht", "NowAvailable": "Anfrage ist jetzt verfügbar", "NowUnavailable": "Anfrage ist jetzt verfügbar", - "SuccessfullyReprocessed": "Successfully Re-processed the request", + "SuccessfullyReprocessed": "Die Anfrage wurde erfolgreich neu verarbeitet", "DeniedRequest": "Abgelehnte Anfrage", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestCollection": "Anfrage Sammlung", + "CollectionSuccesfullyAdded": "Die Sammlung {{name}} wurde erfolgreich hinzugefügt!", + "NeedToSelectEpisodes": "Sie müssen einige Episoden auswählen!", + "RequestAddedSuccessfully": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "AlreadyRequested": "Dies ist bereits beantragt worden", + "EpisodesAlreadyRequested": "Wir haben bereits Episoden aus dieser Serie angefordert", + "NoPermissionsOnBehalf": "Sie haben nicht die richtigen Berechtigungen, um im Namen von Benutzern anzufragen!", + "NoPermissions": "Sie haben nicht die nötigen Rechte!", + "RequestDoesNotExist": "Die Anfrage existiert nicht", "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", - "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", - "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "NoPermissionsRequestMovie": "Sie haben keine Berechtigung, um einen Film anzufordern", + "NoPermissionsRequestTV": "Sie haben keine Berechtigung, um eine TV-Sendung anzufordern", + "NoPermissionsRequestAlbum": "Sie haben keine Berechtigung, um ein Album anzufordern", + "MovieRequestQuotaExceeded": "Sie haben Ihr Kontingent für Filmanfragen überschritten!", + "TvRequestQuotaExceeded": "Sie haben Ihr Kontingent für Episodenanfragen überschritten!", + "AlbumRequestQuotaExceeded": "Sie haben Ihr Kontingent für Albumanfragen überschritten!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "Notify": "Benachrichtigen", + "RemoveNotification": "Benachrichtigungen entfernen", + "SuccessfulNotify": "Sie werden nun für den Titel {{title}} benachrichtigt", + "SuccessfulUnNotify": "Sie werden für den Titel {{title}} nicht mehr benachrichtigt", + "CouldntNotify": "Konnte für den Titel {{title}} nicht benachrichtigen" }, "Issues": { "Title": "Probleme", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Probleme mit {{title}}", "PendingTitle": "Ausstehende Probleme", "InProgressTitle": "Probleme in bearbeitung", "ResolvedTitle": "Behobene Probleme", "ColumnTitle": "Titel", - "Count": "Count", + "Count": "Anzahl", "Category": "Kategorie", "Status": "Status", "Details": "Details", @@ -254,23 +263,23 @@ "WriteMessagePlaceholder": "Nachricht eingeben...", "ReportedBy": "Gemeldet von", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Ein Problem melden", + "DescriptionPlaceholder": "Bitte beschreibe dein Problem", + "TitlePlaceholder": "Kurzer Titel Ihres Tickets", + "SelectCategory": "Kategorie auswählen", + "IssueCreated": "Ticket wurde erstellt" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Es gibt ausstehende Probleme", + "ResolvedDate": "Gelöst am", + "CreatedDate": "Erstellt am", + "MarkedAsResolved": "Dieses Problem wurde jetzt als gelöst markiert!", + "MarkedAsInProgress": "Dieses Problem wurde jetzt als in Bearbeitung markiert!", + "Delete": "Problem löschen", + "DeletedIssue": "Ticket wurde gelöscht", "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", - "UserOnDate": "{{user}} on {{date}}" + "EnterYourMessage": "Geben Sie Ihre Nachricht ein", + "Requested": "Angefordert", + "UserOnDate": "{{user}} am {{date}}" }, "Filter": { "ClearFilter": "Filter zurücksetzen", @@ -278,8 +287,8 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Bestätigt", "PendingApproval": "Genehmigung ausstehend", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "WatchProviders": "Anbieter", + "Keywords": "Schlagwörter" }, "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} verbleibend", @@ -295,54 +304,55 @@ }, "MediaDetails": { "Denied": "Abgelehnt", + "Denied4K": "4K Abgelehnt", "Trailers": "Trailers", "RecommendationsTitle": "Empfehlungen", "SimilarTitle": "Ähnliche", "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", + "AlbumsTitle": "Alben", + "RequestAllAlbums": "Alle Alben anfragen", + "ClearSelection": "Auswahl leeren", + "RequestSelectedAlbums": "Ausgewählte Alben anfordern", + "ViewCollection": "Sammlung ansehen", + "NotEnoughInfo": "Leider gibt es noch nicht genügend Informationen über diese Serie!", + "AdvancedOptions": "Erweiterte Optionen", + "AutoApproveOptions": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet und automatisch genehmigt! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "AutoApproveOptionsTv": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet und automatisch genehmigt! Wenn die Anfrage bereits in Sonarr ist, werden wir den Stammordner oder das Qualitätsprofil nicht ändern, wenn Sie es einstellen! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "AutoApproveOptionsTvShort": "Sie können die Anfrage hier konfigurieren. Sobald die Anfrage gestellt ist, wird sie an Ihre DVR-Anwendung gesendet! Wenn die Anfrage bereits in Sonarr ist, werden wir den Stammordner oder das Qualitätsprofil nicht ändern, wenn Sie es einstellen! Bitte beachten Sie, dass dies optional ist, drücken Sie einfach auf Anfrage zum Überspringen!", + "QualityProfilesSelect": "Wähle ein Qualitätsprofil", + "RootFolderSelect": "Hauptverzeichnis auswählen", + "LanguageProfileSelect": "Wählen Sie ein Sprachprofil", "Status": "Status:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", + "Planned": "Geplant", + "In Production": "In Produktion", + "Post Production": "Postproduktion", + "Released": "Veröffentlicht", "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Returning Series": "Wiederkehrende Serie", + "Ended": "Beendet", + "Canceled": "Abgesagt" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Seasons": "Staffeln:", + "Episodes": "Episoden:", + "Availability": "Verfügbarkeit:", "RequestStatus": "Anfrage Status", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", + "Quality": "Qualität:", + "RootFolderOverride": "Stammverzeichnis Überschreiben:", + "QualityOverride": "Qualitäts Überschreiben:", + "Network": "Netzwerk:", "GenresLabel": "Genres:", "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "FirstAired": "Erstausstrahlung:", + "TheatricalRelease": "Kinostart:", + "DigitalRelease": "Digitale Veröffentlichung:", + "Votes": "Abstimmungen:", + "Runtime": "Laufzeit:", + "Minutes": "{{runtime}} Minuten", + "Revenue": "Einspielergebnis:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Schlagwörter/Tags:", "Casts": { "CastTitle": "Besetzung" }, @@ -350,34 +360,35 @@ "AllSeasonsTooltip": "Dies wird jede Saison für diese Show anfordern", "FirstSeasonTooltip": "Dies wird nur die erste Saison für diese Show anfordern", "LatestSeasonTooltip": "Dies wird nur die letzte Saison für diese Show anfordern", - "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "NoEpisodes": "Es gibt leider noch keine Episodendaten für diese Sendung!", + "SeasonNumber": "Staffel {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "SonarrConfiguration": "Sonarr Konfiguration", + "RadarrConfiguration": "Radarr Konfiguration", + "RequestOnBehalf": "Anfange im Namen von", + "PleaseSelectUser": "Bitte Benutzer auswählen", + "StreamingOn": "Wird gestreamt auf:", + "RequestedBy": "Angefordert von:", + "RequestedByOn": "Angefragt von {{user}} am {{date}}", + "RequestDate": "Datum der Anfrage:", + "DeniedReason": "Ablehnungsgrund:", + "ReProcessRequest": "Anfrage erneut bearbeiten", + "ReProcessRequest4K": "4K Anfrage erneut bearbeiten", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" + "Type": "Typ:", + "Country": "Land:", + "StartDate": "Startdatum:", + "EndDate": "Enddatum:" } }, "Discovery": { "PopularTab": "Beliebt", "TrendingTab": "Angesagt", "UpcomingTab": "Demnächst", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "SeasonalTab": "Saisonal", + "RecentlyRequestedTab": "Kürzlich angefragt", "Movies": "Filme", - "Combined": "Combined", + "Combined": "Kombiniert", "Tv": "TV", "CardDetails": { "Availability": "Verfügbarkeit", @@ -391,30 +402,30 @@ "Writer": "AutorIn", "ExecProducer": "Ausführender Produzent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Entschuldigung, nichts stimmt mit deiner Suche überein!" }, "UserPreferences": { "Welcome": "Willkommen {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", - "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "OmbiLanguage": "Sprache", + "DarkMode": "Dunkler Modus", + "Updated": "Erfolgreich aktualisiert", + "StreamingCountry": "Streaming Land", + "StreamingCountryDescription": "Dies ist der Ländercode, für den wir Streaming-Informationen anzeigen. Wenn Sie sich in den USA befinden, wählen Sie bitte US und Sie erhalten Streaming-Informationen für die USA.", + "LanguageDescription": "Dies ist die Sprache, in der Ombi angezeigt werden soll.", + "MobileQRCode": "Mobiler QR Code", + "LegacyApp": "Legacy-App starten", + "NoQrCode": "Bitte kontaktieren Sie Ihren Administrator, um QR-Codes zu aktivieren", + "UserType": "Benutzertyp:", + "ChangeDetails": "Details ändern", + "NeedCurrentPassword": "Sie benötigen Ihr aktuelles Passwort, um hier Änderungen vorzunehmen", + "CurrentPassword": "Aktuelles Passwort", + "EmailAddress": "E-Mail-Adresse", + "NewPassword": "Neues Passwort", + "NewPasswordConfirm": "Neues Passwort bestätigen", + "Security": "Sicherheit", + "Profile": "Profil", + "UpdatedYourInformation": "Aktualisieren Sie Ihre Informationen", + "Unsubscribed": "Abbestellt!" }, "UserTypeLabel": { "1": "Local User", @@ -424,12 +435,12 @@ "5": "Jellyfin User" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Elemente pro Seite:", + "nextPageLabel": "Nächste Seite", + "previousPageLabel": "Vorherige Seite", + "firstPageLabel": "Erste Seite", + "lastPageLabel": "Letzte Seite", + "rangePageLabel1": "0 von {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} von {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 8fc14d0d5..fb2ba4149 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continuar", "Available": "Disponible", + "Available4K": "Disponible 4K", "Approved": "Aprobado", + "Approve4K": "Aprobar 4K", "Pending": "Pendiente", "PartiallyAvailable": "Disponible parcialmente", "Monitored": "Monitoreado", @@ -24,8 +26,10 @@ "RequestDenied": "Solicitud denegada", "NotRequested": "No solicitado", "Requested": "Solicitado", + "Requested4K": "Solicitado 4K", "Search": "Buscar", "Request": "Solicitar", + "Request4K": "Solicitar 4K", "Denied": "Denegado", "Approve": "Aprobar", "PartlyAvailable": "Disponible parcialmente", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Carpeta raíz", "ChangeQualityProfile": "Perfil de calidad", "MarkUnavailable": "Marcar como no disponible", + "MarkUnavailable4K": "Marcar No Disponible 4K", "MarkAvailable": "Marcar Disponible", + "MarkAvailable4K": "Marcar Disponible 4K", "Remove": "Eliminar", "Deny": "Denegar", + "Deny4K": "Rechazar 4K", + "Has4KRequest": "Tiene Solicitud 4K", "DenyReason": "Razón Denegada", "DeniedReason": "Motivo de denegación", "Season": "Temporada", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Eliminar solicitud", "Approve": "Aprobar Solicitud", + "Approve4K": "Aprobar Solicitud 4K", "ChangeAvailability": "Marcar como disponible", "Deleted": "Los elementos seleccionados ha sido eliminados correctamente", "Approved": "Los elementos seleccionados ha sido aprobados correctamente" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Denegado", + "Denied4K": "Rechazado 4K", "Trailers": "Trailer", "RecommendationsTitle": "Recomendaciones", "SimilarTitle": "Similar", @@ -363,6 +373,7 @@ "RequestDate": "Fecha de solicitud:", "DeniedReason": "Motivo de denegación:", "ReProcessRequest": "Re-procesar solicitud", + "ReProcessRequest4K": "Reprocesar Solicitud 4K", "Music": { "Type": "Tipo:", "Country": "País:", diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 298a87aba..ab2bdff7c 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continuer", "Available": "Disponible", + "Available4K": "4K disponible", "Approved": "Approuvée", + "Approve4K": "Approuver 4K", "Pending": "En attente", "PartiallyAvailable": "Partiellement disponible", "Monitored": "Suivi", @@ -24,8 +26,10 @@ "RequestDenied": "Demande refusée", "NotRequested": "Non demandé", "Requested": "Demandé", + "Requested4K": "4K demandée", "Search": "Rechercher", "Request": "Demander", + "Request4K": "Demander en 4K", "Denied": "Refusé", "Approve": "Approuver", "PartlyAvailable": "Partiellement disponible", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Répertoire racine", "ChangeQualityProfile": "Profil de qualité", "MarkUnavailable": "Marquer indisponible", + "MarkUnavailable4K": "Marquer 4K indisponible", "MarkAvailable": "Marquer disponible", + "MarkAvailable4K": "Marquer 4K disponible", "Remove": "Supprimer", "Deny": "Refuser", + "Deny4K": "Refuser 4K", + "Has4KRequest": "A une demande 4K", "DenyReason": "Motif de refus", "DeniedReason": "Motif de refus", "Season": "Saison", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Supprimer la demande", "Approve": "Approuver la demande", + "Approve4K": "Approuver la demande 4K", "ChangeAvailability": "Marquer comme Disponible", "Deleted": "Éléments sélectionnés supprimés avec succès", "Approved": "Éléments sélectionnés approuvés avec succès" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Refusé", + "Denied4K": "4K refusée", "Trailers": "Bandes-annonces", "RecommendationsTitle": "Recommandations", "SimilarTitle": "Similaires", @@ -363,6 +373,7 @@ "RequestDate": "Date de la demande :", "DeniedReason": "Motif de refus :", "ReProcessRequest": "Refaire une demande", + "ReProcessRequest4K": "Retraiter la demande 4K", "Music": { "Type": "Type :", "Country": "Pays :", diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 7797e1318..45d8622a5 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Tovább", "Available": "Elérhető", + "Available4K": "Available 4K", "Approved": "Jóváhagyva", + "Approve4K": "Approve 4K", "Pending": "Függőben", "PartiallyAvailable": "Részlegesen elérhető", "Monitored": "Figyelve", @@ -24,8 +26,10 @@ "RequestDenied": "Kérés megtagadva", "NotRequested": "Nincs kérve", "Requested": "Kérve", + "Requested4K": "Requested 4K", "Search": "Keresés", "Request": "Kérés", + "Request4K": "Request 4K", "Denied": "Megtagadva", "Approve": "Jóváhagyva", "PartlyAvailable": "Részlegesen elérhető", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Gyökér mappa", "ChangeQualityProfile": "Minőség profil", "MarkUnavailable": "Megjelölés nem elérhetőnek", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Megjelölés elérhetőnek", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Törlés", "Deny": "Elutasítás", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Elutasítási ok", "DeniedReason": "Elutasítás oka", "Season": "Évad", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Kérés törlése", "Approve": "Kérés elfogadása", + "Approve4K": "Approve 4K Request", "ChangeAvailability": "Elérhetőnek jelölés", "Deleted": "A kijelölt elemek törlésre kerultek", "Approved": "A kijelölt elemek jóváhagyásra kerultek" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Megtagadva", + "Denied4K": "Denied 4K", "Trailers": "Előzetesek", "RecommendationsTitle": "Ajánlások", "SimilarTitle": "Hasonló", @@ -363,6 +373,7 @@ "RequestDate": "Kérés ideje:", "DeniedReason": "Elutasítás oka:", "ReProcessRequest": "Kérés újrafeldolgozása", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Típus:", "Country": "Ország:", diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index d1c910b66..ed69c02e0 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Continua", "Available": "Disponibile", + "Available4K": "Disponibile 4K", "Approved": "Approvato", + "Approve4K": "Approva 4K", "Pending": "In Sospeso", "PartiallyAvailable": "Parzialmente disponibile", "Monitored": "Monitorato", @@ -24,8 +26,10 @@ "RequestDenied": "Richiesta negata", "NotRequested": "Non richiesta", "Requested": "Richiesta", + "Requested4K": "Richiesto 4K", "Search": "Cerca", "Request": "Richiesta", + "Request4K": "Richiedi 4K", "Denied": "Negata", "Approve": "Approva", "PartlyAvailable": "Parzialmente disponibile", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Cartella radice", "ChangeQualityProfile": "Profilo qualità", "MarkUnavailable": "Rendi non disponibile", + "MarkUnavailable4K": "Rendi 4K non disponibile", "MarkAvailable": "Rendi disponibile", + "MarkAvailable4K": "Rendi 4K disponibile", "Remove": "Rimuovi", "Deny": "Nega", + "Deny4K": "Nega 4K", + "Has4KRequest": "Ha una Richiesta 4K", "DenyReason": "Nega Motivo", "DeniedReason": "Motivo di Negazione", "Season": "Stagione", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Elimina Richiesta", "Approve": "Approva Richiesta", + "Approve4K": "Approva Richiesta 4K", "ChangeAvailability": "Segna come Disponibile", "Deleted": "Elementi selezionati eliminati correttamente", "Approved": "Elementi selezionati approvati correttamente" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Rifiutato", + "Denied4K": "4K Negato", "Trailers": "Trailer", "RecommendationsTitle": "Raccomandazioni", "SimilarTitle": "Simili", @@ -363,6 +373,7 @@ "RequestDate": "Data di Richiesta:", "DeniedReason": "Motivo di Negazione:", "ReProcessRequest": "Ri-Elabora Richiesta", + "ReProcessRequest4K": "Ri-Elabora Richiesta 4K", "Music": { "Type": "Tipo:", "Country": "Paese:", diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 801f48479..33e311928 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Gebruikersnaam", "PasswordPlaceholder": "Wachtwoord", "RememberMe": "Onthoud Mij", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Inloggen met {{appName}}", + "SignInWithPlex": "Inloggen met Plex", "ForgottenPassword": "Wachtwoord vergeten?", "Errors": { "IncorrectCredentials": "Onjuiste gebruikersnaam of wachtwoord" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Doorgaan", "Available": "Beschikbaar", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Available 4K", + "Approved": "Goedgekeurd", + "Approve4K": "Approve 4K", + "Pending": "In afwachting", "PartiallyAvailable": "Deels Beschikbaar", "Monitored": "Gemonitord", "NotAvailable": "Niet Beschikbaar", @@ -24,8 +26,10 @@ "RequestDenied": "Verzoek geweigerd", "NotRequested": "Niet verzocht", "Requested": "Aangevraagd", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Zoeken", "Request": "Aanvragen", + "Request4K": "Request 4K", "Denied": "Afgewezen", "Approve": "Accepteer", "PartlyAvailable": "Deels Beschikbaar", @@ -33,11 +37,11 @@ "Errors": { "Validation": "Controleer de ingevulde waardes" }, - "Cancel": "Cancel", - "Submit": "Submit", + "Cancel": "Annuleren", + "Submit": "Verzenden", "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "tvShow": "Tv programma", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -79,16 +83,16 @@ "Calendar": "Agenda", "UserPreferences": "Instellingen", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Heb je een geweldig nieuw idee? Stel het hier voor!", "Filter": { "Movies": "Films", "TvShows": "TV Series", "Music": "Muziek", - "People": "People" + "People": "Personen" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Goedemorgen!", + "AfternoonWelcome": "Goedemiddag!", + "EveningWelcome": "Goedenavond!" }, "Search": { "Title": "Zoeken", @@ -104,7 +108,7 @@ "TheatricalRelease": "Bioscoop Uitgave: {{date}}", "ViewOnPlex": "Bekijk op Plex", "ViewOnEmby": "Bekijk op Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Afspelen op Jellyfin", "RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd", "Similar": "Vergelijkbaar", "Refine": "Verfijn", @@ -143,8 +147,8 @@ "Title": "Verzoeken", "Paragraph": "Hieronder zie je jouw en alle andere verzoeken, evenals hun download en goedkeuring status.", "MoviesTab": "Films", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Artiest", + "AlbumName": "Albumnaam", "TvTab": "TV Series", "MusicTab": "Muziek", "RequestedBy": "Verzocht Door", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Hoofdmap wijzigen", "ChangeQualityProfile": "Kwaliteitsprofiel wijzigen", "MarkUnavailable": "Markeren als onbeschikbaar", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Markeren als beschikbaar", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Verwijderen", "Deny": "Weigeren", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Reden van afwijzing", "DeniedReason": "Denied Reason", "Season": "Seizoen", @@ -187,19 +195,20 @@ "NextMinutes": "Een ander verzoek zal worden toegevoegd in {{time}} Minuten", "NextMinute": "Een ander verzoek zal worden toegevoegd in {{time}} Minuut" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Alle verzoeken", + "PendingRequests": "Lopende verzoeken", + "ProcessingRequests": "Verzoeken in behandeling", + "AvailableRequests": "Beschikbare verzoeken", + "DeniedRequests": "Geweigerde verzoeken", + "RequestsToDisplay": "Verzoeken om weer te geven", "RequestsTitle": "Titel", "Details": "Details", - "Options": "Options", + "Options": "Opties", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Delete": "Verwijder Verzoek", + "Approve": "Verzoek Goedkeuren", + "Approve4K": "Approve 4K Request", + "ChangeAvailability": "Markeer beschikbaar", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" }, @@ -212,7 +221,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Aanvraag voor {{title}} is succesvol toegevoegd", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -254,22 +263,22 @@ "WriteMessagePlaceholder": "Schrijf hier je bericht...", "ReportedBy": "Gerapporteerd door", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Meld een probleem", + "DescriptionPlaceholder": "Beschrijf het probleem", + "TitlePlaceholder": "Korte titel van het probleem", + "SelectCategory": "Selecteer categorie", + "IssueCreated": "Probleem is ingediend" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", + "Outstanding": "Er zijn nog openstaande problemen", + "ResolvedDate": "Oplosdatum", + "CreatedDate": "Ingediend op", + "MarkedAsResolved": "Dit probleem is nu gemarkeerd als opgelost!", + "MarkedAsInProgress": "Dit probleem is nu gemarkeerd als in behandeling!", + "Delete": "Verwijder probleem", + "DeletedIssue": "Probleem is verwijderd", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Aangevraagd", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,22 +304,23 @@ }, "MediaDetails": { "Denied": "Afgewezen", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Aanbevelingen", "SimilarTitle": "Vergelijkbaar", "VideosTitle": "Video's", "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "RequestAllAlbums": "Verzoek alle albums", + "ClearSelection": "Wis selectie", + "RequestSelectedAlbums": "Verzoek geselecteerde albums", + "ViewCollection": "Bekijk collectie", + "NotEnoughInfo": "Helaas is er nog niet genoeg informatie over deze tv-serie!", + "AdvancedOptions": "Geavanceerde opties", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", + "QualityProfilesSelect": "Selecteer een kwaliteitsprofiel", + "RootFolderSelect": "Selecteer een hoofdmap", "LanguageProfileSelect": "Select A Language Profile", "Status": "Status:", "StatusValues": { @@ -325,24 +335,24 @@ "Canceled": "Canceled" }, "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Episodes": "Afleveringen:", + "Availability": "Beschikbaarheid:", "RequestStatus": "Aanvraagstatus", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", + "Quality": "Kwaliteit:", + "RootFolderOverride": "Hoofdmap overschrijven:", + "QualityOverride": "Kwaliteit overschrijven:", + "Network": "Netwerk:", "GenresLabel": "Genres:", "Genres": "Genres", - "FirstAired": "First Aired:", + "FirstAired": "Eerste uitzending:", "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", + "DigitalRelease": "Digitale release:", + "Votes": "Stemmen:", + "Runtime": "Looptijd:", + "Minutes": "{{runtime}} minuten", + "Revenue": "Omzet:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Trefwoorden/Labels:", "Casts": { "CastTitle": "Acteurs" }, @@ -351,18 +361,19 @@ "FirstSeasonTooltip": "Dit verzoekt alleen het eerste seizoen van deze serie", "LatestSeasonTooltip": "Dit verzoekt alleen het laatste seizoen van deze show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Seizoen {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Sonarr configuratie", + "RadarrConfiguration": "Radarr configuratie", + "RequestOnBehalf": "Verzoek namens", + "PleaseSelectUser": "Selecteer een gebruiker", + "StreamingOn": "Streamt op:", + "RequestedBy": "Verzocht Door:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Aanvraag Datum:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", @@ -377,7 +388,7 @@ "SeasonalTab": "Seasonal", "RecentlyRequestedTab": "Recently Requested", "Movies": "Films", - "Combined": "Combined", + "Combined": "Gecombineerd", "Tv": "TV", "CardDetails": { "Availability": "Beschikbaarheid", @@ -391,24 +402,24 @@ "Writer": "Schrijver", "ExecProducer": "Uitvoerende producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Sorry, niks komt overeen met jou zoekopdracht!" }, "UserPreferences": { "Welcome": "Welkom {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", + "OmbiLanguage": "Taal", + "DarkMode": "Donkere Modus", + "Updated": "Succesvol bijgewerkt", + "StreamingCountry": "Streaming Land", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", + "LanguageDescription": "Dit is de taal waarin Ombi in wordt weergegeven.", + "MobileQRCode": "QR code voor mobiel", + "LegacyApp": "Start legacy app", "NoQrCode": "Please contact your administrator to enable QR codes", "UserType": "User Type:", "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-mail adres", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 41e027c37..ab409a431 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Brukernavn", "PasswordPlaceholder": "Passord", "RememberMe": "Husk meg", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Logg inn med {{appName}}", + "SignInWithPlex": "Logg inn med Plex", "ForgottenPassword": "Glemt passord?", "Errors": { "IncorrectCredentials": "Ugyldig brukernavn eller passord" @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Gå videre", "Available": "Tilgjengelig", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Godkjent", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Delvis tilgjengelig", "Monitored": "Overvåket", @@ -24,16 +26,18 @@ "RequestDenied": "Forespørsel avslått", "NotRequested": "Ikke forespurt", "Requested": "Forespurt", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Søk", "Request": "Forespørsel", + "Request4K": "Request 4K", "Denied": "Avslått", "Approve": "Godkjenn", "PartlyAvailable": "Delvis tilgjengelig", - "ViewDetails": "View Details", + "ViewDetails": "Vis detaljer", "Errors": { "Validation": "Kontroller de angitte verdiene" }, - "Cancel": "Cancel", + "Cancel": "Avbryt", "Submit": "Submit", "Update": "Update", "tvShow": "TV Show", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Endre rotmappe", "ChangeQualityProfile": "Endre kvalitetsprofil", "MarkUnavailable": "Merk utilgjengelig", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Merk tilgjengelig", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Fjern", "Deny": "Avslå", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Sesong", @@ -199,7 +207,8 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Approve4K": "Approve 4K Request", + "ChangeAvailability": "Merk tilgjengelig", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" }, @@ -212,7 +221,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Forespørsel om {{title}} er lagt til", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +278,7 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Forespurt", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Avslått", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Lignende", @@ -326,16 +336,16 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Tilgjengelighet:", "RequestStatus": "Request Status", "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", + "RootFolderOverride": "Overstyring av rotmappe:", + "QualityOverride": "Overstyr kvalitet:", "Network": "Network:", "GenresLabel": "Genres:", "Genres": "Genres", "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", + "TheatricalRelease": "Kinopremiere:", "DigitalRelease": "Digital Release:", "Votes": "Votes:", "Runtime": "Runtime:", @@ -351,18 +361,19 @@ "FirstSeasonTooltip": "This will only request the First Season for this show", "LatestSeasonTooltip": "This will only request the Latest Season for this show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Sesong {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "RequestedBy": "Etterspurt av:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Dato for forespørsel:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", @@ -408,7 +419,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-postadresse", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index e1a2ad62e..756c2658c 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Nazwa użytkownika", "PasswordPlaceholder": "Hasło", "RememberMe": "Zapamiętaj mnie", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Zaloguj się z {{appName}}", + "SignInWithPlex": "Zaloguj się z Plex", "ForgottenPassword": "Nie pamiętasz hasła?", "Errors": { "IncorrectCredentials": "Nieprawidłowa nazwa użytkownika lub hasło" @@ -14,8 +14,10 @@ "Common": { "ContinueButton": "Kontynuuj", "Available": "Dostępne", - "Approved": "Approved", - "Pending": "Pending", + "Available4K": "Dostępne 4K", + "Approved": "Zatwierdzone", + "Approve4K": "Zatwierdź 4K", + "Pending": "Oczekuje", "PartiallyAvailable": "Częściowo dostępne", "Monitored": "Monitorowane", "NotAvailable": "Niedostępne", @@ -24,8 +26,10 @@ "RequestDenied": "Zgłoszenie odrzucone", "NotRequested": "Niezgłoszone", "Requested": "Zgłoszone", - "Search": "Search", + "Requested4K": "Żądane 4K", + "Search": "Szukaj", "Request": "Zgłoszenie", + "Request4K": "Żądanie 4K", "Denied": "Odrzucone", "Approve": "Zatwierdź", "PartlyAvailable": "Częściowo dostępne", @@ -33,11 +37,11 @@ "Errors": { "Validation": "Proszę sprawdzić wprowadzone wartości" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Anuluj", + "Submit": "Wyślij", + "Update": "Aktualizacja", + "tvShow": "Serial", + "movie": "Film", "album": "Album" }, "PasswordReset": { @@ -56,7 +60,7 @@ "CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Nie znaleziono strony" }, "NavigationBar": { "Discover": "Odkryj", @@ -79,16 +83,16 @@ "Calendar": "Kalendarz", "UserPreferences": "Preferencje", "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "FeatureSuggestionTooltip": "Masz świetny nowy pomysł? Zaproponuj go tutaj!", "Filter": { "Movies": "Filmy", "TvShows": "Programy TV", "Music": "Muzyka", - "People": "People" + "People": "Osoby" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Dzień dobry!", + "AfternoonWelcome": "Dzień dobry!", + "EveningWelcome": "Dobry wieczór!" }, "Search": { "Title": "Szukaj", @@ -96,15 +100,15 @@ "MoviesTab": "Filmy", "TvTab": "Seriale", "MusicTab": "Muzyka", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearch": "Możesz wypełnić dowolny z poniższych wpisów, aby odkryć nowe media. Wszystkie wyniki są posortowane według popularności", + "AdvancedSearchHeader": "Zaawansowane wyszukiwanie", "Suggestions": "Sugestie", "NoResults": "Niestety nic nie znaleziono!", "DigitalDate": "Wydanie cyfrowe: {{date}}", "TheatricalRelease": "Premiera kinowa: {{date}}", "ViewOnPlex": "Obejrzyj w Plex", "ViewOnEmby": "Obejrzyj w Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Odtwórz w Jellyfin", "RequestAdded": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", "Similar": "Podobne", "Refine": "Zawęź", @@ -132,19 +136,19 @@ "Season": "Sezon {{seasonNumber}}", "SelectAllInSeason": "Wybierz wszystkie w sezonie {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", + "AdvancedSearchInstructions": "Wybierz jakiego rodzaju mediów szukasz:", + "YearOfRelease": "Rok wydania", "SearchGenre": "Search Genre", "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", + "SearchProvider": "Dostawcy wyszukiwania", "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { "Title": "Zgłoszenia", "Paragraph": "Poniżej znajdują się Twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", "MoviesTab": "Filmy", - "ArtistName": "Artist", - "AlbumName": "Album Name", + "ArtistName": "Wykonawca", + "AlbumName": "Nazwa albumu", "TvTab": "Seriale", "MusicTab": "Muzyka", "RequestedBy": "Zgłoszone przez", @@ -161,11 +165,15 @@ "ChangeRootFolder": "Folder główny", "ChangeQualityProfile": "Profil jakości", "MarkUnavailable": "Oznacz jako niedostępne", + "MarkUnavailable4K": "Oznacz jako niedostępne 4K", "MarkAvailable": "Oznacz jako dostępne", + "MarkAvailable4K": "Oznacz jako Dostępne 4K", "Remove": "Usuń", "Deny": "Odrzuć", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Powód odrzucenia", - "DeniedReason": "Denied Reason", + "DeniedReason": "Powód odrzucenia", "Season": "Sezon", "GridTitle": "Tytuł", "AirDate": "Data emisji", @@ -187,55 +195,56 @@ "NextMinutes": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)", "NextMinute": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", + "AllRequests": "Wszystkie zgłoszenia", + "PendingRequests": "Zgłoszenia oczekujące", + "ProcessingRequests": "Zgłoszenia przetwarzane", + "AvailableRequests": "Zgłoszenia dostępne", + "DeniedRequests": "Zgłoszenia odrzucone", + "RequestsToDisplay": "Zgłoszenia do wyświetlenia", "RequestsTitle": "Tytuł", "Details": "Szczegóły", - "Options": "Options", + "Options": "Opcje", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Usuń zgłoszenie", + "Approve": "Zatwierdź zgłoszenie", + "Approve4K": "Zatwierdź prośbę o 4K", + "ChangeAvailability": "Ozn. jako dostępne", + "Deleted": "Pomyślnie usunięto wybrane elementy", + "Approved": "Pomyślnie zatwierdzono wybrane elementy" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", + "SuccessfullyApproved": "Zatwierdzono pomyślnie", + "SuccessfullyDeleted": "Prośba pomyślnie usunięta", "NowAvailable": "Request is now available", "NowUnavailable": "Request is now unavailable", "SuccessfullyReprocessed": "Successfully Re-processed the request", "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", + "RequestCollection": "Poproś o kolekcję", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "NeedToSelectEpisodes": "Musisz wybrać jakieś odcinki!", + "RequestAddedSuccessfully": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "RequestDoesNotExist": "Żądanie nie istnieje", "ChildRequestDoesNotExist": "Child Request does not exist", "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "TvRequestQuotaExceeded": "Przekroczyłeś limit próśb odcinków!", + "AlbumRequestQuotaExceeded": "Przekroczyłeś limit próśb Albumów!" }, - "Notify": "Notify", - "RemoveNotification": "Remove Notifications", - "SuccessfulNotify": "You will now be notified for title {{title}}", + "Notify": "Powiadomienie", + "RemoveNotification": "Usuń powiadomienia", + "SuccessfulNotify": "Teraz otrzymasz powiadomienie o tytule {{title}}", "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemy", - "IssuesForTitle": "Issues for {{title}}", + "IssuesForTitle": "Zgłoszenie dla {{title}}", "PendingTitle": "Oczekujące problemy", "InProgressTitle": "Problemy w trakcie", "ResolvedTitle": "Problemy rozwiązane", @@ -254,22 +263,22 @@ "WriteMessagePlaceholder": "Tutaj wpisz swoją wiadomość…", "ReportedBy": "Zgłoszone przez", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Zgłoś problem", + "DescriptionPlaceholder": "Proszę opisać problem", + "TitlePlaceholder": "Krótki tytuł Twojego problemu", + "SelectCategory": "Wybierz kategorię", + "IssueCreated": "Problem został zgłoszony" }, - "Outstanding": "There are outstanding issues", - "ResolvedDate": "Resolved date", - "CreatedDate": "Raised on", - "MarkedAsResolved": "This issue has now been marked as resolved!", - "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted", - "Chat": "Chat", - "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Outstanding": "Występują zaległe problemy", + "ResolvedDate": "Data rozwiązania", + "CreatedDate": "Zgłoszony", + "MarkedAsResolved": "Ten problem został oznaczony jako rozwiązany!", + "MarkedAsInProgress": "Ten problem został oznaczony jako rozwiązywany!", + "Delete": "Usuń zgłoszenie", + "DeletedIssue": "Problem został usunięty", + "Chat": "Czat", + "EnterYourMessage": "Wpisz swoją wiadomość", + "Requested": "Zgłoszone", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -279,7 +288,7 @@ "Approved": "Zatwierdzone", "PendingApproval": "Oczekujące na zatwierdzenie", "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "Keywords": "Słowa kluczowe" }, "UserManagment": { "TvRemaining": "Seriale: pozostało {{remaining}}/{{total}}", @@ -295,54 +304,55 @@ }, "MediaDetails": { "Denied": "Odrzucone", - "Trailers": "Trailers", + "Denied4K": "Denied 4K", + "Trailers": "Zwiastuny", "RecommendationsTitle": "Rekomendacje", "SimilarTitle": "Podobne", "VideosTitle": "Wideo", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "AlbumsTitle": "Albumy", + "RequestAllAlbums": "Zgłoś wszystkie albumy", + "ClearSelection": "Wyczyść zaznaczenie", + "RequestSelectedAlbums": "Zgłoś zaznaczone albumy", + "ViewCollection": "Pokaż kolekcję", + "NotEnoughInfo": "Niestety nie ma jeszcze wystarczających informacji na temat tego serialu!", + "AdvancedOptions": "Opcje zaawansowane", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", + "QualityProfilesSelect": "Wybierz profil jakości", + "RootFolderSelect": "Wybierz katalog główny", "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "Status": "Stan:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", + "Planned": "Planowany", "In Production": "In Production", "Post Production": "Post Production", - "Released": "Released", + "Released": "Wydany", "Running": "Running", "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Ended": "Zakończono", + "Canceled": "Anulowano" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", + "Seasons": "Sezony:", + "Episodes": "Odcinków:", + "Availability": "Dostępność:", "RequestStatus": "Status zgłoszenia", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Quality": "Jakość:", + "RootFolderOverride": "Wymuszenie folderu głównego:", + "QualityOverride": "Wymuszenie jakości:", + "Network": "Stacja:", + "GenresLabel": "Gatunki:", + "Genres": "Gatunki", + "FirstAired": "Pierwsza emisja:", + "TheatricalRelease": "Premiera kinowa:", + "DigitalRelease": "Wydanie cyfrowe:", + "Votes": "Głosy:", + "Runtime": "Czas trwania:", + "Minutes": "{{runtime}} minut(y)", + "Revenue": "Przychód:", + "Budget": "Budżet:", + "Keywords": "Słowa kluczowe/tagi:", "Casts": { "CastTitle": "Obsada" }, @@ -351,23 +361,24 @@ "FirstSeasonTooltip": "Zgłoszenie obejmie pierwszy sezon tego serialu", "LatestSeasonTooltip": "Zgłoszenie obejmie najnowszy sezon tego serialu", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Sezon {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Konfiguracja Sonarr", + "RadarrConfiguration": "Konfiguracja Radarr", + "RequestOnBehalf": "Zgłoszenie w imieniu", + "PleaseSelectUser": "Proszę wybrać użytkownika", + "StreamingOn": "Strumieniowane w:", + "RequestedBy": "Zgłoszone przez:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Data zgłoszenia:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" + "Type": "Typ:", + "Country": "Kraj:", + "StartDate": "Data rozpoczęcia:", + "EndDate": "Data zakończenia:" } }, "Discovery": { @@ -375,10 +386,10 @@ "TrendingTab": "Zyskujące popularność", "UpcomingTab": "Nadchodzące", "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", + "RecentlyRequestedTab": "Ostatnie prośby", "Movies": "Filmy", - "Combined": "Combined", - "Tv": "TV", + "Combined": "Połączone", + "Tv": "Seriale", "CardDetails": { "Availability": "Dostępność", "Studio": "Studio", @@ -391,45 +402,45 @@ "Writer": "Scenarzysta", "ExecProducer": "Producent wykonawczy" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Przepraszamy, nic nie pasuje do Twojego wyszukiwania!" }, "UserPreferences": { "Welcome": "Witaj {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", - "StreamingCountry": "Streaming Country", + "OmbiLanguage": "Język", + "DarkMode": "Tryb ciemny", + "Updated": "Zaktualizowano pomyślnie", + "StreamingCountry": "Kraj strumieniowania", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", - "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", + "LanguageDescription": "To jest język, w którym ma być wyświetlany interfejs Ombi.", + "MobileQRCode": "Kod QR z telefonu", + "LegacyApp": "Uruchom starszą aplikację", "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", + "UserType": "Typ Użytkownika:", "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "NeedCurrentPassword": "Potrzebujesz swojego aktualnego hasła, aby potwierdzić zmiany", + "CurrentPassword": "Obecne hasło", + "EmailAddress": "Adres e-mail", + "NewPassword": "Nowe Hasło", + "NewPasswordConfirm": "Potwierdź nowe hasło", + "Security": "Ochrona", + "Profile": "Profil", + "UpdatedYourInformation": "Zaktualizuj swoje informacje", + "Unsubscribed": "Subskrypcja anulowana!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", - "3": "Emby User", + "1": "Użytkownik lokalny", + "2": "Użytkownik Plex", + "3": "Użytkownik Emby", "4": "Emby Connect User", - "5": "Jellyfin User" + "5": "Użytkownik Jellyfin" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Wpisów na stronie:", + "nextPageLabel": "Następna strona", + "previousPageLabel": "Poprzednia strona", + "firstPageLabel": "Pierwsza strona", + "lastPageLabel": "Ostatnia Strona", + "rangePageLabel1": "0 z {{length}}", + "rangePageLabel2": "{{startIndex}} - {{endIndex}} z {{length}}" } } diff --git a/src/Ombi/wwwroot/translations/pt-BR.json b/src/Ombi/wwwroot/translations/pt-BR.json new file mode 100644 index 000000000..899c42281 --- /dev/null +++ b/src/Ombi/wwwroot/translations/pt-BR.json @@ -0,0 +1,446 @@ +{ + "Login": { + "SignInButton": "Iniciar sessão", + "UsernamePlaceholder": "Nome de usuário", + "PasswordPlaceholder": "Senha", + "RememberMe": "Lembrar-me", + "SignInWith": "Entre com {{appName}}", + "SignInWithPlex": "Iniciar sessão com Plex", + "ForgottenPassword": "Esqueceu sua senha?", + "Errors": { + "IncorrectCredentials": "Nome de usuário ou senha incorretos" + } + }, + "Common": { + "ContinueButton": "Continuar", + "Available": "Disponível", + "Available4K": "Disponível", + "Approved": "Aprovado", + "Approve4K": "Aprovar", + "Pending": "Pendente", + "PartiallyAvailable": "Parcialmente Disponível", + "Monitored": "Monitorado", + "NotAvailable": "Não Disponível", + "ProcessingRequest": "Processando Solicitação", + "PendingApproval": "Aprovação Pendente", + "RequestDenied": "Solicitação Negada", + "NotRequested": "Não Solicitado", + "Requested": "Solicitado", + "Requested4K": "4K requisitado", + "Search": "Buscar", + "Request": "Solicitar", + "Request4K": "Requisitar 4K", + "Denied": "Negado", + "Approve": "Aprovar", + "PartlyAvailable": "Parcialmente Disponível", + "ViewDetails": "Ver detalhes", + "Errors": { + "Validation": "Por favor, verifique os dados inseridos" + }, + "Cancel": "Cancelar", + "Submit": "Submeter", + "Update": "Atualizar", + "tvShow": "Series", + "movie": "Filmes", + "album": "Álbum" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Endereço de e-mail", + "ResetPasswordButton": "Redefinir Senha" + }, + "LandingPage": { + "OnlineHeading": "Online no momento", + "OnlineParagraph": "O servidor de mídia está atualmente online", + "PartiallyOnlineHeading": "Parcialmente Online", + "PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.", + "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", + "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", + "OfflineHeading": "Offline Agora", + "OfflineParagraph": "O servidor de mídia está atualmente offline.", + "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." + }, + "ErrorPages": { + "NotFound": "Pagina não encontrada" + }, + "NavigationBar": { + "Discover": "Explorar", + "Search": "Pesquisar", + "Requests": "Solicitações", + "UserManagement": "User Management", + "Issues": "Problemas", + "Vote": "Votar", + "Donate": "Doações!", + "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", + "DonateTooltip": "É assim que convenço minha esposa a me deixar passar o meu tempo livre desenvolvendo o Ombi 😁", + "UpdateAvailableTooltip": "Atualização Disponível!", + "Settings": "Configurações", + "Welcome": "Bem-vindo(a), {{username}}", + "UpdateDetails": "Detalhes da Atualização", + "Logout": "Desconectar", + "OpenMobileApp": "Abrir Aplicativo do Celular", + "RecentlyAdded": "Recentemente Adicionado", + "ChangeTheme": "Trocar Tema", + "Calendar": "Calendário", + "UserPreferences": "Preferências", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Teve uma ótima idéia? Sugira aqui!", + "Filter": { + "Movies": "Filmes", + "TvShows": "Séries", + "Music": "Músicas", + "People": "Pessoas" + }, + "MorningWelcome": "Bom dia!", + "AfternoonWelcome": "Boa tarde!", + "EveningWelcome": "Boa noite!" + }, + "Search": { + "Title": "Pesquisar", + "Paragraph": "Quer assistir a algo que não está disponível? Sem problemas, basta pesquisar abaixo e solicitar!", + "MoviesTab": "Filmes", + "TvTab": "Séries", + "MusicTab": "Músicas", + "AdvancedSearch": "Você pode preencher qualquer um dos abaixo para descobrir novas mídias. Todos os resultados são classificados por popularidade", + "AdvancedSearchHeader": "Pesquisa avançada", + "Suggestions": "Sugestões", + "NoResults": "Desculpe, não encontramos nenhum resultado!", + "DigitalDate": "Lançamento Digital: {{date}}", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "ViewOnJellyfin": "Assistir no Jellyfin", + "RequestAdded": "O pedido de {{title}} foi adicionado com sucesso", + "Similar": "Semelhantes", + "Refine": "Corrigir", + "SearchBarPlaceholder": "Digite Aqui para Pesquisar", + "Movies": { + "PopularMovies": "Filmes Populares", + "UpcomingMovies": "Filmes Em Breve", + "TopRatedMovies": "Filmes Mais Votados", + "NowPlayingMovies": "Filmes em Cartaz", + "HomePage": "Página Inicial", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Tendências", + "MostWatched": "Mais Assistidos", + "MostAnticipated": "Mais Aguardados", + "Results": "Resultados", + "AirDate": "Data de Exibição:", + "AllSeasons": "Todas as Temporadas", + "FirstSeason": "Primeira temporada", + "LatestSeason": "Última Temporada", + "Select": "Selecionar...", + "SubmitRequest": "Enviar solicitação", + "Season": "Temporada: {{seasonNumber}}", + "SelectAllInSeason": "Selecione Tudo na Temporada {{seasonNumber}}" + }, + "AdvancedSearchInstructions": "Por favor, escolha o tipo de mídia que você está procurando:", + "YearOfRelease": "Ano de lançamento", + "SearchGenre": "Pesquisa por gênero", + "SearchKeyword": "Pesquisar palavras-chave", + "SearchProvider": "Provedores de pesquisa", + "KeywordSearchingDisclaimer": "Por favor, note que a busca por palavra-chave é muito acertada e perdida devido aos dados inconsistentes no TheMovieDb" + }, + "Requests": { + "Title": "Solicitações", + "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", + "MoviesTab": "Filmes", + "ArtistName": "Artistas", + "AlbumName": "Nome do álbum", + "TvTab": "Séries", + "MusicTab": "Músicas", + "RequestedBy": "Solicitado por", + "Status": "Status", + "RequestStatus": "Status da solicitação", + "Denied": " Negados:", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ReleaseDate": "Lançado: {{date}}", + "TheatricalReleaseSort": "Lançamento nos Cinemas", + "DigitalRelease": "Lançamento Digital: {{date}}", + "RequestDate": "Data da Solicitação", + "QualityOverride": "Substituição de Qualidade:", + "RootFolderOverride": "Substituição da Pasta Raiz:", + "ChangeRootFolder": "Pasta Raiz", + "ChangeQualityProfile": "Perfil de Qualidade", + "MarkUnavailable": "Marcar como Indisponível", + "MarkUnavailable4K": "Marcar indisponível 4K", + "MarkAvailable": "Marcar como Disponível", + "MarkAvailable4K": "Marcar disponível 4K", + "Remove": "Remover", + "Deny": "Negar", + "Deny4K": "Recusar 4K", + "Has4KRequest": "Pedido 4K existente", + "DenyReason": "Razão da rejeição", + "DeniedReason": "Razão da rejeição", + "Season": "Temporada", + "GridTitle": "Título", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Relatar Problema", + "Filter": "Filtro", + "Sort": "Ordenar por", + "SeasonNumberHeading": "Temporada: {seasonNumber}", + "SortTitleAsc": "Título ▲", + "SortTitleDesc": "Título ▼", + "SortRequestDateAsc": "Data da Solicitação ▲", + "SortRequestDateDesc": "Data da Solicitação ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} solicitações restantes", + "NextDays": "Outra solicitação será adicionada em {{time}} dias", + "NextHours": "Outra solicitação será adicionada em {{time}} horas", + "NextMinutes": "Outra solicitação será adicionada em {{time}} minutos", + "NextMinute": "Outra solicitação será adicionada em {{time}} minuto" + }, + "AllRequests": "Todas solicitações", + "PendingRequests": "Solicitações pendentes", + "ProcessingRequests": "Solicitações em andamento", + "AvailableRequests": "Solicitação Disponíveis", + "DeniedRequests": "Solicitações Negadas", + "RequestsToDisplay": "Itens por página", + "RequestsTitle": "Título", + "Details": "Detalhes", + "Options": "Opções", + "RequestPanel": { + "Delete": "Apagar Solicitação", + "Approve": "Aprovar Solicitação", + "Approve4K": "Aprovar pedido 4K", + "ChangeAvailability": "Marcar Como Disponível", + "Deleted": "Successfully deleted selected items", + "Approved": "Successfully approved selected items" + }, + "SuccessfullyApproved": "Successfully Approved", + "SuccessfullyDeleted": "Request successfully deleted", + "NowAvailable": "Request is now available", + "NowUnavailable": "Request is now unavailable", + "SuccessfullyReprocessed": "Successfully Re-processed the request", + "DeniedRequest": "Denied Request", + "RequestCollection": "Request Collection", + "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", + "NeedToSelectEpisodes": "You need to select some episodes!", + "RequestAddedSuccessfully": "Solicitação de {{title}} foi adicionada com sucesso", + "ErrorCodes": { + "AlreadyRequested": "This has already been requested", + "EpisodesAlreadyRequested": "We already have episodes requested from this series", + "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", + "NoPermissions": "You do not have the correct permissions!", + "RequestDoesNotExist": "Request does not exist", + "ChildRequestDoesNotExist": "Child Request does not exist", + "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", + "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", + "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", + "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", + "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", + "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" + }, + "Issues": { + "Title": "Problemas", + "IssuesForTitle": "Issues for {{title}}", + "PendingTitle": "Problemas pendentes", + "InProgressTitle": "Problemas em resolução", + "ResolvedTitle": "Problemas Resolvidos", + "ColumnTitle": "Título", + "Count": "Count", + "Category": "Categoria", + "Status": "Status", + "Details": "Detalhes", + "Description": "Descrição", + "NoComments": "Sem Comentários!", + "MarkInProgress": "Marcar como em andamento", + "MarkResolved": "Marcar como resolvido", + "SendMessageButton": "Enviar", + "Subject": "Assunto", + "Comments": "Comentários", + "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", + "ReportedBy": "Reportado por", + "IssueDialog": { + "Title": "Reportar um problema", + "DescriptionPlaceholder": "Por favor, descreva o problema", + "TitlePlaceholder": "Título curto para o problema", + "SelectCategory": "Selecione Uma Categoria", + "IssueCreated": "Um registro de problema foi criado" + }, + "Outstanding": "Existem problemas pendentes", + "ResolvedDate": "Data da resolução", + "CreatedDate": "Notificado em", + "MarkedAsResolved": "Esse problema foi marcado como resolvido!", + "MarkedAsInProgress": "Esse problema foi marcado como resolvendo!", + "Delete": "Deletar problema", + "DeletedIssue": "O problema foi excluído", + "Chat": "Chat", + "EnterYourMessage": "Enter Your Message", + "Requested": "Solicitado", + "UserOnDate": "{{user}} on {{date}}" + }, + "Filter": { + "ClearFilter": "Limpar Filtro", + "FilterHeaderAvailability": "Disponibilidade", + "FilterHeaderRequestStatus": "Status", + "Approved": "Aprovado", + "PendingApproval": "Aprovação Pendente", + "WatchProviders": "Watch Providers", + "Keywords": "Keywords" + }, + "UserManagment": { + "TvRemaining": "Séries: {{remaining}}/{{total}} restantes", + "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", + "MusicRemaining": "Músicas: {{remaining}}/{{total}} restantes", + "TvDue": "Série: {{date}}", + "MovieDue": "Filme: {{date}}", + "MusicDue": "Música: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Votado", + "VotesTab": "Votos necessários" + }, + "MediaDetails": { + "Denied": "Rejeitado", + "Denied4K": "4K recusado", + "Trailers": "Trailers", + "RecommendationsTitle": "Recomendações", + "SimilarTitle": "Semelhante", + "VideosTitle": "Vídeos", + "AlbumsTitle": "Álbuns", + "RequestAllAlbums": "Solicitar Todos Álbuns", + "ClearSelection": "Limpar Seleção", + "RequestSelectedAlbums": "Solicitar Álbuns Selecionados", + "ViewCollection": "Ver Coleção", + "NotEnoughInfo": "Infelizmente ainda não há informação sobre essa série!", + "AdvancedOptions": "Opções Avançadas", + "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "QualityProfilesSelect": "Selecione um perfil de qualidade", + "RootFolderSelect": "Selecione o diretório raiz", + "LanguageProfileSelect": "Select A Language Profile", + "Status": "Status:", + "StatusValues": { + "Rumored": "Rumored", + "Planned": "Planned", + "In Production": "In Production", + "Post Production": "Post Production", + "Released": "Released", + "Running": "Running", + "Returning Series": "Returning Series", + "Ended": "Ended", + "Canceled": "Canceled" + }, + "Seasons": "Seasons:", + "Episodes": "Episodes:", + "Availability": "Disponibilidade:", + "RequestStatus": "Estado da solicitação", + "Quality": "Qualidade:", + "RootFolderOverride": "Substituição da Pasta Raiz:", + "QualityOverride": "Substituição de Qualidade:", + "Network": "Rede:", + "GenresLabel": "Gêneros:", + "Genres": "Gêneros", + "FirstAired": "Primeira Exibição:", + "TheatricalRelease": "Theatrical Release:", + "DigitalRelease": "Lançamento Digital:", + "Votes": "Votos:", + "Runtime": "Tempo de execução:", + "Minutes": "{{runtime}} Minutos", + "Revenue": "Receita:", + "Budget": "Orçamento:", + "Keywords": "Palavras-Chave/Tags:", + "Casts": { + "CastTitle": "Elenco" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Isto irá pedir todas as temporadas da série", + "FirstSeasonTooltip": "Isto somente irá pedir a 1ª temporada da série", + "LatestSeasonTooltip": "Isto somente irá pedir a última temporada da série", + "NoEpisodes": "There unfortunately is no episode data for this show yet!", + "SeasonNumber": "Temporada: {{number}}" + }, + "SonarrConfiguration": "Configuração do Sonarr", + "RadarrConfiguration": "Configuração do Radarr", + "RequestOnBehalf": "Pedido em nome de", + "PleaseSelectUser": "Por favor, selecione um usuário", + "StreamingOn": "Streaming On:", + "RequestedBy": "Solicitado por:", + "RequestedByOn": "Requested By {{user}} on {{date}}", + "RequestDate": "Data da Solicitação:", + "DeniedReason": "Razão da rejeição:", + "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Reprocessar pedido 4K", + "Music": { + "Type": "Type:", + "Country": "Country:", + "StartDate": "Start Date:", + "EndDate": "EndDate:" + } + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Tendências", + "UpcomingTab": "Próximo", + "SeasonalTab": "Seasonal", + "RecentlyRequestedTab": "Recently Requested", + "Movies": "Filmes", + "Combined": "Combinados", + "Tv": "Serie", + "CardDetails": { + "Availability": "Disponibilidade", + "Studio": "Estúdio", + "Network": "Rede", + "UnknownNetwork": "Desconhecido", + "RequestStatus": "Estado da solicitação", + "Director": "Diretor", + "InCinemas": "Nos Cinemas", + "FirstAired": "Primeira Exibição", + "Writer": "Escritor", + "ExecProducer": "Produtor Executivo" + }, + "NoSearch": "Desculpe, nada corresponde à sua pesquisa!" + }, + "UserPreferences": { + "Welcome": "Bem-vindo, {{username}}!", + "OmbiLanguage": "Idioma", + "DarkMode": "Modo Escuro", + "Updated": "Atualizado com Sucesso", + "StreamingCountry": "País de Streaming", + "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", + "LanguageDescription": "Este é o idioma que você gostaria de exibir na interface do Ombi.", + "MobileQRCode": "QR Code para Celular", + "LegacyApp": "Iniciar Legacy App", + "NoQrCode": "Please contact your administrator to enable QR codes", + "UserType": "User Type:", + "ChangeDetails": "Change Details", + "NeedCurrentPassword": "You need your current password to make any changes here", + "CurrentPassword": "Current Password", + "EmailAddress": "Endereço de e-mail", + "NewPassword": "New Password", + "NewPasswordConfirm": "New Password Confirm", + "Security": "Security", + "Profile": "Profile", + "UpdatedYourInformation": "Updated your information", + "Unsubscribed": "Unsubscribed!" + }, + "UserTypeLabel": { + "1": "Local User", + "2": "Plex User", + "3": "Emby User", + "4": "Emby Connect User", + "5": "Jellyfin User" + }, + "Paginator": { + "itemsPerPageLabel": "Items per page:", + "nextPageLabel": "Next page", + "previousPageLabel": "Previous page", + "firstPageLabel": "First page", + "lastPageLabel": "Last page", + "rangePageLabel1": "0 of {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + } +} diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index ea1967e78..736330eb9 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -1,204 +1,213 @@ { "Login": { "SignInButton": "Iniciar sessão", - "UsernamePlaceholder": "Nome de usuário", - "PasswordPlaceholder": "Senha", - "RememberMe": "Lembrar-me", + "UsernamePlaceholder": "Nome de Usuário", + "PasswordPlaceholder": "Palavra-passe", + "RememberMe": "Recorde-me", "SignInWith": "Entre com {{appName}}", "SignInWithPlex": "Iniciar sessão com Plex", "ForgottenPassword": "Esqueceu sua senha?", "Errors": { - "IncorrectCredentials": "Nome de usuário ou senha incorretos" + "IncorrectCredentials": "Usuário ou senha incorretos" } }, "Common": { "ContinueButton": "Continuar", "Available": "Disponível", + "Available4K": "Disponível 4K", "Approved": "Aprovado", - "Pending": "Pendente", + "Approve4K": "Approve 4K", + "Pending": "Pending", "PartiallyAvailable": "Parcialmente Disponível", - "Monitored": "Monitorado", - "NotAvailable": "Não Disponível", - "ProcessingRequest": "Processando Solicitação", + "Monitored": "Monitored", + "NotAvailable": "Não disponível", + "ProcessingRequest": "Processando o pedido", "PendingApproval": "Aprovação Pendente", - "RequestDenied": "Solicitação Negada", + "RequestDenied": "Pedido Negado", "NotRequested": "Não Solicitado", - "Requested": "Solicitado", - "Search": "Buscar", + "Requested": "Pedido", + "Requested4K": "Requested 4K", + "Search": "Search", "Request": "Solicitar", - "Denied": "Negado", + "Request4K": "Request 4K", + "Denied": "Recusado", "Approve": "Aprovar", "PartlyAvailable": "Parcialmente Disponível", "ViewDetails": "Ver detalhes", "Errors": { - "Validation": "Por favor, verifique os dados inseridos" + "Validation": "Por favor, verifique os valores inseridos" }, "Cancel": "Cancelar", "Submit": "Submeter", - "Update": "Atualizar", - "tvShow": "Series", - "movie": "Filmes", - "album": "Álbum" + "Update": "Update", + "tvShow": "TV Show", + "movie": "Movie", + "album": "Album" }, "PasswordReset": { - "EmailAddressPlaceholder": "Endereço de e-mail", - "ResetPasswordButton": "Redefinir Senha" + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Nova senha" }, "LandingPage": { "OnlineHeading": "Online no momento", - "OnlineParagraph": "O servidor de mídia está atualmente online", - "PartiallyOnlineHeading": "Parcialmente Online", - "PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.", - "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", - "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", - "OfflineHeading": "Offline Agora", - "OfflineParagraph": "O servidor de mídia está atualmente offline.", - "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." + "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." }, "ErrorPages": { - "NotFound": "Pagina não encontrada" + "NotFound": "Page not found" }, "NavigationBar": { - "Discover": "Explorar", - "Search": "Pesquisar", - "Requests": "Solicitações", - "UserManagement": "User Management", - "Issues": "Problemas", - "Vote": "Votar", - "Donate": "Doações!", - "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", - "DonateTooltip": "É assim que convenço minha esposa a me deixar passar o meu tempo livre desenvolvendo o Ombi 😁", - "UpdateAvailableTooltip": "Atualização Disponível!", - "Settings": "Configurações", - "Welcome": "Bem-vindo(a), {{username}}", - "UpdateDetails": "Detalhes da Atualização", - "Logout": "Desconectar", - "OpenMobileApp": "Abrir Aplicativo do Celular", - "RecentlyAdded": "Recentemente Adicionado", - "ChangeTheme": "Trocar Tema", - "Calendar": "Calendário", - "UserPreferences": "Preferências", - "FeatureSuggestion": "Feature Suggestion", - "FeatureSuggestionTooltip": "Teve uma ótima idéia? Sugira aqui!", + "Discover": "Discover", + "Search": "Search", + "Requests": "Requests", + "UserManagement": "Users", + "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", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Features", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", "Filter": { - "Movies": "Filmes", - "TvShows": "Séries", - "Music": "Músicas", - "People": "Pessoas" + "Movies": "Movies", + "TvShows": "TV Shows", + "Music": "Music", + "People": "People" }, - "MorningWelcome": "Bom dia!", - "AfternoonWelcome": "Boa tarde!", - "EveningWelcome": "Boa noite!" + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" }, "Search": { - "Title": "Pesquisar", - "Paragraph": "Quer assistir a algo que não está disponível? Sem problemas, basta pesquisar abaixo e solicitar!", - "MoviesTab": "Filmes", - "TvTab": "Séries", - "MusicTab": "Músicas", - "AdvancedSearch": "Você pode preencher qualquer um dos abaixo para descobrir novas mídias. Todos os resultados são classificados por popularidade", - "AdvancedSearchHeader": "Pesquisa avançada", - "Suggestions": "Sugestões", - "NoResults": "Desculpe, não encontramos nenhum resultado!", - "DigitalDate": "Lançamento Digital: {{date}}", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "ViewOnJellyfin": "Assistir no Jellyfin", - "RequestAdded": "O pedido de {{title}} foi adicionado com sucesso", - "Similar": "Semelhantes", - "Refine": "Corrigir", - "SearchBarPlaceholder": "Digite Aqui para Pesquisar", + "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", + "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", + "AdvancedSearchHeader": "Advanced Search", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "Play On Plex", + "ViewOnEmby": "Play On Emby", + "ViewOnJellyfin": "Play On Jellyfin", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", "Movies": { - "PopularMovies": "Filmes Populares", - "UpcomingMovies": "Filmes Em Breve", - "TopRatedMovies": "Filmes Mais Votados", - "NowPlayingMovies": "Filmes em Cartaz", - "HomePage": "Página Inicial", + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", "Trailer": "Trailer" }, "TvShows": { "Popular": "Popular", - "Trending": "Tendências", - "MostWatched": "Mais Assistidos", - "MostAnticipated": "Mais Aguardados", - "Results": "Resultados", - "AirDate": "Data de Exibição:", - "AllSeasons": "Todas as Temporadas", - "FirstSeason": "Primeira temporada", - "LatestSeason": "Última Temporada", - "Select": "Selecionar...", - "SubmitRequest": "Enviar solicitação", - "Season": "Temporada: {{seasonNumber}}", - "SelectAllInSeason": "Selecione Tudo na Temporada {{seasonNumber}}" + "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}}" }, - "AdvancedSearchInstructions": "Por favor, escolha o tipo de mídia que você está procurando:", - "YearOfRelease": "Ano de lançamento", - "SearchGenre": "Pesquisa por gênero", - "SearchKeyword": "Pesquisar palavras-chave", - "SearchProvider": "Provedores de pesquisa", - "KeywordSearchingDisclaimer": "Por favor, note que a busca por palavra-chave é muito acertada e perdida devido aos dados inconsistentes no TheMovieDb" + "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", + "YearOfRelease": "Year of Release", + "SearchGenre": "Search Genre", + "SearchKeyword": "Search Keyword", + "SearchProvider": "Search Provider", + "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { - "Title": "Solicitações", - "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", - "MoviesTab": "Filmes", - "ArtistName": "Artistas", - "AlbumName": "Nome do álbum", - "TvTab": "Séries", - "MusicTab": "Músicas", - "RequestedBy": "Solicitado por", + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By", "Status": "Status", - "RequestStatus": "Status da solicitação", - "Denied": " Negados:", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ReleaseDate": "Lançado: {{date}}", - "TheatricalReleaseSort": "Lançamento nos Cinemas", - "DigitalRelease": "Lançamento Digital: {{date}}", - "RequestDate": "Data da Solicitação", - "QualityOverride": "Substituição de Qualidade:", - "RootFolderOverride": "Substituição da Pasta Raiz:", - "ChangeRootFolder": "Pasta Raiz", - "ChangeQualityProfile": "Perfil de Qualidade", - "MarkUnavailable": "Marcar como Indisponível", - "MarkAvailable": "Marcar como Disponível", - "Remove": "Remover", - "Deny": "Negar", - "DenyReason": "Razão da rejeição", - "DeniedReason": "Razão da rejeição", - "Season": "Temporada", - "GridTitle": "Título", - "AirDate": "AirDate", + "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", + "MarkUnavailable4K": "Mark Unavailable 4K", + "MarkAvailable": "Mark Available", + "MarkAvailable4K": "Mark Available 4K", + "Remove": "Remove", + "Deny": "Deny", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", + "DenyReason": "Deny Reason", + "DeniedReason": "Denied Reason", + "Season": "Season", + "GridTitle": "Title", + "AirDate": "Air Date", "GridStatus": "Status", - "ReportIssue": "Relatar Problema", - "Filter": "Filtro", - "Sort": "Ordenar por", - "SeasonNumberHeading": "Temporada: {seasonNumber}", - "SortTitleAsc": "Título ▲", - "SortTitleDesc": "Título ▼", - "SortRequestDateAsc": "Data da Solicitação ▲", - "SortRequestDateDesc": "Data da Solicitação ▼", + "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}} solicitações restantes", - "NextDays": "Outra solicitação será adicionada em {{time}} dias", - "NextHours": "Outra solicitação será adicionada em {{time}} horas", - "NextMinutes": "Outra solicitação será adicionada em {{time}} minutos", - "NextMinute": "Outra solicitação será adicionada em {{time}} minuto" + "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" }, - "AllRequests": "Todas solicitações", - "PendingRequests": "Solicitações pendentes", - "ProcessingRequests": "Solicitações em andamento", - "AvailableRequests": "Solicitação Disponíveis", - "DeniedRequests": "Solicitações Negadas", - "RequestsToDisplay": "Itens por página", - "RequestsTitle": "Título", - "Details": "Detalhes", - "Options": "Opções", + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Title", + "Details": "Details", + "Options": "Options", "RequestPanel": { - "Delete": "Apagar Solicitação", + "Delete": "Delete Request", "Approve": "Approve Request", + "Approve4K": "Approve 4K Request", "ChangeAvailability": "Mark Available", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" @@ -234,25 +243,25 @@ "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { - "Title": "Problemas", + "Title": "Issues", "IssuesForTitle": "Issues for {{title}}", - "PendingTitle": "Problemas pendentes", - "InProgressTitle": "Problemas em resolução", - "ResolvedTitle": "Problemas Resolvidos", - "ColumnTitle": "Título", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", "Count": "Count", - "Category": "Categoria", + "Category": "Category", "Status": "Status", - "Details": "Detalhes", - "Description": "Descrição", - "NoComments": "Sem Comentários!", - "MarkInProgress": "Marcar como em andamento", - "MarkResolved": "Marcar como resolvido", - "SendMessageButton": "Enviar", - "Subject": "Assunto", - "Comments": "Comentários", - "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", - "ReportedBy": "Reportado por", + "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", "IssueDialog": { "Title": "Report an issue", "DescriptionPlaceholder": "Please describe the issue", @@ -269,39 +278,40 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Pedido", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { - "ClearFilter": "Limpar Filtro", - "FilterHeaderAvailability": "Disponibilidade", + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", "FilterHeaderRequestStatus": "Status", - "Approved": "Aprovado", + "Approved": "Approved", "PendingApproval": "Aprovação Pendente", "WatchProviders": "Watch Providers", "Keywords": "Keywords" }, "UserManagment": { - "TvRemaining": "Séries: {{remaining}}/{{total}} restantes", - "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", - "MusicRemaining": "Músicas: {{remaining}}/{{total}} restantes", - "TvDue": "Série: {{date}}", - "MovieDue": "Filme: {{date}}", - "MusicDue": "Música: {{date}}" + "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": "Votado", - "VotesTab": "Votos necessários" + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" }, "MediaDetails": { - "Denied": "Denied", + "Denied": "Recusado", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", - "VideosTitle": "Vídeos", - "AlbumsTitle": "Álbuns", - "RequestAllAlbums": "Solicitar Todos Álbuns", - "ClearSelection": "Limpar Seleção", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", "RequestSelectedAlbums": "Request Selected Albums", "ViewCollection": "View Collection", "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", @@ -363,6 +373,7 @@ "RequestDate": "Request Date:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 0f57f9c31..9af1e31fc 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Продолжить", "Available": "Доступно", - "Approved": "Approved", + "Available4K": "Available 4K", + "Approved": "Одобрено", + "Approve4K": "Approve 4K", "Pending": "Pending", "PartiallyAvailable": "Частично доступно", "Monitored": "Мониторинг", @@ -24,8 +26,10 @@ "RequestDenied": "Запрос отклонен", "NotRequested": "Не запрошено", "Requested": "Запрошено", - "Search": "Search", + "Requested4K": "Requested 4K", + "Search": "Поиск", "Request": "Запросить", + "Request4K": "Request 4K", "Denied": "Отказано", "Approve": "Одобрить", "PartlyAvailable": "Частично доступно", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Корневая папка", "ChangeQualityProfile": "Профиль качества", "MarkUnavailable": "Отметить недоступным", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Отметить доступным", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Удалить", "Deny": "Отклонить", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Deny Reason", "DeniedReason": "Denied Reason", "Season": "Сезон", @@ -199,7 +207,8 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", + "Approve4K": "Approve 4K Request", + "ChangeAvailability": "Отметить доступным", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" }, @@ -212,7 +221,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Запрос на {{title}} успешно добавлен", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +278,7 @@ "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Запрошено", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Отказано", + "Denied4K": "Denied 4K", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Похожие", @@ -312,7 +322,7 @@ "QualityProfilesSelect": "Select A Quality Profile", "RootFolderSelect": "Select A Root Folder", "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "Status": "Статус:", "StatusValues": { "Rumored": "Rumored", "Planned": "Planned", @@ -326,16 +336,16 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Доступность:", "RequestStatus": "Request Status", "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", + "RootFolderOverride": "Переопределение корневой папки:", + "QualityOverride": "Переопределение качества:", "Network": "Network:", "GenresLabel": "Genres:", "Genres": "Genres", "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", + "TheatricalRelease": "Релиз в кинотеатрах:", "DigitalRelease": "Digital Release:", "Votes": "Votes:", "Runtime": "Runtime:", @@ -351,18 +361,19 @@ "FirstSeasonTooltip": "This will only request the First Season for this show", "LatestSeasonTooltip": "This will only request the Latest Season for this show", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Сезон {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "RequestedBy": "Автор запроса:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Дата запроса:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Type:", "Country": "Country:", @@ -408,7 +419,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "Адрес эл. почты", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 1e0ae25cf..79b08263e 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Pokračovať", "Available": "Dostupné", + "Available4K": "Available 4K", "Approved": "Schválené", + "Approve4K": "Approve 4K", "Pending": "Čakajúce", "PartiallyAvailable": "Čiastočne dostupné", "Monitored": "Sledované", @@ -24,8 +26,10 @@ "RequestDenied": "Požiadavka zamietnutá", "NotRequested": "Nepožiadané", "Requested": "Požiadané", + "Requested4K": "Requested 4K", "Search": "Hľadať", "Request": "Požiadať", + "Request4K": "Request 4K", "Denied": "Zamietnuté", "Approve": "Schválené", "PartlyAvailable": "Čiastočne dostupné", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Koreňový priečinok", "ChangeQualityProfile": "Profil kvality", "MarkUnavailable": "Označiť nedostupné", + "MarkUnavailable4K": "Mark Unavailable 4K", "MarkAvailable": "Označiť dostupné", + "MarkAvailable4K": "Mark Available 4K", "Remove": "Odstrániť", "Deny": "Odmietnuť", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", "DenyReason": "Odmietnuť dôvod", "DeniedReason": "Odmietnuť dôvod", "Season": "Séria", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Odstrániž požiadavku", "Approve": "Schváliť žiadosť", + "Approve4K": "Approve 4K Request", "ChangeAvailability": "Označiť k dispozícií", "Deleted": "Úspešne odstránené vybrané položky", "Approved": "Úspešne schválené vybrané položky" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Zamietnuté", + "Denied4K": "Denied 4K", "Trailers": "Upútavka", "RecommendationsTitle": "Odporúčania", "SimilarTitle": "Podobné", @@ -363,6 +373,7 @@ "RequestDate": "Dátum požiadavky:", "DeniedReason": "Dôvod zamietnutia:", "ReProcessRequest": "Žiadosť o opätovné spracovanie", + "ReProcessRequest4K": "Re-Process 4K Request", "Music": { "Type": "Typ:", "Country": "Krajina:", diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8532930be..03caceb46 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "Fortsätt", "Available": "Tillgänglig", - "Approved": "Approved", + "Available4K": "Tillgänglig 4K", + "Approved": "Godkänd", + "Approve4K": "Godkänn 4K", "Pending": "Pending", "PartiallyAvailable": "Delvis tillgänglig", "Monitored": "Övervakad", @@ -24,8 +26,10 @@ "RequestDenied": "Efterfrågan nekas", "NotRequested": "Inte begärd", "Requested": "Begärd", - "Search": "Search", + "Requested4K": "Begärd 4K", + "Search": "Sök", "Request": "Begär", + "Request4K": "Begär 4K", "Denied": "Nekad", "Approve": "Godkänn", "PartlyAvailable": "Delvis tillgänglig", @@ -104,7 +108,7 @@ "TheatricalRelease": "Biopremiär: {{date}}", "ViewOnPlex": "Visa på Plex", "ViewOnEmby": "Visa på Emby", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Spela på Jellyfin", "RequestAdded": "Begäran av {{title}} har lagts till", "Similar": "Liknande", "Refine": "Förfina", @@ -161,9 +165,13 @@ "ChangeRootFolder": "Byt rotmapp", "ChangeQualityProfile": "Byt kvalitétsprofil", "MarkUnavailable": "Markera Otillgänglig", + "MarkUnavailable4K": "Markera som ej tillgänglig 4K", "MarkAvailable": "Markera Tillgänglig", + "MarkAvailable4K": "Markera som tillgänglig 4K", "Remove": "Ta bort", "Deny": "Neka", + "Deny4K": "Neka 4K", + "Has4KRequest": "Har 4K-förfrågan", "DenyReason": "Anledning för nekande", "DeniedReason": "Denied Reason", "Season": "Säsong", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "Ta bort förfrågan", "Approve": "Godkänn begäran", + "Approve4K": "Godkänn 4K-begäran", "ChangeAvailability": "Markera Tillgänglig", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items" @@ -212,7 +221,7 @@ "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "RequestAddedSuccessfully": "Begäran av {{title}} har lagts till", "ErrorCodes": { "AlreadyRequested": "This has already been requested", "EpisodesAlreadyRequested": "We already have episodes requested from this series", @@ -269,7 +278,7 @@ "DeletedIssue": "Problemet har tagits bort", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", - "Requested": "Requested", + "Requested": "Begärd", "UserOnDate": "{{user}} on {{date}}" }, "Filter": { @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "Nekad", + "Denied4K": "Nekad 4K", "Trailers": "Trailers", "RecommendationsTitle": "Rekommendationer", "SimilarTitle": "Liknande", @@ -326,23 +336,23 @@ }, "Seasons": "Seasons:", "Episodes": "Episodes:", - "Availability": "Availability:", + "Availability": "Tillgänglighet:", "RequestStatus": "Status för begäran", - "Quality": "Quality:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", - "Runtime": "Runtime:", + "Quality": "Kvalitet:", + "RootFolderOverride": "Rotmappsöverskridande:", + "QualityOverride": "Kvalitétsöverskridande:", + "Network": "Tv-nätverk:", + "GenresLabel": "Genrer:", + "Genres": "Genrer", + "FirstAired": "Sändes första gången:", + "TheatricalRelease": "Biopremiär:", + "DigitalRelease": "Digital release:", + "Votes": "Röster:", + "Runtime": "Speltid:", "Minutes": "{{runtime}} minuter", - "Revenue": "Revenue:", + "Revenue": "Intäkter:", "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Keywords": "Nyckelord/Taggar:", "Casts": { "CastTitle": "Rollista" }, @@ -351,18 +361,19 @@ "FirstSeasonTooltip": "Detta kommer endast att begära den första säsongen för denna serie", "LatestSeasonTooltip": "Detta kommer endast att begära den senaste säsongen för denna serie", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Säsong {{number}}" }, - "SonarrConfiguration": "Sonarr Configuration", - "RadarrConfiguration": "Radarr Configuration", - "RequestOnBehalf": "Request on behalf of", - "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", + "SonarrConfiguration": "Sonarr Konfiguration", + "RadarrConfiguration": "Radarr Konfiguration", + "RequestOnBehalf": "På begäran av", + "PleaseSelectUser": "Vänligen välj en användare", + "StreamingOn": "Strömmar på:", + "RequestedBy": "Efterfrågats av:", "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", + "RequestDate": "Datum för begäran:", "DeniedReason": "Denied Reason:", "ReProcessRequest": "Re-Process Request", + "ReProcessRequest4K": "Omarbeta 4K-förfrågan", "Music": { "Type": "Type:", "Country": "Country:", @@ -391,13 +402,13 @@ "Writer": "Författare", "ExecProducer": "Exekutiv producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Tyvärr, inget matchar din sökning!" }, "UserPreferences": { "Welcome": "Välkommen {{username}}!", "OmbiLanguage": "Språk", "DarkMode": "Mörkt läge", - "Updated": "Successfully Updated", + "Updated": "Uppdatering lyckades", "StreamingCountry": "Streaming Country", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", @@ -408,7 +419,7 @@ "ChangeDetails": "Change Details", "NeedCurrentPassword": "You need your current password to make any changes here", "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", + "EmailAddress": "E-postadress", "NewPassword": "New Password", "NewPasswordConfirm": "New Password Confirm", "Security": "Security", diff --git a/src/Ombi/wwwroot/translations/zh-TW.json b/src/Ombi/wwwroot/translations/zh-TW.json new file mode 100644 index 000000000..9dfa34248 --- /dev/null +++ b/src/Ombi/wwwroot/translations/zh-TW.json @@ -0,0 +1,446 @@ +{ + "Login": { + "SignInButton": "登录", + "UsernamePlaceholder": "用户名", + "PasswordPlaceholder": "密码", + "RememberMe": "记住我", + "SignInWith": "使用 {{appName}} 登录", + "SignInWithPlex": "使用 Plex 登录", + "ForgottenPassword": "忘记密码?", + "Errors": { + "IncorrectCredentials": "用户名或密码错误" + } + }, + "Common": { + "ContinueButton": "继续", + "Available": "可播放", + "Available4K": "Available 4K", + "Approved": "已批准", + "Approve4K": "Approve 4K", + "Pending": "待审核", + "PartiallyAvailable": "部分可播放", + "Monitored": "监控中", + "NotAvailable": "不可播放", + "ProcessingRequest": "处理中请求", + "PendingApproval": "等待批准", + "RequestDenied": "请求被拒绝", + "NotRequested": "未请求", + "Requested": "已请求", + "Requested4K": "Requested 4K", + "Search": "搜索", + "Request": "请求", + "Request4K": "Request 4K", + "Denied": "已拒绝", + "Approve": "批准", + "PartlyAvailable": "部分可播放", + "ViewDetails": "查看详情", + "Errors": { + "Validation": "请检查您输入的值" + }, + "Cancel": "取消", + "Submit": "提交", + "Update": "更新", + "tvShow": "电视节目", + "movie": "电影", + "album": "专辑" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "邮箱", + "ResetPasswordButton": "重置密码" + }, + "LandingPage": { + "OnlineHeading": "当前在线", + "OnlineParagraph": "媒体服务器当前在线", + "PartiallyOnlineHeading": "部分在线", + "PartiallyOnlineParagraph": "媒体服务器部分在线", + "MultipleServersUnavailable": "{{totalServers}} 个服务器中有{{serversUnavailable}} 个已离线", + "SingleServerUnavailable": "{{totalServers}} 个服务器中有{{serversUnavailable}} 个已离线", + "OfflineHeading": "当前离线", + "OfflineParagraph": "媒体服务器当前离线", + "CheckPageForUpdates": "检查此页面以获取站点连续更新。" + }, + "ErrorPages": { + "NotFound": "找不到页面" + }, + "NavigationBar": { + "Discover": "发现", + "Search": "搜索", + "Requests": "请求", + "UserManagement": "用户", + "Issues": "问题", + "Vote": "投票", + "Donate": "捐助", + "DonateLibraryMaintainer": "捐赠给维护者", + "DonateTooltip": "这是我说服我妻子让我继续利用业余时间开发Ombi的途径 😁", + "UpdateAvailableTooltip": "有可用更新!", + "Settings": "设置", + "Welcome": "{{username}},欢迎您", + "UpdateDetails": "更新详请", + "Logout": "登出", + "OpenMobileApp": "打开移动应用", + "RecentlyAdded": "最近添加", + "ChangeTheme": "更改主题", + "Calendar": "日历", + "UserPreferences": "偏好设置", + "FeatureSuggestion": "功能", + "FeatureSuggestionTooltip": "有一个很棒的新想法吗?在这里建议!", + "Filter": { + "Movies": "电影", + "TvShows": "电视节目", + "Music": "音乐", + "People": "人员" + }, + "MorningWelcome": "早上好!", + "AfternoonWelcome": "下午好!", + "EveningWelcome": "晚上好!" + }, + "Search": { + "Title": "搜索", + "Paragraph": "想要观看当前无法观看的内容吗?没问题,只需在下方搜索并请求!", + "MoviesTab": "电影", + "TvTab": "电视节目", + "MusicTab": "音乐", + "AdvancedSearch": "您可以填写以下任何一项来发现新媒体,所有结果都按受欢迎程度排序。", + "AdvancedSearchHeader": "高级搜索", + "Suggestions": "建议", + "NoResults": "对不起,我们没有找到任何结果。", + "DigitalDate": "数字版发行:{{date}}", + "TheatricalRelease": "剧场版发行:{{date}}", + "ViewOnPlex": "在Plex上播放", + "ViewOnEmby": "在 Emby上播放", + "ViewOnJellyfin": "在 Jellyfin上播放", + "RequestAdded": "{{title}} 的请求已成功添加", + "Similar": "相似", + "Refine": "精选", + "SearchBarPlaceholder": "在这里输入搜索内容", + "Movies": { + "PopularMovies": "热门电影", + "UpcomingMovies": "即将上映的电影", + "TopRatedMovies": "高评分的电影", + "NowPlayingMovies": "正在播放的电影", + "HomePage": "主页", + "Trailer": "预告片" + }, + "TvShows": { + "Popular": "热门", + "Trending": "趋势", + "MostWatched": "观看次数最多", + "MostAnticipated": "最期待", + "Results": "结果", + "AirDate": "播出日期:", + "AllSeasons": "所有季", + "FirstSeason": "第一季", + "LatestSeason": "最新季", + "Select": "请选择...", + "SubmitRequest": "提交请求", + "Season": "第{{seasonNumber}} 季", + "SelectAllInSeason": "在所有季中选择第{{seasonNumber}} 季" + }, + "AdvancedSearchInstructions": "请选择您需要搜索的媒体类型:", + "YearOfRelease": "发行年份", + "SearchGenre": "按类型搜索", + "SearchKeyword": "按关键字搜索", + "SearchProvider": "按提供者搜索", + "KeywordSearchingDisclaimer": "请注意,由于TheMovieDb中的数据不一致,关键字搜索方式非常容易出错" + }, + "Requests": { + "Title": "请求", + "Paragraph": "您可以在下方看到您的和所有其他人的请求,以及他们的下载和批准状态", + "MoviesTab": "电影", + "ArtistName": "艺术家", + "AlbumName": "专辑名称", + "TvTab": "电视节目", + "MusicTab": "音乐", + "RequestedBy": "请求者", + "Status": "发行状态", + "RequestStatus": "申请状态", + "Denied": "已拒绝:", + "TheatricalRelease": "剧场版发行:{{date}}", + "ReleaseDate": "已发行: {{date}}", + "TheatricalReleaseSort": "剧场版发行", + "DigitalRelease": "数字版发行:{{date}}", + "RequestDate": "请求日期", + "QualityOverride": "质量覆盖:", + "RootFolderOverride": "根目录覆盖:", + "ChangeRootFolder": "根目录", + "ChangeQualityProfile": "画质配置文件", + "MarkUnavailable": "标记为不可用", + "MarkUnavailable4K": "Mark Unavailable 4K", + "MarkAvailable": "标记为可用", + "MarkAvailable4K": "Mark Available 4K", + "Remove": "删除", + "Deny": "拒绝", + "Deny4K": "Deny 4K", + "Has4KRequest": "Has 4K Request", + "DenyReason": "拒绝原因", + "DeniedReason": "被拒绝原因", + "Season": "季", + "GridTitle": "标题", + "AirDate": "播出日期:", + "GridStatus": "状态", + "ReportIssue": "反馈问题", + "Filter": "筛选", + "Sort": "排序", + "SeasonNumberHeading": "第{seasonNumber} 季", + "SortTitleAsc": "标题 ▲", + "SortTitleDesc": "标题 ▼", + "SortRequestDateAsc": "请求日期 ▲", + "SortRequestDateDesc": "请求日期 ▼", + "SortStatusAsc": "状态 ▲", + "SortStatusDesc": "状态 ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} 个请求剩余", + "NextDays": "将在{{time}} 天内添加另一个请求", + "NextHours": "将在{{time}} 小时后添加另一个请求", + "NextMinutes": "将在{{time}} 分钟内添加另一个请求", + "NextMinute": "将在{{time}} 分钟内添加另一个请求" + }, + "AllRequests": "所有请求", + "PendingRequests": "待处理请求", + "ProcessingRequests": "处理中请求", + "AvailableRequests": "可用请求", + "DeniedRequests": "已拒绝请求", + "RequestsToDisplay": "显示请求", + "RequestsTitle": "标题", + "Details": "详情", + "Options": "选项", + "RequestPanel": { + "Delete": "删除请求", + "Approve": "批准请求", + "Approve4K": "Approve 4K Request", + "ChangeAvailability": "标记为可用", + "Deleted": "所选项目已删除", + "Approved": "所选项目已批准" + }, + "SuccessfullyApproved": "批准成功", + "SuccessfullyDeleted": "删除请求成功", + "NowAvailable": "请求现在可观看", + "NowUnavailable": "请求现在不可观看", + "SuccessfullyReprocessed": "重新处理请求成功", + "DeniedRequest": "已拒绝请求", + "RequestCollection": "请求合集", + "CollectionSuccesfullyAdded": "合集 {{name}} 已成功添加!", + "NeedToSelectEpisodes": "您需要选择集数!", + "RequestAddedSuccessfully": "{{title}} 的请求已成功添加", + "ErrorCodes": { + "AlreadyRequested": "请求已经存在", + "EpisodesAlreadyRequested": "已存在这个系列的剧集请求", + "NoPermissionsOnBehalf": "您没有代表用户请求的正确权限!", + "NoPermissions": "您没有正确的权限!", + "RequestDoesNotExist": "请求不存在", + "ChildRequestDoesNotExist": "子请求不存在", + "NoPermissionsRequestMovie": "您没有请求电影的权限", + "NoPermissionsRequestTV": "您没有请求电视节目的权限", + "NoPermissionsRequestAlbum": "您没有请求专辑的权限", + "MovieRequestQuotaExceeded": "您的电影请求已超出配额!", + "TvRequestQuotaExceeded": "您的剧集请求已超出配额!", + "AlbumRequestQuotaExceeded": "您的专辑请求已超出配额!" + }, + "Notify": "通知", + "RemoveNotification": "删除通知", + "SuccessfulNotify": "您将收到标题为 {{title}} 的通知", + "SuccessfulUnNotify": "您将不再收到标题为 {{title}} 的通知", + "CouldntNotify": "无法通知标题 {{title}}" + }, + "Issues": { + "Title": "问题", + "IssuesForTitle": "{{title}} 的问题", + "PendingTitle": "待处理的问题", + "InProgressTitle": "正在处理的问题", + "ResolvedTitle": "已解决的问题", + "ColumnTitle": "标题", + "Count": "总计", + "Category": "类别", + "Status": "状态", + "Details": "详情", + "Description": "描述", + "NoComments": "暂无评论", + "MarkInProgress": "标记为进行中", + "MarkResolved": "标记为已解决", + "SendMessageButton": "发送", + "Subject": "主题", + "Comments": "评论", + "WriteMessagePlaceholder": "在这里写下您的留言", + "ReportedBy": "报告人", + "IssueDialog": { + "Title": "反馈问题", + "DescriptionPlaceholder": "请描述您的问题", + "TitlePlaceholder": "简短标题", + "SelectCategory": "选择分类", + "IssueCreated": "问题已创建" + }, + "Outstanding": "未解决的问题", + "ResolvedDate": "解决日期", + "CreatedDate": "提出日期", + "MarkedAsResolved": "此问题已被标记为已解决!", + "MarkedAsInProgress": "此问题已被标记为正在处理中!", + "Delete": "删除问题", + "DeletedIssue": "问题已被删除", + "Chat": "聊天", + "EnterYourMessage": "输入您的消息", + "Requested": "已请求", + "UserOnDate": "{{user}} 在 {{date}}" + }, + "Filter": { + "ClearFilter": "清除筛选", + "FilterHeaderAvailability": "可用性", + "FilterHeaderRequestStatus": "状态", + "Approved": "已批准", + "PendingApproval": "待批准", + "WatchProviders": "观看提供商", + "Keywords": "关键字" + }, + "UserManagment": { + "TvRemaining": "电视节目:{{remaining}}/{{total}} 剩余", + "MovieRemaining": "电影: {{remaining}}/{{total}} 剩余", + "MusicRemaining": "音乐: {{remaining}}/{{total}} 剩余", + "TvDue": "电视节目:{{date}}", + "MovieDue": "电影: {{date}}", + "MusicDue": "音乐: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "已投票", + "VotesTab": "需要投票" + }, + "MediaDetails": { + "Denied": "已拒绝", + "Denied4K": "Denied 4K", + "Trailers": "预告片", + "RecommendationsTitle": "推荐", + "SimilarTitle": "相似", + "VideosTitle": "视频", + "AlbumsTitle": "专辑", + "RequestAllAlbums": "请求所有专辑", + "ClearSelection": "清除已选择", + "RequestSelectedAlbums": "请求选中的专辑", + "ViewCollection": "查看合集", + "NotEnoughInfo": "很遗憾,这个节目还没有足够的信息!", + "AdvancedOptions": "高级选项", + "AutoApproveOptions": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序并将被自动批准! 请注意,这是可选的,只需按请求跳过!", + "AutoApproveOptionsTv": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序并将被自动批准! 如果请求已经在 Sonarr 中并且您设置了它,我们将不会更改根目录或画质配置文件! 请注意,这是可选的,只需按请求跳过!", + "AutoApproveOptionsTvShort": "您可以在这里配置请求,一旦请求它将被发送到您的DVR应用程序! 如果请求已经在 Sonarr 中并且您设置了它,我们将不会更改根目录或画质配置文件! 请注意,这是可选的,只需按请求跳过!", + "QualityProfilesSelect": "请选择画质配置文件", + "RootFolderSelect": "请选择根目录", + "LanguageProfileSelect": "请选择语言配置文件", + "Status": "状态:", + "StatusValues": { + "Rumored": "有想法", + "Planned": "计划中", + "In Production": "制作中", + "Post Production": "后期处理", + "Released": "已发布", + "Running": "运行中", + "Returning Series": "回归系列", + "Ended": "已结束", + "Canceled": "已取消" + }, + "Seasons": "季:", + "Episodes": "集:", + "Availability": "可用性:", + "RequestStatus": "请求状态", + "Quality": "画质:", + "RootFolderOverride": "根目录覆盖:", + "QualityOverride": "质量覆盖:", + "Network": "网络:", + "GenresLabel": "流派", + "Genres": "流派", + "FirstAired": "首播", + "TheatricalRelease": "发行日:", + "DigitalRelease": "数字版发行:", + "Votes": "投票:", + "Runtime": "运行时间:", + "Minutes": "{{runtime}} 分钟", + "Revenue": "收入:", + "Budget": "预算:", + "Keywords": "关键词/标签:", + "Casts": { + "CastTitle": "演员" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "请求这个节目的每一季", + "FirstSeasonTooltip": "请求这个节目的第一季", + "LatestSeasonTooltip": "只请求这个节目的最新季", + "NoEpisodes": "很遗憾,目前还没有该节目的剧集数据!", + "SeasonNumber": "第{{number}} 季" + }, + "SonarrConfiguration": "Sonarr 配置", + "RadarrConfiguration": "Radarr 配置", + "RequestOnBehalf": "代表请求", + "PleaseSelectUser": "请选择用户", + "StreamingOn": "流媒体:", + "RequestedBy": "请求者:", + "RequestedByOn": "由 {{user}} 在 {{date}} 时请求", + "RequestDate": "请求日期:", + "DeniedReason": "被拒绝原因:", + "ReProcessRequest": "重新处理请求", + "ReProcessRequest4K": "Re-Process 4K Request", + "Music": { + "Type": "类型:", + "Country": "国家:", + "StartDate": "开始日期:", + "EndDate": "结束日期:" + } + }, + "Discovery": { + "PopularTab": "热门", + "TrendingTab": "趋势", + "UpcomingTab": "即将上映", + "SeasonalTab": "按季的", + "RecentlyRequestedTab": "最近请求", + "Movies": "电影", + "Combined": "混合", + "Tv": "电视节目", + "CardDetails": { + "Availability": "可用性", + "Studio": "工作室", + "Network": "网络", + "UnknownNetwork": "未知", + "RequestStatus": "请求状态", + "Director": "导演", + "InCinemas": "影院放映", + "FirstAired": "首播", + "Writer": "编剧", + "ExecProducer": "制作发行商" + }, + "NoSearch": "抱歉,没有符合您搜索条件的内容!" + }, + "UserPreferences": { + "Welcome": "{{username}},欢迎您!", + "OmbiLanguage": "语言", + "DarkMode": "深色模式", + "Updated": "更新成功", + "StreamingCountry": "流媒体国家", + "StreamingCountryDescription": "这是我们将显示流媒体信息的国家代码。 如果您在美国,请选择美国并获取美国相关的流媒体信息。", + "LanguageDescription": "您希望Ombi界面显示的语言", + "MobileQRCode": "手机二维码", + "LegacyApp": "启动旧版应用程序", + "NoQrCode": "请联系管理员以启用二维码", + "UserType": "用户类型:", + "ChangeDetails": "变更详情", + "NeedCurrentPassword": "您需要输入当前密码才能进行更改", + "CurrentPassword": "当前密码", + "EmailAddress": "邮箱地址", + "NewPassword": "新密码", + "NewPasswordConfirm": "确认新密码", + "Security": "安全选项", + "Profile": "用户信息", + "UpdatedYourInformation": "您的用户信息已更新", + "Unsubscribed": "取消订阅!" + }, + "UserTypeLabel": { + "1": "本地用户", + "2": "Plex用户", + "3": "Emby用户", + "4": "Emby Connect用户", + "5": "Jellyfin用户" + }, + "Paginator": { + "itemsPerPageLabel": "每页显示项目数:", + "nextPageLabel": "下一页", + "previousPageLabel": "上一页", + "firstPageLabel": "转到第一页", + "lastPageLabel": "转到最后一页", + "rangePageLabel1": "{{length}} 中的第0项", + "rangePageLabel2": "{{length}} 中的第{{startIndex}} 到{{endIndex}} 项" + } +} diff --git a/src/Ombi/wwwroot/translations/zh.json b/src/Ombi/wwwroot/translations/zh.json index 453ef7418..bc993ca0e 100644 --- a/src/Ombi/wwwroot/translations/zh.json +++ b/src/Ombi/wwwroot/translations/zh.json @@ -14,7 +14,9 @@ "Common": { "ContinueButton": "继续", "Available": "可播放", + "Available4K": "4K可播放", "Approved": "已批准", + "Approve4K": "批准4K", "Pending": "待审核", "PartiallyAvailable": "部分可播放", "Monitored": "监控中", @@ -24,8 +26,10 @@ "RequestDenied": "请求被拒绝", "NotRequested": "未请求", "Requested": "已请求", + "Requested4K": "请求4K", "Search": "搜索", "Request": "请求", + "Request4K": "请求4K", "Denied": "已拒绝", "Approve": "批准", "PartlyAvailable": "部分可播放", @@ -161,9 +165,13 @@ "ChangeRootFolder": "根目录", "ChangeQualityProfile": "画质配置文件", "MarkUnavailable": "标记为不可用", + "MarkUnavailable4K": "标记为不可播放4K", "MarkAvailable": "标记为可用", + "MarkAvailable4K": "标记为可播放4K", "Remove": "删除", "Deny": "拒绝", + "Deny4K": "拒绝4K", + "Has4KRequest": "已有4K请求", "DenyReason": "拒绝原因", "DeniedReason": "被拒绝原因", "Season": "季", @@ -199,6 +207,7 @@ "RequestPanel": { "Delete": "删除请求", "Approve": "批准请求", + "Approve4K": "批准4K请求", "ChangeAvailability": "标记为可用", "Deleted": "所选项目已删除", "Approved": "所选项目已批准" @@ -295,6 +304,7 @@ }, "MediaDetails": { "Denied": "已拒绝", + "Denied4K": "拒绝4K", "Trailers": "预告片", "RecommendationsTitle": "推荐", "SimilarTitle": "相似", @@ -363,6 +373,7 @@ "RequestDate": "请求日期:", "DeniedReason": "被拒绝原因:", "ReProcessRequest": "重新处理请求", + "ReProcessRequest4K": "重新处理4K请求", "Music": { "Type": "类型:", "Country": "国家:", From 98d16a747f7874e3fd3e1a64ff8b4bd00c50c012 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 28 Feb 2022 11:33:54 +0000 Subject: [PATCH 069/210] =?UTF-8?q?=F0=9F=8C=90=20Translations=20Update=20?= =?UTF-8?q?(#4524)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] --- src/Ombi.I18n/Resources/Texts.es.resx | 6 +++--- src/Ombi.I18n/Resources/Texts.it.resx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ombi.I18n/Resources/Texts.es.resx b/src/Ombi.I18n/Resources/Texts.es.resx index e0412c48a..2268cc561 100644 --- a/src/Ombi.I18n/Resources/Texts.es.resx +++ b/src/Ombi.I18n/Resources/Texts.es.resx @@ -145,12 +145,12 @@ Anular Suscripción - Album + Álbum - Movie + Película - TV Show + Serie TV \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.it.resx b/src/Ombi.I18n/Resources/Texts.it.resx index c418310b4..9d27090b7 100644 --- a/src/Ombi.I18n/Resources/Texts.it.resx +++ b/src/Ombi.I18n/Resources/Texts.it.resx @@ -148,9 +148,9 @@ Album - Movie + Film - TV Show + Serie TV \ No newline at end of file From 7e9f54fc80a09c938184e6be40ce5f49ce9673ef Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 28 Feb 2022 16:33:19 +0000 Subject: [PATCH 070/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]=20(#4526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/cs.json | 290 +++++++++++++------------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index 1f74f8127..b594f4b01 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -14,9 +14,9 @@ "Common": { "ContinueButton": "Pokračovat", "Available": "Dostupný", - "Available4K": "Available 4K", + "Available4K": "4K Dostupné", "Approved": "Schváleno", - "Approve4K": "Approve 4K", + "Approve4K": "Schválit 4K", "Pending": "Čeká na vyřízení", "PartiallyAvailable": "Částečně dostupné", "Monitored": "Monitorováno", @@ -26,31 +26,31 @@ "RequestDenied": "Žádost zamítnuta", "NotRequested": "Nevyžádáno", "Requested": "Vyžádáno", - "Requested4K": "Requested 4K", + "Requested4K": "Požádáno o 4K", "Search": "Hledat", "Request": "Žádost", - "Request4K": "Request 4K", + "Request4K": "Požádat o 4K", "Denied": "Zamítnuto", "Approve": "Schválit", "PartlyAvailable": "Částečně k dispozici", - "ViewDetails": "View Details", + "ViewDetails": "Zobrazit Podrobnosti", "Errors": { - "Validation": "Please check your entered values" + "Validation": "Zkontrolujte prosím zadané hodnoty" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "Cancel": "Zrušit", + "Submit": "Potvrdit", + "Update": "Upravit", + "tvShow": "TV Pořad", + "movie": "Film", "album": "Album" }, "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" + "EmailAddressPlaceholder": "Emailová Adresa", + "ResetPasswordButton": "Obnovit Heslo" }, "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", + "OnlineHeading": "Právě Online", + "OnlineParagraph": "Server je momentálně offline", "PartiallyOnlineHeading": "Partially Online", "PartiallyOnlineParagraph": "The media server is partially online.", "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", @@ -60,84 +60,84 @@ "CheckPageForUpdates": "Check this page for continuous site updates." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Stránka nenalezena" }, "NavigationBar": { - "Discover": "Discover", + "Discover": "Objevit nové", "Search": "Hledat", - "Requests": "Requests", - "UserManagement": "Users", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", + "Requests": "Žádosti", + "UserManagement": "Uživatelé", + "Issues": "Problémy", + "Vote": "Hlasuj", + "Donate": "Přispějte!", + "DonateLibraryMaintainer": "Podpořte správce knihovny", "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", - "ChangeTheme": "Change Theme", - "Calendar": "Calendar", - "UserPreferences": "Preferences", + "Settings": "Nastavení", + "Welcome": "Vítejte zpět, {{username}}!", + "UpdateDetails": "Upravit detaily", + "Logout": "Odhlásit se", + "OpenMobileApp": "Otevřít mobilní aplikaci", + "RecentlyAdded": "Naposledy přidané", + "ChangeTheme": "Změnit motiv", + "Calendar": "Kalendář", + "UserPreferences": "Nastavení", "FeatureSuggestion": "Features", "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", "Filter": { - "Movies": "Movies", - "TvShows": "TV Shows", - "Music": "Music", - "People": "People" + "Movies": "Filmy", + "TvShows": "TV pořady", + "Music": "Hudba", + "People": "Lidé" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", + "MorningWelcome": "Dobré ráno!", + "AfternoonWelcome": "Dobré odpoledne!", "EveningWelcome": "Good evening!" }, "Search": { "Title": "Hledat", "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", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "Play On Plex", - "ViewOnEmby": "Play On Emby", - "ViewOnJellyfin": "Play On Jellyfin", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "MoviesTab": "Filmy", + "TvTab": "TV pořady", + "MusicTab": "Hudba", + "AdvancedSearch": "Můžete vyplnit některou z níže uvedených možností pro objevení nových médií. Všechny výsledky jsou seřazeny podle oblíbenosti", + "AdvancedSearchHeader": "Pokročilé vyhledávání", + "Suggestions": "Návrhy", + "NoResults": "Omlouváme se, ale nenašli jsme žádné výsledky!", + "DigitalDate": "Digitální vydání: {{date}}", + "TheatricalRelease": "V kinech: {{date}}", + "ViewOnPlex": "Přehrát v Plex", + "ViewOnEmby": "Přehrát v Emby", + "ViewOnJellyfin": "Přehrát v Jellyfiny", + "RequestAdded": "Žádost o {{title}} byl úspěšně přidán", + "Similar": "Podobné", + "Refine": "Zpřesnit", + "SearchBarPlaceholder": "Pište sem pro vyhledávání", "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", + "PopularMovies": "Populární filmy", + "UpcomingMovies": "Nadcházející filmy", + "TopRatedMovies": "Nejlépe hodnocené filmy", "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "HomePage": "Úvodní stránka", + "Trailer": "Upoutávka" }, "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}}" + "Popular": "Oblíbené", + "Trending": "Žhavé", + "MostWatched": "Nejsledovanější", + "MostAnticipated": "Nejočekávanější", + "Results": "Výsledky", + "AirDate": "Odvysíláno:", + "AllSeasons": "Všechny série", + "FirstSeason": "První série", + "LatestSeason": "Nejnovější série", + "Select": "Vyberte ...", + "SubmitRequest": "Odeslat žádost", + "Season": "Série {{seasonNumber}}", + "SelectAllInSeason": "Vybrat vše v sérii {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", + "AdvancedSearchInstructions": "Vyberte prosím jaký typ médií hledáte:", + "YearOfRelease": "Rok vydání", "SearchGenre": "Search Genre", "SearchKeyword": "Search Keyword", "SearchProvider": "Search Provider", @@ -176,61 +176,61 @@ "DeniedReason": "Denied Reason", "Season": "Season", "GridTitle": "Title", - "AirDate": "Air Date", - "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 ▼", + "AirDate": "Odvysíláno", + "GridStatus": "Stav", + "ReportIssue": "Nahlásit problém", + "Filter": "Třídit", + "Sort": "Seřadit", + "SeasonNumberHeading": "Série: {{seasonNumber}}", + "SortTitleAsc": "Název ▲", + "SortTitleDesc": "Název ▼", + "SortRequestDateAsc": "Datum žádosti ▲", + "SortRequestDateDesc": "Datum žádosti ▼", + "SortStatusAsc": "Stav ▲", + "SortStatusDesc": "Stav ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", + "Quota": "Zbývá {{remaining}}/{{total}} požadavků", "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" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", - "RequestsTitle": "Title", - "Details": "Details", - "Options": "Options", + "AllRequests": "Všechny požadavky", + "PendingRequests": "Nevyřízené požadavky", + "ProcessingRequests": "Zpracovávání požadavku", + "AvailableRequests": "Dostupné požadavky", + "DeniedRequests": "Zamítnuté požadavky", + "RequestsToDisplay": "Požadavky na zobrazení", + "RequestsTitle": "Název", + "Details": "Podrobnosti", + "Options": "Možnosti", "RequestPanel": { - "Delete": "Delete Request", - "Approve": "Approve Request", - "Approve4K": "Approve 4K Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Delete": "Odstranit požadavek", + "Approve": "Schválit požadavek", + "Approve4K": "Schválit 4K požadavek", + "ChangeAvailability": "Označit jako dostupné", + "Deleted": "Vybrané položky úspěšně odstraněny", + "Approved": "Vybrané položky byly úspěšně schváleny" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", - "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", - "RequestCollection": "Request Collection", - "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", - "NeedToSelectEpisodes": "You need to select some episodes!", - "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "SuccessfullyApproved": "Úspěšně schváleno", + "SuccessfullyDeleted": "Požadavek byl úspěšně odstraněn", + "NowAvailable": "Požadavek je nyní k dispozici", + "NowUnavailable": "Požadavek je nyní nedostupný", + "SuccessfullyReprocessed": "Požadavek úspěšně znovu zprocesován", + "DeniedRequest": "Odmítnutý požadavek", + "RequestCollection": "Požádat o kolekci", + "CollectionSuccesfullyAdded": "Kolekce {{name}} byla úspěšně přidána!", + "NeedToSelectEpisodes": "Musíte vybrat nějaké epizody!", + "RequestAddedSuccessfully": "Žádost o {{title}} byla úspěšně přidána", "ErrorCodes": { - "AlreadyRequested": "This has already been requested", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", + "AlreadyRequested": "O toto již bylo požádáno", + "EpisodesAlreadyRequested": "Již máme epizody od této série vyžádány", "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", - "RequestDoesNotExist": "Request does not exist", + "NoPermissions": "Nemáte dostatečná oprávnění!", + "RequestDoesNotExist": "Požadavek neexistuje", "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", - "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", + "NoPermissionsRequestMovie": "Nemáte oprávnění k vyžádání filmu", + "NoPermissionsRequestTV": "Nemáte oprávnění požádat o TV Pořad", "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", @@ -283,46 +283,46 @@ }, "Filter": { "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", + "FilterHeaderAvailability": "Dostupnost", + "FilterHeaderRequestStatus": "Stav", "Approved": "Schváleno", "PendingApproval": "Čeká na schválení", - "WatchProviders": "Watch Providers", - "Keywords": "Keywords" + "WatchProviders": "Online poskytovatelé", + "Keywords": "Klíčová slova" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} zbývá", + "MovieRemaining": "Filmy: {{remaining}}/{{total}} zbývá", + "MusicRemaining": "Hudba: {{remaining}}/{{total}} zbývá", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Odhlasováno", + "VotesTab": "Potřebné hlasy" }, "MediaDetails": { "Denied": "Zamítnuto", - "Denied4K": "Denied 4K", - "Trailers": "Trailers", - "RecommendationsTitle": "Recommendations", - "SimilarTitle": "Similar", - "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", - "RequestSelectedAlbums": "Request Selected Albums", - "ViewCollection": "View Collection", - "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", - "AdvancedOptions": "Advanced Options", + "Denied4K": "4K Zamítnuto", + "Trailers": "Upoutávky", + "RecommendationsTitle": "Doporučení", + "SimilarTitle": "Podobné", + "VideosTitle": "Videa", + "AlbumsTitle": "Alba", + "RequestAllAlbums": "Požádat o všechna alba", + "ClearSelection": "Vyčistit výběr", + "RequestSelectedAlbums": "Požádat o vybraná alba", + "ViewCollection": "Zobrazit kolekci", + "NotEnoughInfo": "Bohužel o tomto seriálu zatím není dostatek informací!", + "AdvancedOptions": "Pokročilá nastavení", "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "QualityProfilesSelect": "Select A Quality Profile", - "RootFolderSelect": "Select A Root Folder", - "LanguageProfileSelect": "Select A Language Profile", - "Status": "Status:", + "QualityProfilesSelect": "Vyberte Profil kvality", + "RootFolderSelect": "Vyberte kořenovou složku", + "LanguageProfileSelect": "Vyberte jazykový profil", + "Status": "Stav:", "StatusValues": { "Rumored": "Rumored", "Planned": "Planned", From f292006a08894a8d0ba899c8c6e9fe863e558dda Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 28 Feb 2022 17:33:08 +0000 Subject: [PATCH 071/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/cs.json | 284 +++++++++++++------------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index b594f4b01..852d3cceb 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -51,8 +51,8 @@ "LandingPage": { "OnlineHeading": "Právě Online", "OnlineParagraph": "Server je momentálně offline", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", + "PartiallyOnlineHeading": "Částečně online", + "PartiallyOnlineParagraph": "Mediální server je částečně online.", "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", "OfflineHeading": "Currently Offline", @@ -82,7 +82,7 @@ "ChangeTheme": "Změnit motiv", "Calendar": "Kalendář", "UserPreferences": "Nastavení", - "FeatureSuggestion": "Features", + "FeatureSuggestion": "Funkce", "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", "Filter": { "Movies": "Filmy", @@ -92,11 +92,11 @@ }, "MorningWelcome": "Dobré ráno!", "AfternoonWelcome": "Dobré odpoledne!", - "EveningWelcome": "Good evening!" + "EveningWelcome": "Dobrý večer!" }, "Search": { "Title": "Hledat", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "Paragraph": "Chcete sledovat něco co je aktuálně nedostupné? Není problém, zkuste to najít a požádat o to!", "MoviesTab": "Filmy", "TvTab": "TV pořady", "MusicTab": "Hudba", @@ -117,7 +117,7 @@ "PopularMovies": "Populární filmy", "UpcomingMovies": "Nadcházející filmy", "TopRatedMovies": "Nejlépe hodnocené filmy", - "NowPlayingMovies": "Now Playing Movies", + "NowPlayingMovies": "Právě hrajeme", "HomePage": "Úvodní stránka", "Trailer": "Upoutávka" }, @@ -138,44 +138,44 @@ }, "AdvancedSearchInstructions": "Vyberte prosím jaký typ médií hledáte:", "YearOfRelease": "Rok vydání", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", + "SearchGenre": "Vyhledávání podle žánru", + "SearchKeyword": "Vyhledávání podle klíčových slov", "SearchProvider": "Search Provider", "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" }, "Requests": { - "Title": "Requests", + "Title": "Žádosti", "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "ArtistName": "Artist", - "AlbumName": "Album Name", - "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", + "MoviesTab": "Filmy", + "ArtistName": "Umělec", + "AlbumName": "Název alba", + "TvTab": "TV pořady", + "MusicTab": "Hudba", + "RequestedBy": "Požadováno od", + "Status": "Stav", + "RequestStatus": "Stav požadavku", + "Denied": " Zamítnuto:", + "TheatricalRelease": "V kinech od: {{date}}", + "ReleaseDate": "Vydáno: {{date}}", + "TheatricalReleaseSort": "Vydáno v Kinech", + "DigitalRelease": "Digitální vydání: {{date}}", + "RequestDate": "Datum požadavku", "QualityOverride": "Quality Override:", "RootFolderOverride": "Root Folder Override:", "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkUnavailable4K": "Mark Unavailable 4K", - "MarkAvailable": "Mark Available", - "MarkAvailable4K": "Mark Available 4K", - "Remove": "Remove", - "Deny": "Deny", - "Deny4K": "Deny 4K", - "Has4KRequest": "Has 4K Request", - "DenyReason": "Deny Reason", - "DeniedReason": "Denied Reason", - "Season": "Season", - "GridTitle": "Title", + "MarkUnavailable": "Označit jako nedostupné", + "MarkUnavailable4K": "Označit jako nedostupné ve 4K", + "MarkAvailable": "Označit jako dostupné", + "MarkAvailable4K": "Označit jako dostupné ve 4K", + "Remove": "Odstranit", + "Deny": "Zamítnout", + "Deny4K": "Zamítnout 4 K", + "Has4KRequest": "Má 4K požadavek", + "DenyReason": "Důvod zamítnutí", + "DeniedReason": "Důvod zamítnutí", + "Season": "Série", + "GridTitle": "Název", "AirDate": "Odvysíláno", "GridStatus": "Stav", "ReportIssue": "Nahlásit problém", @@ -248,41 +248,41 @@ "PendingTitle": "Pending Issues", "InProgressTitle": "In Progress Issues", "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Count": "Count", - "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", + "ColumnTitle": "Název", + "Count": "Počet", + "Category": "Kategorie", + "Status": "Stav", + "Details": "Podrobnosti", + "Description": "Popis", + "NoComments": "Žádné komentáře!", + "MarkInProgress": "Označit jako probíhající", + "MarkResolved": "Označit jako vyřešené", + "SendMessageButton": "Odeslat", + "Subject": "Předmět", + "Comments": "Komentáře", + "WriteMessagePlaceholder": "Sem napište zprávu…", + "ReportedBy": "Nahlášeno", "IssueDialog": { - "Title": "Report an issue", - "DescriptionPlaceholder": "Please describe the issue", - "TitlePlaceholder": "Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated": "Issue has been created" + "Title": "Náhlásit chybu", + "DescriptionPlaceholder": "Popište problém", + "TitlePlaceholder": "Krátký název vašeho problému", + "SelectCategory": "Vybrat kategorii", + "IssueCreated": "Problém byl vytvořen" }, "Outstanding": "There are outstanding issues", "ResolvedDate": "Resolved date", "CreatedDate": "Raised on", "MarkedAsResolved": "This issue has now been marked as resolved!", "MarkedAsInProgress": "This issue has now been marked as in progress!", - "Delete": "Delete issue", + "Delete": "Smazat případ", "DeletedIssue": "Issue has been deleted", "Chat": "Chat", "EnterYourMessage": "Enter Your Message", "Requested": "Vyžádáno", - "UserOnDate": "{{user}} on {{date}}" + "UserOnDate": "{{user}} dne {{date}}" }, "Filter": { - "ClearFilter": "Clear Filter", + "ClearFilter": "Zrušit filtry", "FilterHeaderAvailability": "Dostupnost", "FilterHeaderRequestStatus": "Stav", "Approved": "Schváleno", @@ -325,122 +325,122 @@ "Status": "Stav:", "StatusValues": { "Rumored": "Rumored", - "Planned": "Planned", - "In Production": "In Production", - "Post Production": "Post Production", - "Released": "Released", - "Running": "Running", - "Returning Series": "Returning Series", - "Ended": "Ended", - "Canceled": "Canceled" + "Planned": "Naplánováno", + "In Production": "V produkci", + "Post Production": "V post-produkci", + "Released": "Vydáno", + "Running": "Právě probíhá", + "Returning Series": "Vracející se seriál", + "Ended": "Ukončeno", + "Canceled": "Zrušeno" }, - "Seasons": "Seasons:", - "Episodes": "Episodes:", - "Availability": "Availability:", - "RequestStatus": "Request Status", - "Quality": "Quality:", + "Seasons": "Série:", + "Episodes": "Epizody:", + "Availability": "Dostupnost:", + "RequestStatus": "Stav požadavku", + "Quality": "Kvalita:", "RootFolderOverride": "Root Folder Override:", "QualityOverride": "Quality Override:", - "Network": "Network:", - "GenresLabel": "Genres:", - "Genres": "Genres", - "FirstAired": "First Aired:", - "TheatricalRelease": "Release:", - "DigitalRelease": "Digital Release:", - "Votes": "Votes:", + "Network": "Síť:", + "GenresLabel": "Žánry:", + "Genres": "Žánry", + "FirstAired": "Poprvé vysíláno:", + "TheatricalRelease": "Vydáno:", + "DigitalRelease": "Digitální vydání:", + "Votes": "Hlasy:", "Runtime": "Runtime:", - "Minutes": "{{runtime}} Minutes", - "Revenue": "Revenue:", - "Budget": "Budget:", - "Keywords": "Keywords/Tags:", + "Minutes": "{{runtime}} minut", + "Revenue": "Příjmy:", + "Budget": "Rozpočet:", + "Keywords": "Klíčová slova/Tagy:", "Casts": { - "CastTitle": "Cast" + "CastTitle": "Hrají" }, "EpisodeSelector": { - "AllSeasonsTooltip": "This will request every season for this show", - "FirstSeasonTooltip": "This will only request the First Season for this show", - "LatestSeasonTooltip": "This will only request the Latest Season for this show", + "AllSeasonsTooltip": "Toto vyžádá všechny serie pro tento pořad", + "FirstSeasonTooltip": "Toto vyžádá jen první sérii pro tento pořad", + "LatestSeasonTooltip": "Toto vyžádá jen poslední sérii pro tento pořad", "NoEpisodes": "There unfortunately is no episode data for this show yet!", - "SeasonNumber": "Season {{number}}" + "SeasonNumber": "Série {{number}}" }, "SonarrConfiguration": "Sonarr Configuration", "RadarrConfiguration": "Radarr Configuration", "RequestOnBehalf": "Request on behalf of", "PleaseSelectUser": "Please select a user", - "StreamingOn": "Streaming On:", - "RequestedBy": "Requested By:", - "RequestedByOn": "Requested By {{user}} on {{date}}", - "RequestDate": "Request Date:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", - "ReProcessRequest4K": "Re-Process 4K Request", + "StreamingOn": "Streamuje na:", + "RequestedBy": "Požadováno od:", + "RequestedByOn": "Požádáno uživatelem {{user}} dne {{date}}", + "RequestDate": "Datum požadavku:", + "DeniedReason": "Důvod zamítnutí:", + "ReProcessRequest": "Znovu zpracovat žádost", + "ReProcessRequest4K": "Znovu zpracovat 4K žádost", "Music": { - "Type": "Type:", - "Country": "Country:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" + "Type": "Typ:", + "Country": "Stát:", + "StartDate": "Datum zahájení:", + "EndDate": "Datum ukončení:" } }, "Discovery": { - "PopularTab": "Popular", - "TrendingTab": "Trending", - "UpcomingTab": "Upcoming", - "SeasonalTab": "Seasonal", - "RecentlyRequestedTab": "Recently Requested", - "Movies": "Movies", - "Combined": "Combined", + "PopularTab": "Oblíbené", + "TrendingTab": "Žhavé", + "UpcomingTab": "Nadcházející", + "SeasonalTab": "Sezónní", + "RecentlyRequestedTab": "Nedávno vyžádané", + "Movies": "Filmy", + "Combined": "Kombinované", "Tv": "TV", "CardDetails": { - "Availability": "Availability", + "Availability": "Dostupnost", "Studio": "Studio", - "Network": "Network", - "UnknownNetwork": "Unknown", - "RequestStatus": "Request Status", - "Director": "Director", - "InCinemas": "In Cinemas", - "FirstAired": "First Aired", - "Writer": "Writer", - "ExecProducer": "Exec Producer" + "Network": "Síť", + "UnknownNetwork": "Neznámé", + "RequestStatus": "Stav požadavku", + "Director": "Režisér", + "InCinemas": "V Kinech", + "FirstAired": "Poprvé vysíláno", + "Writer": "Autor", + "ExecProducer": "Exekutivní Producent" }, - "NoSearch": "Sorry, nothing matches your search!" + "NoSearch": "Vašemu hledání neodpovídají žádné shody!" }, "UserPreferences": { - "Welcome": "Welcome {{username}}!", - "OmbiLanguage": "Language", - "DarkMode": "Dark Mode", - "Updated": "Successfully Updated", + "Welcome": "Vítejte, {{username}}!", + "OmbiLanguage": "Jazyk", + "DarkMode": "Tmavý režim", + "Updated": "Úspěšně upraveno", "StreamingCountry": "Streaming Country", "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", - "MobileQRCode": "Mobile QR Code", + "MobileQRCode": "Mobilní QR Code", "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", - "ChangeDetails": "Change Details", - "NeedCurrentPassword": "You need your current password to make any changes here", - "CurrentPassword": "Current Password", - "EmailAddress": "Email Address", - "NewPassword": "New Password", - "NewPasswordConfirm": "New Password Confirm", - "Security": "Security", - "Profile": "Profile", - "UpdatedYourInformation": "Updated your information", - "Unsubscribed": "Unsubscribed!" + "NoQrCode": "Pro povolení QR kódů kontaktujte svého administrátora", + "UserType": "Typ uživatele:", + "ChangeDetails": "Změnit podrobnosti", + "NeedCurrentPassword": "K provedení změn potřebujete své současné heslo", + "CurrentPassword": "Aktuální heslo", + "EmailAddress": "Emailová Adresa", + "NewPassword": "Nové heslo", + "NewPasswordConfirm": "Potvrzení nového hesla", + "Security": "Bezpečnost", + "Profile": "Profil", + "UpdatedYourInformation": "Informace aktualizovány", + "Unsubscribed": "Odhlášeno!" }, "UserTypeLabel": { - "1": "Local User", - "2": "Plex User", + "1": "Místní Uživatel", + "2": "Plex uživatel", "3": "Emby User", - "4": "Emby Connect User", - "5": "Jellyfin User" + "4": "Emby Connect uživatel", + "5": "Jellyfin uživatel" }, "Paginator": { - "itemsPerPageLabel": "Items per page:", - "nextPageLabel": "Next page", - "previousPageLabel": "Previous page", - "firstPageLabel": "First page", - "lastPageLabel": "Last page", - "rangePageLabel1": "0 of {{length}}", - "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + "itemsPerPageLabel": "Položek na stránce:", + "nextPageLabel": "Další stránka", + "previousPageLabel": "Předchozí stránka", + "firstPageLabel": "První stránka", + "lastPageLabel": "Poslední strana", + "rangePageLabel1": "0 z {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} z {{length}}" } } From 132f4d4e609b7fb7e37f38ee2f395926e2911abe Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 28 Feb 2022 17:33:10 +0000 Subject: [PATCH 072/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi.I18n/Resources/Texts.cs.resx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Ombi.I18n/Resources/Texts.cs.resx b/src/Ombi.I18n/Resources/Texts.cs.resx index f619ffb16..80d3b2d95 100644 --- a/src/Ombi.I18n/Resources/Texts.cs.resx +++ b/src/Ombi.I18n/Resources/Texts.cs.resx @@ -118,39 +118,39 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - New Albums + Nová alba - New Movies + Nové filmy - New TV + Nové TV Pořady - Genres: + Žánry: - Type: + Typ: - Season: + Série: - Episodes: + Epizody: Powered by - Unsubscribe + Odhlásit odběr Album - Movie + Film - TV Show + TV Pořad \ No newline at end of file From 6fcaecf80b766f2d43ac7082d74364238e1638b7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 28 Feb 2022 18:34:23 +0000 Subject: [PATCH 073/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index 852d3cceb..d0dadf58c 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -348,7 +348,7 @@ "TheatricalRelease": "Vydáno:", "DigitalRelease": "Digitální vydání:", "Votes": "Hlasy:", - "Runtime": "Runtime:", + "Runtime": "Délka:", "Minutes": "{{runtime}} minut", "Revenue": "Příjmy:", "Budget": "Rozpočet:", From 68600f3b45376e12dd2ef263d81ca4040c84cbca Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 08:25:38 +0000 Subject: [PATCH 074/210] fix(details): :bug: Fixed the missing Play on Media server button for 4k content #4529 --- .../media-details/components/movie/movie-details.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 2a29b30e6..d3997fb1c 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -42,7 +42,7 @@
- + {{'Search.ViewOnPlex' | translate}} From 19fe4e342efe5578c26ab8ba7ee2f2e64bbc9418 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 08:43:45 +0000 Subject: [PATCH 075/210] fix(requests): :bug: Fixed the issue where we could no longer approve TV Requests from the requests list --- src/Ombi.Store/Entities/Requests/BaseRequest.cs | 2 +- src/Ombi.Store/Entities/Requests/MovieRequests.cs | 3 +++ .../components/movies-grid/movies-grid.component.ts | 4 ++-- .../components/options/request-options.component.html | 2 +- .../components/options/request-options.component.ts | 8 +++++--- .../requests-list/components/requests-list.component.ts | 4 ++-- .../requests-list/components/tv-grid/tv-grid.component.ts | 4 ++-- 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Ombi.Store/Entities/Requests/BaseRequest.cs b/src/Ombi.Store/Entities/Requests/BaseRequest.cs index 596041a51..f26bcc8ba 100644 --- a/src/Ombi.Store/Entities/Requests/BaseRequest.cs +++ b/src/Ombi.Store/Entities/Requests/BaseRequest.cs @@ -24,6 +24,6 @@ namespace Ombi.Store.Entities.Requests [NotMapped] - public bool CanApprove => !Approved && !Available; + public virtual bool CanApprove => !Approved && !Available; } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs index 49189a387..415efded2 100644 --- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs +++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs @@ -81,5 +81,8 @@ namespace Ombi.Store.Entities.Requests return string.Empty; } } + + [NotMapped] + public override bool CanApprove => !Approved && !Available || !Approved4K && !Available4K; } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index de3f8de39..b283821ed 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -5,6 +5,7 @@ import { Observable, combineLatest, forkJoin, merge, of as observableOf } from ' import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { AuthService } from "../../../auth/auth.service"; +import { FeaturesFacade } from "../../../state/features/features.facade"; import { MatPaginator } from "@angular/material/paginator"; import { MatSort } from "@angular/material/sort"; import { MatTableDataSource } from "@angular/material/table"; @@ -13,7 +14,6 @@ import { RequestServiceV2 } from "../../../services/requestV2.service"; import { SelectionModel } from "@angular/cdk/collections"; import { StorageService } from "../../../shared/storage/storage-service"; import { TranslateService } from "@ngx-translate/core"; -import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./movies-grid.component.html", @@ -43,7 +43,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { private storageKeyGridCount = "Movie_DefaultGridCount"; private storageKeyCurrentFilter = "Movie_DefaultFilter"; - @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean }>(); + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }>(); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html index 72c0cdce3..dc1c04467 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -2,7 +2,7 @@ {{'Requests.RequestPanel.Delete' | translate}} - + {{'Requests.RequestPanel.Approve' | translate}} diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index 673f978e7..30a55335c 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef } from '@angular/material/bottom-sheet'; import { MessageService, RequestService } from '../../../services'; import { IRequestEngineResult, RequestType } from '../../../interfaces'; @@ -10,7 +10,7 @@ import { firstValueFrom, Observable } from 'rxjs'; selector: 'request-options', templateUrl: './request-options.component.html', }) -export class RequestOptionsComponent { +export class RequestOptionsComponent implements OnInit { public RequestType = RequestType; @@ -19,6 +19,9 @@ export class RequestOptionsComponent { private messageService: MessageService, private bottomSheetRef: MatBottomSheetRef, private translate: TranslateService) { } + ngOnInit(): void { + console.log(this.data); + } public async delete() { var request: Observable; @@ -69,7 +72,6 @@ export class RequestOptionsComponent { public async changeAvailability() { if (this.data.type === RequestType.movie) { - // TODO 4K await firstValueFrom(this.requestService.markMovieAvailable({id: this.data.id, is4K: false})) } if (this.data.type === RequestType.album) { diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts index e5bf34fa4..8117e0c22 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts @@ -12,8 +12,8 @@ export class RequestsListComponent { constructor(private bottomSheet: MatBottomSheet) { } - public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean }) { - const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin, has4kRequest: event.has4kRequest } }); + public onOpenOptions(event: { request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }) { + const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove, manageOwnRequests: event.manageOwnRequests, isAdmin: event.isAdmin, has4kRequest: event.has4kRequest, hasRegularRequest: event.hasRegularRequest } }); ref.afterDismissed().subscribe((result) => { if(!result) { diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts index 1d84fe3f0..25c552924 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts @@ -34,7 +34,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { private storageKeyGridCount = "Tv_DefaultGridCount"; private storageKeyCurrentFilter = "Tv_DefaultFilter"; - @Output() public onOpenOptions = new EventEmitter<{request: any, filter: any, onChange: any}>(); + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any, manageOwnRequests: boolean, isAdmin: boolean, has4kRequest: boolean, hasRegularRequest: boolean }>(); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; @@ -108,7 +108,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: false }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: false, hasRegularRequest: true }; this.onOpenOptions.emit(data); } From dcfd688c8d2337e55fa9c6c33b7c3e80fc560cda Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 08:53:18 +0000 Subject: [PATCH 076/210] fix(discover): :bug: Fixed the issue where there was an option on the discover to request 4k shows (that's not supported currently) --- .../card/discover-card.component.html | 44 +++++++++++-------- .../card/discover-card.component.ts | 8 ++-- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html index b7593902f..6bd515e27 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html @@ -20,24 +20,32 @@
-
- -
-
- - - - - -
+ +
+ +
+ + + + + +
+
+ +
+ +
+
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 470559b0d..84488eef7 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -26,6 +26,7 @@ export class DiscoverCardComponent implements OnInit { public hide: boolean; public fullyLoaded = false; public loading: boolean; + public allow4KButton: boolean = false; public requestable: boolean; @@ -41,6 +42,7 @@ export class DiscoverCardComponent implements OnInit { this.getExtraTvInfo(); } if (this.result.type == RequestType.movie) { + this.allow4KButton = true; this.getExtraMovieInfo(); } if (this.result.type == RequestType.album) { @@ -169,9 +171,9 @@ export class DiscoverCardComponent implements OnInit { private updateMovieItem(updated: ISearchMovieResultV2) { this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/"; - this.result.available = updated.available; - this.result.requested = updated.requested; - this.result.approved = updated.approved; + this.result.available = updated.available || updated.available4K; + this.result.requested = updated.requested || updated.has4KRequest; + this.result.approved = updated.approved || updated.available4K; this.result.rating = updated.voteAverage; this.result.overview = updated.overview; this.result.imdbid = updated.imdbId; From a3046e386cf3e84c31c030e66bccad1e52a01a2e Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 09:17:11 +0000 Subject: [PATCH 077/210] test: fixed unit tests --- src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs | 7 ++++--- src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs index 5aaa624f9..f1af160d6 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs @@ -429,6 +429,7 @@ namespace Ombi.Core.Tests.Engine Id = "id1" }; var lastWeek = new DateTime(2020, 09, 05).AddMonths(-1).AddDays(-1); + var today = new DateTime(2020, 09, 15, 13, 0, 0); var log = new List { new RequestLog @@ -441,7 +442,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) @@ -474,7 +475,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) @@ -514,7 +515,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMovieRequests(user); + var result = await _subject.GetRemainingMovieRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) diff --git a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs index c23c15578..f7291409b 100644 --- a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs +++ b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs @@ -514,7 +514,7 @@ namespace Ombi.Core.Tests.Engine var repoMock = _mocker.GetMock>(); repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object); - var result = await _subject.GetRemainingMusicRequests(user); + var result = await _subject.GetRemainingMusicRequests(user, today); Assert.That(result, Is.InstanceOf() .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) From 5a9a050d6e93d4b4b8546ba280374a68cbbc1dbd Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Mar 2022 09:20:50 +0000 Subject: [PATCH 078/210] chore(release): :rocket: v4.13.1 --- CHANGELOG.md | 24 ++++++++++++------------ version.json | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98bc04767..d3bf8bb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [4.13.1](https://github.com/Ombi-app/Ombi/compare/v4.13.0...v4.13.1) (2022-03-01) + + +### Bug Fixes + +* **details:** :bug: Fixed the missing Play on Media server button for 4k content [#4529](https://github.com/Ombi-app/Ombi/issues/4529) ([68600f3](https://github.com/Ombi-app/Ombi/commit/68600f3b45376e12dd2ef263d81ca4040c84cbca)) +* **discover:** :bug: Fixed the issue where there was an option on the discover to request 4k shows (that's not supported currently) ([dcfd688](https://github.com/Ombi-app/Ombi/commit/dcfd688c8d2337e55fa9c6c33b7c3e80fc560cda)) +* **requests:** :bug: Fixed the issue where we could no longer approve TV Requests from the requests list ([19fe4e3](https://github.com/Ombi-app/Ombi/commit/19fe4e342efe5578c26ab8ba7ee2f2e64bbc9418)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([#4526](https://github.com/Ombi-app/Ombi/issues/4526)) ([7e9f54f](https://github.com/Ombi-app/Ombi/commit/7e9f54fc80a09c938184e6be40ce5f49ce9673ef)) + + + # [4.13.0](https://github.com/Ombi-app/Ombi/compare/v4.12.7...v4.13.0) (2022-02-25) @@ -342,15 +354,3 @@ -## [4.6.5](https://github.com/Ombi-app/Ombi/compare/v4.6.4...v4.6.5) (2021-11-15) - - -### Bug Fixes - -* **issues:** :bug: Added the issue category to the issue 'cards' [#4403](https://github.com/Ombi-app/Ombi/issues/4403) ([a3739f3](https://github.com/Ombi-app/Ombi/commit/a3739f375c49f48e34da12f0a74e4e068f12ab40)) -* **issues:** :bug: Added the issues back to the details page for TV Shows ([0225000](https://github.com/Ombi-app/Ombi/commit/02250000c08a253e57d8a0a855c2d30b8a1e5baa)) -* **issues:** :bug: Fixed an issue where you couldn't navigate to the details page from TV issues ([1a2825b](https://github.com/Ombi-app/Ombi/commit/1a2825bf3839b891b16e1dde4030afe53efe090e)) -* **issues:** :bug: Fixed where we did not show the poster when an issue is raised for media we do not have a request for [#4402](https://github.com/Ombi-app/Ombi/issues/4402) ([15e37b5](https://github.com/Ombi-app/Ombi/commit/15e37b532a83097dbdf1a9fea3eead7d0e211898)) - - - diff --git a/version.json b/version.json index b609ccf58..f466b9e00 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.13.0" + "version": "4.13.1" } \ No newline at end of file From 073f1c946b8a299388130c6cf113989b70a1b678 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 09:50:10 +0000 Subject: [PATCH 079/210] refactor: Made some small changes around the syncs to add in 4k to the radarr sync --- .../Jobs/ArrAvailabilityChecker.cs | 34 +++++++++++++------ .../Jobs/Plex/PlexAvailabilityChecker.cs | 7 ++-- src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 2 -- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs index 0020bb24f..d20f906c6 100644 --- a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs @@ -73,23 +73,37 @@ namespace Ombi.Schedule.Jobs.Radarr private async Task ProcessMovies() { var availableRadarrMovies = _radarrRepo.GetAll().Where(x => x.HasFile).ToImmutableHashSet(); - var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available).ToImmutableHashSet(); + var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)).ToImmutableHashSet(); var itemsForAvailability = new List(); foreach (var movieRequest in unavailableMovieRequests) { // Do we have an item in the radarr list - var available = availableRadarrMovies.Any(x => x.TheMovieDbId == movieRequest.TheMovieDbId); - if (available) + var available = availableRadarrMovies.FirstOrDefault(x => x.TheMovieDbId == movieRequest.TheMovieDbId); + if (available != null) { _logger.LogInformation($"Found move '{movieRequest.Title}' available in Radarr"); - movieRequest.Available = true; - movieRequest.MarkedAsAvailable = DateTime.UtcNow; - itemsForAvailability.Add(new AvailabilityModel + if (available.Has4K && !movieRequest.Available4K) { - Id = movieRequest.Id, - RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty - }); + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + movieRequest.Available4K = true; + movieRequest.MarkedAsAvailable4K = DateTime.UtcNow; + } + if (available.HasRegular) + { + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + movieRequest.Available = true; + movieRequest.MarkedAsAvailable = DateTime.UtcNow; + } + await _movies.SaveChangesAsync(); } } @@ -97,7 +111,6 @@ namespace Ombi.Schedule.Jobs.Radarr { await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Radarr Availability Checker found some new available movies!"); - await _movies.SaveChangesAsync(); } foreach (var item in itemsForAvailability) { @@ -110,7 +123,6 @@ namespace Ombi.Schedule.Jobs.Radarr Recipient = item.RequestedUser }); } - } public async Task ProcessTvShows() diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index a6e1b205b..d8dc273d2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -211,6 +211,7 @@ namespace Ombi.Schedule.Jobs.Plex movie.Available4K = true; movie.Approved4K = true; movie.MarkedAsAvailable4K = DateTime.Now; + await _movieRepo.SaveChangesAsync(); } // If we have a non-4k versison then mark as available @@ -219,6 +220,7 @@ namespace Ombi.Schedule.Jobs.Plex movie.Available = true; movie.Approved = true; movie.MarkedAsAvailable = DateTime.Now; + await _movieRepo.SaveChangesAsync(); } itemsForAvailbility.Add(new AvailabilityModel @@ -228,11 +230,6 @@ namespace Ombi.Schedule.Jobs.Plex }); } - if (itemsForAvailbility.Any()) - { - await _movieRepo.SaveChangesAsync(); - } - foreach (var i in itemsForAvailbility.DistinctBy(x => x.Id)) { await _notificationService.Notify(new NotificationOptions diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index eb97edeff..94970305a 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -103,10 +103,8 @@ namespace Ombi.Schedule.Jobs.Radarr } } } - // Save from the updates made to the existing movies (they are in the EF Change Tracker) await _radarrRepo.SaveChangesAsync(); - await _radarrRepo.AddRange(movieIds); } From 1611ef9198befbb7a4db50a4f0953e50f29a788f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Mar 2022 13:41:24 +0000 Subject: [PATCH 080/210] fix(requests): :bug: Fixed an issue where you couldn't approve movies from the request list --- .../components/movies-grid/movies-grid.component.ts | 2 +- .../components/options/request-options.component.ts | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index b283821ed..8b4ae170a 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -154,7 +154,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { } private checkDate(date: Date|string): boolean { - if (date instanceof String) { + if (typeof date === 'string') { return new Date(date).getFullYear() > 1; } if (date instanceof Date) { diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index 30a55335c..b3de64235 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef } from '@angular/material/bottom-sheet'; import { MessageService, RequestService } from '../../../services'; import { IRequestEngineResult, RequestType } from '../../../interfaces'; @@ -10,7 +10,7 @@ import { firstValueFrom, Observable } from 'rxjs'; selector: 'request-options', templateUrl: './request-options.component.html', }) -export class RequestOptionsComponent implements OnInit { +export class RequestOptionsComponent { public RequestType = RequestType; @@ -19,9 +19,6 @@ export class RequestOptionsComponent implements OnInit { private messageService: MessageService, private bottomSheetRef: MatBottomSheetRef, private translate: TranslateService) { } - ngOnInit(): void { - console.log(this.data); - } public async delete() { var request: Observable; From cd9fd40abe8bc88b53691aa9a7d61addefb8e1aa Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Mar 2022 13:47:07 +0000 Subject: [PATCH 081/210] chore(release): :rocket: v4.13.2 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3bf8bb6c..4cd8b5767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.13.2](https://github.com/Ombi-app/Ombi/compare/v4.13.1...v4.13.2) (2022-03-01) + + +### Bug Fixes + +* **requests:** :bug: Fixed an issue where you couldn't approve movies from the request list ([1611ef9](https://github.com/Ombi-app/Ombi/commit/1611ef9198befbb7a4db50a4f0953e50f29a788f)) + + + ## [4.13.1](https://github.com/Ombi-app/Ombi/compare/v4.13.0...v4.13.1) (2022-03-01) @@ -345,12 +354,3 @@ -# [4.7.0](https://github.com/Ombi-app/Ombi/compare/v4.6.5...v4.7.0) (2021-11-19) - - -### Features - -* **emby:** :sparkles: Added a emby recently added sync! ([a0e1406](https://github.com/Ombi-app/Ombi/commit/a0e14068f4bc457f8a4a565de71707a8f16c803c)) - - - diff --git a/version.json b/version.json index f466b9e00..e0934d75f 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.13.1" + "version": "4.13.2" } \ No newline at end of file From fdb54989b0767fa90a210655482d61d7bd24d5df Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 2 Mar 2022 20:15:56 +0000 Subject: [PATCH 082/210] refactor: :recycle: Small changes around the header auth --- .../Settings/Models/AuthenticationSettings.cs | 1 - .../ClientApp/src/app/login/login.component.ts | 14 +++++++++----- src/Ombi/Controllers/V1/TokenController.cs | 6 ++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs index a72708123..ed2775480 100644 --- a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs @@ -15,6 +15,5 @@ namespace Ombi.Settings.Settings.Models public bool EnableOAuth { get; set; } // Plex OAuth public bool EnableHeaderAuth { get; set; } // Header SSO public string HeaderAuthVariable { get; set; } // Header SSO - } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/login/login.component.ts b/src/Ombi/ClientApp/src/app/login/login.component.ts index 132554f4f..f6f519191 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.ts +++ b/src/Ombi/ClientApp/src/app/login/login.component.ts @@ -106,7 +106,10 @@ export class LoginComponent implements OnDestroy, OnInit { this.settingsService .getAuthentication() - .subscribe((x) => { this.authenticationSettings = x; this.headerAuth(); }); + .subscribe((x) => { + this.authenticationSettings = x; + this.headerAuth(); + }); this.settingsService.getClientId().subscribe((x) => (this.clientId = x)); this.images.getRandomBackground().subscribe((x) => { this.background = this.sanitizer.bypassSecurityTrustStyle( @@ -255,10 +258,9 @@ export class LoginComponent implements OnDestroy, OnInit { } public headerAuth() { - if (this.authenticationSettings.enableHeaderAuth) { - this.authService.headerAuth().subscribe( - (x) => { + this.authService.headerAuth().subscribe({ + next: (x) => { this.store.save("id_token", x.access_token); if (this.authService.loggedIn()) { @@ -270,11 +272,13 @@ export class LoginComponent implements OnDestroy, OnInit { }); } }, - (err) => { + error: (e) => { this.notify.open(this.errorBody, "OK", { duration: 3000000, }); + console.error(e); } + } ); } } diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index 67f0e1189..3a409c206 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -147,7 +147,6 @@ namespace Ombi.Controllers.V1 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - var token = new JwtSecurityToken( claims: claims, expires: rememberMe ? DateTime.Now.AddYears(1) : DateTime.Now.AddDays(7), @@ -279,17 +278,16 @@ namespace Ombi.Controllers.V1 [HttpPost("header_auth")] [ProducesResponseType(401)] + [ProducesResponseType(200)] public async Task HeaderAuth() { - string username = null; - var authSettings = await _authSettings.GetSettingsAsync(); _log.LogInformation("Logging with header: " + authSettings.HeaderAuthVariable); if (authSettings.HeaderAuthVariable != null && authSettings.EnableHeaderAuth) { if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey(authSettings.HeaderAuthVariable)) { - username = Request.HttpContext.Request.Headers[authSettings.HeaderAuthVariable].ToString(); + var username = Request.HttpContext.Request.Headers[authSettings.HeaderAuthVariable].ToString(); // Check if user exists var user = await _userManager.FindByNameAsync(username); From bf3911af76696fd4d3afb6ae70a072c8890e544d Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 2 Mar 2022 20:21:07 +0000 Subject: [PATCH 083/210] refactor: validators --- .../authentication.component.html | 37 +------------------ .../authentication.component.ts | 12 +++++- 2 files changed, 12 insertions(+), 37 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html index bde67e1c7..5960c79f7 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html @@ -25,48 +25,13 @@
-
+
-
diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts index 386711c4f..100a502b3 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup } from "@angular/forms"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; @@ -29,7 +29,17 @@ export class AuthenticationComponent implements OnInit { enableHeaderAuth: [x.enableHeaderAuth], headerAuthVariable: [x.headerAuthVariable], }); + this.form.controls.enableHeaderAuth.valueChanges.subscribe(x => { + if (x) { + this.form.get("headerAuthVariable").setValidators(Validators.required); + } else { + this.form.get("headerAuthVariable").clearValidators(); + } + this.form.get("headerAuthVariable").updateValueAndValidity(); + }); }); + + } public onSubmit(form: FormGroup) { From 6e068a2b3f1e489951c4a0ea1bdb41351cc2f286 Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Wed, 2 Mar 2022 20:23:58 +0000 Subject: [PATCH 084/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 79 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index aacb9a2ea..b176283b7 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,13 @@ Here are some of the features Ombi has:
+ + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - +
- - MattJeanes + + sephrat
- Matt Jeanes + Sephrat
- - sephrat + + MattJeanes
- Sephrat + Matt Jeanes
From fa74f3690efab3de8e45fcb2c9bf65968f07304c Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 1 Feb 2022 20:35:07 +0000 Subject: [PATCH 014/210] Update Crowdin configuration file --- crowdin.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index b7f48ef88..530225513 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,10 +1,10 @@ - -commit_message: "fix(translations): 🌐 New translations from Crowdin [skip ci]" +commit_message: "\UF09F8C90" append_commit_message: false -pull_request_title: "🌐 Translations Update" +pull_request_title: "\UF09F8C90" pull_request_labels: - translations - files: - source: /src/Ombi/wwwroot/translations/en.json translation: /src/Ombi/wwwroot/translations/%two_letters_code%.json + - source: /src/Ombi.I18n/Resources/Texts.resx + translation: /src/Ombi.I18n/Resources/Texts.%two_letters_code%.resx From bcaef5fbde3e2adce5914dba2de4aa42d39ae02a Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Feb 2022 20:35:48 +0000 Subject: [PATCH 015/210] chore(release): :rocket: v4.11.0 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08101f1d2..53efeb7d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [4.11.0](https://github.com/Ombi-app/Ombi/compare/v4.10.4...v4.11.0) (2022-02-01) + + +### Features + +* **newsletter:** Started to localize the newsletter ([#4485](https://github.com/Ombi-app/Ombi/issues/4485)) ([b5ec556](https://github.com/Ombi-app/Ombi/commit/b5ec5562435021ea4b8af07c9b64a3f7249b570a)) + + + ## [4.10.4](https://github.com/Ombi-app/Ombi/compare/v4.10.3...v4.10.4) (2022-02-01) @@ -371,12 +380,3 @@ -## [4.2.6](https://github.com/Ombi-app/Ombi/compare/v4.2.5...v4.2.6) (2021-10-14) - - -### Performance Improvements - -* :zap: Use ngxs store for the whole customization section of the app ([97b493d](https://github.com/Ombi-app/Ombi/commit/97b493d869feee59d360b484a6c59388a2aead1f)) - - - diff --git a/version.json b/version.json index dc8845852..e25eff35e 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.10.4" + "version": "4.11.0" } \ No newline at end of file From b0871bf9ca7100984e7a3c859a0bcc82f8284a71 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Feb 2022 20:38:13 +0000 Subject: [PATCH 016/210] chore(release): :rocket: v4.11.1 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53efeb7d9..9db85ecb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.11.1](https://github.com/Ombi-app/Ombi/compare/v4.11.0...v4.11.1) (2022-02-01) + + + # [4.11.0](https://github.com/Ombi-app/Ombi/compare/v4.10.4...v4.11.0) (2022-02-01) @@ -371,12 +375,3 @@ -## [4.2.7](https://github.com/Ombi-app/Ombi/compare/v4.2.6...v4.2.7) (2021-10-14) - - -### Bug Fixes - -* :bug: Fixed the issue parsing TheMovieDB dates. They have broken something... ([6e397e0](https://github.com/Ombi-app/Ombi/commit/6e397e02e95f894a92e8bf02428efdcac1275b31)) - - - diff --git a/version.json b/version.json index e25eff35e..7827c4d9b 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.0" + "version": "4.11.1" } \ No newline at end of file From 9ea907cc7084026659c3510338643c734b66a601 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 1 Feb 2022 20:48:57 +0000 Subject: [PATCH 017/210] =?UTF-8?q?chore:=20=F0=9F=8C=90=20Translations=20?= =?UTF-8?q?Update=20(#4481)=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] * fix(translations): 🌐 New translations from Crowdin [skip ci] --- src/Ombi/wwwroot/translations/de.json | 38 ++++++++--------- src/Ombi/wwwroot/translations/es.json | 60 +++++++++++++-------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 9ed748ac5..50e5d4abe 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -4,8 +4,8 @@ "UsernamePlaceholder": "Benutzername", "PasswordPlaceholder": "Passwort", "RememberMe": "Eingeloggt bleiben", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", + "SignInWith": "Mit {{appName}} anmelden", + "SignInWithPlex": "Mit Plex anmelden", "ForgottenPassword": "Passwort vergessen?", "Errors": { "IncorrectCredentials": "Falscher Benutzername oder falsches Passwort" @@ -36,8 +36,8 @@ "Cancel": "Cancel", "Submit": "Submit", "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", + "tvShow": "TV-Serie", + "movie": "Filme", "album": "Album" }, "PasswordReset": { @@ -56,7 +56,7 @@ "CheckPageForUpdates": "Überprüfe diese Seite für kontinuierliche Website-Updates." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Seite nicht gefunden" }, "NavigationBar": { "Discover": "Entdecken", @@ -86,9 +86,9 @@ "Music": "Musik", "People": "People" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Guten Morgen!", + "AfternoonWelcome": "Guten Tag!", + "EveningWelcome": "Guten Abend!" }, "Search": { "Title": "Suche", @@ -97,14 +97,14 @@ "TvTab": "Serien", "MusicTab": "Musik", "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", + "AdvancedSearchHeader": "Erweiterte Suche", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", "DigitalDate": "Veröffentlichung der digitalen Version: {{date}}", "TheatricalRelease": "Kinostart: {{date}}", "ViewOnPlex": "In Plex anschauen", "ViewOnEmby": "In Emby anschauen", - "ViewOnJellyfin": "Play On Jellyfin", + "ViewOnJellyfin": "Auf Jellyfin ansehen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "Similar": "Ähnliche", "Refine": "Auswahl verfeinern", @@ -198,17 +198,17 @@ "Options": "Options", "RequestPanel": { "Delete": "Delete Request", - "Approve": "Approve Request", - "ChangeAvailability": "Mark Available", - "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approve": "Anfrage genehmigen", + "ChangeAvailability": "Als verfügbar markieren", + "Deleted": "Ausgewählte Elemente erfolgreich gelöscht", + "Approved": "Ausgewählte Elemente erfolgreich freigegeben" }, - "SuccessfullyApproved": "Successfully Approved", - "SuccessfullyDeleted": "Request successfully deleted", - "NowAvailable": "Request is now available", - "NowUnavailable": "Request is now unavailable", + "SuccessfullyApproved": "Erfolgreich genehmigt", + "SuccessfullyDeleted": "Anfrage erfolgreich gelöscht", + "NowAvailable": "Anfrage ist jetzt verfügbar", + "NowUnavailable": "Anfrage ist jetzt verfügbar", "SuccessfullyReprocessed": "Successfully Re-processed the request", - "DeniedRequest": "Denied Request", + "DeniedRequest": "Abgelehnte Anfrage", "RequestCollection": "Request Collection", "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", "NeedToSelectEpisodes": "You need to select some episodes!", diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index a09d958d0..8fc14d0d5 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -215,23 +215,23 @@ "RequestAddedSuccessfully": "La solicitud de {{title}} se ha añadido correctamente", "ErrorCodes": { "AlreadyRequested": "Ya se ha solicitado", - "EpisodesAlreadyRequested": "We already have episodes requested from this series", - "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", - "NoPermissions": "You do not have the correct permissions!", + "EpisodesAlreadyRequested": "Ya tenemos episodios solicitados de esta serie", + "NoPermissionsOnBehalf": "No tienes los permisos correctos para solicitar en nombre de los usuarios!", + "NoPermissions": "¡No tienes los permisos apropiados!", "RequestDoesNotExist": "Esta petición no existe", - "ChildRequestDoesNotExist": "Child Request does not exist", - "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", + "ChildRequestDoesNotExist": "Esta petición no existe", + "NoPermissionsRequestMovie": "No tienes permiso para solicitar una película", "NoPermissionsRequestTV": "No tienes permiso para solicitar un Programa de televisión", "NoPermissionsRequestAlbum": "No tienes permiso para solicitar un Álbum", "MovieRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de películas!", - "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", - "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + "TvRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de series!", + "AlbumRequestQuotaExceeded": "¡Has superado tu cuota de solicitudes de álbumes!" }, "Notify": "Notificar", "RemoveNotification": "Eliminar notificación", - "SuccessfulNotify": "You will now be notified for title {{title}}", - "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", - "CouldntNotify": "Couldn't notify title {{title}}" + "SuccessfulNotify": "Se te notificará para el título {{title}}", + "SuccessfulUnNotify": "No se te notificará para el título {{title}}", + "CouldntNotify": "No se pudo notificar el título {{title}}" }, "Issues": { "Title": "Problemas", @@ -306,21 +306,21 @@ "ViewCollection": "Ver Colección", "NotEnoughInfo": "Desafortunadamente todavía no hay suficiente información sobre este programa!", "AdvancedOptions": "Opciones Avanzadas", - "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", - "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "AutoApproveOptions": "Puede configurar la solicitud aquí. Una vez solicitado, se te enviará a tu aplicación DVR y se aprobará automáticamente. Ten en cuenta que esto es opcional, presiona \"Solicitar\" para saltar!", + "AutoApproveOptionsTv": "Puede configurar la solicitud aquí, una vez solicitada será enviada a su aplicación DVR y será aprobada automáticamente! Si la solicitud ya está en Sonarr, no cambiaremos la carpeta raíz o el perfil de calidad! Ten en cuenta que esto es opcional, pulsa Solicitar para saltar!", + "AutoApproveOptionsTvShort": "Puede configurar la solicitud aquí. Una vez solicitado, se te enviará a tu aplicación DVR. Si la solicitud ya está en Sonarr, no cambiaremos la carpeta raíz o el perfil de calidad. Ten en cuenta que esto es opcional, presiona \"Solicitar\" para saltar!", "QualityProfilesSelect": "Seleccione un Perfil de Calidad", "RootFolderSelect": "Seleccione una Carpeta Raíz", - "LanguageProfileSelect": "Select A Language Profile", + "LanguageProfileSelect": "Seleccione un perfil de idioma", "Status": "Estado:", "StatusValues": { - "Rumored": "Rumored", + "Rumored": "Rumoreada", "Planned": "Planificado", "In Production": "En Producción", "Post Production": "Post-Producción", "Released": "En cines", - "Running": "Running", - "Returning Series": "Returning Series", + "Running": "En emisión", + "Returning Series": "Serie que regresa", "Ended": "Finalizada", "Canceled": "Cancelada" }, @@ -329,8 +329,8 @@ "Availability": "Disponibilidad:", "RequestStatus": "Estado de solicitud", "Quality": "Calidad:", - "RootFolderOverride": "Root Folder Override:", - "QualityOverride": "Quality Override:", + "RootFolderOverride": "Sobreescribir carpeta raíz:", + "QualityOverride": "Sobreescribir calidad:", "Network": "Cadena:", "GenresLabel": "Géneros:", "Genres": "Géneros", @@ -357,24 +357,24 @@ "RadarrConfiguration": "Configuración de Radarr", "RequestOnBehalf": "Solicitar en nombre de", "PleaseSelectUser": "Seleccione un usuario", - "StreamingOn": "Streaming On:", + "StreamingOn": "Emitido en:", "RequestedBy": "Solicitado por:", "RequestedByOn": "Solicitado por {{user}} el {{date}}", "RequestDate": "Fecha de solicitud:", - "DeniedReason": "Denied Reason:", - "ReProcessRequest": "Re-Process Request", + "DeniedReason": "Motivo de denegación:", + "ReProcessRequest": "Re-procesar solicitud", "Music": { "Type": "Tipo:", "Country": "País:", - "StartDate": "Start Date:", - "EndDate": "EndDate:" + "StartDate": "Fecha de inicio:", + "EndDate": "Fecha de finalización:" } }, "Discovery": { "PopularTab": "Popular", "TrendingTab": "Tendencias", "UpcomingTab": "Próximamente", - "SeasonalTab": "Seasonal", + "SeasonalTab": "Por Temporada", "RecentlyRequestedTab": "Solicitudes recientes", "Movies": "Películas", "Combined": "Combinado", @@ -401,12 +401,12 @@ "StreamingCountry": "País de emisión", "StreamingCountryDescription": "Este es el código de país desde el que mostraremos información de emisión. Si estás en España, por favor selecciona ES y tendrás información relacionada con la emisión en España.", "LanguageDescription": "Este es el idioma en el que desea mostrar la interfaz de Ombi.", - "MobileQRCode": "Mobile QR Code", - "LegacyApp": "Launch Legacy App", - "NoQrCode": "Please contact your administrator to enable QR codes", - "UserType": "User Type:", + "MobileQRCode": "Código QR móvil", + "LegacyApp": "Iniciar aplicación antigua", + "NoQrCode": "Ponte en contacto con tu administrador para habilitar los códigos QR", + "UserType": "Tipo de usuario:", "ChangeDetails": "Modificar mis datos", - "NeedCurrentPassword": "You need your current password to make any changes here", + "NeedCurrentPassword": "Necesitamos tu contraseña actual para confirmar los cambios", "CurrentPassword": "Contraseña actual", "EmailAddress": "Correo electrónico", "NewPassword": "Nueva Contraseña", From 68ef366e8525e2c349b9e81704ad8bcca6c347a0 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Feb 2022 20:51:32 +0000 Subject: [PATCH 018/210] fix: :globe_with_meridians: Added Czech and Chinese Simplified to the language list --- src/Ombi/ClientApp/src/app/app.component.ts | 4 ++-- .../components/user-preference/user-preference.constants.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index 2c543606b..4a0c437d6 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -53,7 +53,7 @@ export class AppComponent implements OnInit { private readonly identity: IdentityService, @Inject(DOCUMENT) private document: HTMLDocument) { - this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru"]); + this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru", "cs", "zh"]); if (this.authService.loggedIn()) { this.identity.getAccessToken().subscribe(x => this.accessToken = x); @@ -81,7 +81,7 @@ export class AppComponent implements OnInit { // See if we can match the supported langs with the current browser lang const browserLang: string = translate.getBrowserLang(); - this.translate.use(browserLang.match(/da|de|en|es|fr|it|hu|nl|no|pl|pt|sk|sv|bg|ru/) ? browserLang : "en"); + this.translate.use(browserLang.match(/da|de|en|es|fr|it|hu|nl|no|pl|pt|sk|sv|bg|ru|cs|zh/) ? browserLang : "en"); } diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts index 21416d056..d5101fa52 100644 --- a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts @@ -14,6 +14,8 @@ export const AvailableLanguages: ILanguage[] = [ { display: 'Svenska', value: 'sv' }, { display: 'Български', value: 'bg' }, { display: 'Русский', value: 'ru' }, + { display: 'čeština', value: 'cs' }, + { display: '简体中文', value: 'zh' }, ]; export interface ILanguage { From ce00ed7c7ed204586c73ef44023978eba1b72aa1 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 1 Feb 2022 20:52:21 +0000 Subject: [PATCH 019/210] refactor: :wastebasket: Fixed a deprecation --- src/Ombi/ClientApp/src/app/app.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index 4a0c437d6..720ec22a2 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -51,7 +51,7 @@ export class AppComponent implements OnInit { private signalrNotification: SignalRNotificationService, private readonly snackBar: MatSnackBar, private readonly identity: IdentityService, - @Inject(DOCUMENT) private document: HTMLDocument) { + @Inject(DOCUMENT) private document: Document) { this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru", "cs", "zh"]); From 004e135b2d9cf4f0fb19c35d379cc89f466e338a Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 1 Feb 2022 20:55:39 +0000 Subject: [PATCH 020/210] chore(release): :rocket: v4.11.2 --- CHANGELOG.md | 19 +++++++++---------- version.json | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db85ecb7..167689d92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.2](https://github.com/Ombi-app/Ombi/compare/v4.11.1...v4.11.2) (2022-02-01) + + +### Bug Fixes + +* :globe_with_meridians: Added Czech and Chinese Simplified to the language list ([68ef366](https://github.com/Ombi-app/Ombi/commit/68ef366e8525e2c349b9e81704ad8bcca6c347a0)) + + + ## [4.11.1](https://github.com/Ombi-app/Ombi/compare/v4.11.0...v4.11.1) (2022-02-01) @@ -365,13 +374,3 @@ -## [4.2.8](https://github.com/Ombi-app/Ombi/compare/v4.2.7...v4.2.8) (2021-10-15) - - -### Bug Fixes - -* :adhesive_bandage: See if this fixes the proxy issue ([74d1aca](https://github.com/Ombi-app/Ombi/commit/74d1acae499707a7e21401f53eb2bb90c5bb9cfa)) -* :bug: Fixed Ombi not writing the baseUrl correctly ([e9cc8b6](https://github.com/Ombi-app/Ombi/commit/e9cc8b6fe71d3e10c1a901e70227989b3362afe3)) - - - diff --git a/version.json b/version.json index 7827c4d9b..447d806a2 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.1" + "version": "4.11.2" } \ No newline at end of file From 8e42dbf8f78caa51ca891bf3d702c6b0ac401f9c Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 3 Feb 2022 09:00:05 +0000 Subject: [PATCH 021/210] fix(API): Fixed an issue where the API key couldn't delete a request #4489 --- src/Ombi.Core/Engine/Interfaces/BaseEngine.cs | 7 ++++++- src/Ombi.sln | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index e949ac297..42aff9a61 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -45,7 +45,12 @@ namespace Ombi.Core.Engine.Interfaces protected async Task IsInRole(string roleName) { - return await UserManager.IsInRoleAsync(await GetUser(), roleName); + if (Username.Equals("API", StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + var user = await GetUser(); + return await UserManager.IsInRoleAsync(user, roleName); } public async Task> RunRequestRules(BaseRequest model) diff --git a/src/Ombi.sln b/src/Ombi.sln index 5149f020b..841f84dbd 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -124,6 +124,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.CloudService", "Om EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.RottenTomatoes", "Ombi.Api.RottenTomatoes\Ombi.Api.RottenTomatoes.csproj", "{8F19C701-7881-4BC7-8BBA-B068A6B954AD}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.I18n", "Ombi.I18n\Ombi.I18n.csproj", "{6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -431,6 +433,12 @@ Global {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.Release|Any CPU.ActiveCfg = Release|Any CPU {8F19C701-7881-4BC7-8BBA-B068A6B954AD}.Release|Any CPU.Build.0 = Release|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.NonUiBuild|Any CPU.ActiveCfg = NonUiBuild|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 86e87dad497b6cef25572f5cb1796072df55c35f Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 3 Feb 2022 09:03:40 +0000 Subject: [PATCH 022/210] chore(release): :rocket: v4.11.3 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 167689d92..09298f459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.3](https://github.com/Ombi-app/Ombi/compare/v4.11.2...v4.11.3) (2022-02-03) + + +### Bug Fixes + +* **API:** Fixed an issue where the API key couldn't delete a request [#4489](https://github.com/Ombi-app/Ombi/issues/4489) ([8e42dbf](https://github.com/Ombi-app/Ombi/commit/8e42dbf8f78caa51ca891bf3d702c6b0ac401f9c)) + + + ## [4.11.2](https://github.com/Ombi-app/Ombi/compare/v4.11.1...v4.11.2) (2022-02-01) @@ -365,12 +374,3 @@ -## [4.2.9](https://github.com/Ombi-app/Ombi/compare/v4.2.8...v4.2.9) (2021-10-15) - - -### Bug Fixes - -* :fire: Really fix the base url issue this time ([9f36923](https://github.com/Ombi-app/Ombi/commit/9f36923c51bfabf9cb026f2da14f9947050af0d9)) - - - diff --git a/version.json b/version.json index 447d806a2..f6e7244af 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.2" + "version": "4.11.3" } \ No newline at end of file From ddf63fbed0b9cbe458aec37318758c76b99b2de9 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 4 Feb 2022 21:28:26 +0100 Subject: [PATCH 023/210] fix(newsletter): Fix newsletter not publishing double episodes (#4495) [skip ci] --- src/Ombi.Store/Entities/EmbyEpisode.cs | 6 ------ src/Ombi.Store/Entities/JellyfinEpisode.cs | 5 ----- src/Ombi.Store/Entities/MediaServerContent.cs | 8 +++++--- src/Ombi.Store/Entities/PlexEpisode.cs | 6 ------ 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/Ombi.Store/Entities/EmbyEpisode.cs b/src/Ombi.Store/Entities/EmbyEpisode.cs index 97fdb09b1..89103c580 100644 --- a/src/Ombi.Store/Entities/EmbyEpisode.cs +++ b/src/Ombi.Store/Entities/EmbyEpisode.cs @@ -57,11 +57,5 @@ namespace Ombi.Store.Entities return content.OfType().FirstOrDefault( x => x.EmbyId == this.EmbySeries.EmbyId); } - - public override bool IsIn(IMediaServerContent content) - { - return content.Episodes.Cast().Any(x => x.EmbyId == this.EmbyId); - } - } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/JellyfinEpisode.cs b/src/Ombi.Store/Entities/JellyfinEpisode.cs index 1c0ac423e..5b105003c 100644 --- a/src/Ombi.Store/Entities/JellyfinEpisode.cs +++ b/src/Ombi.Store/Entities/JellyfinEpisode.cs @@ -58,10 +58,5 @@ namespace Ombi.Store.Entities return content.OfType().FirstOrDefault( x => x.JellyfinId == this.JellyfinSeries.JellyfinId); } - - public override bool IsIn(IMediaServerContent content) - { - return content.Episodes.Cast().Any(x => x.JellyfinId == this.JellyfinId); - } } } diff --git a/src/Ombi.Store/Entities/MediaServerContent.cs b/src/Ombi.Store/Entities/MediaServerContent.cs index 3bccfea06..df50efc86 100644 --- a/src/Ombi.Store/Entities/MediaServerContent.cs +++ b/src/Ombi.Store/Entities/MediaServerContent.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations.Schema; -using Ombi.Store.Repository; +using System.Linq; namespace Ombi.Store.Entities { @@ -42,6 +41,9 @@ namespace Ombi.Store.Entities public IMediaServerContent Series { get; set; } public abstract IMediaServerContent SeriesIsIn(ICollection content); - public abstract bool IsIn(IMediaServerContent content); + public bool IsIn(IMediaServerContent content) + { + return content.Episodes.Any(x => x.SeasonNumber == this.SeasonNumber && x.EpisodeNumber == this.EpisodeNumber); + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/PlexEpisode.cs b/src/Ombi.Store/Entities/PlexEpisode.cs index ac482d7ac..02cfc8a07 100644 --- a/src/Ombi.Store/Entities/PlexEpisode.cs +++ b/src/Ombi.Store/Entities/PlexEpisode.cs @@ -28,11 +28,5 @@ namespace Ombi.Store.Entities return content.OfType().FirstOrDefault( x => x.Key == this.PlexSeries.Key); } - - public override bool IsIn(IMediaServerContent content) - { - return content.Episodes.Cast().Any(x => x.Key == this.Key); - } - } } \ No newline at end of file From 4e7546f63565cca232162de4dd477a9991591a16 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Sat, 5 Feb 2022 22:13:32 +0100 Subject: [PATCH 024/210] fix(newsletter):Declutter newsletter info for series (#4494) * Declutter newsletter info for series - Do not list episodes if the series is complete - Do not list all episodes of a season if the season is complete * Use proper empty string constant [skip ci] --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 62 +++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index f965625f6..dbb343126 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -726,28 +726,8 @@ namespace Ombi.Schedule.Jobs.Ombi AddTvTitle(tvInfo); - // Group by the season number - var results = t.Episodes.GroupBy(p => p.SeasonNumber, - (key, g) => new - { - SeasonNumber = key, - Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() - } - ); - - // Group the episodes - var finalsb = new StringBuilder(); - foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) - { - var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"{Texts.SeasonLabel} {epInformation.SeasonNumber} - {Texts.EpisodesLabel} {episodeString} {episodeAirDate}"); - finalsb.Append("
"); - } - - AddTvEpisodesSummaryGenres(finalsb.ToString(), tvInfo); + var tvEpisodesString = GetTvEpisodesString(tvInfo, t.Episodes); + AddTvEpisodesSummaryGenres(tvEpisodesString, tvInfo); } catch (Exception e) @@ -769,6 +749,44 @@ namespace Ombi.Schedule.Jobs.Ombi } } + private string GetTvEpisodesString(TvInfo tvInfo, ICollection episodes) + { + if (episodes.Count >= tvInfo.number_of_episodes) + { + // do not list individual episodes when the series is complete + return string.Empty; + } + + var sb = new StringBuilder(); + // Group by the season number + var seasons = episodes.GroupBy(p => p.SeasonNumber, + (key, g) => new + { + SeasonNumber = key, + Episodes = g.ToList(), + Header = tvInfo?.seasons?.Where(x => x.season_number == key).FirstOrDefault(), + } + ); + // Group the episodes + foreach (var season in seasons.OrderBy(x => x.SeasonNumber)) + { + string episodeList; + if (season.Episodes.Count >= season.Header.episode_count) + { + // do not list individual episodes when the season is complete + episodeList = string.Empty; + } + else + { + var orderedEpisodes = season.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); + episodeList = $"{Texts.EpisodesLabel} {StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber))}"; + } + var episodeAirDate = season.Header.air_date; + sb.Append($"{Texts.SeasonLabel} {season.SeasonNumber} - {episodeList} {episodeAirDate}"); + sb.Append("
"); + } + return sb.ToString(); + } private void AddTvTitle(TvInfo tvInfo) { var title = ""; From 9915234d38d4701c527081ccc21b566980375331 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Sat, 5 Feb 2022 22:14:38 +0100 Subject: [PATCH 025/210] fix(media-sync): Add sanity checks upon media server sync (#4493) * Add sanity checks upon media server sync Fixes Media content may be improperly imported into Ombi #4472 * Fix Jellyfin sync * Refactor Emby and Jellyfin provider ids * Use new method Any * Fix log formatting --- .../Models/Media/EmbyProviderids.cs | 10 ++++------ src/Ombi.Api.Emby/Ombi.Api.Emby.csproj | 1 + .../Models/Media/JellyfinProviderids.cs | 10 ++++------ src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj | 1 + .../Models/BaseProviderids.cs | 11 +++++++++++ .../Ombi.Api.MediaServer.csproj | 18 ++++++++++++++++++ src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs | 8 +++++++- src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs | 7 +++++++ .../Jobs/Jellyfin/JellyfinContentSync.cs | 7 ++++++- .../Jobs/Jellyfin/JellyfinEpisodeSync.cs | 9 ++++++++- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 5 +++++ src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs | 7 +++++++ 12 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/Ombi.Api.MediaServer/Models/BaseProviderids.cs create mode 100644 src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj diff --git a/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs b/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs index 8302ee3ee..4a19025de 100644 --- a/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs +++ b/src/Ombi.Api.Emby/Models/Media/EmbyProviderids.cs @@ -1,12 +1,10 @@ -namespace Ombi.Api.Emby.Models.Movie +using Ombi.Api.MediaServer.Models; + +namespace Ombi.Api.Emby.Models.Movie { - public class EmbyProviderids + public class EmbyProviderids: BaseProviderids { - public string Tmdb { get; set; } - public string Imdb { get; set; } public string TmdbCollection { get; set; } - - public string Tvdb { get; set; } public string Zap2It { get; set; } public string TvRage { get; set; } } diff --git a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj index f167146af..b524c9ce4 100644 --- a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj +++ b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs index 9b47f9a1a..0896ec4e9 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinProviderids.cs @@ -1,12 +1,10 @@ -namespace Ombi.Api.Jellyfin.Models.Movie +using Ombi.Api.MediaServer.Models; + +namespace Ombi.Api.Jellyfin.Models.Movie { - public class JellyfinProviderids + public class JellyfinProviderids: BaseProviderids { - public string Tmdb { get; set; } - public string Imdb { get; set; } public string TmdbCollection { get; set; } - - public string Tvdb { get; set; } public string Zap2It { get; set; } public string TvRage { get; set; } } diff --git a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj index f167146af..dfdb5a93f 100644 --- a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj +++ b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj @@ -13,6 +13,7 @@ + \ No newline at end of file diff --git a/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs b/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs new file mode 100644 index 000000000..6044288c6 --- /dev/null +++ b/src/Ombi.Api.MediaServer/Models/BaseProviderids.cs @@ -0,0 +1,11 @@ +namespace Ombi.Api.MediaServer.Models +{ + public class BaseProviderids + { + public string Tmdb { get; set; } + public string Imdb { get; set; } + public string Tvdb { get; set; } + public bool Any() => + !string.IsNullOrEmpty(Imdb) || !string.IsNullOrEmpty(Tmdb) || !string.IsNullOrEmpty(Tvdb); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj new file mode 100644 index 000000000..f167146af --- /dev/null +++ b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + 3.0.0.0 + 3.0.0.0 + + + 8.0 + Debug;Release;NonUiBuild + + + + + + + + \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index cb7eaefd3..646cbdee0 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -149,7 +149,7 @@ namespace Ombi.Schedule.Jobs.Emby foreach (var tvShow in tv.Items) { processed++; - if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb)) + if (!tvShow.ProviderIds.Any()) { _logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name); continue; @@ -249,6 +249,12 @@ namespace Ombi.Schedule.Jobs.Emby var alreadyGoingToAdd = content.Any(x => x.EmbyId == movieInfo.Id); if (existingMovie == null && !alreadyGoingToAdd) { + + if (!movieInfo.ProviderIds.Any()) + { + _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); + return; + } _logger.LogDebug("Adding new movie {0}", movieInfo.Name); content.Add(new EmbyContent { diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index c1ca48ef7..b3c1ffbab 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -152,6 +152,13 @@ namespace Ombi.Schedule.Jobs.Emby if (existingEpisode == null && !existingInList) { + // Sanity checks + if (ep.IndexNumber == 0) + { + _logger.LogWarning($"Episode {ep.Name} has no episode number. Skipping."); + continue; + } + _logger.LogDebug("Adding new episode {0} to parent {1}", ep.Name, ep.SeriesName); // add it epToAdd.Add(new EmbyEpisode diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index 60ee42210..fec5ca0ce 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -127,7 +127,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin { processed++; - if (string.IsNullOrEmpty(tvShow.ProviderIds?.Tvdb)) + if (!tvShow.ProviderIds.Any()) { _logger.LogInformation("Provider Id on tv {0} is null", tvShow.Name); continue; @@ -217,6 +217,11 @@ namespace Ombi.Schedule.Jobs.Jellyfin var alreadyGoingToAdd = content.Any(x => x.JellyfinId == movieInfo.Id); if (existingMovie == null && !alreadyGoingToAdd) { + if (!movieInfo.ProviderIds.Any()) + { + _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); + return; + } _logger.LogDebug("Adding new movie {0}", movieInfo.Name); content.Add(new JellyfinContent { diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs index 27e50c9b7..6e2daa7b3 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs @@ -66,7 +66,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin public async Task Execute(IJobExecutionContext job) { var settings = await _settings.GetSettingsAsync(); - + Api = _apiFactory.CreateClient(settings); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Jellyfin Episode Sync Started"); @@ -128,6 +128,13 @@ namespace Ombi.Schedule.Jobs.Jellyfin if (existingEpisode == null && !existingInList) { + // Sanity checks + if (ep.IndexNumber == 0) // no check on season number, Season 0 can be Specials + { + _logger.LogWarning($"Episode {ep.Name} has no episode number. Skipping."); + continue; + } + _logger.LogDebug("Adding new episode {0} to parent {1}", ep.Name, ep.SeriesName); // add it epToAdd.Add(new JellyfinEpisode diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index df96457d0..bdb7e70bc 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -342,6 +342,11 @@ namespace Ombi.Schedule.Jobs.Plex } } + if (!guids.Any()) + { + Logger.LogWarning($"Movie {movie.title} has no relevant metadata. Skipping."); + continue; + } var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); var item = new PlexServerContent diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 4a088ca7b..c17af088c 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -179,6 +179,13 @@ namespace Ombi.Schedule.Jobs.Plex episode.grandparentRatingKey = seriesExists.Key; } + // Sanity checks + if (episode.index == 0) + { + _log.LogWarning($"Episode {episode.title} has no episode number. Skipping."); + continue; + } + ep.Add(new PlexEpisode { EpisodeNumber = episode.index, From 960a94030c8c415953b51c89e23134132e259bce Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Sat, 5 Feb 2022 21:14:53 +0000 Subject: [PATCH 026/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 97f61b650..aacb9a2ea 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,13 @@ Here are some of the features Ombi has:
+ + sephrat +
+ Sephrat +
+
MrTopCat @@ -128,13 +135,6 @@ Here are some of the features Ombi has: Shaun McPeck - - sephrat -
- Sephrat -
-
MattJeanes From 90ecb148ba26783b89c4095e19caaba5ee8f2117 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sat, 5 Feb 2022 21:17:42 +0000 Subject: [PATCH 027/210] chore(release): :rocket: v4.11.4 --- CHANGELOG.md | 19 ++++++++++--------- version.json | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09298f459..22234a0a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [4.11.4](https://github.com/Ombi-app/Ombi/compare/v4.11.3...v4.11.4) (2022-02-05) + + +### Bug Fixes + +* **media-sync:** Add sanity checks upon media server sync ([#4493](https://github.com/Ombi-app/Ombi/issues/4493)) ([9915234](https://github.com/Ombi-app/Ombi/commit/9915234d38d4701c527081ccc21b566980375331)), closes [#4472](https://github.com/Ombi-app/Ombi/issues/4472) +* **newsletter:** Fix newsletter not publishing double episodes ([#4495](https://github.com/Ombi-app/Ombi/issues/4495)) ([ddf63fb](https://github.com/Ombi-app/Ombi/commit/ddf63fbed0b9cbe458aec37318758c76b99b2de9)) + + + ## [4.11.3](https://github.com/Ombi-app/Ombi/compare/v4.11.2...v4.11.3) (2022-02-03) @@ -365,12 +375,3 @@ -## [4.2.10](https://github.com/Ombi-app/Ombi/compare/v4.2.9...v4.2.10) (2021-10-15) - - -### Bug Fixes - -* :bug: Really really fix it this time? ([543d36e](https://github.com/Ombi-app/Ombi/commit/543d36e5615341bc8378cac377b843a3dbc1ef99)) - - - diff --git a/version.json b/version.json index f6e7244af..2c5745167 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.3" + "version": "4.11.4" } \ No newline at end of file From cfb85c23d77626b9ec1d99a6cf76497c438d0338 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 5 Feb 2022 21:38:46 +0000 Subject: [PATCH 028/210] fix(sonarr): Fixed where requesting all seasons would only mark the latest as monitored #4496 --- src/Ombi.Core/Senders/TvSender.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 9f60d2ba0..80fed6434 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -239,7 +239,7 @@ namespace Ombi.Core.Senders languageProfileId = languageProfile; } } - + try { // Does the series actually exist? @@ -358,7 +358,7 @@ namespace Ombi.Core.Senders } } var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList(); - var sonarrEpCount = sonarrEpisodeList.Count; + var sonarrEpCount = sonarrEpisodeList.Count; var ourRequestCount = season.Episodes.Count; var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList(); @@ -374,17 +374,12 @@ namespace Ombi.Core.Senders if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/) { // We have the same amount of requests as all of the episodes in the season. + existingSeason.monitored = true; + seriesChanges = true; - if (!existingSeason.monitored) - { - existingSeason.monitored = true; - seriesChanges = true; - } - // Now update the episodes that need updating - foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber)) - { - await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri); - } + // We do not need to update the episodes as marking the season as monitored will mark the episodes as monitored. + var seasonToUpdate = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); + seasonToUpdate.monitored = true; // Update by ref } else { @@ -442,7 +437,6 @@ namespace Ombi.Core.Senders var seasonsToUpdate = new List(); for (var i = 0; i < model.ParentRequest.TotalSeasons + 1; i++) { - var index = i; var sea = new Season { seasonNumber = i, From 53bff29795ff93c891603b85bcb2db5012fc7e0e Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sat, 5 Feb 2022 21:42:25 +0000 Subject: [PATCH 029/210] chore(release): :rocket: v4.11.5 --- CHANGELOG.md | 13 +++++++++---- version.json | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22234a0a2..220e46849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.5](https://github.com/Ombi-app/Ombi/compare/v4.11.4...v4.11.5) (2022-02-05) + + +### Bug Fixes + +* **sonarr:** Fixed where requesting all seasons would only mark the latest as monitored [#4496](https://github.com/Ombi-app/Ombi/issues/4496) ([cfb85c2](https://github.com/Ombi-app/Ombi/commit/cfb85c23d77626b9ec1d99a6cf76497c438d0338)) + + + ## [4.11.4](https://github.com/Ombi-app/Ombi/compare/v4.11.3...v4.11.4) (2022-02-05) @@ -371,7 +380,3 @@ -## [4.2.11](https://github.com/Ombi-app/Ombi/compare/v4.2.10...v4.2.11) (2021-10-18) - - - diff --git a/version.json b/version.json index 2c5745167..5c318d452 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.4" + "version": "4.11.5" } \ No newline at end of file From 191318ddad5a8148422955bf928f1c49b890e3eb Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Feb 2022 19:14:14 +0000 Subject: [PATCH 030/210] fix(plex): Fixed an issue where in a rare case we couldn't sync the data #4502 --- src/Ombi.Api.Plex/Models/Metadata.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index d0bb227ad..65cb21e95 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -12,23 +12,15 @@ namespace Ombi.Api.Plex.Models public string contentRating { get; set; } public string summary { get; set; } public int index { get; set; } - public float rating { get; set; } - //public int viewCount { get; set; } - //public int lastViewedAt { get; set; } public int year { get; set; } public string thumb { get; set; } public string art { get; set; } public string banner { get; set; } public string theme { get; set; } - //public string duration { get; set; } - //public string originallyAvailableAt { get; set; } public int leafCount { get; set; } public int viewedLeafCount { get; set; } public int childCount { get; set; } - //public long addedAt { get; set; } - //public int updatedAt { get; set; } public Genre[] Genre { get; set; } - //public Role[] Role { get; set; } public string primaryExtraKey { get; set; } public int parentRatingKey { get; set; } public int grandparentRatingKey { get; set; } @@ -47,12 +39,10 @@ namespace Ombi.Api.Plex.Models public string chapterSource { get; set; } public Medium[] Media { get; set; } public List Guid { get; set; } = new List(); - // public Director[] Director { get; set; } - // public Writer[] Writer { get; set; } } public class PlexGuids { public string Id { get; set; } } -} \ No newline at end of file +} From 497273e582538399548b49dd2418ed14345d8da1 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 10 Feb 2022 19:18:10 +0000 Subject: [PATCH 031/210] chore(release): :rocket: v4.11.6 --- CHANGELOG.md | 20 +++++++++----------- version.json | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 220e46849..92bf77674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.6](https://github.com/Ombi-app/Ombi/compare/v4.11.5...v4.11.6) (2022-02-10) + + +### Bug Fixes + +* **plex:** Fixed an issue where in a rare case we couldn't sync the data [#4502](https://github.com/Ombi-app/Ombi/issues/4502) ([191318d](https://github.com/Ombi-app/Ombi/commit/191318ddad5a8148422955bf928f1c49b890e3eb)) + + + ## [4.11.5](https://github.com/Ombi-app/Ombi/compare/v4.11.4...v4.11.5) (2022-02-05) @@ -369,14 +378,3 @@ -## [4.2.12](https://github.com/Ombi-app/Ombi/compare/v4.2.11...v4.2.12) (2021-10-20) - - -### Bug Fixes - -* **newsletter:** :bug: Fixed a few small bugs in the newsletter ([21dba4c](https://github.com/Ombi-app/Ombi/commit/21dba4c524b98b9f2b883d97e7e13329425a8762)) -* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([52eda6a](https://github.com/Ombi-app/Ombi/commit/52eda6ab917a73842bc02b0d8e0c442e564ca8f0)) -* **translations:** 🌐 New translations en.json from Crowdin [skip ci] ([1095d52](https://github.com/Ombi-app/Ombi/commit/1095d524962648a1e427f0bcd8105fa734dd5b60)) - - - diff --git a/version.json b/version.json index 5c318d452..03978da5f 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.5" + "version": "4.11.6" } \ No newline at end of file From 5cc0d7727d72fe1fee8a3f6c3874d44a5b785de4 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 12 Feb 2022 16:37:46 +0000 Subject: [PATCH 032/210] Chore: remove log [skip ci] --- .github/workflows/issue-check.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/issue-check.yml b/.github/workflows/issue-check.yml index 9dfe5cc45..51b87b8d3 100644 --- a/.github/workflows/issue-check.yml +++ b/.github/workflows/issue-check.yml @@ -8,9 +8,6 @@ jobs: issueCheck: runs-on: ubuntu-latest steps: - - name: Output version - run: | - echo "log: ${{ github.event.issue.body }}" - if: startsWith(github.event.issue.body , '**Describe the bug**') == false name: Close Issue From 22bb4226ead2d62e8c2c2c05be47d7da621402e2 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 12 Feb 2022 21:37:51 +0000 Subject: [PATCH 033/210] fix(notifications): :bug: This is a fix for some of the duplicate notification issues #3825 --- .../NotificationServiceTests.cs | 42 +++++++++++++++++++ .../Ombi.Notifications.Tests.csproj | 1 + src/Ombi.Notifications/BaseNotification.cs | 16 +++---- src/Ombi.Notifications/NotificationService.cs | 4 +- 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 src/Ombi.Notifications.Tests/NotificationServiceTests.cs diff --git a/src/Ombi.Notifications.Tests/NotificationServiceTests.cs b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs new file mode 100644 index 000000000..fedd7707e --- /dev/null +++ b/src/Ombi.Notifications.Tests/NotificationServiceTests.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Moq.AutoMock; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ombi.Notifications.Tests +{ + [TestFixture] + public class NotificationServiceTests + { + + private NotitficationServiceTestFacade _subject; + + [SetUp] + public void Setup() + { + var mocker = new AutoMocker(); + mocker.Use(NullLogger.Instance); + _subject = mocker.CreateInstance(); + } + + [Test] + public void PopulateAgentsTests() + { + Assert.That(_subject.Agents, Has.Count.EqualTo(12)); + Assert.That(_subject.Agents.DistinctBy(x => x.NotificationName).ToList(), Has.Count.EqualTo(12)); + } + } + + + public class NotitficationServiceTestFacade : NotificationService + { + public NotitficationServiceTestFacade(IServiceProvider provider, ILogger log) : base(provider, log) + { + } + + public List Agents => base.NotificationAgents; + } +} diff --git a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj index b3edbcf6d..e936c9072 100644 --- a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj +++ b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 9397767bf..b52f0a0cd 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -33,7 +33,7 @@ namespace Ombi.Notifications AlbumRepository = album; UserNotificationPreferences = notificationUserPreferences; _userManager = um; - Settings.ClearCache(); + Settings?.ClearCache(); } protected ISettingsService Settings { get; } @@ -64,7 +64,11 @@ namespace Ombi.Notifications public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings) { - if (settings == null) await NotifyAsync(model); + if (settings == null) + { + await NotifyAsync(model); + return; + } var notificationSettings = (T)settings; @@ -114,15 +118,13 @@ namespace Ombi.Notifications case NotificationType.IssueComment: await IssueComment(model, notificationSettings); break; - case NotificationType.AdminNote: + case NotificationType.PartiallyAvailable: + await PartiallyAvailable(model, notificationSettings); break; + case NotificationType.AdminNote: case NotificationType.WelcomeEmail: - break; case NotificationType.Newsletter: break; - case NotificationType.PartiallyAvailable: - await PartiallyAvailable(model, notificationSettings); - break; default: throw new ArgumentOutOfRangeException(); } diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index 8a24382aa..f22800cdc 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -23,7 +23,7 @@ namespace Ombi.Notifications PopulateAgents(); } - private List NotificationAgents { get; } + protected List NotificationAgents { get; } private ILogger Log { get; } /// @@ -55,7 +55,7 @@ namespace Ombi.Notifications } - private void PopulateAgents() + protected void PopulateAgents() { var baseSearchType = typeof(BaseNotification<>).Name; From 5832133e000a5a75ab5dd09183065aaffcf62ceb Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sat, 12 Feb 2022 21:42:49 +0000 Subject: [PATCH 034/210] chore(release): :rocket: v4.11.7 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92bf77674..5b7cce69a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12) + + +### Bug Fixes + +* **notifications:** :bug: This is a fix for some of the duplicate notification issues [#3825](https://github.com/Ombi-app/Ombi/issues/3825) ([22bb422](https://github.com/Ombi-app/Ombi/commit/22bb4226ead2d62e8c2c2c05be47d7da621402e2)) + + + ## [4.11.6](https://github.com/Ombi-app/Ombi/compare/v4.11.5...v4.11.6) (2022-02-10) @@ -369,12 +378,3 @@ -## [4.2.13](https://github.com/Ombi-app/Ombi/compare/v4.2.12...v4.2.13) (2021-10-20) - - -### Bug Fixes - -* **translations:** 🌐 New translations %two_letters_code% from Crowdin [skip ci] ([8fbd267](https://github.com/Ombi-app/Ombi/commit/8fbd267b516ddaa80fd16c091bae532b860fbf45)) - - - diff --git a/version.json b/version.json index 03978da5f..92f0f8328 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.6" + "version": "4.11.7" } \ No newline at end of file From d3b3316cbac18356b2f6b0912a3deb2c183e6534 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 13 Feb 2022 19:52:01 +0000 Subject: [PATCH 035/210] fix(settings): :bug: Fixed an issue where we were not displaying the excluded keyworks correctly in the TheMovieDbSettings page --- .../src/app/settings/themoviedb/themoviedb.component.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 008e2dfab..21a47637c 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -55,9 +55,10 @@ export class TheMovieDbComponent implements OnInit { this.excludedKeywords.forEach(key => { this.tmdbService.getKeyword(key.id).subscribe(keyResult => { - this.excludedKeywords.filter((val, idx) => { - val.name = keyResult.name; - }) + var keyToUpdate = this.excludedKeywords.filter((val) => { + return val.id == key.id; + })[0]; + keyToUpdate.name = keyResult.name; }); }); From 09f648515ea1e6dddb45ff1503f9db65d082d0b6 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sun, 13 Feb 2022 19:55:11 +0000 Subject: [PATCH 036/210] chore(release): :rocket: v4.11.8 --- CHANGELOG.md | 40 +++++++++------------------------------- version.json | 2 +- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b7cce69a..dd26fb210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13) + + +### Bug Fixes + +* **settings:** :bug: Fixed an issue where we were not displaying the excluded keyworks correctly in the TheMovieDbSettings page ([d3b3316](https://github.com/Ombi-app/Ombi/commit/d3b3316cbac18356b2f6b0912a3deb2c183e6534)) + + + ## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12) @@ -347,34 +356,3 @@ -# [4.3.0](https://github.com/Ombi-app/Ombi/compare/v4.2.13...v4.3.0) (2021-10-20) - - -### Bug Fixes - -* **translations:** 🌐 New translations from Crowdin [skip ci] ([b0f3abb](https://github.com/Ombi-app/Ombi/commit/b0f3abb9ceebdbe5d6c20af98b7355df2999eb58)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([77d017b](https://github.com/Ombi-app/Ombi/commit/77d017b3d8ffd1714a2f6efecc8c900d56d062e4)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([f6e9784](https://github.com/Ombi-app/Ombi/commit/f6e9784367d3678d899ed79bef6caa52005b6661)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([601a877](https://github.com/Ombi-app/Ombi/commit/601a87762a2ad393ee5fa2fe52052ceeeefb1bef)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([a4a80ba](https://github.com/Ombi-app/Ombi/commit/a4a80ba4da49733a65e691003646c0f349bd4c5f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([2961319](https://github.com/Ombi-app/Ombi/commit/2961319f61e95b2871480152b86ddca3375576a1)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([fc8d108](https://github.com/Ombi-app/Ombi/commit/fc8d108b660d53f499538328bfc271b05ac47d2b)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([1e03651](https://github.com/Ombi-app/Ombi/commit/1e03651c3b0eb77e45f9f6c55d31ee672eacd51e)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c0dd327](https://github.com/Ombi-app/Ombi/commit/c0dd327426514e305a88750d7c3deb21c194108f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([2156129](https://github.com/Ombi-app/Ombi/commit/2156129f175335746f204bb123035c070f518e96)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([aef0368](https://github.com/Ombi-app/Ombi/commit/aef0368de3aec306245bd1b16bc0de596a20d451)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([a38090b](https://github.com/Ombi-app/Ombi/commit/a38090b8dde17d1d150af0bca2830ea45d013a0e)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c5f1d33](https://github.com/Ombi-app/Ombi/commit/c5f1d3355758a5c3648479d44e50397c7f6c1a9d)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([3846d56](https://github.com/Ombi-app/Ombi/commit/3846d56a6e561a1b1dc65c385151d90fdd6217ee)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([dafe9c1](https://github.com/Ombi-app/Ombi/commit/dafe9c1a19d84f00c13f0a51ba90927c24282926)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([edb418a](https://github.com/Ombi-app/Ombi/commit/edb418a6f05887c68a0c24c48decc691996f97e4)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([dadabf9](https://github.com/Ombi-app/Ombi/commit/dadabf93e1582a0c39321fd9bf3de3fb11e3f406)) - - -### Features - -* **request-limits:** :sparkles: Added the new request limit options into the user importer ([01d4f4d](https://github.com/Ombi-app/Ombi/commit/01d4f4d718fe85ac181dae52565fb1b427965b4f)) -* **request-limits:** :sparkles: Added the new request limit options to the bulk edit ([03bc23a](https://github.com/Ombi-app/Ombi/commit/03bc23a74e4308aa6b4c6b25636edcdeb65c1f0e)) - - - diff --git a/version.json b/version.json index 92f0f8328..7235ac378 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.11.7" + "version": "4.11.8" } \ No newline at end of file From ba88848866b0a9dedb1e79b55c4d81a0fd453843 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 14 Feb 2022 22:08:09 +0000 Subject: [PATCH 037/210] feat(radarr): 4K Requests and Radarr 4K support * feat: updated radarr settings API to support 4k * feat: refactored the radarr setting page to support the new model * feat: Added 4k radarr to the settings page * feat: Added the new Movie 4k Request * feat: Got some of the backend rules done * feat: Made a load of progress * Removed the csproj ref * feat: fixed the radarr ui * feat: fixed up all the movie requests page * feat: Hide the 4K buttons when the user does not have the 4k permission * fix: fixed the templateref issue * test: fixed up all the tests * feat: Added migrations for media sever quality. Emby and Radarr Sync jobs now pull the quality * feat: Done the media sync jobs * feat: plex availability checker * feat: Updated the jellyfin availability checker to check for 4k * feat: updated emby availbility checker to check for 4k * feat: almost got it all working now * feat: Added 4k approve to the request list options * feat: Added 4k to the requests list and bulk approve * feat: Added the features service * feat: added feature update to the frontend * feat: got the features page working * feat: Applied the feature service on the backend * feat: added the feature flag on the UI * feat: added 4k to the card --- src/Ombi.Api.Emby/EmbyApi.cs | 2 +- .../Models/Media/EmbyMediastream.cs | 29 - .../Models/Media/Movie/EmbyMovie.cs | 1 + src/Ombi.Api.Jellyfin/JellyfinApi.cs | 2 +- .../Models/Media/JellyfinMediastream.cs | 29 - .../Models/Media/Movie/JellyfinMovie.cs | 1 + .../Models/V2/MovieResponse.cs | 7 +- .../Models/V3/RadarrV3QualityProfile.cs | 1 - .../Engine/V2/MovieRequestEngineTests.cs | 4 +- src/Ombi.Core.Tests/Engine/VoteEngineTests.cs | 6 +- .../Rule/Request/AutoApproveRuleTests.cs | 21 +- .../Rule/Request/CanRequestRuleTests.cs | 39 +- .../Request/ExistingMovieRequestRuleTests.cs | 83 +- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 44 +- .../Rule/Search/ExistingRequestRuleTests.cs | 5 +- .../Search/JellyfinAvailabilityRuleTests.cs | 46 +- .../Rule/Search/RadarrCacheRuleTests.cs | 50 +- .../Engine/Interfaces/IMovieRequestEngine.cs | 6 +- .../Engine/Interfaces/IRequestEngine.cs | 6 +- src/Ombi.Core/Engine/MovieRequestEngine.cs | 169 ++- src/Ombi.Core/Engine/TvRequestEngine.cs | 6 +- .../Engine/V2/MovieSearchEngineV2.cs | 7 + src/Ombi.Core/Engine/VoteEngine.cs | 2 +- .../Models/Requests/MovieRequestViewModel.cs | 2 + .../Models/Search/SearchMovieViewModel.cs | 9 + .../Search/V2/MovieFullInfoViewModel.cs | 9 + .../Rule/Rules/Request/AutoApproveRule.cs | 33 +- .../Rule/Rules/Request/CanRequestRule.cs | 19 +- .../Rules/Request/ExistingMovieRequestRule.cs | 32 +- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 24 +- .../Rule/Rules/Search/ExistingRule.cs | 24 +- .../Rules/Search/JellyfinAvailabilityRule.cs | 22 +- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 24 +- .../Rule/Rules/Search/RadarrCacheRule.cs | 13 +- src/Ombi.Core/Senders/IMovieSender.cs | 2 +- src/Ombi.Core/Senders/MovieSender.cs | 24 +- src/Ombi.Core/Services/FeatureService.cs | 28 + src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi.Helpers/OmbiRoles.cs | 1 + .../PlexContentSyncTests.cs | 78 +- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 17 +- .../Jobs/Emby/EmbyContentSync.cs | 43 +- .../Jellyfin/JellyfinAvaliabilityChecker.cs | 18 +- .../Jobs/Jellyfin/JellyfinContentSync.cs | 40 +- .../Jobs/Ombi/AutoDeleteRequests.cs | 2 +- .../Jobs/Ombi/ResendFailedRequests.cs | 4 +- .../Jobs/Plex/PlexAvailabilityChecker.cs | 34 +- .../Jobs/Plex/PlexContentSync.cs | 35 +- src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs | 7 +- src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 137 +- .../Models/External/RadarrSettings.cs | 11 + .../Settings/Models/FeatureSettings.cs | 24 + src/Ombi.Store/Context/SettingsContext.cs | 1 + src/Ombi.Store/Entities/MediaServerContent.cs | 6 +- src/Ombi.Store/Entities/PlexServerContent.cs | 1 - src/Ombi.Store/Entities/RadarrCache.cs | 2 + .../Entities/Requests/MovieRequests.cs | 20 + src/Ombi.Store/MigrationHelper.cs | 24 + ...211213229_MediaServerQualities.Designer.cs | 527 +++++++ .../20220211213229_MediaServerQualities.cs | 59 + .../20220212210902_MediaServer4k.Designer.cs | 536 +++++++ .../20220212210902_MediaServer4k.cs | 48 + .../ExternalMySqlContextModelSnapshot.cs | 27 +- ...211213347_MediaServerQualities.Designer.cs | 525 +++++++ .../20220211213347_MediaServerQualities.cs | 57 + .../20220212210807_MediaServer4k.Designer.cs | 534 +++++++ .../20220212210807_MediaServer4k.cs | 48 + .../ExternalSqliteContextModelSnapshot.cs | 26 +- .../20220210195008_Radarr4kRole.Designer.cs | 1246 ++++++++++++++++ .../OmbiMySql/20220210195008_Radarr4kRole.cs | 20 + .../20220210201011_MovieRequest4K.Designer.cs | 1249 ++++++++++++++++ .../20220210201011_MovieRequest4K.cs | 26 + ...220210215019_4kMovieProperties.Designer.cs | 1273 +++++++++++++++++ .../20220210215019_4kMovieProperties.cs | 102 ++ .../OmbiMySqlContextModelSnapshot.cs | 109 +- .../20220210194758_Radarr4kRole.Designer.cs | 1244 ++++++++++++++++ .../OmbiSqlite/20220210194758_Radarr4kRole.cs | 20 + .../20220210200338_MovieRequest4K.Designer.cs | 1247 ++++++++++++++++ .../20220210200338_MovieRequest4K.cs | 26 + ...220210214920_4kMovieProperties.Designer.cs | 1271 ++++++++++++++++ .../20220210214920_4kMovieProperties.cs | 101 ++ .../OmbiSqliteContextModelSnapshot.cs | 108 +- .../Repository/EmbyContentRepository.cs | 10 +- .../IMediaServerContentRepository.cs | 1 + .../Repository/JellyfinContentRepository.cs | 6 + .../Repository/MediaServerRepository.cs | 1 + .../Repository/PlexContentRepository.cs | 5 + src/Ombi.sln | 9 + src/Ombi/ClientApp/src/app/app.module.ts | 13 +- .../actor/discover-actor.component.html | 2 +- .../actor/discover-actor.component.ts | 17 +- .../card/discover-card.component.html | 16 +- .../card/discover-card.component.scss | 4 + .../card/discover-card.component.ts | 10 +- .../carousel-list.component.html | 2 +- .../carousel-list/carousel-list.component.ts | 6 +- .../discover-collections.component.html | 2 +- .../discover-collections.component.ts | 6 +- .../search-results.component.html | 2 +- .../search-results.component.ts | 6 +- .../src/app/interfaces/IRequestModel.ts | 8 + .../app/interfaces/ISearchMovieResultV2.ts | 5 + .../ClientApp/src/app/interfaces/ISettings.ts | 5 + .../ClientApp/src/app/interfaces/IUser.ts | 5 + .../movie/movie-details.component.html | 98 +- .../movie/movie-details.component.ts | 68 +- .../movie-information-panel.component.html | 5 + .../deny-dialog/deny-dialog.component.ts | 7 +- .../shared/interfaces/interfaces.ts | 1 + .../social-icons/social-icons.component.html | 6 +- .../social-icons/social-icons.component.ts | 10 +- .../tv-requests-panel.component.ts | 2 +- .../ClientApp/src/app/pipes/QualityPipe.ts | 3 + .../albums-grid/albums-grid.component.ts | 16 +- .../movies-grid/movies-grid.component.html | 11 +- .../movies-grid/movies-grid.component.ts | 20 +- .../options/request-options.component.html | 3 + .../options/request-options.component.ts | 23 +- .../components/requests-list.component.ts | 5 +- .../components/tv-grid/tv-grid.component.ts | 16 +- .../src/app/services/feature.service.ts | 27 + .../src/app/services/requestV2.service.ts | 4 +- .../src/app/services/settings.service.ts | 7 +- .../settings/features/features.component.html | 20 + .../settings/features/features.component.scss | 5 + .../settings/features/features.component.ts | 32 + .../components/radarr-form.component.html | 101 ++ .../components/radarr-form.component.scss | 21 + .../components/radarr-form.component.ts | 92 ++ .../app/settings/radarr/radarr.component.html | 121 +- .../app/settings/radarr/radarr.component.ts | 122 +- .../src/app/settings/settings.module.ts | 101 +- .../app/settings/settingsmenu.component.html | 1 + .../shared/role-directive/role-directive.ts | 36 + .../app/shared/role-directive/role.module.ts | 8 + .../ClientApp/src/app/shared/shared.module.ts | 3 + .../customization/customization.state.ts | 1 - .../state/features/features-initializer.ts | 10 + .../app/state/features/features.actions.ts | 15 + .../src/app/state/features/features.facade.ts | 26 + .../app/state/features/features.selectors.ts | 18 + .../src/app/state/features/features.state.ts | 40 + .../ClientApp/src/app/state/features/index.ts | 4 + .../ClientApp/src/app/state/features/types.ts | 4 + .../usermanagement-user.component.ts | 20 +- src/Ombi/Controllers/V1/IdentityController.cs | 41 +- src/Ombi/Controllers/V1/RequestController.cs | 12 +- src/Ombi/Controllers/V1/SettingsController.cs | 14 +- src/Ombi/Controllers/V2/FeaturesController.cs | 88 ++ src/Ombi/Controllers/V2/RequestsController.cs | 8 +- src/Ombi/Models/MovieUpdateModel.cs | 1 + src/Ombi/Ombi.csproj | 1 + src/Ombi/wwwroot/translations/en.json | 11 + 153 files changed, 12435 insertions(+), 781 deletions(-) create mode 100644 src/Ombi.Core/Services/FeatureService.cs create mode 100644 src/Ombi.Settings/Settings/Models/FeatureSettings.cs create mode 100644 src/Ombi.Store/MigrationHelper.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs create mode 100644 src/Ombi/ClientApp/src/app/services/feature.service.ts create mode 100644 src/Ombi/ClientApp/src/app/settings/features/features.component.html create mode 100644 src/Ombi/ClientApp/src/app/settings/features/features.component.scss create mode 100644 src/Ombi/ClientApp/src/app/settings/features/features.component.ts create mode 100644 src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.html create mode 100644 src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.scss create mode 100644 src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts create mode 100644 src/Ombi/ClientApp/src/app/shared/role-directive/role-directive.ts create mode 100644 src/Ombi/ClientApp/src/app/shared/role-directive/role.module.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/features-initializer.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/features.actions.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/features.facade.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/features.selectors.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/features.state.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/index.ts create mode 100644 src/Ombi/ClientApp/src/app/state/features/types.ts create mode 100644 src/Ombi/Controllers/V2/FeaturesController.cs diff --git a/src/Ombi.Api.Emby/EmbyApi.cs b/src/Ombi.Api.Emby/EmbyApi.cs index d911ca212..c12cdb716 100644 --- a/src/Ombi.Api.Emby/EmbyApi.cs +++ b/src/Ombi.Api.Emby/EmbyApi.cs @@ -170,7 +170,7 @@ namespace Ombi.Api.Emby request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,MediaStreams,Overview" : "ProviderIds,MediaStreams "); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); request.AddQueryString("sortBy", "DateCreated"); diff --git a/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs b/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs index 01032e0e7..f633f4ce0 100644 --- a/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs +++ b/src/Ombi.Api.Emby/Models/Media/EmbyMediastream.cs @@ -2,35 +2,6 @@ namespace Ombi.Api.Emby.Models.Movie { public class EmbyMediastream { - public string Codec { get; set; } - public string Language { get; set; } - public string TimeBase { get; set; } - public string CodecTimeBase { get; set; } - public string NalLengthSize { get; set; } - public bool IsInterlaced { get; set; } - public bool IsAVC { get; set; } - public int BitRate { get; set; } - public int BitDepth { get; set; } - public int RefFrames { get; set; } - public bool IsDefault { get; set; } - public bool IsForced { get; set; } - public int Height { get; set; } - public int Width { get; set; } - public float AverageFrameRate { get; set; } - public float RealFrameRate { get; set; } - public string Profile { get; set; } - public string Type { get; set; } - public string AspectRatio { get; set; } - public int Index { get; set; } - public bool IsExternal { get; set; } - public bool IsTextSubtitleStream { get; set; } - public bool SupportsExternalStream { get; set; } - public string PixelFormat { get; set; } - public int Level { get; set; } - public bool IsAnamorphic { get; set; } public string DisplayTitle { get; set; } - public string ChannelLayout { get; set; } - public int Channels { get; set; } - public int SampleRate { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs b/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs index a10ddaae6..e127f75f6 100644 --- a/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs +++ b/src/Ombi.Api.Emby/Models/Media/Movie/EmbyMovie.cs @@ -30,5 +30,6 @@ namespace Ombi.Api.Emby.Models.Movie public int CriticRating { get; set; } public string Overview { get; set; } public EmbyProviderids ProviderIds { get; set; } + public EmbyMediastream[] MediaStreams { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/JellyfinApi.cs b/src/Ombi.Api.Jellyfin/JellyfinApi.cs index 2fafbfd86..f6afb7912 100644 --- a/src/Ombi.Api.Jellyfin/JellyfinApi.cs +++ b/src/Ombi.Api.Jellyfin/JellyfinApi.cs @@ -157,7 +157,7 @@ namespace Ombi.Api.Jellyfin request.AddQueryString("Recursive", true.ToString()); request.AddQueryString("IncludeItemTypes", type); - request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview,ParentId" : "ProviderIds,ParentId"); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,MediaStreams Overview,ParentId" : "ProviderIds,ParentId,MediaStreams"); request.AddQueryString("startIndex", startIndex.ToString()); request.AddQueryString("limit", count.ToString()); if(!string.IsNullOrEmpty(parentIdFilder)) diff --git a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs index 89da2651a..e15a21e7b 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/JellyfinMediastream.cs @@ -2,35 +2,6 @@ namespace Ombi.Api.Jellyfin.Models.Movie { public class JellyfinMediastream { - public string Codec { get; set; } - public string Language { get; set; } - public string TimeBase { get; set; } - public string CodecTimeBase { get; set; } - public string NalLengthSize { get; set; } - public bool IsInterlaced { get; set; } - public bool IsAVC { get; set; } - public int BitRate { get; set; } - public int BitDepth { get; set; } - public int RefFrames { get; set; } - public bool IsDefault { get; set; } - public bool IsForced { get; set; } - public int Height { get; set; } - public int Width { get; set; } - public float AverageFrameRate { get; set; } - public float RealFrameRate { get; set; } - public string Profile { get; set; } - public string Type { get; set; } - public string AspectRatio { get; set; } - public int Index { get; set; } - public bool IsExternal { get; set; } - public bool IsTextSubtitleStream { get; set; } - public bool SupportsExternalStream { get; set; } - public string PixelFormat { get; set; } - public int Level { get; set; } - public bool IsAnamorphic { get; set; } public string DisplayTitle { get; set; } - public string ChannelLayout { get; set; } - public int Channels { get; set; } - public int SampleRate { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs b/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs index d86bf5047..a83e1f087 100644 --- a/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs +++ b/src/Ombi.Api.Jellyfin/Models/Media/Movie/JellyfinMovie.cs @@ -30,5 +30,6 @@ namespace Ombi.Api.Jellyfin.Models.Movie public int CriticRating { get; set; } public string Overview { get; set; } public JellyfinProviderids ProviderIds { get; set; } + public JellyfinMediastream[] MediaStreams { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs index 6eb2f1c5a..15627d414 100644 --- a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs +++ b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs @@ -44,7 +44,10 @@ namespace Ombi.Api.Radarr.Models public int id { get; set; } } - + public class MovieQuality + { + public V3.Quality quality { get; set; } + } public class Moviefile { public int movieId { get; set; } @@ -54,7 +57,7 @@ namespace Ombi.Api.Radarr.Models public DateTime dateAdded { get; set; } public string sceneName { get; set; } public int indexerFlags { get; set; } - public V3.Quality quality { get; set; } + public MovieQuality quality { get; set; } public Mediainfo mediaInfo { get; set; } public string originalFilePath { get; set; } public bool qualityCutoffNotMet { get; set; } diff --git a/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs index d985da358..6eca4af87 100644 --- a/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs +++ b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs @@ -25,5 +25,4 @@ public int resolution { get; set; } public string modifier { get; set; } } - } diff --git a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs index 3c651b167..d9f5b11be 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs @@ -9,6 +9,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Core.Engine; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models; @@ -43,8 +44,9 @@ namespace Ombi.Core.Tests.Engine.V2 var ombiSettings = new Mock>(); var requestSubs = new Mock>(); var mediaCache = new Mock(); + var featureService = new Mock(); _engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object, - logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object); + logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object, featureService.Object); } [Test] diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index be874669c..1269cd2bc 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -83,7 +83,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.True); VoteRepository.Verify(x => x.Add(It.Is(c => c.UserId == "abc" && c.VoteType == type)), Times.Once); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Never); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable VoteData { @@ -129,7 +129,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.False); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Never); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable AttemptedTwiceData { @@ -175,7 +175,7 @@ namespace Ombi.Core.Tests.Engine Assert.That(result.Result, Is.True); VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Once); VoteRepository.Verify(x => x.Add(It.Is(v => v.VoteType == type)), Times.Once); - MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1, false), Times.Never); } public static IEnumerable VoteConvertData { diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index 595ba39e0..9633249d4 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -10,6 +10,7 @@ using Ombi.Test.Common; using System.Collections.Generic; using Ombi.Store.Entities; using System; +using Ombi.Core.Services; namespace Ombi.Core.Tests.Rule.Request { @@ -28,21 +29,23 @@ namespace Ombi.Core.Tests.Rule.Request PrincipalMock = new Mock(); PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); + FeatureService = new Mock(); UserManager = MockHelper.MockUserManager(_users); - Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object); + Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object, FeatureService.Object); } private AutoApproveRule Rule { get; set; } private Mock PrincipalMock { get; set; } private Mock UserManager { get; set; } + private Mock FeatureService { get; set; } [Test] public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Admin)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -64,7 +67,7 @@ namespace Ombi.Core.Tests.Rule.Request public async Task Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -137,5 +140,17 @@ namespace Ombi.Core.Tests.Rule.Request Assert.True(result.Success); Assert.False(request.Approved); } + + [Test] + public async Task Should_ReturnFail_When4kRequestAndFeatureNotEnabled() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), It.IsAny())).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.False(request.Approved); + Assert.False(request.Approved4K); + } } } diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index 03dc6f68c..f601689dc 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -42,7 +42,42 @@ namespace Ombi.Core.Tests.Rule.Request public async Task Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + } + + [Test] + public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithMovieRole() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(true); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + } + + [Test] + public async Task Should_ReturnFailure_WhenRequestingMovie4KWithMovieRole() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true }; + var result = await Rule.Execute(request); + + Assert.False(result.Success); + Assert.False(string.IsNullOrEmpty(result.Message)); + } + + [Test] + public async Task Should_ReturnSuccess_WhenRequestingMovie4KWithAutoApprove() + { + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveMovie)).ReturnsAsync(true); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Request4KMovie)).ReturnsAsync(false); + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Has4KRequest = true }; var result = await Rule.Execute(request); Assert.True(result.Success); @@ -52,7 +87,7 @@ namespace Ombi.Core.Tests.Rule.Request public async Task Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() { UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.RequestMovie)).ReturnsAsync(false); - var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); Assert.False(result.Success); diff --git a/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs index 7ff69c9f2..682d4bf4d 100644 --- a/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/ExistingMovieRequestRuleTests.cs @@ -9,7 +9,9 @@ using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules.Request; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; @@ -24,12 +26,14 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { ContextMock = new Mock(); - Rule = new ExistingMovieRequestRule(ContextMock.Object); + FeatureService = new Mock(); + Rule = new ExistingMovieRequestRule(ContextMock.Object, FeatureService.Object); } private ExistingMovieRequestRule Rule { get; set; } private Mock ContextMock { get; set; } + private Mock FeatureService { get; set; } [Test] public async Task ExistingRequestRule_Movie_Has_Been_Requested_With_TheMovieDBId() @@ -96,5 +100,82 @@ namespace Ombi.Core.Tests.Rule.Request Assert.That(result.Success, Is.True); Assert.That(result.Message, Is.Null.Or.Empty); } + + [Test] + public async Task ExistingRequestRule_Movie_HasAlready4K_Request() + { + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = true + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Has4KRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.False); + Assert.That(result.Message, Is.Not.Empty); + } + + [Test] + public async Task ExistingRequestRule_Movie_4K_Request() + { + FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = false + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Is4kRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.True); + Assert.That(result.Message, Is.Null.Or.Empty); + } + + [Test] + public async Task ExistingRequestRule_Movie_4K_Request_FeatureNotEnabled() + { + FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(false); + ContextMock.Setup(x => x.GetAll()).Returns(new List + { + new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "2", + RequestType = RequestType.Movie, + Is4kRequest = false + } + }.AsQueryable().BuildMock().Object); + var o = new MovieRequests + { + TheMovieDbId = 2, + ImdbId = "1", + Is4kRequest = true + }; + var result = await Rule.Execute(o); + + Assert.That(result.Success, Is.False); + Assert.That(result.Message, Is.Not.Null); + } } } diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 0e455418a..95be538cd 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -35,7 +35,48 @@ namespace Ombi.Core.Tests.Rule.Search SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { - ProviderId = "123" + TheMovieDbId = "123", + Quality = "1" + }); + var search = new SearchMovieViewModel() + { + TheMovieDbId = "123", + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.True(search.Available); + } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInEmby_4K() + { + SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent + { + TheMovieDbId = "123", + Has4K = true + }); + var search = new SearchMovieViewModel() + { + TheMovieDbId = "123", + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.True(search.Available4K); + Assert.False(search.Available); + } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInEmby_Both() + { + SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new EmbySettings()); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent + { + TheMovieDbId = "123", + Has4K = true, + Quality = "1" }); var search = new SearchMovieViewModel() { @@ -44,6 +85,7 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); + Assert.True(search.Available4K); Assert.True(search.Available); } diff --git a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs index 11860ce28..66601f936 100644 --- a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs @@ -30,13 +30,14 @@ namespace Ombi.Core.Tests.Rule.Search [Test] - public async Task ShouldBe_Requested_WhenExisitngMovie() + public async Task ShouldBe_Requested_WhenExistingMovie() { var list = new MovieRequests { TheMovieDbId = 123, Approved = true, - RequestType = RequestType.Movie + RequestType = RequestType.Movie, + RequestedDate = System.DateTime.Now, }; MovieMock.Setup(x => x.GetRequestAsync(123)).ReturnsAsync(list); diff --git a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs index b733b0b2b..c0034afb7 100644 --- a/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/JellyfinAvailabilityRuleTests.cs @@ -35,7 +35,48 @@ namespace Ombi.Core.Tests.Rule.Search SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { - ProviderId = "123" + TheMovieDbId = "123", + Quality = "1080" + }); + var search = new SearchMovieViewModel() + { + TheMovieDbId = "123", + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.True(search.Available); + } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_4K() + { + SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent + { + TheMovieDbId = "123", + Has4K = true + }); + var search = new SearchMovieViewModel() + { + TheMovieDbId = "123", + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.False(search.Available); + Assert.True(search.Available4K); + } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInJellyfin_Both() + { + SettingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new JellyfinSettings()); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent + { + TheMovieDbId = "123", + Has4K = true, + Quality = "1" }); var search = new SearchMovieViewModel() { @@ -45,6 +86,7 @@ namespace Ombi.Core.Tests.Rule.Search Assert.True(result.Success); Assert.True(search.Available); + Assert.True(search.Available4K); } [Test] @@ -66,7 +108,7 @@ namespace Ombi.Core.Tests.Rule.Search }); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new JellyfinContent { - ProviderId = "123", + TheMovieDbId = "123", JellyfinId = 1.ToString() }); var search = new SearchMovieViewModel() diff --git a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs index 94efe89a2..8c5e0c662 100644 --- a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs @@ -28,25 +28,67 @@ namespace Ombi.Core.Tests.Rule.Search { var list = new List(){new RadarrCache { - TheMovieDbId = 123 + TheMovieDbId = 123, + HasRegular = true }}.AsQueryable(); - + ContextMock.Setup(x => x.GetAll()).Returns(list); var request = new SearchMovieViewModel { Id = 123 }; - var result =await Rule.Execute(request); + var result = await Rule.Execute(request); Assert.True(result.Success); Assert.True(request.Approved); } + [Test] + public async Task Should_ReturnAvailabl_WhenMovieIsInRadarr_4K() + { + var list = new List(){new RadarrCache + { + TheMovieDbId = 123, + Has4K = true, + HasFile = true + }}.AsQueryable(); + + ContextMock.Setup(x => x.GetAll()).Returns(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.False(request.Available); + Assert.True(request.Available4K); + } + + [Test] + public async Task Should_ReturnAvailable_WhenMovieIsInRadarr_Both() + { + var list = new List(){new RadarrCache + { + TheMovieDbId = 123, + Has4K = true, + HasRegular = true, + HasFile = true + }}.AsQueryable(); + + ContextMock.Setup(x => x.GetAll()).Returns(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.True(request.Available); + Assert.True(request.Available4K); + + } [Test] public async Task Should_ReturnNotApproved_WhenMovieIsNotInRadarr() { var list = DbHelper.GetQueryableMockDbSet(new RadarrCache { - TheMovieDbId = 000012 + TheMovieDbId = 000012, }); ContextMock.Setup(x => x.GetAll()).Returns(list); diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index 7cc64bee2..ab7a9079a 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -18,9 +18,9 @@ namespace Ombi.Core.Engine.Interfaces Task RemoveAllMovieRequests(); Task GetRequest(int requestId); Task UpdateMovieRequest(MovieRequests request); - Task ApproveMovie(MovieRequests request); - Task ApproveMovieById(int requestId); - Task DenyMovieById(int modelId, string denyReason); + Task ApproveMovie(MovieRequests request, bool is4K); + Task ApproveMovieById(int requestId, bool is4K); + Task DenyMovieById(int modelId, string denyReason, bool is4K); Task> GetRequests(int count, int position, string sortProperty, string sortOrder); Task> GetUnavailableRequests(int count, int position, string sortProperty, diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index 44278753f..d0fc04b10 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -19,11 +19,11 @@ namespace Ombi.Core.Engine.Interfaces Task> GetRequests(); Task UserHasRequest(string userId); - Task MarkUnavailable(int modelId); - Task MarkAvailable(int modelId); + Task MarkUnavailable(int modelId, bool is4K); + Task MarkAvailable(int modelId, bool is4K); Task GetTotal(); Task UnSubscribeRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type); - Task ReProcessRequest(int requestId, CancellationToken cancellationToken); + Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index f69e890be..2a29196b2 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -22,6 +22,7 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using Ombi.Core.Models; using System.Threading; +using Ombi.Core.Services; namespace Ombi.Core.Engine { @@ -30,7 +31,8 @@ namespace Ombi.Core.Engine public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, - ISettingsService ombiSettings, IRepository sub, IMediaCacheService mediaCacheService) + ISettingsService ombiSettings, IRepository sub, IMediaCacheService mediaCacheService, + IFeatureService featureService) : base(user, requestService, r, manager, cache, ombiSettings, sub) { MovieApi = movieApi; @@ -39,6 +41,7 @@ namespace Ombi.Core.Engine Logger = log; _requestLog = rl; _mediaCacheService = mediaCacheService; + _featureService = featureService; } private IMovieDbApi MovieApi { get; } @@ -47,6 +50,7 @@ namespace Ombi.Core.Engine private ILogger Logger { get; } private readonly IRepository _requestLog; private readonly IMediaCacheService _mediaCacheService; + private readonly IFeatureService _featureService; /// /// Requests the movie. @@ -72,7 +76,8 @@ namespace Ombi.Core.Engine var userDetails = await GetUser(); var canRequestOnBehalf = model.RequestOnBehalf.HasValue(); - var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); + var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) + || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); if (canRequestOnBehalf && !isAdmin) { return new RequestEngineResult @@ -93,27 +98,53 @@ namespace Ombi.Core.Engine }; } - var requestModel = new MovieRequests + var is4kFeatureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + var is4kRequest = is4kFeatureEnabled && model.Is4kRequest; + + MovieRequests requestModel; + bool isExisting = false; + // Do we already have a request? 4k or non 4k + var existingRequest = await MovieRepository.GetRequestAsync(movieInfo.Id); + if (existingRequest != null && is4kFeatureEnabled) { - TheMovieDbId = movieInfo.Id, - RequestType = RequestType.Movie, - Overview = movieInfo.Overview, - ImdbId = movieInfo.ImdbId, - PosterPath = PosterPathHelper.FixPosterPath(movieInfo.PosterPath), - Title = movieInfo.Title, - ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) - ? DateTime.Parse(movieInfo.ReleaseDate) - : DateTime.MinValue, - Status = movieInfo.Status, - RequestedDate = DateTime.UtcNow, - Approved = false, - RequestedUserId = canRequestOnBehalf ? model.RequestOnBehalf : userDetails.Id, - Background = movieInfo.BackdropPath, - LangCode = model.LanguageCode, - RequestedByAlias = model.RequestedByAlias, - RootPathOverride = model.RootFolderOverride.GetValueOrDefault(), - QualityOverride = model.QualityPathOverride.GetValueOrDefault() - }; + if (model.Is4kRequest) + { + existingRequest.Is4kRequest = true; + existingRequest.RequestedDate4k = DateTime.Now; + } + else + { + existingRequest.RequestedDate = DateTime.Now; + } + isExisting = true; + requestModel = existingRequest; + } + else + { + requestModel = new MovieRequests + { + TheMovieDbId = movieInfo.Id, + RequestType = RequestType.Movie, + Overview = movieInfo.Overview, + ImdbId = movieInfo.ImdbId, + PosterPath = PosterPathHelper.FixPosterPath(movieInfo.PosterPath), + Title = movieInfo.Title, + ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) + ? DateTime.Parse(movieInfo.ReleaseDate) + : DateTime.MinValue, + Status = movieInfo.Status, + RequestedDate = model.Is4kRequest ? DateTime.MinValue : DateTime.Now, + Approved = false, + RequestedUserId = canRequestOnBehalf ? model.RequestOnBehalf : userDetails.Id, + Background = movieInfo.BackdropPath, + LangCode = model.LanguageCode, + RequestedByAlias = model.RequestedByAlias, + RootPathOverride = model.RootFolderOverride.GetValueOrDefault(), + QualityOverride = model.QualityPathOverride.GetValueOrDefault(), + RequestedDate4k = model.Is4kRequest ? DateTime.Now : DateTime.MinValue, + Is4kRequest = model.Is4kRequest + }; + } var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); requestModel.DigitalReleaseDate = usDates?.ReleaseDate @@ -132,10 +163,10 @@ namespace Ombi.Core.Engine if (requestModel.Approved) // The rules have auto approved this { - var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf); + var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest); if (requestEngineResult.Result) { - var result = await ApproveMovie(requestModel); + var result = await ApproveMovie(requestModel, model.Is4kRequest); if (result.IsError) { Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message); @@ -153,7 +184,7 @@ namespace Ombi.Core.Engine // If there are no providers then it's successful but movie has not been sent } - return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf); + return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest); } @@ -508,13 +539,13 @@ namespace Ombi.Core.Engine return results; } - public async Task ApproveMovieById(int requestId) + public async Task ApproveMovieById(int requestId, bool is4K) { var request = await MovieRepository.Find(requestId); - return await ApproveMovie(request); + return await ApproveMovie(request, is4K); } - public async Task DenyMovieById(int modelId, string denyReason) + public async Task DenyMovieById(int modelId, string denyReason, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -525,8 +556,16 @@ namespace Ombi.Core.Engine }; } - request.Denied = true; - request.DeniedReason = denyReason; + if (is4K) + { + request.Denied4K = true; + request.DeniedReason4K = denyReason; + } + else + { + request.Denied = true; + request.DeniedReason = denyReason; + } await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -540,7 +579,7 @@ namespace Ombi.Core.Engine }; } - public async Task ApproveMovie(MovieRequests request) + public async Task ApproveMovie(MovieRequests request, bool is4K) { if (request == null) { @@ -550,9 +589,18 @@ namespace Ombi.Core.Engine }; } - request.MarkedAsApproved = DateTime.Now; - request.Approved = true; - request.Denied = false; + if (is4K) + { + request.MarkedAsApproved4K = DateTime.Now; + request.Approved4K = true; + request.Denied4K = false; + } + else + { + request.MarkedAsApproved = DateTime.Now; + request.Approved = true; + request.Denied = false; + } await MovieRepository.Update(request); var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification, string.Empty); @@ -562,7 +610,7 @@ namespace Ombi.Core.Engine } await _mediaCacheService.Purge(); - return await ProcessSendingMovie(request); + return await ProcessSendingMovie(request, is4K); } public async Task RequestCollection(int collectionId, CancellationToken cancellationToken) @@ -590,11 +638,11 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId }; } - private async Task ProcessSendingMovie(MovieRequests request) + private async Task ProcessSendingMovie(MovieRequests request, bool is4K) { if (request.Approved) { - var result = await Sender.Send(request); + var result = await Sender.Send(request, is4K); if (result.Success && result.Sent) { return new RequestEngineResult @@ -662,7 +710,7 @@ namespace Ombi.Core.Engine var result = await CheckCanManageRequest(request); if (result.IsError) return result; - + await MovieRepository.Delete(request); await _mediaCacheService.Purge(); return new RequestEngineResult @@ -683,7 +731,7 @@ namespace Ombi.Core.Engine return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId); } - public async Task ReProcessRequest(int requestId, CancellationToken cancellationToken) + public async Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken) { var request = await MovieRepository.Find(requestId); if (request == null) @@ -695,10 +743,10 @@ namespace Ombi.Core.Engine }; } - return await ProcessSendingMovie(request); + return await ProcessSendingMovie(request, is4K); } - public async Task MarkUnavailable(int modelId) + public async Task MarkUnavailable(int modelId, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -709,7 +757,14 @@ namespace Ombi.Core.Engine }; } - request.Available = false; + if (is4K) + { + request.Available4K = false; + } + else + { + request.Available = false; + } await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -720,7 +775,7 @@ namespace Ombi.Core.Engine }; } - public async Task MarkAvailable(int modelId) + public async Task MarkAvailable(int modelId, bool is4K) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -730,9 +785,16 @@ namespace Ombi.Core.Engine ErrorMessage = "Request does not exist" }; } - - request.Available = true; - request.MarkedAsAvailable = DateTime.Now; + if (!is4K) + { + request.Available = true; + request.MarkedAsAvailable = DateTime.Now; + } + else + { + request.Available4K = true; + request.MarkedAsAvailable4K = DateTime.Now; + } await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MovieRepository.Update(request); await _mediaCacheService.Purge(); @@ -744,9 +806,20 @@ namespace Ombi.Core.Engine }; } - private async Task AddMovieRequest(MovieRequests model, string movieName, string requestOnBehalf) + private async Task AddMovieRequest(MovieRequests model, string movieName, string requestOnBehalf, bool isExisting, bool is4k) { - await MovieRepository.Add(model); + if (is4k) + { + model.Has4KRequest = true; + } + if (!isExisting) + { + await MovieRepository.Add(model); + } + else + { + await MovieRepository.Update(model); + } var result = await RunSpecificRule(model, SpecificRules.CanSendNotification, requestOnBehalf); if (result.Success) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index edfa7b392..4b46e8151 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -793,7 +793,7 @@ namespace Ombi.Core.Engine return await TvRepository.GetChild().AnyAsync(x => x.RequestedUserId == userId); } - public async Task MarkUnavailable(int modelId) + public async Task MarkUnavailable(int modelId, bool is4K) { var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == modelId); if (request == null) @@ -821,7 +821,7 @@ namespace Ombi.Core.Engine }; } - public async Task MarkAvailable(int modelId) + public async Task MarkAvailable(int modelId, bool is4K) { ChildRequests request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == modelId); if (request == null) @@ -918,7 +918,7 @@ namespace Ombi.Core.Engine return await AfterRequest(model.ChildRequests.FirstOrDefault(), requestOnBehalf); } - public async Task ReProcessRequest(int requestId, CancellationToken cancellationToken) + public async Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken) { var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId, cancellationToken); if (request == null) diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index 7c69e4d5d..d160435be 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -406,6 +406,13 @@ namespace Ombi.Core.Engine.V2 mapped.Subscribed = viewMovie.Subscribed; mapped.ShowSubscribe = viewMovie.ShowSubscribe; mapped.DigitalReleaseDate = viewMovie.DigitalReleaseDate; + mapped.RequestedDate4k = viewMovie.RequestedDate4k; + mapped.Approved4K = viewMovie.Approved4K; + mapped.Available4K = viewMovie.Available4K; + mapped.Denied4K = viewMovie.Denied4K; + mapped.DeniedReason4K = viewMovie.DeniedReason4K; + mapped.Has4KRequest = viewMovie.Has4KRequest; + return mapped; } diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 5c73e03d9..a63ba1604 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -193,7 +193,7 @@ namespace Ombi.Core.Engine case RequestType.Movie: if (totalVotes >= voteSettings.MovieVoteMax) { - result = await _movieRequestEngine.ApproveMovieById(requestId); + result = await _movieRequestEngine.ApproveMovieById(requestId, false); } break; case RequestType.Album: diff --git a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs index 05eec3e3f..39a5b6c2a 100644 --- a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs @@ -34,6 +34,8 @@ namespace Ombi.Core.Models.Requests public int TheMovieDbId { get; set; } public string LanguageCode { get; set; } = "en"; + public bool Is4kRequest { get; set; } + /// /// This is only set from a HTTP Header /// diff --git a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs index 4d0d05a49..10cc76404 100644 --- a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs @@ -28,5 +28,14 @@ namespace Ombi.Core.Models.Search public override RequestType Type => RequestType.Movie; public ReleaseDatesDto ReleaseDates { get; set; } public DateTime? DigitalReleaseDate { get; set; } + public bool Has4KRequest { get; set; } + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs index 8e8dac9b1..847780e57 100644 --- a/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs +++ b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs @@ -41,6 +41,15 @@ namespace Ombi.Core.Models.Search.V2 public Recommendations Recommendations { get; set; } public ExternalIds ExternalIds { get; set; } public Keywords Keywords { get; set; } + public bool Has4KRequest { get; set; } + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } } public class Keywords { diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index f427434f0..92c1b11a7 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -5,7 +5,9 @@ using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Services; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -13,14 +15,16 @@ namespace Ombi.Core.Rule.Rules.Request { public class AutoApproveRule : BaseRequestRule, IRules { - public AutoApproveRule(IPrincipal principal, OmbiUserManager um) + public AutoApproveRule(IPrincipal principal, OmbiUserManager um, IFeatureService featureService) { User = principal; _manager = um; + _featureService = featureService; } private IPrincipal User { get; } private readonly OmbiUserManager _manager; + private readonly IFeatureService _featureService; public async Task Execute(BaseRequest obj) { @@ -28,17 +32,40 @@ namespace Ombi.Core.Rule.Rules.Request var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) { - obj.Approved = true; + if (obj is MovieRequests movie) + { + await Check4K(movie); + } + else + { + obj.Approved = true; + } return Success(); } if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) - obj.Approved = true; + { + var movie = (MovieRequests)obj; + await Check4K(movie); + } if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) obj.Approved = true; if (obj.RequestType == RequestType.Album && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic)) obj.Approved = true; return Success(); // We don't really care, we just don't set the obj to approve } + + private async Task Check4K(MovieRequests movie) + { + var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (movie.Is4kRequest && featureEnabled) + { + movie.Approved4K = true; + } + else + { + movie.Approved = true; + } + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 1c720a385..2546e1f29 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -33,8 +33,23 @@ namespace Ombi.Core.Rule.Rules.Request if (obj.RequestType == RequestType.Movie) { - if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) - return Success(); + var movie = (MovieRequests)obj; + var hasAutoApprove = await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie); + if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || hasAutoApprove) + { + if (movie.Is4kRequest && !hasAutoApprove) + { + var has4kPermission = await _manager.IsInRoleAsync(user, OmbiRoles.Request4KMovie); + if (has4kPermission) + { + return Success(); + } + } + else + { + return Success(); + } + } return Fail(ErrorCode.NoPermissionsRequestMovie, "You do not have permissions to Request a Movie"); } diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs index c837c42d1..17533a570 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs @@ -1,21 +1,24 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository; using Ombi.Core.Engine; using Ombi.Store.Repository.Requests; +using Ombi.Core.Services; +using Ombi.Settings.Settings.Models; namespace Ombi.Core.Rule.Rules.Request { public class ExistingMovieRequestRule : BaseRequestRule, IRules { - public ExistingMovieRequestRule(IMovieRequestRepository movie) + private readonly IFeatureService _featureService; + + public ExistingMovieRequestRule(IMovieRequestRepository movie, IFeatureService featureService) { Movie = movie; + _featureService = featureService; } private IMovieRequestRepository Movie { get; } @@ -35,7 +38,7 @@ namespace Ombi.Core.Rule.Rules.Request var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == movie.TheMovieDbId); if (existing != null) // Do we already have a request for this? { - found = true; + found = await Check4KRequests(movie, existing); } if (!found && movie.ImdbId.HasValue()) @@ -45,15 +48,30 @@ namespace Ombi.Core.Rule.Rules.Request x.ImdbId == movie.ImdbId); if (existing != null) { - found = true; + found = await Check4KRequests(movie, existing); } } - if(found) + if (found) { return Fail(ErrorCode.AlreadyRequested, $"\"{obj.Title}\" has already been requested"); } } return Success(); } + + private async Task Check4KRequests(MovieRequests movie, MovieRequests existing) + { + var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); + if (movie.Is4kRequest && existing.Has4KRequest && featureEnabled) + { + return true; + } + if (!movie.Is4kRequest && !existing.Has4KRequest || !featureEnabled) + { + return true; + } + + return false; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index e7a629854..4bc42ad04 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -63,11 +63,29 @@ namespace Ombi.Core.Rule.Rules.Search } } } - + if (item != null) { - obj.Available = true; - obj.EmbyUrl = item.Url; + if (obj is SearchMovieViewModel movie) + { + if (item.Has4K) + { + movie.Available4K = true; + obj.EmbyUrl = item.Url; + } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + obj.EmbyUrl = item.Url; + } if (obj.Type == RequestType.TvShow) { diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index 58c2508a6..a9bf13265 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -26,17 +26,27 @@ namespace Ombi.Core.Rule.Rules.Search public async Task Execute(SearchViewModel obj) { - if (obj.Type == RequestType.Movie) + if (obj is SearchMovieViewModel movie) { var movieRequests = await Movie.GetRequestAsync(obj.Id); if (movieRequests != null) // Do we already have a request for this? { - obj.Requested = true; - obj.RequestId = movieRequests.Id; - obj.Approved = movieRequests.Approved; - obj.Denied = movieRequests.Denied ?? false; - obj.DeniedReason = movieRequests.DeniedReason; - obj.Available = movieRequests.Available; + // If the RequestDate is a min value, that means there's only a 4k request + movie.Requested = movieRequests.RequestedDate != DateTime.MinValue; + movie.RequestId = movieRequests.Id; + movie.Approved = movieRequests.Approved; + movie.Denied = movieRequests.Denied ?? false; + movie.DeniedReason = movieRequests.DeniedReason; + movie.Available = movieRequests.Available; + movie.Has4KRequest = movieRequests.Has4KRequest; + movie.RequestedDate4k = movieRequests.RequestedDate4k; + movie.Approved4K = movieRequests.Approved4K; + movie.Available4K = movieRequests.Available4K; + movie.Denied4K = movieRequests.Denied4K; + movie.DeniedReason4K = movieRequests.DeniedReason4K; + movie.MarkedAsApproved4K = movieRequests.MarkedAsApproved4K; + movie.MarkedAsAvailable4K = movieRequests.MarkedAsAvailable4K; + movie.MarkedAsDenied4K = movieRequests.MarkedAsDenied4K; return Success(); } diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index 95a2da80b..f8c69c0f0 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -80,8 +80,26 @@ namespace Ombi.Core.Rule.Rules.Search obj.TheMovieDbId = obj.Id.ToString(); useTheMovieDb = true; } - obj.Available = true; - obj.JellyfinUrl = item.Url; + if (obj is SearchMovieViewModel movie) + { + if (item.Has4K) + { + movie.Available4K = true; + obj.JellyfinUrl = item.Url; + } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.EmbyUrl = item.Url; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + obj.JellyfinUrl = item.Url; + } if (obj.Type == RequestType.TvShow) { diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 4c05e0fe1..1742f9f20 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -89,7 +89,25 @@ namespace Ombi.Core.Rule.Rules.Search obj.TheMovieDbId = obj.Id.ToString(); useTheMovieDb = true; } - obj.Available = true; + + if (obj is SearchMovieViewModel movie) + { + if (item.Has4K) + { + movie.Available4K = true; + } + + if (item.Quality.HasValue()) + { + obj.Available = true; + obj.Quality = item.Quality; + } + } + else + { + obj.Available = true; + } + if (item.Url.StartsWith("http")) { obj.PlexUrl = item.Url; @@ -99,11 +117,9 @@ namespace Ombi.Core.Rule.Rules.Search // legacy content obj.PlexUrl = PlexHelper.BuildPlexMediaUrl(item.Url, host); } - obj.Quality = item.Quality; - if (obj.Type == RequestType.TvShow) + if (obj is SearchTvShowViewModel search) { - var search = (SearchTvShowViewModel)obj; // Let's go through the episodes now if (search.SeasonRequests.Any()) { diff --git a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs index 105681c82..63546f8c8 100644 --- a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs @@ -18,16 +18,23 @@ namespace Ombi.Core.Rule.Rules.Search public Task Execute(SearchViewModel obj) { - if (obj.Type == RequestType.Movie) + if (obj is SearchMovieViewModel movie) { // Check if it's in Radarr var result = _db.GetAll().FirstOrDefault(x => x.TheMovieDbId == obj.Id); if (result != null) { - obj.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? + movie.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? if (result.HasFile) { - obj.Available = true; + if (result.Has4K) + { + movie.Available4K = true; + } + if (result.HasRegular) + { + movie.Available = true; + } } } } diff --git a/src/Ombi.Core/Senders/IMovieSender.cs b/src/Ombi.Core/Senders/IMovieSender.cs index cf8ddf33b..dcf3f766f 100644 --- a/src/Ombi.Core/Senders/IMovieSender.cs +++ b/src/Ombi.Core/Senders/IMovieSender.cs @@ -6,6 +6,6 @@ namespace Ombi.Core { public interface IMovieSender { - Task Send(MovieRequests model); + Task Send(MovieRequests model, bool is4K); } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 87d686d35..36d40bdad 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -20,13 +20,12 @@ namespace Ombi.Core.Senders { public class MovieSender : IMovieSender { - public MovieSender(ISettingsService radarrSettings, IRadarrApi api, ILogger log, + public MovieSender(ISettingsService radarrSettings, ISettingsService radarr4kSettings, ILogger log, ISettingsService dogSettings, IDogNzbApi dogApi, ISettingsService cpSettings, ICouchPotatoApi cpApi, IRepository userProfiles, IRepository requestQueue, INotificationHelper notify, IRadarrV3Api radarrV3Api) { _radarrSettings = radarrSettings; - _radarrV2Api = api; _log = log; _dogNzbSettings = dogSettings; _dogNzbApi = dogApi; @@ -36,10 +35,11 @@ namespace Ombi.Core.Senders _requestQueuRepository = requestQueue; _notificationHelper = notify; _radarrV3Api = radarrV3Api; + _radarr4KSettings = radarr4kSettings; } private readonly ISettingsService _radarrSettings; - private readonly IRadarrApi _radarrV2Api; + private readonly ISettingsService _radarr4KSettings; private readonly ILogger _log; private readonly IDogNzbApi _dogNzbApi; private readonly ISettingsService _dogNzbSettings; @@ -50,16 +50,24 @@ namespace Ombi.Core.Senders private readonly INotificationHelper _notificationHelper; private readonly IRadarrV3Api _radarrV3Api; - public async Task Send(MovieRequests model) + public async Task Send(MovieRequests model, bool is4K) { try { var cpSettings = await _couchPotatoSettings.GetSettingsAsync(); - //var watcherSettings = await WatcherSettings.GetSettingsAsync(); - var radarrSettings = await _radarrSettings.GetSettingsAsync(); + + RadarrSettings radarrSettings; + if (is4K) + { + radarrSettings = await _radarr4KSettings.GetSettingsAsync(); + } + else + { + radarrSettings = await _radarrSettings.GetSettingsAsync(); + } if (radarrSettings.Enabled) { - return await SendToRadarr(model, radarrSettings); + return await SendToRadarr(model, is4K, radarrSettings); } var dogSettings = await _dogNzbSettings.GetSettingsAsync(); @@ -123,7 +131,7 @@ namespace Ombi.Core.Senders return await _dogNzbApi.AddMovie(settings.ApiKey, id); } - private async Task SendToRadarr(MovieRequests model, RadarrSettings settings) + private async Task SendToRadarr(MovieRequests model, bool is4K, RadarrSettings settings) { var qualityToUse = int.Parse(settings.DefaultQualityProfile); diff --git a/src/Ombi.Core/Services/FeatureService.cs b/src/Ombi.Core/Services/FeatureService.cs new file mode 100644 index 000000000..279c5c2c5 --- /dev/null +++ b/src/Ombi.Core/Services/FeatureService.cs @@ -0,0 +1,28 @@ +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Core.Services +{ + public interface IFeatureService + { + Task FeatureEnabled(string featureName); + } + + public class FeatureService : IFeatureService + { + private readonly ISettingsService _featureSettings; + + public FeatureService(ISettingsService featureSettings) + { + _featureSettings = featureSettings; + } + + public async Task FeatureEnabled(string featureName) + { + var settings = await _featureSettings.GetSettingsAsync(); + return settings.Features?.Where(x => x.Name.Equals(featureName, System.StringComparison.InvariantCultureIgnoreCase)).Select(x => x.Enabled)?.FirstOrDefault() ?? false; + } + } +} diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index f81cd05da..3fb5cd643 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -224,6 +224,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddScoped(); } public static void RegisterJobs(this IServiceCollection services) diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index 02a480fdf..3174419c4 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -16,5 +16,6 @@ public const string ReceivesNewsletter = nameof(ReceivesNewsletter); public const string ManageOwnRequests = nameof(ManageOwnRequests); public const string EditCustomPage = nameof(EditCustomPage); + public const string Request4KMovie = nameof(Request4KMovie); } } \ No newline at end of file diff --git a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs index 3b9fa33b0..da128794c 100644 --- a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs +++ b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs @@ -133,12 +133,88 @@ namespace Ombi.Schedule.Tests } })); - await _subject.MovieLoop(new PlexServers { Ip = "http://test.com/", Port = 80}, content, contentToAdd, contentProcessed); + await _subject.MovieLoop(new PlexServers { Ip = "http://test.com/", Port = 80 }, content, contentToAdd, contentProcessed); var first = contentToAdd.First(); Assert.That(first.ImdbId, Is.EqualTo("tt0322259")); _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } + + [Test] + public async Task UpdatesExistingMovieWhen_WeFindAnotherQuality() + { + var content = new Mediacontainer + { + Metadata = new[] + { + new Metadata + { + ratingKey = 11, + title = "test1", + year = 2021, + type = "movie", + Media = new Medium[1] + { + new Medium + { + videoResolution = "4k" + } + } + }, + } + }; + var contentToAdd = new HashSet(); + var contentProcessed = new Dictionary(); + _mocker.Setup(x => + x.GetFirstContentByCustom(It.IsAny>>())) + .Returns(Task.FromResult(new PlexServerContent + { + Quality = "1080" + })); + + await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); + + Assert.That(contentToAdd, Is.Empty); + _mocker.Verify(x => x.Update(It.Is(x => x.Quality == "1080" && x.Has4K)), Times.Once); + } + + [Test] + public async Task DoesNotUpdatesExistingMovieWhen_WeFindSameQuality() + { + var content = new Mediacontainer + { + Metadata = new[] + { + new Metadata + { + ratingKey = 11, + title = "test1", + year = 2021, + type = "movie", + Media = new Medium[1] + { + new Medium + { + videoResolution = "1080" + } + } + }, + } + }; + var contentToAdd = new HashSet(); + var contentProcessed = new Dictionary(); + _mocker.Setup(x => + x.GetFirstContentByCustom(It.IsAny>>())) + .Returns(Task.FromResult(new PlexServerContent + { + Quality = "1080" + })); + + await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); + + Assert.That(contentToAdd, Is.Empty); + _mocker.Verify(x => x.Update(It.IsAny()), Times.Never); + } } } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 852530be4..1c4416e36 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -53,10 +53,11 @@ namespace Ombi.Schedule.Jobs.Emby private async Task ProcessMovies() { - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); foreach (var movie in movies) { + var has4kRequest = movie.Has4KRequest; EmbyContent embyContent = null; if (movie.TheMovieDbId > 0) { @@ -75,8 +76,18 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogInformation("We have found the request {0} on Emby, sending the notification", movie?.Title ?? string.Empty); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; + if (has4kRequest && embyContent.Has4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + } + + // If we have a non-4k versison then mark as available + if (embyContent.Quality.HasValue()) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + } if (movie.Available) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 646cbdee0..89baa7e9d 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; @@ -86,10 +87,10 @@ namespace Ombi.Schedule.Jobs.Emby private async Task StartServerCache(EmbyServers server, bool recentlyAdded) { if (!ValidateSettings(server)) + { return; + } - //await _repo.ExecuteSql("DELETE FROM EmbyEpisode"); - //await _repo.ExecuteSql("DELETE FROM EmbyContent"); if (server.EmbySelectedLibraries.Any() && server.EmbySelectedLibraries.Any(x => x.Enabled)) { @@ -209,6 +210,7 @@ namespace Ombi.Schedule.Jobs.Emby var totalCount = movies.TotalRecordCount; var processed = 0; var mediaToAdd = new HashSet(); + var mediaToUpdate = new HashSet(); while (processed < totalCount) { foreach (var movie in movies.Items) @@ -219,13 +221,13 @@ namespace Ombi.Schedule.Jobs.Emby await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { - await ProcessMovies(item, mediaToAdd, server); + await ProcessMovies(item, mediaToAdd, mediaToUpdate, server); } } else { // Regular movie - await ProcessMovies(movie, mediaToAdd, server); + await ProcessMovies(movie, mediaToAdd, mediaToUpdate, server); } processed++; @@ -238,24 +240,32 @@ namespace Ombi.Schedule.Jobs.Emby movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, AmountToTake, server.AdministratorId, server.FullUri); } await _repo.AddRange(mediaToAdd); + await _repo.UpdateRange(mediaToUpdate); mediaToAdd.Clear(); } } - private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content, EmbyServers server) + private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content, ICollection toUpdate, EmbyServers server) { + var quality = movieInfo.MediaStreams?.FirstOrDefault()?.DisplayTitle ?? string.Empty; + var has4K = false; + if (quality.Contains("4K", CompareOptions.IgnoreCase)) + { + has4K = true; + } + // Check if it exists var existingMovie = await _repo.GetByEmbyId(movieInfo.Id); var alreadyGoingToAdd = content.Any(x => x.EmbyId == movieInfo.Id); if (existingMovie == null && !alreadyGoingToAdd) { - if (!movieInfo.ProviderIds.Any()) { _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); return; } - _logger.LogDebug("Adding new movie {0}", movieInfo.Name); + _logger.LogDebug($"Adding new movie {movieInfo.Name}"); + content.Add(new EmbyContent { ImdbId = movieInfo.ProviderIds.Imdb, @@ -264,13 +274,26 @@ namespace Ombi.Schedule.Jobs.Emby Type = MediaType.Movie, EmbyId = movieInfo.Id, Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow + AddedAt = DateTime.UtcNow, + Quality = has4K ? null : quality, + Has4K = has4K }); } else { - // we have this - _logger.LogDebug("We already have movie {0}", movieInfo.Name); + if (!existingMovie.Quality.Equals(quality, StringComparison.InvariantCultureIgnoreCase)) + { + _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); + existingMovie.Quality = has4K ? null : quality; + existingMovie.Has4K = has4K; + + toUpdate.Add(existingMovie); + } + else + { + // we have this + _logger.LogDebug($"We already have movie {movieInfo.Name}"); + } } } diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 125b27fc3..dd183e537 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -80,10 +80,11 @@ namespace Ombi.Schedule.Jobs.Jellyfin private async Task ProcessMovies() { - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); foreach (var movie in movies) { + var has4kRequest = movie.Has4KRequest; JellyfinContent jellyfinContent = null; if (movie.TheMovieDbId > 0) { @@ -102,8 +103,19 @@ namespace Ombi.Schedule.Jobs.Jellyfin _log.LogInformation("We have found the request {0} on Jellyfin, sending the notification", movie?.Title ?? string.Empty); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; + if (has4kRequest && jellyfinContent.Has4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + } + + // If we have a non-4k versison then mark as available + if (jellyfinContent.Quality.HasValue()) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + } + if (movie.Available) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index fec5ca0ce..10a6ae98c 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; @@ -77,9 +78,6 @@ namespace Ombi.Schedule.Jobs.Jellyfin return; } - //await _repo.ExecuteSql("DELETE FROM JellyfinEpisode"); - //await _repo.ExecuteSql("DELETE FROM JellyfinContent"); - if (server.JellyfinSelectedLibraries.Any() && server.JellyfinSelectedLibraries.Any(x => x.Enabled)) { var movieLibsToFilter = server.JellyfinSelectedLibraries.Where(x => x.Enabled && x.CollectionType == "movies"); @@ -179,6 +177,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin var totalCount = movies.TotalRecordCount; var processed = 0; var mediaToAdd = new HashSet(); + var mediaToUpdate = new HashSet(); while (processed < totalCount) { foreach (var movie in movies.Items) @@ -189,7 +188,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { - await ProcessMovies(item, mediaToAdd, server); + await ProcessMovies(item, mediaToAdd, mediaToUpdate, server); } processed++; @@ -198,20 +197,28 @@ namespace Ombi.Schedule.Jobs.Jellyfin { processed++; // Regular movie - await ProcessMovies(movie, mediaToAdd, server); + await ProcessMovies(movie, mediaToAdd, mediaToUpdate, server); } } // Get the next batch movies = await Api.GetAllMovies(server.ApiKey, parentId, processed, 200, server.AdministratorId, server.FullUri); await _repo.AddRange(mediaToAdd); + await _repo.UpdateRange(mediaToUpdate); mediaToAdd.Clear(); } } - private async Task ProcessMovies(JellyfinMovie movieInfo, ICollection content, JellyfinServers server) + private async Task ProcessMovies(JellyfinMovie movieInfo, ICollection content, ICollection toUpdate, JellyfinServers server) { + var quality = movieInfo.MediaStreams?.FirstOrDefault()?.DisplayTitle ?? string.Empty; + var has4K = false; + if (quality.Contains("4K", CompareOptions.IgnoreCase)) + { + has4K = true; + } + // Check if it exists var existingMovie = await _repo.GetByJellyfinId(movieInfo.Id); var alreadyGoingToAdd = content.Any(x => x.JellyfinId == movieInfo.Id); @@ -222,7 +229,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin _logger.LogWarning($"Movie {movieInfo.Name} has no relevant metadata. Skipping."); return; } - _logger.LogDebug("Adding new movie {0}", movieInfo.Name); + _logger.LogDebug($"Adding new movie {movieInfo.Name}"); content.Add(new JellyfinContent { ImdbId = movieInfo.ProviderIds.Imdb, @@ -231,13 +238,26 @@ namespace Ombi.Schedule.Jobs.Jellyfin Type = MediaType.Movie, JellyfinId = movieInfo.Id, Url = JellyfinHelper.GetJellyfinMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), - AddedAt = DateTime.UtcNow + AddedAt = DateTime.UtcNow, + Quality = has4K ? null : quality, + Has4K = has4K }); } else { - // we have this - _logger.LogDebug("We already have movie {0}", movieInfo.Name); + if (!existingMovie.Quality.Equals(quality, StringComparison.InvariantCultureIgnoreCase)) + { + _logger.LogDebug($"We have found another quality for Movie '{movieInfo.Name}', Quality: '{quality}'"); + existingMovie.Quality = has4K ? null : quality; + existingMovie.Has4K = has4K; + + toUpdate.Add(existingMovie); + } + else + { + // we have this + _logger.LogDebug($"We already have movie {movieInfo.Name}"); + } } } diff --git a/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs index a2a7e4ed1..eba3c4998 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs @@ -25,7 +25,7 @@ namespace Ombi.Schedule.Jobs.Ombi _ombiSettings = ombiSettings; _movieRequests = movieRequest; _tvRequestRepository = tvRequestRepository; - _musicRequestRepository = _musicRequestRepository; + _musicRequestRepository = musicRequestRepository; _logger = logger; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs index 3a9a75835..e0df3752c 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs @@ -49,7 +49,9 @@ namespace Ombi.Schedule.Jobs.Ombi await _requestQueue.SaveChangesAsync(); continue; } - var result = await _movieSender.Send(movieRequest); + + // TODO probably need to add something to the request queue to better idenitfy if it's a 4k request + var result = await _movieSender.Send(movieRequest, movieRequest.Approved4K); if (result.Success) { request.Completed = DateTime.UtcNow; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 74dc4aa96..a6e1b205b 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -180,16 +180,12 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessMovies() { // Get all non available - var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); var itemsForAvailbility = new List(); foreach (var movie in movies) { - if (movie.Available) - { - return; - } - + var has4kRequest = movie.Has4KRequest; PlexServerContent item = null; if (movie.ImdbId.HasValue()) { @@ -208,9 +204,23 @@ namespace Ombi.Schedule.Jobs.Plex continue; } - _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); - movie.Available = true; - movie.MarkedAsAvailable = DateTime.UtcNow; + _log.LogInformation($"[PAC] - Movie request {movie.Title} - {movie.Id} is now available, sending notification"); + + if (has4kRequest && item.Has4K) + { + movie.Available4K = true; + movie.Approved4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + } + + // If we have a non-4k versison then mark as available + if (item.Quality.HasValue()) + { + movie.Available = true; + movie.Approved = true; + movie.MarkedAsAvailable = DateTime.Now; + } + itemsForAvailbility.Add(new AvailabilityModel { Id = movie.Id, @@ -222,9 +232,9 @@ namespace Ombi.Schedule.Jobs.Plex { await _movieRepo.SaveChangesAsync(); } - foreach (var i in itemsForAvailbility) - { + foreach (var i in itemsForAvailbility.DistinctBy(x => x.Id)) + { await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, @@ -234,8 +244,6 @@ namespace Ombi.Schedule.Jobs.Plex Recipient = i.RequestedUser }); } - - //await _repo.SaveChangesAsync(); } private bool _disposed; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index bdb7e70bc..04b28d6e7 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -293,7 +293,7 @@ namespace Ombi.Schedule.Jobs.Plex Dictionary contentProcessed) { Logger.LogDebug("Processing Movies"); - foreach (var movie in content?.Metadata ?? new Metadata[] { }) + foreach (var movie in content?.Metadata ?? Array.Empty()) { // Let's check if we have this movie @@ -302,11 +302,31 @@ namespace Ombi.Schedule.Jobs.Plex var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title && x.ReleaseYear == movie.year.ToString() && x.Type == MediaType.Movie); - // The rating key keeps changing - //var existing = await Repo.GetByKey(movie.ratingKey); if (existing != null) { - Logger.LogDebug("We already have movie {0}", movie.title); + // We need to see if this is a different quality, + // We want to know if this is a 4k content for example + var foundQualities = movie.Media?.Select(x => x.videoResolution); + + foreach (var quality in foundQualities) + { + if (quality.Equals(existing.Quality)) + { + // We got it + continue; + } + + // We don't have this quality + if (quality.Equals("4k", StringComparison.InvariantCultureIgnoreCase)) + { + Logger.LogDebug($"We already have movie {movie.title}, But found a 4K version!"); + existing.Has4K = true; + await Repo.Update(existing); + } + } + + + Logger.LogDebug($"We already have movie {movie.title}"); continue; } @@ -349,6 +369,10 @@ namespace Ombi.Schedule.Jobs.Plex } var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + var qualities = movie.Media?.Select(x => x.videoResolution); + var is4k = qualities != null && qualities.Any(x => x.Equals("4k", StringComparison.InvariantCultureIgnoreCase)); + var selectedQuality = is4k ? string.Empty : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; + var item = new PlexServerContent { AddedAt = DateTime.Now, @@ -358,7 +382,8 @@ namespace Ombi.Schedule.Jobs.Plex Title = movie.title, Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, movie.ratingKey, servers.ServerHostname), Seasons = new List(), - Quality = movie.Media?.FirstOrDefault()?.videoResolution ?? string.Empty + Quality = selectedQuality, + Has4K = is4k, }; if (providerIds.ImdbId.HasValue()) { diff --git a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs index 1fb191fd1..19178ca48 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Ombi.Store.Entities; - -namespace Ombi.Schedule.Jobs.Radarr +namespace Ombi.Schedule.Jobs.Radarr { public interface IRadarrSync : IBaseJob { - Task> GetCachedContent(); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 3cda06281..eb97edeff 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -10,106 +9,114 @@ using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; +using Ombi.Store.Repository; using Quartz; -using Serilog; namespace Ombi.Schedule.Jobs.Radarr { public class RadarrSync : IRadarrSync { - public RadarrSync(ISettingsService radarr, IRadarrV3Api radarrApi, ILogger log, ExternalContext ctx) + public RadarrSync(ISettingsService radarr, ISettingsService radarr4k, IRadarrV3Api radarrApi, ILogger log, ExternalContext ctx, + IExternalRepository radarrRepo) { - RadarrSettings = radarr; - RadarrApi = radarrApi; - Logger = log; + _radarrSettings = radarr; + _radarr4kSettings = radarr4k; + _api = radarrApi; + _logger = log; _ctx = ctx; - RadarrSettings.ClearCache(); + _radarrRepo = radarrRepo; + _radarrSettings.ClearCache(); + _radarr4kSettings.ClearCache(); } - private ISettingsService RadarrSettings { get; } - private IRadarrV3Api RadarrApi { get; } - private ILogger Logger { get; } + private readonly ISettingsService _radarrSettings; + private readonly ISettingsService _radarr4kSettings; + private readonly IRadarrV3Api _api; + private readonly ILogger _logger; private readonly ExternalContext _ctx; - - private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1); + private readonly IExternalRepository _radarrRepo; public async Task Execute(IJobExecutionContext job) { - await SemaphoreSlim.WaitAsync(); try { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) + var strat = _ctx.Database.CreateExecutionStrategy(); + await strat.ExecuteAsync(async () => { - try + // Let's remove the old cached data + using var tran = await _ctx.Database.BeginTransactionAsync(); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); + tran.Commit(); + }); + + var radarrSettings = _radarrSettings.GetSettingsAsync(); + var radarr4kSettings = _radarr4kSettings.GetSettingsAsync(); + await Process(await radarrSettings); + await Process(await radarr4kSettings); + } + catch (Exception) + { + _logger.LogInformation(LoggingEvents.RadarrCacher, "Radarr is not setup, cannot cache episodes"); + } + } + + private async Task Process(RadarrSettings settings) + { + if (settings.Enabled) + { + try + { + var movies = await _api.GetMovies(settings.ApiKey, settings.FullUri); + var existingMovies = _radarrRepo.GetAll(); + if (movies != null) { - var movies = await RadarrApi.GetMovies(settings.ApiKey, settings.FullUri); - if (movies != null) + var movieIds = new List(); + foreach (var m in movies) { - var strat = _ctx.Database.CreateExecutionStrategy(); - await strat.ExecuteAsync(async () => + if (m.monitored || m.hasFile) { - // Let's remove the old cached data - using (var tran = await _ctx.Database.BeginTransactionAsync()) + if (m.tmdbId > 0) { - await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); - tran.Commit(); - } - }); + var is4k = m.movieFile?.quality?.quality?.resolution >= 2160; - var movieIds = new List(); - foreach (var m in movies) - { - if (m.monitored || m.hasFile) - { - if (m.tmdbId > 0) + // Do we have a cached movie for this already? + var existing = await existingMovies.FirstOrDefaultAsync(x => x.TheMovieDbId == m.tmdbId); + if (existing != null) + { + existing.Has4K = is4k; + existing.HasFile = m.hasFile; + } + else { movieIds.Add(new RadarrCache { TheMovieDbId = m.tmdbId, - HasFile = m.hasFile + HasFile = m.hasFile, + Has4K = is4k, + HasRegular = !is4k }); } - else - { - Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); - } } - } - strat = _ctx.Database.CreateExecutionStrategy(); - await strat.ExecuteAsync(async () => - { - using (var tran = await _ctx.Database.BeginTransactionAsync()) + else { - await _ctx.RadarrCache.AddRangeAsync(movieIds); - - await _ctx.SaveChangesAsync(); - tran.Commit(); + _logger.LogError($"TMDBId is not > 0 for movie {m.title}"); } - }); + } } - await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); - } - catch (System.Exception ex) - { - Logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Radarr"); + // Save from the updates made to the existing movies (they are in the EF Change Tracker) + await _radarrRepo.SaveChangesAsync(); + + await _radarrRepo.AddRange(movieIds); } + + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); + } + catch (System.Exception ex) + { + _logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Radarr"); } } - catch (Exception) - { - Logger.LogInformation(LoggingEvents.RadarrCacher, "Radarr is not setup, cannot cache episodes"); - } - finally - { - SemaphoreSlim.Release(); - } - } - - public async Task> GetCachedContent() - { - return await _ctx.RadarrCache.ToListAsync(); } private bool _disposed; diff --git a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs index b074e28d6..1b3e0982f 100644 --- a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs @@ -10,4 +10,15 @@ public string MinimumAvailability { get; set; } public bool ScanForAvailability { get; set; } } + + public class Radarr4KSettings : RadarrSettings + { + // no additional properties needed + } + + public class RadarrCombinedModel + { + public RadarrSettings Radarr { get; set; } + public Radarr4KSettings Radarr4K { get; set; } + } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/FeatureSettings.cs b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs new file mode 100644 index 000000000..6a285d422 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/FeatureSettings.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ombi.Settings.Settings.Models +{ + public class FeatureSettings : Settings + { + public List Features { get; set; } + } + + public class FeatureEnablement + { + public string Name { get; set; } + public bool Enabled { get; set; } + } + + public static class FeatureNames + { + public const string Movie4KRequests = nameof(Movie4KRequests); + } +} diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index 83ffa792d..39883cb92 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -1,5 +1,6 @@ using System.Linq; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; using Ombi.Store.Entities; namespace Ombi.Store.Context diff --git a/src/Ombi.Store/Entities/MediaServerContent.cs b/src/Ombi.Store/Entities/MediaServerContent.cs index df50efc86..4f086060b 100644 --- a/src/Ombi.Store/Entities/MediaServerContent.cs +++ b/src/Ombi.Store/Entities/MediaServerContent.cs @@ -12,7 +12,11 @@ namespace Ombi.Store.Entities public string TvDbId { get; set; } public string TheMovieDbId { get; set; } public MediaType Type { get; set; } - + /// + /// Only populated if it's not 4k + /// + public string Quality { get; set; } + public bool Has4K { get; set; } public string Url { get; set; } public ICollection Episodes { get; set; } diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index cba02c68c..f33ddb2f1 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -41,7 +41,6 @@ namespace Ombi.Store.Entities /// Plex's internal ID for this item /// public int Key { get; set; } - public string Quality { get; set; } public int? RequestId { get; set; } diff --git a/src/Ombi.Store/Entities/RadarrCache.cs b/src/Ombi.Store/Entities/RadarrCache.cs index 4b62412fc..553e84f2b 100644 --- a/src/Ombi.Store/Entities/RadarrCache.cs +++ b/src/Ombi.Store/Entities/RadarrCache.cs @@ -7,5 +7,7 @@ namespace Ombi.Store.Entities { public int TheMovieDbId { get; set; } public bool HasFile { get; set; } + public bool Has4K { get; set; } + public bool HasRegular { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs index 42b17be73..49189a387 100644 --- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs +++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; +using System; namespace Ombi.Store.Entities.Requests { @@ -22,9 +23,28 @@ namespace Ombi.Store.Entities.Requests [NotMapped] public bool ShowSubscribe { get; set; } + /// + /// This is only used during the request process to identify if + /// it's a regular request or a 4k + /// + [NotMapped] + public bool Is4kRequest { get; set; } + public int RootPathOverride { get; set; } public int QualityOverride { get; set; } + public bool Has4KRequest { get; set; } + + public bool Approved4K { get; set; } + public DateTime MarkedAsApproved4K { get; set; } + public DateTime RequestedDate4k { get; set; } + public bool Available4K { get; set; } + public DateTime? MarkedAsAvailable4K { get; set; } + public bool? Denied4K { get; set; } + public DateTime MarkedAsDenied4K { get; set; } + public string DeniedReason4K { get; set; } + + /// /// Only Use for setting the Language Code, Use the LanguageCode property for reading /// diff --git a/src/Ombi.Store/MigrationHelper.cs b/src/Ombi.Store/MigrationHelper.cs new file mode 100644 index 000000000..58b6d6b68 --- /dev/null +++ b/src/Ombi.Store/MigrationHelper.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +namespace Ombi.Store +{ + internal static class MigrationHelper + { + public static void InsertRole(this MigrationBuilder mb, string role) + { + mb.Sql($@" +INSERT INTO AspnetRoles(Id, ConcurrencyStamp, Name, NormalizedName) +SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}' +WHERE NOT EXISTS(SELECT 1 FROM AspnetRoles WHERE Name = '{role}');"); + } + + public static void InsertRoleMySql(this MigrationBuilder mb, string role) + { + mb.Sql($@" +INSERT INTO AspNetRoles(Id, ConcurrencyStamp, Name, NormalizedName) +SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}' +WHERE NOT EXISTS(SELECT 1 FROM AspNetRoles WHERE Name = '{role}');"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs new file mode 100644 index 000000000..ab88ff30d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.Designer.cs @@ -0,0 +1,527 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220211213229_MediaServerQualities")] + partial class MediaServerQualities + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("PlexContentId") + .HasColumnType("int"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs new file mode 100644 index 000000000..add7da05e --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220211213229_MediaServerQualities.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class MediaServerQualities : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "RadarrCache", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "HasRegular", + table: "RadarrCache", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Quality", + table: "JellyfinContent", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Quality", + table: "EmbyContent", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "HasRegular", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs new file mode 100644 index 000000000..fbdc63e32 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.Designer.cs @@ -0,0 +1,536 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220212210902_MediaServer4k")] + partial class MediaServer4k + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("int"); + + b.Property("PlexContentId") + .HasColumnType("int"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs new file mode 100644 index 000000000..c7e1888a6 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220212210902_MediaServer4k.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class MediaServer4k : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "PlexServerContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "JellyfinContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "EmbyContent", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "PlexServerContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs index dbdbe6f55..b75c45665 100644 --- a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.MySql; +#nullable disable + namespace Ombi.Store.Migrations.ExternalMySql { [DbContext(typeof(ExternalMySqlContext))] @@ -14,8 +16,8 @@ namespace Ombi.Store.Migrations.ExternalMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -44,12 +46,18 @@ namespace Ombi.Store.Migrations.ExternalMySql .IsRequired() .HasColumnType("varchar(255)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); b.Property("ProviderId") .HasColumnType("longtext"); + b.Property("Quality") + .HasColumnType("longtext"); + b.Property("TheMovieDbId") .HasColumnType("longtext"); @@ -122,6 +130,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("AddedAt") .HasColumnType("datetime(6)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -132,6 +143,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("ProviderId") .HasColumnType("longtext"); + b.Property("Quality") + .HasColumnType("longtext"); + b.Property("TheMovieDbId") .HasColumnType("longtext"); @@ -321,6 +335,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("AddedAt") .HasColumnType("datetime(6)"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -362,9 +379,15 @@ namespace Ombi.Store.Migrations.ExternalMySql .ValueGeneratedOnAdd() .HasColumnType("int"); + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + b.Property("HasFile") .HasColumnType("tinyint(1)"); + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + b.Property("TheMovieDbId") .HasColumnType("int"); diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs new file mode 100644 index 000000000..4ec8422d5 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.Designer.cs @@ -0,0 +1,525 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220211213347_MediaServerQualities")] + partial class MediaServerQualities + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("PlexContentId") + .HasColumnType("INTEGER"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs new file mode 100644 index 000000000..b194b7845 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220211213347_MediaServerQualities.cs @@ -0,0 +1,57 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class MediaServerQualities : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "RadarrCache", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "HasRegular", + table: "RadarrCache", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Quality", + table: "JellyfinContent", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "Quality", + table: "EmbyContent", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "HasRegular", + table: "RadarrCache"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Quality", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs new file mode 100644 index 000000000..70cd280e9 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.Designer.cs @@ -0,0 +1,534 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220212210807_MediaServer4k")] + partial class MediaServer4k + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("INTEGER"); + + b.Property("PlexContentId") + .HasColumnType("INTEGER"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs new file mode 100644 index 000000000..593465c0a --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220212210807_MediaServer4k.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class MediaServer4k : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4K", + table: "PlexServerContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "JellyfinContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Has4K", + table: "EmbyContent", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4K", + table: "PlexServerContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "JellyfinContent"); + + migrationBuilder.DropColumn( + name: "Has4K", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs index 00d4f44f4..302f5f537 100644 --- a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.Sqlite; +#nullable disable + namespace Ombi.Store.Migrations.ExternalSqlite { [DbContext(typeof(ExternalSqliteContext))] @@ -13,8 +15,7 @@ namespace Ombi.Store.Migrations.ExternalSqlite protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -43,12 +44,18 @@ namespace Ombi.Store.Migrations.ExternalSqlite .IsRequired() .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); b.Property("ProviderId") .HasColumnType("TEXT"); + b.Property("Quality") + .HasColumnType("TEXT"); + b.Property("TheMovieDbId") .HasColumnType("TEXT"); @@ -121,6 +128,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("AddedAt") .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -131,6 +141,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("ProviderId") .HasColumnType("TEXT"); + b.Property("Quality") + .HasColumnType("TEXT"); + b.Property("TheMovieDbId") .HasColumnType("TEXT"); @@ -320,6 +333,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("AddedAt") .HasColumnType("TEXT"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -361,9 +377,15 @@ namespace Ombi.Store.Migrations.ExternalSqlite .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("Has4K") + .HasColumnType("INTEGER"); + b.Property("HasFile") .HasColumnType("INTEGER"); + b.Property("HasRegular") + .HasColumnType("INTEGER"); + b.Property("TheMovieDbId") .HasColumnType("INTEGER"); diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs new file mode 100644 index 000000000..713672bcf --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.Designer.cs @@ -0,0 +1,1246 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210195008_Radarr4kRole")] + partial class Radarr4kRole + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + 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() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs new file mode 100644 index 000000000..88eeed9f2 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210195008_Radarr4kRole.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Ombi.Helpers; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class Radarr4kRole : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertRoleMySql(OmbiRoles.Request4KMovie); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs new file mode 100644 index 000000000..7a6c430bd --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.Designer.cs @@ -0,0 +1,1249 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210201011_MovieRequest4K")] + partial class MovieRequest4K + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + 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() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Is4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs new file mode 100644 index 000000000..f9d02b876 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210201011_MovieRequest4K.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class MovieRequest4K : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4KRequest", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4KRequest", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs new file mode 100644 index 000000000..240993d15 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.Designer.cs @@ -0,0 +1,1273 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220210215019_4kMovieProperties")] + partial class _4kMovieProperties + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + 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() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs new file mode 100644 index 000000000..3b599c0e0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220210215019_4kMovieProperties.cs @@ -0,0 +1,102 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class _4kMovieProperties : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Approved4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Available4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Denied4K", + table: "MovieRequests", + type: "tinyint(1)", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeniedReason4K", + table: "MovieRequests", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "RequestedDate4k", + table: "MovieRequests", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Approved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Available4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Denied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "DeniedReason4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "RequestedDate4k", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 8fdebc4c2..5a5c28b40 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.MySql; +#nullable disable + namespace Ombi.Store.Migrations.OmbiMySql { [DbContext(typeof(OmbiMySqlContext))] @@ -14,8 +16,8 @@ namespace Ombi.Store.Migrations.OmbiMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -40,7 +42,7 @@ namespace Ombi.Store.Migrations.OmbiMySql .IsUnique() .HasDatabaseName("RoleNameIndex"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -63,7 +65,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => @@ -86,7 +88,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -108,7 +110,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -123,7 +125,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -142,7 +144,7 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.Audit", b => @@ -342,7 +344,7 @@ namespace Ombi.Store.Migrations.OmbiMySql .IsUnique() .HasDatabaseName("UserNameIndex"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => @@ -406,28 +408,6 @@ namespace Ombi.Store.Migrations.OmbiMySql b.ToTable("RequestQueue"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("RequestId") - .HasColumnType("int"); - - b.Property("RequestType") - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("RequestSubscription"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") @@ -661,21 +641,36 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("Approved") .HasColumnType("tinyint(1)"); + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + b.Property("Available") .HasColumnType("tinyint(1)"); + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + b.Property("Background") .HasColumnType("longtext"); b.Property("Denied") .HasColumnType("tinyint(1)"); + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + b.Property("DeniedReason") .HasColumnType("longtext"); + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + b.Property("DigitalReleaseDate") .HasColumnType("datetime(6)"); + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -688,12 +683,21 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("MarkedAsApproved") .HasColumnType("datetime(6)"); + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + b.Property("MarkedAsAvailable") .HasColumnType("datetime(6)"); + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + b.Property("MarkedAsDenied") .HasColumnType("datetime(6)"); + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + b.Property("Overview") .HasColumnType("longtext"); @@ -715,6 +719,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("RequestedDate") .HasColumnType("datetime(6)"); + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + b.Property("RequestedUserId") .HasColumnType("varchar(255)"); @@ -815,6 +822,28 @@ namespace Ombi.Store.Migrations.OmbiMySql b.ToTable("TvRequests"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") @@ -1052,15 +1081,6 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Navigation("User"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.HasOne("Ombi.Store.Entities.OmbiUser", "User") - .WithMany() - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") @@ -1145,6 +1165,15 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Navigation("User"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs new file mode 100644 index 000000000..e2c442a23 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.Designer.cs @@ -0,0 +1,1244 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210194758_Radarr4kRole")] + partial class Radarr4kRole + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs new file mode 100644 index 000000000..a97de9011 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210194758_Radarr4kRole.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Ombi.Helpers; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class Radarr4kRole : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertRole(OmbiRoles.Request4KMovie); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs new file mode 100644 index 000000000..a2dee4283 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.Designer.cs @@ -0,0 +1,1247 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210200338_MovieRequest4K")] + partial class MovieRequest4K + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Is4KRequest") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs new file mode 100644 index 000000000..8d70a0358 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210200338_MovieRequest4K.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class MovieRequest4K : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Has4KRequest", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Has4KRequest", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs new file mode 100644 index 000000000..e315e78ea --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.Designer.cs @@ -0,0 +1,1271 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220210214920_4kMovieProperties")] + partial class _4kMovieProperties + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs new file mode 100644 index 000000000..38f010eae --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220210214920_4kMovieProperties.cs @@ -0,0 +1,101 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class _4kMovieProperties : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Approved4K", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Available4K", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Denied4K", + table: "MovieRequests", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeniedReason4K", + table: "MovieRequests", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "RequestedDate4k", + table: "MovieRequests", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Approved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Available4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Denied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "DeniedReason4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsApproved4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsAvailable4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "MarkedAsDenied4K", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "RequestedDate4k", + table: "MovieRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 46a00353e..528989d02 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Ombi.Store.Context.Sqlite; +#nullable disable + namespace Ombi.Store.Migrations.OmbiSqlite { [DbContext(typeof(OmbiSqliteContext))] @@ -13,8 +15,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -39,7 +40,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite .IsUnique() .HasDatabaseName("RoleNameIndex"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -62,7 +63,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => @@ -85,7 +86,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -107,7 +108,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -122,7 +123,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -141,7 +142,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.Audit", b => @@ -341,7 +342,7 @@ namespace Ombi.Store.Migrations.OmbiSqlite .IsUnique() .HasDatabaseName("UserNameIndex"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => @@ -405,28 +406,6 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.ToTable("RequestQueue"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("RequestId") - .HasColumnType("INTEGER"); - - b.Property("RequestType") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("RequestSubscription"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") @@ -660,21 +639,36 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("Approved") .HasColumnType("INTEGER"); + b.Property("Approved4K") + .HasColumnType("INTEGER"); + b.Property("Available") .HasColumnType("INTEGER"); + b.Property("Available4K") + .HasColumnType("INTEGER"); + b.Property("Background") .HasColumnType("TEXT"); b.Property("Denied") .HasColumnType("INTEGER"); + b.Property("Denied4K") + .HasColumnType("INTEGER"); + b.Property("DeniedReason") .HasColumnType("TEXT"); + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + b.Property("DigitalReleaseDate") .HasColumnType("TEXT"); + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -687,12 +681,21 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("MarkedAsApproved") .HasColumnType("TEXT"); + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + b.Property("MarkedAsAvailable") .HasColumnType("TEXT"); + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + b.Property("MarkedAsDenied") .HasColumnType("TEXT"); + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + b.Property("Overview") .HasColumnType("TEXT"); @@ -714,6 +717,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("RequestedDate") .HasColumnType("TEXT"); + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + b.Property("RequestedUserId") .HasColumnType("TEXT"); @@ -814,6 +820,28 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.ToTable("TvRequests"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") @@ -1051,15 +1079,6 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Navigation("User"); }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => - { - b.HasOne("Ombi.Store.Entities.OmbiUser", "User") - .WithMany() - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") @@ -1144,6 +1163,15 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Navigation("User"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index 19bab7f76..ddec14025 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -25,7 +25,6 @@ // ************************************************************************/ #endregion -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -37,7 +36,6 @@ namespace Ombi.Store.Repository { public class EmbyContentRepository : MediaServerContentRepository, IEmbyContentRepository { - public EmbyContentRepository(ExternalContext db):base(db) { } @@ -97,7 +95,13 @@ namespace Ombi.Store.Repository { Db.EmbyContent.Update((EmbyContent)existingContent); } - + + public override Task UpdateRange(IEnumerable existingContent) + { + Db.EmbyContent.UpdateRange((EmbyContent)existingContent); + return InternalSaveChanges(); + } + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Emby; } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs index 73cc00fde..db4835a16 100644 --- a/src/Ombi.Store/Repository/IMediaServerContentRepository.cs +++ b/src/Ombi.Store/Repository/IMediaServerContentRepository.cs @@ -10,6 +10,7 @@ namespace Ombi.Store.Repository { RecentlyAddedType RecentlyAddedType{ get; } Task Update(IMediaServerContent existingContent); + Task UpdateRange(IEnumerable existingContent); IQueryable GetAllEpisodes(); Task Add(IMediaServerEpisode content); Task AddRange(IEnumerable content); diff --git a/src/Ombi.Store/Repository/JellyfinContentRepository.cs b/src/Ombi.Store/Repository/JellyfinContentRepository.cs index 28cdcfae8..02acee5b0 100644 --- a/src/Ombi.Store/Repository/JellyfinContentRepository.cs +++ b/src/Ombi.Store/Repository/JellyfinContentRepository.cs @@ -98,6 +98,12 @@ namespace Ombi.Store.Repository Db.JellyfinContent.Update((JellyfinContent)existingContent); } + public override Task UpdateRange(IEnumerable existingContent) + { + Db.JellyfinContent.UpdateRange((JellyfinContent)existingContent); + return InternalSaveChanges(); + } + public override RecentlyAddedType RecentlyAddedType => RecentlyAddedType.Jellyfin; } } diff --git a/src/Ombi.Store/Repository/MediaServerRepository.cs b/src/Ombi.Store/Repository/MediaServerRepository.cs index 0f458ee2b..c1c7d4ec8 100644 --- a/src/Ombi.Store/Repository/MediaServerRepository.cs +++ b/src/Ombi.Store/Repository/MediaServerRepository.cs @@ -21,5 +21,6 @@ namespace Ombi.Store.Repository public abstract Task Add(IMediaServerEpisode content); public abstract Task AddRange(IEnumerable content); public abstract void UpdateWithoutSave(IMediaServerContent existingContent); + public abstract Task UpdateRange(IEnumerable existingContent); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index b99ba157f..be79d1a29 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -164,5 +164,10 @@ namespace Ombi.Store.Repository await InternalSaveChanges(); } + public override Task UpdateRange(IEnumerable existingContent) + { + Db.PlexServerContent.UpdateRange((PlexServerContent)existingContent); + return InternalSaveChanges(); + } } } \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index 841f84dbd..a92df055e 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -126,6 +126,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.RottenTomatoes", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.I18n", "Ombi.I18n\Ombi.I18n.csproj", "{6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MediaServer", "Ombi.Api.MediaServer\Ombi.Api.MediaServer.csproj", "{AFC0BA9B-E38D-479F-825A-2F94EE4D6120}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -439,6 +441,12 @@ Global {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A922D57-8622-4C36-8E6E-D5BA9E8DA6C0}.Release|Any CPU.Build.0 = Release|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.NonUiBuild|Any CPU.ActiveCfg = NonUiBuild|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.NonUiBuild|Any CPU.Build.0 = NonUiBuild|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -487,6 +495,7 @@ Global {E2186FDA-D827-4781-8663-130AC382F12C} = {9293CA11-360A-4C20-A674-B9E794431BF5} {5DE40A66-B369-469E-8626-ECE23D9D8034} = {9293CA11-360A-4C20-A674-B9E794431BF5} {8F19C701-7881-4BC7-8BBA-B068A6B954AD} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {AFC0BA9B-E38D-479F-825A-2F94EE4D6120} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/src/app/app.module.ts b/src/Ombi/ClientApp/src/app/app.module.ts index 082ce80d2..735dce36b 100644 --- a/src/Ombi/ClientApp/src/app/app.module.ts +++ b/src/Ombi/ClientApp/src/app/app.module.ts @@ -21,6 +21,8 @@ import { CustomPageComponent } from "./custompage/custompage.component"; import { CustomizationState } from "./state/customization/customization.state"; import { DataViewModule } from "primeng/dataview"; import { DialogModule } from "primeng/dialog"; +import { FEATURES_INITIALIZER } from "./state/features/features-initializer"; +import { FeatureState } from "./state/features"; import { JwtModule } from "@auth0/angular-jwt"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LandingPageService } from "./services"; @@ -38,6 +40,8 @@ import { MatInputModule } from "@angular/material/input"; import { MatListModule } from '@angular/material/list'; import { MatMenuModule } from "@angular/material/menu"; import { MatNativeDateModule } from '@angular/material/core'; +import { MatPaginatorI18n } from "./localization/MatPaginatorI18n"; +import { MatPaginatorIntl } from "@angular/material/paginator"; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSidenavModule } from '@angular/material/sidenav'; import { MatSlideToggleModule } from "@angular/material/slide-toggle"; @@ -63,11 +67,9 @@ import { StorageService } from "./shared/storage/storage-service"; import { TokenResetPasswordComponent } from "./login/tokenresetpassword.component"; import { TooltipModule } from "primeng/tooltip"; import { TranslateHttpLoader } from "@ngx-translate/http-loader"; +import { TranslateService } from "@ngx-translate/core"; import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor"; import { environment } from "../environments/environment"; -import { MatPaginatorIntl } from "@angular/material/paginator"; -import { TranslateService } from "@ngx-translate/core"; -import { MatPaginatorI18n } from "./localization/MatPaginatorI18n"; const routes: Routes = [ { path: "*", component: PageNotFoundComponent }, @@ -162,10 +164,10 @@ export function JwtTokenGetter() { }), SidebarModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, LayoutModule, MatSlideToggleModule, - NgxsModule.forRoot([CustomizationState], { + NgxsModule.forRoot([CustomizationState, FeatureState], { developmentMode: !environment.production, }), - ...environment.production ? [] : + ...environment.production ? [] : [ NgxsReduxDevtoolsPluginModule.forRoot(), ] @@ -205,6 +207,7 @@ export function JwtTokenGetter() { StorageService, RequestService, SignalRNotificationService, + FEATURES_INITIALIZER, CUSTOMIZATION_INITIALIZER, { provide: APP_BASE_HREF, diff --git a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html index 67f243503..87db00955 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.html @@ -5,7 +5,7 @@
- +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts index 290042d87..5c333522c 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { SearchV2Service } from "../../../services"; import { IActorCredits, IActorCast } from "../../../interfaces/ISearchTvResultV2"; @@ -6,30 +6,31 @@ import { IDiscoverCardResult } from "../../interfaces"; import { RequestType } from "../../../interfaces"; import { AuthService } from "../../../auth/auth.service"; import { forkJoin } from "rxjs"; -import { isEqual } from "lodash"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./discover-actor.component.html", styleUrls: ["./discover-actor.component.scss"], }) -export class DiscoverActorComponent { +export class DiscoverActorComponent implements OnInit { public actorId: number; public loadingFlag: boolean; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; constructor(private searchService: SearchV2Service, private route: ActivatedRoute, - private auth: AuthService) { + private auth: AuthService, + private featureService: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.actorId = params.actorId; - this.isAdmin = this.auth.isAdmin(); - this.search(); }); } - - private search() { + ngOnInit() { + this.isAdmin = this.auth.isAdmin(); + this.is4kEnabled = this.featureService.is4kEnabled(); this.discoverResults = []; this.loading(); diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html index 5a6993e44..b7593902f 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html @@ -20,12 +20,24 @@
-
-
+
+ + + + + +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss index 6bf6748bf..38cd4501e 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss @@ -292,4 +292,8 @@ a.poster-overlay:hover{ .btn-ombi{ background-color:#293a4c; +} + +::ng-deep .mat-menu-panel { + min-width: 190px !important; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 4de883256..470559b0d 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -21,6 +21,7 @@ export class DiscoverCardComponent implements OnInit { @Input() public discoverType: DiscoverType; @Input() public result: IDiscoverCardResult; @Input() public isAdmin: boolean; + @Input() public is4kEnabled: boolean = false; public RequestType = RequestType; public hide: boolean; public fullyLoaded = false; @@ -111,7 +112,7 @@ export class DiscoverCardComponent implements OnInit { return ""; } - public request(event: any) { + public request(event: any, is4k: boolean) { event.preventDefault(); this.loading = true; switch (this.result.type) { @@ -121,14 +122,15 @@ export class DiscoverCardComponent implements OnInit { return; case RequestType.movie: if (this.isAdmin) { - const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id }, panelClass: 'modal-panel' }); + const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id, }, panelClass: 'modal-panel' }); dialog.afterClosed().subscribe((result) => { if (result) { this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, qualityPathOverride: result.radarrPathId, requestOnBehalf: result.username?.id, - rootFolderOverride: result.radarrFolderId, }).subscribe(x => { + rootFolderOverride: result.radarrFolderId, + is4KRequest: is4k }).subscribe(x => { if (x.result) { this.result.requested = true; this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.result.title }), "Ok"); @@ -139,7 +141,7 @@ export class DiscoverCardComponent implements OnInit { } }); } else { - this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null }).subscribe(x => { + this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: this.translate.currentLang, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null, is4KRequest: is4k }).subscribe(x => { if (x.result) { this.result.requested = true; this.messageService.send(this.translate.instant("Requests.RequestAddedSuccessfully", { title: this.result.title }), "Ok"); diff --git a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html index aa9ffc5f2..5be2aa1ad 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.html @@ -8,6 +8,6 @@ - + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts index a00146ad5..9617c993e 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts @@ -5,6 +5,7 @@ import { SearchV2Service } from "../../../services"; import { StorageService } from "../../../shared/storage/storage-service"; import { MatButtonToggleChange } from '@angular/material/button-toggle'; import { Carousel } from 'primeng/carousel'; +import { FeaturesFacade } from "../../../state/features/features.facade"; export enum DiscoverType { Upcoming, @@ -36,6 +37,7 @@ export class CarouselListComponent implements OnInit { public RequestType = RequestType; public loadingFlag: boolean; public DiscoverType = DiscoverType; + public is4kEnabled = false; get mediaTypeStorageKey() { return "DiscoverOptions" + this.discoverType.toString(); @@ -44,7 +46,8 @@ export class CarouselListComponent implements OnInit { private currentlyLoaded = 0; constructor(private searchService: SearchV2Service, - private storageService: StorageService) { + private storageService: StorageService, + private featureFacade: FeaturesFacade) { this.responsiveOptions = [ { breakpoint: '4000px', @@ -135,6 +138,7 @@ export class CarouselListComponent implements OnInit { } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.currentlyLoaded = 0; const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey); if (localDiscoverOptions) { diff --git a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html index 23a7791f0..0750a12c0 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.html @@ -16,7 +16,7 @@
- +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts index 9e84ea7d0..d643c52af 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/collections/discover-collections.component.ts @@ -8,6 +8,7 @@ import { IDiscoverCardResult } from "../../interfaces"; import { IMovieCollectionsViewModel } from "../../../interfaces/ISearchTvResultV2"; import { RequestServiceV2 } from "../../../services/requestV2.service"; import { RequestType } from "../../../interfaces"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./discover-collections.component.html", @@ -19,6 +20,7 @@ export class DiscoverCollectionsComponent implements OnInit { public collection: IMovieCollectionsViewModel; public loadingFlag: boolean; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; @@ -27,13 +29,15 @@ export class DiscoverCollectionsComponent implements OnInit { private requestServiceV2: RequestServiceV2, private messageService: MessageService, private auth: AuthService, - private translate: TranslateService) { + private translate: TranslateService, + private featureFacade: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.collectionId = params.collectionId; }); } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.loadingFlag = true; this.isAdmin = this.auth.isAdmin(); this.collection = await this.searchService.getMovieCollections(this.collectionId); diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html index 4ef9255fb..b1911ceee 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html @@ -4,7 +4,7 @@
- +
diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts index f0258b97d..a8544365d 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts @@ -10,6 +10,7 @@ import { SearchFilter } from "../../../my-nav/SearchFilter"; import { SearchV2Service } from "../../../services"; import { StorageService } from "../../../shared/storage/storage-service"; import { isEqual } from "lodash"; +import { FeaturesFacade } from "../../../state/features/features.facade"; @Component({ templateUrl: "./search-results.component.html", @@ -21,6 +22,7 @@ export class DiscoverSearchResultsComponent implements OnInit { public searchTerm: string; public results: IMultiSearchResult[]; public isAdmin: boolean; + public is4kEnabled = false; public discoverResults: IDiscoverCardResult[] = []; @@ -34,7 +36,8 @@ export class DiscoverSearchResultsComponent implements OnInit { private router: Router, private advancedDataService: AdvancedSearchDialogDataService, private store: StorageService, - private authService: AuthService) { + private authService: AuthService, + private featureFacade: FeaturesFacade) { this.route.params.subscribe((params: any) => { this.isAdvancedSearch = this.router.url === '/discover/advanced/search'; if (this.isAdvancedSearch) { @@ -53,6 +56,7 @@ export class DiscoverSearchResultsComponent implements OnInit { } public async ngOnInit() { + this.is4kEnabled = this.featureFacade.is4kEnabled(); this.isAdmin = this.authService.isAdmin(); this.filterService.onFilterChange.subscribe(async x => { if (!isEqual(this.filter, x)) { diff --git a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts index 440e0d5b2..1ccbd355b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts @@ -16,6 +16,12 @@ export interface IMovieRequests extends IFullBaseRequest { subscribed: boolean; showSubscribe: boolean; requestStatus: string; + has4KRequest: boolean; + approved4K: boolean; + available4K: boolean; + denied4K: boolean; + deniedReason4K: string; + requestedDate4k: Date; // For the UI rootPathOverrideTitle: string; @@ -53,6 +59,7 @@ export interface IRequestsViewModel { export interface IMovieUpdateModel { id: number; + is4K: boolean; } export interface IDenyMovieModel extends IMovieUpdateModel { @@ -176,6 +183,7 @@ export interface IEpisodesRequests { export interface IMovieRequestModel extends BaseRequestOptions { theMovieDbId: number; languageCode: string | undefined; + is4KRequest?: boolean; } export interface IFilter { diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts index da4b27f32..d4faf5bfe 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts @@ -42,6 +42,11 @@ externalIds: IExternalIds; keywords: IKeywords; belongsToCollection: ICollectionsModel; + has4KRequest: boolean; + approved4K: boolean; + available4K: boolean; + denied4K: boolean; + deniedReason4K: string; // for the UI requestProcessing: boolean; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index c7990215f..8bf2755ec 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -158,6 +158,11 @@ export interface IRadarrSettings extends IExternalSettings { scanForAvailability: boolean; } +export interface IRadarrCombined { + radarr: IRadarrSettings; + radarr4K: IRadarrSettings; +} + export interface ILidarrSettings extends IExternalSettings { enabled: boolean; apiKey: string; diff --git a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts index 97882e783..069b1e506 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts @@ -146,3 +146,8 @@ export enum INotificationAgent { Webhook = 9, WhatsApp = 10 } + +export interface IFeatureEnablement { + name: string; + enabled: boolean; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 2e807547c..2a29b30e6 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -22,9 +22,11 @@ [isAdmin]="isAdmin" [canShowAdvanced]="showAdvanced && movieRequest" [type]="requestType" + [has4KRequest]="movie.has4KRequest" (openTrailer)="openDialog()" (onAdvancedOptions)="openAdvancedOptions()" - (onReProcessRequest)="reProcessRequest()" + (onReProcessRequest)="reProcessRequest(false)" + (onReProcess4KRequest)="reProcessRequest(true)" > @@ -54,6 +56,7 @@ + @@ -65,40 +68,85 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + - - + + +
+
+ {{'MediaDetails.Quality' | translate }}  + {{"4K" | quality}} +
+
{{'MediaDetails.RootFolderOverride' | translate }}
{{request.rootPathOverrideTitle}}
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts index 3132ac84f..caa799794 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts @@ -4,6 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { RequestService, MessageService } from "../../../../services"; import { TranslateService } from "@ngx-translate/core"; import { RequestType, IRequestEngineResult } from "../../../../interfaces"; +import { firstValueFrom } from "rxjs"; @Component({ selector: "deny-dialog", @@ -22,13 +23,13 @@ export class DenyDialogComponent { public async deny() { let result: IRequestEngineResult; if(this.data.requestType == RequestType.movie) { - result = await this.requestService.denyMovie({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyMovie({id: this.data.requestId, reason: this.denyReason, is4K: this.data.is4K })); } if(this.data.requestType == RequestType.tvShow) { - result = await this.requestService.denyChild({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyChild({id: this.data.requestId, reason: this.denyReason })); } if(this.data.requestType == RequestType.album) { - result = await this.requestService.denyAlbum({id: this.data.requestId, reason: this.denyReason }).toPromise(); + result = await firstValueFrom(this.requestService.denyAlbum({id: this.data.requestId, reason: this.denyReason })); } if (result.result) { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts index 4237386c4..215a82ace 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts @@ -4,6 +4,7 @@ export interface IDenyDialogData { requestType: RequestType; requestId: number; denied: boolean; + is4K: boolean; } export interface IIssueDialogData { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index f05792aa9..98bb999b2 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -35,9 +35,13 @@ {{ 'MediaDetails.RadarrConfiguration' | translate}} {{ 'MediaDetails.SonarrConfiguration' | translate}} - +
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts index bc504347b..9215c1464 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.ts @@ -23,10 +23,12 @@ export class SocialIconsComponent { @Input() isAdmin: boolean; @Input() canShowAdvanced: boolean; + @Input() has4KRequest: boolean; @Output() openTrailer: EventEmitter = new EventEmitter(); @Output() onAdvancedOptions: EventEmitter = new EventEmitter(); @Output() onReProcessRequest: EventEmitter = new EventEmitter(); + @Output() onReProcess4KRequest: EventEmitter = new EventEmitter(); public RequestType = RequestType; @@ -39,7 +41,11 @@ export class SocialIconsComponent { this.onAdvancedOptions.emit(); } - public reProcessRequest() { - this.onReProcessRequest.emit(); + public reProcessRequest(is4K: boolean) { + if (is4K) { + this.onReProcess4KRequest.emit(); + } else { + this.onReProcessRequest.emit(); + } } } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts index 10eee3989..2de85814c 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts @@ -100,7 +100,7 @@ export class TvRequestsPanelComponent { } public reProcessRequest(request: IChildRequests) { - this.requestService2.reprocessRequest(request.id, RequestType.tvShow).subscribe(result => { + this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(result => { if (result.result) { this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok"); } else { diff --git a/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts b/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts index 393e08640..c1f9a4211 100644 --- a/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts +++ b/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts @@ -6,6 +6,9 @@ export class QualityPipe implements PipeTransform { if (value.toUpperCase() === "4K" || value.toUpperCase() === "8K") { return value; } + if (value[value.length - 1].toUpperCase() === "P") { + return value; + } return value + "p"; } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts index d0529e018..a58d8cd9f 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts @@ -1,14 +1,14 @@ -import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef, OnInit } from "@angular/core"; -import { IRequestsViewModel, IAlbumRequest } from "../../../interfaces"; -import { MatPaginator } from "@angular/material/paginator"; -import { MatSort } from "@angular/material/sort"; -import { merge, Observable, of as observableOf } from 'rxjs'; +import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, OnInit, Output, ViewChild } from "@angular/core"; +import { IAlbumRequest, IRequestsViewModel } from "../../../interfaces"; +import { Observable, merge, of as observableOf } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; -import { RequestServiceV2 } from "../../../services/requestV2.service"; import { AuthService } from "../../../auth/auth.service"; -import { StorageService } from "../../../shared/storage/storage-service"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; import { RequestFilterType } from "../../models/RequestFilterType"; +import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { StorageService } from "../../../shared/storage/storage-service"; @Component({ templateUrl: "./albums-grid.component.html", @@ -130,7 +130,7 @@ export class AlbumsGridComponent implements OnInit, AfterViewInit { this.ref.detectChanges(); }; - const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin }; + const data = { request: request, filter: filter, onChange: onChange, manageOwnRequests: this.manageOwnRequests, isAdmin: this.isAdmin, has4kRequest: false }; this.onOpenOptions.emit(data); } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html index 61baa3eaa..d9366e7d1 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html @@ -58,7 +58,7 @@
{{ 'Requests.RequestDate' | translate}} {{element.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL'}} {{getRequestDate(element) | amLocal | amUserLocale | amDateFormat: 'LL'}} {{element.status |translateStatus }} {{ 'Requests.Has4KRequest' | translate}} + + + {{ 'Requests.RequestStatus' | translate}}
\"Poster\"
{posterContent}
+ + fservida +
+ Francesco Servida +
+
Patricol @@ -277,15 +284,15 @@ Here are some of the features Ombi has:
Aptalca
-
mhann
Mhann
-
ombi-bot @@ -320,15 +327,15 @@ Here are some of the features Ombi has:
D34DC3N73R
-
pooley182
David Pooley
-
Fredrik81 @@ -363,15 +370,15 @@ Here are some of the features Ombi has:
Marius Schiffer
-
Qstick
Qstick
-
Vbgf @@ -406,15 +413,15 @@ Here are some of the features Ombi has:
Alexander Standke
-
Alasano
Aljosa Asanovic
-
Ashyni @@ -449,15 +456,15 @@ Here are some of the features Ombi has:
Christopher Demicoli
-
Codehhh
Codehhh
-
danopia @@ -492,15 +499,15 @@ Here are some of the features Ombi has:
Eli
-
Fish2
Fish2
-
hariesramdhani @@ -535,15 +542,15 @@ Here are some of the features Ombi has:
Joe Groocock
-
errorhandler
Joe Harvey
-
jonbloom @@ -578,15 +585,15 @@ Here are some of the features Ombi has:
Lightkeeper
-
devbymadde
Madeleine Schönemann
-
mattmattmatt @@ -621,15 +628,15 @@ Here are some of the features Ombi has:
Qiming Chen
-
randallbruder
Randall Bruder
-
rob1998 @@ -664,15 +671,15 @@ Here are some of the features Ombi has:
Thomas Van Tilburg
-
Tim-Trott
Tim Trott
-
tombomb @@ -707,15 +714,15 @@ Here are some of the features Ombi has:
Tim OBrien
-
x-limitless-x
Blake Drumm
-
camjac251 @@ -750,15 +757,15 @@ Here are some of the features Ombi has:
Maartenheebink
-
masterhuck
Patrick Weber
-
sir-marv From 6571bb7b98dc87c212def1f5203f20c07b447861 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 2 Mar 2022 20:27:32 +0000 Subject: [PATCH 085/210] chore(release): :rocket: v4.14.0 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cd8b5767..b0d516980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# [4.14.0](https://github.com/Ombi-app/Ombi/compare/v4.13.2...v4.14.0) (2022-03-02) + + + ## [4.13.2](https://github.com/Ombi-app/Ombi/compare/v4.13.1...v4.13.2) (2022-03-01) @@ -345,12 +349,3 @@ -## [4.7.1](https://github.com/Ombi-app/Ombi/compare/v4.7.0...v4.7.1) (2021-11-22) - - -### Bug Fixes - -* **emby:** :bug: Fixed an issue where we slightly broke the full sync ([332d934](https://github.com/Ombi-app/Ombi/commit/332d9344d002a5ffd5aeac516c7441dcdec52248)) - - - diff --git a/version.json b/version.json index e0934d75f..bc032a60b 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.13.2" + "version": "4.14.0" } \ No newline at end of file From 356c7424e0ce8c1c5063b04bc6ed9b809f214d65 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 3 Mar 2022 12:41:26 +0000 Subject: [PATCH 086/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi.I18n/Resources/Texts.zh.resx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi.I18n/Resources/Texts.zh.resx b/src/Ombi.I18n/Resources/Texts.zh.resx index 08fb2ec4f..03f696076 100644 --- a/src/Ombi.I18n/Resources/Texts.zh.resx +++ b/src/Ombi.I18n/Resources/Texts.zh.resx @@ -145,12 +145,12 @@ 取消订阅 - Album + 专辑 - Movie + 电影 - TV Show + 电视节目 \ No newline at end of file From 27993f5a302c04f33594542a12c4483bbaa3f87c Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Thu, 3 Mar 2022 18:05:05 +0100 Subject: [PATCH 087/210] Fix Radarr settings no longer initialized in settings page --- .../settings/radarr/components/radarr-form.component.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts index f426f273b..e85bfc08b 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/radarr/components/radarr-form.component.ts @@ -39,6 +39,14 @@ export class RadarrFormComponent implements OnInit { { name: "In Cinemas", value: "InCinemas" }, { name: "Physical / Web", value: "Released" }, ]; + + if (this.form.controls.defaultQualityProfile.value) { + this.getProfiles(this.form); + } + + if (this.form.controls.defaultRootPath.value) { + this.getRootFolders(this.form); + } } public toggleValidators() { From cb8a0ff63267c67a31715764ae867f3b300ba730 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 3 Mar 2022 20:11:40 +0000 Subject: [PATCH 088/210] chore(release): :rocket: v4.14.1 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0d516980..38347117a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.14.1](https://github.com/Ombi-app/Ombi/compare/v4.14.0...v4.14.1) (2022-03-03) + + + # [4.14.0](https://github.com/Ombi-app/Ombi/compare/v4.13.2...v4.14.0) (2022-03-02) @@ -340,12 +344,3 @@ -## [4.7.2](https://github.com/Ombi-app/Ombi/compare/v4.7.1...v4.7.2) (2021-11-22) - - -### Bug Fixes - -* **request-list:** :bug: Fixed an issue where the bulk delete would not work for movie requests ([4b540fb](https://github.com/Ombi-app/Ombi/commit/4b540fb45bcc389664f0953159802288d005db9f)) - - - diff --git a/version.json b/version.json index bc032a60b..630c67f83 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.14.0" + "version": "4.14.1" } \ No newline at end of file From 60cfd41f68e9006555c1a419dcff1aaa24b3e09f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 5 Mar 2022 21:35:23 +0000 Subject: [PATCH 089/210] fix(Sonarr): :bug: Fixed an issue where some seasons were not being monitored correctly in sonarr #4506 --- .github/workflows/build.yml | 3 ++- src/Ombi.Core/Senders/TvSender.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6191c7a55..e72167806 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -190,7 +190,8 @@ jobs: if: contains(github.ref, 'develop') with: prerelease: true - body: ${{ needs.versioning.outputs.changelog }} + generate_release_notes: true + # body: ${{ needs.versioning.outputs.changelog }} name: ${{ needs.versioning.outputs.tag }} tag_name: ${{ needs.versioning.outputs.tag }} files: | diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 80fed6434..3676d05ee 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -357,6 +357,8 @@ namespace Ombi.Core.Senders episodesToUpdate.Add(sonarrEp); } } + + existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList(); var sonarrEpCount = sonarrEpisodeList.Count; var ourRequestCount = season.Episodes.Count; From 81ec65763143d58ca3924ab5f3d6d12e271f4ed7 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sat, 5 Mar 2022 21:39:16 +0000 Subject: [PATCH 090/210] chore(release): :rocket: v4.14.2 --- CHANGELOG.md | 13 +++++++++---- version.json | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38347117a..63a5afb26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.14.2](https://github.com/Ombi-app/Ombi/compare/v4.14.1...v4.14.2) (2022-03-05) + + +### Bug Fixes + +* **Sonarr:** :bug: Fixed an issue where some seasons were not being monitored correctly in sonarr ([60cfd41](https://github.com/Ombi-app/Ombi/commit/60cfd41f68e9006555c1a419dcff1aaa24b3e09f)), closes [#4506](https://github.com/Ombi-app/Ombi/issues/4506) + + + ## [4.14.1](https://github.com/Ombi-app/Ombi/compare/v4.14.0...v4.14.1) (2022-03-03) @@ -340,7 +349,3 @@ -## [4.7.3](https://github.com/Ombi-app/Ombi/compare/v4.7.2...v4.7.3) (2021-11-23) - - - diff --git a/version.json b/version.json index 630c67f83..8b6691b5a 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.14.1" + "version": "4.14.2" } \ No newline at end of file From f9ebc1cc2e13c7cd335121cd86295b10eda529ba Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 6 Mar 2022 20:44:18 +0000 Subject: [PATCH 091/210] fix(availability): :bug: Fixed an issue where with 4k content, we could repeat notifications --- .github/workflows/build.yml | 2 +- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 10 +++++++--- .../Jellyfin/JellyfinAvaliabilityChecker.cs | 10 +++++++--- .../Jobs/Plex/PlexAvailabilityChecker.cs | 19 +++++++++++++------ .../Jobs/Plex/PlexContentSync.cs | 10 +++++----- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e72167806..333ba2a71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -191,7 +191,7 @@ jobs: with: prerelease: true generate_release_notes: true - # body: ${{ needs.versioning.outputs.changelog }} + body: ${{ needs.versioning.outputs.changelog }} name: ${{ needs.versioning.outputs.tag }} tag_name: ${{ needs.versioning.outputs.tag }} files: | diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 1c4416e36..c62871265 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -76,19 +76,23 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogInformation("We have found the request {0} on Emby, sending the notification", movie?.Title ?? string.Empty); - if (has4kRequest && embyContent.Has4K) + var notify = false; + + if (has4kRequest && embyContent.Has4K && !movie.Available4K) { movie.Available4K = true; movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; } // If we have a non-4k versison then mark as available - if (embyContent.Quality.HasValue()) + if (embyContent.Quality.HasValue() && !movie.Available) { movie.Available = true; movie.MarkedAsAvailable = DateTime.Now; + notify = true; } - if (movie.Available) + if (notify) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index dd183e537..3b4da800b 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -103,20 +103,24 @@ namespace Ombi.Schedule.Jobs.Jellyfin _log.LogInformation("We have found the request {0} on Jellyfin, sending the notification", movie?.Title ?? string.Empty); - if (has4kRequest && jellyfinContent.Has4K) + var notify = false; + + if (has4kRequest && jellyfinContent.Has4K && !movie.Available4K) { movie.Available4K = true; movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; } // If we have a non-4k versison then mark as available - if (jellyfinContent.Quality.HasValue()) + if (jellyfinContent.Quality.HasValue() && !movie.Available) { movie.Available = true; movie.MarkedAsAvailable = DateTime.Now; + notify = true; } - if (movie.Available) + if (notify) { var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index d8dc273d2..4eb83105d 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -206,28 +206,35 @@ namespace Ombi.Schedule.Jobs.Plex _log.LogInformation($"[PAC] - Movie request {movie.Title} - {movie.Id} is now available, sending notification"); - if (has4kRequest && item.Has4K) + var notify = false; + + if (has4kRequest && item.Has4K && !movie.Available4K) { movie.Available4K = true; movie.Approved4K = true; movie.MarkedAsAvailable4K = DateTime.Now; await _movieRepo.SaveChangesAsync(); + notify = true; } // If we have a non-4k versison then mark as available - if (item.Quality.HasValue()) + if (item.Quality.HasValue() && !movie.Available) { movie.Available = true; movie.Approved = true; movie.MarkedAsAvailable = DateTime.Now; await _movieRepo.SaveChangesAsync(); + notify = true; } - itemsForAvailbility.Add(new AvailabilityModel + if (notify) { - Id = movie.Id, - RequestedUser = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty - }); + itemsForAvailbility.Add(new AvailabilityModel + { + Id = movie.Id, + RequestedUser = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty + }); + } } foreach (var i in itemsForAvailbility.DistinctBy(x => x.Id)) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 71bc5dcf4..2cfc02d90 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -340,11 +340,11 @@ namespace Ombi.Schedule.Jobs.Plex continue; } - var hasSameKey = await Repo.GetByKey(movie.ratingKey); - if (hasSameKey != null) - { - await Repo.Delete(hasSameKey); - } + //var hasSameKey = await Repo.GetByKey(movie.ratingKey); + //if (hasSameKey != null) + //{ + // await Repo.Delete(hasSameKey); + //} Logger.LogDebug("Adding movie {0}", movie.title); var guids = new List(); From eb36e47a934c45e79f3482832afa951207463e67 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Sun, 6 Mar 2022 20:47:54 +0000 Subject: [PATCH 092/210] chore(release): :rocket: v4.14.3 --- CHANGELOG.md | 19 +++++++++---------- version.json | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a5afb26..56105b570 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.14.3](https://github.com/Ombi-app/Ombi/compare/v4.14.2...v4.14.3) (2022-03-06) + + +### Bug Fixes + +* **availability:** :bug: Fixed an issue where with 4k content, we could repeat notifications ([f9ebc1c](https://github.com/Ombi-app/Ombi/commit/f9ebc1cc2e13c7cd335121cd86295b10eda529ba)) + + + ## [4.14.2](https://github.com/Ombi-app/Ombi/compare/v4.14.1...v4.14.2) (2022-03-05) @@ -339,13 +348,3 @@ -## [4.7.4](https://github.com/Ombi-app/Ombi/compare/v4.7.3...v4.7.4) (2021-11-25) - - -### Bug Fixes - -* **availability-rules:** :bug: Fixed a small issue where some shows would not appear as Available even know they had no future unaired episodes listed ([914b096](https://github.com/Ombi-app/Ombi/commit/914b096781c9b73292a533a010a5dd05ecfd0aac)) -* **emby:** :bug: Fixed an issue where we were not properly syncing episodes ([75529dd](https://github.com/Ombi-app/Ombi/commit/75529dd972c5102f3c5234a2acf6fe664a1bcfad)) - - - diff --git a/version.json b/version.json index 8b6691b5a..e6251a0f6 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.14.2" + "version": "4.14.3" } \ No newline at end of file From cdeb51515107ed3a70e28242d0ac795d8564f695 Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Tue, 8 Mar 2022 14:42:45 +0100 Subject: [PATCH 093/210] Localize genres filter --- src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs | 5 +++++ src/Ombi.Core/Engine/V2/MultiSearchEngine.cs | 10 ++++++++++ src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 2 +- src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 3 ++- .../services/applications/themoviedb.service.ts | 4 ---- .../ClientApp/src/app/services/searchV2.service.ts | 7 ++++++- .../settings/themoviedb/themoviedb.component.ts | 7 ++++--- .../genre-select/genre-select.component.ts | 6 +++--- .../V1/External/TheMovieDbController.cs | 8 -------- src/Ombi/Controllers/V2/SearchController.cs | 14 ++++++++++++++ 10 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs index 1b78eaea5..7ad8c509a 100644 --- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs @@ -4,10 +4,15 @@ using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search.V2; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Core.Engine.V2 { public interface IMultiSearchEngine { Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken); + Task> GetGenres(string media, CancellationToken requestAborted); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index fc2595676..44f792415 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -17,6 +17,10 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Repository; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Core.Engine.V2 { public class MultiSearchEngine : BaseMediaEngine, IMultiSearchEngine @@ -113,5 +117,11 @@ namespace Ombi.Core.Engine.V2 return model; } + + public async Task> GetGenres(string media, CancellationToken cancellationToken) + { + var lang = await DefaultLanguageCode(null); + return await _movieDbApi.GetGenres(media, cancellationToken, lang); + } } } diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index eadfb3a3a..dc2e5525c 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -40,7 +40,7 @@ namespace Ombi.Api.TheMovieDb Task GetKeyword(int keywordId); Task GetMovieWatchProviders(int theMoviedbId, CancellationToken token); Task GetTvWatchProviders(int theMoviedbId, CancellationToken token); - Task> GetGenres(string media, CancellationToken cancellationToken); + Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode); Task> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken); Task> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken); } diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 0391c184a..335ea7da3 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -427,10 +427,11 @@ namespace Ombi.Api.TheMovieDb return keyword == null || keyword.Id == 0 ? null : keyword; } - public async Task> GetGenres(string media, CancellationToken cancellationToken) + public async Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode) { var request = new Request($"genre/{media}/list", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", languageCode); AddRetry(request); var result = await Api.Request>(request, cancellationToken); diff --git a/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts b/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts index a49fb4146..d2c5b6122 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/themoviedb.service.ts @@ -25,10 +25,6 @@ export class TheMovieDbService extends ServiceHelpers { .pipe(catchError((error: HttpErrorResponse) => error.status === 404 ? empty() : throwError(error))); } - public getGenres(media: string): Observable { - return this.http.get(`${this.url}/Genres/${media}`, { headers: this.headers }) - } - public getWatchProviders(media: string): Observable { return this.http.get(`${this.url}/WatchProviders/${media}`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index 9e065ea97..c80655370 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IDiscoverModel, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; +import { IDiscoverModel, IMovieDbKeyword, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; @@ -23,6 +23,11 @@ export class SearchV2Service extends ServiceHelpers { public multiSearch(searchTerm: string, filter: SearchFilter): Observable { return this.http.post(`${this.url}/multi/${encodeURIComponent(searchTerm)}`, filter); } + + public getGenres(media: string): Observable { + return this.http.get(`${this.url}/Genres/${media}`, { headers: this.headers }) + } + public getFullMovieDetails(theMovieDbId: number): Observable { return this.http.get(`${this.url}/Movie/${theMovieDbId}`); } diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 427905902..512f60363 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -5,7 +5,7 @@ import { IMovieDbKeyword, ITheMovieDbSettings } from "../../interfaces"; import { debounceTime, switchMap } from "rxjs/operators"; import { MatAutocomplete } from "@angular/material/autocomplete"; -import { NotificationService } from "../../services"; +import { NotificationService, SearchV2Service } from "../../services"; import { SettingsService } from "../../services"; import { TheMovieDbService } from "../../services"; @@ -33,6 +33,7 @@ export class TheMovieDbComponent implements OnInit { constructor(private settingsService: SettingsService, private notificationService: NotificationService, private tmdbService: TheMovieDbService, + private searchService: SearchV2Service, private fb: FormBuilder) { } public ngOnInit() { @@ -71,7 +72,7 @@ export class TheMovieDbComponent implements OnInit { })) : []; - this.tmdbService.getGenres("movie").subscribe(results => { + this.searchService.getGenres("movie").subscribe(results => { this.filteredMovieGenres = results; this.excludedMovieGenres.forEach(genre => { @@ -92,7 +93,7 @@ export class TheMovieDbComponent implements OnInit { })) : []; - this.tmdbService.getGenres("tv").subscribe(results => { + this.searchService.getGenres("tv").subscribe(results => { this.filteredTvGenres = results; this.excludedTvGenres.forEach(genre => { diff --git a/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts b/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts index 06c92e4cf..839b8169c 100644 --- a/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts +++ b/src/Ombi/ClientApp/src/app/shared/components/genre-select/genre-select.component.ts @@ -5,7 +5,7 @@ import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from "r import { IMovieDbKeyword } from "../../../interfaces"; import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete"; import { Observable } from "rxjs"; -import { TheMovieDbService } from "../../../services"; +import { SearchV2Service } from "../../../services"; @Component({ selector: "genre-select", @@ -13,7 +13,7 @@ import { TheMovieDbService } from "../../../services"; }) export class GenreSelectComponent { constructor( - private tmdbService: TheMovieDbService + private searchService: SearchV2Service ) {} @Input() public form: FormGroup; @@ -21,7 +21,7 @@ export class GenreSelectComponent { private _mediaType: string; @Input() set mediaType(type: string) { this._mediaType = type; - this.tmdbService.getGenres(this._mediaType).subscribe((res) => { + this.searchService.getGenres(this._mediaType).subscribe((res) => { this.genres = res; this.filteredKeywords = this.control.valueChanges.pipe( startWith(''), diff --git a/src/Ombi/Controllers/V1/External/TheMovieDbController.cs b/src/Ombi/Controllers/V1/External/TheMovieDbController.cs index f5fdb996f..4017c0b42 100644 --- a/src/Ombi/Controllers/V1/External/TheMovieDbController.cs +++ b/src/Ombi/Controllers/V1/External/TheMovieDbController.cs @@ -39,14 +39,6 @@ namespace Ombi.Controllers.External return keyword == null ? NotFound() : Ok(keyword); } - /// - /// Gets the genres for either Tv or Movies depending on media type - /// - /// Either `tv` or `movie`. - [HttpGet("Genres/{media}")] - public async Task> GetGenres(string media) => - await TmdbApi.GetGenres(media, HttpContext.RequestAborted); - /// /// Searches for the watch providers matching the specified term. /// diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index ac5905c33..fc970b793 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -16,6 +16,10 @@ using Ombi.Api.RottenTomatoes.Models; using Ombi.Api.RottenTomatoes; using Ombi.Helpers; +// Due to conflicting Genre models in +// Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models +using Genre = Ombi.TheMovieDbApi.Models.Genre; + namespace Ombi.Controllers.V2 { public class SearchController : V2Controller @@ -55,6 +59,16 @@ namespace Ombi.Controllers.V2 return await _multiSearchEngine.MultiSearch(Uri.UnescapeDataString(searchTerm), filter, Request.HttpContext.RequestAborted); } + /// + /// Gets the genres for either Tv or Movies depending on media type + /// + /// Either `tv` or `movie`. + [HttpGet("Genres/{media}")] + public Task> GetGenres(string media) + { + return _multiSearchEngine.GetGenres(media, HttpContext.RequestAborted); + } + /// /// Returns details for a single movie /// From a8ba2f3544a1c01c57f217c4036a277ab0e67a09 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 10 Mar 2022 11:55:11 +0000 Subject: [PATCH 094/210] fix: :bug: Fixed the Request On Behalf autocomplete not filtering correctly #4539 --- .../admin-request-dialog.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts b/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts index acf6560b9..d495a88e7 100644 --- a/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/shared/admin-request-dialog/admin-request-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject, OnInit } from "@angular/core"; import { FormBuilder, FormGroup } from "@angular/forms"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; -import { Observable } from "rxjs"; +import { firstValueFrom, Observable } from "rxjs"; import { startWith, map } from "rxjs/operators"; import { ILanguageProfiles, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, ISonarrSettings, IUserDropdown, RequestType } from "../../interfaces"; import { IdentityService, MessageService, RadarrService, RequestService, SettingsService, SonarrService } from "../../services"; @@ -55,7 +55,7 @@ export class AdminRequestDialogComponent implements OnInit { radarrFolderId: [null] }) - this.options = await this.identityService.getUsersDropdown().toPromise(); + this.options = await firstValueFrom(this.identityService.getUsersDropdown()); this.filteredOptions = this.form.controls['username'].valueChanges.pipe( startWith(""), @@ -96,7 +96,10 @@ export class AdminRequestDialogComponent implements OnInit { public displayFn(user: IUserDropdown): string { const username = user?.username ? user.username : ""; const email = user?.email ? `(${user.email})` : ""; - return `${username} ${email}`; + if (username && email) { + return `${username} ${email}`; + } + return ''; } private _filter(value: string | IUserDropdown): IUserDropdown[] { From 8dfa858eed7e0bf0712d0e67ce9376ef11057649 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 10 Mar 2022 11:58:48 +0000 Subject: [PATCH 095/210] chore(release): :rocket: v4.14.4 --- CHANGELOG.md | 24 +++++++++++++----------- version.json | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56105b570..8ac3ea353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [4.14.4](https://github.com/Ombi-app/Ombi/compare/v4.14.3...v4.14.4) (2022-03-10) + + +### Bug Fixes + +* :bug: Fixed the Request On Behalf autocomplete not filtering correctly ([a8ba2f3](https://github.com/Ombi-app/Ombi/commit/a8ba2f3544a1c01c57f217c4036a277ab0e67a09)), closes [#4539](https://github.com/Ombi-app/Ombi/issues/4539) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([356c742](https://github.com/Ombi-app/Ombi/commit/356c7424e0ce8c1c5063b04bc6ed9b809f214d65)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([6fcaecf](https://github.com/Ombi-app/Ombi/commit/6fcaecf80b766f2d43ac7082d74364238e1638b7)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([132f4d4](https://github.com/Ombi-app/Ombi/commit/132f4d4e609b7fb7e37f38ee2f395926e2911abe)) +* **translations:** 🌐 New translations from Crowdin [skip ci] ([f292006](https://github.com/Ombi-app/Ombi/commit/f292006a08894a8d0ba899c8c6e9fe863e558dda)) + + + ## [4.14.3](https://github.com/Ombi-app/Ombi/compare/v4.14.2...v4.14.3) (2022-03-06) @@ -337,14 +350,3 @@ -## [4.7.5](https://github.com/Ombi-app/Ombi/compare/v4.7.4...v4.7.5) (2021-11-28) - - -### Bug Fixes - -* **notifications:** fixed an error that could happen when Ombi sends out a issue notification ([7442dcf](https://github.com/Ombi-app/Ombi/commit/7442dcf59da5d2190cc3087b10402e85bcfcf83b)) -* **translations:** 🌐 Fix incorrect text translation reference RequestedByOn ([#4420](https://github.com/Ombi-app/Ombi/issues/4420)) ([202d155](https://github.com/Ombi-app/Ombi/commit/202d155493c29a6ddd4c5507186bf376a28f4c1d)) -* **translations:** 🌐 New translations from Crowdin ([473c172](https://github.com/Ombi-app/Ombi/commit/473c1724922515fe376e0b2058ac391807c923f2)) - - - diff --git a/version.json b/version.json index e6251a0f6..1b6ee2826 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.14.3" + "version": "4.14.4" } \ No newline at end of file From 18b167d16a3d682b5060ee36dedbbb069bef09de Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 10 Mar 2022 15:52:10 +0000 Subject: [PATCH 096/210] fix(jellyfin): :bug: Fixed an issue where Jellyfin content was showing the Play on Emby button #4542 --- src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs | 4 ++-- .../Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs index f10ac4bdd..514731740 100644 --- a/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/JellyfinAvailabilityRule.cs @@ -92,14 +92,14 @@ namespace Ombi.Core.Rule.Rules.Search else { obj.Available = true; - obj.EmbyUrl = item.Url; + obj.JellyfinUrl = item.Url; obj.Quality = item.Quality; } if (item.Quality.HasValue()) { obj.Available = true; - obj.EmbyUrl = item.Url; + obj.JellyfinUrl = item.Url; obj.Quality = item.Quality; } } diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 3b4da800b..5c73c66b8 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -33,11 +33,9 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; -using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; -using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; From a2be81d634751302ff7b5096268b1f93b4fa856f Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 17 Mar 2022 20:48:45 +0000 Subject: [PATCH 097/210] chore(release): :rocket: v4.15.0 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac3ea353..ab62fce06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [4.15.0](https://github.com/Ombi-app/Ombi/compare/v4.14.4...v4.15.0) (2022-03-17) + + +### Bug Fixes + +* **jellyfin:** :bug: Fixed an issue where Jellyfin content was showing the Play on Emby button ([18b167d](https://github.com/Ombi-app/Ombi/commit/18b167d16a3d682b5060ee36dedbbb069bef09de)), closes [#4542](https://github.com/Ombi-app/Ombi/issues/4542) + + + ## [4.14.4](https://github.com/Ombi-app/Ombi/compare/v4.14.3...v4.14.4) (2022-03-10) @@ -341,12 +350,3 @@ -## [4.7.6](https://github.com/Ombi-app/Ombi/compare/v4.7.5...v4.7.6) (2021-12-02) - - -### Bug Fixes - -* **user-management:** :bug: Fixed an issue where you couldn't 'unset' a users custom quality and root folders ([bae96af](https://github.com/Ombi-app/Ombi/commit/bae96af17f50a80ae3ade235a5ef68d5d2dc12ba)) - - - diff --git a/version.json b/version.json index 1b6ee2826..3429c29ca 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.14.4" + "version": "4.15.0" } \ No newline at end of file From 21a794cbc0a5fa735ca0347c8f7f1ac04a487fbc Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Mar 2022 16:59:09 +0000 Subject: [PATCH 098/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi.I18n/Resources/Texts.fr.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.I18n/Resources/Texts.fr.resx b/src/Ombi.I18n/Resources/Texts.fr.resx index 2b4cdffae..9b9d96e48 100644 --- a/src/Ombi.I18n/Resources/Texts.fr.resx +++ b/src/Ombi.I18n/Resources/Texts.fr.resx @@ -121,7 +121,7 @@ Nouveaux Albums - Nouveaux Films + Nouveaux films Nouvelles séries From 9cdd6f41cdab8825a984905c089611409c53c753 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 18 Mar 2022 21:12:12 +0000 Subject: [PATCH 099/210] fix(mediaserver): fixed an issue where we were not detecting available content correctly #4542 --- src/Ombi.Api.TvMaze/ITvMazeApi.cs | 2 -- src/Ombi.Api.TvMaze/TvMazeApi.cs | 22 ------------------- src/Ombi.Core/Engine/MovieSearchEngine.cs | 12 +++++----- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 2 +- .../Jellyfin/JellyfinAvaliabilityChecker.cs | 2 +- .../Jobs/Ombi/RefreshMetadata.cs | 11 ++++++---- .../Jobs/Plex/PlexAvailabilityChecker.cs | 2 +- .../Jobs/Plex/PlexContentSync.cs | 2 +- 8 files changed, 17 insertions(+), 38 deletions(-) diff --git a/src/Ombi.Api.TvMaze/ITvMazeApi.cs b/src/Ombi.Api.TvMaze/ITvMazeApi.cs index 819051d83..983858810 100644 --- a/src/Ombi.Api.TvMaze/ITvMazeApi.cs +++ b/src/Ombi.Api.TvMaze/ITvMazeApi.cs @@ -8,10 +8,8 @@ namespace Ombi.Api.TvMaze public interface ITvMazeApi { Task> EpisodeLookup(int showId); - Task> GetSeasons(int id); Task> Search(string searchTerm); Task ShowLookup(int showId); Task ShowLookupByTheTvDbId(int theTvDbId); - Task GetTvFullInformation(int id); } } \ No newline at end of file diff --git a/src/Ombi.Api.TvMaze/TvMazeApi.cs b/src/Ombi.Api.TvMaze/TvMazeApi.cs index 5d761da47..3f37d7488 100644 --- a/src/Ombi.Api.TvMaze/TvMazeApi.cs +++ b/src/Ombi.Api.TvMaze/TvMazeApi.cs @@ -64,27 +64,5 @@ namespace Ombi.Api.TvMaze return null; } } - - public async Task> GetSeasons(int id) - { - var request = new Request($"shows/{id}/seasons", Uri, HttpMethod.Get); - - request.AddContentHeader("Content-Type", "application/json"); - - return await Api.Request>(request); - } - - public async Task GetTvFullInformation(int id) - { - var request = new Request($"shows/{id}", Uri, HttpMethod.Get); - - request.AddQueryString("embed[]", "cast"); - request.AddQueryString("embed[]", "crew"); - request.AddQueryString("embed[]", "episodes"); - - request.AddContentHeader("Content-Type", "application/json"); - - return await Api.Request(request); - } } } diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index d911c1cf5..7d84a0b40 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -46,7 +46,7 @@ namespace Ombi.Core.Engine { langCode = await DefaultLanguageCode(langCode); var movieInfo = await Cache.GetOrAddAsync(nameof(LookupImdbInformation) + langCode + theMovieDbId, - () => MovieApi.GetMovieInformationWithExtraInfo(theMovieDbId, langCode), + () => MovieApi.GetMovieInformationWithExtraInfo(theMovieDbId, langCode), DateTimeOffset.Now.AddHours(12)); var viewMovie = Mapper.Map(movieInfo); @@ -81,11 +81,11 @@ namespace Ombi.Core.Engine { return resultSet; } - + // Get this person movie credits var credits = await MovieApi.GetActorMovieCredits(person.id, langaugeCode); // Grab results from both cast and crew, prefer items in cast. we can handle directors like this. - var movieResults = (from role in credits.cast select new { Id = role.id, Title = role.title, ReleaseDate = role.release_date }).ToList(); + var movieResults = (from role in credits.cast select new { Id = role.id, Title = role.title, ReleaseDate = role.release_date }).ToList(); movieResults.AddRange((from job in credits.crew select new { Id = job.id, Title = job.title, ReleaseDate = job.release_date }).ToList()); movieResults = movieResults.Take(10).ToList(); @@ -120,7 +120,7 @@ namespace Ombi.Core.Engine /// public async Task> PopularMovies() { - + var result = await Cache.GetOrAddAsync(CacheKeys.PopularMovies, async () => { var langCode = await DefaultLanguageCode(null); @@ -201,7 +201,7 @@ namespace Ombi.Core.Engine protected async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) { - if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty()) + if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty() && viewMovie.Id > 0) { var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); viewMovie.Id = showInfo.Id; // TheMovieDbId @@ -217,7 +217,7 @@ namespace Ombi.Core.Engine // This requires the rules to be run first to populate the RequestId property await CheckForSubscription(viewMovie); - + return viewMovie; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index c62871265..9d88c5907 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -86,7 +86,7 @@ namespace Ombi.Schedule.Jobs.Emby } // If we have a non-4k versison then mark as available - if (embyContent.Quality.HasValue() && !movie.Available) + if (embyContent.Quality != null && !movie.Available) { movie.Available = true; movie.MarkedAsAvailable = DateTime.Now; diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 5c73c66b8..b1dafa71f 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -111,7 +111,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin } // If we have a non-4k versison then mark as available - if (jellyfinContent.Quality.HasValue() && !movie.Available) + if (jellyfinContent.Quality != null && !movie.Available) { movie.Available = true; movie.MarkedAsAvailable = DateTime.Now; diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 2421d5af0..1f5abb5e4 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -447,17 +447,20 @@ namespace Ombi.Schedule.Jobs.Ombi default: break; } - + } } if (hasTvDbId && type == RequestType.TvShow) { _log.LogInformation("The show {0} has tvdbid but not ImdbId, searching for ImdbId", title); - if (int.TryParse(tvDbId, out var id)) + + var result = await _movieApi.Find(tvDbId.ToString(), ExternalSource.tvdb_id); + var movieDbId = result.tv_results.FirstOrDefault()?.id ?? 0; + if (movieDbId != 0) { - var result = await _tvApi.ShowLookupByTheTvDbId(id); - return result?.externals?.imdb; + var externalsResult = await _movieApi.GetTvExternals(movieDbId); + return externalsResult.imdb_id; } } return string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 4eb83105d..6d082195e 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -218,7 +218,7 @@ namespace Ombi.Schedule.Jobs.Plex } // If we have a non-4k versison then mark as available - if (item.Quality.HasValue() && !movie.Available) + if (item.Quality != null && !movie.Available) { movie.Available = true; movie.Approved = true; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 2cfc02d90..823766bd2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -381,7 +381,7 @@ namespace Ombi.Schedule.Jobs.Plex var qualities = movie.Media?.Select(x => x.videoResolution); var is4k = qualities != null && qualities.Any(x => x.Equals("4k", StringComparison.InvariantCultureIgnoreCase)); - var selectedQuality = is4k ? string.Empty : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; + var selectedQuality = is4k ? null : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; var item = new PlexServerContent { From 051be3e8675e768e144f1d3aa5bba614facb2da0 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 18 Mar 2022 21:15:41 +0000 Subject: [PATCH 100/210] chore(release): :rocket: v4.15.1 --- CHANGELOG.md | 19 +++++++++---------- version.json | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab62fce06..2d5f4519d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.15.1](https://github.com/Ombi-app/Ombi/compare/v4.15.0...v4.15.1) (2022-03-18) + + +### Bug Fixes + +* **mediaserver:** fixed an issue where we were not detecting available content correctly [#4542](https://github.com/Ombi-app/Ombi/issues/4542) ([9cdd6f4](https://github.com/Ombi-app/Ombi/commit/9cdd6f41cdab8825a984905c089611409c53c753)) + + + # [4.15.0](https://github.com/Ombi-app/Ombi/compare/v4.14.4...v4.15.0) (2022-03-17) @@ -340,13 +349,3 @@ -## [4.7.7](https://github.com/Ombi-app/Ombi/compare/v4.7.6...v4.7.7) (2021-12-08) - - -### Bug Fixes - -* **notifications:** 🐛 Do not notify user upon auto approval of a TV show ([#4432](https://github.com/Ombi-app/Ombi/issues/4432)) ([3ad3bdd](https://github.com/Ombi-app/Ombi/commit/3ad3bddd8313d607ee2a39a51a92e61a3673082c)), closes [#4431](https://github.com/Ombi-app/Ombi/issues/4431) -* **translations:** 🌐 New translations from Crowdin ([8943a97](https://github.com/Ombi-app/Ombi/commit/8943a978bf459eaeb496d50c61c4d1506c727366)) - - - diff --git a/version.json b/version.json index 3429c29ca..4bca0b192 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.0" + "version": "4.15.1" } \ No newline at end of file From 83d1a15cc9d0ee91be73bd91c4672cf1bcf2728a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Mar 2022 11:01:48 +0000 Subject: [PATCH 101/210] fix(metadata): improved the metadata job to also lookup the media in Plex to see if it has any more uptodate metadata --- src/Ombi.Helpers/PlexHelper.cs | 2 + .../Jobs/Ombi/RefreshMetadata.cs | 68 ++++++++++++++++--- .../Jobs/Plex/PlexContentSync.cs | 6 ++ 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index 6827d0f74..7951a7edf 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -180,6 +180,8 @@ namespace Ombi.Helpers public string ImdbId { get; set; } public bool Plex { get; set; } + public bool Any() => TheTvDb.HasValue() || TheMovieDb.HasValue() || ImdbId.HasValue(); + public ProviderType Type { get diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 1f5abb5e4..64abb2aac 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Api.Jellyfin; +using Ombi.Api.Plex; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze; @@ -30,7 +31,8 @@ namespace Ombi.Schedule.Jobs.Ombi IMovieDbApi movieApi, ISettingsService embySettings, IEmbyApiFactory embyApi, ISettingsService jellyfinSettings, IJellyfinApiFactory jellyfinApi, - IHubContext notification, IMediaCacheService mediaCacheService) + IHubContext notification, IMediaCacheService mediaCacheService, + IPlexApi plexApi) { _plexRepo = plexRepo; _embyRepo = embyRepo; @@ -45,6 +47,7 @@ namespace Ombi.Schedule.Jobs.Ombi _jellyfinApiFactory = jellyfinApi; _notification = notification; _mediaCacheService = mediaCacheService; + _plexApi = plexApi; } private readonly IPlexContentRepository _plexRepo; @@ -60,6 +63,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly IJellyfinApiFactory _jellyfinApiFactory; private readonly IHubContext _notification; private readonly IMediaCacheService _mediaCacheService; + private readonly IPlexApi _plexApi; private IEmbyApi EmbyApi { get; set; } private IJellyfinApi JellyfinApi { get; set; } @@ -75,7 +79,7 @@ namespace Ombi.Schedule.Jobs.Ombi var settings = await _plexSettings.GetSettingsAsync(); if (settings.Enable) { - await StartPlex(); + await StartPlex(settings); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } @@ -112,12 +116,12 @@ namespace Ombi.Schedule.Jobs.Ombi .SendAsync(NotificationHub.NotificationEvent, "Metadata Refresh Finished"); } - private async Task StartPlex() + private async Task StartPlex(PlexSettings settings) { // Ensure we check that we have not linked this item to a request var allMovies = await _plexRepo.GetAll().Where(x => - x.Type == MediaType.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); - await StartPlexMovies(allMovies); + x.Type == MediaType.Movie && x.RequestId == null && ((x.TheMovieDbId == null || x.TheMovieDbId == string.Empty ) || (x.ImdbId == null || x.ImdbId == string.Empty))).ToListAsync(); + await StartPlexMovies(allMovies, settings); // Now Tv var allTv = await _plexRepo.GetAll().Where(x => @@ -245,7 +249,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task StartPlexMovies(List allMovies) + private async Task StartPlexMovies(List allMovies, PlexSettings settings) { foreach (var movie in allMovies) { @@ -261,14 +265,58 @@ namespace Ombi.Schedule.Jobs.Ombi if (!hasImdb) { var imdbId = await GetImdbId(hasTheMovieDb, false, movie.Title, movie.TheMovieDbId, string.Empty, RequestType.Movie); - movie.ImdbId = imdbId; - _plexRepo.UpdateWithoutSave(movie); + if (imdbId.HasValue()) + { + movie.ImdbId = imdbId; + hasImdb = true; + _plexRepo.UpdateWithoutSave(movie); + } } if (!hasTheMovieDb) { var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); - movie.TheMovieDbId = id; - _plexRepo.UpdateWithoutSave(movie); + if (id.HasValue()) + { + movie.TheMovieDbId = id; + hasTheMovieDb = true; + _plexRepo.UpdateWithoutSave(movie); + } + } + if (!hasTheMovieDb || !hasImdb) + { + // Check to see if the Plex item has anything + if (!settings.Servers.Any()) + { + continue; + } + var servers = settings.Servers[0]; + var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key); + var guids = new List(); + + var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); + guids.Add(meta.guid); + if (meta.Guid != null) + { + foreach (var g in meta.Guid) + { + guids.Add(g.Id); + } + } + + var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + if (providerIds.Any()) + { + if (providerIds.TheMovieDb.HasValue() && !hasTheMovieDb) + { + movie.TheMovieDbId = providerIds.TheMovieDb; + _plexRepo.UpdateWithoutSave(movie); + } + if (providerIds.ImdbId.HasValue() && !hasImdb) + { + movie.ImdbId = providerIds.ImdbId; + _plexRepo.UpdateWithoutSave(movie); + } + } } await _plexRepo.SaveChangesAsync(); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 823766bd2..62d0fb1b9 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -379,6 +379,12 @@ namespace Ombi.Schedule.Jobs.Plex } var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + if (!providerIds.Any()) + { + Logger.LogWarning($"Movie {movie.title} has no External Ids in Plex (ImdbId, TheMovieDbId). Skipping."); + continue; + } + var qualities = movie.Media?.Select(x => x.videoResolution); var is4k = qualities != null && qualities.Any(x => x.Equals("4k", StringComparison.InvariantCultureIgnoreCase)); var selectedQuality = is4k ? null : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; From 421754a0ae36dec35fbcc771cdd32d4023cc0311 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 23 Mar 2022 11:05:27 +0000 Subject: [PATCH 102/210] chore(release): :rocket: v4.15.2 --- CHANGELOG.md | 20 +++++++++----------- version.json | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d5f4519d..6018a3c14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.15.2](https://github.com/Ombi-app/Ombi/compare/v4.15.1...v4.15.2) (2022-03-23) + + +### Bug Fixes + +* **metadata:** improved the metadata job to also lookup the media in Plex to see if it has any more uptodate metadata ([83d1a15](https://github.com/Ombi-app/Ombi/commit/83d1a15cc9d0ee91be73bd91c4672cf1bcf2728a)) + + + ## [4.15.1](https://github.com/Ombi-app/Ombi/compare/v4.15.0...v4.15.1) (2022-03-18) @@ -338,14 +347,3 @@ -## [4.7.8](https://github.com/Ombi-app/Ombi/compare/v4.7.7...v4.7.8) (2021-12-11) - - -### Bug Fixes - -* **notifications:** :bug: Fixed the DenyReason sometimes not appearing in the notification message [#4409](https://github.com/Ombi-app/Ombi/issues/4409) ([209e311](https://github.com/Ombi-app/Ombi/commit/209e31175c95f6ee8909d878d45bf8269a9842d9)) -* **oauth:** :lock: Fixed the issue where some users running their browsers in a different language could not open the Plex OAuth window ([d5404ea](https://github.com/Ombi-app/Ombi/commit/d5404eaad7837010d6e4563cd8f7a1009231d362)), closes [#4408](https://github.com/Ombi-app/Ombi/issues/4408) -* **translations:** 🌐 New translations from Crowdin ([5cfb76c](https://github.com/Ombi-app/Ombi/commit/5cfb76cad7a25eed8b452bf9c01cef8c32804369)) - - - diff --git a/version.json b/version.json index 4bca0b192..6ee442cb4 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.1" + "version": "4.15.2" } \ No newline at end of file From 55c2e77a303790866dffe4373b96135b97dbc1c1 Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Thu, 24 Mar 2022 08:42:47 +0100 Subject: [PATCH 103/210] Display blank status for episodes not requested Fixes Non requested series have a Pending Approval status #4553 --- src/Ombi.Store/Entities/Requests/SeasonRequests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs index 0d8d587a5..da224681e 100644 --- a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs +++ b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs @@ -58,7 +58,7 @@ namespace Ombi.Store.Repository.Requests return "Common.ProcessingRequest"; } - if (!Approved && !Available) + if (Requested && !Approved && !Available) { return "Common.PendingApproval"; } From 73d438fcdb72acc219dceac15c31bb2245352dec Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Thu, 24 Mar 2022 08:56:36 +0100 Subject: [PATCH 104/210] Fix issues being merged for items bearing the same name Fixes #4540 --- src/Ombi.Core/Engine/V2/IssuesEngine.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs index 830dd4295..177ba599e 100644 --- a/src/Ombi.Core/Engine/V2/IssuesEngine.cs +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -33,7 +33,7 @@ namespace Ombi.Core.Engine.V2 public async Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token) { var issues = await _issues.GetAll().Where(x => x.Status == status && x.ProviderId != null).Skip(position).Take(take).OrderBy(x => x.Title).ToListAsync(token); - var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g }); + var grouped = issues.GroupBy(x => new { x.Title, x.ProviderId }, (key, g) => new { key = key, Issues = g }); var model = new List(); @@ -42,8 +42,8 @@ namespace Ombi.Core.Engine.V2 model.Add(new IssuesSummaryModel { Count = group.Issues.Count(), - Title = group.Title, - ProviderId = group.Issues.FirstOrDefault()?.ProviderId + Title = group.key.Title, + ProviderId = group.key.ProviderId }); } From 4a18d661641442f132417a89d64470c057ff4e9d Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 24 Mar 2022 19:19:08 +0000 Subject: [PATCH 105/210] chore(release): :rocket: v4.15.3 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6018a3c14..2eff3e96c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.15.3](https://github.com/Ombi-app/Ombi/compare/v4.15.2...v4.15.3) (2022-03-24) + + + ## [4.15.2](https://github.com/Ombi-app/Ombi/compare/v4.15.1...v4.15.2) (2022-03-23) @@ -338,12 +342,3 @@ -## [4.7.9](https://github.com/Ombi-app/Ombi/compare/v4.7.8...v4.7.9) (2021-12-16) - - -### Bug Fixes - -* **sonarr:** :bug: Fixed an issue where we were sometimes incorrectly setting the state of episodes that are already monitored in sonarr ([fd1acb8](https://github.com/Ombi-app/Ombi/commit/fd1acb88cbc5e73f91b7f81e6e28ee06d66b277e)) - - - diff --git a/version.json b/version.json index 6ee442cb4..583f36c5d 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.2" + "version": "4.15.3" } \ No newline at end of file From eb2788b761b55c487a59a049427ca08f6c10e836 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 25 Mar 2022 09:35:13 +0000 Subject: [PATCH 106/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi.I18n/Resources/Texts.da.resx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.I18n/Resources/Texts.da.resx b/src/Ombi.I18n/Resources/Texts.da.resx index 244fc97a7..2f217736e 100644 --- a/src/Ombi.I18n/Resources/Texts.da.resx +++ b/src/Ombi.I18n/Resources/Texts.da.resx @@ -148,9 +148,9 @@ Album - Movie + Film - TV Show + TV-Serier \ No newline at end of file From e62509093e72c92f82e3cde2dde569c8ece25fd5 Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:23:56 +0200 Subject: [PATCH 107/210] Display 'partly available' status on TV show discover card --- .../components/card/discover-card.component.html | 2 +- .../components/card/discover-card.component.scss | 16 ++++++---------- .../components/card/discover-card.component.ts | 8 +++++++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html index 6bd515e27..9ca607082 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.html @@ -6,7 +6,7 @@ {{ 'Common.' + RequestType[result.type] | translate }}
- {{getAvailbilityStatus()}} + {{getAvailabilityStatus()}}
Date: Mon, 28 Mar 2022 15:30:33 +0200 Subject: [PATCH 108/210] Make Serilog configurable and default level to Information --- src/Ombi/Ombi.csproj | 3 ++- src/Ombi/Startup.cs | 2 +- src/Ombi/appsettings.Development.json | 3 +++ src/Ombi/appsettings.json | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 3dbc377cf..69ee6b233 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -75,9 +75,10 @@ - + + diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index a37c1d230..9fe01019e 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -49,7 +49,7 @@ namespace Ombi Configuration = builder.Build(); ILogger config = new LoggerConfiguration() - .MinimumLevel.Debug() + .ReadFrom.Configuration(Configuration) .WriteTo.RollingFile(Path.Combine(StoragePath.StoragePath.IsNullOrEmpty() ? env.ContentRootPath : StoragePath.StoragePath, "Logs", "log-{Date}.txt")) .CreateLogger(); diff --git a/src/Ombi/appsettings.Development.json b/src/Ombi/appsettings.Development.json index 645fb3aaa..0a2a2974c 100644 --- a/src/Ombi/appsettings.Development.json +++ b/src/Ombi/appsettings.Development.json @@ -8,5 +8,8 @@ "System.Net.Http.HttpClient.health-checks": "Information", "HealthChecks": "Information" } + }, + "Serilog": { + "MinimumLevel": "Debug" } } diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 869428806..b27b627a9 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -10,6 +10,9 @@ "HealthChecks": "Warning" } }, + "Serilog": { + "MinimumLevel": "Information" + }, "ApplicationSettings": { "NotificationService": "https://ombinotifications.azurewebsites.net/api/", "OmbiService": "?" From dffadbe9d7efaa7cfd1ada242047a81ff855fbf0 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 29 Mar 2022 12:16:56 +0000 Subject: [PATCH 109/210] chore(release): :rocket: v4.15.4 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eff3e96c..ed8c9b28c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.15.4](https://github.com/Ombi-app/Ombi/compare/v4.15.3...v4.15.4) (2022-03-29) + + + ## [4.15.3](https://github.com/Ombi-app/Ombi/compare/v4.15.2...v4.15.3) (2022-03-24) @@ -333,12 +337,3 @@ -## [4.7.10](https://github.com/Ombi-app/Ombi/compare/v4.7.9...v4.7.10) (2021-12-16) - - -### Bug Fixes - -* **discover:** :bug: Fixed an issue where monitored movies in radarr were not correctly represented on the search results ([75b15bc](https://github.com/Ombi-app/Ombi/commit/75b15bc7cba21f0a14a18c8e64fd52482f5c6325)) - - - diff --git a/version.json b/version.json index 583f36c5d..fc93bc86f 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.3" + "version": "4.15.4" } \ No newline at end of file From 04c1fa73e87dcbf1e065aeeefa9b73a027f8daa7 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Wed, 6 Apr 2022 12:15:24 +0200 Subject: [PATCH 110/210] Fix incorrect request status for denied movies --- src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs | 2 ++ .../movie/panels/movie-information-panel.component.html | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index d160435be..576b511fa 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -398,6 +398,8 @@ namespace Ombi.Core.Engine.V2 mapped.Available = viewMovie.Available; mapped.Approved = viewMovie.Approved; + mapped.Denied = viewMovie.Denied; + mapped.DeniedReason = viewMovie.DeniedReason; mapped.RequestId = viewMovie.RequestId; mapped.Requested = viewMovie.Requested; mapped.PlexUrl = viewMovie.PlexUrl; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index 019e24214..a288b76be 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -36,10 +36,11 @@
{{'MediaDetails.RequestStatus' | translate }} -
{{'Common.ProcessingRequest' | translate}}
-
{{'Common.PendingApproval' | translate}} +
{{'Common.Denied' | translate}}
+
{{'Common.ProcessingRequest' | translate}}
+
{{'Common.PendingApproval' | translate}}
-
{{'Common.NotRequested' | translate}} +
{{'Common.NotRequested' | translate}}
From 890d74037a5dee57ead2b5d421bb394a25a7c062 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 6 Apr 2022 20:02:52 +0100 Subject: [PATCH 111/210] wip: made a start on the import --- src/Ombi.Api.Plex/IPlexApi.cs | 2 ++ src/Ombi.Api.Plex/Models/PlexWatchlist.cs | 14 ++++++++++++ src/Ombi.Api.Plex/PlexApi.cs | 12 ++++++++++ .../Plex/Interfaces/IPlexWatchlistImport.cs | 6 +++++ .../Jobs/Plex/PlexWatchlistImport.cs | 22 +++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 src/Ombi.Api.Plex/Models/PlexWatchlist.cs create mode 100644 src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs create mode 100644 src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index a4597765e..445a7e6ce 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.Friends; @@ -26,5 +27,6 @@ namespace Ombi.Api.Plex Task GetPin(int pinId); Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); + Task GetWatchlist(string plexToken, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlist.cs b/src/Ombi.Api.Plex/Models/PlexWatchlist.cs new file mode 100644 index 000000000..52ca82cf9 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlist.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlist + { + public string librarySectionID { get; set; } + public string librarySectionTitle { get; set; } + public int offset { get; set; } + public int totalSize { get; set; } + public int size { get; set; } + public List Metadata { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 176af31ec..cee668236 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -1,5 +1,6 @@ using System; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using Ombi.Api.Plex.Models; @@ -66,6 +67,7 @@ namespace Ombi.Api.Plex private const string FriendsUri = "https://plex.tv/pms/friends/all"; private const string GetAccountUri = "https://plex.tv/users/account.json"; private const string ServerUri = "https://plex.tv/pms/servers.xml"; + private const string WatchlistUri = "https://metadata.provider.plex.tv/library/sections/watchlist/all"; /// /// Sign into the Plex API @@ -288,6 +290,16 @@ namespace Ombi.Api.Plex } } + public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) + { + var request = new Request(string.Empty, WatchlistUri, HttpMethod.Get); + await AddHeaders(request, plexToken); + + var result = await Api.Request(request, cancellationToken); + + return result; + } + /// /// Adds the required headers and also the authorization header diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs new file mode 100644 index 000000000..2dd6d46e4 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexWatchlistImport.cs @@ -0,0 +1,6 @@ +namespace Ombi.Schedule.Jobs.Plex +{ + public interface IPlexWatchlistImport : IBaseJob + { + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs new file mode 100644 index 000000000..d3626fc8d --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -0,0 +1,22 @@ +using Quartz; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Plex +{ + public class PlexWatchlistImport : IPlexWatchlistImport + { + public void Dispose() + { + throw new NotImplementedException(); + } + + public Task Execute(IJobExecutionContext context) + { + throw new NotImplementedException(); + } + } +} From b5a268510d1a66a770c265239f57e5263a3bd5de Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 6 Apr 2022 21:42:24 +0100 Subject: [PATCH 112/210] Updated projects, updated entities to use a string as the primary keys. migrations need doing --- .../Ombi.Api.CouchPotato.csproj | 2 +- src/Ombi.Api.Discord/Ombi.Api.Discord.csproj | 2 +- src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj | 2 +- src/Ombi.Api.Emby/Ombi.Api.Emby.csproj | 2 +- .../Ombi.Api.FanartTv.csproj | 2 +- src/Ombi.Api.Github/Ombi.Api.Github.csproj | 2 +- src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj | 2 +- src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj | 2 +- .../Ombi.Api.Jellyfin.csproj | 2 +- src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj | 2 +- .../Ombi.Api.Mattermost.csproj | 2 +- .../Ombi.Api.MediaServer.csproj | 2 +- .../Ombi.Api.MusicBrainz.csproj | 2 +- .../Ombi.Api.Notifications.csproj | 2 +- src/Ombi.Api.Plex/IPlexApi.cs | 8 +- src/Ombi.Api.Plex/Models/Metadata.cs | 6 +- src/Ombi.Api.Plex/Ombi.Api.Plex.csproj | 2 +- src/Ombi.Api.Plex/PlexApi.cs | 10 +- .../Ombi.Api.Pushbullet.csproj | 2 +- .../Ombi.Api.Pushover.csproj | 2 +- src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj | 2 +- .../Ombi.Api.RottenTomatoes.csproj | 2 +- src/Ombi.Api.Service/Ombi.Api.Service.csproj | 2 +- .../Ombi.Api.SickRage.csproj | 2 +- src/Ombi.Api.Slack/Ombi.Api.Slack.csproj | 2 +- src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj | 2 +- .../Ombi.Api.Telegram.csproj | 2 +- src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj | 2 +- src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj | 2 +- src/Ombi.Api/Ombi.Api.csproj | 2 +- src/Ombi.Core/Ombi.Core.csproj | 2 +- .../Ombi.DependencyInjection.csproj | 2 +- src/Ombi.Helpers/Ombi.Helpers.csproj | 2 +- src/Ombi.Helpers/PlexHelper.cs | 2 +- src/Ombi.Hubs/Ombi.Hubs.csproj | 2 +- src/Ombi.I18n/Ombi.I18n.csproj | 4 +- src/Ombi.Mapping/Ombi.Mapping.csproj | 2 +- .../Ombi.Notifications.Templates.csproj | 2 +- .../Ombi.Notifications.csproj | 2 +- .../Ombi.Schedule.Tests.csproj | 1 + .../PlexContentSyncTests.cs | 26 ++-- .../PlexWatchlistImportTests.cs | 57 +++++++++ .../Jobs/Plex/Models/ProcessedContent.cs | 2 +- .../Jobs/Plex/PlexContentSync.cs | 6 +- .../Jobs/Plex/PlexWatchlistImport.cs | 112 +++++++++++++++++- src/Ombi.Schedule/Ombi.Schedule.csproj | 2 +- src/Ombi.Settings/Ombi.Settings.csproj | 2 +- src/Ombi.Store/Entities/OmbiUser.cs | 1 + src/Ombi.Store/Entities/PlexEpisode.cs | 6 +- src/Ombi.Store/Entities/PlexServerContent.cs | 8 +- src/Ombi.Store/Ombi.Store.csproj | 2 +- .../Repository/IPlexContentRepository.cs | 4 +- .../Repository/PlexContentRepository.cs | 4 +- src/Ombi.Test.Common/Ombi.Test.Common.csproj | 2 +- .../Ombi.Api.TheMovieDb.csproj | 2 +- 55 files changed, 248 insertions(+), 87 deletions(-) create mode 100644 src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs diff --git a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj +++ b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj +++ b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj +++ b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj index b524c9ce4..f60971192 100644 --- a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj +++ b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj +++ b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Github/Ombi.Api.Github.csproj b/src/Ombi.Api.Github/Ombi.Api.Github.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Github/Ombi.Api.Github.csproj +++ b/src/Ombi.Api.Github/Ombi.Api.Github.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj index 1285c073c..be32916f8 100644 --- a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj +++ b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj +++ b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj index dfdb5a93f..0c745556e 100644 --- a/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj +++ b/src/Ombi.Api.Jellyfin/Ombi.Api.Jellyfin.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj +++ b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj index a25024b6c..16c3a8558 100644 --- a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj +++ b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj index f167146af..a1b98b765 100644 --- a/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj +++ b/src/Ombi.Api.MediaServer/Ombi.Api.MediaServer.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj index 584b980ce..c8a78e491 100644 --- a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj +++ b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj index f84a8add6..6406ef9de 100644 --- a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj +++ b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 445a7e6ce..b80ef1827 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -17,9 +17,9 @@ namespace Ombi.Api.Plex Task GetServer(string authToken); Task GetLibrarySections(string authToken, string plexFullHost); Task GetLibrary(string authToken, string plexFullHost, string libraryId); - Task GetEpisodeMetaData(string authToken, string host, int ratingKey); - Task GetMetadata(string authToken, string plexFullHost, int itemId); - Task GetSeasons(string authToken, string plexFullHost, int ratingKey); + Task GetEpisodeMetaData(string authToken, string host, string ratingKey); + Task GetMetadata(string authToken, string plexFullHost, string itemId); + Task GetSeasons(string authToken, string plexFullHost, string ratingKey); Task GetAllEpisodes(string authToken, string host, string section, int start, int retCount); Task GetUsers(string authToken); Task GetAccount(string authToken); @@ -27,6 +27,6 @@ namespace Ombi.Api.Plex Task GetPin(int pinId); Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); - Task GetWatchlist(string plexToken, CancellationToken cancellationToken); + Task GetWatchlist(string plexToken, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index 65cb21e95..3481e9b57 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -4,7 +4,7 @@ namespace Ombi.Api.Plex.Models { public class Metadata { - public int ratingKey { get; set; } + public string ratingKey { get; set; } public string key { get; set; } public string studio { get; set; } public string type { get; set; } @@ -22,8 +22,8 @@ namespace Ombi.Api.Plex.Models public int childCount { get; set; } public Genre[] Genre { get; set; } public string primaryExtraKey { get; set; } - public int parentRatingKey { get; set; } - public int grandparentRatingKey { get; set; } + public string parentRatingKey { get; set; } + public string grandparentRatingKey { get; set; } public string guid { get; set; } public int librarySectionID { get; set; } public string librarySectionKey { get; set; } diff --git a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj +++ b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index cee668236..ea7140366 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -147,21 +147,21 @@ namespace Ombi.Api.Plex /// /// /// - public async Task GetEpisodeMetaData(string authToken, string plexFullHost, int ratingKey) + public async Task GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey) { var request = new Request($"/library/metadata/{ratingKey}", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); return await Api.Request(request); } - public async Task GetMetadata(string authToken, string plexFullHost, int itemId) + public async Task GetMetadata(string authToken, string plexFullHost, string itemId) { var request = new Request($"library/metadata/{itemId}", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); return await Api.Request(request); } - public async Task GetSeasons(string authToken, string plexFullHost, int ratingKey) + public async Task GetSeasons(string authToken, string plexFullHost, string ratingKey) { var request = new Request($"library/metadata/{ratingKey}/children", plexFullHost, HttpMethod.Get); await AddHeaders(request, authToken); @@ -290,12 +290,12 @@ namespace Ombi.Api.Plex } } - public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) + public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) { var request = new Request(string.Empty, WatchlistUri, HttpMethod.Get); await AddHeaders(request, plexToken); - var result = await Api.Request(request, cancellationToken); + var result = await Api.Request(request, cancellationToken); return result; } diff --git a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj +++ b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj index 1285c073c..be32916f8 100644 --- a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj +++ b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj index f14df4f5f..889aa0ea6 100644 --- a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj +++ b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj b/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj +++ b/src/Ombi.Api.RottenTomatoes/Ombi.Api.RottenTomatoes.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Service/Ombi.Api.Service.csproj b/src/Ombi.Api.Service/Ombi.Api.Service.csproj index a344de142..38bcd678a 100644 --- a/src/Ombi.Api.Service/Ombi.Api.Service.csproj +++ b/src/Ombi.Api.Service/Ombi.Api.Service.csproj @@ -8,7 +8,7 @@ Ombi.Api.Service Ombi.Api.Service - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj +++ b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj +++ b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj index 4945a2fb2..70032d638 100644 --- a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj +++ b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj index 6353f4bf9..89c47d251 100644 --- a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj +++ b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj index e07f40c60..fd9632e56 100644 --- a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj +++ b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj index f167146af..a1b98b765 100644 --- a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj +++ b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Api/Ombi.Api.csproj b/src/Ombi.Api/Ombi.Api.csproj index 83c3ee62e..7670d4d14 100644 --- a/src/Ombi.Api/Ombi.Api.csproj +++ b/src/Ombi.Api/Ombi.Api.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 0f7ca6845..67ecdbe13 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index e65f2d5a2..93b839c07 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index afc881d94..2098fa51f 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index 7951a7edf..4ae39f6ce 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -104,7 +104,7 @@ namespace Ombi.Helpers return new ProviderId(); } - public static string GetPlexMediaUrl(string machineId, int mediaId, string plexHost) + public static string GetPlexMediaUrl(string machineId, string mediaId, string plexHost) { var url = $"web/#!/server/{machineId}/details?key=%2flibrary%2Fmetadata%2F{mediaId}"; diff --git a/src/Ombi.Hubs/Ombi.Hubs.csproj b/src/Ombi.Hubs/Ombi.Hubs.csproj index fc65e2dc2..f6bee2eb1 100644 --- a/src/Ombi.Hubs/Ombi.Hubs.csproj +++ b/src/Ombi.Hubs/Ombi.Hubs.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.I18n/Ombi.I18n.csproj b/src/Ombi.I18n/Ombi.I18n.csproj index f44037974..a3387cdea 100644 --- a/src/Ombi.I18n/Ombi.I18n.csproj +++ b/src/Ombi.I18n/Ombi.I18n.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Mapping/Ombi.Mapping.csproj b/src/Ombi.Mapping/Ombi.Mapping.csproj index 9ad1f1135..322942cf2 100644 --- a/src/Ombi.Mapping/Ombi.Mapping.csproj +++ b/src/Ombi.Mapping/Ombi.Mapping.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj index 87a876caa..99e7509b4 100644 --- a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj +++ b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 6b497c23e..41fd3ae17 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index fd23ee60b..d8e698d0e 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs index da128794c..8540f0037 100644 --- a/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs +++ b/src/Ombi.Schedule.Tests/PlexContentSyncTests.cs @@ -47,7 +47,7 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); _mocker.Setup(x => x.GetFirstContentByCustom(It.IsAny>>())) .Returns(Task.FromResult(new PlexServerContent())); @@ -76,18 +76,18 @@ namespace Ombi.Schedule.Tests Id = "imdb://tt0322259" } }, - ratingKey = 1 + ratingKey = "1" }, } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); await _subject.MovieLoop(new PlexServers(), content, contentToAdd, contentProcessed); var first = contentToAdd.First(); Assert.That(first.ImdbId, Is.EqualTo("tt0322259")); - _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(),It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(),It.IsAny()), Times.Never); } [Test] @@ -99,7 +99,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -107,8 +107,8 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); - _mocker.Setup(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny())) + var contentProcessed = new Dictionary(); + _mocker.Setup(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.FromResult(new PlexMetadata { MediaContainer = new Mediacontainer @@ -117,7 +117,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -138,7 +138,7 @@ namespace Ombi.Schedule.Tests var first = contentToAdd.First(); Assert.That(first.ImdbId, Is.EqualTo("tt0322259")); - _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.GetMetadata(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [Test] @@ -150,7 +150,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -165,7 +165,7 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); _mocker.Setup(x => x.GetFirstContentByCustom(It.IsAny>>())) .Returns(Task.FromResult(new PlexServerContent @@ -188,7 +188,7 @@ namespace Ombi.Schedule.Tests { new Metadata { - ratingKey = 11, + ratingKey = "11", title = "test1", year = 2021, type = "movie", @@ -203,7 +203,7 @@ namespace Ombi.Schedule.Tests } }; var contentToAdd = new HashSet(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); _mocker.Setup(x => x.GetFirstContentByCustom(It.IsAny>>())) .Returns(Task.FromResult(new PlexServerContent diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs new file mode 100644 index 000000000..e0c6ef589 --- /dev/null +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -0,0 +1,57 @@ +using Moq; +using Moq.AutoMock; +using NUnit.Framework; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Schedule.Jobs.Plex; +using Ombi.Store.Entities; +using Ombi.Test.Common; +using Quartz; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Tests +{ + [TestFixture] + public class PlexWatchlistImportTests + { + + private PlexWatchlistImport _subject; + private AutoMocker _mocker; + private Mock _context; + + [SetUp] + public void Setup() + { + _mocker = new AutoMocker(); + var um = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); + _mocker.Use(um); + _context = _mocker.GetMock(); + _context.Setup(x => x.CancellationToken).Returns(CancellationToken.None); + _subject = _mocker.CreateInstance(); + } + + [Test] + public async Task TerminatesWhenPlexIsNotEnabled() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false }); + await _subject.Execute(null); + } + + [Test] + public async Task EmptyWatchList() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlist()); + await _subject.Execute(_context.Object); + } + } +} diff --git a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs index fc46e88b7..84748c1f7 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs @@ -5,7 +5,7 @@ namespace Ombi.Schedule.Jobs.Plex.Models { public class ProcessedContent { - public IEnumerable Content { get; set; } + public IEnumerable Content { get; set; } public IEnumerable Episodes { get; set; } public bool HasProcessedContent => Content?.Any() ?? false; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 62d0fb1b9..170f6b943 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -167,7 +167,7 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch) { var retVal = new ProcessedContent(); - var contentProcessed = new Dictionary(); + var contentProcessed = new Dictionary(); var episodesProcessed = new List(); Logger.LogDebug("Getting all content from server {0}", servers.Name); var allContent = await GetAllContent(servers, recentlyAddedSearch); @@ -290,7 +290,7 @@ namespace Ombi.Schedule.Jobs.Plex } public async Task MovieLoop(PlexServers servers, Mediacontainer content, HashSet contentToAdd, - Dictionary contentProcessed) + Dictionary contentProcessed) { Logger.LogDebug("Processing Movies"); foreach (var movie in content?.Metadata ?? Array.Empty()) @@ -437,7 +437,7 @@ namespace Ombi.Schedule.Jobs.Plex } } - private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) + private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) { var seasonList = await PlexApi.GetSeasons(servers.PlexAuthToken, servers.FullUri, show.ratingKey); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index d3626fc8d..7c808ccf2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -1,4 +1,13 @@ -using Quartz; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models; +using Ombi.Core.Authentication; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; +using Ombi.Store.Entities; +using Ombi.Store.Repository.Requests; +using Quartz; using System; using System.Collections.Generic; using System.Linq; @@ -9,14 +18,107 @@ namespace Ombi.Schedule.Jobs.Plex { public class PlexWatchlistImport : IPlexWatchlistImport { - public void Dispose() + private readonly IPlexApi _plexApi; + private readonly ISettingsService _settings; + private readonly OmbiUserManager _ombiUserManager; + private readonly IMovieRequestRepository _movieRequestRepository; + private readonly ITvRequestRepository _tvRequestRepository; + private readonly IMovieRequestEngine _movieRequestEngine; + + public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, + IMovieRequestRepository movieRequestRepository, ITvRequestRepository tvRequestRepository, IMovieRequestEngine movieRequestEngine) + { + _plexApi = plexApi; + _settings = settings; + _ombiUserManager = ombiUserManager; + _movieRequestRepository = movieRequestRepository; + _tvRequestRepository = tvRequestRepository; + _movieRequestEngine = movieRequestEngine; + } + + public async Task Execute(IJobExecutionContext context) + { + var token = "-DpQi6mzq2QMakYgFr2g"; // !!!!!!!!!!!!!!!!!!!! TODO REMOVE !!!!!!!!!!!!!!!!!!!!!!! + + var settings = await _settings.GetSettingsAsync(); + if (!settings.Enable) + { + return; + } + + var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); + foreach (var user in plexUsersWithTokens) + { + var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context.CancellationToken); + if (watchlist == null || !watchlist.Metadata.Any()) + { + continue; + } + + var items = watchlist.Metadata; + foreach (var item in items) + { + switch (item.type) + { + case "show": + await ProcessShow(item); + break; + case "movie": + await ProcessMovie(item, null); + break; + } + } + + + } + } + + private async Task ProcessMovie(Metadata movie, PlexServers servers) { - throw new NotImplementedException(); + var providerIds = await GetProviderIds(movie, servers); + if (!providerIds.TheMovieDb.HasValue()) + { + // We need a MovieDbId to support this; + return; + } + //_movieRequestEngine.RequestMovie(new() { TheMovieDbId = }); } - public Task Execute(IJobExecutionContext context) + private async Task GetProviderIds(Metadata movie, PlexServers servers) { - throw new NotImplementedException(); + var guids = new List(); + if (!movie.Guid.Any()) + { + var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, + movie.ratingKey); + + var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); + guids.Add(meta.guid); + if (meta.Guid != null) + { + foreach (var g in meta.Guid) + { + guids.Add(g.Id); + } + } + } + else + { + // Currently a Plex Pass feature only + foreach (var g in movie.Guid) + { + guids.Add(g.Id); + } + } + var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + return providerIds; } + + private async Task ProcessShow(Metadata metadata) + { + + } + + public void Dispose() { } } } diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index ed1a7d9a1..a972aa6bb 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index 4b3aa4c60..3821892f0 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -6,7 +6,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index 1b7ea6f7c..376db28f7 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -36,6 +36,7 @@ namespace Ombi.Store.Entities public RequestLimitType? MusicRequestLimitType { get; set; } public string UserAccessToken { get; set; } + public string MediaServerToken { get; set; } public List NotificationUserIds { get; set; } public List UserNotificationPreferences { get; set; } diff --git a/src/Ombi.Store/Entities/PlexEpisode.cs b/src/Ombi.Store/Entities/PlexEpisode.cs index 02cfc8a07..a9628a13d 100644 --- a/src/Ombi.Store/Entities/PlexEpisode.cs +++ b/src/Ombi.Store/Entities/PlexEpisode.cs @@ -7,15 +7,15 @@ namespace Ombi.Store.Entities [Table("PlexEpisode")] public class PlexEpisode : MediaServerEpisode { - public int Key { get; set; } // RatingKey + public string Key { get; set; } // RatingKey /// /// The parent key. /// - public int ParentKey { get; set; } + public string ParentKey { get; set; } /// /// The grandparent key. /// - public int GrandparentKey { get; set; } + public string GrandparentKey { get; set; } [NotMapped] public PlexServerContent PlexSeries { diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index f33ddb2f1..8af5e250e 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -40,7 +40,7 @@ namespace Ombi.Store.Entities /// /// Plex's internal ID for this item /// - public int Key { get; set; } + public string Key { get; set; } public int? RequestId { get; set; } @@ -50,9 +50,9 @@ namespace Ombi.Store.Entities [Table("PlexSeasonsContent")] public class PlexSeasonsContent : Entity { - public int PlexContentId { get; set; } + public string PlexContentId { get; set; } public int SeasonNumber { get; set; } - public int SeasonKey { get; set; } - public int ParentKey { get; set; } + public string SeasonKey { get; set; } + public string ParentKey { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index f35da548f..1c145f55a 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -7,7 +7,7 @@ true - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.Store/Repository/IPlexContentRepository.cs b/src/Ombi.Store/Repository/IPlexContentRepository.cs index f3c6d0ae2..aeb4aae0a 100644 --- a/src/Ombi.Store/Repository/IPlexContentRepository.cs +++ b/src/Ombi.Store/Repository/IPlexContentRepository.cs @@ -13,8 +13,8 @@ namespace Ombi.Store.Repository Task ContentExists(string providerId); Task Get(string providerId, ProviderType type); Task GetByType(string providerId, ProviderType type, MediaType mediaType); - Task GetByKey(int key); - Task GetEpisodeByKey(int key); + Task GetByKey(string key); + Task GetEpisodeByKey(string key); IEnumerable GetWhereContentByCustom(Expression> predicate); Task GetFirstContentByCustom(Expression> predicate); Task DeleteEpisode(PlexEpisode content); diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 9ae5adce8..96dfbe8e1 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -92,7 +92,7 @@ namespace Ombi.Store.Repository return null; } - public async Task GetByKey(int key) + public async Task GetByKey(string key) { return await Db.PlexServerContent.Include(x => x.Seasons).FirstOrDefaultAsync(x => x.Key == key); } @@ -154,7 +154,7 @@ namespace Ombi.Store.Repository await InternalSaveChanges(); } - public async Task GetEpisodeByKey(int key) + public async Task GetEpisodeByKey(string key) { return await Db.PlexEpisode.FirstOrDefaultAsync(x => x.Key == key); } diff --git a/src/Ombi.Test.Common/Ombi.Test.Common.csproj b/src/Ombi.Test.Common/Ombi.Test.Common.csproj index 71b05f59c..512055143 100644 --- a/src/Ombi.Test.Common/Ombi.Test.Common.csproj +++ b/src/Ombi.Test.Common/Ombi.Test.Common.csproj @@ -2,7 +2,7 @@ net6.0 - 8.0 + latest Debug;Release;NonUiBuild diff --git a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj index 41ac19686..ddab7e3f8 100644 --- a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj +++ b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj @@ -7,7 +7,7 @@ 3.0.0.0 - 8.0 + latest Debug;Release;NonUiBuild From 1c4fc78a44575ef5a2ef7f15327a65fe6617e186 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 6 Apr 2022 20:46:56 +0000 Subject: [PATCH 113/210] chore(release): :rocket: v4.15.5 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed8c9b28c..7191d7cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.15.5](https://github.com/Ombi-app/Ombi/compare/v4.15.4...v4.15.5) (2022-04-06) + + + ## [4.15.4](https://github.com/Ombi-app/Ombi/compare/v4.15.3...v4.15.4) (2022-03-29) @@ -328,12 +332,3 @@ -## [4.7.11](https://github.com/Ombi-app/Ombi/compare/v4.7.10...v4.7.11) (2021-12-17) - - -### Bug Fixes - -* **availability-rules:** :bug: Show the 'Requested' button when a show has all of the episodes marked as requested ([cb7ecf6](https://github.com/Ombi-app/Ombi/commit/cb7ecf684ac3ab204f329a28baecfd4f6cd408f7)) - - - diff --git a/version.json b/version.json index fc93bc86f..789d05bbe 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.4" + "version": "4.15.5" } \ No newline at end of file From df59b46a785a350e5c5ea9ae416dcb0e3c5a2141 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 6 Apr 2022 22:47:00 +0100 Subject: [PATCH 114/210] Added sqlite migrations --- src/Ombi.Api.Plex/IPlexApi.cs | 3 +- .../Models/PlexWatchlistContainer.cs | 9 + .../Models/PlexWatchlistMetadataContainer.cs | 31 + src/Ombi.Api.Plex/PlexApi.cs | 18 +- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + .../Jobs/Plex/PlexWatchlistImport.cs | 27 +- .../20220406212825_PlexIds.Designer.cs | 533 +++++++ .../ExternalSqlite/20220406212825_PlexIds.cs | 162 +++ .../ExternalSqliteContextModelSnapshot.cs | 33 +- .../20220406213123_PlexIds.Designer.cs | 1274 +++++++++++++++++ .../OmbiSqlite/20220406213123_PlexIds.cs | 25 + .../OmbiSqliteContextModelSnapshot.cs | 3 + src/Ombi/Controllers/V1/TokenController.cs | 7 +- 13 files changed, 2089 insertions(+), 37 deletions(-) create mode 100644 src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs create mode 100644 src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index b80ef1827..746c85b77 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -27,6 +27,7 @@ namespace Ombi.Api.Plex Task GetPin(int pinId); Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); - Task GetWatchlist(string plexToken, CancellationToken cancellationToken); + Task GetWatchlist(string plexToken, CancellationToken cancellationToken); + Task GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs b/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs new file mode 100644 index 000000000..b208c189f --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlistContainer.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlistContainer + { + public PlexWatchlist MediaContainer { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs b/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs new file mode 100644 index 000000000..b582ca4e1 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexWatchlistMetadataContainer.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Plex.Models +{ + public class PlexWatchlistMetadataContainer + { + public PlexWatchlistMetadata MediaContainer { get; set; } + } + + + public class PlexWatchlistMetadata + { + public int offset { get; set; } + public int totalSize { get; set; } + public string identifier { get; set; } + public int size { get; set; } + public WatchlistMetadata[] Metadata { get; set; } + } + + public class WatchlistMetadata + { + public string guid { get; set; } + public string key { get; set; } + public string primaryExtraKey { get; set; } + public string ratingKey { get; set; } + public string type { get; set; } + public string slug { get; set; } + public string title { get; set; } + public List Guid { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index ea7140366..9f91c540c 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -67,7 +67,7 @@ namespace Ombi.Api.Plex private const string FriendsUri = "https://plex.tv/pms/friends/all"; private const string GetAccountUri = "https://plex.tv/users/account.json"; private const string ServerUri = "https://plex.tv/pms/servers.xml"; - private const string WatchlistUri = "https://metadata.provider.plex.tv/library/sections/watchlist/all"; + private const string WatchlistUri = "https://metadata.provider.plex.tv/"; /// /// Sign into the Plex API @@ -290,12 +290,22 @@ namespace Ombi.Api.Plex } } - public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) + public async Task GetWatchlist(string plexToken, CancellationToken cancellationToken) { - var request = new Request(string.Empty, WatchlistUri, HttpMethod.Get); + var request = new Request("library/sections/watchlist/all", WatchlistUri, HttpMethod.Get); await AddHeaders(request, plexToken); - var result = await Api.Request(request, cancellationToken); + var result = await Api.Request(request, cancellationToken); + + return result; + } + + public async Task GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken) + { + var request = new Request($"library/metadata/{ratingKey}", WatchlistUri, HttpMethod.Get); + await AddHeaders(request, plexToken); + + var result = await Api.Request(request, cancellationToken); return result; } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3fb5cd643..d22990f39 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -233,6 +233,7 @@ namespace Ombi.DependencyInjection services.AddSingleton(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 7c808ccf2..4fefdf2aa 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Schedule.Jobs.Plex @@ -38,7 +39,6 @@ namespace Ombi.Schedule.Jobs.Plex public async Task Execute(IJobExecutionContext context) { - var token = "-DpQi6mzq2QMakYgFr2g"; // !!!!!!!!!!!!!!!!!!!! TODO REMOVE !!!!!!!!!!!!!!!!!!!!!!! var settings = await _settings.GetSettingsAsync(); if (!settings.Enable) @@ -47,15 +47,15 @@ namespace Ombi.Schedule.Jobs.Plex } var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); - foreach (var user in plexUsersWithTokens) - { - var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context.CancellationToken); - if (watchlist == null || !watchlist.Metadata.Any()) + //foreach (var user in plexUsersWithTokens) + //{ + var watchlist = await _plexApi.GetWatchlist(token, context?.CancellationToken ?? CancellationToken.None); + if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) { - continue; + return; } - var items = watchlist.Metadata; + var items = watchlist.MediaContainer.Metadata; foreach (var item in items) { switch (item.type) @@ -64,18 +64,18 @@ namespace Ombi.Schedule.Jobs.Plex await ProcessShow(item); break; case "movie": - await ProcessMovie(item, null); + await ProcessMovie(token, item, null, context?.CancellationToken ?? CancellationToken.None); break; } } - } + //} } - private async Task ProcessMovie(Metadata movie, PlexServers servers) + private async Task ProcessMovie(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) { - var providerIds = await GetProviderIds(movie, servers); + var providerIds = await GetProviderIds(authToken, movie, servers, cancellationToken); if (!providerIds.TheMovieDb.HasValue()) { // We need a MovieDbId to support this; @@ -84,13 +84,12 @@ namespace Ombi.Schedule.Jobs.Plex //_movieRequestEngine.RequestMovie(new() { TheMovieDbId = }); } - private async Task GetProviderIds(Metadata movie, PlexServers servers) + private async Task GetProviderIds(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) { var guids = new List(); if (!movie.Guid.Any()) { - var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, - movie.ratingKey); + var metaData = await _plexApi.GetWatchlistMetadata(movie.ratingKey, authToken, cancellationToken); var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); guids.Add(meta.guid); diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs new file mode 100644 index 000000000..eb5a07394 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.Designer.cs @@ -0,0 +1,533 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220406212825_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("PlexContentId") + .HasColumnType("TEXT"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs new file mode 100644 index 000000000..4f3d92ece --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220406212825_PlexIds.cs @@ -0,0 +1,162 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "TEXT", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "TEXT", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "INTEGER", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs index 302f5f537..ca7ba7a96 100644 --- a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs @@ -274,14 +274,14 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("EpisodeNumber") .HasColumnType("INTEGER"); - b.Property("GrandparentKey") - .HasColumnType("INTEGER"); + b.Property("GrandparentKey") + .HasColumnType("TEXT"); - b.Property("Key") - .HasColumnType("INTEGER"); + b.Property("Key") + .HasColumnType("TEXT"); - b.Property("ParentKey") - .HasColumnType("INTEGER"); + b.Property("ParentKey") + .HasColumnType("TEXT"); b.Property("SeasonNumber") .HasColumnType("INTEGER"); @@ -302,17 +302,17 @@ namespace Ombi.Store.Migrations.ExternalSqlite .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); - b.Property("ParentKey") - .HasColumnType("INTEGER"); + b.Property("ParentKey") + .HasColumnType("TEXT"); - b.Property("PlexContentId") - .HasColumnType("INTEGER"); + b.Property("PlexContentId") + .HasColumnType("TEXT"); b.Property("PlexServerContentId") .HasColumnType("INTEGER"); - b.Property("SeasonKey") - .HasColumnType("INTEGER"); + b.Property("SeasonKey") + .HasColumnType("TEXT"); b.Property("SeasonNumber") .HasColumnType("INTEGER"); @@ -339,8 +339,9 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.Property("ImdbId") .HasColumnType("TEXT"); - b.Property("Key") - .HasColumnType("INTEGER"); + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); b.Property("Quality") .HasColumnType("TEXT"); @@ -496,9 +497,7 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") .WithMany("Episodes") .HasForeignKey("GrandparentKey") - .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasPrincipalKey("Key"); b.Navigation("Series"); }); diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs new file mode 100644 index 000000000..2d3d8c76c --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.Designer.cs @@ -0,0 +1,1274 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220406213123_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs new file mode 100644 index 000000000..b83d441a0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220406213123_PlexIds.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MediaServerToken", + table: "AspNetUsers", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MediaServerToken", + table: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 528989d02..8062087df 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -281,6 +281,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("LockoutEnd") .HasColumnType("TEXT"); + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + b.Property("MovieRequestLimit") .HasColumnType("INTEGER"); diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index 3a409c206..bd0d7da52 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -18,6 +18,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; +using Ombi.Schedule.Jobs.Plex; namespace Ombi.Controllers.V1 { @@ -27,7 +28,8 @@ namespace Ombi.Controllers.V1 public class TokenController : ControllerBase { public TokenController(OmbiUserManager um, IOptions ta, ITokenRepository token, - IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth) + IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth, + IPlexWatchlistImport import) { _userManager = um; _tokenAuthenticationOptions = ta.Value; @@ -35,6 +37,7 @@ namespace Ombi.Controllers.V1 _plexOAuthManager = oAuthManager; _log = logger; _authSettings = auth; + _import = import; } private readonly TokenAuthentication _tokenAuthenticationOptions; @@ -43,6 +46,7 @@ namespace Ombi.Controllers.V1 private readonly IPlexOAuthManager _plexOAuthManager; private readonly ILogger _log; private readonly ISettingsService _authSettings; + private readonly IPlexWatchlistImport _import; /// /// Gets the token. @@ -53,6 +57,7 @@ namespace Ombi.Controllers.V1 [ProducesResponseType(401)] public async Task GetToken([FromBody] UserAuthModel model) { + await _import.Execute(null); if (!model.UsePlexOAuth) { var user = await _userManager.FindByNameAsync(model.Username); From a5355a3023e6900c4dd1b0da4722d7596c03907f Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 08:00:36 +0100 Subject: [PATCH 115/210] fix(radarr): Fixed an issue where we couldn't sync radarr content #4577 --- src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs index 15627d414..f40dfcd80 100644 --- a/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs +++ b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs @@ -77,13 +77,10 @@ namespace Ombi.Api.Radarr.Models public class Mediainfo { public string audioAdditionalFeatures { get; set; } - public int audioBitrate { get; set; } public float audioChannels { get; set; } public string audioCodec { get; set; } public string audioLanguages { get; set; } public int audioStreamCount { get; set; } - public int videoBitDepth { get; set; } - public int videoBitrate { get; set; } public string videoCodec { get; set; } public float videoFps { get; set; } public string resolution { get; set; } @@ -122,4 +119,4 @@ namespace Ombi.Api.Radarr.Models public int id { get; set; } public string name { get; set; } } -} \ No newline at end of file +} From e5e7354da7d331762e1e31db97ab57fa1e808714 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 7 Apr 2022 07:04:16 +0000 Subject: [PATCH 116/210] chore(release): :rocket: v4.15.6 --- CHANGELOG.md | 23 +++++++++-------------- version.json | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7191d7cf7..f4e990da1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.15.6](https://github.com/Ombi-app/Ombi/compare/v4.15.5...v4.15.6) (2022-04-07) + + +### Bug Fixes + +* **radarr:** Fixed an issue where we couldn't sync radarr content [#4577](https://github.com/Ombi-app/Ombi/issues/4577) ([a5355a3](https://github.com/Ombi-app/Ombi/commit/a5355a3023e6900c4dd1b0da4722d7596c03907f)) + + + ## [4.15.5](https://github.com/Ombi-app/Ombi/compare/v4.15.4...v4.15.5) (2022-04-06) @@ -318,17 +327,3 @@ -# [4.8.0](https://github.com/Ombi-app/Ombi/compare/v4.7.11...v4.8.0) (2021-12-22) - - -### Bug Fixes - -* **auto-delete:** :bug: We now also auto delete music requests, this was previously missing ([9fe1f8e](https://github.com/Ombi-app/Ombi/commit/9fe1f8e988aa31d36e7a685ae19f72d9c8414dc0)) - - -### Features - -* **details:** :sparkles: Added the notify button back into the details pages for requests ([8b33cdc](https://github.com/Ombi-app/Ombi/commit/8b33cdccef83db8794414b247438214b00860fac)) - - - diff --git a/version.json b/version.json index 789d05bbe..6f0b0f8a4 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.5" + "version": "4.15.6" } \ No newline at end of file From f41eea89a0dd163269c9bf1f35e0be45c1033ebd Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Apr 2022 11:20:33 +0100 Subject: [PATCH 117/210] Added the watchlist import for movies --- .../Engine/CalendarEngineTests.cs | 3 +- .../Engine/MovieRequestEngineTests.cs | 6 + .../Engine/MovieRequestLimitsTests.cs | 8 + .../Engine/MusicRequestLimitTests.cs | 6 + .../Engine/TvRequestLimitsTests.cs | 6 + .../Engine/V2/MovieRequestEngineTests.cs | 3 +- .../Engine/V2/MusicSearchEngineV2Tests.cs | 3 +- src/Ombi.Core.Tests/Engine/VoteEngineTests.cs | 8 +- .../Rule/Request/AutoApproveRuleTests.cs | 13 +- .../Rule/Request/CanRequestRuleTests.cs | 11 +- .../Authentication/OmbiUserManager.cs | 25 +- src/Ombi.Core/Engine/BaseMediaEngine.cs | 2 +- .../Engine/Demo/DemoMovieSearchEngine.cs | 3 +- .../Engine/Demo/DemoTvSearchEngine.cs | 3 +- src/Ombi.Core/Engine/Interfaces/BaseEngine.cs | 31 +- .../Engine/Interfaces/IRequestEngine.cs | 1 + src/Ombi.Core/Engine/MovieRequestEngine.cs | 3 +- src/Ombi.Core/Engine/MovieSearchEngine.cs | 3 +- src/Ombi.Core/Engine/MusicRequestEngine.cs | 3 +- src/Ombi.Core/Engine/MusicSearchEngine.cs | 2 +- src/Ombi.Core/Engine/TvRequestEngine.cs | 2 +- src/Ombi.Core/Engine/TvSearchEngine.cs | 3 +- src/Ombi.Core/Engine/V2/CalendarEngine.cs | 3 +- .../Engine/V2/MovieSearchEngineV2.cs | 3 +- src/Ombi.Core/Engine/V2/MultiSearchEngine.cs | 3 +- .../Engine/V2/MusicSearchEngineV2.cs | 3 +- src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs | 3 +- src/Ombi.Core/Engine/VoteEngine.cs | 3 +- src/Ombi.Core/Helpers/CurrentUser.cs | 47 + src/Ombi.Core/Helpers/ICurrentUser.cs | 15 + .../Models/Requests/MovieRequestViewModel.cs | 36 +- .../Rule/Rules/Request/AutoApproveRule.cs | 8 +- .../Rule/Rules/Request/CanRequestRule.cs | 8 +- src/Ombi.Core/Services/RequestLimitService.cs | 8 +- src/Ombi.DependencyInjection/IocExtensions.cs | 3 + .../PlexWatchlistImportTests.cs | 198 ++- .../Jobs/Plex/PlexWatchlistImport.cs | 53 +- src/Ombi.Schedule/OmbiScheduler.cs | 1 + .../Settings/Models/External/PlexSettings.cs | 1 + .../Settings/Models/JobSettings.cs | 1 + .../Settings/Models/JobSettingsHelper.cs | 5 + .../Entities/Requests/BaseRequest.cs | 2 + .../Entities/Requests/RequestSource.cs | 8 + .../20220407072656_RequestSource.Designer.cs | 1283 +++++++++++++++++ .../20220407072656_RequestSource.cs | 48 + .../OmbiSqliteContextModelSnapshot.cs | 9 + .../ClientApp/src/app/interfaces/ISettings.ts | 2 + .../ClientApp/src/app/services/job.service.ts | 4 + .../src/app/settings/jobs/jobs.component.html | 7 + .../src/app/settings/jobs/jobs.component.ts | 1 + .../src/app/settings/plex/plex.component.html | 12 + .../src/app/settings/plex/plex.component.ts | 8 + src/Ombi/Controllers/V1/JobController.cs | 11 + src/Ombi/Controllers/V1/SettingsController.cs | 1 + src/Ombi/Controllers/V1/TokenController.cs | 14 +- 55 files changed, 1824 insertions(+), 136 deletions(-) create mode 100644 src/Ombi.Core/Helpers/CurrentUser.cs create mode 100644 src/Ombi.Core/Helpers/ICurrentUser.cs create mode 100644 src/Ombi.Store/Entities/Requests/RequestSource.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs diff --git a/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs b/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs index b922a21c0..0a85fd058 100644 --- a/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/CalendarEngineTests.cs @@ -10,6 +10,7 @@ using Ombi.Core.Authentication; using Ombi.Core.Engine.V2; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Engine { @@ -25,7 +26,7 @@ namespace Ombi.Core.Tests.Engine { MovieRepo = new Mock(); TvRepo = new Mock(); - var principle = new Mock(); + var principle = new Mock(); var identity = new Mock(); identity.Setup(x => x.Name).Returns("UnitTest"); principle.Setup(x => x.Identity).Returns(identity.Object); diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs index 8c37aaa9a..f8ced161f 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestEngineTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -35,12 +36,17 @@ namespace Ombi.Core.Tests.Engine var identity = new Mock(); identity.Setup(x => x.Name).Returns("Test"); principle.Setup(x => x.Identity).Returns(identity.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identity.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { NormalizedUserName = "TEST", Id = "a" }); _repoMock = new Mock(); var requestServiceMock = new Mock(); requestServiceMock.Setup(x => x.MovieRequestService).Returns(_repoMock.Object); _mocker.Use(principle.Object); + _mocker.Use(currentUser.Object); _mocker.Use(userManager.Object); _mocker.Use(requestServiceMock); diff --git a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs index f1af160d6..88e1c75d2 100644 --- a/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -36,6 +37,13 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); + + _mocker.Use(currentUser.Object); _mocker.Use(principleMock.Object); _subject = _mocker.CreateInstance(); diff --git a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs index f7291409b..93dd5050d 100644 --- a/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs +++ b/src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -36,7 +37,12 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); _mocker.Use(principleMock.Object); + _mocker.Use(currentUser.Object); _subject = _mocker.CreateInstance(); } diff --git a/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs b/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs index e601ab84d..ba383da6c 100644 --- a/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs +++ b/src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs @@ -4,6 +4,7 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Services; using Ombi.Helpers; @@ -33,7 +34,12 @@ namespace Ombi.Core.Tests.Engine var identityMock = new Mock(); identityMock.SetupGet(x => x.Name).Returns("Test"); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); + var currentUser = new Mock(); + currentUser.Setup(x => x.Identity).Returns(identityMock.Object); + currentUser.Setup(x => x.Username).Returns("Test"); + currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" }); _mocker.Use(principleMock.Object); + _mocker.Use(currentUser.Object); _subject = _mocker.CreateInstance(); } diff --git a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs index d9f5b11be..16b7cb811 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MovieRequestEngineTests.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using Ombi.Api.TheMovieDb; using Ombi.Core.Engine; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Services; @@ -33,7 +34,7 @@ namespace Ombi.Core.Tests.Engine.V2 var requestService = new Mock(); _movieRequestRepository = new Mock(); requestService.Setup(x => x.MovieRequestService).Returns(_movieRequestRepository.Object); - var user = new Mock(); + var user = new Mock(); var notificationHelper = new Mock(); var rules = new Mock(); var movieSender = new Mock(); diff --git a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs index 50ab63346..1b773f060 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs @@ -23,6 +23,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Test.Common; using Artist = Hqub.MusicBrainz.API.Entities.Artist; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Engine.V2 { @@ -45,7 +46,7 @@ namespace Ombi.Core.Tests.Engine.V2 .ForEach(b => F.Behaviors.Remove(b)); F.Behaviors.Add(new OmitOnRecursionBehavior()); - var principle = new Mock(); + var principle = new Mock(); var requestService = new Mock(); var ruleEval = new Mock(); var um = MockHelper.MockUserManager(new List()); diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index 1269cd2bc..4194ae0ea 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Ombi.Core.Authentication; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; @@ -32,8 +33,9 @@ namespace Ombi.Core.Tests.Engine TvRequestEngine = new Mock(); MovieRequestEngine = new Mock(); MovieRequestEngine = new Mock(); - User = new Mock(); - User.Setup(x => x.Identity.Name).Returns("abc"); + User = new Mock(); + User.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "abc" }); + UserManager = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); Rule = new Mock(); Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, @@ -48,7 +50,7 @@ namespace Ombi.Core.Tests.Engine public Fixture F { get; set; } public VoteEngine Engine { get; set; } - public Mock User { get; set; } + public Mock User { get; set; } public Mock UserManager { get; set; } public Mock Rule { get; set; } public Mock> VoteRepository { get; set; } diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index 9633249d4..c73237097 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using Ombi.Store.Entities; using System; using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.Core.Tests.Rule.Request { @@ -27,17 +28,18 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { - PrincipalMock = new Mock(); - PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); FeatureService = new Mock(); + PrincipalMock = new Mock(); + PrincipalMock.Setup(x => x.Username).Returns("abc"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" }); + UserManager = MockHelper.MockUserManager(_users); Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object, FeatureService.Object); } - private AutoApproveRule Rule { get; set; } - private Mock PrincipalMock { get; set; } + private Mock PrincipalMock { get; set; } private Mock UserManager { get; set; } private Mock FeatureService { get; set; } @@ -99,7 +101,8 @@ namespace Ombi.Core.Tests.Rule.Request [Test] public async Task Should_ReturnSuccess_WhenSystemUserAndRequestTV() { - PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" }); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveTv)).ReturnsAsync(false); var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow }; var result = await Rule.Execute(request); diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index f601689dc..9d8db25d1 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Moq; using NUnit.Framework; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules.Request; using Ombi.Helpers; @@ -26,8 +27,9 @@ namespace Ombi.Core.Tests.Rule.Request public void Setup() { - PrincipalMock = new Mock(); - PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); + PrincipalMock = new Mock(); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" }); + UserManager = MockHelper.MockUserManager(_users); Rule = new CanRequestRule(PrincipalMock.Object, UserManager.Object); @@ -35,7 +37,7 @@ namespace Ombi.Core.Tests.Rule.Request private CanRequestRule Rule { get; set; } - private Mock PrincipalMock { get; set; } + private Mock PrincipalMock { get; set; } private Mock UserManager { get; set; } [Test] @@ -107,7 +109,8 @@ namespace Ombi.Core.Tests.Rule.Request [Test] public async Task Should_ReturnSuccess_WhenRequestingMovieWithSystemRole() { - PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" }); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Admin)).ReturnsAsync(false); var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; var result = await Rule.Execute(request); diff --git a/src/Ombi.Core/Authentication/OmbiUserManager.cs b/src/Ombi.Core/Authentication/OmbiUserManager.cs index 87f82c1de..124ff1aeb 100644 --- a/src/Ombi.Core/Authentication/OmbiUserManager.cs +++ b/src/Ombi.Core/Authentication/OmbiUserManager.cs @@ -116,16 +116,25 @@ namespace Ombi.Core.Authentication public async Task GetOmbiUserFromPlexToken(string plexToken) { var plexAccount = await _plexApi.GetAccount(plexToken); - + // Check for a ombi user - if (plexAccount?.user != null) + if (plexAccount?.user == null) + { + return null; + } + + var potentialOmbiUser = await Users.FirstOrDefaultAsync(x => + x.ProviderUserId == plexAccount.user.id); + // Update ombi user with the token + + if (potentialOmbiUser != null) { - var potentialOmbiUser = await Users.FirstOrDefaultAsync(x => - x.ProviderUserId == plexAccount.user.id); - return potentialOmbiUser; + potentialOmbiUser.MediaServerToken = plexAccount.user.authentication_token; + await UpdateAsync(potentialOmbiUser); } - return null; + return potentialOmbiUser; + } @@ -142,6 +151,10 @@ namespace Ombi.Core.Authentication var result = await _plexApi.SignIn(new UserRequest { password = password, login = login }); if (result.user?.authentication_token != null) { + // Update ombi user with the token + user.MediaServerToken = result.user?.authentication_token; + await UpdateAsync(user); + return true; } return false; diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index 277144ab1..ee1ce55a8 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -26,7 +26,7 @@ namespace Ombi.Core.Engine private Dictionary _dbMovies; private Dictionary _dbTv; - protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService, + protected BaseMediaEngine(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub) : base(identity, um, rules) { RequestService = requestService; diff --git a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs index f392bf7ad..af88813d9 100644 --- a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs @@ -11,6 +11,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo { public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine { - public DemoMovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public DemoMovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, IOptions lists) : base(identity, service, movApi, mapper, logger, r, um, mem, s, sub) diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs index 2c91a458f..706a5337d 100644 --- a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -4,6 +4,7 @@ using Ombi.Api.Trakt; using Ombi.Api.TvMaze; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine { - public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public DemoTvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, IRepository sub, IOptions lists, IImageService imageService, ISettingsService custom) diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index 42aff9a61..2c68ea371 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -1,42 +1,35 @@ using System; using Ombi.Core.Rule; using System.Collections.Generic; -using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Entities.Requests; using Ombi.Store.Entities; -using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; -using Ombi.Helpers; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine.Interfaces { public abstract class BaseEngine { - protected BaseEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules) + protected BaseEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules) { - UserPrinciple = user; + CurrentUser = user; Rules = rules; UserManager = um; } - protected IPrincipal UserPrinciple { get; } + protected ICurrentUser CurrentUser { get; } protected IRuleEvaluator Rules { get; } - protected OmbiUserManager UserManager { get; } - protected string Username => UserPrinciple.Identity.Name; + protected OmbiUserManager UserManager { get; } + protected string Username => CurrentUser.Username; + protected Task GetUser() => CurrentUser.GetUser(); - private OmbiUser _user; - protected async Task GetUser() - { - if(!Username.HasValue()) - { - return null; - } - var username = Username.ToUpper(); - return _user ??= await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); - } + /// + /// Only used for background tasks + /// + public void SetUser(OmbiUser user) => CurrentUser.SetUser(user); protected async Task UserAlias() { @@ -52,7 +45,7 @@ namespace Ombi.Core.Engine.Interfaces var user = await GetUser(); return await UserManager.IsInRoleAsync(user, roleName); } - + public async Task> RunRequestRules(BaseRequest model) { var ruleResults = await Rules.StartRequestRules(model); diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index d0fc04b10..01300287e 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -25,5 +25,6 @@ namespace Ombi.Core.Engine.Interfaces Task UnSubscribeRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type); Task ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken); + void SetUser(OmbiUser user); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 498cf3e0b..64b5418dd 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -23,12 +23,13 @@ using Ombi.Store.Repository; using Ombi.Core.Models; using System.Threading; using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine { - public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, + public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings, IRepository sub, IMediaCacheService mediaCacheService, diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 7d84a0b40..682a999eb 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -22,7 +23,7 @@ namespace Ombi.Core.Engine { public class MovieSearchEngine : BaseMediaEngine, IMovieEngine { - public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public MovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub) : base(identity, service, r, um, mem, s, sub) { diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index b9aa183d2..640d2ade3 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -24,12 +24,13 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System.ComponentModel; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { public class MusicRequestEngine : BaseMediaEngine, IMusicRequestEngine { - public MusicRequestEngine(IRequestServiceMain requestService, IPrincipal user, + public MusicRequestEngine(IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator r, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings, IRepository sub, ILidarrApi lidarr, diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 89bae7069..2602bf71e 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -27,7 +27,7 @@ namespace Ombi.Core.Engine { public class MusicSearchEngine : BaseMediaEngine, IMusicSearchEngine { - public MusicSearchEngine(IPrincipal identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper, + public MusicSearchEngine(ICurrentUser identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, ISettingsService lidarrSettings) : base(identity, service, r, um, mem, s, sub) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 4b46e8151..c3828eae3 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -32,7 +32,7 @@ namespace Ombi.Core.Engine { public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine { - public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, + public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger logger, ITvSender sender, IRepository rl, ISettingsService settings, ICacheService cache, IRepository sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub) diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index 518b97720..2747f262a 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -23,6 +23,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using System.Threading; using TraktSharp.Entities; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine { @@ -32,7 +33,7 @@ namespace Ombi.Core.Engine private readonly IImageService _imageService; private readonly IMovieDbApi _theMovieDbApi; - public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public TvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService customizationSettings, ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService, IMovieDbApi theMovieDbApi) diff --git a/src/Ombi.Core/Engine/V2/CalendarEngine.cs b/src/Ombi.Core/Engine/V2/CalendarEngine.cs index b7ecc8ec6..8347141bb 100644 --- a/src/Ombi.Core/Engine/V2/CalendarEngine.cs +++ b/src/Ombi.Core/Engine/V2/CalendarEngine.cs @@ -5,6 +5,7 @@ using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Search.V2; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Entities; @@ -17,7 +18,7 @@ namespace Ombi.Core.Engine.V2 { public DateTime DaysAgo => DateTime.Now.AddDays(-90); public DateTime DaysAhead => DateTime.Now.AddDays(90); - public CalendarEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo, + public CalendarEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo, ITvRequestRepository tvRequestRepo) : base(user, um, rules) { _movieRepo = movieRepo; diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index d160435be..8c612b698 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -5,6 +5,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; @@ -28,7 +29,7 @@ namespace Ombi.Core.Engine.V2 { public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2 { - public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + public MovieSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, ISettingsService customizationSettings, IMovieRequestEngine movieRequestEngine, IHttpClientFactory httpClientFactory) : base(identity, service, r, um, mem, s, sub) diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index 44f792415..362a79e43 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -7,6 +7,7 @@ using Ombi.Api.MusicBrainz; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search.V2; using Ombi.Core.Rule.Interfaces; @@ -25,7 +26,7 @@ namespace Ombi.Core.Engine.V2 { public class MultiSearchEngine : BaseMediaEngine, IMultiSearchEngine { - public MultiSearchEngine(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, + public MultiSearchEngine(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub, IMovieDbApi movieDbApi, ISettingsService lidarrSettings, IMusicBrainzApi musicApi) : base(identity, requestService, rules, um, cache, ombiSettings, sub) diff --git a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs index b7d9575db..fc3fcf40e 100644 --- a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs @@ -11,6 +11,7 @@ using Ombi.Api.Lidarr.Models; using Ombi.Api.MusicBrainz; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search.V2.Music; using Ombi.Core.Rule.Interfaces; @@ -31,7 +32,7 @@ namespace Ombi.Core.Engine.V2 private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; - public MusicSearchEngineV2(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, + public MusicSearchEngineV2(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub, IMusicBrainzApi musicBrainzApi, ISettingsService lidarrSettings, ILidarrApi lidarrApi) diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 07f8ce981..46cd44bf1 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -25,6 +25,7 @@ using Ombi.Api.TheMovieDb.Models; using System.Diagnostics; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.UI; +using Ombi.Core.Helpers; namespace Ombi.Core.Engine.V2 { @@ -37,7 +38,7 @@ namespace Ombi.Core.Engine.V2 private readonly ISettingsService _customization; private readonly ITvRequestEngine _requestEngine; - public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + public TvSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, IRepository sub, IMovieDbApi movieApi, ISettingsService customization, ITvRequestEngine requestEngine) : base(identity, service, r, um, memCache, s, sub) diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index a63ba1604..3e7f6f542 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; @@ -20,7 +21,7 @@ namespace Ombi.Core.Engine { public class VoteEngine : BaseEngine, IVoteEngine { - public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, + public VoteEngine(IRepository votes, ICurrentUser user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r) { _voteRepository = votes; diff --git a/src/Ombi.Core/Helpers/CurrentUser.cs b/src/Ombi.Core/Helpers/CurrentUser.cs new file mode 100644 index 000000000..d69d0a56d --- /dev/null +++ b/src/Ombi.Core/Helpers/CurrentUser.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Helpers; +using Ombi.Store.Entities; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Helpers +{ + public class CurrentUser : ICurrentUser + { + private readonly IPrincipal _principle; + private readonly OmbiUserManager _userManager; + private OmbiUser _user; + public IIdentity Identity { get; set; } + + public CurrentUser(IPrincipal principle, OmbiUserManager userManager) + { + _principle = principle; + _userManager = userManager; + Identity = _principle?.Identity; + } + + public void SetUser(OmbiUser user) + { + _user = user; + } + + public string Username => Identity.Name; + public async Task GetUser() + { + if (!Username.HasValue() && _user == null) + { + return null; + } + + if (_user != null) + { + return _user; + } + + var username = Username.ToUpper(); + return _user ??= await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); + } + + } +} diff --git a/src/Ombi.Core/Helpers/ICurrentUser.cs b/src/Ombi.Core/Helpers/ICurrentUser.cs new file mode 100644 index 000000000..1cce973f3 --- /dev/null +++ b/src/Ombi.Core/Helpers/ICurrentUser.cs @@ -0,0 +1,15 @@ +using Ombi.Store.Entities; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Helpers +{ + public interface ICurrentUser + { + string Username { get; } + + Task GetUser(); + void SetUser(OmbiUser user); + IIdentity Identity { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs index 39a5b6c2a..18125ed71 100644 --- a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs @@ -1,31 +1,5 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2018 Jamie Rees -// File: MovieRequestViewModel.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using Newtonsoft.Json; +using Newtonsoft.Json; +using Ombi.Store.Entities.Requests; namespace Ombi.Core.Models.Requests { @@ -41,5 +15,11 @@ namespace Ombi.Core.Models.Requests /// [JsonIgnore] public string RequestedByAlias { get; set; } + + /// + /// Only set via list imports + /// + [JsonIgnore] + public RequestSource Source { get; set; } = RequestSource.Ombi; } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index 92c1b11a7..23d26625b 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -3,6 +3,7 @@ using System.Security.Principal; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Services; @@ -15,20 +16,21 @@ namespace Ombi.Core.Rule.Rules.Request { public class AutoApproveRule : BaseRequestRule, IRules { - public AutoApproveRule(IPrincipal principal, OmbiUserManager um, IFeatureService featureService) + public AutoApproveRule(ICurrentUser principal, OmbiUserManager um, IFeatureService featureService) { User = principal; _manager = um; _featureService = featureService; } - private IPrincipal User { get; } + private ICurrentUser User { get; } private readonly OmbiUserManager _manager; private readonly IFeatureService _featureService; public async Task Execute(BaseRequest obj) { - var username = User.Identity.Name.ToUpper(); + var currentUser = await User.GetUser(); + var username = currentUser.UserName.ToUpper(); var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) { diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 2546e1f29..e2e81e612 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -10,23 +10,25 @@ using Ombi.Core.Engine; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities.Requests; +using Ombi.Core.Helpers; namespace Ombi.Core.Rule.Rules.Request { public class CanRequestRule : BaseRequestRule, IRules { - public CanRequestRule(IPrincipal principal, OmbiUserManager manager) + public CanRequestRule(ICurrentUser principal, OmbiUserManager manager) { User = principal; _manager = manager; } - private IPrincipal User { get; } + private ICurrentUser User { get; } private readonly OmbiUserManager _manager; public async Task Execute(BaseRequest obj) { - var username = User.Identity.Name.ToUpper(); + var currentUser = await User.GetUser(); + var username = currentUser.UserName.ToUpper(); var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) return Success(); diff --git a/src/Ombi.Core/Services/RequestLimitService.cs b/src/Ombi.Core/Services/RequestLimitService.cs index 83a87c7e7..d90e0d77c 100644 --- a/src/Ombi.Core/Services/RequestLimitService.cs +++ b/src/Ombi.Core/Services/RequestLimitService.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; +using Ombi.Core.Helpers; using Ombi.Core.Models; using Ombi.Helpers; using Ombi.Store.Entities; @@ -20,11 +21,11 @@ namespace Ombi.Core.Services } public class RequestLimitService : IRequestLimitService { - private readonly IPrincipal _user; + private readonly ICurrentUser _user; private readonly OmbiUserManager _userManager; private readonly IRepository _requestLog; - public RequestLimitService(IPrincipal user, OmbiUserManager userManager, IRepository rl) + public RequestLimitService(ICurrentUser user, OmbiUserManager userManager, IRepository rl) { _user = user; _userManager = userManager; @@ -141,7 +142,8 @@ namespace Ombi.Core.Services private async Task GetUser() { - var username = _user.Identity.Name.ToUpper(); + var currentUser = await _user.GetUser(); + var username = currentUser.UserName.ToUpper(); return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index d22990f39..691aca237 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -70,6 +70,7 @@ using Ombi.Api.RottenTomatoes; using System.Net.Http; using Microsoft.Extensions.Logging; using Ombi.Core.Services; +using Ombi.Core.Helpers; namespace Ombi.DependencyInjection { @@ -124,6 +125,8 @@ namespace Ombi.DependencyInjection var runtimeVersion = AssemblyHelper.GetRuntimeVersion(); services.AddSingleton(); services.AddScoped(sp => sp.GetService().HttpContext.User); + // HttpContext User is null for background jobs + services.AddScoped(sp => new CurrentUser(sp.GetService()?.HttpContext?.User ?? null, sp.GetService())); services.AddHttpClient("OmbiClient", client => { client.DefaultRequestHeaders.Add("User-Agent", $"Ombi/{runtimeVersion} (https://ombi.io/)"); diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index e0c6ef589..7f3e0ccbd 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -3,18 +3,16 @@ using Moq.AutoMock; using NUnit.Framework; using Ombi.Api.Plex; using Ombi.Api.Plex.Models; -using Ombi.Core.Authentication; +using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models.Requests; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Schedule.Jobs.Plex; using Ombi.Store.Entities; using Ombi.Test.Common; using Quartz; -using System; using System.Collections.Generic; -using System.Linq; -using System.Security.Principal; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -27,11 +25,11 @@ namespace Ombi.Schedule.Tests private PlexWatchlistImport _subject; private AutoMocker _mocker; private Mock _context; - + [SetUp] public void Setup() { - _mocker = new AutoMocker(); + _mocker = new AutoMocker(); var um = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); _mocker.Use(um); _context = _mocker.GetMock(); @@ -42,16 +40,194 @@ namespace Ombi.Schedule.Tests [Test] public async Task TerminatesWhenPlexIsNotEnabled() { - _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false }); + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false, EnableWatchlistImport = true }); await _subject.Execute(null); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); } - + [Test] + public async Task TerminatesWhenWatchlistIsNotEnabled() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = false }); + await _subject.Execute(null); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + } + [Test] public async Task EmptyWatchList() { - _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true }); - _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlist()); + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer()); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + } + + [Test] + public async Task NoPlexUsersWithToken() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + var um = MockHelper.MockUserManager(new List + { + new OmbiUser { Id = "abc", UserType = UserType.EmbyUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.LocalUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.SystemUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.JellyfinUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.EmbyConnectUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" }, + new OmbiUser { Id = "abc", UserType = UserType.PlexUser, UserName = "abc", NormalizedUserName = "ABC" }, + }); + _mocker.Use(um); + _subject = _mocker.CreateInstance(); + + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + } + + + [Test] + public async Task MovieRequestFromWatchList_NoGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + } + + [Test] + public async Task MovieRequestFromWatchList_AlreadyRequested() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { ErrorCode = ErrorCode.AlreadyRequested, ErrorMessage = "Requested" }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + } + + [Test] + public async Task MovieRequestFromWatchList_NoTmdbGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "imdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestMovie(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 4fefdf2aa..b07e95da0 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -1,17 +1,17 @@ -using Ombi.Api.Plex; +using Microsoft.Extensions.Logging; +using Ombi.Api.Plex; using Ombi.Api.Plex.Models; using Ombi.Core.Authentication; +using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Store.Entities; -using Ombi.Store.Repository.Requests; +using Ombi.Store.Entities.Requests; using Quartz; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -22,34 +22,32 @@ namespace Ombi.Schedule.Jobs.Plex private readonly IPlexApi _plexApi; private readonly ISettingsService _settings; private readonly OmbiUserManager _ombiUserManager; - private readonly IMovieRequestRepository _movieRequestRepository; - private readonly ITvRequestRepository _tvRequestRepository; private readonly IMovieRequestEngine _movieRequestEngine; + private readonly ILogger _logger; public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, - IMovieRequestRepository movieRequestRepository, ITvRequestRepository tvRequestRepository, IMovieRequestEngine movieRequestEngine) + IMovieRequestEngine movieRequestEngine, + ILogger logger) { _plexApi = plexApi; _settings = settings; _ombiUserManager = ombiUserManager; - _movieRequestRepository = movieRequestRepository; - _tvRequestRepository = tvRequestRepository; _movieRequestEngine = movieRequestEngine; + _logger = logger; } public async Task Execute(IJobExecutionContext context) { - var settings = await _settings.GetSettingsAsync(); - if (!settings.Enable) + if (!settings.Enable || !settings.EnableWatchlistImport) { return; } var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); - //foreach (var user in plexUsersWithTokens) - //{ - var watchlist = await _plexApi.GetWatchlist(token, context?.CancellationToken ?? CancellationToken.None); + foreach (var user in plexUsersWithTokens) + { + var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None); if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) { return; @@ -64,27 +62,38 @@ namespace Ombi.Schedule.Jobs.Plex await ProcessShow(item); break; case "movie": - await ProcessMovie(token, item, null, context?.CancellationToken ?? CancellationToken.None); + await ProcessMovie(user.MediaServerToken, item, user, context?.CancellationToken ?? CancellationToken.None); break; } } - - - //} + } } - private async Task ProcessMovie(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) + private async Task ProcessMovie(string authToken, Metadata movie, OmbiUser user, CancellationToken cancellationToken) { - var providerIds = await GetProviderIds(authToken, movie, servers, cancellationToken); + var providerIds = await GetProviderIds(authToken, movie, cancellationToken); if (!providerIds.TheMovieDb.HasValue()) { // We need a MovieDbId to support this; return; } - //_movieRequestEngine.RequestMovie(new() { TheMovieDbId = }); + _movieRequestEngine.SetUser(user); + var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = int.Parse(providerIds.TheMovieDb), Source = RequestSource.PlexWatchlist}); + if (response.IsError) + { + if (response.ErrorCode == ErrorCode.AlreadyRequested) + { + return; + } + _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); + } + else + { + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); + } } - private async Task GetProviderIds(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) + private async Task GetProviderIds(string authToken, Metadata movie, CancellationToken cancellationToken) { var guids = new List(); if (!movie.Guid.Any()) diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index 8e45be57c..41602f641 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -91,6 +91,7 @@ namespace Ombi.Schedule await OmbiQuartz.Instance.AddJob(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s)); await OmbiQuartz.Instance.AddJob(nameof(IPlexEpisodeSync), "Plex", null); await OmbiQuartz.Instance.AddJob(nameof(IPlexAvailabilityChecker), "Plex", null); + await OmbiQuartz.Instance.AddJob(nameof(IPlexWatchlistImport), "Plex", JobSettingsHelper.PlexWatchlistImport(s)); } private static async Task AddEmby(JobSettings s) diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index 6cf021f7c..5917e2592 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -7,6 +7,7 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } + public bool EnableWatchlistImport { get; set; } /// /// This is the ClientId for OAuth /// diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index ac7ab3bdc..cc4ed2e23 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -19,5 +19,6 @@ public string RetryRequests { get; set; } public string MediaDatabaseRefresh { get; set; } public string AutoDeleteRequests { get; set; } + public string PlexWatchlistImport { get; set; } } } diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index e580e1977..b0839cce6 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -54,6 +54,11 @@ namespace Ombi.Settings.Settings.Models { return ValidateCron(Get(s.UserImporter, Cron.Daily())); } + + public static string PlexWatchlistImport(JobSettings s) + { + return ValidateCron(Get(s.PlexWatchlistImport, Cron.Daily())); + } public static string Newsletter(JobSettings s) { diff --git a/src/Ombi.Store/Entities/Requests/BaseRequest.cs b/src/Ombi.Store/Entities/Requests/BaseRequest.cs index f26bcc8ba..9c564376b 100644 --- a/src/Ombi.Store/Entities/Requests/BaseRequest.cs +++ b/src/Ombi.Store/Entities/Requests/BaseRequest.cs @@ -22,6 +22,8 @@ namespace Ombi.Store.Entities.Requests [ForeignKey(nameof(RequestedUserId))] public OmbiUser RequestedUser { get; set; } + public RequestSource Source { get; set; } = RequestSource.Ombi; + [NotMapped] public virtual bool CanApprove => !Approved && !Available; diff --git a/src/Ombi.Store/Entities/Requests/RequestSource.cs b/src/Ombi.Store/Entities/Requests/RequestSource.cs new file mode 100644 index 000000000..44ccc20d8 --- /dev/null +++ b/src/Ombi.Store/Entities/Requests/RequestSource.cs @@ -0,0 +1,8 @@ +namespace Ombi.Store.Entities.Requests +{ + public enum RequestSource + { + Ombi = 0, + PlexWatchlist = 1 + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs new file mode 100644 index 000000000..32f92ff6c --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.Designer.cs @@ -0,0 +1,1283 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20220407072656_RequestSource")] + partial class RequestSource + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MediaServerToken") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MovieRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimitType") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Approved4K") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Available4K") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("Denied4K") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DeniedReason4K") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Has4KRequest") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedDate4k") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Source") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("LanguageProfile") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs new file mode 100644 index 000000000..c1a2400d0 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20220407072656_RequestSource.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class RequestSource : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Source", + table: "MovieRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "ChildRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "AlbumRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Source", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "ChildRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "AlbumRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 8062087df..f9ce86bae 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -469,6 +469,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("RequestedUserId") .HasColumnType("TEXT"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Title") .HasColumnType("TEXT"); @@ -527,6 +530,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("SeriesType") .HasColumnType("INTEGER"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Title") .HasColumnType("TEXT"); @@ -729,6 +735,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("RootPathOverride") .HasColumnType("INTEGER"); + b.Property("Source") + .HasColumnType("INTEGER"); + b.Property("Status") .HasColumnType("TEXT"); diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 1dc94f261..95b1fba00 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -112,6 +112,7 @@ export interface IPublicInfo { export interface IPlexSettings extends ISettings { enable: boolean; + enableWatchlistImport: boolean; servers: IPlexServer[]; } @@ -219,6 +220,7 @@ export interface IJobSettings { mediaDatabaseRefresh: string; autoDeleteRequests: string; embyRecentlyAddedSync: string; + plexWatchlistImport: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/src/app/services/job.service.ts b/src/Ombi/ClientApp/src/app/services/job.service.ts index 8bd08c4f5..6cece68d9 100644 --- a/src/Ombi/ClientApp/src/app/services/job.service.ts +++ b/src/Ombi/ClientApp/src/app/services/job.service.ts @@ -27,6 +27,10 @@ export class JobService extends ServiceHelpers { return this.http.post(`${this.url}plexUserImporter/`, {headers: this.headers}); } + public runPlexWatchlistImport(): Observable { + return this.http.post(`${this.url}plexwatchlist/`, {headers: this.headers}); + } + public runEmbyImporter(): Observable { return this.http.post(`${this.url}embyUserImporter/`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html index e15a88b7f..47e7ef1cd 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html @@ -77,6 +77,13 @@ The Plex Sync is required
+
+ + Plex Watchlist Import + + The Plex Watchlist Import is required + +
diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts index 47d05776b..89131bc42 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts @@ -37,6 +37,7 @@ export class JobsComponent implements OnInit { mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], autoDeleteRequests: [x.autoDeleteRequests, Validators.required], embyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required], + plexWatchlistImport: [x.plexWatchlistImport, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html index f84395043..858a94358 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html @@ -9,6 +9,12 @@ Enable
+
+ Enable User Watchlist Requests + +

When a Plex User adds something to their watchlist in Plex, it will turn up in Ombi as a Request if enabled. This only applies to users that are logging in with their Plex Account

+

Request limits if set are all still applied etc.

+
Advanced
@@ -183,6 +189,12 @@ Clear Data And Resync
+
+ +
diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts index 8d42419fe..d7c977b7b 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts @@ -172,6 +172,14 @@ export class PlexComponent implements OnInit, OnDestroy { }); } + public runWatchlistImport(): void { + this.jobService.runPlexWatchlistImport().subscribe(x => { + if (x) { + this.notificationService.success("Triggered the Watchlist Import"); + } + }); + } + public ngOnDestroy() { this.subscriptions.next(); this.subscriptions.complete(); diff --git a/src/Ombi/Controllers/V1/JobController.cs b/src/Ombi/Controllers/V1/JobController.cs index 442866762..57ec060a2 100644 --- a/src/Ombi/Controllers/V1/JobController.cs +++ b/src/Ombi/Controllers/V1/JobController.cs @@ -91,6 +91,17 @@ namespace Ombi.Controllers.V1 return true; } + /// + /// Runs the Plex Watchlist Importer + /// + /// + [HttpPost("plexwatchlist")] + public async Task PlexWatchlistImport() + { + await OmbiQuartz.TriggerJob(nameof(IPlexWatchlistImport), "Plex"); + return true; + } + /// /// Runs the Emby User importer /// diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index ff4dea913..0892b1dda 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -626,6 +626,7 @@ namespace Ombi.Controllers.V1 j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j); j.AutoDeleteRequests = j.AutoDeleteRequests.HasValue() ? j.AutoDeleteRequests : JobSettingsHelper.AutoDeleteRequests(j); j.EmbyRecentlyAddedSync = j.EmbyRecentlyAddedSync.HasValue() ? j.EmbyRecentlyAddedSync : JobSettingsHelper.EmbyRecentlyAddedSync(j); + j.PlexWatchlistImport = j.PlexWatchlistImport.HasValue() ? j.PlexWatchlistImport : JobSettingsHelper.PlexWatchlistImport(j); return j; } diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index bd0d7da52..588c4f606 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -6,19 +6,16 @@ using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using Ombi.Core.Authentication; using Ombi.Helpers; using Ombi.Models; using Ombi.Models.External; -using Ombi.Models.Identity; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; -using Ombi.Schedule.Jobs.Plex; namespace Ombi.Controllers.V1 { @@ -27,26 +24,21 @@ namespace Ombi.Controllers.V1 [ApiController] public class TokenController : ControllerBase { - public TokenController(OmbiUserManager um, IOptions ta, ITokenRepository token, - IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth, - IPlexWatchlistImport import) + public TokenController(OmbiUserManager um, ITokenRepository token, + IPlexOAuthManager oAuthManager, ILogger logger, ISettingsService auth) { _userManager = um; - _tokenAuthenticationOptions = ta.Value; _token = token; _plexOAuthManager = oAuthManager; _log = logger; _authSettings = auth; - _import = import; } - private readonly TokenAuthentication _tokenAuthenticationOptions; private readonly ITokenRepository _token; private readonly OmbiUserManager _userManager; private readonly IPlexOAuthManager _plexOAuthManager; private readonly ILogger _log; private readonly ISettingsService _authSettings; - private readonly IPlexWatchlistImport _import; ///
/// Gets the token. @@ -57,7 +49,6 @@ namespace Ombi.Controllers.V1 [ProducesResponseType(401)] public async Task GetToken([FromBody] UserAuthModel model) { - await _import.Execute(null); if (!model.UsePlexOAuth) { var user = await _userManager.FindByNameAsync(model.Username); @@ -122,6 +113,7 @@ namespace Ombi.Controllers.V1 { return Unauthorized(); } + return await CreateToken(true, user); } From 268e31c01953c1e992d137892a9d7e76cde7da72 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Apr 2022 12:05:07 +0100 Subject: [PATCH 118/210] Added the request source to the details --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 3 ++- src/Ombi.Core/Helpers/CurrentUser.cs | 4 ++-- src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts | 7 +++++++ .../movie/panels/movie-information-panel.component.html | 5 +++++ .../movie/panels/movie-information-panel.component.ts | 3 ++- src/Ombi/wwwroot/translations/en.json | 3 ++- 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 64b5418dd..6e81e3e73 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -143,7 +143,8 @@ namespace Ombi.Core.Engine RootPathOverride = model.RootFolderOverride.GetValueOrDefault(), QualityOverride = model.QualityPathOverride.GetValueOrDefault(), RequestedDate4k = model.Is4kRequest ? DateTime.Now : DateTime.MinValue, - Is4kRequest = model.Is4kRequest + Is4kRequest = model.Is4kRequest, + Source = model.Source }; } diff --git a/src/Ombi.Core/Helpers/CurrentUser.cs b/src/Ombi.Core/Helpers/CurrentUser.cs index d69d0a56d..974d59cd6 100644 --- a/src/Ombi.Core/Helpers/CurrentUser.cs +++ b/src/Ombi.Core/Helpers/CurrentUser.cs @@ -18,7 +18,7 @@ namespace Ombi.Core.Helpers { _principle = principle; _userManager = userManager; - Identity = _principle?.Identity; + Identity = _principle?.Identity ?? null; } public void SetUser(OmbiUser user) @@ -26,7 +26,7 @@ namespace Ombi.Core.Helpers _user = user; } - public string Username => Identity.Name; + public string Username => Identity?.Name ?? _user?.UserName; public async Task GetUser() { if (!Username.HasValue() && _user == null) diff --git a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts index 130a97c1c..36b75adb6 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts @@ -104,6 +104,13 @@ export interface IBaseRequest { canApprove: boolean; title: string; requestedByAlias: string; + source: RequestSource; +} + +export enum RequestSource +{ + Ombi = 0, + PlexWatchlist = 1 } export interface ITvRequests { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index 019e24214..814713fd0 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -53,6 +53,11 @@ {{request.requestedDate | amUserLocale | amDateFormat: 'LL'}} +
+ {{'MediaDetails.RequestSource' | translate }} + {{RequestSource[request.source]}} +
+
{{'MediaDetails.DeniedReason' | translate }} {{request.deniedReason}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts index c11a0f61c..ade256a82 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts @@ -1,6 +1,6 @@ import { Component, ViewEncapsulation, Input, OnInit, Inject } from "@angular/core"; import { ISearchMovieResultV2 } from "../../../../interfaces/ISearchMovieResultV2"; -import { IMovieRequests } from "../../../../interfaces"; +import { IMovieRequests, RequestSource } from "../../../../interfaces"; import { SearchV2Service } from "../../../../services/searchV2.service"; import { IMovieRatings } from "../../../../interfaces/IRatings"; import { APP_BASE_HREF } from "@angular/common"; @@ -21,6 +21,7 @@ export class MovieInformationPanelComponent implements OnInit { public ratings: IMovieRatings; public streams: IStreamingData[]; + public RequestSource = RequestSource; public baseUrl: string; diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index d0e282dce..ad4aeaae2 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource":"Source:" }, "Discovery": { "PopularTab": "Popular", From 0329c2b9d97d8e65b16df807361459874533392b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Apr 2022 12:44:36 +0100 Subject: [PATCH 119/210] Added Tv watchlist import --- src/Ombi.Core/Engine/TvRequestEngine.cs | 2 +- .../Helpers/TvShowRequestBuilderV2.cs | 5 +- .../Models/Requests/TvRequestViewModelV2.cs | 2 + .../PlexWatchlistImportTests.cs | 142 ++++++++++++++++++ .../Jobs/Plex/PlexWatchlistImport.cs | 47 ++++-- .../tv-requests-panel.component.html | 1 + .../tv-requests-panel.component.ts | 4 +- 7 files changed, 184 insertions(+), 19 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index c3828eae3..5664d276f 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -188,7 +188,7 @@ namespace Ombi.Core.Engine (await tvBuilder .GetShowInfo(tv.TheMovieDbId, tv.languageCode)) .CreateTvList(tv) - .CreateChild(tv, canRequestOnBehalf ? tv.RequestOnBehalf : user.Id); + .CreateChild(tv, canRequestOnBehalf ? tv.RequestOnBehalf : user.Id, tv.Source); await tvBuilder.BuildEpisodes(tv); diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs index 6843332c0..4053109da 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs @@ -53,7 +53,7 @@ namespace Ombi.Core.Helpers return this; } - public TvShowRequestBuilderV2 CreateChild(TvRequestViewModelV2 model, string userId) + public TvShowRequestBuilderV2 CreateChild(TvRequestViewModelV2 model, string userId, RequestSource source) { var animationGenre = TheMovieDbRecord.genres?.Any(s => s.name.Equals("Animation", StringComparison.InvariantCultureIgnoreCase)) ?? false; var animeKeyword = TheMovieDbRecord.Keywords?.KeywordsValue?.Any(s => s.Name.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ?? false; @@ -68,7 +68,8 @@ namespace Ombi.Core.Helpers Title = TheMovieDbRecord.name, ReleaseYear = FirstAir, RequestedByAlias = model.RequestedByAlias, - SeriesType = animationGenre && animeKeyword ? SeriesType.Anime : SeriesType.Standard + SeriesType = animationGenre && animeKeyword ? SeriesType.Anime : SeriesType.Standard, + Source = source }; return this; diff --git a/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs index a9742fb32..e1df9553f 100644 --- a/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs +++ b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; +using Ombi.Store.Entities.Requests; namespace Ombi.Core.Models.Requests { @@ -7,5 +8,6 @@ namespace Ombi.Core.Models.Requests { public int TheMovieDbId { get; set; } public string languageCode { get; set; } = "en"; + public RequestSource Source { get; set; } = RequestSource.Ombi; } } \ No newline at end of file diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index 7f3e0ccbd..b4759e280 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -136,6 +136,54 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); } + + [Test] + public async Task TvRequestFromWatchList_NoGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "show", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + } + [Test] public async Task MovieRequestFromWatchList_AlreadyRequested() { @@ -183,6 +231,53 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); } + [Test] + public async Task TvRequestFromWatchList_AlreadyRequested() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "show", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { ErrorCode = ErrorCode.AlreadyRequested, ErrorMessage = "Requested" }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + } + [Test] public async Task MovieRequestFromWatchList_NoTmdbGuid() { @@ -229,5 +324,52 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); } + + [Test] + public async Task TvRequestFromWatchList_NoTmdbGuid() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "imdb://123" + } + } + } + } + + } + }); + _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) + .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestTvShow(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index b07e95da0..10e34bf20 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -4,6 +4,7 @@ using Ombi.Api.Plex.Models; using Ombi.Core.Authentication; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models.Requests; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -23,16 +24,18 @@ namespace Ombi.Schedule.Jobs.Plex private readonly ISettingsService _settings; private readonly OmbiUserManager _ombiUserManager; private readonly IMovieRequestEngine _movieRequestEngine; + private readonly ITvRequestEngine _tvRequestEngine; private readonly ILogger _logger; public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, - IMovieRequestEngine movieRequestEngine, + IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, ILogger logger) { _plexApi = plexApi; _settings = settings; _ombiUserManager = ombiUserManager; _movieRequestEngine = movieRequestEngine; + _tvRequestEngine = tvRequestEngine; _logger = logger; } @@ -56,29 +59,48 @@ namespace Ombi.Schedule.Jobs.Plex var items = watchlist.MediaContainer.Metadata; foreach (var item in items) { + var providerIds = await GetProviderIds(user.MediaServerToken, item, context?.CancellationToken ?? CancellationToken.None); + if (!providerIds.TheMovieDb.HasValue()) + { + // We need a MovieDbId to support this; + return; + } switch (item.type) { case "show": - await ProcessShow(item); + await ProcessShow(int.Parse(providerIds.TheMovieDb), user, context?.CancellationToken ?? CancellationToken.None); break; case "movie": - await ProcessMovie(user.MediaServerToken, item, user, context?.CancellationToken ?? CancellationToken.None); + await ProcessMovie(int.Parse(providerIds.TheMovieDb), user, context?.CancellationToken ?? CancellationToken.None); break; } } } } - private async Task ProcessMovie(string authToken, Metadata movie, OmbiUser user, CancellationToken cancellationToken) + private async Task ProcessMovie(int theMovieDbId, OmbiUser user, CancellationToken cancellationToken) { - var providerIds = await GetProviderIds(authToken, movie, cancellationToken); - if (!providerIds.TheMovieDb.HasValue()) + _movieRequestEngine.SetUser(user); + var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist}); + if (response.IsError) { - // We need a MovieDbId to support this; - return; + if (response.ErrorCode == ErrorCode.AlreadyRequested) + { + return; + } + _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); } - _movieRequestEngine.SetUser(user); - var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = int.Parse(providerIds.TheMovieDb), Source = RequestSource.PlexWatchlist}); + else + { + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); + } + } + + + private async Task ProcessShow(int theMovieDbId, OmbiUser user, CancellationToken cancellationToken) + { + _tvRequestEngine.SetUser(user); + var response = await _tvRequestEngine.RequestTvShow(new TvRequestViewModelV2 { RequestAll = true, TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); if (response.IsError) { if (response.ErrorCode == ErrorCode.AlreadyRequested) @@ -122,11 +144,6 @@ namespace Ombi.Schedule.Jobs.Plex return providerIds; } - private async Task ProcessShow(Metadata metadata) - { - - } - public void Dispose() { } } } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html index 4098bb748..8356aecb2 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html @@ -9,6 +9,7 @@ user: request.requestedUser.userAlias, date: request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' } }} - {{request.deniedReason}} + {{'MediaDetails.RequestSource' | translate }} {{RequestSource[request.source]}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts index 2de85814c..e397e60ea 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from "@angular/core"; -import { IChildRequests, RequestType } from "../../../../../interfaces"; +import { IChildRequests, RequestSource, RequestType } from "../../../../../interfaces"; import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component"; import { MatDialog } from "@angular/material/dialog"; @@ -17,6 +17,8 @@ export class TvRequestsPanelComponent { @Input() public isAdmin: boolean; @Input() public manageOwnRequests: boolean; + public RequestSource = RequestSource; + public displayedColumns: string[] = ['number', 'title', 'airDate', 'status']; constructor(private requestService: RequestService, From 75356b44c7aea564e6d5df428822636c7603d66a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Apr 2022 12:52:09 +0100 Subject: [PATCH 120/210] Added migrations for mysql --- .../20220407114744_PlexIds.Designer.cs | 535 +++++++ .../ExternalMySql/20220407114744_PlexIds.cs | 176 +++ .../ExternalMySqlContextModelSnapshot.cs | 33 +- .../20220407114619_RequestSource.Designer.cs | 1285 +++++++++++++++++ .../OmbiMySql/20220407114619_RequestSource.cs | 59 + .../OmbiMySqlContextModelSnapshot.cs | 12 + .../tv-requests-panel.component.html | 2 +- 7 files changed, 2084 insertions(+), 18 deletions(-) create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs create mode 100644 src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs new file mode 100644 index 000000000..e0ca84108 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.Designer.cs @@ -0,0 +1,535 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220407114744_PlexIds")] + partial class PlexIds + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("PlexContentId") + .HasColumnType("longtext"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs new file mode 100644 index 000000000..826260c93 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220407114744_PlexIds.cs @@ -0,0 +1,176 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class PlexIds : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "varchar(255)", + nullable: false, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "longtext", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "varchar(255)", + nullable: true, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexServerContent", + type: "int", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255)") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SeasonKey", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PlexContentId", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexSeasonsContent", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ParentKey", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "GrandparentKey", + table: "PlexEpisode", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(string), + oldType: "varchar(255)", + oldNullable: true) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey", + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs index b75c45665..f55793b72 100644 --- a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -276,14 +276,14 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("EpisodeNumber") .HasColumnType("int"); - b.Property("GrandparentKey") - .HasColumnType("int"); + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); - b.Property("Key") - .HasColumnType("int"); + b.Property("Key") + .HasColumnType("longtext"); - b.Property("ParentKey") - .HasColumnType("int"); + b.Property("ParentKey") + .HasColumnType("longtext"); b.Property("SeasonNumber") .HasColumnType("int"); @@ -304,17 +304,17 @@ namespace Ombi.Store.Migrations.ExternalMySql .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("ParentKey") - .HasColumnType("int"); + b.Property("ParentKey") + .HasColumnType("longtext"); - b.Property("PlexContentId") - .HasColumnType("int"); + b.Property("PlexContentId") + .HasColumnType("longtext"); b.Property("PlexServerContentId") .HasColumnType("int"); - b.Property("SeasonKey") - .HasColumnType("int"); + b.Property("SeasonKey") + .HasColumnType("longtext"); b.Property("SeasonNumber") .HasColumnType("int"); @@ -341,8 +341,9 @@ namespace Ombi.Store.Migrations.ExternalMySql b.Property("ImdbId") .HasColumnType("longtext"); - b.Property("Key") - .HasColumnType("int"); + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); b.Property("Quality") .HasColumnType("longtext"); @@ -498,9 +499,7 @@ namespace Ombi.Store.Migrations.ExternalMySql b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") .WithMany("Episodes") .HasForeignKey("GrandparentKey") - .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasPrincipalKey("Key"); b.Navigation("Series"); }); diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs new file mode 100644 index 000000000..c4d1fd2f1 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.Designer.cs @@ -0,0 +1,1285 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20220407114619_RequestSource")] + partial class RequestSource + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("EpisodeRequestLimitType") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MediaServerToken") + .HasColumnType("longtext"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MovieRequestLimitType") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimitType") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + 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() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Approved4K") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Available4K") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("Denied4K") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DeniedReason4K") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Has4KRequest") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsApproved4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable4K") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied4K") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedDate4k") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Source") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("LanguageProfile") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs new file mode 100644 index 000000000..1020b4d63 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20220407114619_RequestSource.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class RequestSource : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Source", + table: "MovieRequests", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Source", + table: "ChildRequests", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "MediaServerToken", + table: "AspNetUsers", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Source", + table: "AlbumRequests", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Source", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "Source", + table: "ChildRequests"); + + migrationBuilder.DropColumn( + name: "MediaServerToken", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Source", + table: "AlbumRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 5a5c28b40..e66e29521 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -283,6 +283,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("LockoutEnd") .HasColumnType("datetime(6)"); + b.Property("MediaServerToken") + .HasColumnType("longtext"); + b.Property("MovieRequestLimit") .HasColumnType("int"); @@ -468,6 +471,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("RequestedUserId") .HasColumnType("varchar(255)"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Title") .HasColumnType("longtext"); @@ -526,6 +532,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("SeriesType") .HasColumnType("int"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Title") .HasColumnType("longtext"); @@ -728,6 +737,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("RootPathOverride") .HasColumnType("int"); + b.Property("Source") + .HasColumnType("int"); + b.Property("Status") .HasColumnType("longtext"); diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html index 8356aecb2..ea34849d0 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.html @@ -9,7 +9,7 @@ user: request.requestedUser.userAlias, date: request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' } }} - {{request.deniedReason}} - {{'MediaDetails.RequestSource' | translate }} {{RequestSource[request.source]}} +  {{'MediaDetails.RequestSource' | translate }} {{RequestSource[request.source]}} From 4509a0aed6ed03043b88e5e210bffc48fa345294 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 7 Apr 2022 13:14:46 +0100 Subject: [PATCH 121/210] automation improvements --- tests/cypress/tests/requests/requests.spec.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/cypress/tests/requests/requests.spec.ts b/tests/cypress/tests/requests/requests.spec.ts index fc1a7489c..c161d0645 100644 --- a/tests/cypress/tests/requests/requests.spec.ts +++ b/tests/cypress/tests/requests/requests.spec.ts @@ -9,22 +9,27 @@ describe("Requests Tests", () => { cy.intercept("token").as("login"); cy.login(); - cy.requestAllTv(60735); // The Flash + const dbID = 60735; // The Flash + cy.requestAllTv(dbID); Page.visit(); Page.tvTab.click(); - const row = Page.tv.getGridRow(60735); + cy.waitUntil(() => { + const row = Page.tv.getGridRow(dbID); + return row.detailsButton.should("be.visible"); + }); + const row = Page.tv.getGridRow(dbID); row.detailsButton.click(); - cy.location("pathname").should("contains", "/details/tv/60735"); + cy.location("pathname").should("contains", "/details/tv/" + dbID); TvPage.title.contains("The Flash"); }); it("Deleting TV requests, removes from grid", () => { cy.intercept("POST", "request/tv").as("tvRequest"); cy.intercept("token").as("login"); - cy.intercept('DELETE', 'Request/tv/child/60735').as('deleteRequest'); + cy.intercept('DELETE','api/v1/Request/tv/child/60735').as('deleteRequest'); cy.login(); // cy.wait('@login'); From d933196cf0ccfcbc9663aaf1dab22685526d1936 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Thu, 7 Apr 2022 12:33:09 +0000 Subject: [PATCH 122/210] chore(release): :rocket: v4.16.0 --- CHANGELOG.md | 8 ++++---- version.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4e990da1..46ba44d3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# [4.16.0](https://github.com/Ombi-app/Ombi/compare/v4.15.6...v4.16.0) (2022-04-07) + + + ## [4.15.6](https://github.com/Ombi-app/Ombi/compare/v4.15.5...v4.15.6) (2022-04-07) @@ -323,7 +327,3 @@ -## [4.8.1](https://github.com/Ombi-app/Ombi/compare/v4.8.0...v4.8.1) (2022-01-04) - - - diff --git a/version.json b/version.json index 6f0b0f8a4..3445af871 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.15.6" + "version": "4.16.0" } \ No newline at end of file From d1152ab7674243daa528c524c0cdc87d81ad49c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:55:55 +0100 Subject: [PATCH 123/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/fr.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index ab2bdff7c..2a3d56d9d 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -379,7 +379,8 @@ "Country": "Pays :", "StartDate": "Date de début :", "EndDate": "Date de fin :" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populaire", From 8297db91e85da308bde6fb09ad78347dee063630 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:55:56 +0100 Subject: [PATCH 124/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 756c2658c..33feef3b6 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -379,7 +379,8 @@ "Country": "Kraj:", "StartDate": "Data rozpoczęcia:", "EndDate": "Data zakończenia:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popularne", From 4881775eda69a8f136ce0d8fbbf970e3d0406dc9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:55:57 +0100 Subject: [PATCH 125/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/zh-TW.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/zh-TW.json b/src/Ombi/wwwroot/translations/zh-TW.json index 9dfa34248..f5ed12a34 100644 --- a/src/Ombi/wwwroot/translations/zh-TW.json +++ b/src/Ombi/wwwroot/translations/zh-TW.json @@ -379,7 +379,8 @@ "Country": "国家:", "StartDate": "开始日期:", "EndDate": "结束日期:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "热门", From 94b16dfe09bf1d2cd6286777d74eb5d4496abbbb Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:55:58 +0100 Subject: [PATCH 126/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/zh.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/zh.json b/src/Ombi/wwwroot/translations/zh.json index bc993ca0e..ce9ea5970 100644 --- a/src/Ombi/wwwroot/translations/zh.json +++ b/src/Ombi/wwwroot/translations/zh.json @@ -379,7 +379,8 @@ "Country": "国家:", "StartDate": "开始日期:", "EndDate": "结束日期:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "热门", From f428ce6a700c081437703839bc84d2f2b1138bcc Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:55:59 +0100 Subject: [PATCH 127/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/sv.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 03caceb46..5ced30e09 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populära", From ac8b16a3051ad71dbd54a8973c7dd847b564a515 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:02 +0100 Subject: [PATCH 128/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/sk.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 79b08263e..925decf6c 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -379,7 +379,8 @@ "Country": "Krajina:", "StartDate": "Dátum začatia:", "EndDate": "Dátum ukončenia:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populárne", From 24eb842fc4424f7bcc3ec2949d7f5472492e96f6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:03 +0100 Subject: [PATCH 129/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/ru.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 9af1e31fc..64314fbd4 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Популярное", From 698a23fb83f323cdd1dd57cb49803079d44214a7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:04 +0100 Subject: [PATCH 130/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index 736330eb9..a94be05ec 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popular", From 01047a3fd67153f3ff16f860d2c7b50213e8d9b2 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:05 +0100 Subject: [PATCH 131/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/no.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index ab409a431..7dc8dfda4 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populært", From 8a9e7ea588aefbcd73ed82625887e3614e1703ea Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:07 +0100 Subject: [PATCH 132/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/es.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index fb2ba4149..e0bbe9da0 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -379,7 +379,8 @@ "Country": "País:", "StartDate": "Fecha de inicio:", "EndDate": "Fecha de finalización:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popular", From d5bf9692ce1fc0ccfe7beca6dd200c78be177bdc Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:08 +0100 Subject: [PATCH 133/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/nl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 33e311928..62b8afb35 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populair", From 6c0a5dadd4b8f37760252eb0fe7f88908f55506d Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:11 +0100 Subject: [PATCH 134/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index ed69c02e0..8d80fe1db 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -379,7 +379,8 @@ "Country": "Paese:", "StartDate": "Data Iniziale:", "EndDate": "Data Finale:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popolare", From 30e3417285a4eed18d429d7776f0e74096e834c0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:12 +0100 Subject: [PATCH 135/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/hu.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 45d8622a5..187af76f0 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -379,7 +379,8 @@ "Country": "Ország:", "StartDate": "Kezdés dátuma:", "EndDate": "Befejezés dátuma:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Népszerű", From 289ab77b0e04aae235b6f6cebc86e0a8d1f0cf2b Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:13 +0100 Subject: [PATCH 136/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 18c5450c7..d793598b1 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -379,7 +379,8 @@ "Country": "Land:", "StartDate": "Startdatum:", "EndDate": "Enddatum:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Beliebt", From 8c4c0b262978c1303767af360d802c4b4c2b4d24 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:16 +0100 Subject: [PATCH 137/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/da.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 63869300b..e44241e6d 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -379,7 +379,8 @@ "Country": "Land:", "StartDate": "Startdato:", "EndDate": "Slutdato:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Populære", From 0b9596d807178f5e071113ec0347868ec7f0960b Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:17 +0100 Subject: [PATCH 138/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/cs.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index d0dadf58c..1b27bd557 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -379,7 +379,8 @@ "Country": "Stát:", "StartDate": "Datum zahájení:", "EndDate": "Datum ukončení:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Oblíbené", From d43451405be489254d7cdc7755d5f516a1e495a5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:18 +0100 Subject: [PATCH 139/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/bg.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index 789af74df..3b3b73055 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Популярни", From 5826e2d9a1c3f1210a87fa270dc0c81bac32944a Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 13:56:19 +0100 Subject: [PATCH 140/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt-BR.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt-BR.json b/src/Ombi/wwwroot/translations/pt-BR.json index 899c42281..3c9b6a523 100644 --- a/src/Ombi/wwwroot/translations/pt-BR.json +++ b/src/Ombi/wwwroot/translations/pt-BR.json @@ -379,7 +379,8 @@ "Country": "Country:", "StartDate": "Start Date:", "EndDate": "EndDate:" - } + }, + "RequestSource": "Source:" }, "Discovery": { "PopularTab": "Popular", From 63996437a02fe10ffae6822ffa15369bec0a6b36 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 14:54:34 +0100 Subject: [PATCH 141/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 2a3d56d9d..2c0f012a7 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -380,7 +380,7 @@ "StartDate": "Date de début :", "EndDate": "Date de fin :" }, - "RequestSource": "Source:" + "RequestSource": "Source :" }, "Discovery": { "PopularTab": "Populaire", From 0c31e628df376aac6d56ae67c7c705a9a4a7c080 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 14:54:36 +0100 Subject: [PATCH 142/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index d793598b1..279751779 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -433,7 +433,7 @@ "2": "Plex User", "3": "Emby User", "4": "Emby Connect User", - "5": "Jellyfin User" + "5": "Jellyfin Server" }, "Paginator": { "itemsPerPageLabel": "Elemente pro Seite:", From fa1017422c4efd4b0897871bd3c671151774d7c3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 14:54:37 +0100 Subject: [PATCH 143/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 8d80fe1db..27d310604 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -380,7 +380,7 @@ "StartDate": "Data Iniziale:", "EndDate": "Data Finale:" }, - "RequestSource": "Source:" + "RequestSource": "Sorgente:" }, "Discovery": { "PopularTab": "Popolare", From 1a6b95d45c220310213b8d811272a63f0f6ff42b Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 14:54:38 +0100 Subject: [PATCH 144/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index a94be05ec..5b9096392 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -380,7 +380,7 @@ "StartDate": "Start Date:", "EndDate": "EndDate:" }, - "RequestSource": "Source:" + "RequestSource": "Origem:" }, "Discovery": { "PopularTab": "Popular", From d7fea7843aaaab7ddff8dc31ca6d2a9117471dcc Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 16:05:36 +0100 Subject: [PATCH 145/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/sv.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 5ced30e09..59ee9c798 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -380,7 +380,7 @@ "StartDate": "Start Date:", "EndDate": "EndDate:" }, - "RequestSource": "Source:" + "RequestSource": "Källa:" }, "Discovery": { "PopularTab": "Populära", From 33f4cf2c6182aab74c166c6e4e6a6d308feeb57c Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Thu, 7 Apr 2022 18:02:23 +0200 Subject: [PATCH 146/210] Fix incorrect request status for denied movies in discover card --- .../discover/components/card/discover-card.component.scss | 4 ++++ .../discover/components/card/discover-card.component.ts | 7 +++++++ .../ClientApp/src/app/interfaces/ISearchMovieResultV2.ts | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss index f1ca4774e..c228031b2 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss @@ -216,6 +216,10 @@ small { background-color: #ff5722; } +.top-right.denied span.indicator:before{ + background-color: #ff5722; +} + .top-right.partly-available span.indicator:before{ background-color: #ffd740; } diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 48ac6feed..6aee9f4e5 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -98,6 +98,9 @@ export class DiscoverCardComponent implements OnInit { if (this.result.approved) { return "approved"; } + if (this.result.denied) { + return "denied"; + } if (this.result.requested) { return "requested"; } @@ -114,6 +117,9 @@ export class DiscoverCardComponent implements OnInit { if (this.result.approved) { return this.translate.instant("Common.Approved"); } + if (this.result.denied) { + return this.translate.instant("Common.Denied"); + } if (this.result.requested) { return this.translate.instant("Common.Pending"); } @@ -180,6 +186,7 @@ export class DiscoverCardComponent implements OnInit { this.result.available = updated.available || updated.available4K; this.result.requested = updated.requested || updated.has4KRequest; this.result.approved = updated.approved || updated.available4K; + this.result.denied = updated.denied || updated.denied4K; this.result.rating = updated.voteAverage; this.result.overview = updated.overview; this.result.imdbid = updated.imdbId; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts index d4faf5bfe..937234c42 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts @@ -23,6 +23,8 @@ homepage: string; imdbId: string; approved: boolean; + denied: boolean; + deniedReason: string; requested: boolean; requestId: number; available: boolean; From 01546a0f7f86379528b486463246ef9bdfb9033e Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 7 Apr 2022 17:03:29 +0100 Subject: [PATCH 147/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 279751779..c3a4edade 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -228,7 +228,7 @@ "NoPermissionsOnBehalf": "Sie haben nicht die richtigen Berechtigungen, um im Namen von Benutzern anzufragen!", "NoPermissions": "Sie haben nicht die nötigen Rechte!", "RequestDoesNotExist": "Die Anfrage existiert nicht", - "ChildRequestDoesNotExist": "Child Request does not exist", + "ChildRequestDoesNotExist": "Untergeordnete Anfrage existiert nicht", "NoPermissionsRequestMovie": "Sie haben keine Berechtigung, um einen Film anzufordern", "NoPermissionsRequestTV": "Sie haben keine Berechtigung, um eine TV-Sendung anzufordern", "NoPermissionsRequestAlbum": "Sie haben keine Berechtigung, um ein Album anzufordern", @@ -380,7 +380,7 @@ "StartDate": "Startdatum:", "EndDate": "Enddatum:" }, - "RequestSource": "Source:" + "RequestSource": "Quelle:" }, "Discovery": { "PopularTab": "Beliebt", From 0523c9a3f157b81ce3dc8b526bdcba50a2d0b2ce Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Thu, 7 Apr 2022 18:43:13 +0200 Subject: [PATCH 148/210] Enhance display of denied TV shows --- src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs | 3 +++ src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs | 1 + .../Models/Search/V2/SearchFullInfoTvShowViewModel.cs | 1 + src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs | 6 ++++++ .../app/discover/components/card/discover-card.component.ts | 1 + src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts | 3 +++ .../media-details/components/tv/tv-details.component.html | 6 +++++- 7 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 46cd44bf1..1ebfe0003 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -308,6 +308,9 @@ namespace Ombi.Core.Engine.V2 item.PartlyAvailable = oldModel.PartlyAvailable; item.Requested = oldModel.Requested; item.Available = oldModel.Available; + item.Denied = oldModel.Denied; + item.DeniedReason = oldModel.DeniedReason; + item.FullyDenied = oldModel.FullyDenied; item.Approved = oldModel.Approved; item.SeasonRequests = oldModel.SeasonRequests; item.RequestId = oldModel.RequestId; diff --git a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs index 1a3f47175..96a98f5d7 100644 --- a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs @@ -56,6 +56,7 @@ namespace Ombi.Core.Models.Search public bool FullyAvailable { get; set; } // We only have some episodes public bool PartlyAvailable { get; set; } + public bool FullyDenied { get; set; } public override RequestType Type => RequestType.TvShow; public string BackdropPath { get; set; } diff --git a/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs b/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs index 0902c1fb1..179178c3e 100644 --- a/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs +++ b/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs @@ -48,6 +48,7 @@ namespace Ombi.Core.Models.Search.V2 public bool FullyAvailable { get; set; } // We only have some episodes public bool PartlyAvailable { get; set; } + public bool FullyDenied { get; set; } public override RequestType Type => RequestType.TvShow; } diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index a9bf13265..b3e08257e 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -62,6 +62,7 @@ namespace Ombi.Core.Rule.Rules.Search request.Requested = true; request.Approved = tvRequests.ChildRequests.Any(x => x.Approved); request.Denied = tvRequests.ChildRequests.Any(x => x.Denied ?? false); + request.DeniedReason = tvRequests.ChildRequests.FirstOrDefault(x => x.Denied == true).DeniedReason; // Let's modify the seasonsrequested to reflect what we have requested... foreach (var season in request.SeasonRequests) @@ -100,6 +101,11 @@ namespace Ombi.Core.Rule.Rules.Search request.PartlyAvailable = true; } + if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Denied ?? false))) + { + request.FullyDenied = true; + } + var hasUnairedRequests = request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.AirDate >= DateTime.UtcNow)); if (request.FullyAvailable) diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 48ac6feed..4af3fdabb 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -206,6 +206,7 @@ export class DiscoverCardComponent implements OnInit { this.result.overview = updated.overview; this.result.approved = updated.approved; this.result.available = updated.fullyAvailable; + this.result.denied = updated.fullyDenied; this.fullyLoaded = true; } diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts index 8ea7bacc5..ad15306f4 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts @@ -25,6 +25,9 @@ export interface ISearchTvResultV2 { seasonRequests: INewSeasonRequests[]; requestAll: boolean; approved: boolean; + denied: boolean; + deniedReason: string; + fullyDenied: boolean; requested: boolean; available: boolean; plexUrl: string; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html index 9397e07b8..091f38f29 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html @@ -65,7 +65,7 @@ (click)="request()"> {{ 'Common.Request' | translate }} - @@ -82,6 +82,10 @@ class="btn-spacing" color="accent" [disabled]> {{'Common.PartiallyAvailable' | translate }} + + - @@ -83,7 +83,7 @@ {{'Common.PartiallyAvailable' | translate }} - From 6398f6a4f7755281ebeac537e3ff623df5cfa0f3 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 8 Apr 2022 08:26:10 +0100 Subject: [PATCH 158/210] fix(plex-watchlist): :bug: Fixed the issue where the watchlist didn't work for users logging in via OAuth --- .../src/app/wizard/createadmin/createadmin.component.html | 2 +- .../src/app/wizard/ombiconfig/ombiconfig.component.html | 2 +- .../ClientApp/src/app/wizard/welcome/welcome.component.html | 2 +- src/Ombi/Controllers/V1/TokenController.cs | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html index ff44f7093..5d79f5ebd 100644 --- a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.html @@ -1,6 +1,6 @@ 
- +
diff --git a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html index 33d15bb58..a8d7d212e 100644 --- a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html @@ -1,6 +1,6 @@ 
- +
diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html index 7ca3de4ce..f32e59b8d 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html @@ -67,7 +67,7 @@ Done
- +
diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index 588c4f606..1dd08fcbe 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -200,6 +200,9 @@ namespace Ombi.Controllers.V1 } } + user.MediaServerToken = account.user.authentication_token; + await _userManager.UpdateAsync(user); + return await CreateToken(true, user); } From 7eedf5876be2d22124b60fec22ab219f531d451c Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 8 Apr 2022 08:08:14 +0000 Subject: [PATCH 159/210] chore(release): :rocket: v4.16.3 --- CHANGELOG.md | 20 +++++++++----------- version.json | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671d0e414..6d02be3fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.16.3](https://github.com/Ombi-app/Ombi/compare/v4.16.2...v4.16.3) (2022-04-08) + + +### Bug Fixes + +* **plex-watchlist:** :bug: Fixed the issue where the watchlist didn't work for users logging in via OAuth ([6398f6a](https://github.com/Ombi-app/Ombi/commit/6398f6a4f7755281ebeac537e3ff623df5cfa0f3)) + + + ## [4.16.2](https://github.com/Ombi-app/Ombi/compare/v4.16.1...v4.16.2) (2022-04-07) @@ -309,14 +318,3 @@ -## [4.9.2](https://github.com/Ombi-app/Ombi/compare/v4.9.1...v4.9.2) (2022-01-14) - - -### Bug Fixes - -* :bug: Add UI for Emby recently added cronjob settings ([#4469](https://github.com/Ombi-app/Ombi/issues/4469)) ([7d47bbe](https://github.com/Ombi-app/Ombi/commit/7d47bbe92204855bf75d70b8fa548f9c3f3612bc)) -* **sonarr:** :bug: Fixed an issue where we could attempt to add a series to sonarr before sonarr has got all the metadata [#4459](https://github.com/Ombi-app/Ombi/issues/4459) ([5c691dc](https://github.com/Ombi-app/Ombi/commit/5c691dc98437a4cd24560ff625414fe05dd22f89)) -* **wizard:** :bug: Fixed the issue where the Application Url wasn't validated in the wizard ([33b8d11](https://github.com/Ombi-app/Ombi/commit/33b8d1111a1c6663d8c0bbd912be4660da7d013f)), closes [#4417](https://github.com/Ombi-app/Ombi/issues/4417) - - - diff --git a/version.json b/version.json index 7eeb9e555..a2796d255 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.2" + "version": "4.16.3" } \ No newline at end of file From 448f196165a2653c87b78f1b56398031c013d63e Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 8 Apr 2022 11:13:52 +0200 Subject: [PATCH 160/210] Add Deny option to requests list --- .../movies-grid/movies-grid.component.html | 6 +- .../movies-grid/movies-grid.component.ts | 67 ++++++++++++++----- .../options/request-options.component.html | 12 +++- .../options/request-options.component.ts | 29 ++++++-- .../components/requests-list.component.ts | 5 ++ .../app/requests-list/models/UpdateType.ts | 3 +- src/Ombi/wwwroot/translations/en.json | 5 +- 7 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html index d9366e7d1..d95460b40 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html @@ -98,7 +98,9 @@ - - + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index 8b4ae170a..ca36a5d62 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -62,11 +62,11 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.manageOwnRequests = this.auth.hasRole("ManageOwnRequests") if (this.isAdmin) { this.displayedColumns.unshift('select'); - } - + } + this.is4kEnabled = this.featureFacade.is4kEnabled(); if ((this.isAdmin || this.auth.hasRole("Request4KMovie")) - && this.is4kEnabled) { + && this.is4kEnabled) { this.displayedColumns.splice(4, 0, 'has4kRequest'); } @@ -155,13 +155,13 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { private checkDate(date: Date|string): boolean { if (typeof date === 'string') { - return new Date(date).getFullYear() > 1; + return new Date(date).getFullYear() > 1; } if (date instanceof Date) { - return date.getFullYear() > 1; + return date.getFullYear() > 1; } return false; - } + } public switchFilter(type: RequestFilterType) { this.currentFilter = type; @@ -172,15 +172,15 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { const numSelected = this.selection.selected.length; const numRows = this.dataSource.data.length; return numSelected === numRows; - } + } - public masterToggle() { + public masterToggle() { this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach(row => this.selection.select(row)); - } + } - public async bulkDelete() { + public async bulkDelete() { if (this.selection.isEmpty()) { return; } @@ -194,13 +194,13 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.selection.clear(); this.ngAfterViewInit(); }); - } + } - public bulkApprove = () => this.bulkApproveInternal(false); + public bulkApprove = () => this.bulkApproveInternal(false); - public bulkApprove4K = () => this.bulkApproveInternal(true); + public bulkApprove4K = () => this.bulkApproveInternal(true); - private bulkApproveInternal(is4k: boolean) { + private bulkApproveInternal(is4k: boolean) { if (this.selection.isEmpty()) { return; } @@ -222,12 +222,45 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { this.selection.clear(); this.ngAfterViewInit(); }) - } + } + + public bulkDeny = () => this.bulkDenyInternal(false); + + public bulkDeny4K = () => this.bulkDenyInternal(true); + + private bulkDenyInternal(is4k: boolean) { + if (this.selection.isEmpty()) { + return; + } + let tasks = new Array>(); + this.selection.selected.forEach((selected) => { + + tasks.push(this.requestServiceV1.denyMovie({ + id: selected.id, + is4K: is4k, + reason: `` // TOOD: reuse DenyDialog to allow for a reason to be entered + })); + }); + + this.isLoadingResults = true; + forkJoin(tasks).subscribe((result: IRequestEngineResult[]) => { + this.isLoadingResults = false; + const failed = result.filter(x => !x.result); + if (failed.length > 0) { + this.notification.error("Some requests failed to deny: " + failed[0].errorMessage); + this.selection.clear(); + return; + } + this.notification.success(this.translateService.instant('Requests.RequestPanel.Denied')); + this.selection.clear(); + this.ngAfterViewInit(); + }) + } - public getRequestDate(request: IMovieRequests) : Date { + public getRequestDate(request: IMovieRequests): Date { if (new Date(request.requestedDate).getFullYear() === 1) { return request.requestedDate4k; } return request.requestedDate; - } + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html index dc1c04467..b32c872ac 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -1,14 +1,20 @@ - - {{'Requests.RequestPanel.Delete' | translate}} - {{'Requests.RequestPanel.Approve' | translate}} + + {{'Requests.RequestPanel.Deny' | translate}} + {{'Requests.RequestPanel.Approve4K' | translate}} + + {{'Requests.RequestPanel.Deny4K' | translate}} + {{'Requests.RequestPanel.ChangeAvailability' | translate}} + + {{'Requests.RequestPanel.Delete' | translate}} + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index b3de64235..909c34544 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -5,6 +5,8 @@ import { IRequestEngineResult, RequestType } from '../../../interfaces'; import { UpdateType } from '../../models/UpdateType'; import { TranslateService } from '@ngx-translate/core'; import { firstValueFrom, Observable } from 'rxjs'; +import { DenyDialogComponent } from '../../../media-details/components/shared/deny-dialog/deny-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; @Component({ selector: 'request-options', @@ -17,6 +19,7 @@ export class RequestOptionsComponent { constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any, private requestService: RequestService, private messageService: MessageService, + public dialog: MatDialog, private bottomSheetRef: MatBottomSheetRef, private translate: TranslateService) { } @@ -33,11 +36,11 @@ export class RequestOptionsComponent { } request.subscribe(result => { if (result.result) { - this.messageService.send(this.translate.instant("Requests.SuccessfullyDeleted")); - this.bottomSheetRef.dismiss({type: UpdateType.Delete}); - return; + this.messageService.send(this.translate.instant("Requests.SuccessfullyDeleted")); + this.bottomSheetRef.dismiss({type: UpdateType.Delete}); + return; } else { - this.messageService.sendRequestEngineResultError(result); + this.messageService.sendRequestEngineResultError(result); } }); } @@ -57,6 +60,24 @@ export class RequestOptionsComponent { return; } + public deny = () => this.denyInternal(false); + + public deny4K = () => this.denyInternal(true); + + private async denyInternal(is4K: boolean) { + const dialogRef = this.dialog.open(DenyDialogComponent, { + width: '250px', + data: { requestId: this.data.id, is4K: is4K, requestType: this.data.type } + }); + + dialogRef.afterClosed().subscribe(result => { + if (result.denied) { + this.bottomSheetRef.dismiss({ type: UpdateType.Deny }); + + } + }); + } + public async approve4K() { if (this.data.type != RequestType.movie) { return; diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts index 8117e0c22..4ea6e4886 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts @@ -35,6 +35,11 @@ export class RequestsListComponent { event.onChange(); return; } + if (result.type == UpdateType.Deny) { + event.request.requestStatus = 'Common.Denied'; + event.onChange(); + return; + } }); } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts index 3a0f690db..9e54b1114 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts @@ -1,5 +1,6 @@ export enum UpdateType { Delete, Approve, - Availability + Availability, + Deny } \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index ad4aeaae2..a9c40c197 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete":"Delete Request", "Approve":"Approve Request", + "Deny":"Deny Request", "Approve4K":"Approve 4K Request", + "Deny4K":"Deny 4K Request", "ChangeAvailability":"Mark Available", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 2770de01d7da977eefc5ca62f80791f6defdcae2 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 8 Apr 2022 14:13:20 +0100 Subject: [PATCH 161/210] bug(watchlist): Added more logging around the watchlist feature for better debugging --- .../Jobs/Plex/PlexWatchlistImport.cs | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 10e34bf20..d1217c8b5 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; using Ombi.Api.Plex; using Ombi.Api.Plex.Models; using Ombi.Core.Authentication; @@ -8,9 +9,11 @@ using Ombi.Core.Models.Requests; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; +using Ombi.Hubs; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Quartz; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -25,10 +28,11 @@ namespace Ombi.Schedule.Jobs.Plex private readonly OmbiUserManager _ombiUserManager; private readonly IMovieRequestEngine _movieRequestEngine; private readonly ITvRequestEngine _tvRequestEngine; + private readonly IHubContext _hub; private readonly ILogger _logger; public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, - IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, + IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IHubContext hub, ILogger logger) { _plexApi = plexApi; @@ -36,6 +40,7 @@ namespace Ombi.Schedule.Jobs.Plex _ombiUserManager = ombiUserManager; _movieRequestEngine = movieRequestEngine; _tvRequestEngine = tvRequestEngine; + _hub = hub; _logger = logger; } @@ -44,48 +49,69 @@ namespace Ombi.Schedule.Jobs.Plex var settings = await _settings.GetSettingsAsync(); if (!settings.Enable || !settings.EnableWatchlistImport) { + _logger.LogDebug($"Not enabled. Plex Enabled: {settings.Enable}, Watchlist Enabled: {settings.EnableWatchlistImport}"); return; } var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); + _logger.LogInformation($"Found {plexUsersWithTokens.Count} users with tokens"); + await NotifyClient("Starting Watchlist Import"); + foreach (var user in plexUsersWithTokens) { - var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None); - if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) + try { - return; - } - var items = watchlist.MediaContainer.Metadata; - foreach (var item in items) - { - var providerIds = await GetProviderIds(user.MediaServerToken, item, context?.CancellationToken ?? CancellationToken.None); - if (!providerIds.TheMovieDb.HasValue()) + _logger.LogDebug($"Starting Watchlist Import for {user.UserName} with token {user.MediaServerToken}"); + var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None); + if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) { - // We need a MovieDbId to support this; + _logger.LogDebug($"No watchlist found for {user.UserName}"); return; } - switch (item.type) + + var items = watchlist.MediaContainer.Metadata; + _logger.LogDebug($"Items found in watchlist: {watchlist.MediaContainer.totalSize}"); + foreach (var item in items) { - case "show": - await ProcessShow(int.Parse(providerIds.TheMovieDb), user, context?.CancellationToken ?? CancellationToken.None); - break; - case "movie": - await ProcessMovie(int.Parse(providerIds.TheMovieDb), user, context?.CancellationToken ?? CancellationToken.None); - break; + _logger.LogDebug($"Processing {item.title} {item.type}"); + var providerIds = await GetProviderIds(user.MediaServerToken, item, context?.CancellationToken ?? CancellationToken.None); + if (!providerIds.TheMovieDb.HasValue()) + { + _logger.LogWarning($"No TheMovieDb Id found for {item.title}, could not import via Plex WatchList"); + // We need a MovieDbId to support this; + return; + } + switch (item.type) + { + case "show": + await ProcessShow(int.Parse(providerIds.TheMovieDb), user); + break; + case "movie": + await ProcessMovie(int.Parse(providerIds.TheMovieDb), user); + break; + } } } + catch (Exception ex) + { + _logger.LogError(ex, $"Exception thrown when importing watchlist for user {user.UserName}"); + continue; + } } + + await NotifyClient("Finished Watchlist Import"); } - private async Task ProcessMovie(int theMovieDbId, OmbiUser user, CancellationToken cancellationToken) + private async Task ProcessMovie(int theMovieDbId, OmbiUser user) { _movieRequestEngine.SetUser(user); - var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist}); + var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); if (response.IsError) { if (response.ErrorCode == ErrorCode.AlreadyRequested) { + _logger.LogDebug($"Movie already requested for user '{user.UserName}'"); return; } _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); @@ -97,7 +123,7 @@ namespace Ombi.Schedule.Jobs.Plex } - private async Task ProcessShow(int theMovieDbId, OmbiUser user, CancellationToken cancellationToken) + private async Task ProcessShow(int theMovieDbId, OmbiUser user) { _tvRequestEngine.SetUser(user); var response = await _tvRequestEngine.RequestTvShow(new TvRequestViewModelV2 { RequestAll = true, TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); @@ -105,6 +131,7 @@ namespace Ombi.Schedule.Jobs.Plex { if (response.ErrorCode == ErrorCode.AlreadyRequested) { + _logger.LogDebug($"Show already requested for user '{user.UserName}'"); return; } _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); @@ -144,6 +171,15 @@ namespace Ombi.Schedule.Jobs.Plex return providerIds; } + private async Task NotifyClient(string message) + { + if (_hub?.Clients == null) + { + return; + } + await _hub?.Clients?.Clients(NotificationHub.AdminConnectionIds)? + .SendAsync(NotificationHub.NotificationEvent, $"Plex Watchlist Import - {message}"); + } public void Dispose() { } } } From 174b97ea33291b541a5ed419ad009a983a19faf4 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 8 Apr 2022 13:16:52 +0000 Subject: [PATCH 162/210] chore(release): :rocket: v4.16.4 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d02be3fe..32da99cfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.16.4](https://github.com/Ombi-app/Ombi/compare/v4.16.3...v4.16.4) (2022-04-08) + + + ## [4.16.3](https://github.com/Ombi-app/Ombi/compare/v4.16.2...v4.16.3) (2022-04-08) @@ -309,12 +313,3 @@ -# [4.10.0](https://github.com/Ombi-app/Ombi/compare/v4.9.2...v4.10.0) (2022-01-14) - - -### Features - -* **notifications:** :sparkles: Send new request email notifications to power users ([#4462](https://github.com/Ombi-app/Ombi/issues/4462)) ([10cc0c0](https://github.com/Ombi-app/Ombi/commit/10cc0c0951f13221179516f8ff5c44dbecc9a0fd)) - - - diff --git a/version.json b/version.json index a2796d255..5a260f95f 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.3" + "version": "4.16.4" } \ No newline at end of file From d962a3211eca29520662ddce962676e3aea17ec5 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 8 Apr 2022 14:54:24 +0100 Subject: [PATCH 163/210] fix(watchlist): actually fixed it this time... --- src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index d1217c8b5..ac5d21b16 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -67,7 +67,7 @@ namespace Ombi.Schedule.Jobs.Plex if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) { _logger.LogDebug($"No watchlist found for {user.UserName}"); - return; + continue; } var items = watchlist.MediaContainer.Metadata; @@ -80,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Plex { _logger.LogWarning($"No TheMovieDb Id found for {item.title}, could not import via Plex WatchList"); // We need a MovieDbId to support this; - return; + continue; } switch (item.type) { From 70706048edd8593c1cac9830dc65ef6489351aa0 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 8 Apr 2022 13:58:48 +0000 Subject: [PATCH 164/210] chore(release): :rocket: v4.16.5 --- CHANGELOG.md | 17 +++++++++-------- version.json | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32da99cfb..ffc4bd2c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.16.5](https://github.com/Ombi-app/Ombi/compare/v4.16.4...v4.16.5) (2022-04-08) + + +### Bug Fixes + +* **watchlist:** actually fixed it this time... ([d962a32](https://github.com/Ombi-app/Ombi/commit/d962a3211eca29520662ddce962676e3aea17ec5)) + + + ## [4.16.4](https://github.com/Ombi-app/Ombi/compare/v4.16.3...v4.16.4) (2022-04-08) @@ -305,11 +314,3 @@ -## [4.10.1](https://github.com/Ombi-app/Ombi/compare/v4.10.0...v4.10.1) (2022-01-22) - - - -## [4.3.3](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.3.3) (2021-11-05) - - - diff --git a/version.json b/version.json index 5a260f95f..c01a9f2c1 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.4" + "version": "4.16.5" } \ No newline at end of file From 25342ec3c25fae3028f30beabfcd84afd24ae430 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 8 Apr 2022 16:20:55 +0200 Subject: [PATCH 165/210] Lint it first --- .../movie/movie-details.component.html | 218 ++++++++++-------- 1 file changed, 122 insertions(+), 96 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index d3997fb1c..adff7acc1 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -4,30 +4,18 @@
- + @@ -43,118 +31,146 @@
- + {{'Search.ViewOnPlex' | translate}} - + {{'Search.ViewOnEmby' | translate}} - + {{'Search.ViewOnJellyfin' | translate}} - - - - - - - - - + + + + + + + + + - - + + - - + - - - - - - + - - + + + + + + + - - - - - - - - - - - - - - - - + + + +
@@ -163,7 +179,8 @@
- + @@ -199,9 +216,14 @@ {{'MediaDetails.Trailers' | translate}} - + - + @@ -229,7 +251,9 @@ @@ -249,7 +273,9 @@ From 614f9b3b21cb1b4d7a5873903db99c5d6f18e999 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 8 Apr 2022 16:21:39 +0200 Subject: [PATCH 166/210] Fix subscribe button displayed only if 4K is enabled --- .../movie/movie-details.component.html | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index adff7acc1..a7b4df576 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -104,17 +104,18 @@ {{'Common.Request4K' | translate }} - - - - + + + + + - From 6c8205ffc8e3c8f9756282b4f8912f33962c2d4e Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 8 Apr 2022 17:15:27 +0200 Subject: [PATCH 170/210] Allow admins to subscribe too! --- .../media-details/components/movie/movie-details.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 597c4d52f..add339ad8 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -108,7 +108,7 @@ - + From da0404d5528dcd9a6217199632068d0d40672ea5 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 8 Apr 2022 17:18:41 +0200 Subject: [PATCH 171/210] Fix regression when request is not made --- .../components/movie/movie-details.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index add339ad8..2207ea323 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -108,11 +108,11 @@ - - - From 10a7f8d4fb705adedd492d6e6197f49fca2194c4 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Sat, 9 Apr 2022 09:19:42 +0200 Subject: [PATCH 172/210] Restore Subscribed field in search service Let's only flag it as obsolete for now --- src/Ombi.Core/Engine/MovieSearchEngine.cs | 26 ++++++++++++++++ .../Engine/V2/MovieSearchEngineV2.cs | 31 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 76cb13968..682a999eb 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -16,6 +16,7 @@ using Ombi.Store.Repository; using System; using System.Collections.Generic; using System.Linq; +using System.Security.Principal; using System.Threading.Tasks; namespace Ombi.Core.Engine @@ -215,9 +216,34 @@ namespace Ombi.Core.Engine await RunSearchRules(viewMovie); + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(viewMovie); + return viewMovie; } + private async Task CheckForSubscription(SearchMovieViewModel viewModel) + { + // Check if this user requested it + var user = await GetUser(); + if (user == null) + { + return; + } + var request = await RequestService.MovieRequestService.GetAll() + .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id); + if (request || viewModel.Available) + { + viewModel.ShowSubscribe = false; + } + else + { + viewModel.ShowSubscribe = true; + var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => s.UserId == user.Id + && s.RequestId == viewModel.RequestId && s.RequestType == RequestType.Movie); + viewModel.Subscribed = sub != null; + } + } private async Task ProcessSingleMovie(MovieDbSearchResult movie) { diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index 614c2df55..3acd7d1f0 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -393,6 +393,8 @@ namespace Ombi.Core.Engine.V2 await RunSearchRules(viewMovie); + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(viewMovie); var mapped = Mapper.Map(movie); mapped.Available = viewMovie.Available; @@ -404,6 +406,7 @@ namespace Ombi.Core.Engine.V2 mapped.PlexUrl = viewMovie.PlexUrl; mapped.EmbyUrl = viewMovie.EmbyUrl; mapped.JellyfinUrl = viewMovie.JellyfinUrl; + mapped.Subscribed = viewMovie.Subscribed; mapped.ShowSubscribe = viewMovie.ShowSubscribe; mapped.DigitalReleaseDate = viewMovie.DigitalReleaseDate; mapped.RequestedDate4k = viewMovie.RequestedDate4k; @@ -426,6 +429,8 @@ namespace Ombi.Core.Engine.V2 var mappedMovie = Mapper.Map(movie); await RunSearchRules(mappedMovie); + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(mappedMovie); var mapped = Mapper.Map(movie); mapped.Available = movie.Available; @@ -435,6 +440,7 @@ namespace Ombi.Core.Engine.V2 mapped.PlexUrl = movie.PlexUrl; mapped.EmbyUrl = movie.EmbyUrl; mapped.JellyfinUrl = movie.JellyfinUrl; + mapped.Subscribed = movie.Subscribed; mapped.ShowSubscribe = movie.ShowSubscribe; mapped.ReleaseDate = movie.ReleaseDate; } @@ -464,9 +470,34 @@ namespace Ombi.Core.Engine.V2 await RunSearchRules(viewMovie); + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(viewMovie); + return viewMovie; } + private async Task CheckForSubscription(SearchViewModel viewModel) + { + // Check if this user requested it + var user = await GetUser(); + if (user == null) + { + return; + } + var request = await RequestService.MovieRequestService.GetAll() + .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id); + if (request) + { + viewModel.ShowSubscribe = false; + } + else + { + viewModel.ShowSubscribe = true; + var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => s.UserId == user.Id + && s.RequestId == viewModel.RequestId && s.RequestType == RequestType.Movie); + viewModel.Subscribed = sub != null; + } + } public async Task GetMovieInfoByImdbId(string imdbId, CancellationToken cancellationToken) { From 76bd81c3ca55a98c6ec944a838dc01294a6193a6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 11 Apr 2022 17:08:40 +0100 Subject: [PATCH 173/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 27d310604..07dacca82 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -14,7 +14,7 @@ "Common": { "ContinueButton": "Continua", "Available": "Disponibile", - "Available4K": "Disponibile 4K", + "Available4K": "Disponibile in 4K", "Approved": "Approvato", "Approve4K": "Approva 4K", "Pending": "In Sospeso", @@ -66,7 +66,7 @@ "Discover": "Scopri", "Search": "Cerca", "Requests": "Richieste", - "UserManagement": "Gestione degli utenti", + "UserManagement": "Utenti", "Issues": "Problemi", "Vote": "Vota", "Donate": "Dona!", @@ -74,7 +74,7 @@ "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", "UpdateAvailableTooltip": "Aggiornamento disponibile!", "Settings": "Impostazioni", - "Welcome": "Ti diamo il benvenuto {{username}}", + "Welcome": "Benvenuto {{username}}", "UpdateDetails": "Aggiorna dettagli", "Logout": "Esci", "OpenMobileApp": "Apri l'app Mobile", @@ -90,9 +90,9 @@ "Music": "Musica", "People": "Persone" }, - "MorningWelcome": "Buona mattina!", + "MorningWelcome": "Buongiorno!", "AfternoonWelcome": "Buon pomeriggio!", - "EveningWelcome": "Buona sera!" + "EveningWelcome": "Buonasera!" }, "Search": { "Title": "Cerca", @@ -103,7 +103,7 @@ "AdvancedSearch": "Puoi compilare uno dei seguenti per scoprire nuovi media. Tutti i risultati sono ordinati per popolarità", "AdvancedSearchHeader": "Ricerca Avanzata", "Suggestions": "Suggerimenti", - "NoResults": "Spiacenti, non abbiamo trovato nulla!", + "NoResults": "Nessun risultato trovato!", "DigitalDate": "Uscita in digitale: {{date}}", "TheatricalRelease": "Uscita nei cinema: {{date}}", "ViewOnPlex": "Guarda su Plex", From c075a1a66784d975eaf60f2dfbbcbe048f2f63d7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 11 Apr 2022 18:10:59 +0100 Subject: [PATCH 174/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 68 +++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 07dacca82..c0740c484 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -100,7 +100,7 @@ "MoviesTab": "Film", "TvTab": "Serie TV", "MusicTab": "Musica", - "AdvancedSearch": "Puoi compilare uno dei seguenti per scoprire nuovi media. Tutti i risultati sono ordinati per popolarità", + "AdvancedSearch": "Compila uno dei seguenti campi per cercare nuovi media. I risultati sono in ordine di popolarità", "AdvancedSearchHeader": "Ricerca Avanzata", "Suggestions": "Suggerimenti", "NoResults": "Nessun risultato trovato!", @@ -136,12 +136,12 @@ "Season": "Stagione {{seasonNumber}}", "SelectAllInSeason": "Seleziona tutto nella stagione {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Sei pregato di scegliere che tipo di media stai cercando:", + "AdvancedSearchInstructions": "Scegli che tipo di media cercare:", "YearOfRelease": "Anno di Rilascio", "SearchGenre": "Cerca per genere", - "SearchKeyword": "Termini di ricerca", + "SearchKeyword": "Cerca per parola chiave", "SearchProvider": "Provider di ricerca", - "KeywordSearchingDisclaimer": "Sei pregato di notare che la Ricerca per Parola chiave è molto a fortuna a causa di dati non coerenti nel TheMovieDb" + "KeywordSearchingDisclaimer": "Attenzione: La ricerca per parola chiave è incostante a causa di dati non coerenti su TheMovieDb" }, "Requests": { "Title": "Richieste", @@ -212,12 +212,12 @@ "Deleted": "Elementi selezionati eliminati correttamente", "Approved": "Elementi selezionati approvati correttamente" }, - "SuccessfullyApproved": "Approvato Correttamente", + "SuccessfullyApproved": "Approvata", "SuccessfullyDeleted": "Richiesta eliminata correttamente", "NowAvailable": "Richiesta ora disponibile", "NowUnavailable": "Richiesta ora non disponibile", - "SuccessfullyReprocessed": "Richiesta ri-elaborata correttamente", - "DeniedRequest": "Richiesta Negata", + "SuccessfullyReprocessed": "Richiesta rielaborata correttamente", + "DeniedRequest": "Richiesta Rifiutata", "RequestCollection": "Richiedi Raccolta", "CollectionSuccesfullyAdded": "La raccolta {{name}} è stata aggiunta correttamente!", "NeedToSelectEpisodes": "Devi selezionare degli episodi!", @@ -243,20 +243,20 @@ "CouldntNotify": "Impossibile notificare il titolo {{title}}" }, "Issues": { - "Title": "Problemi", - "IssuesForTitle": "Problemi per {{title}}", - "PendingTitle": "Problemi In Attesa", - "InProgressTitle": "Problemi In Corso", - "ResolvedTitle": "Problemi Risolti", + "Title": "Segnalazioni", + "IssuesForTitle": "Segnalazioni per {{title}}", + "PendingTitle": "Segnalazioni In Attesa", + "InProgressTitle": "Segnalazioni In Risoluzione", + "ResolvedTitle": "Segnalazioni Risolte", "ColumnTitle": "Titolo", - "Count": "Conteggio", + "Count": "Totale", "Category": "Categoria", "Status": "Stato", "Details": "Dettagli", "Description": "Descrizione", "NoComments": "Nessun Commento!", - "MarkInProgress": "Senza In Corso", - "MarkResolved": "Segna Risolto", + "MarkInProgress": "Approva", + "MarkResolved": "Risolvi", "SendMessageButton": "Invia", "Subject": "Oggetto", "Comments": "Commenti", @@ -306,22 +306,22 @@ "Denied": "Rifiutato", "Denied4K": "4K Negato", "Trailers": "Trailer", - "RecommendationsTitle": "Raccomandazioni", + "RecommendationsTitle": "Raccomandati", "SimilarTitle": "Simili", "VideosTitle": "Video", "AlbumsTitle": "Album", - "RequestAllAlbums": "Richiedi Tutti gli Album", + "RequestAllAlbums": "Richiedi tutti gli Album", "ClearSelection": "Cancella Selezione", - "RequestSelectedAlbums": "Richiesta degli Album Selezionati", + "RequestSelectedAlbums": "Richiedi gli Album Selezionati", "ViewCollection": "Visualizza Raccolta", - "NotEnoughInfo": "Sfortunatamente ancora non ci sono abbastanza informazioni su questo show!", + "NotEnoughInfo": "Purtroppo ancora non ci sono abbastanza informazioni su questa serie!", "AdvancedOptions": "Opzioni Avanzate", "AutoApproveOptions": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR e automaticamente approvata! La configurazione è facoltativa, basta premere Richiedi per saltarla!", "AutoApproveOptionsTv": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR e automaticamente approvata! Se la richiesta è già presente in Sonarr, la cartella radice o il profilo qualità non verrà cambiato! La configurazione è facoltativa, basta premere Richiedi per saltarla!", "AutoApproveOptionsTvShort": "Puoi configurare qui la tua richiesta, che verrà inviata alla tua applicazione DVR! Se la richiesta è già presente in Sonarr, la cartella radice o il profilo qualità non verrà cambiato! La configurazione è facoltativa, basta premere Richiedi per saltarla!", - "QualityProfilesSelect": "Seleziona Un Profilo di Qualità", - "RootFolderSelect": "Seleziona Una Cartella di Root", - "LanguageProfileSelect": "Seleziona Un Profilo della Lingua", + "QualityProfilesSelect": "Seleziona un Profilo per la Qualità", + "RootFolderSelect": "Seleziona una Cartella Principale", + "LanguageProfileSelect": "Seleziona un profilo per la Lingua", "Status": "Stato:", "StatusValues": { "Rumored": "Rumor", @@ -331,16 +331,16 @@ "Released": "Rilasciato", "Running": "In Corso", "Returning Series": "Serie Rinnovate", - "Ended": "Terminata", - "Canceled": "Annullata" + "Ended": "Conclusa", + "Canceled": "Cancellata" }, "Seasons": "Stagioni:", "Episodes": "Episodi:", "Availability": "Disponibilità:", "RequestStatus": "Stato Richiesta", "Quality": "Qualità:", - "RootFolderOverride": "Sovrascrizione Cartella di Root:", - "QualityOverride": "Sovrascrizione Qualità:", + "RootFolderOverride": "Sovrascrivi Cartella Principale:", + "QualityOverride": "Sovrascrivi Qualità:", "Network": "Rete:", "GenresLabel": "Generi:", "Genres": "Generi", @@ -357,9 +357,9 @@ "CastTitle": "Trasmetti" }, "EpisodeSelector": { - "AllSeasonsTooltip": "Questo richiederà ogni stagione per questo show", - "FirstSeasonTooltip": "Questo richiederà solo la Prima Stagione per questo show", - "LatestSeasonTooltip": "Questo richiederà solo l'Ultima Stagione per questo show", + "AllSeasonsTooltip": "Richiederà tutte le stagioni per questa serie", + "FirstSeasonTooltip": "Richiederà solo la Prima Stagione per questa serie", + "LatestSeasonTooltip": "Richiederà solo l'Ultima Stagione per questa serie", "NoEpisodes": "Sfortunatamente, non c'è ancora alcun dato dell'episodio per questa serie!", "SeasonNumber": "Stagione {{number}}" }, @@ -411,14 +411,14 @@ "DarkMode": "Modalità Scura", "Updated": "Aggiornate Correttamente", "StreamingCountry": "Paese di Streaming", - "StreamingCountryDescription": "Questo è il codice paese per cui mostreremo le informazioni di streaming. Se sei negli USA, selezionando US riceverai le informazioni di streaming correlate agli USA.", + "StreamingCountryDescription": "Questo è il codice del paese per cui mostreremo le informazioni dei media. Se sei in Italia, seleziona IT e ti mostreremo le informazioni dei media in Italiano.", "LanguageDescription": "Questa è la lingua in cui vorresti fosse visualizzata l'interfaccia di Ombi.", "MobileQRCode": "Codice QR Mobile", "LegacyApp": "Avvia l'App Legacy", - "NoQrCode": "Sei pregato di contattare il tuo amministratore per abilitare i codici QR", + "NoQrCode": "Contatta l'amministratore per abilitare i codici QR", "UserType": "Tipo di Utente:", "ChangeDetails": "Modifica i Dettagli", - "NeedCurrentPassword": "Necessiti la tua password corrente per effettuare qualsiasi modifica qui", + "NeedCurrentPassword": "Hai bisogno della tua password attuale per apportare qualsiasi modifica qui", "CurrentPassword": "Password Corrente", "EmailAddress": "Indirizzo Email", "NewPassword": "Nuova Password", @@ -430,8 +430,8 @@ }, "UserTypeLabel": { "1": "Utente Locale", - "2": "Utente di Plex", - "3": "Utente di Emby", + "2": "Utente Plex", + "3": "Utente Emby", "4": "Connetti Utente di Emby", "5": "Utente di Jellyfin" }, From ff33d6b5166d9d01ae32f9b66d9253290a56ef42 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 11 Apr 2022 20:36:49 +0100 Subject: [PATCH 175/210] added the watchlist history --- .../PlexWatchlistImportTests.cs | 93 +++++++++++++++++++ .../Jobs/Plex/PlexContentSync.cs | 2 +- .../Jobs/Plex/PlexWatchlistImport.cs | 27 +++++- src/Ombi.Store/Context/ExternalContext.cs | 1 + .../Entities/PlexWatchlistHistory.cs | 10 ++ 5 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Store/Entities/PlexWatchlistHistory.cs diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index b4759e280..b45f471d2 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -10,9 +10,11 @@ using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Schedule.Jobs.Plex; using Ombi.Store.Entities; +using Ombi.Store.Repository; using Ombi.Test.Common; using Quartz; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -45,6 +47,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] public async Task TerminatesWhenWatchlistIsNotEnabled() @@ -54,6 +58,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -65,6 +71,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -86,6 +94,31 @@ namespace Ombi.Schedule.Tests await _subject.Execute(_context.Object); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + } + + + [Test] + public async Task MultipleUsers() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + var um = MockHelper.MockUserManager(new List + { + new OmbiUser { Id = "abc1", UserType = UserType.PlexUser, MediaServerToken = "abc1", UserName = "abc1", NormalizedUserName = "ABC1" }, + new OmbiUser { Id = "abc2", UserType = UserType.PlexUser, MediaServerToken = "abc2", UserName = "abc2", NormalizedUserName = "ABC2" }, + new OmbiUser { Id = "abc3", UserType = UserType.PlexUser, MediaServerToken = "abc3", UserName = "abc3", NormalizedUserName = "ABC3" }, + new OmbiUser { Id = "abc4", UserType = UserType.PlexUser, MediaServerToken = "abc4", UserName = "abc4", NormalizedUserName = "ABC4" }, + new OmbiUser { Id = "abc5", UserType = UserType.PlexUser, MediaServerToken = "abc5", UserName = "abc5", NormalizedUserName = "ABC5" }, + }); + _mocker.Use(um); + _subject = _mocker.CreateInstance(); + + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Exactly(5)); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } @@ -134,6 +167,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } @@ -182,6 +217,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } [Test] @@ -229,6 +266,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -276,6 +315,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -323,6 +364,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); } [Test] @@ -370,6 +413,56 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + } + + [Test] + public async Task MovieRequestFromWatchList_AlreadyImported() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true }); + _mocker.Setup>(x => x.GetWatchlist(It.IsAny(), It.IsAny())).ReturnsAsync(new PlexWatchlistContainer + { + MediaContainer = new PlexWatchlist + { + Metadata = new List + { + new Metadata + { + type = "movie", + ratingKey = "abc" + } + } + } + }); + _mocker.Setup>(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny())) + .ReturnsAsync(new PlexWatchlistMetadataContainer + { + MediaContainer = new PlexWatchlistMetadata + { + Metadata = new WatchlistMetadata[] + { + new WatchlistMetadata + { + Guid = new List + { + new PlexGuids + { + Id = "tmdb://123" + } + } + } + } + + } + }); + _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List { new PlexWatchlistHistory { Id = 1, TmdbId = "123" } }.AsQueryable()); + await _subject.Execute(_context.Object); + _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); + _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); + _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Once); } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 170f6b943..9c5a651e2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -385,7 +385,7 @@ namespace Ombi.Schedule.Jobs.Plex continue; } - var qualities = movie.Media?.Select(x => x.videoResolution); + var qualities = movie?.Media?.Select(x => x?.videoResolution ?? string.Empty) ?? Enumerable.Empty(); var is4k = qualities != null && qualities.Any(x => x.Equals("4k", StringComparison.InvariantCultureIgnoreCase)); var selectedQuality = is4k ? null : qualities?.OrderBy(x => x)?.FirstOrDefault() ?? string.Empty; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index ac5d21b16..b62ab0ddf 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -12,6 +12,7 @@ using Ombi.Helpers; using Ombi.Hubs; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; using Quartz; using System; using System.Collections.Generic; @@ -30,10 +31,11 @@ namespace Ombi.Schedule.Jobs.Plex private readonly ITvRequestEngine _tvRequestEngine; private readonly IHubContext _hub; private readonly ILogger _logger; + private readonly IRepository _watchlistRepo; public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IHubContext hub, - ILogger logger) + ILogger logger, IRepository watchlistRepo) { _plexApi = plexApi; _settings = settings; @@ -42,6 +44,7 @@ namespace Ombi.Schedule.Jobs.Plex _tvRequestEngine = tvRequestEngine; _hub = hub; _logger = logger; + _watchlistRepo = watchlistRepo; } public async Task Execute(IJobExecutionContext context) @@ -82,6 +85,15 @@ namespace Ombi.Schedule.Jobs.Plex // We need a MovieDbId to support this; continue; } + + // Check to see if we have already imported this item + var alreadyImported = _watchlistRepo.GetAll().Any(x => x.TmdbId == providerIds.TheMovieDb); + if (alreadyImported) + { + _logger.LogDebug($"{item.title} already imported via Plex WatchList, skipping"); + continue; + } + switch (item.type) { case "show": @@ -118,6 +130,13 @@ namespace Ombi.Schedule.Jobs.Plex } else { + // Add to the watchlist history + var history = new PlexWatchlistHistory + { + TmdbId = theMovieDbId.ToString() + }; + await _watchlistRepo.Add(history); + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); } } @@ -138,6 +157,12 @@ namespace Ombi.Schedule.Jobs.Plex } else { + // Add to the watchlist history + var history = new PlexWatchlistHistory + { + TmdbId = theMovieDbId.ToString() + }; + await _watchlistRepo.Add(history); _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); } } diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index b6f8d6485..f13c1e74f 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -27,6 +27,7 @@ namespace Ombi.Store.Context public DbSet PlexServerContent { get; set; } public DbSet PlexSeasonsContent { get; set; } public DbSet PlexEpisode { get; set; } + public DbSet PlexWatchlistHistory { get; set; } public DbSet RadarrCache { get; set; } public DbSet CouchPotatoCache { get; set; } public DbSet EmbyContent { get; set; } diff --git a/src/Ombi.Store/Entities/PlexWatchlistHistory.cs b/src/Ombi.Store/Entities/PlexWatchlistHistory.cs new file mode 100644 index 000000000..e6aee29b4 --- /dev/null +++ b/src/Ombi.Store/Entities/PlexWatchlistHistory.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + [Table(nameof(PlexWatchlistHistory))] + public class PlexWatchlistHistory : Entity + { + public string TmdbId { get; set; } + } +} From 0492e71ab71d4e8d647af2662b3d239b6707e57a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 11 Apr 2022 21:16:15 +0100 Subject: [PATCH 176/210] Added the watchlist migrations --- .../PlexWatchlistImportTests.cs | 50 +- .../Jobs/Plex/PlexWatchlistImport.cs | 4 +- ...0220411193943_WatchlistHistory.Designer.cs | 549 ++++++++++++++++++ .../20220411193943_WatchlistHistory.cs | 34 ++ .../ExternalMySqlContextModelSnapshot.cs | 14 + ...0220411193827_WatchlistHistory.Designer.cs | 547 +++++++++++++++++ .../20220411193827_WatchlistHistory.cs | 31 + .../ExternalSqliteContextModelSnapshot.cs | 14 + src/Ombi/Properties/launchSettings.json | 2 +- 9 files changed, 1217 insertions(+), 28 deletions(-) create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs create mode 100644 src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index b45f471d2..ec66b1cea 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -47,8 +47,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] public async Task TerminatesWhenWatchlistIsNotEnabled() @@ -58,8 +58,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -71,8 +71,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -94,8 +94,8 @@ namespace Ombi.Schedule.Tests await _subject.Execute(_context.Object); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Never); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } @@ -117,8 +117,8 @@ namespace Ombi.Schedule.Tests await _subject.Execute(_context.Object); _mocker.Verify(x => x.GetWatchlist(It.IsAny(), It.IsAny()), Times.Exactly(5)); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } @@ -167,8 +167,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); - _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } @@ -217,8 +217,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); - _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } [Test] @@ -266,8 +266,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); - _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -315,8 +315,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); - _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); } [Test] @@ -364,8 +364,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); } [Test] @@ -413,8 +413,8 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.RequestTvShow(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Never); } [Test] @@ -456,13 +456,13 @@ namespace Ombi.Schedule.Tests } }); - _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List { new PlexWatchlistHistory { Id = 1, TmdbId = "123" } }.AsQueryable()); + _mocker.Setup, IQueryable>(x => x.GetAll()).Returns(new List { new PlexWatchlistHistory { Id = 1, TmdbId = "123" } }.AsQueryable()); await _subject.Execute(_context.Object); _mocker.Verify(x => x.RequestMovie(It.IsAny()), Times.Never); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Never); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); - _mocker.Verify>(x => x.GetAll(), Times.Once); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.GetAll(), Times.Once); } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index b62ab0ddf..202287bf6 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -31,11 +31,11 @@ namespace Ombi.Schedule.Jobs.Plex private readonly ITvRequestEngine _tvRequestEngine; private readonly IHubContext _hub; private readonly ILogger _logger; - private readonly IRepository _watchlistRepo; + private readonly IExternalRepository _watchlistRepo; public PlexWatchlistImport(IPlexApi plexApi, ISettingsService settings, OmbiUserManager ombiUserManager, IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IHubContext hub, - ILogger logger, IRepository watchlistRepo) + ILogger logger, IExternalRepository watchlistRepo) { _plexApi = plexApi; _settings = settings; diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs new file mode 100644 index 000000000..69d012d5d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.Designer.cs @@ -0,0 +1,549 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + [DbContext(typeof(ExternalMySqlContext))] + [Migration("20220411193943_WatchlistHistory")] + partial class WatchlistHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EmbyId") + .HasColumnType("longtext"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("JellyfinId") + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("varchar(255)"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TrackCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArtistId") + .HasColumnType("int"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("Monitored") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("GrandparentKey") + .HasColumnType("varchar(255)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ParentKey") + .HasColumnType("longtext"); + + b.Property("PlexContentId") + .HasColumnType("longtext"); + + b.Property("PlexServerContentId") + .HasColumnType("int"); + + b.Property("SeasonKey") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("Quality") + .HasColumnType("longtext"); + + b.Property("ReleaseYear") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TvDbId") + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TmdbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Has4K") + .HasColumnType("tinyint(1)"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("HasRegular") + .HasColumnType("tinyint(1)"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("HasFile") + .HasColumnType("tinyint(1)"); + + b.Property("MovieDbId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs new file mode 100644 index 000000000..760f40c25 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalMySql/20220411193943_WatchlistHistory.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalMySql +{ + public partial class WatchlistHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PlexWatchlistHistory", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TmdbId = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_PlexWatchlistHistory", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PlexWatchlistHistory"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs index f55793b72..1e86ddf7b 100644 --- a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -374,6 +374,20 @@ namespace Ombi.Store.Migrations.ExternalMySql b.ToTable("PlexServerContent"); }); + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("TmdbId") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => { b.Property("Id") diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs new file mode 100644 index 000000000..03da8c7eb --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.Designer.cs @@ -0,0 +1,547 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20220411193827_WatchlistHistory")] + partial class WatchlistHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EmbyId") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("JellyfinContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("JellyfinId") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("JellyfinEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.Property("PercentOfTracks") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrackCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("Monitored") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("GrandparentKey") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ParentKey") + .HasColumnType("TEXT"); + + b.Property("PlexContentId") + .HasColumnType("TEXT"); + + b.Property("PlexServerContentId") + .HasColumnType("INTEGER"); + + b.Property("SeasonKey") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quality") + .HasColumnType("TEXT"); + + b.Property("ReleaseYear") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TvDbId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TmdbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Has4K") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("HasRegular") + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("HasFile") + .HasColumnType("INTEGER"); + + b.Property("MovieDbId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + 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"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b => + { + b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("JellyfinId"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b => + { + b.Navigation("Episodes"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Navigation("Episodes"); + + b.Navigation("Seasons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs new file mode 100644 index 000000000..030cefa1d --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20220411193827_WatchlistHistory.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class WatchlistHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PlexWatchlistHistory", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TmdbId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexWatchlistHistory", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PlexWatchlistHistory"); + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs index ca7ba7a96..2f5de3382 100644 --- a/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalSqlite/ExternalSqliteContextModelSnapshot.cs @@ -372,6 +372,20 @@ namespace Ombi.Store.Migrations.ExternalSqlite b.ToTable("PlexServerContent"); }); + modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("TmdbId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlexWatchlistHistory"); + }); + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => { b.Property("Id") diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index 213b92518..b3899f8c3 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -22,7 +22,7 @@ }, "Ombi": { "commandName": "Project", - "commandLineArgs": "--host http://localhost:3577 --demo true", + "commandLineArgs": "--host http://localhost:3577", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, From 408be3c5ed51865804c4cc172a2a8354edfc01d9 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Mon, 11 Apr 2022 20:35:55 +0000 Subject: [PATCH 177/210] chore(release): :rocket: v4.16.6 --- CHANGELOG.md | 14 ++++---------- version.json | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffc4bd2c4..61e98bebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.16.6](https://github.com/Ombi-app/Ombi/compare/v4.16.5...v4.16.6) (2022-04-11) + + + ## [4.16.5](https://github.com/Ombi-app/Ombi/compare/v4.16.4...v4.16.5) (2022-04-08) @@ -304,13 +308,3 @@ -## [4.10.3](https://github.com/Ombi-app/Ombi/compare/v4.10.1...v4.10.3) (2022-01-31) - - -### Bug Fixes - -* fix swagger api key auth ([#4483](https://github.com/Ombi-app/Ombi/issues/4483)) [no ci] ([32ee4e8](https://github.com/Ombi-app/Ombi/commit/32ee4e88ec05bf610150933974408fbe95ccd7bd)) -* **frontend:** add link on logo text ([6d7274a](https://github.com/Ombi-app/Ombi/commit/6d7274a94ea24343f32fc028984bd3fd5d5f2ee3)) - - - diff --git a/version.json b/version.json index c01a9f2c1..30e2697bb 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.5" + "version": "4.16.6" } \ No newline at end of file From 7ec8939cdf6e50717dc2cbd8f6022e5e5ff95762 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 12 Apr 2022 10:27:36 +0100 Subject: [PATCH 178/210] Do not allow already available movies to be imported via the watchlist --- .../Request/ExistingPlexRequestRuleTests.cs | 42 +++++++++++++++++++ .../Rules/Request/ExistingPlexRequestRule.cs | 9 ++++ .../PlexWatchlistImportTests.cs | 4 +- .../Jobs/Plex/PlexWatchlistImport.cs | 29 ++++++------- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs index 3cabfa438..314b543b8 100644 --- a/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/ExistingPlexRequestRuleTests.cs @@ -1,6 +1,7 @@ using MockQueryable.Moq; using Moq; using NUnit.Framework; +using Ombi.Core.Engine; using Ombi.Core.Rule.Rules.Request; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -176,6 +177,47 @@ namespace Ombi.Core.Tests.Rule.Request Assert.That(result.Success, Is.True); } + [Test] + public async Task RequestMovie_IsSuccessful() + { + SetupMockData(); + + var req = new MovieRequests + { + RequestType = RequestType.Movie, + TheMovieDbId = 123, + Id = 1, + }; + var result = await Rule.Execute(req); + + + Assert.That(result.Success, Is.True); + } + + [Test] + public async Task RequestMovie_IsAlreadyAvailable() + { + var content = new List { + new PlexServerContent + { + TheMovieDbId = 123.ToString(), + } + }; + PlexContentRepo.Setup(x => x.GetAll()).Returns(content.AsQueryable().BuildMock().Object); + + var req = new MovieRequests + { + RequestType = RequestType.Movie, + TheMovieDbId = 123, + Id = 1, + }; + var result = await Rule.Execute(req); + + + Assert.That(result.Success, Is.False); + Assert.That(result.ErrorCode, Is.EqualTo(ErrorCode.AlreadyRequested)); + } + private void SetupMockData() { var childRequests = new List diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs index 40be1c73e..4f32c2eb8 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs @@ -54,6 +54,15 @@ namespace Ombi.Core.Rule.Rules.Request // looks like we have a match on the TVDbID return CheckExistingContent(tvRequest, anyMovieDbMatches); } + if (obj.RequestType == RequestType.Movie) + { + var movie = (MovieRequests)obj; + var exists = _plexContent.GetAll().Where(x => x.Type == MediaType.Movie).Any(x => x.TheMovieDbId == movie.Id.ToString() || x.TheMovieDbId == movie.TheMovieDbId.ToString()); + if (exists) + { + return Fail(ErrorCode.AlreadyRequested, "This movie is already available." ); + } + } return Success(); } diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index ec66b1cea..ff3af5018 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -267,7 +267,7 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } [Test] @@ -316,7 +316,7 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); _mocker.Verify>(x => x.GetAll(), Times.Once); - _mocker.Verify>(x => x.Add(It.IsAny()), Times.Never); + _mocker.Verify>(x => x.Add(It.IsAny()), Times.Once); } [Test] diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 202287bf6..36a448130 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -124,24 +124,19 @@ namespace Ombi.Schedule.Jobs.Plex if (response.ErrorCode == ErrorCode.AlreadyRequested) { _logger.LogDebug($"Movie already requested for user '{user.UserName}'"); + await AddToHistory(theMovieDbId); return; } _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); } else { - // Add to the watchlist history - var history = new PlexWatchlistHistory - { - TmdbId = theMovieDbId.ToString() - }; - await _watchlistRepo.Add(history); - + await AddToHistory(theMovieDbId); + _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); } } - private async Task ProcessShow(int theMovieDbId, OmbiUser user) { _tvRequestEngine.SetUser(user); @@ -151,21 +146,27 @@ namespace Ombi.Schedule.Jobs.Plex if (response.ErrorCode == ErrorCode.AlreadyRequested) { _logger.LogDebug($"Show already requested for user '{user.UserName}'"); + await AddToHistory(theMovieDbId); return; } _logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'"); } else { - // Add to the watchlist history - var history = new PlexWatchlistHistory - { - TmdbId = theMovieDbId.ToString() - }; - await _watchlistRepo.Add(history); + await AddToHistory(theMovieDbId); _logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}"); } } + private async Task AddToHistory(int theMovieDbId) + { + + // Add to the watchlist history + var history = new PlexWatchlistHistory + { + TmdbId = theMovieDbId.ToString() + }; + await _watchlistRepo.Add(history); + } private async Task GetProviderIds(string authToken, Metadata movie, CancellationToken cancellationToken) { From 0b0ed4900714331a379f7ecfcfa523f61bbef625 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 12 Apr 2022 09:53:09 +0000 Subject: [PATCH 179/210] chore(release): :rocket: v4.16.7 --- CHANGELOG.md | 8 ++++---- version.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61e98bebe..e58ebf404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.16.7](https://github.com/Ombi-app/Ombi/compare/v4.16.6...v4.16.7) (2022-04-12) + + + ## [4.16.6](https://github.com/Ombi-app/Ombi/compare/v4.16.5...v4.16.6) (2022-04-11) @@ -304,7 +308,3 @@ -## [4.10.4](https://github.com/Ombi-app/Ombi/compare/v4.10.3...v4.10.4) (2022-02-01) - - - diff --git a/version.json b/version.json index 30e2697bb..b02f314fb 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.6" + "version": "4.16.7" } \ No newline at end of file From b49269961d4830a530e3054976a47f519524948b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Apr 2022 15:21:26 +0100 Subject: [PATCH 180/210] fix(availability): Fixed an issue where we wouldn't mark a available 4k movie as available (when 4K request feature is disabled) --- .../Jobs/Plex/PlexAvailabilityChecker.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 6d082195e..e686c6dee 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -6,10 +6,12 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; +using Ombi.Core.Services; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Plex.Models; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; @@ -21,7 +23,7 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationHelper notification, ILogger log, IHubContext hub) + INotificationHelper notification, ILogger log, IHubContext hub, IFeatureService featureService) { _tvRepo = tvRequest; _repo = repo; @@ -29,6 +31,7 @@ namespace Ombi.Schedule.Jobs.Plex _notificationService = notification; _log = log; _notification = hub; + _featureService = featureService; } private readonly ITvRequestRepository _tvRepo; @@ -37,6 +40,7 @@ namespace Ombi.Schedule.Jobs.Plex private readonly INotificationHelper _notificationService; private readonly ILogger _log; private readonly IHubContext _notification; + private readonly IFeatureService _featureService; public async Task Execute(IJobExecutionContext job) { @@ -179,6 +183,7 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessMovies() { + var feature4kEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests); // Get all non available var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available || (!x.Available4K && x.Has4KRequest)); var itemsForAvailbility = new List(); @@ -208,7 +213,7 @@ namespace Ombi.Schedule.Jobs.Plex var notify = false; - if (has4kRequest && item.Has4K && !movie.Available4K) + if (has4kRequest && item.Has4K && !movie.Available4K && feature4kEnabled) { movie.Available4K = true; movie.Approved4K = true; @@ -217,6 +222,14 @@ namespace Ombi.Schedule.Jobs.Plex notify = true; } + if (!feature4kEnabled && !movie.Available) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + await _movieRepo.SaveChangesAsync(); + notify = true; + } + // If we have a non-4k versison then mark as available if (item.Quality != null && !movie.Available) { From ea0529dbf570ec3ddce1f9188704be5493f58cbc Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Apr 2022 15:53:50 +0100 Subject: [PATCH 181/210] fixed tests --- src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index a86afcad0..6a549458b 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -18,6 +18,7 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; using Ombi.Helpers; +using Ombi.Core.Services; namespace Ombi.Schedule.Tests { @@ -36,7 +37,7 @@ namespace Ombi.Schedule.Tests hub.Setup(x => x.Clients.Clients(It.IsAny>()).SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())); NotificationHub.UsersOnline.TryAdd("A", new HubUsers()); - Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object); + Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object, Mock.Of()); } From 309e2402e03cde69f17ea5bb0c6075807e6057f3 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 13 Apr 2022 14:57:23 +0000 Subject: [PATCH 182/210] chore(release): :rocket: v4.16.8 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e58ebf404..9e7d95c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.16.8](https://github.com/Ombi-app/Ombi/compare/v4.16.7...v4.16.8) (2022-04-13) + + +### Bug Fixes + +* **availability:** Fixed an issue where we wouldn't mark a available 4k movie as available (when 4K request feature is disabled) ([b492699](https://github.com/Ombi-app/Ombi/commit/b49269961d4830a530e3054976a47f519524948b)) + + + ## [4.16.7](https://github.com/Ombi-app/Ombi/compare/v4.16.6...v4.16.7) (2022-04-12) @@ -299,12 +308,3 @@ -# [4.11.0](https://github.com/Ombi-app/Ombi/compare/v4.10.4...v4.11.0) (2022-02-01) - - -### Features - -* **newsletter:** Started to localize the newsletter ([#4485](https://github.com/Ombi-app/Ombi/issues/4485)) ([b5ec556](https://github.com/Ombi-app/Ombi/commit/b5ec5562435021ea4b8af07c9b64a3f7249b570a)) - - - diff --git a/version.json b/version.json index b02f314fb..eb3cc380d 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.7" + "version": "4.16.8" } \ No newline at end of file From 77a47ff157c6c5feafe3f2a29a3fcba8df4fdfef Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Apr 2022 20:44:23 +0100 Subject: [PATCH 183/210] fix(plex-watchlist): Only request the latest season when importing from the watchlist --- src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 36a448130..8e6b443ef 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -140,7 +140,7 @@ namespace Ombi.Schedule.Jobs.Plex private async Task ProcessShow(int theMovieDbId, OmbiUser user) { _tvRequestEngine.SetUser(user); - var response = await _tvRequestEngine.RequestTvShow(new TvRequestViewModelV2 { RequestAll = true, TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); + var response = await _tvRequestEngine.RequestTvShow(new TvRequestViewModelV2 { LatestSeason = true, TheMovieDbId = theMovieDbId, Source = RequestSource.PlexWatchlist }); if (response.IsError) { if (response.ErrorCode == ErrorCode.AlreadyRequested) From f486e2ef54dffd9824207d376d23fa2fa00ecbb8 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 13 Apr 2022 19:48:33 +0000 Subject: [PATCH 184/210] chore(release): :rocket: v4.16.9 --- CHANGELOG.md | 13 +++++++++---- version.json | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e7d95c1a..dc5b2e1bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.16.9](https://github.com/Ombi-app/Ombi/compare/v4.16.8...v4.16.9) (2022-04-13) + + +### Bug Fixes + +* **plex-watchlist:** Only request the latest season when importing from the watchlist ([77a47ff](https://github.com/Ombi-app/Ombi/commit/77a47ff157c6c5feafe3f2a29a3fcba8df4fdfef)) + + + ## [4.16.8](https://github.com/Ombi-app/Ombi/compare/v4.16.7...v4.16.8) (2022-04-13) @@ -304,7 +313,3 @@ -## [4.11.1](https://github.com/Ombi-app/Ombi/compare/v4.11.0...v4.11.1) (2022-02-01) - - - diff --git a/version.json b/version.json index eb3cc380d..89e5ff660 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.8" + "version": "4.16.9" } \ No newline at end of file From 2c17d7cca4eaae5c1735a426da7c1cc472625afc Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 13 Apr 2022 19:53:19 +0000 Subject: [PATCH 185/210] chore(release): :rocket: v4.16.10 --- CHANGELOG.md | 13 ++++--------- version.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc5b2e1bd..7191517ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.16.10](https://github.com/Ombi-app/Ombi/compare/v4.16.9...v4.16.10) (2022-04-13) + + + ## [4.16.9](https://github.com/Ombi-app/Ombi/compare/v4.16.8...v4.16.9) (2022-04-13) @@ -304,12 +308,3 @@ -## [4.11.2](https://github.com/Ombi-app/Ombi/compare/v4.11.1...v4.11.2) (2022-02-01) - - -### Bug Fixes - -* :globe_with_meridians: Added Czech and Chinese Simplified to the language list ([68ef366](https://github.com/Ombi-app/Ombi/commit/68ef366e8525e2c349b9e81704ad8bcca6c347a0)) - - - diff --git a/version.json b/version.json index 89e5ff660..674e605d4 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.16.9" + "version": "4.16.10" } \ No newline at end of file From 2941acd3b2ec74a5e6aeea275ab5a39d2653f37f Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:24 +0100 Subject: [PATCH 186/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/fr.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 2c0f012a7..0dddde0a9 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Supprimer la demande", "Approve": "Approuver la demande", + "Deny": "Deny Request", "Approve4K": "Approuver la demande 4K", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Marquer comme Disponible", "Deleted": "Éléments sélectionnés supprimés avec succès", - "Approved": "Éléments sélectionnés approuvés avec succès" + "Approved": "Éléments sélectionnés approuvés avec succès", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Approuvée avec succès", "SuccessfullyDeleted": "Demande supprimée avec succès", From 6ed1a03b7ff4077f09ea9e13394b18b0d138f4c3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:25 +0100 Subject: [PATCH 187/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 33feef3b6..869feaac1 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Usuń zgłoszenie", "Approve": "Zatwierdź zgłoszenie", + "Deny": "Deny Request", "Approve4K": "Zatwierdź prośbę o 4K", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Ozn. jako dostępne", "Deleted": "Pomyślnie usunięto wybrane elementy", - "Approved": "Pomyślnie zatwierdzono wybrane elementy" + "Approved": "Pomyślnie zatwierdzono wybrane elementy", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Zatwierdzono pomyślnie", "SuccessfullyDeleted": "Prośba pomyślnie usunięta", From 3b0b730cb02efe24f6d4026e5fdb20d37e495119 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:26 +0100 Subject: [PATCH 188/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/zh-TW.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/zh-TW.json b/src/Ombi/wwwroot/translations/zh-TW.json index f5ed12a34..16d8d9adf 100644 --- a/src/Ombi/wwwroot/translations/zh-TW.json +++ b/src/Ombi/wwwroot/translations/zh-TW.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "删除请求", "Approve": "批准请求", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "标记为可用", "Deleted": "所选项目已删除", - "Approved": "所选项目已批准" + "Approved": "所选项目已批准", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "批准成功", "SuccessfullyDeleted": "删除请求成功", From 0c9e1ec090827080cc8f7393e5e91456ff37d691 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:27 +0100 Subject: [PATCH 189/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/zh.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/zh.json b/src/Ombi/wwwroot/translations/zh.json index ce9ea5970..edbdf6e94 100644 --- a/src/Ombi/wwwroot/translations/zh.json +++ b/src/Ombi/wwwroot/translations/zh.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "删除请求", "Approve": "批准请求", + "Deny": "Deny Request", "Approve4K": "批准4K请求", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "标记为可用", "Deleted": "所选项目已删除", - "Approved": "所选项目已批准" + "Approved": "所选项目已批准", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "批准成功", "SuccessfullyDeleted": "删除请求成功", From 7cf64f909d78908edaabeffb8a39a7d02e73fe7e Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:29 +0100 Subject: [PATCH 190/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/sv.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 59ee9c798..7b4ba0439 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Ta bort förfrågan", "Approve": "Godkänn begäran", + "Deny": "Deny Request", "Approve4K": "Godkänn 4K-begäran", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Markera Tillgänglig", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From d14f11e0eb20ab0a68e765ee77968b3b3e54e995 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:30 +0100 Subject: [PATCH 191/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/sk.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 925decf6c..b13ddd8ff 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Odstrániž požiadavku", "Approve": "Schváliť žiadosť", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Označiť k dispozícií", "Deleted": "Úspešne odstránené vybrané položky", - "Approved": "Úspešne schválené vybrané položky" + "Approved": "Úspešne schválené vybrané položky", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Úspešne schválené", "SuccessfullyDeleted": "Žiadosť bola úspešne vymazaná", From b404baad6d0aeaa1561701e0db8db4e78613a364 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:31 +0100 Subject: [PATCH 192/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/ru.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 64314fbd4..b60adcaaa 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Отметить доступным", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 634982df2661cefab5ea9f5163fe04a005cc0171 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:32 +0100 Subject: [PATCH 193/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index 5b9096392..ed1aa5434 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Mark Available", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 92a785e736fa4b72a45270da2d0f4661df433078 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:33 +0100 Subject: [PATCH 194/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/no.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 7dc8dfda4..fcb16d35b 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Delete Request", "Approve": "Approve Request", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Merk tilgjengelig", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From d04c60aa5909b47ba6bffa6f66b03079cbd43521 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:34 +0100 Subject: [PATCH 195/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/es.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index adc945c02..135806181 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Eliminar solicitud", "Approve": "Aprobar Solicitud", + "Deny": "Deny Request", "Approve4K": "Aprobar Solicitud 4K", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Marcar como disponible", "Deleted": "Los elementos seleccionados ha sido eliminados correctamente", - "Approved": "Los elementos seleccionados ha sido aprobados correctamente" + "Approved": "Los elementos seleccionados ha sido aprobados correctamente", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Se ha aprobado con éxito", "SuccessfullyDeleted": "Solicitud eliminada con éxito", From 8a78adc9bb62f277f2b213dcb3847ed6d0089fcb Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:36 +0100 Subject: [PATCH 196/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/nl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 62b8afb35..932bbff9c 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Verwijder Verzoek", "Approve": "Verzoek Goedkeuren", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Markeer beschikbaar", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 80233ed560cc976e83570d0655c3472f20171fb3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:36 +0100 Subject: [PATCH 197/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index c0740c484..bca842e34 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Elimina Richiesta", "Approve": "Approva Richiesta", + "Deny": "Deny Request", "Approve4K": "Approva Richiesta 4K", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Segna come Disponibile", "Deleted": "Elementi selezionati eliminati correttamente", - "Approved": "Elementi selezionati approvati correttamente" + "Approved": "Elementi selezionati approvati correttamente", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Approvata", "SuccessfullyDeleted": "Richiesta eliminata correttamente", From bee4ccb804594e7385b1fbdc9fe2ef5c42e0d21f Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:37 +0100 Subject: [PATCH 198/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/hu.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 187af76f0..9a9013317 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Kérés törlése", "Approve": "Kérés elfogadása", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Elérhetőnek jelölés", "Deleted": "A kijelölt elemek törlésre kerultek", - "Approved": "A kijelölt elemek jóváhagyásra kerultek" + "Approved": "A kijelölt elemek jóváhagyásra kerultek", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Sikeresen jóváhagyva", "SuccessfullyDeleted": "Kérés sikeresen törölve", From d1998d326f999a38586d0a351a20c5448df95842 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:39 +0100 Subject: [PATCH 199/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/de.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index c3a4edade..d397f0c55 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Anfrage löschen", "Approve": "Anfrage genehmigen", + "Deny": "Deny Request", "Approve4K": "4K Anfrage genehmigen", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Als verfügbar markieren", "Deleted": "Ausgewählte Elemente erfolgreich gelöscht", - "Approved": "Ausgewählte Elemente erfolgreich freigegeben" + "Approved": "Ausgewählte Elemente erfolgreich freigegeben", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Erfolgreich genehmigt", "SuccessfullyDeleted": "Anfrage erfolgreich gelöscht", From e4b00e6b3468bd9389eeb02fc6ad7daf27abc3b3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:40 +0100 Subject: [PATCH 200/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/da.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index f002574e1..1486bcfae 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Slet Anmodning", "Approve": "Godkend Andmodning", + "Deny": "Deny Request", "Approve4K": "Godkend 4K Anmodning", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Markér som tilgængelig", "Deleted": "De valgte elementer blev slettet", - "Approved": "De valgte elementer blev godkendt" + "Approved": "De valgte elementer blev godkendt", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Godkendt", "SuccessfullyDeleted": "Anmodningen blev slettet", From bc0c2f622e34fb5a2711039d9ed7aad34f982b15 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:41 +0100 Subject: [PATCH 201/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/cs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json index 1b27bd557..c1dec8f37 100644 --- a/src/Ombi/wwwroot/translations/cs.json +++ b/src/Ombi/wwwroot/translations/cs.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Odstranit požadavek", "Approve": "Schválit požadavek", + "Deny": "Deny Request", "Approve4K": "Schválit 4K požadavek", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Označit jako dostupné", "Deleted": "Vybrané položky úspěšně odstraněny", - "Approved": "Vybrané položky byly úspěšně schváleny" + "Approved": "Vybrané položky byly úspěšně schváleny", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Úspěšně schváleno", "SuccessfullyDeleted": "Požadavek byl úspěšně odstraněn", From c12d89d6781a337520977ad285f8d08c93f434dd Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:42 +0100 Subject: [PATCH 202/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/bg.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index 3b3b73055..fd207e4bb 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Изтриване на заявка", "Approve": "Одобряване на заявка", + "Deny": "Deny Request", "Approve4K": "Approve 4K Request", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Маркиране като налично", "Deleted": "Избраните елементи са изтрити успешно", - "Approved": "Избраните елементи са одобрени успешно" + "Approved": "Избраните елементи са одобрени успешно", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 06e4cefa7b4e55b860da9a64f461f6ec8fa17367 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 21:14:43 +0100 Subject: [PATCH 203/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt-BR.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt-BR.json b/src/Ombi/wwwroot/translations/pt-BR.json index 3c9b6a523..5ac23d0b4 100644 --- a/src/Ombi/wwwroot/translations/pt-BR.json +++ b/src/Ombi/wwwroot/translations/pt-BR.json @@ -207,10 +207,13 @@ "RequestPanel": { "Delete": "Apagar Solicitação", "Approve": "Aprovar Solicitação", + "Deny": "Deny Request", "Approve4K": "Aprovar pedido 4K", + "Deny4K": "Deny 4K Request", "ChangeAvailability": "Marcar Como Disponível", "Deleted": "Successfully deleted selected items", - "Approved": "Successfully approved selected items" + "Approved": "Successfully approved selected items", + "Denied": "Successfully denied selected items" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 76ab733b91791e4d93d184f3c7d0779c6a388695 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 22:15:40 +0100 Subject: [PATCH 204/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/it.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index bca842e34..71b7c121f 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -207,13 +207,13 @@ "RequestPanel": { "Delete": "Elimina Richiesta", "Approve": "Approva Richiesta", - "Deny": "Deny Request", + "Deny": "Rifiuta Richiesta", "Approve4K": "Approva Richiesta 4K", - "Deny4K": "Deny 4K Request", + "Deny4K": "Rifiuta Richiesta 4K", "ChangeAvailability": "Segna come Disponibile", "Deleted": "Elementi selezionati eliminati correttamente", "Approved": "Elementi selezionati approvati correttamente", - "Denied": "Successfully denied selected items" + "Denied": "Elementi selezionati rifiutati con successo" }, "SuccessfullyApproved": "Approvata", "SuccessfullyDeleted": "Richiesta eliminata correttamente", From 4fc2c1f24534085a783a3d5791f5533b68272153 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 22:15:41 +0100 Subject: [PATCH 205/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/pt-BR.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pt-BR.json b/src/Ombi/wwwroot/translations/pt-BR.json index 5ac23d0b4..88623edd5 100644 --- a/src/Ombi/wwwroot/translations/pt-BR.json +++ b/src/Ombi/wwwroot/translations/pt-BR.json @@ -207,13 +207,13 @@ "RequestPanel": { "Delete": "Apagar Solicitação", "Approve": "Aprovar Solicitação", - "Deny": "Deny Request", + "Deny": "Recusar pedido", "Approve4K": "Aprovar pedido 4K", - "Deny4K": "Deny 4K Request", + "Deny4K": "Recusar pedido de 4K", "ChangeAvailability": "Marcar Como Disponível", "Deleted": "Successfully deleted selected items", "Approved": "Successfully approved selected items", - "Denied": "Successfully denied selected items" + "Denied": "Itens selecionados negados com sucesso" }, "SuccessfullyApproved": "Successfully Approved", "SuccessfullyDeleted": "Request successfully deleted", From 7b0ad61bfcff3986b33180dc64022cba7ea8eefb Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 23:29:18 +0100 Subject: [PATCH 206/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/fr.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 0dddde0a9..ec7e1c27d 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -207,13 +207,13 @@ "RequestPanel": { "Delete": "Supprimer la demande", "Approve": "Approuver la demande", - "Deny": "Deny Request", + "Deny": "Refuser la demande", "Approve4K": "Approuver la demande 4K", - "Deny4K": "Deny 4K Request", + "Deny4K": "Refuser la demande 4K", "ChangeAvailability": "Marquer comme Disponible", "Deleted": "Éléments sélectionnés supprimés avec succès", "Approved": "Éléments sélectionnés approuvés avec succès", - "Denied": "Successfully denied selected items" + "Denied": "Les éléments sélectionnés ont été refusés" }, "SuccessfullyApproved": "Approuvée avec succès", "SuccessfullyDeleted": "Demande supprimée avec succès", From 0e8a64b8ca00d210fbe843ac2c3f6af218d80cbc Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 13 Apr 2022 23:29:19 +0100 Subject: [PATCH 207/210] =?UTF-8?q?fix(translations):=20=F0=9F=8C=90=20New?= =?UTF-8?q?=20translations=20from=20Crowdin=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/es.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 135806181..bb8cb4a9a 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -207,13 +207,13 @@ "RequestPanel": { "Delete": "Eliminar solicitud", "Approve": "Aprobar Solicitud", - "Deny": "Deny Request", + "Deny": "Rechazar Solicitud", "Approve4K": "Aprobar Solicitud 4K", - "Deny4K": "Deny 4K Request", + "Deny4K": "Rechazar Solicitud 4K", "ChangeAvailability": "Marcar como disponible", "Deleted": "Los elementos seleccionados ha sido eliminados correctamente", "Approved": "Los elementos seleccionados ha sido aprobados correctamente", - "Denied": "Successfully denied selected items" + "Denied": "Elementos seleccionados rechazados con éxito" }, "SuccessfullyApproved": "Se ha aprobado con éxito", "SuccessfullyDeleted": "Solicitud eliminada con éxito", From 75906af0adee3e3c68d825c3aaa8f7b918461b1f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 14 Apr 2022 08:55:19 +0100 Subject: [PATCH 208/210] fix: Set the default job for the watchlist import to hourly instead of daily --- src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs | 2 +- src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs index ff3af5018..950f6f431 100644 --- a/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs +++ b/src/Ombi.Schedule.Tests/PlexWatchlistImportTests.cs @@ -214,7 +214,7 @@ namespace Ombi.Schedule.Tests _mocker.Setup>(x => x.RequestTvShow(It.IsAny())) .ReturnsAsync(new RequestEngineResult { RequestId = 1 }); await _subject.Execute(_context.Object); - _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123)), Times.Once); + _mocker.Verify(x => x.RequestTvShow(It.Is(x => x.TheMovieDbId == 123 && x.LatestSeason == true)), Times.Once); _mocker.Verify(x => x.GetWatchlistMetadata("abc", It.IsAny(), It.IsAny()), Times.Once); _mocker.Verify(x => x.SetUser(It.Is(x => x.Id == "abc")), Times.Once); _mocker.Verify>(x => x.GetAll(), Times.Once); diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index b0839cce6..1a0ea9148 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -57,7 +57,7 @@ namespace Ombi.Settings.Settings.Models public static string PlexWatchlistImport(JobSettings s) { - return ValidateCron(Get(s.PlexWatchlistImport, Cron.Daily())); + return ValidateCron(Get(s.PlexWatchlistImport, Cron.Hourly(25)); } public static string Newsletter(JobSettings s) From 633281889fed9dd75311405fab18156886fb9b6c Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Thu, 14 Apr 2022 07:57:04 +0000 Subject: [PATCH 209/210] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b176283b7..32552817e 100644 --- a/README.md +++ b/README.md @@ -107,18 +107,18 @@ Here are some of the features Ombi has:
- - Magikarplvl4 + + sephrat
- Magikarp Lvl 4 + Sephrat
- - sephrat + + Magikarplvl4
- Sephrat + Magikarp Lvl 4
From 024fdb186955e8ff0af9ed13709f429302b84f75 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 14 Apr 2022 09:13:29 +0100 Subject: [PATCH 210/210] Fixed code --- src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 1a0ea9148..b80943cc5 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -57,7 +57,7 @@ namespace Ombi.Settings.Settings.Models public static string PlexWatchlistImport(JobSettings s) { - return ValidateCron(Get(s.PlexWatchlistImport, Cron.Hourly(25)); + return ValidateCron(Get(s.PlexWatchlistImport, Cron.Hourly(25))); } public static string Newsletter(JobSettings s)