1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-25 02:30:20 +02:00

Start of adding indexer to specifications

This will get renamed and squashed later dw
This commit is contained in:
Arthur Melton 2024-07-01 19:09:16 -04:00
parent 6de536a7ad
commit 45619a1df3
20 changed files with 97 additions and 5 deletions

View File

@ -21,6 +21,7 @@ public class Blocklist : ModelBase
public long? Size { get; set; }
public DownloadProtocol Protocol { get; set; }
public string Indexer { get; set; }
public int IndexerId { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public ReleaseType ReleaseType { get; set; }
public string Message { get; set; }

View File

@ -83,6 +83,7 @@ public void Block(RemoteEpisode remoteEpisode, string message)
PublishedDate = remoteEpisode.Release.PublishDate,
Size = remoteEpisode.Release.Size,
Indexer = remoteEpisode.Release.Indexer,
IndexerId = remoteEpisode.Release.IndexerId,
Protocol = remoteEpisode.Release.DownloadProtocol,
Message = message,
Languages = remoteEpisode.ParsedEpisodeInfo.Languages
@ -183,6 +184,7 @@ public void Handle(DownloadFailedEvent message)
PublishedDate = DateTime.Parse(message.Data.GetValueOrDefault("publishedDate")),
Size = long.Parse(message.Data.GetValueOrDefault("size", "0")),
Indexer = message.Data.GetValueOrDefault("indexer"),
IndexerId = int.Parse(message.Data.GetValueOrDefault("indexerId")),
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
Message = message.Message,
TorrentInfoHash = message.Data.GetValueOrDefault("torrentInfoHash"),

View File

@ -42,7 +42,8 @@ public List<CustomFormat> ParseCustomFormat(RemoteEpisode remoteEpisode, long si
Size = size,
Languages = remoteEpisode.Languages,
IndexerFlags = remoteEpisode.Release?.IndexerFlags ?? 0,
ReleaseType = remoteEpisode.ParsedEpisodeInfo.ReleaseType
ReleaseType = remoteEpisode.ParsedEpisodeInfo.ReleaseType,
IndexerId = remoteEpisode.Release?.IndexerId ?? 0,
};
return ParseCustomFormat(input);
@ -78,7 +79,8 @@ public List<CustomFormat> ParseCustomFormat(Blocklist blocklist, Series series)
Size = blocklist.Size ?? 0,
Languages = blocklist.Languages,
IndexerFlags = blocklist.IndexerFlags,
ReleaseType = blocklist.ReleaseType
ReleaseType = blocklist.ReleaseType,
IndexerId = blocklist.IndexerId,
};
return ParseCustomFormat(input);
@ -89,6 +91,7 @@ public List<CustomFormat> ParseCustomFormat(EpisodeHistory history, Series serie
var parsed = Parser.Parser.ParseTitle(history.SourceTitle);
long.TryParse(history.Data.GetValueOrDefault("size"), out var size);
int.TryParse(history.Data.GetValueOrDefault("indexerId"), out var indexerId);
Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags indexerFlags);
Enum.TryParse(history.Data.GetValueOrDefault("releaseType"), out ReleaseType releaseType);
@ -108,6 +111,7 @@ public List<CustomFormat> ParseCustomFormat(EpisodeHistory history, Series serie
Size = size,
Languages = history.Languages,
IndexerFlags = indexerFlags,
IndexerId = indexerId,
ReleaseType = releaseType
};
@ -132,6 +136,7 @@ public List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode)
Size = localEpisode.Size,
Languages = localEpisode.Languages,
IndexerFlags = localEpisode.IndexerFlags,
IndexerId = localEpisode.Release.IndexerId,
ReleaseType = localEpisode.ReleaseType,
Filename = Path.GetFileName(localEpisode.Path)
};
@ -203,6 +208,7 @@ private List<CustomFormat> ParseCustomFormat(EpisodeFile episodeFile, Series ser
Size = episodeFile.Size,
Languages = episodeFile.Languages,
IndexerFlags = episodeFile.IndexerFlags,
IndexerId = episodeFile.IndexerId,
ReleaseType = episodeFile.ReleaseType,
Filename = Path.GetFileName(episodeFile.RelativePath),
};

View File

