From 1d24c1df170d743d5b0d2c1c8c503e44486c6875 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 25 Aug 2026 20:12:52 +0200 Subject: Keep an OMDb credit whole when its annotation holds a comma --- .../Plugins/Omdb/OmdbProvider.cs | 32 ++++++++++++++++++++-- .../Omdb/OmdbProviderTests.cs | 14 ++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 7262cddd33..d51d913caa 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -443,7 +443,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var names = new List(); - foreach (var credit in credits.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) + foreach (var credit in SplitCredits(credits)) { // OMDb annotates the credited role in parentheses, e.g. "Mari Okada (screenplay)". The same // person can be credited more than once this way, so strip it and let AddPerson deduplicate. @@ -451,9 +451,10 @@ namespace MediaBrowser.Providers.Plugins.Omdb var annotation = name.IndexOf('(', StringComparison.Ordinal); if (annotation >= 0) { - name = name[..annotation].TrimEnd(); + name = name[..annotation]; } + name = name.Trim(); if (name.Length == 0) { continue; @@ -480,6 +481,33 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } + // Only the commas between credits, never one inside an annotation: "Jerry Siegel (created by: + // Superman, Superboy)" is one credit, and splitting it blindly invents a person called "Superboy)". + private static IEnumerable SplitCredits(string credits) + { + var depth = 0; + var start = 0; + + for (var i = 0; i < credits.Length; i++) + { + switch (credits[i]) + { + case '(': + depth++; + break; + case ')': + depth = Math.Max(0, depth - 1); + break; + case ',' when depth == 0: + yield return credits[start..i]; + start = i + 1; + break; + } + } + + yield return credits[start..]; + } + private static bool IsNameSuffix(string value) { var suffix = value.EndsWith('.') ? value[..^1] : value; diff --git a/tests/Jellyfin.Providers.Tests/Omdb/OmdbProviderTests.cs b/tests/Jellyfin.Providers.Tests/Omdb/OmdbProviderTests.cs index 5e053943af..bd50a903f1 100644 --- a/tests/Jellyfin.Providers.Tests/Omdb/OmdbProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Omdb/OmdbProviderTests.cs @@ -34,6 +34,20 @@ namespace Jellyfin.Providers.Tests.Omdb result.People!.Select(p => p.Name)); } + [Theory] + [InlineData( + "Jerry Siegel (created by: Superman, Superboy), Bob Kane (created by: Batman)", + "Jerry Siegel|Bob Kane")] + [InlineData("Alan Moore (created by: John Constantine)", "Alan Moore")] + public void AddPeople_CommaInsideAnAnnotation_StaysOneCredit(string credits, string expected) + { + var result = new MetadataResult(); + + OmdbProvider.AddPeople(result, credits, PersonKind.Writer); + + Assert.Equal(expected.Split('|'), result.People!.Select(p => p.Name)); + } + [Theory] [InlineData("Jack Salvatore, Jr.", "Jack Salvatore, Jr.")] [InlineData("Efrem Zimbalist, Jr., Tom Hanks", "Efrem Zimbalist, Jr.|Tom Hanks")] -- cgit v1.2.3