mirror of
https://github.com/Radarr/Radarr
synced 2026-05-08 15:21:29 +02:00
Merge 68c3400bb0 into 065414211d
This commit is contained in:
commit
cb18445255
14 changed files with 100 additions and 4 deletions
|
|
@ -78,6 +78,7 @@ function EditImportListModalContent({
|
||||||
qualityProfileId,
|
qualityProfileId,
|
||||||
searchOnAdd,
|
searchOnAdd,
|
||||||
tags,
|
tags,
|
||||||
|
tagExisting,
|
||||||
fields,
|
fields,
|
||||||
} = item;
|
} = item;
|
||||||
|
|
||||||
|
|
@ -256,6 +257,18 @@ function EditImportListModalContent({
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('TagExisting')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="tagExisting"
|
||||||
|
helpText={translate('TagExistingHelpText')}
|
||||||
|
{...tagExisting}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
{fields?.length ? (
|
{fields?.length ? (
|
||||||
<div>
|
<div>
|
||||||
{fields.map((field) => {
|
{fields.map((field) => {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ interface SavePayload {
|
||||||
qualityProfileId?: number;
|
qualityProfileId?: number;
|
||||||
minimumAvailability?: string;
|
minimumAvailability?: string;
|
||||||
rootFolderPath?: string;
|
rootFolderPath?: string;
|
||||||
|
tagExisting?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ManageImportListsEditModalContentProps {
|
interface ManageImportListsEditModalContentProps {
|
||||||
|
|
@ -62,7 +63,7 @@ function ManageImportListsEditModalContent(
|
||||||
);
|
);
|
||||||
const [minimumAvailability, setMinimumAvailability] = useState(NO_CHANGE);
|
const [minimumAvailability, setMinimumAvailability] = useState(NO_CHANGE);
|
||||||
const [rootFolderPath, setRootFolderPath] = useState(NO_CHANGE);
|
const [rootFolderPath, setRootFolderPath] = useState(NO_CHANGE);
|
||||||
|
const [tagExisting, setTagExisting] = useState(NO_CHANGE);
|
||||||
const save = useCallback(() => {
|
const save = useCallback(() => {
|
||||||
let hasChanges = false;
|
let hasChanges = false;
|
||||||
const payload: SavePayload = {};
|
const payload: SavePayload = {};
|
||||||
|
|
@ -91,6 +92,10 @@ function ManageImportListsEditModalContent(
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
payload.rootFolderPath = rootFolderPath;
|
payload.rootFolderPath = rootFolderPath;
|
||||||
}
|
}
|
||||||
|
if (tagExisting !== NO_CHANGE) {
|
||||||
|
hasChanges = true;
|
||||||
|
payload.tagExisting = tagExisting === 'enabled';
|
||||||
|
}
|
||||||
|
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
onSavePress(payload);
|
onSavePress(payload);
|
||||||
|
|
@ -103,6 +108,7 @@ function ManageImportListsEditModalContent(
|
||||||
qualityProfileId,
|
qualityProfileId,
|
||||||
minimumAvailability,
|
minimumAvailability,
|
||||||
rootFolderPath,
|
rootFolderPath,
|
||||||
|
tagExisting,
|
||||||
onSavePress,
|
onSavePress,
|
||||||
onModalClose,
|
onModalClose,
|
||||||
]);
|
]);
|
||||||
|
|
@ -124,6 +130,9 @@ function ManageImportListsEditModalContent(
|
||||||
case 'rootFolderPath':
|
case 'rootFolderPath':
|
||||||
setRootFolderPath(value as string);
|
setRootFolderPath(value as string);
|
||||||
break;
|
break;
|
||||||
|
case 'tagExisting':
|
||||||
|
setTagExisting(value as string);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn(`EditImportListModalContent Unknown Input: '${name}'`);
|
console.warn(`EditImportListModalContent Unknown Input: '${name}'`);
|
||||||
}
|
}
|
||||||
|
|
@ -199,6 +208,18 @@ function ManageImportListsEditModalContent(
|
||||||
onChange={onInputChange}
|
onChange={onInputChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('TagExisting')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.SELECT}
|
||||||
|
name="tagExisting"
|
||||||
|
value={tagExisting}
|
||||||
|
values={enableOptions}
|
||||||
|
onChange={onInputChange}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter className={styles.modalFooter}>
|
<ModalFooter className={styles.modalFooter}>
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ const COLUMNS = [
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'tagExisting',
|
||||||
|
label: () => translate('TagExisting'),
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
interface ManageImportListsModalContentProps {
|
interface ManageImportListsModalContentProps {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
.minimumAvailability,
|
.minimumAvailability,
|
||||||
.qualityProfileId,
|
.qualityProfileId,
|
||||||
.rootFolderPath,
|
.rootFolderPath,
|
||||||
|
.tagExisting,
|
||||||
.implementation {
|
.implementation {
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ interface CssExports {
|
||||||
'name': string;
|
'name': string;
|
||||||
'qualityProfileId': string;
|
'qualityProfileId': string;
|
||||||
'rootFolderPath': string;
|
'rootFolderPath': string;
|
||||||
|
'tagExisting': string;
|
||||||
'tags': string;
|
'tags': string;
|
||||||
}
|
}
|
||||||
export const cssExports: CssExports;
|
export const cssExports: CssExports;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ interface ManageImportListsModalRowProps {
|
||||||
minimumAvailability: string;
|
minimumAvailability: string;
|
||||||
implementation: string;
|
implementation: string;
|
||||||
tags: number[];
|
tags: number[];
|
||||||
|
tagExisting: boolean;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
enableAuto: boolean;
|
enableAuto: boolean;
|
||||||
columns: Column[];
|
columns: Column[];
|
||||||
|
|
@ -38,6 +39,7 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) {
|
||||||
enabled,
|
enabled,
|
||||||
enableAuto,
|
enableAuto,
|
||||||
tags,
|
tags,
|
||||||
|
tagExisting,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
|
@ -91,6 +93,10 @@ function ManageImportListsModalRow(props: ManageImportListsModalRowProps) {
|
||||||
<TableRowCell className={styles.tags}>
|
<TableRowCell className={styles.tags}>
|
||||||
<MovieTagList tags={tags} />
|
<MovieTagList tags={tags} />
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
|
|
||||||
|
<TableRowCell className={styles.tagExisting}>
|
||||||
|
{tagExisting ? translate('Yes') : translate('No')}
|
||||||
|
</TableRowCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ interface ImportList extends Provider {
|
||||||
minRefreshInterval: string;
|
minRefreshInterval: string;
|
||||||
name: string;
|
name: string;
|
||||||
tags: number[];
|
tags: number[];
|
||||||
|
tagExisting: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImportList;
|
export default ImportList;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration;
|
||||||
|
|
||||||
|
[Migration(243)]
|
||||||
|
public class add_tag_existing_to_importlists : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("ImportLists").AddColumn("TagExisting").AsBoolean().WithDefaultValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ public class ImportListDefinition : ProviderDefinition, IEquatable<ImportListDef
|
||||||
public int QualityProfileId { get; set; }
|
public int QualityProfileId { get; set; }
|
||||||
public string RootFolderPath { get; set; }
|
public string RootFolderPath { get; set; }
|
||||||
public bool SearchOnAdd { get; set; }
|
public bool SearchOnAdd { get; set; }
|
||||||
|
public bool TagExisting { get; set; }
|
||||||
|
|
||||||
[MemberwiseEqualityIgnore]
|
[MemberwiseEqualityIgnore]
|
||||||
public override bool Enable => Enabled;
|
public override bool Enable => Enabled;
|
||||||
|
|
|
||||||
|
|
@ -76,18 +76,25 @@ private void SyncList(ImportListDefinition definition)
|
||||||
|
|
||||||
private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie report, List<ImportListExclusion> listExclusions, List<int> dbMovies, List<Movie> moviesToAdd)
|
private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie report, List<ImportListExclusion> listExclusions, List<int> dbMovies, List<Movie> moviesToAdd)
|
||||||
{
|
{
|
||||||
if (report.TmdbId == 0 || !importList.EnableAuto)
|
if (report.TmdbId == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if movie in DB
|
// Check to see if movie in DB and maybe apply tags
|
||||||
if (dbMovies.Contains(report.TmdbId))
|
if (dbMovies.Contains(report.TmdbId))
|
||||||
{
|
{
|
||||||
|
TagExisting(importList, report);
|
||||||
_logger.Debug("{0} [{1}] Rejected, Movie Exists in DB", report.TmdbId, report.Title);
|
_logger.Debug("{0} [{1}] Rejected, Movie Exists in DB", report.TmdbId, report.Title);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that retro-tags are applied, end if auto import is disabled
|
||||||
|
if (!importList.EnableAuto)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see if movie excluded
|
// Check to see if movie excluded
|
||||||
var excludedMovie = listExclusions.SingleOrDefault(s => s.TmdbId == report.TmdbId);
|
var excludedMovie = listExclusions.SingleOrDefault(s => s.TmdbId == report.TmdbId);
|
||||||
|
|
||||||
|
|
@ -123,6 +130,26 @@ private void ProcessMovieReport(ImportListDefinition importList, ImportListMovie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TagExisting(ImportListDefinition importList, ImportListMovie report)
|
||||||
|
{
|
||||||
|
if (importList.TagExisting)
|
||||||
|
{
|
||||||
|
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}] Tagged existing movie", report.TmdbId, report.Title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ProcessListItems(ImportListFetchResult listFetchResult)
|
private void ProcessListItems(ImportListFetchResult listFetchResult)
|
||||||
{
|
{
|
||||||
listFetchResult.Movies = listFetchResult.Movies.DistinctBy(x =>
|
listFetchResult.Movies = listFetchResult.Movies.DistinctBy(x =>
|
||||||
|
|
|
||||||
|
|
@ -1697,6 +1697,8 @@
|
||||||
"Result": "Result",
|
"Result": "Result",
|
||||||
"Retention": "Retention",
|
"Retention": "Retention",
|
||||||
"RetentionHelpText": "Usenet only: Set to zero to set for unlimited retention",
|
"RetentionHelpText": "Usenet only: Set to zero to set for unlimited retention",
|
||||||
|
"TagExistingHelpText": "Tag existing movies in {appName}",
|
||||||
|
"TagExisting": "Tag Existing",
|
||||||
"RetryingDownloadOn": "Retrying download on {date} at {time}",
|
"RetryingDownloadOn": "Retrying download on {date} at {time}",
|
||||||
"RootFolder": "Root Folder",
|
"RootFolder": "Root Folder",
|
||||||
"RootFolderCheckMultipleMessage": "Multiple root folders are missing: {rootFolderPaths}",
|
"RootFolderCheckMultipleMessage": "Multiple root folders are missing: {rootFolderPaths}",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ public class ImportListBulkResource : ProviderBulkResource<ImportListBulkResourc
|
||||||
public string RootFolderPath { get; set; }
|
public string RootFolderPath { get; set; }
|
||||||
public int? QualityProfileId { get; set; }
|
public int? QualityProfileId { get; set; }
|
||||||
public MovieStatusType? MinimumAvailability { get; set; }
|
public MovieStatusType? MinimumAvailability { get; set; }
|
||||||
|
public bool? TagExisting { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportListBulkResourceMapper : ProviderBulkResourceMapper<ImportListBulkResource, ImportListDefinition>
|
public class ImportListBulkResourceMapper : ProviderBulkResourceMapper<ImportListBulkResource, ImportListDefinition>
|
||||||
|
|
@ -29,6 +30,7 @@ public override List<ImportListDefinition> UpdateModel(ImportListBulkResource re
|
||||||
existing.RootFolderPath = resource.RootFolderPath ?? existing.RootFolderPath;
|
existing.RootFolderPath = resource.RootFolderPath ?? existing.RootFolderPath;
|
||||||
existing.QualityProfileId = resource.QualityProfileId ?? existing.QualityProfileId;
|
existing.QualityProfileId = resource.QualityProfileId ?? existing.QualityProfileId;
|
||||||
existing.MinimumAvailability = resource.MinimumAvailability ?? existing.MinimumAvailability;
|
existing.MinimumAvailability = resource.MinimumAvailability ?? existing.MinimumAvailability;
|
||||||
|
existing.TagExisting = resource.TagExisting ?? existing.TagExisting;
|
||||||
});
|
});
|
||||||
|
|
||||||
return existingDefinitions;
|
return existingDefinitions;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ public class ImportListResource : ProviderResource<ImportListResource>
|
||||||
public ImportListType ListType { get; set; }
|
public ImportListType ListType { get; set; }
|
||||||
public int ListOrder { get; set; }
|
public int ListOrder { get; set; }
|
||||||
public TimeSpan MinRefreshInterval { get; set; }
|
public TimeSpan MinRefreshInterval { get; set; }
|
||||||
|
public bool TagExisting { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportListResourceMapper : ProviderResourceMapper<ImportListResource, ImportListDefinition>
|
public class ImportListResourceMapper : ProviderResourceMapper<ImportListResource, ImportListDefinition>
|
||||||
|
|
@ -39,6 +40,7 @@ public override ImportListResource ToResource(ImportListDefinition definition)
|
||||||
resource.ListType = definition.ListType;
|
resource.ListType = definition.ListType;
|
||||||
resource.ListOrder = (int)definition.ListType;
|
resource.ListOrder = (int)definition.ListType;
|
||||||
resource.MinRefreshInterval = definition.MinRefreshInterval;
|
resource.MinRefreshInterval = definition.MinRefreshInterval;
|
||||||
|
resource.TagExisting = definition.TagExisting;
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
@ -61,6 +63,7 @@ public override ImportListDefinition ToModel(ImportListResource resource, Import
|
||||||
definition.MinimumAvailability = resource.MinimumAvailability;
|
definition.MinimumAvailability = resource.MinimumAvailability;
|
||||||
definition.ListType = resource.ListType;
|
definition.ListType = resource.ListType;
|
||||||
definition.MinRefreshInterval = resource.MinRefreshInterval;
|
definition.MinRefreshInterval = resource.MinRefreshInterval;
|
||||||
|
definition.TagExisting = resource.TagExisting;
|
||||||
|
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ public class ProviderResource<T> : RestResource
|
||||||
public string InfoLink { get; set; }
|
public string InfoLink { get; set; }
|
||||||
public ProviderMessage Message { get; set; }
|
public ProviderMessage Message { get; set; }
|
||||||
public HashSet<int> Tags { get; set; }
|
public HashSet<int> Tags { get; set; }
|
||||||
|
|
||||||
public List<T> Presets { get; set; }
|
public List<T> Presets { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue