From b1f128fee856acef8afdb562d3719ccc24dc1110 Mon Sep 17 00:00:00 2001 From: Willie Slepecki Date: Fri, 4 Oct 2024 13:47:43 -0400 Subject: [PATCH] Add retroactive tag application to import lists This commit introduces a new feature allowing tags to be retroactively applied to movies already in the database. Changes include database migration for the new column, updates to the frontend to manage this feature, and backend logic to handle retroactive tagging. --- .../ImportLists/EditImportListModalContent.js | 13 +++++++++++ .../Manage/ManageImportListsModalContent.tsx | 6 +++++ .../Manage/ManageImportListsModalRow.tsx | 6 +++++ src/Directory.Build.props | 2 +- .../241_add_retroapply_to_importlists.cs | 13 +++++++++++ .../ImportLists/ImportListSyncService.cs | 23 ++++++++++++++++++- src/NzbDrone.Core/Localization/Core/en.json | 2 ++ .../ThingiProvider/ProviderDefinition.cs | 1 + src/Radarr.Api.V3/ProviderResource.cs | 5 +++- 9 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/NzbDrone.Core/Datastore/Migration/241_add_retroapply_to_importlists.cs diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js index d80427d48e..03756adec9 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js +++ b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js @@ -55,6 +55,7 @@ function EditImportListModalContent(props) { rootFolderPath, searchOnAdd, tags, + retroApplyTags, fields, message } = item; @@ -225,6 +226,18 @@ function EditImportListModalContent(props) { /> + + {translate('RadarrRetroactiveApply')} + + + + { fields.map((field) => { return ( diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx index 37e962a260..a854c31c40 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx @@ -82,6 +82,12 @@ const COLUMNS = [ isSortable: true, isVisible: true, }, + { + name: 'retroApplyTags', + label: () => translate('RetroApplyTags'), + isSortable: true, + isVisible: true, + }, ]; interface ManageImportListsModalContentProps { diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx index 829ed94c49..92e6b2b013 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalRow.tsx @@ -19,6 +19,7 @@ interface ManageImportListsModalRowProps { minimumAvailability: string; implementation: string; tags: number[]; + retroApplyTags: boolean; enabled: boolean; enableAuto: boolean; columns: Column[]; @@ -38,6 +39,7 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) { enabled, enableAuto, tags, + retroApplyTags, onSelectedChange, } = props; @@ -91,6 +93,10 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) { + + + {retroApplyTags ? translate('Yes') : translate('No')} + ); } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 174d1cb8a2..1e722177f0 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -221,7 +221,7 @@ <_UsingDefaultRuntimeIdentifier>true - osx-x64 + osx-$(Architecture) diff --git a/src/NzbDrone.Core/Datastore/Migration/241_add_retroapply_to_importlists.cs b/src/NzbDrone.Core/Datastore/Migration/241_add_retroapply_to_importlists.cs new file mode 100644 index 0000000000..2b80ffd0ca --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/241_add_retroapply_to_importlists.cs @@ -0,0 +1,13 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration; + +[Migration(241)] +public class add_retroapply_to_importlists : NzbDroneMigrationBase +{ + protected override void MainDbUpgrade() + { + Alter.Table("ImportLists").AddColumn("RetroApplyTags").AsInt32().WithDefaultValue(0); + } +} diff --git a/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs b/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs index 60c118a6a0..84c5da6b4c 100644 --- a/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs +++ b/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs @@ -81,9 +81,10 @@ private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie return; } - // Check to see if movie in DB + // Check to see if movie in DB and maybe apply retro-tags if (dbMovies.Contains(report.TmdbId)) { + RetroApplyTags(importList, report); _logger.Debug("{0} [{1}] Rejected, Movie Exists in DB", report.TmdbId, report.Title); return; } @@ -123,6 +124,26 @@ private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie } } + private void RetroApplyTags(ImportListDefinition importList, ImportListMovie report) + { + if (importList.RetroApplyTags) + { + var movie = _movieService.FindByTmdbId(report.TmdbId); + + var preCount = movie.Tags.Count; + foreach (var tag in importList.Tags) + { + movie.Tags.Add(tag); + } + + if (preCount != movie.Tags.Count) + { + _movieService.UpdateMovie(movie); + _logger.Debug("{0} [{1}] Retro-Actively added tags to movie", report.TmdbId, report.Title); + } + } + } + private void ProcessListItems(ImportListFetchResult listFetchResult) { listFetchResult.Movies = listFetchResult.Movies.DistinctBy(x => diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 884c7394ce..f21cd84a69 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -841,6 +841,7 @@ "ListSyncLevelHelpText": "Movies in library will be handled based on your selection if they fall off or do not appear on your list(s)", "ListSyncLevelHelpTextWarning": "Movie files will be permanently deleted, this can result in wiping your library if your lists are empty", "ListTagsHelpText": "Tags list items will be added with", + "RetroApplyListTagsHelpText": "Retro-Actively apply tags to movies already in Radarr", "ListWillRefreshEveryInterval": "List will refresh every {refreshInterval}", "Lists": "Lists", "Loading": "Loading", @@ -1366,6 +1367,7 @@ "Queued": "Queued", "QuickImport": "Move Automatically", "RadarrTags": "{appName} Tags", + "RadarrRetroactiveApply": "Retro-Apply Tags", "Rating": "Rating", "Ratings": "Ratings", "ReadTheWikiForMoreInformation": "Read the Wiki for more information", diff --git a/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs b/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs index a4c5db45b0..449af4c7ae 100644 --- a/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs +++ b/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs @@ -28,6 +28,7 @@ protected ProviderDefinition() public ProviderMessage Message { get; set; } public HashSet Tags { get; set; } + public bool RetroApplyTags { get; set; } [MemberwiseEqualityIgnore] public IProviderConfig Settings diff --git a/src/Radarr.Api.V3/ProviderResource.cs b/src/Radarr.Api.V3/ProviderResource.cs index c5e8a1cd6f..4cecc4f0b4 100644 --- a/src/Radarr.Api.V3/ProviderResource.cs +++ b/src/Radarr.Api.V3/ProviderResource.cs @@ -16,6 +16,7 @@ public class ProviderResource : RestResource public string InfoLink { get; set; } public ProviderMessage Message { get; set; } public HashSet Tags { get; set; } + public bool RetroApplyTags { get; set; } public List Presets { get; set; } } @@ -36,6 +37,7 @@ public virtual TProviderResource ToResource(TProviderDefinition definition) ConfigContract = definition.ConfigContract, Message = definition.Message, Tags = definition.Tags, + RetroApplyTags = definition.RetroApplyTags, Fields = SchemaBuilder.ToSchema(definition.Settings), // radarr/supported is an disambiguation page. the # should be a header on the page with appropriate details/link @@ -60,7 +62,8 @@ public virtual TProviderDefinition ToModel(TProviderResource resource, TProvider Implementation = resource.Implementation, ConfigContract = resource.ConfigContract, Message = resource.Message, - Tags = resource.Tags + Tags = resource.Tags, + RetroApplyTags = resource.RetroApplyTags, }; var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);