mirror of https://github.com/jellyfin/jellyfin.git
Sort embedded collections in Nfo files
Because the Nfo files emit the collections as they are in-memory, the files are not stable in format, genres, tags, albums, people, etc. are emitted in random orders. Add ordering of the collections when emitting the Nfo files so the file remains stable (unchanged) when underlying media information doesn't change. In the process of this, it became clear that most of the providers and probes don't trim the strings like people's names, genre names, etc. so did a pass of Trim cleanup too. Specific ordering: (alphabetical/numeric ascending after trimming blanks and defaulting to zero for missing numbers) BaseItem: Directors, Writers, Trailers (by Url), Production Locations, Genres, Studios, Tags, Custom Provider Data (by key), Linked Children (by Path>LibraryItemId), Backdrop Images (by path), Actors (by SortOrder>Name) AlbumNfo: Artists, Album Artists, Tracks (by ParentIndexNumber>IndexNumber>Name) ArtistNfo: Albums (by Production Year>SortName>Name) MovieNfo: Artists Fix Debug build lint Fix CI debug build lint issue. Fix review issues Fixed debug-build lint issues. Emits the `disc` number to NFO for tracks with a non-zero ParentIndexNumber and only emit `position` if non-zero. Removed the exception filtering I put in for testing. Don't emit actors for MusicAlbums or MusicArtists Swap from String.Trimmed() to ?.Trim() Addressing PR feedback Can't use ReadOnlySpan in an async method Removed now-unused namespace
This commit is contained in:
parent
e5dcaa6ed5
commit
21d8e5438e
|
@ -22,6 +22,7 @@ using MediaBrowser.Controller.Entities.Audio;
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
@ -909,7 +910,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));
|
||||
|
@ -1746,7 +1747,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public void AddStudio(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
|
||||
name = name.Trim();
|
||||
var current = Studios;
|
||||
|
||||
if (!current.Contains(name, StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -1768,7 +1769,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public void SetStudios(IEnumerable<string> names)
|
||||
{
|
||||
Studios = names.Distinct().ToArray();
|
||||
Studios = names.Trimmed().Distinct().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1779,6 +1780,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public void AddGenre(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
name = name.Trim();
|
||||
|
||||
var genres = Genres;
|
||||
if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase))
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -30,5 +30,10 @@ namespace MediaBrowser.Controller.Sorting
|
|||
{
|
||||
return list.ThenByDescending(getName, _comparer);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Trimmed(this IEnumerable<string> values)
|
||||
{
|
||||
return values.Select(i => (i ?? string.Empty).Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,7 +361,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
continue;
|
||||
}
|
||||
|
||||
item.AddStudio(name);
|
||||
item.AddStudio(name.Trim());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -446,7 +446,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
item.AddTrailerUrl(val);
|
||||
item.AddTrailerUrl(val.Trim());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -460,7 +460,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
{
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
hasDisplayOrder.DisplayOrder = val;
|
||||
hasDisplayOrder.DisplayOrder = val.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,7 +811,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
item.Tagline = val;
|
||||
item.Tagline = val.Trim();
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -890,7 +890,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
{
|
||||
tags.Add(tag);
|
||||
tags.Add(tag.Trim());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -982,7 +982,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
item.AddTrailerUrl(val);
|
||||
item.AddTrailerUrl(val.Trim());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1113,7 +1113,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
}
|
||||
}
|
||||
|
||||
var personInfo = new PersonInfo { Name = name.Trim(), Role = role, Type = type, SortOrder = sortOrder };
|
||||
var personInfo = new PersonInfo { Name = name.Trim(), Role = role.Trim(), Type = type, SortOrder = sortOrder };
|
||||
|
||||
return new[] { personInfo };
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using System.Xml;
|
|||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
@ -518,42 +519,44 @@ namespace MediaBrowser.MediaEncoding.Probing
|
|||
private void ProcessPairs(string key, List<NameValuePair> pairs, MediaInfo info)
|
||||
{
|
||||
IList<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
|
||||
});
|
||||
}
|
||||
|
@ -603,7 +606,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
|||
return new NameValuePair
|
||||
{
|
||||
Name = name,
|
||||
Value = value
|
||||
Value = value?.Trim()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1437,7 +1440,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
|||
continue;
|
||||
}
|
||||
|
||||
genres.Add(genre);
|
||||
genres.Add(genre.Trim());
|
||||
}
|
||||
|
||||
info.Genres = genres
|
||||
|
|
|
@ -13,6 +13,7 @@ using MediaBrowser.Controller.Library;
|
|||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
@ -227,7 +228,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = albumArtist,
|
||||
Name = albumArtist.Trim(),
|
||||
Type = PersonKind.AlbumArtist
|
||||
});
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = performer,
|
||||
Name = performer.Trim(),
|
||||
Type = PersonKind.Artist
|
||||
});
|
||||
}
|
||||
|
@ -252,7 +253,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
PeopleHelper.AddPerson(people, new PersonInfo
|
||||
{
|
||||
Name = composer,
|
||||
Name = composer.Trim(),
|
||||
Type = PersonKind.Composer
|
||||
});
|
||||
}
|
||||
|
@ -263,8 +264,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
audio.AlbumArtists = albumArtists;
|
||||
}
|
||||
|
||||
audio.Name = tags.Title;
|
||||
audio.Album = tags.Album;
|
||||
audio.Name = tags.Title.Trim();
|
||||
audio.Album = tags.Album.Trim();
|
||||
audio.IndexNumber = Convert.ToInt32(tags.Track);
|
||||
audio.ParentIndexNumber = Convert.ToInt32(tags.Disc);
|
||||
|
||||
|
@ -277,7 +278,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
|
||||
if (!audio.LockedFields.Contains(MetadataField.Genres))
|
||||
{
|
||||
audio.Genres = tags.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
audio.Genres = tags.Genres.Trimmed().Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
}
|
||||
|
||||
audio.SetProviderId(MetadataProvider.MusicBrainzArtist, tags.MusicBrainzArtistId);
|
||||
|
|
|
@ -539,9 +539,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
|
||||
});
|
||||
}
|
||||
|
|
|
@ -424,7 +424,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Director,
|
||||
Name = result.Director.Trim(),
|
||||
Type = PersonKind.Director
|
||||
};
|
||||
|
||||
|
@ -435,7 +435,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Writer,
|
||||
Name = result.Writer.Trim(),
|
||||
Type = PersonKind.Writer
|
||||
};
|
||||
|
||||
|
@ -454,7 +454,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = actor,
|
||||
Name = actor.Trim(),
|
||||
Type = PersonKind.Actor
|
||||
};
|
||||
|
||||
|
|
|
@ -258,7 +258,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
|
||||
};
|
||||
|
@ -293,7 +293,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
|||
var personInfo = new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
};
|
||||
|
||||
|
|
|
@ -168,7 +168,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
|
||||
});
|
||||
|
@ -182,7 +182,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
|
||||
});
|
||||
|
@ -206,7 +206,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||
metadataResult.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||
result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = cast[i].Name.Trim(),
|
||||
Role = cast[i].Character,
|
||||
Role = cast[i].Character.Trim(),
|
||||
Type = PersonKind.Actor,
|
||||
SortOrder = cast[i].Order
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||
result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
|
|
@ -352,7 +352,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)
|
||||
|
@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||
yield return new PersonInfo
|
||||
{
|
||||
Name = person.Name.Trim(),
|
||||
Role = person.Job,
|
||||
Role = person.Job?.Trim(),
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1285,7 +1285,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|||
return new PersonInfo
|
||||
{
|
||||
Name = name.Trim(),
|
||||
Role = role,
|
||||
Role = role.Trim(),
|
||||
Type = type,
|
||||
SortOrder = sortOrder,
|
||||
ImageUrl = imageUrl
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Controller.Configuration;
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
@ -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,19 @@ 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 => 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,11 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.XbmcMetadata.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -69,7 +71,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
|||
|
||||
private void AddAlbums(IList<BaseItem> albums, XmlWriter writer)
|
||||
{
|
||||
foreach (var album in albums)
|
||||
foreach (var album in albums
|
||||
.OrderBy(album => album.ProductionYear ?? 0)
|
||||
.ThenBy(album => album.SortName?.Trim())
|
||||
.ThenBy(album => album.Name?.Trim()))
|
||||
{
|
||||
writer.WriteStartElement("album");
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ using MediaBrowser.Controller.Entities.Audio;
|
|||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
@ -488,7 +489,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 +501,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 +516,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 +664,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 +756,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 +768,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 +789,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 +804,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 +848,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));
|
||||
}
|
||||
|
@ -913,7 +922,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
|||
|
||||
private void AddActors(List<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))
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Controller.Entities.Movies;
|
|||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -103,7 +104,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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue