Updated some cases and some spacing on Parser. Cyberpunk 2077 is not implemented as long as there is a # before issue number.

This commit is contained in:
Joseph Milazzo 2021-10-06 08:10:18 -05:00
parent 0be13399f4
commit 6b3b9bc63d
2 changed files with 110 additions and 201 deletions

View file

@ -48,9 +48,9 @@ namespace API.Tests.Parser
[InlineData("Chew v1 - Taster´s Choise (2012) (Digital) (1920) (Kingpin-Empire)", "Chew")] [InlineData("Chew v1 - Taster´s Choise (2012) (Digital) (1920) (Kingpin-Empire)", "Chew")]
[InlineData("Chew Script Book (2011) (digital-Empire) SP04", "Chew Script Book")] [InlineData("Chew Script Book (2011) (digital-Empire) SP04", "Chew Script Book")]
[InlineData("Batman - Detective Comics - Rebirth Deluxe Edition Book 02 (2018) (digital) (Son of Ultron-Empire)", "Batman - Detective Comics - Rebirth Deluxe Edition Book")] [InlineData("Batman - Detective Comics - Rebirth Deluxe Edition Book 02 (2018) (digital) (Son of Ultron-Empire)", "Batman - Detective Comics - Rebirth Deluxe Edition Book")]
[InlineData("Cyberpunk 2077 - Your Voice 01", "Cyberpunk 2077 - Your Voice")] [InlineData("Cyberpunk 2077 - Your Voice #01", "Cyberpunk 2077 - Your Voice")]
[InlineData("Cyberpunk 2077 #01", "Cyberpunk 2077")] [InlineData("Cyberpunk 2077 #01", "Cyberpunk 2077")]
[InlineData("Cyberpunk 2077 - Trauma Team 04.cbz", "Cyberpunk 2077 - Trauma Team")] [InlineData("Cyberpunk 2077 - Trauma Team #04.cbz", "Cyberpunk 2077 - Trauma Team")]
[InlineData("Batgirl Vol.2000 #57 (December, 2004)", "Batgirl")] [InlineData("Batgirl Vol.2000 #57 (December, 2004)", "Batgirl")]
[InlineData("Batgirl V2000 #57", "Batgirl")] [InlineData("Batgirl V2000 #57", "Batgirl")]
[InlineData("Fables 021 (2004) (Digital) (Nahga-Empire).cbr", "Fables")] [InlineData("Fables 021 (2004) (Digital) (Nahga-Empire).cbr", "Fables")]
@ -125,7 +125,7 @@ namespace API.Tests.Parser
[InlineData("Batgirl Vol.2000 #57 (December, 2004)", "57")] [InlineData("Batgirl Vol.2000 #57 (December, 2004)", "57")]
[InlineData("Batgirl V2000 #57", "57")] [InlineData("Batgirl V2000 #57", "57")]
[InlineData("Fables 021 (2004) (Digital) (Nahga-Empire).cbr", "21")] [InlineData("Fables 021 (2004) (Digital) (Nahga-Empire).cbr", "21")]
[InlineData("Cyberpunk 2077 - Trauma Team 04.cbz", "4")] [InlineData("Cyberpunk 2077 - Trauma Team #04.cbz", "4")]
public void ParseComicChapterTest(string filename, string expected) public void ParseComicChapterTest(string filename, string expected)
{ {
Assert.Equal(expected, API.Parser.Parser.ParseComicChapter(filename)); Assert.Equal(expected, API.Parser.Parser.ParseComicChapter(filename));

View file

@ -25,32 +25,24 @@ namespace API.Parser
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant; RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant;
public static readonly Regex FontSrcUrlRegex = new Regex(@"(src:url\(.{1})" + "([^\"']*)" + @"(.{1}\))", public static readonly Regex FontSrcUrlRegex = new Regex(@"(src:url\(.{1})" + "([^\"']*)" + @"(.{1}\))",
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
public static readonly Regex CssImportUrlRegex = new Regex("(@import\\s[\"|'])(?<Filename>[\\w\\d/\\._-]+)([\"|'];?)", public static readonly Regex CssImportUrlRegex = new Regex("(@import\\s[\"|'])(?<Filename>[\\w\\d/\\._-]+)([\"|'];?)",
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly string XmlRegexExtensions = @"\.xml"; private static readonly string XmlRegexExtensions = @"\.xml";
private static readonly Regex ImageRegex = new Regex(ImageFileExtensions, private static readonly Regex ImageRegex = new Regex(ImageFileExtensions,
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex ArchiveFileRegex = new Regex(ArchiveFileExtensions, private static readonly Regex ArchiveFileRegex = new Regex(ArchiveFileExtensions,
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex XmlRegex = new Regex(XmlRegexExtensions, private static readonly Regex XmlRegex = new Regex(XmlRegexExtensions,
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex BookFileRegex = new Regex(BookFileExtensions, private static readonly Regex BookFileRegex = new Regex(BookFileExtensions,
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex CoverImageRegex = new Regex(@"(?<![[a-z]\d])(?:!?)(cover|folder)(?![\w\d])", private static readonly Regex CoverImageRegex = new Regex(@"(?<![[a-z]\d])(?:!?)(cover|folder)(?![\w\d])",
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex NormalizeRegex = new Regex(@"[^a-zA-Z0-9\+]", private static readonly Regex NormalizeRegex = new Regex(@"[^a-zA-Z0-9\+]",
MatchOptions, MatchOptions, RegexTimeout);
RegexTimeout);
private static readonly Regex[] MangaVolumeRegex = new[] private static readonly Regex[] MangaVolumeRegex = new[]
@ -58,43 +50,35 @@ namespace API.Parser
// Dance in the Vampire Bund v16-17 // Dance in the Vampire Bund v16-17
new Regex( new Regex(
@"(?<Series>.*)(\b|_)v(?<Volume>\d+-?\d+)( |_)", @"(?<Series>.*)(\b|_)v(?<Volume>\d+-?\d+)( |_)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// NEEDLESS_Vol.4_-Simeon_6_v2[SugoiSugoi].rar // NEEDLESS_Vol.4_-Simeon_6_v2[SugoiSugoi].rar
new Regex( new Regex(
@"(?<Series>.*)(\b|_)(?!\[)(vol\.?)(?<Volume>\d+(-\d+)?)(?!\])", @"(?<Series>.*)(\b|_)(?!\[)(vol\.?)(?<Volume>\d+(-\d+)?)(?!\])",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Historys Strongest Disciple Kenichi_v11_c90-98.zip or Dance in the Vampire Bund v16-17 // Historys Strongest Disciple Kenichi_v11_c90-98.zip or Dance in the Vampire Bund v16-17
new Regex( new Regex(
@"(?<Series>.*)(\b|_)(?!\[)v(?<Volume>\d+(-\d+)?)(?!\])", @"(?<Series>.*)(\b|_)(?!\[)v(?<Volume>\d+(-\d+)?)(?!\])",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Kodomo no Jikan vol. 10, [dmntsf.net] One Piece - Digital Colored Comics Vol. 20.5-21.5 Ch. 177 // Kodomo no Jikan vol. 10, [dmntsf.net] One Piece - Digital Colored Comics Vol. 20.5-21.5 Ch. 177
new Regex( new Regex(
@"(?<Series>.*)(\b|_)(vol\.? ?)(?<Volume>\d+(\.\d)?(-\d+)?(\.\d)?)", @"(?<Series>.*)(\b|_)(vol\.? ?)(?<Volume>\d+(\.\d)?(-\d+)?(\.\d)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb) // Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
new Regex( new Regex(
@"(vol\.? ?)(?<Volume>\d+(\.\d)?)", @"(vol\.? ?)(?<Volume>\d+(\.\d)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Tonikaku Cawaii [Volume 11].cbz // Tonikaku Cawaii [Volume 11].cbz
new Regex( new Regex(
@"(volume )(?<Volume>\d+(\.\d)?)", @"(volume )(?<Volume>\d+(\.\d)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Tower Of God S01 014 (CBT) (digital).cbz // Tower Of God S01 014 (CBT) (digital).cbz
new Regex( new Regex(
@"(?<Series>.*)(\b|_|)(S(?<Volume>\d+))", @"(?<Series>.*)(\b|_|)(S(?<Volume>\d+))",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// vol_001-1.cbz for MangaPy default naming convention // vol_001-1.cbz for MangaPy default naming convention
new Regex( new Regex(
@"(vol_)(?<Volume>\d+(\.\d)?)", @"(vol_)(?<Volume>\d+(\.\d)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] MangaSeriesRegex = new[] private static readonly Regex[] MangaSeriesRegex = new[]
@ -102,13 +86,11 @@ namespace API.Parser
// Grand Blue Dreaming - SP02 // Grand Blue Dreaming - SP02
new Regex( new Regex(
@"(?<Series>.*)(\b|_|-|\s)(?:sp)\d", @"(?<Series>.*)(\b|_|-|\s)(?:sp)\d",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [SugoiSugoi]_NEEDLESS_Vol.2_-_Disk_The_Informant_5_[ENG].rar, Yuusha Ga Shinda! - Vol.tbd Chapter 27.001 V2 Infection ①.cbz // [SugoiSugoi]_NEEDLESS_Vol.2_-_Disk_The_Informant_5_[ENG].rar, Yuusha Ga Shinda! - Vol.tbd Chapter 27.001 V2 Infection ①.cbz
new Regex( new Regex(
@"^(?<Series>.*)( |_)Vol\.?(\d+|tbd)", @"^(?<Series>.*)( |_)Vol\.?(\d+|tbd)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Mad Chimera World - Volume 005 - Chapter 026.cbz (couldn't figure out how to get Volume negative lookaround working on below regex), // Mad Chimera World - Volume 005 - Chapter 026.cbz (couldn't figure out how to get Volume negative lookaround working on below regex),
// The Duke of Death and His Black Maid - Vol. 04 Ch. 054.5 - V4 Omake // The Duke of Death and His Black Maid - Vol. 04 Ch. 054.5 - V4 Omake
new Regex( new Regex(
@ -123,23 +105,19 @@ namespace API.Parser
// Gokukoku no Brynhildr - c001-008 (v01) [TrinityBAKumA], Black Bullet - v4 c17 [batoto] // Gokukoku no Brynhildr - c001-008 (v01) [TrinityBAKumA], Black Bullet - v4 c17 [batoto]
new Regex( new Regex(
@"(?<Series>.*)( - )(?:v|vo|c)\d", @"(?<Series>.*)( - )(?:v|vo|c)\d",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Kedouin Makoto - Corpse Party Musume, Chapter 19 [Dametrans].zip // Kedouin Makoto - Corpse Party Musume, Chapter 19 [Dametrans].zip
new Regex( new Regex(
@"(?<Series>.*)(?:, Chapter )(?<Chapter>\d+)", @"(?<Series>.*)(?:, Chapter )(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Please Go Home, Akutsu-San! - Chapter 038.5 - Volume Announcement.cbz // Please Go Home, Akutsu-San! - Chapter 038.5 - Volume Announcement.cbz
new Regex( new Regex(
@"(?<Series>.*)(\s|_|-)(?!Vol)(\s|_|-)(?:Chapter)(\s|_|-)(?<Chapter>\d+)", @"(?<Series>.*)(\s|_|-)(?!Vol)(\s|_|-)(?:Chapter)(\s|_|-)(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [dmntsf.net] One Piece - Digital Colored Comics Vol. 20 Ch. 177 - 30 Million vs 81 Million.cbz // [dmntsf.net] One Piece - Digital Colored Comics Vol. 20 Ch. 177 - 30 Million vs 81 Million.cbz
new Regex( new Regex(
@"(?<Series>.*) (\b|_|-)(vol)\.?(\s|-|_)?\d+", @"(?<Series>.*) (\b|_|-)(vol)\.?(\s|-|_)?\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [xPearse] Kyochuu Rettou Volume 1 [English] [Manga] [Volume Scans] // [xPearse] Kyochuu Rettou Volume 1 [English] [Manga] [Volume Scans]
new Regex( new Regex(
@"(?<Series>.*) (\b|_|-)(vol)(ume)", @"(?<Series>.*) (\b|_|-)(vol)(ume)",
@ -148,121 +126,98 @@ namespace API.Parser
//Knights of Sidonia c000 (S2 LE BD Omake - BLAME!) [Habanero Scans] //Knights of Sidonia c000 (S2 LE BD Omake - BLAME!) [Habanero Scans]
new Regex( new Regex(
@"(?<Series>.*)(\bc\d+\b)", @"(?<Series>.*)(\bc\d+\b)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
//Tonikaku Cawaii [Volume 11], Darling in the FranXX - Volume 01.cbz //Tonikaku Cawaii [Volume 11], Darling in the FranXX - Volume 01.cbz
new Regex( new Regex(
@"(?<Series>.*)(?: _|-|\[|\()\s?vol(ume)?", @"(?<Series>.*)(?: _|-|\[|\()\s?vol(ume)?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Momo The Blood Taker - Chapter 027 Violent Emotion.cbz, Grand Blue Dreaming - SP02 Extra (2019) (Digital) (danke-Empire).cbz // Momo The Blood Taker - Chapter 027 Violent Emotion.cbz, Grand Blue Dreaming - SP02 Extra (2019) (Digital) (danke-Empire).cbz
new Regex( new Regex(
@"^(?<Series>(?!Vol).+?)(?:(ch(apter|\.)(\b|_|-|\s))|sp)\d", @"^(?<Series>(?!Vol).+?)(?:(ch(apter|\.)(\b|_|-|\s))|sp)\d",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb) // Historys Strongest Disciple Kenichi_v11_c90-98.zip, Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
new Regex( new Regex(
@"(?<Series>.*) (\b|_|-)(v|ch\.?|c)\d+", @"(?<Series>.*) (\b|_|-)(v|ch\.?|c)\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
//Ichinensei_ni_Nacchattara_v01_ch01_[Taruby]_v1.1.zip must be before [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip //Ichinensei_ni_Nacchattara_v01_ch01_[Taruby]_v1.1.zip must be before [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
// due to duplicate version identifiers in file. // due to duplicate version identifiers in file.
new Regex( new Regex(
@"(?<Series>.*)(v|s)\d+(-\d+)?(_|\s)", @"(?<Series>.*)(v|s)\d+(-\d+)?(_|\s)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
//[Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip //[Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
new Regex( new Regex(
@"(?<Series>.*)(v|s)\d+(-\d+)?", @"(?<Series>.*)(v|s)\d+(-\d+)?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Hinowa ga CRUSH! 018 (2019) (Digital) (LuCaZ).cbz // Hinowa ga CRUSH! 018 (2019) (Digital) (LuCaZ).cbz
new Regex( new Regex(
@"(?<Series>.*) (?<Chapter>\d+) (?:\(\d{4}\)) ", @"(?<Series>.*) (?<Chapter>\d+) (?:\(\d{4}\)) ",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Goblin Slayer - Brand New Day 006.5 (2019) (Digital) (danke-Empire) // Goblin Slayer - Brand New Day 006.5 (2019) (Digital) (danke-Empire)
new Regex( new Regex(
@"(?<Series>.*) (?<Chapter>\d+(?:.\d+|-\d+)?) \(\d{4}\)", @"(?<Series>.*) (?<Chapter>\d+(?:.\d+|-\d+)?) \(\d{4}\)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Noblesse - Episode 429 (74 Pages).7z // Noblesse - Episode 429 (74 Pages).7z
new Regex( new Regex(
@"(?<Series>.*)(\s|_)(?:Episode|Ep\.?)(\s|_)(?<Chapter>\d+(?:.\d+|-\d+)?)", @"(?<Series>.*)(\s|_)(?:Episode|Ep\.?)(\s|_)(?<Chapter>\d+(?:.\d+|-\d+)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Akame ga KILL! ZERO (2016-2019) (Digital) (LuCaZ) // Akame ga KILL! ZERO (2016-2019) (Digital) (LuCaZ)
new Regex( new Regex(
@"(?<Series>.*)\(\d", @"(?<Series>.*)\(\d",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Tonikaku Kawaii (Ch 59-67) (Ongoing) // Tonikaku Kawaii (Ch 59-67) (Ongoing)
new Regex( new Regex(
@"(?<Series>.*)(\s|_)\((c\s|ch\s|chapter\s)", @"(?<Series>.*)(\s|_)\((c\s|ch\s|chapter\s)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Black Bullet (This is very loose, keep towards bottom) // Black Bullet (This is very loose, keep towards bottom)
new Regex( new Regex(
@"(?<Series>.*)(_)(v|vo|c|volume)( |_)\d+", @"(?<Series>.*)(_)(v|vo|c|volume)( |_)\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [Hidoi]_Amaenaideyo_MS_vol01_chp02.rar // [Hidoi]_Amaenaideyo_MS_vol01_chp02.rar
new Regex( new Regex(
@"(?<Series>.*)( |_)(vol\d+)?( |_)(?:Chp\.? ?\d+)", @"(?<Series>.*)( |_)(vol\d+)?( |_)(?:Chp\.? ?\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Mahoutsukai to Deshi no Futekisetsu na Kankei Chp. 1 // Mahoutsukai to Deshi no Futekisetsu na Kankei Chp. 1
new Regex( new Regex(
@"(?<Series>.*)( |_)(?:Chp.? ?\d+)", @"(?<Series>.*)( |_)(?:Chp.? ?\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Corpse Party -The Anthology- Sachikos game of love Hysteric Birthday 2U Chapter 01 // Corpse Party -The Anthology- Sachikos game of love Hysteric Birthday 2U Chapter 01
new Regex( new Regex(
@"^(?!Vol)(?<Series>.*)( |_)Chapter( |_)(\d+)", @"^(?!Vol)(?<Series>.*)( |_)Chapter( |_)(\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Fullmetal Alchemist chapters 101-108.cbz // Fullmetal Alchemist chapters 101-108.cbz
new Regex( new Regex(
@"^(?!vol)(?<Series>.*)( |_)(chapters( |_)?)\d+-?\d*", @"^(?!vol)(?<Series>.*)( |_)(chapters( |_)?)\d+-?\d*",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Umineko no Naku Koro ni - Episode 1 - Legend of the Golden Witch #1 // Umineko no Naku Koro ni - Episode 1 - Legend of the Golden Witch #1
new Regex( new Regex(
@"^(?!Vol\.?)(?<Series>.*)( |_|-)(?<!-)(episode|chapter|(ch\.?) ?)\d+-?\d*", @"^(?!Vol\.?)(?<Series>.*)( |_|-)(?<!-)(episode|chapter|(ch\.?) ?)\d+-?\d*",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Baketeriya ch01-05.zip // Baketeriya ch01-05.zip
new Regex( new Regex(
@"^(?!Vol)(?<Series>.*)ch\d+-?\d?", @"^(?!Vol)(?<Series>.*)ch\d+-?\d?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Magi - Ch.252-005.cbz // Magi - Ch.252-005.cbz
new Regex( new Regex(
@"(?<Series>.*)( ?- ?)Ch\.\d+-?\d*", @"(?<Series>.*)( ?- ?)Ch\.\d+-?\d*",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [BAA]_Darker_than_Black_Omake-1.zip // [BAA]_Darker_than_Black_Omake-1.zip
new Regex( new Regex(
@"^(?!Vol)(?<Series>.*)(-)\d+-?\d*", // This catches a lot of stuff ^(?!Vol)(?<Series>.*)( |_)(\d+) @"^(?!Vol)(?<Series>.*)(-)\d+-?\d*", // This catches a lot of stuff ^(?!Vol)(?<Series>.*)( |_)(\d+)
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Kodoja #001 (March 2016) // Kodoja #001 (March 2016)
new Regex( new Regex(
@"(?<Series>.*)(\s|_|-)#", @"(?<Series>.*)(\s|_|-)#",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Baketeriya ch01-05.zip, Akiiro Bousou Biyori - 01.jpg, Beelzebub_172_RHS.zip, Cynthia the Mission 29.rar, A Compendium of Ghosts - 031 - The Third Story_ Part 12 (Digital) (Cobalt001) // Baketeriya ch01-05.zip, Akiiro Bousou Biyori - 01.jpg, Beelzebub_172_RHS.zip, Cynthia the Mission 29.rar, A Compendium of Ghosts - 031 - The Third Story_ Part 12 (Digital) (Cobalt001)
new Regex( new Regex(
@"^(?!Vol\.?)(?<Series>.+?)( |_|-)(?<!-)(ch)?\d+-?\d*", @"^(?!Vol\.?)(?<Series>.+?)( |_|-)(?<!-)(ch)?\d+-?\d*",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [BAA]_Darker_than_Black_c1 (This is very greedy, make sure it's close to last) // [BAA]_Darker_than_Black_c1 (This is very greedy, make sure it's close to last)
new Regex( new Regex(
@"^(?!Vol)(?<Series>.*)( |_|-)(ch?)\d+", @"^(?!Vol)(?<Series>.*)( |_|-)(ch?)\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] ComicSeriesRegex = new[] private static readonly Regex[] ComicSeriesRegex = new[]
@ -270,85 +225,67 @@ namespace API.Parser
// Invincible Vol 01 Family matters (2005) (Digital) // Invincible Vol 01 Family matters (2005) (Digital)
new Regex( new Regex(
@"(?<Series>.*)(\b|_)(vol\.?)( |_)(?<Volume>\d+(-\d+)?)", @"(?<Series>.*)(\b|_)(vol\.?)( |_)(?<Volume>\d+(-\d+)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman Beyond 2.0 001 (2013) // Batman Beyond 2.0 001 (2013)
new Regex( new Regex(
@"^(?<Series>.+?\S\.\d) (?<Chapter>\d+)", @"^(?<Series>.+?\S\.\d) (?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// 04 - Asterix the Gladiator (1964) (Digital-Empire) (WebP by Doc MaKS) // 04 - Asterix the Gladiator (1964) (Digital-Empire) (WebP by Doc MaKS)
new Regex( new Regex(
@"^(?<Volume>\d+) (- |_)?(?<Series>.*(\d{4})?)( |_)(\(|\d+)", @"^(?<Volume>\d+) (- |_)?(?<Series>.*(\d{4})?)( |_)(\(|\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// 01 Spider-Man & Wolverine 01.cbr // 01 Spider-Man & Wolverine 01.cbr
new Regex( new Regex(
@"^(?<Volume>\d+) (?:- )?(?<Series>.*) (\d+)?", @"^(?<Volume>\d+) (?:- )?(?<Series>.*) (\d+)?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman & Wildcat (1 of 3) // Batman & Wildcat (1 of 3)
new Regex( new Regex(
@"(?<Series>.*(\d{4})?)( |_)(?:\((?<Volume>\d+) of \d+)", @"(?<Series>.*(\d{4})?)( |_)(?:\((?<Volume>\d+) of \d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus) // Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)v\d+", @"^(?<Series>.*)(?: |_)v\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Amazing Man Comics chapter 25 // Amazing Man Comics chapter 25
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)c(hapter) \d+", @"^(?<Series>.*)(?: |_)c(hapter) \d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Amazing Man Comics issue #25 // Amazing Man Comics issue #25
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)i(ssue) #\d+", @"^(?<Series>.*)(?: |_)i(ssue) #\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman Wayne Family Adventures - Ep. 001 - Moving In // Batman Wayne Family Adventures - Ep. 001 - Moving In
new Regex( new Regex(
@"^(?<Series>.+?)(\s|_|-)?(?:Ep\.?)(\s|_|-)+\d+", @"^(?<Series>.+?)(\s|_|-)?(?:Ep\.?)(\s|_|-)+\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batgirl Vol.2000 #57 (December, 2004) // Batgirl Vol.2000 #57 (December, 2004)
new Regex( new Regex(
@"^(?<Series>.+?)Vol\.?\s?#?(?:\d+)", @"^(?<Series>.+?)Vol\.?\s?#?(?:\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman & Catwoman - Trail of the Gun 01, Batman & Grendel (1996) 01 - Devil's Bones, Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex(
@"^(?<Series>.+?)(?: \d+)",
MatchOptions,
RegexTimeout),
// Batman & Robin the Teen Wonder #0 // Batman & Robin the Teen Wonder #0
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)#\d+", @"^(?<Series>.*)(?: |_)#\d+",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout), // Batman & Catwoman - Trail of the Gun 01, Batman & Grendel (1996) 01 - Devil's Bones, Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex(
@"^(?<Series>.+?)(?: \d+)",
MatchOptions, RegexTimeout),
// Scott Pilgrim 02 - Scott Pilgrim vs. The World (2005) // Scott Pilgrim 02 - Scott Pilgrim vs. The World (2005)
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)(?<Volume>\d+)", @"^(?<Series>.*)(?: |_)(?<Volume>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// The First Asterix Frieze (WebP by Doc MaKS) // The First Asterix Frieze (WebP by Doc MaKS)
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)(?!\(\d{4}|\d{4}-\d{2}\))\(", @"^(?<Series>.*)(?: |_)(?!\(\d{4}|\d{4}-\d{2}\))\(",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// spawn-123 (from https://github.com/Girbons/comics-downloader) // spawn-123 (from https://github.com/Girbons/comics-downloader)
new Regex( new Regex(
@"^(?<Series>.+?)-(?<Chapter>\d+)", @"^(?<Series>.+?)-(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// MUST BE LAST: Batman & Daredevil - King of New York // MUST BE LAST: Batman & Daredevil - King of New York
new Regex( new Regex(
@"^(?<Series>.*)", @"^(?<Series>.*)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] ComicVolumeRegex = new[] private static readonly Regex[] ComicVolumeRegex = new[]
@ -356,13 +293,11 @@ namespace API.Parser
// Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus) // Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)v(?<Volume>\d+)", @"^(?<Series>.*)(?: |_)v(?<Volume>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batgirl Vol.2000 #57 (December, 2004) // Batgirl Vol.2000 #57 (December, 2004)
new Regex( new Regex(
@"^(?<Series>.+?)(?:\s|_)vol\.?\s?(?<Volume>\d+)", @"^(?<Series>.+?)(?:\s|_)vol\.?\s?(?<Volume>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] ComicChapterRegex = new[] private static readonly Regex[] ComicChapterRegex = new[]
@ -370,28 +305,27 @@ namespace API.Parser
// Batman & Wildcat (1 of 3) // Batman & Wildcat (1 of 3)
new Regex( new Regex(
@"(?<Series>.*(\d{4})?)( |_)(?:\((?<Chapter>\d+) of \d+)", @"(?<Series>.*(\d{4})?)( |_)(?:\((?<Chapter>\d+) of \d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman Beyond 04 (of 6) (1999) // Batman Beyond 04 (of 6) (1999)
new Regex( new Regex(
@"(?<Series>.+?)(?<Chapter>\d+)(\s|_|-)?\(of", @"(?<Series>.+?)(?<Chapter>\d+)(\s|_|-)?\(of",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman Beyond 2.0 001 (2013) // Batman Beyond 2.0 001 (2013)
new Regex( new Regex(
@"^(?<Series>.+?\S\.\d) (?<Chapter>\d+)", @"^(?<Series>.+?\S\.\d) (?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus) // Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex( new Regex(
@"^(?<Series>.+?)(?: |_)v(?<Volume>\d+)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)(c? ?)", @"^(?<Series>.+?)(?: |_)v(?<Volume>\d+)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)(c? ?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout), // Batman & Robin the Teen Wonder #0
new Regex(
@"^(?<Series>.+?)(?:\s|_)#(?<Chapter>\d+)",
MatchOptions, RegexTimeout),
// Invincible 070.5 - Invincible Returns 1 (2010) (digital) (Minutemen-InnerDemons).cbr // Invincible 070.5 - Invincible Returns 1 (2010) (digital) (Minutemen-InnerDemons).cbr
new Regex( new Regex(
@"^(?<Series>.+?)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)(c? ?)-", @"^(?<Series>.+?)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)(c? ?)-",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batgirl Vol.2000 #57 (December, 2004) // Batgirl Vol.2000 #57 (December, 2004)
new Regex( new Regex(
@"^(?<Series>.+?)(?:vol\.?\d+)\s#(?<Chapter>\d+)", @"^(?<Series>.+?)(?:vol\.?\d+)\s#(?<Chapter>\d+)",
@ -400,41 +334,36 @@ namespace API.Parser
// Batman & Catwoman - Trail of the Gun 01, Batman & Grendel (1996) 01 - Devil's Bones, Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus) // Batman & Catwoman - Trail of the Gun 01, Batman & Grendel (1996) 01 - Devil's Bones, Teen Titans v1 001 (1966-02) (digital) (OkC.O.M.P.U.T.O.-Novus)
new Regex( new Regex(
@"^(?<Series>.+?)(?: (?<Chapter>\d+))", @"^(?<Series>.+?)(?: (?<Chapter>\d+))",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Batman & Robin the Teen Wonder #0
new Regex(
@"^(?<Series>.+?)(?:\s|_)#(?<Chapter>\d+)",
MatchOptions,
RegexTimeout),
// Saga 001 (2012) (Digital) (Empire-Zone) // Saga 001 (2012) (Digital) (Empire-Zone)
new Regex( new Regex(
@"(?<Series>.+?)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)\s\(\d{4}", @"(?<Series>.+?)(?: |_)(c? ?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)\s\(\d{4}",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Amazing Man Comics chapter 25 // Amazing Man Comics chapter 25
new Regex( new Regex(
@"^(?!Vol)(?<Series>.+?)( |_)c(hapter)( |_)(?<Chapter>\d*)", @"^(?!Vol)(?<Series>.+?)( |_)c(hapter)( |_)(?<Chapter>\d*)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Amazing Man Comics issue #25 // Amazing Man Comics issue #25
new Regex( new Regex(
@"^(?!Vol)(?<Series>.+?)( |_)i(ssue)( |_) #(?<Chapter>\d*)", @"^(?!Vol)(?<Series>.+?)( |_)i(ssue)( |_) #(?<Chapter>\d*)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// spawn-123 (from https://github.com/Girbons/comics-downloader ) // spawn-123 (from https://github.com/Girbons/comics-downloader )
new Regex( new Regex(
@"^(?<Series>.+?)-(?<Chapter>\d+)", @"^(?<Series>.+?)-(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout), // Cyberpunk 2077 - Your Voice 01
// new Regex(
// @"^(?<Series>.+?\s?-\s?(?:.+?))(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)$",
// MatchOptions,
// RegexTimeout),
}; };
private static readonly Regex[] ReleaseGroupRegex = new[] private static readonly Regex[] ReleaseGroupRegex = new[]
{ {
// [TrinityBAKumA Finella&anon], [BAA]_, [SlowManga&OverloadScans], [batoto] // [TrinityBAKumA Finella&anon], [BAA]_, [SlowManga&OverloadScans], [batoto]
new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)", new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// (Shadowcat-Empire), // (Shadowcat-Empire),
// new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)", // new Regex(@"(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
// MatchOptions), // MatchOptions),
@ -445,76 +374,62 @@ namespace API.Parser
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, ...c90.5-100.5 // Historys Strongest Disciple Kenichi_v11_c90-98.zip, ...c90.5-100.5
new Regex( new Regex(
@"(\b|_)(c|ch)(\.?\s?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)", @"(\b|_)(c|ch)(\.?\s?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip // [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
new Regex( new Regex(
@"v\d+\.(?<Chapter>\d+(?:.\d+|-\d+)?)", @"v\d+\.(?<Chapter>\d+(?:.\d+|-\d+)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Umineko no Naku Koro ni - Episode 3 - Banquet of the Golden Witch #02.cbz (Rare case, if causes issue remove) // Umineko no Naku Koro ni - Episode 3 - Banquet of the Golden Witch #02.cbz (Rare case, if causes issue remove)
new Regex( new Regex(
@"^(?<Series>.*)(?: |_)#(?<Chapter>\d+)", @"^(?<Series>.*)(?: |_)#(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Green Worldz - Chapter 027, Kimi no Koto ga Daidaidaidaidaisuki na 100-nin no Kanojo Chapter 11-10 // Green Worldz - Chapter 027, Kimi no Koto ga Daidaidaidaidaisuki na 100-nin no Kanojo Chapter 11-10
new Regex( new Regex(
@"^(?!Vol)(?<Series>.*)\s?(?<!vol\. )\sChapter\s(?<Chapter>\d+(?:\.?[\d-]+)?)", @"^(?!Vol)(?<Series>.*)\s?(?<!vol\. )\sChapter\s(?<Chapter>\d+(?:\.?[\d-]+)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Hinowa ga CRUSH! 018 (2019) (Digital) (LuCaZ).cbz, Hinowa ga CRUSH! 018.5 (2019) (Digital) (LuCaZ).cbz // Hinowa ga CRUSH! 018 (2019) (Digital) (LuCaZ).cbz, Hinowa ga CRUSH! 018.5 (2019) (Digital) (LuCaZ).cbz
new Regex( new Regex(
@"^(?!Vol)(?<Series>.+?)(?<!Vol)\.?\s(?<Chapter>\d+(?:.\d+|-\d+)?)(?:\s\(\d{4}\))?(\b|_|-)", @"^(?!Vol)(?<Series>.+?)(?<!Vol)\.?\s(?<Chapter>\d+(?:.\d+|-\d+)?)(?:\s\(\d{4}\))?(\b|_|-)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Tower Of God S01 014 (CBT) (digital).cbz // Tower Of God S01 014 (CBT) (digital).cbz
new Regex( new Regex(
@"(?<Series>.*)\sS(?<Volume>\d+)\s(?<Chapter>\d+(?:.\d+|-\d+)?)", @"(?<Series>.*)\sS(?<Volume>\d+)\s(?<Chapter>\d+(?:.\d+|-\d+)?)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Beelzebub_01_[Noodles].zip, Beelzebub_153b_RHS.zip // Beelzebub_01_[Noodles].zip, Beelzebub_153b_RHS.zip
new Regex( new Regex(
@"^((?!v|vo|vol|Volume).)*(\s|_)(?<Chapter>\.?\d+(?:.\d+|-\d+)?)(?<Part>b)?(\s|_|\[|\()", @"^((?!v|vo|vol|Volume).)*(\s|_)(?<Chapter>\.?\d+(?:.\d+|-\d+)?)(?<Part>b)?(\s|_|\[|\()",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Yumekui-Merry_DKThias_Chapter21.zip // Yumekui-Merry_DKThias_Chapter21.zip
new Regex( new Regex(
@"Chapter(?<Chapter>\d+(-\d+)?)", //(?:.\d+|-\d+)? @"Chapter(?<Chapter>\d+(-\d+)?)", //(?:.\d+|-\d+)?
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// [Hidoi]_Amaenaideyo_MS_vol01_chp02.rar // [Hidoi]_Amaenaideyo_MS_vol01_chp02.rar
new Regex( new Regex(
@"(?<Series>.*)(\s|_)(vol\d+)?(\s|_)Chp\.? ?(?<Chapter>\d+)", @"(?<Series>.*)(\s|_)(vol\d+)?(\s|_)Chp\.? ?(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Vol 1 Chapter 2 // Vol 1 Chapter 2
new Regex( new Regex(
@"(?<Volume>((vol|volume|v))?(\s|_)?\.?\d+)(\s|_)(Chp|Chapter)\.?(\s|_)?(?<Chapter>\d+)", @"(?<Volume>((vol|volume|v))?(\s|_)?\.?\d+)(\s|_)(Chp|Chapter)\.?(\s|_)?(?<Chapter>\d+)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] MangaEditionRegex = { private static readonly Regex[] MangaEditionRegex = {
// Tenjo Tenge {Full Contact Edition} v01 (2011) (Digital) (ASTC).cbz // Tenjo Tenge {Full Contact Edition} v01 (2011) (Digital) (ASTC).cbz
new Regex( new Regex(
@"(?<Edition>({|\(|\[).* Edition(}|\)|\]))", @"(?<Edition>({|\(|\[).* Edition(}|\)|\]))",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Tenjo Tenge {Full Contact Edition} v01 (2011) (Digital) (ASTC).cbz // Tenjo Tenge {Full Contact Edition} v01 (2011) (Digital) (ASTC).cbz
new Regex( new Regex(
@"(\b|_)(?<Edition>Omnibus(( |_)?Edition)?)(\b|_)?", @"(\b|_)(?<Edition>Omnibus(( |_)?Edition)?)(\b|_)?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// To Love Ru v01 Uncensored (Ch.001-007) // To Love Ru v01 Uncensored (Ch.001-007)
new Regex( new Regex(
@"(\b|_)(?<Edition>Uncensored)(\b|_)", @"(\b|_)(?<Edition>Uncensored)(\b|_)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// AKIRA - c003 (v01) [Full Color] [Darkhorse].cbz // AKIRA - c003 (v01) [Full Color] [Darkhorse].cbz
new Regex( new Regex(
@"(\b|_)(?<Edition>Full(?: |_)Color)(\b|_)?", @"(\b|_)(?<Edition>Full(?: |_)Color)(\b|_)?",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] CleanupRegex = private static readonly Regex[] CleanupRegex =
@ -522,18 +437,15 @@ namespace API.Parser
// (), {}, [] // (), {}, []
new Regex( new Regex(
@"(?<Cleanup>(\{\}|\[\]|\(\)))", @"(?<Cleanup>(\{\}|\[\]|\(\)))",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// (Complete) // (Complete)
new Regex( new Regex(
@"(?<Cleanup>(\{Complete\}|\[Complete\]|\(Complete\)))", @"(?<Cleanup>(\{Complete\}|\[Complete\]|\(Complete\)))",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
// Anything in parenthesis // Anything in parenthesis
new Regex( new Regex(
@"\(.*\)", @"\(.*\)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] MangaSpecialRegex = private static readonly Regex[] MangaSpecialRegex =
@ -541,8 +453,7 @@ namespace API.Parser
// All Keywords, does not account for checking if contains volume/chapter identification. Parser.Parse() will handle. // All Keywords, does not account for checking if contains volume/chapter identification. Parser.Parse() will handle.
new Regex( new Regex(
@"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Art Collection|Side( |_)Stories|Bonus)", @"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Art Collection|Side( |_)Stories|Bonus)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
private static readonly Regex[] ComicSpecialRegex = private static readonly Regex[] ComicSpecialRegex =
@ -550,15 +461,13 @@ namespace API.Parser
// All Keywords, does not account for checking if contains volume/chapter identification. Parser.Parse() will handle. // All Keywords, does not account for checking if contains volume/chapter identification. Parser.Parse() will handle.
new Regex( new Regex(
@"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Book \d.+?|Compendium \d.+?|Omnibus \d.+?|TPB \d.+?|FCBD \d.+?|Absolute \d.+?|Preview \d.+?|Art Collection|Side( |_)Stories|Bonus)", @"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Book \d.+?|Compendium \d.+?|Omnibus \d.+?|TPB \d.+?|FCBD \d.+?|Absolute \d.+?|Preview \d.+?|Art Collection|Side( |_)Stories|Bonus)",
MatchOptions, MatchOptions, RegexTimeout),
RegexTimeout),
}; };
// If SP\d+ is in the filename, we force treat it as a special regardless if volume or chapter might have been found. // If SP\d+ is in the filename, we force treat it as a special regardless if volume or chapter might have been found.
private static readonly Regex SpecialMarkerRegex = new Regex( private static readonly Regex SpecialMarkerRegex = new Regex(
@"(?<Special>SP\d+)", @"(?<Special>SP\d+)",
MatchOptions, MatchOptions, RegexTimeout
RegexTimeout
); );