diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index f0c50d8e51..eb93148c6a 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -43,19 +43,23 @@ namespace MediaBrowser.XbmcMetadata.Parsers { item.ResetPeople(); - var xml = streamReader.ReadToEnd(); + var xmlFile = streamReader.ReadToEnd(); var srch = ""; - var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + var index = xmlFile.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + + var xml = xmlFile; if (index != -1) { - xml = xml.Substring(0, index + srch.Length); + xml = xmlFile.Substring(0, index + srch.Length); + xmlFile = xmlFile.Substring(index + srch.Length); } // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions try { + // Extract episode details from the first episodedetails block using (var stringReader = new StringReader(xml)) using (var reader = XmlReader.Create(stringReader, settings)) { @@ -77,6 +81,25 @@ namespace MediaBrowser.XbmcMetadata.Parsers } } } + + // Extract the last episode number from nfo + // This is needed because XBMC metadata uses multiple episodedetails blocks instead of episodenumberend tag + while ((index = xmlFile.IndexOf(srch, StringComparison.OrdinalIgnoreCase)) != -1) + { + xml = xmlFile.Substring(0, index + srch.Length); + xmlFile = xmlFile.Substring(index + srch.Length); + + using (var stringReader = new StringReader(xml)) + using (var reader = XmlReader.Create(stringReader, settings)) + { + reader.MoveToContent(); + + if (reader.ReadToDescendant("episode") && int.TryParse(reader.ReadElementContentAsString(), out var num)) + { + item.Item.IndexNumberEnd = Math.Max(num, item.Item.IndexNumberEnd ?? num); + } + } + } } catch (XmlException) { diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs index d10ef9b478..053e0a89ea 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs @@ -42,7 +42,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers } [Fact] - public void Fetch_Valid_Succes() + public void Fetch_Valid_Success() { var result = new MetadataResult() { @@ -97,6 +97,26 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers Assert.Equal(new DateTime(2017, 10, 7, 14, 25, 47), item.DateCreated); } + [Fact] + public void Fetch_Valid_MultiEpisode_Success() + { + var result = new MetadataResult() + { + Item = new Episode() + }; + + _parser.Fetch(result, "Test Data/Rising.nfo", CancellationToken.None); + + var item = result.Item; + Assert.Equal("Rising (1)", item.Name); + Assert.Equal(1, item.IndexNumber); + Assert.Equal(2, item.IndexNumberEnd); + Assert.Equal(1, item.ParentIndexNumber); + Assert.Equal("A new Stargate team embarks on a dangerous mission to a distant galaxy, where they discover a mythical lost city -- and a deadly new enemy.", item.Overview); + Assert.Equal(new DateTime(2004, 7, 16), item.PremiereDate); + Assert.Equal(2004, item.ProductionYear); + } + [Fact] public void Fetch_WithNullItem_ThrowsArgumentException() { diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 76231391e2..ff4795569c 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -57,7 +57,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers } [Fact] - public void Fetch_Valid_Succes() + public void Fetch_Valid_Success() { var result = new MetadataResult