diff options
| author | Stepan Goremykin <goremukin@gmail.com> | 2023-10-12 20:11:16 +0200 |
|---|---|---|
| committer | Stepan Goremykin <goremukin@gmail.com> | 2023-10-12 20:11:16 +0200 |
| commit | 8d7e4229ca694d8222cd7b97519b63a5c79f770b (patch) | |
| tree | 81def03b33fb5bb737467c2f92a289e17fb9a53d /MediaBrowser.XbmcMetadata | |
| parent | 96c3bde3463ad0457d894ed532093ed28e868ba8 (diff) | |
| parent | 075b828cbf42804439fd847b5ae3701061906fda (diff) | |
Merge branch 'master' into fix-resharper-warnings
# Conflicts:
# Emby.Server.Implementations/Net/SocketFactory.cs
# RSSDP/SsdpCommunicationsServer.cs
# RSSDP/SsdpDeviceLocator.cs
# RSSDP/SsdpDevicePublisher.cs
Diffstat (limited to 'MediaBrowser.XbmcMetadata')
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 859 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs | 175 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs | 29 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs | 29 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs | 21 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs | 4 |
6 files changed, 325 insertions, 792 deletions
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index af01b8be2..70e5b66c1 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -13,6 +13,7 @@ using MediaBrowser.Common.Providers; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -261,158 +262,84 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult<T> itemResult) { var item = itemResult.Item; - var nfoConfiguration = _config.GetNfoConfiguration(); - UserItemData? userData = null; + UserItemData? userData; switch (reader.Name) { - // DateCreated case "dateadded": + if (reader.TryReadDateTime(out var dateCreated)) { - var val = reader.ReadElementContentAsString(); - - if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var added)) - { - item.DateCreated = added; - } - else - { - Logger.LogWarning("Invalid Added value found: {Value}", val); - } - - break; + item.DateCreated = dateCreated; } + break; case "originaltitle": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrEmpty(val)) - { - item.OriginalTitle = val; - } - - break; - } - + item.OriginalTitle = reader.ReadNormalizedString(); + break; case "name": case "title": case "localtitle": - item.Name = reader.ReadElementContentAsString(); + item.Name = reader.ReadNormalizedString(); break; - case "sortname": - item.SortName = reader.ReadElementContentAsString(); + item.SortName = reader.ReadNormalizedString(); break; - case "criticrating": + var criticRatingText = reader.ReadElementContentAsString(); + if (float.TryParse(criticRatingText, CultureInfo.InvariantCulture, out var value)) { - var text = reader.ReadElementContentAsString(); - - if (float.TryParse(text, CultureInfo.InvariantCulture, out var value)) - { - item.CriticRating = value; - } - - break; + item.CriticRating = value; } + break; case "sorttitle": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.ForcedSortName = val; - } - - break; - } - + item.ForcedSortName = reader.ReadNormalizedString(); + break; case "biography": case "plot": case "review": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.Overview = val; - } - - break; - } - + item.Overview = reader.ReadNormalizedString(); + break; case "language": - { - var val = reader.ReadElementContentAsString(); - - item.PreferredMetadataLanguage = val; - - break; - } - + item.PreferredMetadataLanguage = reader.ReadNormalizedString(); + break; case "watched": + var played = reader.ReadElementContentAsBoolean(); + if (!string.IsNullOrWhiteSpace(nfoConfiguration.UserId)) { - var val = reader.ReadElementContentAsBoolean(); - - if (!string.IsNullOrWhiteSpace(nfoConfiguration.UserId)) - { - var user = _userManager.GetUserById(Guid.Parse(nfoConfiguration.UserId)); - userData = _userDataManager.GetUserData(user, item); - userData.Played = val; - _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); - } - - break; + var user = _userManager.GetUserById(Guid.Parse(nfoConfiguration.UserId)); + userData = _userDataManager.GetUserData(user, item); + userData.Played = played; + _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); } + break; case "playcount": + if (reader.TryReadInt(out var count) + && Guid.TryParse(nfoConfiguration.UserId, out var playCountUserId)) { - var val = reader.ReadElementContentAsString(); - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var count) - && Guid.TryParse(nfoConfiguration.UserId, out var guid)) - { - var user = _userManager.GetUserById(guid); - userData = _userDataManager.GetUserData(user, item); - userData.PlayCount = count; - _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); - } - - break; + var user = _userManager.GetUserById(playCountUserId); + userData = _userDataManager.GetUserData(user, item); + userData.PlayCount = count; + _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); } + break; case "lastplayed": + if (reader.TryReadDateTime(out var lastPlayed) + && Guid.TryParse(nfoConfiguration.UserId, out var lastPlayedUserId)) { - var val = reader.ReadElementContentAsString(); - if (Guid.TryParse(nfoConfiguration.UserId, out var guid)) - { - if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var added)) - { - var user = _userManager.GetUserById(guid); - userData = _userDataManager.GetUserData(user, item); - userData.LastPlayedDate = added; - _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); - } - else - { - Logger.LogWarning("Invalid lastplayed value found: {Value}", val); - } - } - - break; + var user = _userManager.GetUserById(lastPlayedUserId); + userData = _userDataManager.GetUserData(user, item); + userData.LastPlayedDate = lastPlayed; + _userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None); } + break; case "countrycode": - { - var val = reader.ReadElementContentAsString(); - - item.PreferredMetadataCountryCode = val; - - break; - } - + item.PreferredMetadataCountryCode = reader.ReadNormalizedString(); + break; case "lockedfields": { var val = reader.ReadElementContentAsString(); @@ -434,9 +361,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers } case "tagline": - item.Tagline = reader.ReadElementContentAsString(); + item.Tagline = reader.ReadNormalizedString(); break; - case "country": { var val = reader.ReadElementContentAsString(); @@ -453,94 +379,45 @@ namespace MediaBrowser.XbmcMetadata.Parsers } case "mpaa": - { - var rating = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(rating)) - { - item.OfficialRating = rating; - } - - break; - } - + item.OfficialRating = reader.ReadNormalizedString(); + break; case "customrating": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.CustomRating = val; - } - - break; - } - + item.CustomRating = reader.ReadNormalizedString(); + break; case "runtime": + var runtimeText = reader.ReadElementContentAsString(); + if (int.TryParse(runtimeText.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) { - var text = reader.ReadElementContentAsString(); - - if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) - { - item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; - } - - break; + item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } + break; case "aspectratio": + var aspectRatio = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(aspectRatio) && item is IHasAspectRatio hasAspectRatio) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val) - && item is IHasAspectRatio hasAspectRatio) - { - hasAspectRatio.AspectRatio = val; - } - - break; + hasAspectRatio.AspectRatio = aspectRatio; } + break; case "lockdata": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); - } - - break; - } - + item.IsLocked = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase); + break; case "studio": + var studio = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(studio)) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.AddStudio(val); - } - - break; + item.AddStudio(studio); } + break; case "director": + foreach (var director in reader.GetPersonArray(PersonKind.Director)) { - var val = reader.ReadElementContentAsString(); - foreach (var p in SplitNames(val).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonKind.Director })) - { - if (string.IsNullOrWhiteSpace(p.Name)) - { - continue; - } - - itemResult.AddPerson(p); - } - - break; + itemResult.AddPerson(director); } + break; case "credits": { var val = reader.ReadElementContentAsString(); @@ -565,141 +442,76 @@ namespace MediaBrowser.XbmcMetadata.Parsers } case "writer": + foreach (var writer in reader.GetPersonArray(PersonKind.Writer)) { - var val = reader.ReadElementContentAsString(); - foreach (var p in SplitNames(val).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonKind.Writer })) - { - if (string.IsNullOrWhiteSpace(p.Name)) - { - continue; - } - - itemResult.AddPerson(p); - } - - break; + itemResult.AddPerson(writer); } + break; case "actor": + var person = reader.GetPersonFromXmlNode(); + if (person is not null) { - if (!reader.IsEmptyElement) - { - using (var subtree = reader.ReadSubtree()) - { - var person = GetPersonFromXmlNode(subtree); - - if (!string.IsNullOrWhiteSpace(person.Name)) - { - itemResult.AddPerson(person); - } - } - } - else - { - reader.Read(); - } - - break; + itemResult.AddPerson(person); } + break; case "trailer": + var trailer = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(trailer)) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", BaseNfoSaver.YouTubeWatchUrl, StringComparison.OrdinalIgnoreCase); - - item.AddTrailerUrl(val); - } - - break; + item.AddTrailerUrl(trailer.Replace( + "plugin://plugin.video.youtube/?action=play_video&videoid=", + BaseNfoSaver.YouTubeWatchUrl, + StringComparison.OrdinalIgnoreCase)); } + break; case "displayorder": + var displayOrder = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(displayOrder) && item is IHasDisplayOrder hasDisplayOrder) { - var val = reader.ReadElementContentAsString(); - - if (item is IHasDisplayOrder hasDisplayOrder && !string.IsNullOrWhiteSpace(val)) - { - hasDisplayOrder.DisplayOrder = val; - } - - break; + hasDisplayOrder.DisplayOrder = displayOrder; } + break; case "year": + if (reader.TryReadInt(out var productionYear) && productionYear > 1850) { - var val = reader.ReadElementContentAsString(); - - if (int.TryParse(val, out var productionYear) && productionYear > 1850) - { - item.ProductionYear = productionYear; - } - - break; + item.ProductionYear = productionYear; } + break; case "rating": + var rating = reader.ReadElementContentAsString().Replace(',', '.'); + // All external meta is saving this as '.' for decimal I believe...but just to be sure + if (float.TryParse(rating, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var communityRating)) { - var rating = reader.ReadElementContentAsString(); - - // All external meta is saving this as '.' for decimal I believe...but just to be sure - if (float.TryParse(rating.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var val)) - { - item.CommunityRating = val; - } - - break; + item.CommunityRating = communityRating; } + break; case "ratings": - { - if (!reader.IsEmptyElement) - { - using var subtree = reader.ReadSubtree(); - FetchFromRatingsNode(subtree, item); - } - else - { - reader.Read(); - } - - break; - } - + FetchFromRatingsNode(reader, item); + break; case "aired": case "formed": case "premiered": case "releasedate": + if (reader.TryReadDateTimeExact(nfoConfiguration.ReleaseDateFormat, out var releaseDate)) { - var formatString = nfoConfiguration.ReleaseDateFormat; - - var val = reader.ReadElementContentAsString(); - - if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var date) && date.Year > 1850) - { - item.PremiereDate = date; - item.ProductionYear = date.Year; - } - - break; + item.PremiereDate = releaseDate; + item.ProductionYear = releaseDate.Year; } + break; case "enddate": + if (reader.TryReadDateTimeExact(nfoConfiguration.ReleaseDateFormat, out var endDate)) { - var formatString = nfoConfiguration.ReleaseDateFormat; - - var val = reader.ReadElementContentAsString(); - - if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var date) && date.Year > 1850) - { - item.EndDate = date; - } - - break; + item.EndDate = endDate; } + break; case "genre": { var val = reader.ReadElementContentAsString(); @@ -721,57 +533,34 @@ namespace MediaBrowser.XbmcMetadata.Parsers case "style": case "tag": + var tag = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(tag)) { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.AddTag(val); - } - - break; + item.AddTag(tag); } + break; case "fileinfo": - { - if (!reader.IsEmptyElement) - { - using (var subtree = reader.ReadSubtree()) - { - FetchFromFileInfoNode(subtree, item); - } - } - else - { - reader.Read(); - } - - break; - } - + FetchFromFileInfoNode(reader, item); + break; case "uniqueid": + if (reader.IsEmptyElement) { - if (reader.IsEmptyElement) - { - reader.Read(); - break; - } - - var provider = reader.GetAttribute("type"); - var id = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(provider) && !string.IsNullOrWhiteSpace(id)) - { - item.SetProviderId(provider, id); - } - + reader.Read(); break; } - case "thumb": + var provider = reader.GetAttribute("type"); + var providerId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(provider) && !string.IsNullOrWhiteSpace(providerId)) { - FetchThumbNode(reader, itemResult, "thumb"); - break; + item.SetProviderId(provider, providerId); } + break; + case "thumb": + FetchThumbNode(reader, itemResult, "thumb"); + break; case "fanart": { if (reader.IsEmptyElement) @@ -876,242 +665,188 @@ namespace MediaBrowser.XbmcMetadata.Parsers } } - private void FetchFromFileInfoNode(XmlReader reader, T item) + private void FetchFromFileInfoNode(XmlReader parentReader, T item) { + if (parentReader.IsEmptyElement) + { + parentReader.Read(); + return; + } + + using var reader = parentReader.ReadSubtree(); reader.MoveToContent(); reader.Read(); // Loop through each element while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - if (reader.NodeType == XmlNodeType.Element) + if (reader.NodeType != XmlNodeType.Element) { - switch (reader.Name) - { - case "streamdetails": - { - if (reader.IsEmptyElement) - { - reader.Read(); - continue; - } - - using (var subtree = reader.ReadSubtree()) - { - FetchFromStreamDetailsNode(subtree, item); - } - - break; - } - - default: - reader.Skip(); - break; - } + reader.Read(); + continue; } - else + + switch (reader.Name) { - reader.Read(); + case "streamdetails": + FetchFromStreamDetailsNode(reader, item); + break; + default: + reader.Skip(); + break; } } } - private void FetchFromStreamDetailsNode(XmlReader reader, T item) + private void FetchFromStreamDetailsNode(XmlReader parentReader, T item) { + if (parentReader.IsEmptyElement) + { + parentReader.Read(); + return; + } + + using var reader = parentReader.ReadSubtree(); reader.MoveToContent(); reader.Read(); // Loop through each element while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - if (reader.NodeType == XmlNodeType.Element) + if (reader.NodeType != XmlNodeType.Element) { - switch (reader.Name) - { - case "video": - { - if (reader.IsEmptyElement) - { - reader.Read(); - continue; - } - - using (var subtree = reader.ReadSubtree()) - { - FetchFromVideoNode(subtree, item); - } - - break; - } - - case "subtitle": - { - if (reader.IsEmptyElement) - { - reader.Read(); - continue; - } - - using (var subtree = reader.ReadSubtree()) - { - FetchFromSubtitleNode(subtree, item); - } - - break; - } - - default: - reader.Skip(); - break; - } + reader.Read(); + continue; } - else + + switch (reader.Name) { - reader.Read(); + case "video": + FetchFromVideoNode(reader, item); + break; + case "subtitle": + FetchFromSubtitleNode(reader, item); + break; + default: + reader.Skip(); + break; } } } - private void FetchFromVideoNode(XmlReader reader, T item) + private void FetchFromVideoNode(XmlReader parentReader, T item) { + if (parentReader.IsEmptyElement) + { + parentReader.Read(); + return; + } + + using var reader = parentReader.ReadSubtree(); reader.MoveToContent(); reader.Read(); // Loop through each element while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - if (reader.NodeType == XmlNodeType.Element) + if (reader.NodeType != XmlNodeType.Element || item is not Video video) { - switch (reader.Name) - { - case "format3d": - { - var val = reader.ReadElementContentAsString(); - - var video = item as Video; - - if (video is not null) - { - if (string.Equals("HSBS", val, StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfSideBySide; - } - else if (string.Equals("HTAB", val, StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfTopAndBottom; - } - else if (string.Equals("FTAB", val, StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.FullTopAndBottom; - } - else if (string.Equals("FSBS", val, StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.FullSideBySide; - } - else if (string.Equals("MVC", val, StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.MVC; - } - } - - break; - } - - case "aspect": - { - var val = reader.ReadElementContentAsString(); - - if (item is Video video) - { - video.AspectRatio = val; - } - - break; - } - - case "width": - { - var val = reader.ReadElementContentAsInt(); - - if (item is Video video) - { - video.Width = val; - } - - break; - } - - case "height": - { - var val = reader.ReadElementContentAsInt(); - - if (item is Video video) - { - video.Height = val; - } - - break; - } - - case "durationinseconds": - { - var val = reader.ReadElementContentAsInt(); - - if (item is Video video) - { - video.RunTimeTicks = new TimeSpan(0, 0, val).Ticks; - } - - break; - } - - default: - reader.Skip(); - break; - } + reader.Read(); + continue; } - else + + switch (reader.Name) { - reader.Read(); + case "format3d": + var format = reader.ReadElementContentAsString(); + if (string.Equals("HSBS", format, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.HalfSideBySide; + } + else if (string.Equals("HTAB", format, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.HalfTopAndBottom; + } + else if (string.Equals("FTAB", format, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.FullTopAndBottom; + } + else if (string.Equals("FSBS", format, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.FullSideBySide; + } + else if (string.Equals("MVC", format, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.MVC; + } + + break; + case "aspect": + video.AspectRatio = reader.ReadNormalizedString(); + break; + case "width": + video.Width = reader.ReadElementContentAsInt(); + break; + case "height": + video.Height = reader.ReadElementContentAsInt(); + break; + case "durationinseconds": + video.RunTimeTicks = new TimeSpan(0, 0, reader.ReadElementContentAsInt()).Ticks; + break; + default: + reader.Skip(); + break; } } } - private void FetchFromSubtitleNode(XmlReader reader, T item) + private void FetchFromSubtitleNode(XmlReader parentReader, T item) { + if (parentReader.IsEmptyElement) + { + parentReader.Read(); + return; + } + + using var reader = parentReader.ReadSubtree(); reader.MoveToContent(); reader.Read(); // Loop through each element while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - if (reader.NodeType == XmlNodeType.Element) + if (reader.NodeType != XmlNodeType.Element) { - switch (reader.Name) - { - case "language": - _ = reader.ReadElementContentAsString(); - if (item is Video video) - { - video.HasSubtitles = true; - } - - break; - - default: - reader.Skip(); - break; - } + reader.Read(); + continue; } - else + + switch (reader.Name) { - reader.Read(); + case "language": + _ = reader.ReadElementContentAsString(); + if (item is Video video) + { + video.HasSubtitles = true; + } + + break; + default: + reader.Skip(); + break; } } } - private void FetchFromRatingsNode(XmlReader reader, T item) + private void FetchFromRatingsNode(XmlReader parentReader, T item) { + if (parentReader.IsEmptyElement) + { + parentReader.Read(); + return; + } + + using var reader = parentReader.ReadSubtree(); reader.MoveToContent(); reader.Read(); @@ -1196,102 +931,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers } } - /// <summary> - /// Gets the persons from a XML node. - /// </summary> - /// <param name="reader">The <see cref="XmlReader"/>.</param> - /// <returns>IEnumerable{PersonInfo}.</returns> - private PersonInfo GetPersonFromXmlNode(XmlReader reader) - { - var name = string.Empty; - var type = PersonKind.Actor; // If type is not specified assume actor - var role = string.Empty; - int? sortOrder = null; - string? imageUrl = null; - - reader.MoveToContent(); - reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "name": - name = reader.ReadElementContentAsString(); - break; - - case "role": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - role = val; - } - - break; - } - - case "type": - { - var val = reader.ReadElementContentAsString(); - if (!Enum.TryParse(val, true, out type)) - { - type = PersonKind.Actor; - } - - break; - } - - case "order": - case "sortorder": - { - var val = reader.ReadElementContentAsString(); - - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) - { - sortOrder = intVal; - } - - break; - } - - case "thumb": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - imageUrl = val; - } - - break; - } - - default: - reader.Skip(); - break; - } - } - else - { - reader.Read(); - } - } - - return new PersonInfo - { - Name = name.Trim(), - Role = role, - Type = type, - SortOrder = sortOrder, - ImageUrl = imageUrl - }; - } - internal XmlReaderSettings GetXmlReaderSettings() => new XmlReaderSettings() { @@ -1302,24 +941,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers }; /// <summary> - /// Used to split names of comma or pipe delimited genres and people. - /// </summary> - /// <param name="value">The value.</param> - /// <returns>IEnumerable{System.String}.</returns> - private IEnumerable<string> SplitNames(string value) - { - // Only split by comma if there is no pipe in the string - // We have to be careful to not split names like Matthew, Jr. - var separator = !value.Contains('|', StringComparison.Ordinal) && !value.Contains(';', StringComparison.Ordinal) - ? new[] { ',' } - : new[] { '|', ';' }; - - value = value.Trim().Trim(separator); - - return string.IsNullOrWhiteSpace(value) ? Array.Empty<string>() : value.Split(separator, StringSplitOptions.RemoveEmptyEntries); - } - - /// <summary> /// Parses the <see cref="ImageType"/> from the NFO aspect property. /// </summary> /// <param name="aspect">The NFO aspect property.</param> diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index d2f349ad7..044efb51e 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -1,10 +1,11 @@ using System; -using System.Globalization; using System.IO; +using System.Text; using System.Threading; using System.Xml; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using Microsoft.Extensions.Logging; @@ -81,7 +82,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers } // Extract the last episode number from nfo + // Retrieves all title and plot tags from the rest of the nfo and concatenates them with the first episode // This is needed because XBMC metadata uses multiple episodedetails blocks instead of episodenumberend tag + var name = new StringBuilder(item.Item.Name); + var overview = new StringBuilder(item.Item.Overview); while ((index = xmlFile.IndexOf(srch, StringComparison.OrdinalIgnoreCase)) != -1) { xml = xmlFile.Substring(0, index + srch.Length); @@ -92,12 +96,44 @@ namespace MediaBrowser.XbmcMetadata.Parsers { reader.MoveToContent(); - if (reader.ReadToDescendant("episode") && int.TryParse(reader.ReadElementContentAsString(), out var num)) + while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - item.Item.IndexNumberEnd = Math.Max(num, item.Item.IndexNumberEnd ?? num); + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "name": + case "title": + case "localtitle": + name.Append(" / ").Append(reader.ReadElementContentAsString()); + break; + case "episode": + { + if (int.TryParse(reader.ReadElementContentAsString(), out var num)) + { + item.Item.IndexNumberEnd = Math.Max(num, item.Item.IndexNumberEnd ?? num); + } + + break; + } + + case "biography": + case "plot": + case "review": + overview.Append(" / ").Append(reader.ReadElementContentAsString()); + break; + } + } + + reader.Read(); } } } + + item.Item.Name = name.ToString(); + item.Item.Overview = overview.ToString(); } catch (XmlException) { @@ -112,142 +148,53 @@ namespace MediaBrowser.XbmcMetadata.Parsers switch (reader.Name) { case "season": + if (reader.TryReadInt(out var seasonNumber)) { - var number = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(number)) - { - if (int.TryParse(number, out var num)) - { - item.ParentIndexNumber = num; - } - } - - break; + item.ParentIndexNumber = seasonNumber; } + break; case "episode": + if (reader.TryReadInt(out var episodeNumber)) { - var number = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(number)) - { - if (int.TryParse(number, out var num)) - { - item.IndexNumber = num; - } - } - - break; + item.IndexNumber = episodeNumber; } + break; case "episodenumberend": + if (reader.TryReadInt(out var episodeNumberEnd)) { - var number = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(number)) - { - if (int.TryParse(number, out var num)) - { - item.IndexNumberEnd = num; - } - } - - break; + item.IndexNumberEnd = episodeNumberEnd; } + break; case "airsbefore_episode": + case "displayepisode": + if (reader.TryReadInt(out var airsBeforeEpisode)) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) - { - item.AirsBeforeEpisodeNumber = rval; - } - } - - break; + item.AirsBeforeEpisodeNumber = airsBeforeEpisode; } + break; case "airsafter_season": + case "displayafterseason": + if (reader.TryReadInt(out var airsAfterSeason)) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) - { - item.AirsAfterSeasonNumber = rval; - } - } - - break; + item.AirsAfterSeasonNumber = airsAfterSeason; } + break; case "airsbefore_season": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) - { - item.AirsBeforeSeasonNumber = rval; - } - } - - break; - } - case "displayseason": + if (reader.TryReadInt(out var airsBeforeSeason)) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) - { - item.AirsBeforeSeasonNumber = rval; - } - } - - break; - } - - case "displayepisode": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) - { - item.AirsBeforeEpisodeNumber = rval; - } - } - - break; + item.AirsBeforeSeasonNumber = airsBeforeSeason; } + break; case "showtitle": - { - var showtitle = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(showtitle)) - { - item.SeriesName = showtitle; - } - - break; - } - + item.SeriesName = reader.ReadNormalizedString(); + break; default: base.FetchDataFromXmlNode(reader, itemResult); break; diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index ecfed6873..16ea5e3ea 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -5,6 +5,7 @@ using System.Xml; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -113,31 +114,23 @@ namespace MediaBrowser.XbmcMetadata.Parsers } case "artist": + var artist = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(artist) && item is MusicVideo artistVideo) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val) && item is MusicVideo movie) - { - var list = movie.Artists.ToList(); - list.Add(val); - movie.Artists = list.ToArray(); - } - - break; + var list = artistVideo.Artists.ToList(); + list.Add(artist); + artistVideo.Artists = list.ToArray(); } + break; case "album": + var album = reader.ReadNormalizedString(); + if (!string.IsNullOrEmpty(album) && item is MusicVideo albumVideo) { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val) && item is MusicVideo movie) - { - movie.Album = val; - } - - break; + albumVideo.Album = album; } + break; default: base.FetchDataFromXmlNode(reader, itemResult); break; diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs index 51d5f932b..e13f0d997 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs @@ -1,7 +1,7 @@ -using System.Globalization; using System.Xml; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using Microsoft.Extensions.Logging; @@ -41,32 +41,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers switch (reader.Name) { case "seasonnumber": + if (reader.TryReadInt(out var seasonNumber)) { - var number = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(number)) - { - if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num)) - { - item.IndexNumber = num; - } - } - - break; + item.IndexNumber = seasonNumber; } + break; case "seasonname": - { - var name = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(name)) - { - item.Name = name; - } - - break; - } - + item.Name = reader.ReadNormalizedString(); + break; default: base.FetchDataFromXmlNode(reader, itemResult); break; diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index f4b4eccf8..dbcfe7997 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Xml; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -75,23 +76,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers } case "airs_dayofweek": - { - item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString()); - break; - } - + item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString()); + break; case "airs_time": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - item.AirTime = val; - } - - break; - } - + item.AirTime = reader.ReadNormalizedString(); + break; case "status": { var status = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index 82e1dc860..8fa22fad9 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -60,13 +60,13 @@ namespace MediaBrowser.XbmcMetadata.Savers } else { - yield return Path.ChangeExtension(item.Path, ".nfo"); - // only allow movie object to read movie.nfo, not owned videos (which will be itemtype video, not movie) if (!item.IsInMixedFolder && item.ItemType == typeof(Movie)) { yield return Path.Combine(item.ContainingFolderPath, "movie.nfo"); } + + yield return Path.ChangeExtension(item.Path, ".nfo"); } } |
