mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-03-05 13:20:20 -05:00
New: Calculate custom score using renamed filename before importing
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Profiles.Qualities;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
{
|
||||
[TestFixture]
|
||||
public class LocalEpisodeCustomFormatCalculationServiceFixture : CoreTest<LocalEpisodeCustomFormatCalculationService>
|
||||
{
|
||||
private const int EnglishCustomFormatScore = 10;
|
||||
private const int SpanishCustomFormatScore = 2;
|
||||
private LocalEpisode _localEpisode;
|
||||
private Series _series;
|
||||
private QualityModel _quality;
|
||||
private CustomFormat _englishCustomFormat;
|
||||
private CustomFormat _spanishCustomFormat;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_englishCustomFormat = new CustomFormat("HasEnglish") { Id = 1 };
|
||||
_spanishCustomFormat = new CustomFormat("HasSpanish") { Id = 2 };
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.With(e => e.Path = @"C:\Test\Series".AsOsAgnostic())
|
||||
.With(e => e.QualityProfile = new QualityProfile
|
||||
{
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
FormatItems = [
|
||||
new ProfileFormatItem { Format = _englishCustomFormat, Score = EnglishCustomFormatScore },
|
||||
new ProfileFormatItem { Format = _spanishCustomFormat, Score = SpanishCustomFormatScore }
|
||||
]
|
||||
})
|
||||
.Build();
|
||||
|
||||
_quality = new QualityModel(Quality.DVD);
|
||||
|
||||
_localEpisode = new LocalEpisode
|
||||
{
|
||||
Series = _series,
|
||||
Quality = _quality,
|
||||
Languages = new List<Language> { Language.Spanish },
|
||||
Episodes = new List<Episode> { new Episode() },
|
||||
Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.Spanish.XviD-OSiTV.avi"
|
||||
};
|
||||
|
||||
Mocker.GetMock<ICustomFormatCalculationService>()
|
||||
.Setup(s => s.ParseCustomFormat(It.IsAny<LocalEpisode>(), It.Is<string>(x => x.Contains("English"))))
|
||||
.Returns([_englishCustomFormat]);
|
||||
|
||||
Mocker.GetMock<ICustomFormatCalculationService>()
|
||||
.Setup(s => s.ParseCustomFormat(It.IsAny<LocalEpisode>(), It.Is<string>(x => x.Contains("Spanish"))))
|
||||
.Returns([_spanishCustomFormat]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_build_a_filename_and_use_it_to_calculate_custom_score()
|
||||
{
|
||||
var renamedFileName = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.English.XviD-OSiTV.avi";
|
||||
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.BuildFileName(It.IsAny<List<Episode>>(), It.IsAny<Series>(), It.IsAny<EpisodeFile>(), "", null, null))
|
||||
.Returns(renamedFileName);
|
||||
|
||||
Subject.ParseEpisodeCustomFormats(_localEpisode).Should().BeEquivalentTo([_englishCustomFormat]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_custom_formats_on_local_episode()
|
||||
{
|
||||
var renamedFileName = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.English.XviD-OSiTV.avi";
|
||||
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.BuildFileName(It.IsAny<List<Episode>>(), It.IsAny<Series>(), It.IsAny<EpisodeFile>(), "", null, null))
|
||||
.Returns(renamedFileName);
|
||||
|
||||
Subject.UpdateEpisodeCustomFormats(_localEpisode);
|
||||
_localEpisode.FileNameUsedForCustomFormatCalculation.Should().Be(renamedFileName);
|
||||
|
||||
_localEpisode.OriginalFileNameCustomFormats.Should().BeEquivalentTo([_spanishCustomFormat]);
|
||||
_localEpisode.OriginalFileNameCustomFormatScore.Should().Be(SpanishCustomFormatScore);
|
||||
|
||||
_localEpisode.CustomFormats.Should().BeEquivalentTo([_englishCustomFormat]);
|
||||
_localEpisode.CustomFormatScore.Should().Be(EnglishCustomFormatScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles;
|
||||
@@ -565,5 +566,48 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_and_a_specific_reason_if_not_upgrade_to_custom_format_score_after_local_file_rename_but_was_before()
|
||||
{
|
||||
var episodeFileCustomFormats = Builder<CustomFormat>.CreateListOfSize(1).Build().ToList();
|
||||
|
||||
var episodeFile = new EpisodeFile
|
||||
{
|
||||
Quality = new QualityModel(Quality.Bluray1080p)
|
||||
};
|
||||
|
||||
_series.QualityProfile.Value.FormatItems = episodeFileCustomFormats.Select(c => new ProfileFormatItem
|
||||
{
|
||||
Format = c,
|
||||
Score = 50
|
||||
})
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.DownloadPropersAndRepacks)
|
||||
.Returns(ProperDownloadTypes.DoNotPrefer);
|
||||
|
||||
Mocker.GetMock<ICustomFormatCalculationService>()
|
||||
.Setup(s => s.ParseCustomFormat(episodeFile))
|
||||
.Returns(episodeFileCustomFormats);
|
||||
|
||||
_localEpisode.Quality = new QualityModel(Quality.Bluray1080p);
|
||||
_localEpisode.CustomFormats = Builder<CustomFormat>.CreateListOfSize(1).Build().ToList();
|
||||
_localEpisode.CustomFormatScore = 20;
|
||||
_localEpisode.OriginalFileNameCustomFormats = Builder<CustomFormat>.CreateListOfSize(1).Build().ToList();
|
||||
_localEpisode.OriginalFileNameCustomFormatScore = 60;
|
||||
|
||||
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.EpisodeFileId = 1)
|
||||
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(episodeFile))
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
var result = Subject.IsSatisfiedBy(_localEpisode, null);
|
||||
result.Accepted.Should().BeFalse();
|
||||
result.Reason.Should().Be(ImportRejectionReason.NotCustomFormatUpgradeAfterRename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.CustomFormats
|
||||
List<CustomFormat> ParseCustomFormat(EpisodeFile episodeFile);
|
||||
List<CustomFormat> ParseCustomFormat(Blocklist blocklist, Series series);
|
||||
List<CustomFormat> ParseCustomFormat(EpisodeHistory history, Series series);
|
||||
List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode);
|
||||
List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode, string fileName);
|
||||
}
|
||||
|
||||
public class CustomFormatCalculationService : ICustomFormatCalculationService
|
||||
@@ -114,12 +114,12 @@ namespace NzbDrone.Core.CustomFormats
|
||||
return ParseCustomFormat(input);
|
||||
}
|
||||
|
||||
public List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode)
|
||||
public List<CustomFormat> ParseCustomFormat(LocalEpisode localEpisode, string fileName)
|
||||
{
|
||||
var episodeInfo = new ParsedEpisodeInfo
|
||||
{
|
||||
SeriesTitle = localEpisode.Series.Title,
|
||||
ReleaseTitle = localEpisode.SceneName.IsNotNullOrWhiteSpace() ? localEpisode.SceneName : Path.GetFileName(localEpisode.Path),
|
||||
ReleaseTitle = localEpisode.SceneName.IsNotNullOrWhiteSpace() ? localEpisode.SceneName : fileName,
|
||||
Quality = localEpisode.Quality,
|
||||
Languages = localEpisode.Languages,
|
||||
ReleaseGroup = localEpisode.ReleaseGroup
|
||||
@@ -133,7 +133,7 @@ namespace NzbDrone.Core.CustomFormats
|
||||
Languages = localEpisode.Languages,
|
||||
IndexerFlags = localEpisode.IndexerFlags,
|
||||
ReleaseType = localEpisode.ReleaseType,
|
||||
Filename = Path.GetFileName(localEpisode.Path)
|
||||
Filename = fileName
|
||||
};
|
||||
|
||||
return ParseCustomFormat(input);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
@@ -85,24 +84,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
continue;
|
||||
}
|
||||
|
||||
var episodeFile = new EpisodeFile();
|
||||
episodeFile.DateAdded = DateTime.UtcNow;
|
||||
episodeFile.SeriesId = localEpisode.Series.Id;
|
||||
episodeFile.Path = localEpisode.Path.CleanFilePath();
|
||||
var episodeFile = localEpisode.ToEpisodeFile();
|
||||
episodeFile.Size = _diskProvider.GetFileSize(localEpisode.Path);
|
||||
episodeFile.Quality = localEpisode.Quality;
|
||||
episodeFile.MediaInfo = localEpisode.MediaInfo;
|
||||
episodeFile.Series = localEpisode.Series;
|
||||
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
||||
episodeFile.Episodes = localEpisode.Episodes;
|
||||
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
|
||||
episodeFile.ReleaseHash = localEpisode.ReleaseHash;
|
||||
episodeFile.Languages = localEpisode.Languages;
|
||||
|
||||
// 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 ??
|
||||
localEpisode.FolderEpisodeInfo?.ReleaseType ??
|
||||
localEpisode.FileEpisodeInfo.ReleaseType;
|
||||
|
||||
if (downloadClientItem?.DownloadId.IsNotNullOrWhiteSpace() == true)
|
||||
{
|
||||
@@ -118,23 +101,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
// Prefer the release type from the grabbed history
|
||||
if (Enum.TryParse(grabHistory?.Data.GetValueOrDefault("releaseType"), true, out ReleaseType releaseType))
|
||||
{
|
||||
episodeFile.ReleaseType = releaseType;
|
||||
if (releaseType != ReleaseType.Unknown)
|
||||
{
|
||||
episodeFile.ReleaseType = releaseType;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
episodeFile.IndexerFlags = localEpisode.IndexerFlags;
|
||||
episodeFile.ReleaseType = localEpisode.ReleaseType;
|
||||
}
|
||||
|
||||
// Fall back to parsed information if history is unavailable or missing
|
||||
if (episodeFile.ReleaseType == ReleaseType.Unknown)
|
||||
{
|
||||
// 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 ??
|
||||
localEpisode.FolderEpisodeInfo?.ReleaseType ??
|
||||
localEpisode.FileEpisodeInfo.ReleaseType;
|
||||
}
|
||||
|
||||
bool copyOnly;
|
||||
switch (importMode)
|
||||
@@ -153,15 +125,20 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
episodeFile.SceneName = localEpisode.SceneName;
|
||||
episodeFile.OriginalFilePath = GetOriginalFilePath(downloadClientItem, localEpisode);
|
||||
if (downloadClientItem is { OutputPath.IsEmpty: false })
|
||||
{
|
||||
var outputDirectory = downloadClientItem.OutputPath.Directory.ToString();
|
||||
|
||||
if (outputDirectory.IsParentPath(localEpisode.Path))
|
||||
{
|
||||
episodeFile.OriginalFilePath = outputDirectory.GetRelativePath(localEpisode.Path);
|
||||
}
|
||||
}
|
||||
|
||||
oldFiles = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode, copyOnly).OldFiles;
|
||||
}
|
||||
else
|
||||
{
|
||||
episodeFile.RelativePath = localEpisode.Series.Path.GetRelativePath(episodeFile.Path);
|
||||
|
||||
// Delete existing files from the DB mapped to this path
|
||||
var previousFiles = _mediaFileService.GetFilesWithRelativePath(localEpisode.Series.Id, episodeFile.RelativePath);
|
||||
|
||||
@@ -228,42 +205,5 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
return importResults;
|
||||
}
|
||||
|
||||
private string GetOriginalFilePath(DownloadClientItem downloadClientItem, LocalEpisode localEpisode)
|
||||
{
|
||||
var path = localEpisode.Path;
|
||||
|
||||
if (downloadClientItem != null && !downloadClientItem.OutputPath.IsEmpty)
|
||||
{
|
||||
var outputDirectory = downloadClientItem.OutputPath.Directory.ToString();
|
||||
|
||||
if (outputDirectory.IsParentPath(path))
|
||||
{
|
||||
return outputDirectory.GetRelativePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
var folderEpisodeInfo = localEpisode.FolderEpisodeInfo;
|
||||
|
||||
if (folderEpisodeInfo != null)
|
||||
{
|
||||
var folderPath = path.GetAncestorPath(folderEpisodeInfo.ReleaseTitle);
|
||||
|
||||
if (folderPath != null)
|
||||
{
|
||||
return folderPath.GetParentPath().GetRelativePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
var parentPath = path.GetParentPath();
|
||||
var grandparentPath = parentPath.GetParentPath();
|
||||
|
||||
if (grandparentPath != null)
|
||||
{
|
||||
return grandparentPath.GetRelativePath(path);
|
||||
}
|
||||
|
||||
return Path.GetFileName(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
|
||||
@@ -30,7 +29,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDetectSample _detectSample;
|
||||
private readonly ITrackedDownloadService _trackedDownloadService;
|
||||
private readonly ICustomFormatCalculationService _formatCalculator;
|
||||
private readonly ILocalEpisodeCustomFormatCalculationService _formatCalculator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
|
||||
@@ -39,7 +38,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
IDiskProvider diskProvider,
|
||||
IDetectSample detectSample,
|
||||
ITrackedDownloadService trackedDownloadService,
|
||||
ICustomFormatCalculationService formatCalculator,
|
||||
ILocalEpisodeCustomFormatCalculationService formatCalculator,
|
||||
Logger logger)
|
||||
{
|
||||
_specifications = specifications;
|
||||
@@ -158,8 +157,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
}
|
||||
}
|
||||
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
|
||||
localEpisode.CustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
_formatCalculator.UpdateEpisodeCustomFormats(localEpisode);
|
||||
|
||||
decision = GetDecision(localEpisode, downloadClientItem);
|
||||
}
|
||||
|
||||
@@ -36,5 +36,6 @@ public enum ImportRejectionReason
|
||||
UnverifiedSceneMapping,
|
||||
NotQualityUpgrade,
|
||||
NotRevisionUpgrade,
|
||||
NotCustomFormatUpgrade
|
||||
NotCustomFormatUpgrade,
|
||||
NotCustomFormatUpgradeAfterRename
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
|
||||
public interface ILocalEpisodeCustomFormatCalculationService
|
||||
{
|
||||
public List<CustomFormat> ParseEpisodeCustomFormats(LocalEpisode localEpisode);
|
||||
public void UpdateEpisodeCustomFormats(LocalEpisode localEpisode);
|
||||
}
|
||||
|
||||
public class LocalEpisodeCustomFormatCalculationService : ILocalEpisodeCustomFormatCalculationService
|
||||
{
|
||||
private readonly IBuildFileNames _fileNameBuilder;
|
||||
private readonly ICustomFormatCalculationService _formatCalculator;
|
||||
|
||||
public LocalEpisodeCustomFormatCalculationService(IBuildFileNames fileNameBuilder, ICustomFormatCalculationService formatCalculator)
|
||||
{
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
_formatCalculator = formatCalculator;
|
||||
}
|
||||
|
||||
public List<CustomFormat> ParseEpisodeCustomFormats(LocalEpisode localEpisode)
|
||||
{
|
||||
var fileNameUsedForCustomFormatCalculation = _fileNameBuilder.BuildFileName(localEpisode.Episodes, localEpisode.Series, localEpisode.ToEpisodeFile());
|
||||
return _formatCalculator.ParseCustomFormat(localEpisode, fileNameUsedForCustomFormatCalculation);
|
||||
}
|
||||
|
||||
public void UpdateEpisodeCustomFormats(LocalEpisode localEpisode)
|
||||
{
|
||||
var fileNameUsedForCustomFormatCalculation = _fileNameBuilder.BuildFileName(localEpisode.Episodes, localEpisode.Series, localEpisode.ToEpisodeFile());
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode, fileNameUsedForCustomFormatCalculation);
|
||||
localEpisode.FileNameUsedForCustomFormatCalculation = fileNameUsedForCustomFormatCalculation;
|
||||
localEpisode.CustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
|
||||
localEpisode.OriginalFileNameCustomFormats = _formatCalculator.ParseCustomFormat(localEpisode, Path.GetFileName(localEpisode.Path));
|
||||
localEpisode.OriginalFileNameCustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.OriginalFileNameCustomFormats) ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly ICustomFormatCalculationService _formatCalculator;
|
||||
private readonly ILocalEpisodeCustomFormatCalculationService _localEpisodeFormatCalculator;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
@@ -55,6 +56,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
ITrackedDownloadService trackedDownloadService,
|
||||
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
||||
IMediaFileService mediaFileService,
|
||||
ILocalEpisodeCustomFormatCalculationService localEpisodeFormatCalculator,
|
||||
ICustomFormatCalculationService formatCalculator,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
@@ -70,6 +72,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
_trackedDownloadService = trackedDownloadService;
|
||||
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
||||
_mediaFileService = mediaFileService;
|
||||
_localEpisodeFormatCalculator = localEpisodeFormatCalculator;
|
||||
_formatCalculator = formatCalculator;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
@@ -180,8 +183,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
localEpisode.IndexerFlags = (IndexerFlags)indexerFlags;
|
||||
localEpisode.ReleaseType = releaseType;
|
||||
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
|
||||
localEpisode.CustomFormatScore = localEpisode.Series?.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
_localEpisodeFormatCalculator.UpdateEpisodeCustomFormats(localEpisode);
|
||||
|
||||
// Augment episode file so imported files have all additional information an automatic import would
|
||||
localEpisode = _aggregationService.Augment(localEpisode, downloadClientItem);
|
||||
@@ -445,8 +447,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
if (decision.LocalEpisode.Series != null)
|
||||
{
|
||||
item.Series = decision.LocalEpisode.Series;
|
||||
|
||||
item.CustomFormats = _formatCalculator.ParseCustomFormat(decision.LocalEpisode);
|
||||
item.CustomFormats = _localEpisodeFormatCalculator.ParseEpisodeCustomFormats(decision.LocalEpisode);
|
||||
item.CustomFormatScore = item.Series.QualityProfile?.Value.CalculateCustomFormatScore(item.CustomFormats) ?? 0;
|
||||
}
|
||||
|
||||
@@ -537,8 +538,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
localEpisode.IndexerFlags = (IndexerFlags)file.IndexerFlags;
|
||||
localEpisode.ReleaseType = file.ReleaseType;
|
||||
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
|
||||
localEpisode.CustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
_localEpisodeFormatCalculator.UpdateEpisodeCustomFormats(localEpisode);
|
||||
|
||||
// TODO: Cleanup non-tracked downloads
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
var currentFormatScore = qualityProfile.CalculateCustomFormatScore(currentFormats);
|
||||
var newFormats = localEpisode.CustomFormats;
|
||||
var newFormatScore = localEpisode.CustomFormatScore;
|
||||
var newFormatsBeforeRename = localEpisode.OriginalFileNameCustomFormats;
|
||||
var newFormatScoreBeforeRename = localEpisode.OriginalFileNameCustomFormatScore;
|
||||
|
||||
if (qualityCompare == 0 && newFormatScore < currentFormatScore)
|
||||
{
|
||||
@@ -71,6 +73,18 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
currentFormats != null ? currentFormats.ConcatToString() : "",
|
||||
currentFormatScore);
|
||||
|
||||
if (newFormatScoreBeforeRename > currentFormatScore)
|
||||
{
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NotCustomFormatUpgradeAfterRename,
|
||||
"Not a Custom Format upgrade for existing episode file(s). AfterRename: [{0}] ({1}) do not improve on Existing: [{2}] ({3}) even though BeforeRename: [{4}] ({5}) did.",
|
||||
newFormats != null ? newFormats.ConcatToString() : "",
|
||||
newFormatScore,
|
||||
currentFormats != null ? currentFormats.ConcatToString() : "",
|
||||
currentFormatScore,
|
||||
newFormatsBeforeRename != null ? newFormatsBeforeRename.ConcatToString() : "",
|
||||
newFormatScoreBeforeRename);
|
||||
}
|
||||
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NotCustomFormatUpgrade,
|
||||
"Not a Custom Format upgrade for existing episode file(s). New: [{0}] ({1}) do not improve on Existing: [{2}] ({3})",
|
||||
newFormats != null ? newFormats.ConcatToString() : "",
|
||||
|
||||
@@ -85,7 +85,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
}
|
||||
|
||||
episodeFile.MediaInfo = updatedMediaInfo;
|
||||
_mediaFileService.Update(episodeFile);
|
||||
|
||||
if (episodeFile.Id != 0)
|
||||
{
|
||||
_mediaFileService.Update(episodeFile);
|
||||
}
|
||||
|
||||
_logger.Debug("Updated MediaInfo for '{0}'", path);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
@@ -13,13 +14,6 @@ namespace NzbDrone.Core.Parser.Model
|
||||
{
|
||||
public class LocalEpisode
|
||||
{
|
||||
public LocalEpisode()
|
||||
{
|
||||
Episodes = new List<Episode>();
|
||||
Languages = new List<Language>();
|
||||
CustomFormats = new List<CustomFormat>();
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
public long Size { get; set; }
|
||||
public ParsedEpisodeInfo FileEpisodeInfo { get; set; }
|
||||
@@ -27,10 +21,10 @@ namespace NzbDrone.Core.Parser.Model
|
||||
public DownloadClientItem DownloadItem { get; set; }
|
||||
public ParsedEpisodeInfo FolderEpisodeInfo { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public List<Episode> Episodes { get; set; }
|
||||
public List<Episode> Episodes { get; set; } = new();
|
||||
public List<DeletedEpisodeFile> OldFiles { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public List<Language> Languages { get; set; }
|
||||
public List<Language> Languages { get; set; } = new();
|
||||
public IndexerFlags IndexerFlags { get; set; }
|
||||
public ReleaseType ReleaseType { get; set; }
|
||||
public MediaInfoModel MediaInfo { get; set; }
|
||||
@@ -40,11 +34,14 @@ namespace NzbDrone.Core.Parser.Model
|
||||
public string ReleaseHash { get; set; }
|
||||
public string SceneName { get; set; }
|
||||
public bool OtherVideoFiles { get; set; }
|
||||
public List<CustomFormat> CustomFormats { get; set; }
|
||||
public List<CustomFormat> CustomFormats { get; set; } = new();
|
||||
public int CustomFormatScore { get; set; }
|
||||
public List<CustomFormat> OriginalFileNameCustomFormats { get; set; } = new();
|
||||
public int OriginalFileNameCustomFormatScore { get; set; }
|
||||
public GrabbedReleaseInfo Release { get; set; }
|
||||
public bool ScriptImported { get; set; }
|
||||
public string FileNameBeforeRename { get; set; }
|
||||
public string FileNameUsedForCustomFormatCalculation { get; set; }
|
||||
public bool ShouldImportExtras { get; set; }
|
||||
public List<string> PossibleExtraFiles { get; set; }
|
||||
public SubtitleTitleInfo SubtitleInfo { get; set; }
|
||||
@@ -75,5 +72,80 @@ namespace NzbDrone.Core.Parser.Model
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
public string GetSceneOrFileName()
|
||||
{
|
||||
if (SceneName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return SceneName;
|
||||
}
|
||||
|
||||
if (Path.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return System.IO.Path.GetFileNameWithoutExtension(Path);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public EpisodeFile ToEpisodeFile()
|
||||
{
|
||||
var episodeFile = new EpisodeFile
|
||||
{
|
||||
DateAdded = DateTime.UtcNow,
|
||||
SeriesId = Series.Id,
|
||||
Path = Path.CleanFilePath(),
|
||||
Quality = Quality,
|
||||
MediaInfo = MediaInfo,
|
||||
Series = Series,
|
||||
SeasonNumber = SeasonNumber,
|
||||
Episodes = Episodes,
|
||||
ReleaseGroup = ReleaseGroup,
|
||||
ReleaseHash = ReleaseHash,
|
||||
Languages = Languages,
|
||||
IndexerFlags = IndexerFlags,
|
||||
ReleaseType = ReleaseType,
|
||||
SceneName = SceneName,
|
||||
OriginalFilePath = GetOriginalFilePath()
|
||||
};
|
||||
|
||||
if (Series.Path.IsParentPath(episodeFile.Path))
|
||||
{
|
||||
episodeFile.RelativePath = Series.Path.GetRelativePath(Path.CleanFilePath());
|
||||
}
|
||||
|
||||
if (episodeFile.ReleaseType == ReleaseType.Unknown)
|
||||
{
|
||||
episodeFile.ReleaseType = DownloadClientEpisodeInfo?.ReleaseType ??
|
||||
FolderEpisodeInfo?.ReleaseType ??
|
||||
FileEpisodeInfo?.ReleaseType ??
|
||||
ReleaseType.Unknown;
|
||||
}
|
||||
|
||||
return episodeFile;
|
||||
}
|
||||
|
||||
private string GetOriginalFilePath()
|
||||
{
|
||||
if (FolderEpisodeInfo != null)
|
||||
{
|
||||
var folderPath = Path.GetAncestorPath(FolderEpisodeInfo.ReleaseTitle);
|
||||
|
||||
if (folderPath != null)
|
||||
{
|
||||
return folderPath.GetParentPath().GetRelativePath(Path);
|
||||
}
|
||||
}
|
||||
|
||||
var parentPath = Path.GetParentPath();
|
||||
var grandparentPath = parentPath.GetParentPath();
|
||||
|
||||
if (grandparentPath != null)
|
||||
{
|
||||
return grandparentPath.GetRelativePath(Path);
|
||||
}
|
||||
|
||||
return System.IO.Path.GetFileName(Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user