parent
48cb5d2271
commit
d86aeb7472
|
@ -154,6 +154,10 @@ const otherTokens = [
|
||||||
{ token: '{Custom Format:FormatName}', example: 'AMZN' }
|
{ token: '{Custom Format:FormatName}', example: 'AMZN' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const otherAnimeTokens = [
|
||||||
|
{ token: '{Release Hash}', example: 'ABCDEFGH' }
|
||||||
|
];
|
||||||
|
|
||||||
const originalTokens = [
|
const originalTokens = [
|
||||||
{ token: '{Original Title}', example: 'The.Series.Title\'s!.S01E01.WEBDL.1080p.x264-EVOLVE' },
|
{ token: '{Original Title}', example: 'The.Series.Title\'s!.S01E01.WEBDL.1080p.x264-EVOLVE' },
|
||||||
{ token: '{Original Filename}', example: 'the.series.title\'s!.s01e01.webdl.1080p.x264-EVOLVE' }
|
{ token: '{Original Filename}', example: 'the.series.title\'s!.s01e01.webdl.1080p.x264-EVOLVE' }
|
||||||
|
@ -535,6 +539,24 @@ class NamingModal extends Component {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
anime && otherAnimeTokens.map(({ token, example }) => {
|
||||||
|
return (
|
||||||
|
<NamingOption
|
||||||
|
key={token}
|
||||||
|
name={name}
|
||||||
|
value={value}
|
||||||
|
token={token}
|
||||||
|
example={example}
|
||||||
|
tokenSeparator={tokenSeparator}
|
||||||
|
tokenCase={tokenCase}
|
||||||
|
onPress={this.onOptionPress}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class AggregateReleaseHashFixture : CoreTest<AggregateReleaseHash>
|
||||||
|
{
|
||||||
|
private Series _series;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_series = Builder<Series>.CreateNew().Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_prefer_file()
|
||||||
|
{
|
||||||
|
var fileEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC) [ABCDEFGH]");
|
||||||
|
var folderEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 [12345678]");
|
||||||
|
var downloadClientEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC) [ABCD1234]");
|
||||||
|
var localEpisode = new LocalEpisode
|
||||||
|
{
|
||||||
|
FileEpisodeInfo = fileEpisodeInfo,
|
||||||
|
FolderEpisodeInfo = folderEpisodeInfo,
|
||||||
|
DownloadClientEpisodeInfo = downloadClientEpisodeInfo,
|
||||||
|
Path = @"C:\Test\Unsorted TV\Series.Title.S01\Series.Title.S01E01.mkv".AsOsAgnostic(),
|
||||||
|
Series = _series
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Aggregate(localEpisode, null);
|
||||||
|
|
||||||
|
localEpisode.ReleaseHash.Should().Be("ABCDEFGH");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_fallback_to_downloadclient()
|
||||||
|
{
|
||||||
|
var fileEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC)");
|
||||||
|
var downloadClientEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC) [ABCD1234]");
|
||||||
|
var folderEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 [12345678]");
|
||||||
|
var localEpisode = new LocalEpisode
|
||||||
|
{
|
||||||
|
FileEpisodeInfo = fileEpisodeInfo,
|
||||||
|
FolderEpisodeInfo = folderEpisodeInfo,
|
||||||
|
DownloadClientEpisodeInfo = downloadClientEpisodeInfo,
|
||||||
|
Path = @"C:\Test\Unsorted TV\Series.Title.S01\Series.Title.S01E01.WEB-DL.mkv".AsOsAgnostic(),
|
||||||
|
Series = _series
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Aggregate(localEpisode, null);
|
||||||
|
|
||||||
|
localEpisode.ReleaseHash.Should().Be("ABCD1234");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_fallback_to_folder()
|
||||||
|
{
|
||||||
|
var fileEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC)");
|
||||||
|
var downloadClientEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 (1280x720 10bit AAC)");
|
||||||
|
var folderEpisodeInfo = Parser.Parser.ParseTitle("[DHD] Series Title! - 08 [12345678]");
|
||||||
|
var localEpisode = new LocalEpisode
|
||||||
|
{
|
||||||
|
FileEpisodeInfo = fileEpisodeInfo,
|
||||||
|
FolderEpisodeInfo = folderEpisodeInfo,
|
||||||
|
DownloadClientEpisodeInfo = downloadClientEpisodeInfo,
|
||||||
|
Path = @"C:\Test\Unsorted TV\Series.Title.S01\Series.Title.S01E01.WEB-DL.mkv".AsOsAgnostic(),
|
||||||
|
Series = _series
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Aggregate(localEpisode, null);
|
||||||
|
|
||||||
|
localEpisode.ReleaseHash.Should().Be("12345678");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -991,6 +991,28 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
result.Should().EndWith("HDR");
|
result.Should().EndWith("HDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_release_hash_with_stored_hash()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardEpisodeFormat = "{Release Hash}";
|
||||||
|
|
||||||
|
_episodeFile.ReleaseHash = "ABCDEFGH";
|
||||||
|
|
||||||
|
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
||||||
|
.Should().Be("ABCDEFGH");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_null_release_hash_with_empty_string()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardEpisodeFormat = "{Release Hash}";
|
||||||
|
|
||||||
|
_episodeFile.ReleaseHash = null;
|
||||||
|
|
||||||
|
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
||||||
|
.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenMediaInfoModel(string videoCodec = "h264",
|
private void GivenMediaInfoModel(string videoCodec = "h264",
|
||||||
string audioCodec = "dts",
|
string audioCodec = "dts",
|
||||||
int audioChannels = 6,
|
int audioChannels = 6,
|
||||||
|
|
|
@ -22,12 +22,42 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
[TestCase("Series Title - 031 - The Resolution to Kill [Lunar].avi", "Lunar", "")]
|
[TestCase("Series Title - 031 - The Resolution to Kill [Lunar].avi", "Lunar", "")]
|
||||||
[TestCase("[ACX]Series Title 01 Episode Name [Kosaka] [9C57891E].mkv", "ACX", "9C57891E")]
|
[TestCase("[ACX]Series Title 01 Episode Name [Kosaka] [9C57891E].mkv", "ACX", "9C57891E")]
|
||||||
[TestCase("[S-T-D] Series Title! - 06 (1280x720 10bit AAC) [59B3F2EA].mkv", "S-T-D", "59B3F2EA")]
|
[TestCase("[S-T-D] Series Title! - 06 (1280x720 10bit AAC) [59B3F2EA].mkv", "S-T-D", "59B3F2EA")]
|
||||||
public void should_parse_absolute_numbers(string postTitle, string subGroup, string hash)
|
|
||||||
|
// These tests are dupes of the above, except with parenthesized hashes instead of square bracket
|
||||||
|
[TestCase("[SubDESU]_Show_Title_DxD_07_(1280x720_x264-AAC)_(6B7FD717)", "SubDESU", "6B7FD717")]
|
||||||
|
[TestCase("[Chihiro]_Show_Title!!_-_06_[848x480_H.264_AAC](859EEAFA)", "Chihiro", "859EEAFA")]
|
||||||
|
[TestCase("[Underwater]_Show_Title_-_12_(720p)_(5C7BC4F9)", "Underwater", "5C7BC4F9")]
|
||||||
|
[TestCase("[HorribleSubs]_Show_Title_-_33_[720p]", "HorribleSubs", "")]
|
||||||
|
[TestCase("[HorribleSubs] Show-Title - 13 [1080p].mkv", "HorribleSubs", "")]
|
||||||
|
[TestCase("[Doremi].Show.Title.5.Go.Go!.31.[1280x720].(C65D4B1F).mkv", "Doremi", "C65D4B1F")]
|
||||||
|
[TestCase("[Doremi].Show.Title.5.Go.Go!.31[1280x720].(C65D4B1F)", "Doremi", "C65D4B1F")]
|
||||||
|
[TestCase("[Doremi].Show.Title.5.Go.Go!.31.[1280x720].mkv", "Doremi", "")]
|
||||||
|
[TestCase("[K-F] Series Title 214", "K-F", "")]
|
||||||
|
[TestCase("[K-F] Series Title S10E14 214", "K-F", "")]
|
||||||
|
[TestCase("[K-F] Series Title 10x14 214", "K-F", "")]
|
||||||
|
[TestCase("[K-F] Series Title 214 10x14", "K-F", "")]
|
||||||
|
[TestCase("Series Title - 031 - The Resolution to Kill [Lunar].avi", "Lunar", "")]
|
||||||
|
[TestCase("[ACX]Series Title 01 Episode Name [Kosaka] (9C57891E).mkv", "ACX", "9C57891E")]
|
||||||
|
[TestCase("[S-T-D] Series Title! - 06 (1280x720 10bit AAC) (59B3F2EA).mkv", "S-T-D", "59B3F2EA")]
|
||||||
|
public void should_parse_releasegroup_and_hash(string postTitle, string subGroup, string hash)
|
||||||
{
|
{
|
||||||
var result = Parser.Parser.ParseTitle(postTitle);
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
result.Should().NotBeNull();
|
result.Should().NotBeNull();
|
||||||
result.ReleaseGroup.Should().Be(subGroup);
|
result.ReleaseGroup.Should().Be(subGroup);
|
||||||
result.ReleaseHash.Should().Be(hash);
|
result.ReleaseHash.Should().Be(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("[DHD] Series Title! - 08 (1280x720 10bit AAC) [8B00F2EA].mkv", "8B00F2EA")]
|
||||||
|
[TestCase("[DHD] Series Title! - 10 (1280x720 10bit AAC) [10BBF2EA].mkv", "10BBF2EA")]
|
||||||
|
[TestCase("[DHD] Series Title! - 08 (1280x720 10bit AAC) [008BF28B].mkv", "008BF28B")]
|
||||||
|
[TestCase("[DHD] Series Title! - 10 (1280x720 10bit AAC) [000BF10B].mkv", "000BF10B")]
|
||||||
|
[TestCase("[DHD] Series Title! - 08 (1280x720 8bit AAC) [8B8BF2EA].mkv", "8B8BF2EA")]
|
||||||
|
[TestCase("[DHD] Series Title! - 10 (1280x720 8bit AAC) [10B10BEA].mkv", "10B10BEA")]
|
||||||
|
public void should_parse_release_hashes_with_10b_or_8b(string postTitle, string hash)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.ReleaseHash.Should().Be(hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
|
using Dapper;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(204)]
|
||||||
|
public class add_add_release_hash : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("EpisodeFiles").AddColumn("ReleaseHash").AsString().Nullable();
|
||||||
|
|
||||||
|
Execute.WithConnection(UpdateEpisodeFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateEpisodeFiles(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var updates = new List<object>();
|
||||||
|
|
||||||
|
using (var cmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.Transaction = tran;
|
||||||
|
cmd.CommandText = "SELECT \"Id\", \"SceneName\", \"RelativePath\", \"OriginalFilePath\" FROM \"EpisodeFiles\"";
|
||||||
|
|
||||||
|
using var reader = cmd.ExecuteReader();
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var id = reader.GetInt32(0);
|
||||||
|
var sceneName = reader[1] as string;
|
||||||
|
var relativePath = reader[2] as string;
|
||||||
|
var originalFilePath = reader[3] as string;
|
||||||
|
|
||||||
|
ParsedEpisodeInfo parsedEpisodeInfo = null;
|
||||||
|
|
||||||
|
var originalTitle = sceneName;
|
||||||
|
|
||||||
|
if (originalTitle.IsNullOrWhiteSpace() && originalFilePath.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
originalTitle = Path.GetFileNameWithoutExtension(originalFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalTitle.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
parsedEpisodeInfo = Parser.Parser.ParseTitle(originalTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedEpisodeInfo == null || parsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
parsedEpisodeInfo = Parser.Parser.ParseTitle(Path.GetFileNameWithoutExtension(relativePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedEpisodeInfo != null && parsedEpisodeInfo.ReleaseHash.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
updates.Add(new
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
ReleaseHash = parsedEpisodeInfo.ReleaseHash
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.Count > 0)
|
||||||
|
{
|
||||||
|
var updateEpisodeFilesSql = "UPDATE \"EpisodeFiles\" SET \"ReleaseHash\" = @ReleaseHash WHERE \"Id\" = @Id";
|
||||||
|
conn.Execute(updateEpisodeFilesSql, updates, transaction: tran);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public string OriginalFilePath { get; set; }
|
public string OriginalFilePath { get; set; }
|
||||||
public string SceneName { get; set; }
|
public string SceneName { get; set; }
|
||||||
public string ReleaseGroup { get; set; }
|
public string ReleaseGroup { get; set; }
|
||||||
|
public string ReleaseHash { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public IndexerFlags IndexerFlags { get; set; }
|
public IndexerFlags IndexerFlags { get; set; }
|
||||||
public MediaInfoModel MediaInfo { get; set; }
|
public MediaInfoModel MediaInfo { get; set; }
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
|
||||||
|
{
|
||||||
|
public class AggregateReleaseHash : IAggregateLocalEpisode
|
||||||
|
{
|
||||||
|
public int Order => 1;
|
||||||
|
|
||||||
|
public LocalEpisode Aggregate(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
var releaseHash = GetReleaseHash(localEpisode.FileEpisodeInfo);
|
||||||
|
|
||||||
|
if (releaseHash.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
releaseHash = GetReleaseHash(localEpisode.DownloadClientEpisodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (releaseHash.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
releaseHash = GetReleaseHash(localEpisode.FolderEpisodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
localEpisode.ReleaseHash = releaseHash;
|
||||||
|
|
||||||
|
return localEpisode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetReleaseHash(ParsedEpisodeInfo episodeInfo)
|
||||||
|
{
|
||||||
|
// ReleaseHash doesn't make sense for a FullSeason, since hashes should be specific to a file
|
||||||
|
if (episodeInfo == null || episodeInfo.FullSeason)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return episodeInfo.ReleaseHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,6 +95,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
||||||
episodeFile.Episodes = localEpisode.Episodes;
|
episodeFile.Episodes = localEpisode.Episodes;
|
||||||
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
|
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
|
||||||
|
episodeFile.ReleaseHash = localEpisode.ReleaseHash;
|
||||||
episodeFile.Languages = localEpisode.Languages;
|
episodeFile.Languages = localEpisode.Languages;
|
||||||
|
|
||||||
// Prefer the release type from the download client, folder and finally the file so we have the most accurate information.
|
// Prefer the release type from the download client, folder and finally the file so we have the most accurate information.
|
||||||
|
|
|
@ -623,6 +623,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile, useCurrentFilenameAsFallback);
|
tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile, useCurrentFilenameAsFallback);
|
||||||
tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile, useCurrentFilenameAsFallback);
|
tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile, useCurrentFilenameAsFallback);
|
||||||
tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup.IsNullOrWhiteSpace() ? m.DefaultValue("Sonarr") : Truncate(episodeFile.ReleaseGroup, m.CustomFormat);
|
tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup.IsNullOrWhiteSpace() ? m.DefaultValue("Sonarr") : Truncate(episodeFile.ReleaseGroup, m.CustomFormat);
|
||||||
|
tokenHandlers["{Release Hash}"] = m => episodeFile.ReleaseHash ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddQualityTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Series series, EpisodeFile episodeFile)
|
private void AddQualityTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Series series, EpisodeFile episodeFile)
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public bool ExistingFile { get; set; }
|
public bool ExistingFile { get; set; }
|
||||||
public bool SceneSource { get; set; }
|
public bool SceneSource { get; set; }
|
||||||
public string ReleaseGroup { get; set; }
|
public string ReleaseGroup { get; set; }
|
||||||
|
public string ReleaseHash { get; set; }
|
||||||
public string SceneName { get; set; }
|
public string SceneName { get; set; }
|
||||||
public bool OtherVideoFiles { get; set; }
|
public bool OtherVideoFiles { get; set; }
|
||||||
public List<CustomFormat> CustomFormats { get; set; }
|
public List<CustomFormat> CustomFormats { get; set; }
|
||||||
|
|
|
@ -83,11 +83,11 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Season+Episode
|
// Anime - [SubGroup] Title Season+Episode
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:[_. ](?!\d+)).*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:[_. ](?!\d+)).*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Episode Absolute Episode Number ([SubGroup] Series Title Episode 01)
|
// Anime - [SubGroup] Title Episode Absolute Episode Number ([SubGroup] Series Title Episode 01)
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+)))+.*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Absolute Episode Number + Season+Episode
|
// Anime - [SubGroup] Title Absolute Episode Number + Season+Episode
|
||||||
|
@ -95,39 +95,39 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Season+Episode + Absolute Episode Number
|
// Anime - [SubGroup] Title Season+Episode + Absolute Episode Number
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:(?:_|-|\s|\.)+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+|\-[a-z])))+.*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:(?:_|-|\s|\.)+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+|\-[a-z])))+.*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title with trailing number Absolute Episode Number - Batch separated with tilde
|
// Anime - [SubGroup] Title with trailing number Absolute Episode Number - Batch separated with tilde
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+))\s?~\s?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+))(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+))\s?~\s?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+))(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title with season number in brackets Absolute Episode Number
|
// Anime - [SubGroup] Title with season number in brackets Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)[_. ]+?\(Season[_. ](?<season>\d+)\)[-_. ]+?(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)[_. ]+?\(Season[_. ](?<season>\d+)\)[-_. ]+?(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title with trailing number Absolute Episode Number
|
// Anime - [SubGroup] Title with trailing number Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title with trailing 3-digit number and sub title - Absolute Episode Number
|
// Anime - [SubGroup] Title with trailing 3-digit number and sub title - Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^]]+?)(?:[-_. ]{3}?(?<absoluteepisode>\d{2}(\.\d{1,2})?(?!-?\d+|-[a-z]+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^]]+?)(?:[-_. ]{3}?(?<absoluteepisode>\d{2}(\.\d{1,2})?(?!-?\d+|-[a-z]+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title with trailing number Absolute Episode Number
|
// Anime - [SubGroup] Title with trailing number Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+)[_ ]+)(?:[-_. ]?(?<absoluteepisode>\d{3}(\.\d{1,2})?(?!\d+|-[a-z]+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+)[_ ]+)(?:[-_. ]?(?<absoluteepisode>\d{3}(\.\d{1,2})?(?!\d+|-[a-z]+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title - Absolute Episode Number
|
// Anime - [SubGroup] Title - Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:(?<!\b[0]\d+))(?:[. ]-[. ](?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-])))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:(?<!\b[0]\d+))(?:[. ]-[. ](?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-])))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Absolute Episode Number - Absolute Episode Number (batches without full separator between title and absolute episode numbers)
|
// Anime - [SubGroup] Title Absolute Episode Number - Absolute Episode Number (batches without full separator between title and absolute episode numbers)
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:(?<!\b[0]\d+))(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-]))[. ]-[. ](?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-]))(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:(?<!\b[0]\d+))(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-]))[. ]-[. ](?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|[-]))(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - [SubGroup] Title Absolute Episode Number
|
// Anime - [SubGroup] Title Absolute Episode Number
|
||||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)[-_. ]+\(?(?:[-_. ]?#?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|-[a-z]+)))+\)?(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)[-_. ]+\(?(?:[-_. ]?#?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+|-[a-z]+)))+\)?(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Multi-episode Repeated (S01E05 - S01E06)
|
// Multi-episode Repeated (S01E05 - S01E06)
|
||||||
|
@ -155,11 +155,11 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number [SubGroup] [Hash]? (Series Title Episode 99-100 [RlsGroup] [ABCD1234])
|
// Anime - Title Absolute Episode Number [SubGroup] [Hash]? (Series Title Episode 99-100 [RlsGroup] [ABCD1234])
|
||||||
new Regex(@"^(?<title>.+?)[-_. ]Episode(?:[-_. ]+(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\].*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?<title>.+?)[-_. ]Episode(?:[-_. ]+(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\].*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number [SubGroup] [Hash]
|
// Anime - Title Absolute Episode Number [SubGroup] [Hash]
|
||||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{3}(\.\d{1,2})(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\].*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{3}(\.\d{1,2})(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\].*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number (Year) [SubGroup]
|
// Anime - Title Absolute Episode Number (Year) [SubGroup]
|
||||||
|
@ -167,11 +167,11 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title with trailing number, Absolute Episode Number and hash
|
// Anime - Title with trailing number, Absolute Episode Number and hash
|
||||||
new Regex(@"^(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])(?:$|\.mkv)",
|
new Regex(@"^(?<title>[^-]+?)(?:(?<![-_. ]|\b[0]\d+) - )(?:[-_. ]?(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>[(\[]\w{8}[)\]])(?:$|\.mkv)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number [Hash]
|
// Anime - Title Absolute Episode Number [Hash]
|
||||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?[-_. ]+.*?(?<hash>\[\w{8}\])(?:$|\.)",
|
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?[-_. ]+.*?(?<hash>[(\[]\w{8}[)\]])$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Episodes with airdate AND season/episode number, capture season/episode only
|
// Episodes with airdate AND season/episode number, capture season/episode only
|
||||||
|
@ -358,7 +358,7 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number (E195 or E1206)
|
// Anime - Title Absolute Episode Number (E195 or E1206)
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:_|-|\s|\.)+(?:e|ep)(?<absoluteepisode>(\d{3}|\d{4})(\.\d{1,2})?))+[-_. ].*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:_|-|\s|\.)+(?:e|ep)(?<absoluteepisode>(\d{3}|\d{4})(\.\d{1,2})?))+[-_. ].*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Supports 1103/1113 naming
|
// Supports 1103/1113 naming
|
||||||
|
@ -386,27 +386,27 @@ namespace NzbDrone.Core.Parser
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime Range - Title Absolute Episode Number (ep01-12)
|
// Anime Range - Title Absolute Episode Number (ep01-12)
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:_|\s|\.)+(?:e|ep)(?<absoluteepisode>\d{2,3}(\.\d{1,2})?)-(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+|-)).*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:_|\s|\.)+(?:e|ep)(?<absoluteepisode>\d{2,3}(\.\d{1,2})?)-(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+|-)).*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number (e66)
|
// Anime - Title Absolute Episode Number (e66)
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:_|-|\s|\.)+(?:e|ep)(?<absoluteepisode>\d{2,4}(\.\d{1,2})?))+[-_. ].*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:_|-|\s|\.)+(?:e|ep)(?<absoluteepisode>\d{2,4}(\.\d{1,2})?))+[-_. ].*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Episode Absolute Episode Number (Series Title Episode 01)
|
// Anime - Title Episode Absolute Episode Number (Series Title Episode 01)
|
||||||
new Regex(@"^(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
new Regex(@"^(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+)))+.*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime Range - Title Absolute Episode Number (1 or 2 digit absolute episode numbers in a range, 1-10)
|
// Anime Range - Title Absolute Episode Number (1 or 2 digit absolute episode numbers in a range, 1-10)
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)[_. ]+(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+))-(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+|-))(?:_|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)[_. ]+(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+))-(?<absoluteepisode>(?<!\d+)\d{1,2}(\.\d{1,2})?(?!\d+|-)).*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title Absolute Episode Number
|
// Anime - Title Absolute Episode Number
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,4}(\.\d{1,2})?(?!\d+|[ip])))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,4}(\.\d{1,2})?(?!\d+|[ip])))+.*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Anime - Title {Absolute Episode Number}
|
// Anime - Title {Absolute Episode Number}
|
||||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+|[ip])))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<absoluteepisode>(?<!\d+)\d{2,3}(\.\d{1,2})?(?!\d+|[ip])))+.*?(?<hash>[(\[]\w{8}[)\]])?$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
// Extant, terrible multi-episode naming (extant.10708.hdtv-lol.mp4)
|
// Extant, terrible multi-episode naming (extant.10708.hdtv-lol.mp4)
|
||||||
|
@ -492,7 +492,7 @@ namespace NzbDrone.Core.Parser
|
||||||
private static readonly Regex FileExtensionRegex = new Regex(@"\.[a-z0-9]{2,4}$",
|
private static readonly Regex FileExtensionRegex = new Regex(@"\.[a-z0-9]{2,4}$",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly RegexReplace SimpleTitleRegex = new RegexReplace(@"(?:(480|540|576|720|1080|2160)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(8|10)b(it)?|10-bit)\s*?",
|
private static readonly RegexReplace SimpleTitleRegex = new RegexReplace(@"(?:(480|540|576|720|1080|2160)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(?<![a-f0-9])(8|10)(b(?![a-z0-9])|bit)|10-bit)\s*?",
|
||||||
string.Empty,
|
string.Empty,
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
@ -1197,7 +1197,7 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
if (hash.Success)
|
if (hash.Success)
|
||||||
{
|
{
|
||||||
var hashValue = hash.Value.Trim('[', ']');
|
var hashValue = hash.Value.Trim('[', ']', '(', ')');
|
||||||
|
|
||||||
if (hashValue.Equals("1280x720"))
|
if (hashValue.Equals("1280x720"))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue