SearchEngine.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #nullable disable
  2. #pragma warning disable CS1591
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using Diacritics.Extensions;
  7. using Jellyfin.Data.Entities;
  8. using Jellyfin.Data.Enums;
  9. using MediaBrowser.Controller.Dto;
  10. using MediaBrowser.Controller.Entities;
  11. using MediaBrowser.Controller.Library;
  12. using MediaBrowser.Model.Querying;
  13. using MediaBrowser.Model.Search;
  14. namespace Emby.Server.Implementations.Library
  15. {
  16. public class SearchEngine : ISearchEngine
  17. {
  18. private readonly ILibraryManager _libraryManager;
  19. private readonly IUserManager _userManager;
  20. public SearchEngine(ILibraryManager libraryManager, IUserManager userManager)
  21. {
  22. _libraryManager = libraryManager;
  23. _userManager = userManager;
  24. }
  25. public QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query)
  26. {
  27. User user = null;
  28. if (!query.UserId.Equals(default))
  29. {
  30. user = _userManager.GetUserById(query.UserId);
  31. }
  32. var results = GetSearchHints(query, user);
  33. var totalRecordCount = results.Count;
  34. if (query.StartIndex.HasValue)
  35. {
  36. results = results.GetRange(query.StartIndex.Value, totalRecordCount - query.StartIndex.Value);
  37. }
  38. if (query.Limit.HasValue)
  39. {
  40. results = results.GetRange(0, Math.Min(query.Limit.Value, results.Count));
  41. }
  42. return new QueryResult<SearchHintInfo>(
  43. query.StartIndex,
  44. totalRecordCount,
  45. results);
  46. }
  47. private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value)
  48. {
  49. if (!list.Contains(value))
  50. {
  51. list.Add(value);
  52. }
  53. }
  54. /// <summary>
  55. /// Gets the search hints.
  56. /// </summary>
  57. /// <param name="query">The query.</param>
  58. /// <param name="user">The user.</param>
  59. /// <returns>IEnumerable{SearchHintResult}.</returns>
  60. /// <exception cref="ArgumentException"><c>query.SearchTerm</c> is <c>null</c> or empty.</exception>
  61. private List<SearchHintInfo> GetSearchHints(SearchQuery query, User user)
  62. {
  63. var searchTerm = query.SearchTerm;
  64. if (string.IsNullOrEmpty(searchTerm))
  65. {
  66. throw new ArgumentException("SearchTerm can't be empty.", nameof(query));
  67. }
  68. searchTerm = searchTerm.Trim().RemoveDiacritics();
  69. var excludeItemTypes = query.ExcludeItemTypes.ToList();
  70. var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty<BaseItemKind>()).ToList();
  71. excludeItemTypes.Add(BaseItemKind.Year);
  72. excludeItemTypes.Add(BaseItemKind.Folder);
  73. if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Genre)))
  74. {
  75. if (!query.IncludeMedia)
  76. {
  77. AddIfMissing(includeItemTypes, BaseItemKind.Genre);
  78. AddIfMissing(includeItemTypes, BaseItemKind.MusicGenre);
  79. }
  80. }
  81. else
  82. {
  83. AddIfMissing(excludeItemTypes, BaseItemKind.Genre);
  84. AddIfMissing(excludeItemTypes, BaseItemKind.MusicGenre);
  85. }
  86. if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Person)))
  87. {
  88. if (!query.IncludeMedia)
  89. {
  90. AddIfMissing(includeItemTypes, BaseItemKind.Person);
  91. }
  92. }
  93. else
  94. {
  95. AddIfMissing(excludeItemTypes, BaseItemKind.Person);
  96. }
  97. if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Studio)))
  98. {
  99. if (!query.IncludeMedia)
  100. {
  101. AddIfMissing(includeItemTypes, BaseItemKind.Studio);
  102. }
  103. }
  104. else
  105. {
  106. AddIfMissing(excludeItemTypes, BaseItemKind.Studio);
  107. }
  108. if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.MusicArtist)))
  109. {
  110. if (!query.IncludeMedia)
  111. {
  112. AddIfMissing(includeItemTypes, BaseItemKind.MusicArtist);
  113. }
  114. }
  115. else
  116. {
  117. AddIfMissing(excludeItemTypes, BaseItemKind.MusicArtist);
  118. }
  119. AddIfMissing(excludeItemTypes, BaseItemKind.CollectionFolder);
  120. AddIfMissing(excludeItemTypes, BaseItemKind.Folder);
  121. var mediaTypes = query.MediaTypes.ToList();
  122. if (includeItemTypes.Count > 0)
  123. {
  124. excludeItemTypes.Clear();
  125. mediaTypes.Clear();
  126. }
  127. var searchQuery = new InternalItemsQuery(user)
  128. {
  129. SearchTerm = searchTerm,
  130. ExcludeItemTypes = excludeItemTypes.ToArray(),
  131. IncludeItemTypes = includeItemTypes.ToArray(),
  132. Limit = query.Limit,
  133. IncludeItemsByName = !query.ParentId.HasValue,
  134. ParentId = query.ParentId ?? Guid.Empty,
  135. OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
  136. Recursive = true,
  137. IsKids = query.IsKids,
  138. IsMovie = query.IsMovie,
  139. IsNews = query.IsNews,
  140. IsSeries = query.IsSeries,
  141. IsSports = query.IsSports,
  142. MediaTypes = mediaTypes.ToArray(),
  143. DtoOptions = new DtoOptions
  144. {
  145. Fields = new ItemFields[]
  146. {
  147. ItemFields.AirTime,
  148. ItemFields.DateCreated,
  149. ItemFields.ChannelInfo,
  150. ItemFields.ParentId
  151. }
  152. }
  153. };
  154. List<BaseItem> mediaItems;
  155. if (searchQuery.IncludeItemTypes.Length == 1 && searchQuery.IncludeItemTypes[0] == BaseItemKind.MusicArtist)
  156. {
  157. if (!searchQuery.ParentId.Equals(default))
  158. {
  159. searchQuery.AncestorIds = new[] { searchQuery.ParentId };
  160. searchQuery.ParentId = Guid.Empty;
  161. }
  162. searchQuery.IncludeItemsByName = true;
  163. searchQuery.IncludeItemTypes = Array.Empty<BaseItemKind>();
  164. mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item).ToList();
  165. }
  166. else
  167. {
  168. mediaItems = _libraryManager.GetItemList(searchQuery);
  169. }
  170. return mediaItems.Select(i => new SearchHintInfo
  171. {
  172. Item = i
  173. }).ToList();
  174. }
  175. }
  176. }