diff --git a/Futonizer.csproj b/Futonizer.csproj
index da12e26..46adaac 100644
--- a/Futonizer.csproj
+++ b/Futonizer.csproj
@@ -9,8 +9,8 @@
enable
Futonizer
Futonizer
- 1.0.13
- 1.0.13.0
+ 1.0.14
+ 1.0.14.0
Assets\app.ico
diff --git a/Services/FileNameHelper.cs b/Services/FileNameHelper.cs
index 79f600b..be9662e 100644
--- a/Services/FileNameHelper.cs
+++ b/Services/FileNameHelper.cs
@@ -60,6 +60,14 @@ public static class FileNameHelper
private static readonly Regex EpisodeStartRegex =
new(@"^(\d+|S\d+E\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
+ // Bare leading episode number with no tag of its own on the file (the
+ // release tag, if any, comes only from the folder), e.g. "11 - Title.mkv",
+ // "06_Title.mkv", "06.Title.mkv". Requires a separator right after the
+ // digits so resolution/quality tokens glued to more characters (e.g.
+ // "1080p") aren't mistaken for an episode number lead-in.
+ private static readonly Regex BareLeadingEpisodeNumberRegex =
+ new(@"^\d{1,3}(?=[\s._-])", RegexOptions.Compiled);
+
// Individual metadata-token patterns used to find where the show name ends
// inside a folder name.
private static readonly Regex[] MetadataPatterns =
@@ -104,8 +112,9 @@ public static class FileNameHelper
/// 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.
+ /// an episode code (e.g. S01E01), or with a bare episode number
+ /// (e.g. "11 - Title") once a release tag has been resolved, the
+ /// show name is derived from the parent folder and prepended.
/// - Release-tag prefix — a [TAG] bracket prefix, sourced from
/// the filename suffix, the folder suffix, or the folder prefix,
/// in that priority order.
@@ -211,6 +220,17 @@ public static class FileNameHelper
}
}
}
+ // Pattern C: file has no tag of its own — the tag came only from
+ // the folder — but the filename still starts with a bare
+ // episode number, e.g. "11 - Title.mkv" in a
+ // "[DmonHiro] Show Name (BD, 1080p)" folder. Inject the show
+ // name here; the tag is prepended separately in step 4.
+ else if (BareLeadingEpisodeNumberRegex.IsMatch(stemNoExt))
+ {
+ string showName = ExtractShowName(folderName);
+ if (!string.IsNullOrEmpty(showName))
+ fileName = showName + " " + fileName;
+ }
}
}
@@ -273,6 +293,19 @@ public static class FileNameHelper
name = FolderSuffixBracketTagRegex.Replace(name, "").Trim();
name = PrefixTagRegex.Replace(name, "").Trim();
+ // Strip a trailing parenthesised metadata block, e.g. "(BD, 1080p)",
+ // when every comma/space-separated word inside it is recognisable
+ // quality/source metadata — so a real release group or descriptive
+ // parenthetical left at the end of the name isn't mistakenly dropped.
+ var trailingParenMatch = TrailingParenGroupRegex.Match(name);
+ if (trailingParenMatch.Success)
+ {
+ var parenWords = trailingParenMatch.Groups[1].Value
+ .Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ if (parenWords.Length > 0 && parenWords.All(IsMetadataToken))
+ name = name[..trailingParenMatch.Index].Trim();
+ }
+
// Nothing left, or what remains immediately starts with a bracket — no show name.
if (string.IsNullOrEmpty(name) || name[0] == '[') return string.Empty;