1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-13 20:44:52 -04:00

New: Set Indexer flags in Manual Import

This commit is contained in:
Bogdan
2023-08-01 20:28:12 +03:00
parent 25ab396a2c
commit 9dd31be7b3
36 changed files with 444 additions and 97 deletions

View File

@@ -78,8 +78,8 @@ namespace NzbDrone.Core.CustomFormats
MovieInfo = movieInfo,
Movie = movie,
Size = blocklist.Size ?? 0,
IndexerFlags = blocklist.IndexerFlags,
Languages = blocklist.Languages
Languages = blocklist.Languages,
IndexerFlags = blocklist.IndexerFlags
};
return ParseCustomFormat(input);
@@ -90,7 +90,7 @@ namespace NzbDrone.Core.CustomFormats
var parsed = Parser.Parser.ParseMovieTitle(history.SourceTitle);
long.TryParse(history.Data.GetValueOrDefault("size"), out var size);
Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags flags);
Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags indexerFlags);
var movieInfo = new ParsedMovieInfo
{
@@ -108,8 +108,8 @@ namespace NzbDrone.Core.CustomFormats
MovieInfo = movieInfo,
Movie = movie,
Size = size,
IndexerFlags = flags,
Languages = history.Languages
Languages = history.Languages,
IndexerFlags = indexerFlags
};
return ParseCustomFormat(input);
@@ -117,7 +117,7 @@ namespace NzbDrone.Core.CustomFormats
public List<CustomFormat> ParseCustomFormat(LocalMovie localMovie)
{
var episodeInfo = new ParsedMovieInfo
var movieInfo = new ParsedMovieInfo
{
MovieTitles = new List<string>() { localMovie.Movie.Title },
SimpleReleaseTitle = localMovie.SceneName.IsNotNullOrWhiteSpace() ? localMovie.SceneName.SimplifyReleaseTitle() : Path.GetFileName(localMovie.Path).SimplifyReleaseTitle(),
@@ -130,10 +130,11 @@ namespace NzbDrone.Core.CustomFormats
var input = new CustomFormatInput
{
MovieInfo = episodeInfo,
MovieInfo = movieInfo,
Movie = localMovie.Movie,
Size = localMovie.Size,
Languages = localMovie.Languages,
IndexerFlags = localMovie.IndexerFlags,
Filename = Path.GetFileName(localMovie.Path)
};
@@ -203,8 +204,8 @@ namespace NzbDrone.Core.CustomFormats
MovieInfo = movieInfo,
Movie = movie,
Size = movieFile.Size,
IndexerFlags = movieFile.IndexerFlags,
Languages = movieFile.Languages,
IndexerFlags = movieFile.IndexerFlags,
Filename = Path.GetFileName(movieFile.RelativePath)
};

View File

@@ -15,7 +15,7 @@ namespace NzbDrone.Core.CustomFormats
{
if (!Enum.IsDefined(typeof(IndexerFlags), qualityValue))
{
context.AddFailure(string.Format("Invalid indexer flag condition value: {0}", qualityValue));
context.AddFailure($"Invalid indexer flag condition value: {qualityValue}");
}
});
}
@@ -23,17 +23,17 @@ namespace NzbDrone.Core.CustomFormats
public class IndexerFlagSpecification : CustomFormatSpecificationBase
{
private static readonly IndexerFlagSpecificationValidator Validator = new IndexerFlagSpecificationValidator();
private static readonly IndexerFlagSpecificationValidator Validator = new ();
public override int Order => 4;
public override string ImplementationName => "Indexer Flag";
[FieldDefinition(1, Label = "Flag", Type = FieldType.Select, SelectOptions = typeof(IndexerFlags))]
[FieldDefinition(1, Label = "CustomFormatsSpecificationFlag", Type = FieldType.Select, SelectOptions = typeof(IndexerFlags))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return input.IndexerFlags.HasFlag((IndexerFlags)Value) == true;
return input.IndexerFlags.HasFlag((IndexerFlags)Value);
}
public override NzbDroneValidationResult Validate()

View File

@@ -140,12 +140,11 @@ namespace NzbDrone.Core.Download.TrackedDownloads
var firstHistoryItem = historyItems.FirstOrDefault();
var grabbedEvent = historyItems.FirstOrDefault(v => v.EventType == MovieHistoryEventType.Grabbed);
trackedDownload.Indexer = grabbedEvent?.Data["indexer"];
trackedDownload.Indexer = grabbedEvent?.Data?.GetValueOrDefault("indexer");
trackedDownload.Added = grabbedEvent?.Date;
if (parsedMovieInfo == null ||
trackedDownload.RemoteMovie == null ||
trackedDownload.RemoteMovie.Movie == null)
trackedDownload.RemoteMovie?.Movie == null)
{
parsedMovieInfo = Parser.Parser.ParseMovieTitle(firstHistoryItem.SourceTitle);

View File

@@ -39,18 +39,6 @@ namespace NzbDrone.Core.Indexers.FileList
{
var id = result.Id;
IndexerFlags flags = 0;
if (result.FreeLeech)
{
flags |= IndexerFlags.G_Freeleech;
}
if (result.Internal)
{
flags |= IndexerFlags.G_Internal;
}
var imdbId = 0;
if (result.ImdbId != null && result.ImdbId.Length > 2)
{
@@ -68,14 +56,29 @@ namespace NzbDrone.Core.Indexers.FileList
Peers = result.Leechers + result.Seeders,
PublishDate = result.UploadDate,
ImdbId = imdbId,
IndexerFlags = flags
IndexerFlags = GetIndexerFlags(result)
});
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private static IndexerFlags GetIndexerFlags(FileListTorrent item)
{
IndexerFlags flags = 0;
if (item.FreeLeech)
{
flags |= IndexerFlags.G_Freeleech;
}
if (item.Internal)
{
flags |= IndexerFlags.G_Internal;
}
return flags;
}
private string GetDownloadUrl(string torrentId)
{
@@ -95,5 +98,7 @@ namespace NzbDrone.Core.Indexers.FileList
return url.FullUri;
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
}

View File

@@ -50,19 +50,6 @@ namespace NzbDrone.Core.Indexers.HDBits
foreach (var result in queryResults)
{
var id = result.Id;
var internalRelease = result.TypeOrigin == 1;
IndexerFlags flags = 0;
if (result.FreeLeech == "yes")
{
flags |= IndexerFlags.G_Freeleech;
}
if (internalRelease)
{
flags |= IndexerFlags.G_Internal;
}
torrentInfos.Add(new HDBitsInfo
{
@@ -75,16 +62,30 @@ namespace NzbDrone.Core.Indexers.HDBits
Seeders = result.Seeders,
Peers = result.Leechers + result.Seeders,
PublishDate = result.Added.ToUniversalTime(),
Internal = internalRelease,
ImdbId = result.ImdbInfo?.Id ?? 0,
IndexerFlags = flags
IndexerFlags = GetIndexerFlags(result)
});
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private static IndexerFlags GetIndexerFlags(TorrentQueryResponse item)
{
IndexerFlags flags = 0;
if (item.FreeLeech == "yes")
{
flags |= IndexerFlags.G_Freeleech;
}
if (item.TypeOrigin == 1)
{
flags |= IndexerFlags.G_Internal;
}
return flags;
}
private string GetDownloadUrl(string torrentId)
{
@@ -104,5 +105,7 @@ namespace NzbDrone.Core.Indexers.HDBits
return url.FullUri;
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
}

View File

@@ -193,6 +193,7 @@
"Clear": "Clear",
"ClearBlocklist": "Clear blocklist",
"ClearBlocklistMessageText": "Are you sure you want to clear all items from the blocklist?",
"ClickToChangeIndexerFlags": "Click to change indexer flags",
"ClickToChangeLanguage": "Click to change language",
"ClickToChangeMovie": "Click to change movie",
"ClickToChangeQuality": "Click to change quality",
@@ -255,6 +256,7 @@
"CustomFormatsLoadError": "Unable to load Custom Formats",
"CustomFormatsSettings": "Custom Formats Settings",
"CustomFormatsSettingsSummary": "Custom Formats and Settings",
"CustomFormatsSpecificationFlag": "Flag",
"CustomFormatsSpecificationRegularExpression": "Regular Expression",
"CustomFormatsSpecificationRegularExpressionHelpText": "Custom Format RegEx is Case Insensitive",
"Cutoff": "Cutoff",
@@ -1483,6 +1485,7 @@
"SelectDropdown": "Select...",
"SelectFolder": "Select Folder",
"SelectFolderModalTitle": "{modalTitle} - Select Folder",
"SelectIndexerFlags": "Select Indexer Flags",
"SelectLanguage": "Select Language",
"SelectLanguageModalTitle": "{modalTitle} - Select Language",
"SelectLanguages": "Select Languages",
@@ -1490,6 +1493,8 @@
"SelectQuality": "Select Quality",
"SelectReleaseGroup": "Select Release Group",
"SendAnonymousUsageData": "Send Anonymous Usage Data",
"SetIndexerFlags": "Set Indexer Flags",
"SetIndexerFlagsModalTitle": "{modalTitle} - Set Indexer Flags",
"SetPermissions": "Set Permissions",
"SetPermissionsLinuxHelpText": "Should chmod be run when files are imported/renamed?",
"SetPermissionsLinuxHelpTextWarning": "If you're unsure what these settings do, do not alter them.",

View File

@@ -20,12 +20,12 @@ namespace NzbDrone.Core.MediaFiles
public string OriginalFilePath { get; set; }
public string SceneName { get; set; }
public string ReleaseGroup { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public QualityModel Quality { get; set; }
public List<Language> Languages { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public string Edition { get; set; }
public Movie Movie { get; set; }
public List<Language> Languages { get; set; }
public override string ToString()
{

View File

@@ -108,6 +108,10 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
movieFile.IndexerFlags = flags;
}
}
else
{
movieFile.IndexerFlags = localMovie.IndexerFlags;
}
bool copyOnly;
switch (importMode)

View File

@@ -13,6 +13,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public QualityModel Quality { get; set; }
public List<Language> Languages { get; set; }
public string ReleaseGroup { get; set; }
public int IndexerFlags { get; set; }
public string DownloadId { get; set; }
public int MovieId { get; set; }

View File

@@ -20,6 +20,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public string DownloadId { get; set; }
public List<CustomFormat> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
public Movie Movie { get; set; }

View File

@@ -24,7 +24,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public interface IManualImportService
{
List<ManualImportItem> GetMediaFiles(string path, string downloadId, int? movieId, bool filterExistingFiles);
ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List<Language> languages);
ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags);
}
public class ManualImportService : IExecute<ManualImportCommand>, IManualImportService
@@ -97,7 +97,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
return ProcessFolder(path, path, downloadId, movieId, filterExistingFiles);
}
public ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List<Language> languages)
public ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags)
{
var rootFolder = Path.GetDirectoryName(path);
var movie = _movieService.GetMovie(movieId);
@@ -122,9 +122,10 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
SceneSource = SceneSource(movie, rootFolder),
ExistingFile = movie.Path.IsParentPath(path),
Size = _diskProvider.GetFileSize(path),
ReleaseGroup = releaseGroup.IsNullOrWhiteSpace() ? Parser.Parser.ParseReleaseGroup(path) : releaseGroup,
Languages = languages?.Count <= 1 && (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages,
Quality = (quality?.Quality ?? Quality.Unknown) == Quality.Unknown ? QualityParser.ParseQuality(path) : quality,
ReleaseGroup = releaseGroup.IsNullOrWhiteSpace() ? Parser.Parser.ParseReleaseGroup(path) : releaseGroup,
IndexerFlags = (IndexerFlags)indexerFlags
};
return MapItem(_importDecisionMaker.GetDecision(localMovie, downloadClientItem), rootFolder, downloadId, null);
@@ -320,6 +321,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
item.Languages = decision.LocalMovie.Languages;
item.ReleaseGroup = decision.LocalMovie.ReleaseGroup;
item.Rejections = decision.Rejections;
item.IndexerFlags = (int)decision.LocalMovie.IndexerFlags;
return item;
}
@@ -346,9 +348,10 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
ExistingFile = existingFile,
FileMovieInfo = fileMovieInfo,
Path = file.Path,
ReleaseGroup = file.ReleaseGroup,
Quality = file.Quality,
Languages = file.Languages,
ReleaseGroup = file.ReleaseGroup,
IndexerFlags = (IndexerFlags)file.IndexerFlags,
Movie = movie,
Size = 0
};
@@ -373,9 +376,10 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
// Apply the user-chosen values.
localMovie.Movie = movie;
localMovie.ReleaseGroup = file.ReleaseGroup;
localMovie.Quality = file.Quality;
localMovie.Languages = file.Languages;
localMovie.ReleaseGroup = file.ReleaseGroup;
localMovie.IndexerFlags = (IndexerFlags)file.IndexerFlags;
// TODO: Cleanup non-tracked downloads
var importDecision = new ImportDecision(localMovie);

