mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge pull request #9560 from IDisposable/sort-nfo-data
Sort embedded collections in Nfo files
This commit is contained in:
commit
f87150bb3d
@ -919,7 +919,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
// Remove from middle if surrounded by spaces
|
||||
sortable = sortable.Replace(" " + search + " ", " ", StringComparison.Ordinal);
|
||||
|
||||
// Remove from end if followed by a space
|
||||
// Remove from end if preceeded by a space
|
||||
if (sortable.EndsWith(" " + search, StringComparison.Ordinal))
|
||||
{
|
||||
sortable = sortable.Remove(sortable.Length - (search.Length + 1));
|
||||
@ -1775,7 +1775,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
public void AddStudio(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
|
||||
var current = Studios;
|
||||
|
||||
if (!current.Contains(name, StringComparison.OrdinalIgnoreCase))
|
||||
@ -1794,7 +1793,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public void SetStudios(IEnumerable<string> names)
|
||||
{
|
||||
Studios = names.Distinct().ToArray();
|
||||
Studios = names.Trimmed().Distinct().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -15,6 +15,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
ArgumentNullException.ThrowIfNull(person);
|
||||
ArgumentException.ThrowIfNullOrEmpty(person.Name);
|
||||
|
||||
person.Name = person.Name.Trim();
|
||||
|
||||
// Normalize
|
||||
if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -234,8 +234,8 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
item.CustomRating = reader.ReadNormalizedString();
|
||||
break;
|
||||
case "RunningTime":
|
||||
var runtimeText = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrWhiteSpace(runtimeText))
|
||||
var runtimeText = reader.ReadNormalizedString();
|
||||
if (!string.IsNullOrEmpty(runtimeText))
|
||||
{
|
||||
if (int.TryParse(runtimeText.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime))
|
||||
{
|
||||
@ -253,7 +253,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
|
||||
break;
|
||||
case "LockData":
|
||||
item.IsLocked = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase);
|
||||
item.IsLocked = string.Equals(reader.ReadNormalizedString(), "true", StringComparison.OrdinalIgnoreCase);
|
||||
break;
|
||||
case "Network":
|
||||
foreach (var name in reader.GetStringArray())
|
||||
@ -331,9 +331,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
case "Rating":
|
||||
case "IMDBrating":
|
||||
{
|
||||
var rating = reader.ReadElementContentAsString();
|
||||
var rating = reader.ReadNormalizedString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(rating))
|
||||
if (!string.IsNullOrEmpty(rating))
|
||||
{
|
||||
// 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))
|
||||
@ -449,7 +449,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
|
||||
case "OwnerUserId":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
var val = reader.ReadNormalizedString();
|
||||
|
||||
if (Guid.TryParse(val, out var guid) && !guid.Equals(Guid.Empty))
|
||||
{
|
||||
@ -464,7 +464,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
|
||||
case "Format3D":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
var val = reader.ReadNormalizedString();
|
||||
|
||||
if (item is Video video)
|
||||
{
|
||||
@ -498,7 +498,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
string readerName = reader.Name;
|
||||
if (_validProviderIds!.TryGetValue(readerName, out string? providerIdValue))
|
||||
{
|
||||
var id = reader.ReadElementContentAsString();
|
||||
var id = reader.ReadNormalizedString();
|
||||
item.TrySetProviderId(providerIdValue, id);
|
||||
}
|
||||
else
|
||||
@ -580,7 +580,12 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Tagline":
|
||||
item.Tagline = reader.ReadNormalizedString();
|
||||
var val = reader.ReadNormalizedString();
|
||||
if (!string.IsNullOrEmpty(val))
|
||||
{
|
||||
item.Tagline = val;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
@ -842,7 +847,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
userId = reader.ReadNormalizedString();
|
||||
break;
|
||||
case "CanEdit":
|
||||
canEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase);
|
||||
canEdit = string.Equals(reader.ReadNormalizedString(), "true", StringComparison.OrdinalIgnoreCase);
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
@ -856,7 +861,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
}
|
||||
|
||||
// This is valid
|
||||
if (!string.IsNullOrWhiteSpace(userId) && Guid.TryParse(userId, out var guid))
|
||||
if (!string.IsNullOrEmpty(userId) && Guid.TryParse(userId, out var guid))
|
||||
{
|
||||
return new PlaylistUserPermissions(guid, canEdit);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
@ -531,42 +532,44 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
private void ProcessPairs(string key, List<NameValuePair> pairs, MediaInfo info)
|
||||
{
|
||||
List<BaseItemPerson> peoples = new List<BaseItemPerson>();
|
||||
var distinctPairs = pairs.Select(p => p.Value)
|
||||
.Where(i => !string.IsNullOrWhiteSpace(i))
|
||||
.Trimmed()
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (string.Equals(key, "studio", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
info.Studios = pairs.Select(p => p.Value)
|
||||
.Where(i => !string.IsNullOrWhiteSpace(i))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
info.Studios = distinctPairs.ToArray();
|
||||
}
|
||||
else if (string.Equals(key, "screenwriters", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (var pair in pairs)
|
||||
foreach (var pair in distinctPairs)
|
||||
{
|
||||
peoples.Add(new BaseItemPerson
|
||||
{
|
||||
Name = pair.Value,
|
||||
Name = pair,
|
||||
Type = PersonKind.Writer
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (string.Equals(key, "producers", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (var pair in pairs)
|
||||
foreach (var pair in distinctPairs)
|
||||
{
|
||||
peoples.Add(new BaseItemPerson
|
||||
{
|
||||
Name = pair.Value,
|
||||
Name = pair,
|
||||
Type = PersonKind.Producer
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (string.Equals(key, "directors", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (var pair in pairs)
|
||||
foreach (var pair in distinctPairs)
|
||||
{
|
||||
peoples.Add(new BaseItemPerson
|
||||
{
|
||||
Name = pair.Value,
|
||||
Name = pair,
|
||||
Type = PersonKind.Director
|
||||
});
|
||||
}
|
||||
@ -591,10 +594,10 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "key":
|
||||
name = reader.ReadElementContentAsString();
|
||||
name = reader.ReadNormalizedString();
|
||||
break;
|
||||
case "string":
|
||||
value = reader.ReadElementContentAsString();
|
||||
value = reader.ReadNormalizedString();
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
@ -607,8 +610,8 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name)
|
||||
|| string.IsNullOrWhiteSpace(value))
|
||||
if (string.IsNullOrEmpty(name)
|
||||
|| string.IsNullOrEmpty(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -1453,7 +1456,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
var genres = new List<string>(info.Genres);
|
||||
foreach (var genre in Split(genreVal, true))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(genre))
|
||||
if (string.IsNullOrEmpty(genre))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ATL;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
@ -179,8 +180,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
// That setter is meant for its own tag parser and external editor usage and will have unwanted side effects
|
||||
// For example, setting the Year property will also set the Date property, which is not what we want here.
|
||||
// To properly handle fallback values, we make a clone of those fields when valid.
|
||||
var trackTitle = string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title;
|
||||
var trackAlbum = string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album;
|
||||
var trackTitle = (string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title).Trim();
|
||||
var trackAlbum = (string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album).Trim();
|
||||
var trackYear = track.Year is null or 0 ? mediaInfo.ProductionYear : track.Year;
|
||||
var trackTrackNumber = track.TrackNumber is null or 0 ? mediaInfo.IndexNumber : track.TrackNumber;
|
||||
var trackDiscNumber = track.DiscNumber is null or 0 ? mediaInfo.ParentIndexNumber : track.DiscNumber;
|
||||
@ -197,11 +198,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
foreach (var albumArtist in albumArtists)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(albumArtist))
|
||||
if (!string.IsNullOrWhiteSpace(albumArtist))
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = albumArtist,
|
||||
Name = albumArtist.Trim(),
|
||||
Type = PersonKind.AlbumArtist
|
||||
});
|
||||
}
|
||||
@ -229,11 +230,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
foreach (var performer in performers)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(performer))
|
||||
if (!string.IsNullOrWhiteSpace(performer))
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = performer,
|
||||
Name = performer.Trim(),
|
||||
Type = PersonKind.Artist
|
||||
});
|
||||
}
|
||||
@ -241,11 +242,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
foreach (var composer in track.Composer.Split(InternalValueSeparator))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(composer))
|
||||
if (!string.IsNullOrWhiteSpace(composer))
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = composer,
|
||||
Name = composer.Trim(),
|
||||
Type = PersonKind.Composer
|
||||
});
|
||||
}
|
||||
@ -331,6 +332,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
genres = genres.SelectMany(g => SplitWithCustomDelimiter(g, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist)).ToArray();
|
||||
}
|
||||
|
||||
genres = genres.Trimmed().Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
|
||||
audio.Genres = options.ReplaceAllMetadata || audio.Genres is null || audio.Genres.Length == 0
|
||||
? genres
|
||||
: audio.Genres;
|
||||
|
@ -6,6 +6,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Chapters;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
@ -407,7 +408,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
video.Genres = Array.Empty<string>();
|
||||
|
||||
foreach (var genre in data.Genres)
|
||||
foreach (var genre in data.Genres.Trimmed())
|
||||
{
|
||||
video.AddGenre(genre);
|
||||
}
|
||||
@ -516,9 +517,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = person.Name,
|
||||
Name = person.Name.Trim(),
|
||||
Type = person.Type,
|
||||
Role = person.Role
|
||||
Role = person.Role.Trim()
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = albumArtist,
|
||||
Name = albumArtist.Trim(),
|
||||
Type = PersonKind.AlbumArtist
|
||||
});
|
||||
}
|
||||
@ -196,7 +196,7 @@ namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = artist,
|
||||
Name = artist.Trim(),
|
||||
Type = PersonKind.Artist
|
||||
});
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Director,
|
||||
Name = result.Director.Trim(),
|
||||
Type = PersonKind.Director
|
||||
};
|
||||
|
||||
@ -432,7 +432,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Writer,
|
||||
Name = result.Writer.Trim(),
|
||||
Type = PersonKind.Writer
|
||||
};
|
||||
|
||||
|
@ -234,7 +234,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
|
||||
var genres = movieResult.Genres;
|
||||
|
||||
foreach (var genre in genres.Select(g => g.Name))
|
||||
foreach (var genre in genres.Select(g => g.Name).Trimmed())
|
||||
{
|
||||
movie.AddGenre(genre);
|
||||
}
|
||||
@ -254,7 +254,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
Name = actor.Name.Trim(),
|
||||
Role = actor.Character,
|
||||
Role = actor.Character.Trim(),
|
||||
Type = PersonKind.Actor,
|
||||
SortOrder = actor.Order
|
||||
};
|
||||
@ -289,7 +289,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
};
|
||||
|
||||
|
@ -211,7 +211,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
metadataResult.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = actor.Name.Trim(),
|
||||
Role = actor.Character,
|
||||
Role = actor.Character.Trim(),
|
||||
Type = PersonKind.Actor,
|
||||
SortOrder = actor.Order
|
||||
});
|
||||
@ -225,7 +225,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
metadataResult.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = guest.Name.Trim(),
|
||||
Role = guest.Character,
|
||||
Role = guest.Character.Trim(),
|
||||
Type = PersonKind.GuestStar,
|
||||
SortOrder = guest.Order
|
||||
});
|
||||
@ -249,7 +249,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
metadataResult.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
@ -82,12 +82,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
var cast = credits.Cast.OrderBy(c => c.Order).Take(Plugin.Instance.Configuration.MaxCastMembers).ToList();
|
||||
for (var i = 0; i < cast.Count; i++)
|
||||
{
|
||||
var member = cast[i];
|
||||
result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = cast[i].Name.Trim(),
|
||||
Role = cast[i].Character,
|
||||
Name = member.Name.Trim(),
|
||||
Role = member.Character.Trim(),
|
||||
Type = PersonKind.Actor,
|
||||
SortOrder = cast[i].Order
|
||||
SortOrder = member.Order
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -108,7 +109,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
Name = actor.Name.Trim(),
|
||||
Role = actor.Character,
|
||||
Role = actor.Character.Trim(),
|
||||
Type = PersonKind.Actor,
|
||||
SortOrder = actor.Order,
|
||||
ImageUrl = _tmdbClientManager.GetPosterUrl(actor.ProfilePath)
|
||||
@ -368,7 +368,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
yield return new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
@ -55,12 +56,12 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
{
|
||||
var album = (MusicAlbum)item;
|
||||
|
||||
foreach (var artist in album.Artists)
|
||||
foreach (var artist in album.Artists.Trimmed().OrderBy(artist => artist))
|
||||
{
|
||||
writer.WriteElementString("artist", artist);
|
||||
}
|
||||
|
||||
foreach (var artist in album.AlbumArtists)
|
||||
foreach (var artist in album.AlbumArtists.Trimmed().OrderBy(artist => artist))
|
||||
{
|
||||
writer.WriteElementString("albumartist", artist);
|
||||
}
|
||||
@ -70,11 +71,20 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
private void AddTracks(IEnumerable<BaseItem> tracks, XmlWriter writer)
|
||||
{
|
||||
foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0))
|
||||
foreach (var track in tracks
|
||||
.OrderBy(i => i.ParentIndexNumber ?? 0)
|
||||
.ThenBy(i => i.IndexNumber ?? 0)
|
||||
.ThenBy(i => SortNameOrName(i))
|
||||
.ThenBy(i => i.Name?.Trim()))
|
||||
{
|
||||
writer.WriteStartElement("track");
|
||||
|
||||
if (track.IndexNumber.HasValue)
|
||||
if (track.ParentIndexNumber.HasValue && track.ParentIndexNumber.Value != 0)
|
||||
{
|
||||
writer.WriteElementString("disc", track.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (track.IndexNumber.HasValue && track.IndexNumber.Value != 0)
|
||||
{
|
||||
writer.WriteElementString("position", track.IndexNumber.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
@ -69,7 +70,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
private void AddAlbums(IReadOnlyList<BaseItem> albums, XmlWriter writer)
|
||||
{
|
||||
foreach (var album in albums)
|
||||
foreach (var album in albums
|
||||
.OrderBy(album => album.ProductionYear ?? 0)
|
||||
.ThenBy(album => SortNameOrName(album))
|
||||
.ThenBy(album => album.Name?.Trim()))
|
||||
{
|
||||
writer.WriteStartElement("album");
|
||||
|
||||
|
@ -488,7 +488,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
var directors = people
|
||||
.Where(i => i.IsType(PersonKind.Director))
|
||||
.Select(i => i.Name)
|
||||
.Select(i => i.Name?.Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(i => i)
|
||||
.ToList();
|
||||
|
||||
foreach (var person in directors)
|
||||
@ -498,8 +500,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
var writers = people
|
||||
.Where(i => i.IsType(PersonKind.Writer))
|
||||
.Select(i => i.Name)
|
||||
.Select(i => i.Name?.Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(i => i)
|
||||
.ToList();
|
||||
|
||||
foreach (var person in writers)
|
||||
@ -512,7 +515,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteElementString("credits", person);
|
||||
}
|
||||
|
||||
foreach (var trailer in item.RemoteTrailers)
|
||||
foreach (var trailer in item.RemoteTrailers.OrderBy(t => t.Url?.Trim()))
|
||||
{
|
||||
writer.WriteElementString("trailer", GetOutputTrailerUrl(trailer.Url));
|
||||
}
|
||||
@ -660,22 +663,22 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteElementString("tagline", item.Tagline);
|
||||
}
|
||||
|
||||
foreach (var country in item.ProductionLocations)
|
||||
foreach (var country in item.ProductionLocations.Trimmed().OrderBy(country => country))
|
||||
{
|
||||
writer.WriteElementString("country", country);
|
||||
}
|
||||
|
||||
foreach (var genre in item.Genres)
|
||||
foreach (var genre in item.Genres.Trimmed().OrderBy(genre => genre))
|
||||
{
|
||||
writer.WriteElementString("genre", genre);
|
||||
}
|
||||
|
||||
foreach (var studio in item.Studios)
|
||||
foreach (var studio in item.Studios.Trimmed().OrderBy(studio => studio))
|
||||
{
|
||||
writer.WriteElementString("studio", studio);
|
||||
}
|
||||
|
||||
foreach (var tag in item.Tags)
|
||||
foreach (var tag in item.Tags.Trimmed().OrderBy(tag => tag))
|
||||
{
|
||||
if (item is MusicAlbum || item is MusicArtist)
|
||||
{
|
||||
@ -752,7 +755,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
if (item.ProviderIds is not null)
|
||||
{
|
||||
foreach (var providerKey in item.ProviderIds.Keys)
|
||||
foreach (var providerKey in item.ProviderIds.Keys.OrderBy(providerKey => providerKey))
|
||||
{
|
||||
var providerId = item.ProviderIds[providerKey];
|
||||
if (!string.IsNullOrEmpty(providerId) && !writtenProviderIds.Contains(providerKey))
|
||||
@ -764,7 +767,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
XmlConvert.VerifyName(tagName);
|
||||
Logger.LogDebug("Saving custom provider tagname {0}", tagName);
|
||||
|
||||
writer.WriteElementString(GetTagForProviderKey(providerKey), providerId);
|
||||
writer.WriteElementString(tagName, providerId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
@ -785,7 +788,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
AddUserData(item, writer, userManager, userDataRepo, options);
|
||||
|
||||
AddActors(people, writer, libraryManager, options.SaveImagePathsInNfo);
|
||||
if (item is not MusicAlbum && item is not MusicArtist)
|
||||
{
|
||||
AddActors(people, writer, libraryManager, options.SaveImagePathsInNfo);
|
||||
}
|
||||
|
||||
if (item is BoxSet folder)
|
||||
{
|
||||
@ -797,6 +803,8 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
{
|
||||
var items = item.LinkedChildren
|
||||
.Where(i => i.Type == LinkedChildType.Manual)
|
||||
.OrderBy(i => i.Path?.Trim())
|
||||
.ThenBy(i => i.LibraryItemId?.Trim())
|
||||
.ToList();
|
||||
|
||||
foreach (var link in items)
|
||||
@ -839,7 +847,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteElementString("poster", GetImagePathToSave(image, libraryManager));
|
||||
}
|
||||
|
||||
foreach (var backdrop in item.GetImages(ImageType.Backdrop))
|
||||
foreach (var backdrop in item.GetImages(ImageType.Backdrop).OrderBy(b => b.Path?.Trim()))
|
||||
{
|
||||
writer.WriteElementString("fanart", GetImagePathToSave(backdrop, libraryManager));
|
||||
}
|
||||
@ -916,7 +924,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
private void AddActors(IReadOnlyList<PersonInfo> people, XmlWriter writer, ILibraryManager libraryManager, bool saveImagePath)
|
||||
{
|
||||
foreach (var person in people)
|
||||
foreach (var person in people
|
||||
.OrderBy(person => person.SortOrder ?? 0)
|
||||
.ThenBy(person => person.Name?.Trim()))
|
||||
{
|
||||
if (person.IsType(PersonKind.Director) || person.IsType(PersonKind.Writer))
|
||||
{
|
||||
@ -1027,5 +1037,24 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
private string GetTagForProviderKey(string providerKey)
|
||||
=> providerKey.ToLowerInvariant() + "id";
|
||||
|
||||
protected static string SortNameOrName(BaseItem item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (item.SortName != null)
|
||||
{
|
||||
string trimmed = item.SortName.Trim();
|
||||
if (trimmed.Length > 0)
|
||||
{
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
return (item.Name ?? string.Empty).Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
@ -100,7 +101,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
if (item is MusicVideo musicVideo)
|
||||
{
|
||||
foreach (var artist in musicVideo.Artists)
|
||||
foreach (var artist in musicVideo.Artists.Trimmed().OrderBy(artist => artist))
|
||||
{
|
||||
writer.WriteElementString("artist", artist);
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICU4N.Text;
|
||||
|
||||
@ -123,5 +125,15 @@ namespace Jellyfin.Extensions
|
||||
{
|
||||
return (_transliterator.Value is null) ? text : _transliterator.Value.Transliterate(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures all strings are non-null and trimmed of leading an trailing blanks.
|
||||
/// </summary>
|
||||
/// <param name="values">The enumerable of strings to trim.</param>
|
||||
/// <returns>The enumeration of trimmed strings.</returns>
|
||||
public static IEnumerable<string> Trimmed(this IEnumerable<string> values)
|
||||
{
|
||||
return values.Select(i => (i ?? string.Empty).Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user