@ -11,6 +11,7 @@ public class CustomFormatInput
public Series Series { get; set; }
public long Size { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public int IndexerId { get; set; }
public List<Language> Languages { get; set; }
public string Filename { get; set; }
public ReleaseType ReleaseType { get; set; }

View File

@ -0,0 +1,44 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class IndexerSpecificationValidator : AbstractValidator<IndexerSpecification>
{
public IndexerSpecificationValidator(/*IIndexerFactory indexerFactory*/)
{
RuleFor(c => c.Value).NotEmpty();
/*
RuleFor(c => c.Value).Custom((indexerId, context) =>
{
if (indexerId != 0 && !indexerFactory.Exists(indexerId))
{
context.AddFailure($"Invalid indexer value: {indexerId}");
}
});
*/
}
}
public class IndexerSpecification : CustomFormatSpecificationBase
{
private static readonly IndexerSpecificationValidator Validator = new ();
public override int Order => 11;
public override string ImplementationName => "Indexer";
[FieldDefinition(1, Label = "CustomFormatsSpecificationIndexer", Type = FieldType.Select, SelectOptionsProviderAction = "getIndexersList")]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return input.IndexerId == Value;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@ -170,6 +170,7 @@ public void Handle(EpisodeGrabbedEvent message)
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
history.Data.Add("ReleaseSource", message.Episode.ReleaseSource.ToString());
history.Data.Add("IndexerFlags", message.Episode.Release.IndexerFlags.ToString());
history.Data.Add("IndexerId", message.Episode.Release.IndexerId.ToString());
history.Data.Add("ReleaseType", message.Episode.ParsedEpisodeInfo.ReleaseType.ToString());
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
@ -223,6 +224,7 @@ public void Handle(EpisodeImportedEvent message)
history.Data.Add("CustomFormatScore", message.EpisodeInfo.CustomFormatScore.ToString());
history.Data.Add("Size", message.EpisodeInfo.Size.ToString());
history.Data.Add("IndexerFlags", message.ImportedEpisode.IndexerFlags.ToString());
history.Data.Add("IndexerId", message.ImportedEpisode.IndexerId.ToString());
history.Data.Add("ReleaseType", message.ImportedEpisode.ReleaseType.ToString());
_historyRepository.Insert(history);
@ -284,6 +286,7 @@ public void Handle(EpisodeFileDeletedEvent message)
history.Data.Add("Reason", message.Reason.ToString());
history.Data.Add("ReleaseGroup", message.EpisodeFile.ReleaseGroup);
history.Data.Add("Size", message.EpisodeFile.Size.ToString());
history.Data.Add("IndexerId", message.EpisodeFile.IndexerId.ToString());
history.Data.Add("IndexerFlags", message.EpisodeFile.IndexerFlags.ToString());
history.Data.Add("ReleaseType", message.EpisodeFile.ReleaseType.ToString());
@ -318,6 +321,7 @@ public void Handle(EpisodeFileRenamedEvent message)
history.Data.Add("ReleaseGroup", message.EpisodeFile.ReleaseGroup);
history.Data.Add("Size", message.EpisodeFile.Size.ToString());
history.Data.Add("IndexerFlags", message.EpisodeFile.IndexerFlags.ToString());
history.Data.Add("IndexerId", message.EpisodeFile.IndexerId.ToString());
history.Data.Add("ReleaseType", message.EpisodeFile.ReleaseType.ToString());
_historyRepository.Insert(history);

View File

@ -37,6 +37,18 @@ protected override List<IndexerDefinition> Active()
return base.Active().Where(c => c.Enable).ToList();
}
public virtual object RequestAction(string action, IDictionary<string, string> query)
{
_logger.Info("HELLO WORLD");
if (action == "getIndexerList")
{
return GetAvailableProviders();
}
return new { };
}
public override void SetProviderCharacteristics(IIndexer provider, IndexerDefinition definition)
{
base.SetProviderCharacteristics(provider, definition);

View File

@ -284,6 +284,7 @@
"CustomFormatsSettingsSummary": "Custom Formats and Settings",
"CustomFormatsSettingsTriggerInfo": "A Custom Format will be applied to a release or file when it matches at least one of each of the different condition types chosen.",
"CustomFormatsSpecificationFlag": "Flag",
"CustomFormatsSpecificationIndexer": "Indexer",
"CustomFormatsSpecificationLanguage": "Language",
"CustomFormatsSpecificationMaximumSize": "Maximum Size",
"CustomFormatsSpecificationMaximumSizeHelpText": "Release must be less than or equal to this size",

View File

@ -23,6 +23,7 @@ public class EpisodeFile : ModelBase
public string ReleaseGroup { get; set; }
public string ReleaseHash { get; set; }
public QualityModel Quality { get; set; }
public int IndexerId { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public LazyLoaded<List<Episode>> Episodes { get; set; }

View File

@ -97,6 +97,7 @@ public List<ImportResult> Import(List<ImportDecision> decisions, bool newDownloa
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
episodeFile.ReleaseHash = localEpisode.ReleaseHash;
episodeFile.Languages = localEpisode.Languages;
episodeFile.IndexerId = localEpisode.IndexerId;
// Prefer the release type from the download client, folder and finally the file so we have the most accurate information.
episodeFile.ReleaseType = localEpisode.DownloadClientEpisodeInfo?.ReleaseType ??

View File

@ -18,6 +18,7 @@ public class ManualImportFile : IEquatable<ManualImportFile>
public List<Language> Languages { get; set; }
public string ReleaseGroup { get; set; }
public int IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType ReleaseType { get; set; }
public string DownloadId { get; set; }

View File

@ -26,6 +26,7 @@ public class ManualImportItem
public List<CustomFormat> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType ReleaseType { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }

View File

@ -25,7 +25,7 @@ public interface IManualImportService
{
List<ManualImportItem> GetMediaFiles(int seriesId, int? seasonNumber);
List<ManualImportItem> GetMediaFiles(string path, string downloadId, int? seriesId, bool filterExistingFiles);
ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, int? seasonNumber, List<int> episodeIds, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags, ReleaseType releaseType);
ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, int? seasonNumber, List<int> episodeIds, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags, int indexerId, ReleaseType releaseType);
}
public class ManualImportService : IExecute<ManualImportCommand>, IManualImportService
@ -139,7 +139,7 @@ public List<ManualImportItem> GetMediaFiles(string path, string downloadId, int?
return ProcessFolder(path, path, downloadId, seriesId, filterExistingFiles);
}
public ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, int? seasonNumber, List<int> episodeIds, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags, ReleaseType releaseType)
public ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, int? seasonNumber, List<int> episodeIds, string releaseGroup, QualityModel quality, List<Language> languages, int indexerFlags, int indexerId, ReleaseType releaseType)
{
var rootFolder = Path.GetDirectoryName(path);
var series = _seriesService.GetSeries(seriesId);
@ -170,6 +170,7 @@ public ManualImportItem ReprocessItem(string path, string downloadId, int series
localEpisode.Languages = languages?.Count <= 1 && (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages;
localEpisode.Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality;
localEpisode.IndexerFlags = (IndexerFlags)indexerFlags;
localEpisode.IndexerId = indexerId;
localEpisode.ReleaseType = releaseType;
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
@ -202,6 +203,7 @@ public ManualImportItem ReprocessItem(string path, string downloadId, int series
Languages = languages?.Count <= 1 && (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? LanguageParser.ParseLanguages(path) : languages,
Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality,
IndexerFlags = (IndexerFlags)indexerFlags,
IndexerId = indexerId,
ReleaseType = releaseType
};
@ -428,6 +430,7 @@ private ManualImportItem MapItem(ImportDecision decision, string rootFolder, str
item.Size = _diskProvider.GetFileSize(decision.LocalEpisode.Path);
item.Rejections = decision.Rejections;
item.IndexerFlags = (int)decision.LocalEpisode.IndexerFlags;
item.IndexerId = decision.LocalEpisode.IndexerId;
item.ReleaseType = decision.LocalEpisode.ReleaseType;
return item;
@ -448,6 +451,7 @@ private ManualImportItem MapItem(EpisodeFile episodeFile, Series series, string
item.Quality = episodeFile.Quality;
item.Languages = episodeFile.Languages;
item.IndexerFlags = (int)episodeFile.IndexerFlags;
item.IndexerId = episodeFile.IndexerId;
item.ReleaseType = episodeFile.ReleaseType;
item.Size = _diskProvider.GetFileSize(item.Path);
item.Rejections = Enumerable.Empty<Rejection>();
@ -486,6 +490,7 @@ public void Execute(ManualImportCommand message)
Quality = file.Quality,
Languages = file.Languages,
IndexerFlags = (IndexerFlags)file.IndexerFlags,
IndexerId = file.IndexerId,
ReleaseType = file.ReleaseType,
Series = series,
Size = 0
@ -516,6 +521,7 @@ public void Execute(ManualImportCommand message)
localEpisode.Quality = file.Quality;
localEpisode.Languages = file.Languages;
localEpisode.IndexerFlags = (IndexerFlags)file.IndexerFlags;
localEpisode.IndexerId = file.IndexerId;
localEpisode.ReleaseType = file.ReleaseType;
// TODO: Cleanup non-tracked downloads

View File

@ -91,6 +91,7 @@ public override void OnGrab(GrabMessage message)
environmentVariables.Add("Sonarr_Release_QualityVersion", remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version.ToString());
environmentVariables.Add("Sonarr_Release_ReleaseGroup", releaseGroup ?? string.Empty);
environmentVariables.Add("Sonarr_Release_IndexerFlags", remoteEpisode.Release.IndexerFlags.ToString());
environmentVariables.Add("Sonarr_Release_IndexerId", remoteEpisode.Release.IndexerId.ToString());
environmentVariables.Add("Sonarr_Download_Client", message.DownloadClientName ?? string.Empty);
environmentVariables.Add("Sonarr_Download_Client_Type", message.DownloadClientType ?? string.Empty);
environmentVariables.Add("Sonarr_Download_Id", message.DownloadId ?? string.Empty);

View File

@ -8,6 +8,7 @@ public class GrabbedReleaseInfo
{
public string Title { get; set; }
public string Indexer { get; set; }
public int IndexerId { get; set; }
public long Size { get; set; }
public List<int> EpisodeIds { get; set; }
@ -18,11 +19,14 @@ public GrabbedReleaseInfo(List<EpisodeHistory> grabbedHistories)
var episodeIds = grabbedHistories.Select(h => h.EpisodeId).Distinct().ToList();
grabbedHistory.Data.TryGetValue("indexer", out var indexer);
grabbedHistory.Data.TryGetValue("indexerId", out var indexerIdString);
grabbedHistory.Data.TryGetValue("size", out var sizeString);
long.TryParse(sizeString, out var size);
int.TryParse(indexerIdString, out var indexerId);
Title = grabbedHistory.SourceTitle;
Indexer = indexer;
IndexerId = indexerId;
Size = size;
EpisodeIds = episodeIds;
}

View File

@ -32,6 +32,7 @@ public LocalEpisode()
public QualityModel Quality { get; set; }
public List<Language> Languages { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType ReleaseType { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public bool ExistingFile { get; set; }

View File

@ -27,6 +27,7 @@ public class EpisodeFileResource : RestResource
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int? IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType? ReleaseType { get; set; }
public MediaInfoResource MediaInfo { get; set; }
@ -65,6 +66,7 @@ public static EpisodeFileResource ToResource(this EpisodeFile model, NzbDrone.Co
CustomFormats = customFormats.ToResource(false),
CustomFormatScore = customFormatScore,
IndexerFlags = (int)model.IndexerFlags,
IndexerId = model.IndexerId,
ReleaseType = model.ReleaseType,
};
}

View File

@ -39,7 +39,7 @@ public object ReprocessItems([FromBody] List<ManualImportReprocessResource> item
{
foreach (var item in items)
{
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.SeriesId, item.SeasonNumber, item.EpisodeIds ?? new List<int>(), item.ReleaseGroup, item.Quality, item.Languages, item.IndexerFlags, item.ReleaseType);
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.SeriesId, item.SeasonNumber, item.EpisodeIds ?? new List<int>(), item.ReleaseGroup, item.Quality, item.Languages, item.IndexerFlags, item.IndexerId, item.ReleaseType);
item.SeasonNumber = processedItem.SeasonNumber;
item.Episodes = processedItem.Episodes.ToResource();

View File

@ -23,6 +23,7 @@ public class ManualImportReprocessResource : RestResource
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType ReleaseType { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}

View File

@ -32,6 +32,7 @@ public class ManualImportResource : RestResource
public List<CustomFormatResource> CustomFormats { get; set; }
public int CustomFormatScore { get; set; }
public int IndexerFlags { get; set; }
public int IndexerId { get; set; }
public ReleaseType ReleaseType { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}
@ -62,6 +63,7 @@ public static ManualImportResource ToResource(this ManualImportItem model)
EpisodeFileId = model.EpisodeFileId,
ReleaseGroup = model.ReleaseGroup,
Quality = model.Quality,
IndexerId = model.IndexerId,
Languages = model.Languages,
CustomFormats = customFormats.ToResource(false),
CustomFormatScore = customFormatScore,