View File

@@ -26,6 +26,7 @@ namespace NzbDrone.Core.Parser.Model
public List<DeletedMovieFile> OldFiles { get; set; }
public QualityModel Quality { get; set; }
public List<Language> Languages { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public bool ExistingFile { get; set; }
public bool SceneSource { get; set; }

View File

@@ -108,12 +108,12 @@ namespace NzbDrone.Core.Parser.Model
G_DoubleUpload = 4, // General
PTP_Golden = 8, // PTP
PTP_Approved = 16, // PTP
G_Internal = 32, // General, internal
G_Internal = 32, // General, uploader is an internal release group
[Obsolete]
AHD_Internal = 64, // AHD, internal
G_Scene = 128, // General, the torrent comes from the "scene"
G_Freeleech75 = 256, // Currently only used for AHD, signifies a torrent counts towards 75 percent of your download quota.
G_Freeleech25 = 512, // Currently only used for AHD, signifies a torrent counts towards 25 percent of your download quota.
G_Scene = 128, // General, the torrent comes from a "scene" group
G_Freeleech75 = 256, // Signifies a torrent counts towards 75 percent of your download quota.
G_Freeleech25 = 512, // Signifies a torrent counts towards 25 percent of your download quota.
[Obsolete]
AHD_UserRelease = 1024 // AHD, internal
}

