AudioBookListResolver.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #pragma warning disable CS1591
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using Emby.Naming.Common;
  7. using Emby.Naming.Video;
  8. using MediaBrowser.Model.IO;
  9. namespace Emby.Naming.AudioBook
  10. {
  11. public class AudioBookListResolver
  12. {
  13. private readonly NamingOptions _options;
  14. public AudioBookListResolver(NamingOptions options)
  15. {
  16. _options = options;
  17. }
  18. public IEnumerable<AudioBookInfo> Resolve(IEnumerable<FileSystemMetadata> files)
  19. {
  20. var audioBookResolver = new AudioBookResolver(_options);
  21. // File with empty fullname will be sorted out here
  22. var audiobookFileInfos = files
  23. .Select(i => audioBookResolver.Resolve(i.FullName))
  24. .OfType<AudioBookFileInfo>()
  25. .ToList();
  26. var stackResult = new StackResolver(_options)
  27. .ResolveAudioBooks(audiobookFileInfos);
  28. foreach (var stack in stackResult)
  29. {
  30. var stackFiles = stack.Files
  31. .Select(i => audioBookResolver.Resolve(i))
  32. .OfType<AudioBookFileInfo>()
  33. .ToList();
  34. stackFiles.Sort();
  35. var nameParserResult = new AudioBookNameParser(_options).Parse(stack.Name);
  36. FindExtraAndAlternativeFiles(ref stackFiles, out var extras, out var alternativeVersions, nameParserResult);
  37. var info = new AudioBookInfo(
  38. nameParserResult.Name,
  39. nameParserResult.Year,
  40. stackFiles,
  41. extras,
  42. alternativeVersions);
  43. yield return info;
  44. }
  45. }
  46. private void FindExtraAndAlternativeFiles(ref List<AudioBookFileInfo> stackFiles, out List<AudioBookFileInfo> extras, out List<AudioBookFileInfo> alternativeVersions, AudioBookNameParserResult nameParserResult)
  47. {
  48. extras = new List<AudioBookFileInfo>();
  49. alternativeVersions = new List<AudioBookFileInfo>();
  50. var haveChaptersOrPages = stackFiles.Any(x => x.ChapterNumber != null || x.PartNumber != null);
  51. var groupedBy = stackFiles.GroupBy(file => new { file.ChapterNumber, file.PartNumber });
  52. foreach (var group in groupedBy)
  53. {
  54. if (group.Key.ChapterNumber == null && group.Key.PartNumber == null)
  55. {
  56. if (group.Count() > 1 || haveChaptersOrPages)
  57. {
  58. var ex = new List<AudioBookFileInfo>();
  59. var alt = new List<AudioBookFileInfo>();
  60. foreach (var audioFile in group)
  61. {
  62. var name = Path.GetFileNameWithoutExtension(audioFile.Path);
  63. if (name == "audiobook" ||
  64. name.Contains(nameParserResult.Name, StringComparison.OrdinalIgnoreCase) ||
  65. name.Contains(nameParserResult.Name.Replace(" ", "."), StringComparison.OrdinalIgnoreCase))
  66. {
  67. alt.Add(audioFile);
  68. }
  69. else
  70. {
  71. ex.Add(audioFile);
  72. }
  73. }
  74. if (ex.Count > 0)
  75. {
  76. var extra = ex
  77. .OrderBy(x => x.Container)
  78. .ThenBy(x => x.Path)
  79. .ToList();
  80. stackFiles = stackFiles.Except(extra).ToList();
  81. extras.AddRange(extra);
  82. }
  83. if (alt.Count > 0)
  84. {
  85. var alternatives = alt
  86. .OrderBy(x => x.Container)
  87. .ThenBy(x => x.Path)
  88. .ToList();
  89. var main = FindMainAudioBookFile(alternatives, nameParserResult.Name);
  90. alternatives.Remove(main);
  91. stackFiles = stackFiles.Except(alternatives).ToList();
  92. alternativeVersions.AddRange(alternatives);
  93. }
  94. }
  95. }
  96. else if (group.Count() > 1)
  97. {
  98. var alternatives = group
  99. .OrderBy(x => x.Container)
  100. .ThenBy(x => x.Path)
  101. .Skip(1)
  102. .ToList();
  103. stackFiles = stackFiles.Except(alternatives).ToList();
  104. alternativeVersions.AddRange(alternatives);
  105. }
  106. }
  107. }
  108. private AudioBookFileInfo FindMainAudioBookFile(List<AudioBookFileInfo> files, string name)
  109. {
  110. var main = files.Find(x => Path.GetFileNameWithoutExtension(x.Path) == name);
  111. main ??= files.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x.Path) == "audiobook");
  112. main ??= files.OrderBy(x => x.Container)
  113. .ThenBy(x => x.Path)
  114. .First();
  115. return main;
  116. }
  117. }
  118. }