AlbumMetadataService.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using MediaBrowser.Controller.Configuration;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Entities.Audio;
  7. using MediaBrowser.Controller.Library;
  8. using MediaBrowser.Controller.Providers;
  9. using MediaBrowser.Model.Entities;
  10. using MediaBrowser.Model.IO;
  11. using MediaBrowser.Providers.Manager;
  12. using Microsoft.Extensions.Logging;
  13. namespace MediaBrowser.Providers.Music
  14. {
  15. /// <summary>
  16. /// The album metadata service.
  17. /// </summary>
  18. public class AlbumMetadataService : MetadataService<MusicAlbum, AlbumInfo>
  19. {
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref="AlbumMetadataService"/> class.
  22. /// </summary>
  23. /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/>.</param>
  24. /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
  25. /// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
  26. /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
  27. /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
  28. public AlbumMetadataService(
  29. IServerConfigurationManager serverConfigurationManager,
  30. ILogger<AlbumMetadataService> logger,
  31. IProviderManager providerManager,
  32. IFileSystem fileSystem,
  33. ILibraryManager libraryManager)
  34. : base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
  35. {
  36. }
  37. /// <inheritdoc />
  38. protected override bool EnableUpdatingPremiereDateFromChildren => true;
  39. /// <inheritdoc />
  40. protected override bool EnableUpdatingGenresFromChildren => true;
  41. /// <inheritdoc />
  42. protected override bool EnableUpdatingStudiosFromChildren => true;
  43. /// <inheritdoc />
  44. protected override IList<BaseItem> GetChildrenForMetadataUpdates(MusicAlbum item)
  45. => item.GetRecursiveChildren(i => i is Audio);
  46. /// <inheritdoc />
  47. protected override ItemUpdateType UpdateMetadataFromChildren(MusicAlbum item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType)
  48. {
  49. var updateType = base.UpdateMetadataFromChildren(item, children, isFullRefresh, currentUpdateType);
  50. if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
  51. {
  52. if (!item.LockedFields.Contains(MetadataField.Name))
  53. {
  54. var name = children.Select(i => i.Album).FirstOrDefault(i => !string.IsNullOrEmpty(i));
  55. if (!string.IsNullOrEmpty(name)
  56. && !string.Equals(item.Name, name, StringComparison.Ordinal))
  57. {
  58. item.Name = name;
  59. updateType |= ItemUpdateType.MetadataEdit;
  60. }
  61. }
  62. var songs = children.Cast<Audio>().ToArray();
  63. updateType |= SetArtistsFromSongs(item, songs);
  64. updateType |= SetAlbumArtistFromSongs(item, songs);
  65. updateType |= SetAlbumFromSongs(item, songs);
  66. updateType |= SetPeople(item);
  67. }
  68. return updateType;
  69. }
  70. private ItemUpdateType SetAlbumArtistFromSongs(MusicAlbum item, IReadOnlyList<Audio> songs)
  71. {
  72. var updateType = ItemUpdateType.None;
  73. var albumArtists = songs
  74. .SelectMany(i => i.AlbumArtists)
  75. .GroupBy(i => i)
  76. .OrderByDescending(g => g.Count())
  77. .Select(g => g.Key)
  78. .ToArray();
  79. updateType |= SetProviderIdFromSongs(item, songs, MetadataProvider.MusicBrainzAlbumArtist);
  80. if (!item.AlbumArtists.SequenceEqual(albumArtists, StringComparer.OrdinalIgnoreCase))
  81. {
  82. item.AlbumArtists = albumArtists;
  83. updateType |= ItemUpdateType.MetadataEdit;
  84. }
  85. return updateType;
  86. }
  87. private ItemUpdateType SetArtistsFromSongs(MusicAlbum item, IReadOnlyList<Audio> songs)
  88. {
  89. var updateType = ItemUpdateType.None;
  90. var artists = songs
  91. .SelectMany(i => i.Artists)
  92. .GroupBy(i => i)
  93. .OrderByDescending(g => g.Count())
  94. .Select(g => g.Key)
  95. .ToArray();
  96. if (!item.Artists.SequenceEqual(artists, StringComparer.OrdinalIgnoreCase))
  97. {
  98. item.Artists = artists;
  99. updateType |= ItemUpdateType.MetadataEdit;
  100. }
  101. return updateType;
  102. }
  103. private ItemUpdateType SetAlbumFromSongs(MusicAlbum item, IReadOnlyList<Audio> songs)
  104. {
  105. var updateType = ItemUpdateType.None;
  106. updateType |= SetProviderIdFromSongs(item, songs, MetadataProvider.MusicBrainzAlbum);
  107. updateType |= SetProviderIdFromSongs(item, songs, MetadataProvider.MusicBrainzReleaseGroup);
  108. return updateType;
  109. }
  110. private ItemUpdateType SetProviderIdFromSongs(BaseItem item, IReadOnlyList<Audio> songs, MetadataProvider provider)
  111. {
  112. var ids = songs
  113. .Select(i => i.GetProviderId(provider))
  114. .GroupBy(i => i)
  115. .OrderByDescending(g => g.Count())
  116. .Select(g => g.Key)
  117. .ToArray();
  118. var id = item.GetProviderId(provider);
  119. if (ids.Any())
  120. {
  121. var firstId = ids[0];
  122. if (!string.IsNullOrEmpty(firstId)
  123. && (string.IsNullOrEmpty(id)
  124. || !id.Equals(firstId, StringComparison.OrdinalIgnoreCase)))
  125. {
  126. item.SetProviderId(provider, firstId);
  127. return ItemUpdateType.MetadataEdit;
  128. }
  129. }
  130. return ItemUpdateType.None;
  131. }
  132. private void SetProviderId(MusicAlbum sourceItem, MusicAlbum targetItem, MetadataProvider provider)
  133. {
  134. var source = sourceItem.GetProviderId(provider);
  135. var target = targetItem.GetProviderId(provider);
  136. if (!string.IsNullOrEmpty(source)
  137. && (string.IsNullOrEmpty(target)
  138. || !target.Equals(source, StringComparison.Ordinal)))
  139. {
  140. targetItem.SetProviderId(provider, source);
  141. }
  142. }
  143. private ItemUpdateType SetPeople(MusicAlbum item)
  144. {
  145. var updateType = ItemUpdateType.None;
  146. if (item.AlbumArtists.Any() || item.Artists.Any())
  147. {
  148. var people = new List<PersonInfo>();
  149. foreach (var albumArtist in item.AlbumArtists)
  150. {
  151. PeopleHelper.AddPerson(people, new PersonInfo
  152. {
  153. Name = albumArtist,
  154. Type = "AlbumArtist"
  155. });
  156. }
  157. foreach (var artist in item.Artists)
  158. {
  159. PeopleHelper.AddPerson(people, new PersonInfo
  160. {
  161. Name = artist,
  162. Type = "Artist"
  163. });
  164. }
  165. LibraryManager.UpdatePeople(item, people);
  166. updateType |= ItemUpdateType.MetadataEdit;
  167. }
  168. return updateType;
  169. }
  170. /// <inheritdoc />
  171. protected override void MergeData(
  172. MetadataResult<MusicAlbum> source,
  173. MetadataResult<MusicAlbum> target,
  174. MetadataField[] lockedFields,
  175. bool replaceData,
  176. bool mergeMetadataSettings)
  177. {
  178. base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
  179. var sourceItem = source.Item;
  180. var targetItem = target.Item;
  181. if (replaceData || targetItem.Artists.Count == 0)
  182. {
  183. targetItem.Artists = sourceItem.Artists;
  184. }
  185. if (replaceData || string.IsNullOrEmpty(targetItem.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist)))
  186. {
  187. SetProviderId(sourceItem, targetItem, MetadataProvider.MusicBrainzAlbumArtist);
  188. }
  189. if (replaceData || string.IsNullOrEmpty(targetItem.GetProviderId(MetadataProvider.MusicBrainzAlbum)))
  190. {
  191. SetProviderId(sourceItem, targetItem, MetadataProvider.MusicBrainzAlbum);
  192. }
  193. if (replaceData || string.IsNullOrEmpty(targetItem.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup)))
  194. {
  195. SetProviderId(sourceItem, targetItem, MetadataProvider.MusicBrainzReleaseGroup);
  196. }
  197. }
  198. }
  199. }