View File

@@ -45,7 +45,6 @@ namespace Radarr.Api.V3.Indexers
public string InfoUrl { get; set; }
public bool DownloadAllowed { get; set; }
public int ReleaseWeight { get; set; }
public IEnumerable<string> IndexerFlags { get; set; }
public string Edition { get; set; }
public string MagnetUrl { get; set; }
@@ -53,6 +52,7 @@ namespace Radarr.Api.V3.Indexers
public int? Seeders { get; set; }
public int? Leechers { get; set; }
public DownloadProtocol Protocol { get; set; }
public int IndexerFlags { get; set; }
// Sent when queuing an unknown release
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
@@ -76,7 +76,7 @@ namespace Radarr.Api.V3.Indexers
var parsedMovieInfo = model.RemoteMovie.ParsedMovieInfo;
var remoteMovie = model.RemoteMovie;
var torrentInfo = (model.RemoteMovie.Release as TorrentInfo) ?? new TorrentInfo();
var indexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None).Where(x => x != "0");
var indexerFlags = torrentInfo.IndexerFlags;
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
return new ReleaseResource
@@ -118,7 +118,7 @@ namespace Radarr.Api.V3.Indexers
Seeders = torrentInfo.Seeders,
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
Protocol = releaseInfo.DownloadProtocol,
IndexerFlags = indexerFlags
IndexerFlags = (int)indexerFlags
};
}

