mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-09-29 15:31:04 -04:00
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
101 lines
3.6 KiB
C#
101 lines
3.6 KiB
C#
#pragma warning disable CS1591
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Jellyfin.Data.Enums;
|
|
using MediaBrowser.Model.Entities;
|
|
|
|
namespace MediaBrowser.Controller.Entities
|
|
{
|
|
public static class PeopleHelper
|
|
{
|
|
public static void AddPerson(List<PersonInfo> people, PersonInfo person)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(person);
|
|
ArgumentException.ThrowIfNullOrEmpty(person.Name);
|
|
|
|
person.Name = person.Name.Trim();
|
|
|
|
// Normalize
|
|
if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
person.Type = PersonKind.GuestStar;
|
|
}
|
|
else if (string.Equals(person.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
person.Type = PersonKind.Director;
|
|
}
|
|
else if (string.Equals(person.Role, PersonType.Producer, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
person.Type = PersonKind.Producer;
|
|
}
|
|
else if (string.Equals(person.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
person.Type = PersonKind.Writer;
|
|
}
|
|
|
|
// If the type is GuestStar and there's already an Actor entry, then update it to avoid dupes
|
|
if (person.Type == PersonKind.GuestStar)
|
|
{
|
|
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type == PersonKind.Actor);
|
|
|
|
if (existing is not null)
|
|
{
|
|
existing.Type = PersonKind.GuestStar;
|
|
MergeExisting(existing, person);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (person.Type == PersonKind.Actor)
|
|
{
|
|
// If the actor already exists without a role and we have one, fill it in
|
|
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type == PersonKind.Actor || p.Type == PersonKind.GuestStar));
|
|
if (existing is null)
|
|
{
|
|
// Wasn't there - add it
|
|
people.Add(person);
|
|
}
|
|
else
|
|
{
|
|
// Was there, if no role and we have one - fill it in
|
|
if (string.IsNullOrEmpty(existing.Role) && !string.IsNullOrEmpty(person.Role))
|
|
{
|
|
existing.Role = person.Role;
|
|
}
|
|
|
|
MergeExisting(existing, person);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var existing = people.FirstOrDefault(p =>
|
|
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase)
|
|
&& p.Type == person.Type);
|
|
|
|
// Check for dupes based on the combination of Name and Type
|
|
if (existing is null)
|
|
{
|
|
people.Add(person);
|
|
}
|
|
else
|
|
{
|
|
MergeExisting(existing, person);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void MergeExisting(PersonInfo existing, PersonInfo person)
|
|
{
|
|
existing.SortOrder = person.SortOrder ?? existing.SortOrder;
|
|
existing.ImageUrl = person.ImageUrl ?? existing.ImageUrl;
|
|
|
|
foreach (var id in person.ProviderIds)
|
|
{
|
|
existing.SetProviderId(id.Key, id.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|