diff --git a/Futonizer.csproj b/Futonizer.csproj
index 76c76ed..3263779 100644
--- a/Futonizer.csproj
+++ b/Futonizer.csproj
@@ -9,8 +9,8 @@
enable
Futonizer
Futonizer
- 1.0.7
- 1.0.7.0
+ 1.0.8
+ 1.0.8.0
Assets\app.ico
diff --git a/Services/FileNameHelper.cs b/Services/FileNameHelper.cs
index 678afc4..c963cb4 100644
--- a/Services/FileNameHelper.cs
+++ b/Services/FileNameHelper.cs
@@ -20,6 +20,13 @@ public static class FileNameHelper
private static readonly Regex FileSuffixTagRegex =
new(@"-([A-Za-z][A-Za-z0-9]{2,20})$", RegexOptions.Compiled);
+ // Trailing parenthesised metadata block ending in the release group as its
+ // last word, e.g. "... (1080p AMZN WEB-DL x265 Celdra)" → group="Celdra".
+ // Common on Amazon/streaming rips that don't set the group off with a
+ // "-" or its own brackets.
+ private static readonly Regex TrailingParenGroupRegex =
+ new(@"\(([^()]*)\)$", RegexOptions.Compiled);
+
// Prefix release tag: "[KAA] Show Name" → tag = "KAA"
private static readonly Regex PrefixTagRegex =
new(@"^\[(.+?)\]", RegexOptions.Compiled);
@@ -45,7 +52,8 @@ public static class FileNameHelper
new(@"^(BD|BluRay|Blu-Ray|WEB|WEB-DL|WEBRip|HDTV|AMZN|NF|DSNP|HULU|MAX)$",RegexOptions.IgnoreCase | RegexOptions.Compiled), // sources
new(@"^(Remux|Encode)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), // processing
new(@"^(HEVC|AVC|x264|x265|H\.?264|H\.?265|VP9)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), // video codecs
- new(@"^(FLAC|AAC|DTS|TrueHD|Atmos|AC3|EAC3|Opus|MP3)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), // audio codecs
+ new(@"^(FLAC|AAC|DTS(-HD)?|TrueHD|Atmos|E?AC3|DDP?|Opus|MP3)(\d(\.\d)?)?$", RegexOptions.IgnoreCase | RegexOptions.Compiled), // audio codecs (+ optional channel suffix, e.g. DDP5.1)
+ new(@"^\d\.\d$", RegexOptions.Compiled), // bare channel count, e.g. 5.1
new(@"^(HDR|SDR|10bit|8bit|HDR10|DV|DoVi)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), // HDR / bit-depth
];
@@ -56,8 +64,10 @@ public static class FileNameHelper
/// (in order):
///
/// - Filename suffix tag extraction — a trailing -GroupName on
- /// the filename stem is stripped and promoted to a bracket prefix.
- /// Takes priority over any folder-derived tag.
+ /// the filename stem, or a release group tucked in as the last word
+ /// of a trailing (...) metadata block (e.g. Amazon rips like
+ /// (1080p AMZN WEB-DL x265 Celdra)), is stripped and promoted
+ /// to a bracket prefix. Takes priority over any folder-derived tag.
/// - Show-name injection — if the (now tag-free) filename starts with
/// an episode code (e.g. S01E01) the show name is derived from the
/// parent folder and prepended.
@@ -85,6 +95,31 @@ public static class FileNameHelper
stemNoExt = stemNoExt[..fileSuffixMatch.Index];
fileName = stemNoExt + ext;
}
+ else
+ {
+ // 1b. Extract a release group tucked in as the last word of a
+ // trailing "(...)" metadata block, e.g.
+ // "... (1080p AMZN WEB-DL x265 Celdra)" → tag="Celdra",
+ // stem="... (1080p AMZN WEB-DL x265)".
+ var parenMatch = TrailingParenGroupRegex.Match(stemNoExt);
+ if (parenMatch.Success)
+ {
+ string parenContent = parenMatch.Groups[1].Value;
+ var words = parenContent.Split(' ', StringSplitOptions.RemoveEmptyEntries);
+ // Only treat the last word as a release group if the rest of the
+ // block is recognisable quality/source/codec metadata — this
+ // avoids misfiring on unrelated parentheticals like "(2020)" or
+ // "(Dual Audio)" that don't carry a group name.
+ if (words.Length >= 2 && !IsMetadataToken(words[^1]) && words[..^1].Any(IsMetadataToken))
+ {
+ fileTag = words[^1];
+ string remaining = string.Join(" ", words[..^1]);
+ string beforeParen = stemNoExt[..parenMatch.Index].TrimEnd();
+ stemNoExt = string.IsNullOrEmpty(remaining) ? beforeParen : $"{beforeParen} ({remaining})";
+ fileName = stemNoExt + ext;
+ }
+ }
+ }
// 2. Determine the release tag: filename suffix > folder tag.
string? tag = fileTag;