View File

@@ -34,9 +34,10 @@ namespace Radarr.Api.V3.ManualImport
{
foreach (var item in items)
{
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.MovieId, item.ReleaseGroup, item.Quality, item.Languages);
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.MovieId, item.ReleaseGroup, item.Quality, item.Languages, item.IndexerFlags);
item.Movie = processedItem.Movie.ToResource(0);
item.IndexerFlags = processedItem.IndexerFlags;
item.Rejections = processedItem.Rejections;
item.CustomFormats = processedItem.CustomFormats.ToResource(false);
item.CustomFormatScore = processedItem.CustomFormatScore;

View File

@@ -19,6 +19,7 @@ namespace Radarr.Api.V3.ManualImport
public string DownloadId { get; set; }
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}
}

View File

@@ -26,6 +26,7 @@ namespace Radarr.Api.V3.ManualImport
public string DownloadId { get; set; }
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}
@@ -58,6 +59,7 @@ namespace Radarr.Api.V3.ManualImport
// QualityWeight
DownloadId = model.DownloadId,
IndexerFlags = model.IndexerFlags,
Rejections = model.Rejections
};
}

View File

@@ -19,16 +19,17 @@ namespace Radarr.Api.V3.MovieFiles
public long Size { get; set; }
public DateTime DateAdded { get; set; }
public string SceneName { get; set; }
public int IndexerFlags { get; set; }
public string ReleaseGroup { get; set; }
public string Edition { get; set; }
public List<Language> Languages { get; set; }
public QualityModel Quality { get; set; }
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int? IndexerFlags { get; set; }
public MediaInfoResource MediaInfo { get; set; }
public string OriginalFilePath { get; set; }
public bool QualityCutoffNotMet { get; set; }
public List<Language> Languages { get; set; }
public string ReleaseGroup { get; set; }
public string Edition { get; set; }
}
public static class MovieFileResourceMapper
@@ -78,14 +79,14 @@ namespace Radarr.Api.V3.MovieFiles
Size = model.Size,
DateAdded = model.DateAdded,
SceneName = model.SceneName,
IndexerFlags = (int)model.IndexerFlags,
Quality = model.Quality,
Languages = model.Languages,
Edition = model.Edition,
ReleaseGroup = model.ReleaseGroup,
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
QualityCutoffNotMet = upgradableSpecification?.QualityCutoffNotMet(movie.QualityProfile, model.Quality) ?? false,
OriginalFilePath = model.OriginalFilePath
OriginalFilePath = model.OriginalFilePath,
IndexerFlags = (int)model.IndexerFlags
};
if (formatCalculationService != null)