2
0

SearchEngine.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 != Guid.Empty)
  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. {
  44. TotalRecordCount = totalRecordCount,
  45. Items = results
  46. };
  47. }
  48. private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value)
  49. {
  50. if (!list.Contains(value))
  51. {
  52. list.Add(value);
  53. }
  54. }
  55. /// <summary>
  56. /// Gets the search hints.
  57. /// </summary>
  58. /// <param name="query">The query.</param>
  59. /// <param name="user">The user.</param>
  60. /// <returns>IEnumerable{SearchHintResult}.</returns>
  61. /// <exception cref="ArgumentException"><c>query.SearchTerm</c> is <c>null</c> or empty.</exception>
  62. private List<SearchHintInfo> GetSearchHints(SearchQuery query, User user)
  63. {
  64. var searchTerm = query.SearchTerm;
  65. if (string.IsNullOrEmpty(searchTerm))
  66. {
  67. throw new ArgumentException("SearchTerm can't be empty.", nameof(query));
  68. }
  69. searchTerm = searchTerm.Trim().RemoveDiacritics();
  70. var excludeItemTypes = query.ExcludeItemTypes.ToList();
  71. var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty<BaseItemKind>()).ToList();
  72. excludeItemTypes.Add(BaseItemKind.Year);
  73. excludeItemTypes.Add(BaseItemKind.Folder);
  74. if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Genre)))
  75. {
  76. if (!query.IncludeMedia)
  77. {
  78. AddIfMissing(includeItemTypes, BaseItemKind.Genre);
  79. AddIfMissing(includeItemTypes, BaseItemKind.MusicGenre);
  80. }
  81. }
  82. else
  83. {
  84. AddIfMissing(excludeItemTypes, BaseItemKind.Genre);
  85. AddIfMissing(excludeItemTypes, BaseItemKind.MusicGenre);
  86. }
  87. if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Person)))
  88. {
  89. if (!query.IncludeMedia)
  90. {
  91. AddIfMissing(includeItemTypes, BaseItemKind.Person);
  92. }
  93. }
  94. else
  95. {
  96. AddIfMissing(excludeItemTypes, BaseItemKind.Person);
  97. }
  98. if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Studio)))
  99. {
  100. if (!query.IncludeMedia)
  101. {
  102. AddIfMissing(includeItemTypes, BaseItemKind.Studio);
  103. }
  104. }
  105. else
  106. {
  107. AddIfMissing(excludeItemTypes, BaseItemKind.Studio);
  108. }
  109. if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.MusicArtist)))
  110. {
  111. if (!query.IncludeMedia)
  112. {
  113. AddIfMissing(includeItemTypes, BaseItemKind.MusicArtist);
  114. }
  115. }
  116. else
  117. {
  118. AddIfMissing(excludeItemTypes, BaseItemKind.MusicArtist);
  119. }
  120. AddIfMissing(excludeItemTypes, BaseItemKind.CollectionFolder);
  121. AddIfMissing(excludeItemTypes, BaseItemKind.Folder);
  122. var mediaTypes = query.MediaTypes.ToList();
  123. if (includeItemTypes.Count > 0)
  124. {
  125. excludeItemTypes.Clear();
  126. mediaTypes.Clear();
  127. }
  128. var searchQuery = new InternalItemsQuery(user)
  129. {
  130. SearchTerm = searchTerm,
  131. ExcludeItemTypes = excludeItemTypes.ToArray(),
  132. IncludeItemTypes = includeItemTypes.ToArray(),
  133. Limit = query.Limit,
  134. IncludeItemsByName = !query.ParentId.HasValue,
  135. ParentId = query.ParentId ?? Guid.Empty,
  136. OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
  137. Recursive = true,
  138. IsKids = query.IsKids,
  139. IsMovie = query.IsMovie,
  140. IsNews = query.IsNews,
  141. IsSeries = query.IsSeries,
  142. IsSports = query.IsSports,
  143. MediaTypes = mediaTypes.ToArray(),
  144. DtoOptions = new DtoOptions
  145. {
  146. Fields = new ItemFields[]
  147. {
  148. ItemFields.AirTime,
  149. ItemFields.DateCreated,
  150. ItemFields.ChannelInfo,
  151. ItemFields.ParentId
  152. }
  153. }
  154. };
  155. List<BaseItem> mediaItems;
  156. if (searchQuery.IncludeItemTypes.Length == 1 && searchQuery.IncludeItemTypes[0] == BaseItemKind.MusicArtist)
  157. {
  158. if (!searchQuery.ParentId.Equals(Guid.Empty))
  159. {
  160. searchQuery.AncestorIds = new[] { searchQuery.ParentId };
  161. }
  162. searchQuery.ParentId = Guid.Empty;
  163. searchQuery.IncludeItemsByName = true;
  164. searchQuery.IncludeItemTypes = Array.Empty<BaseItemKind>();
  165. mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item).ToList();
  166. }
  167. else
  168. {
  169. mediaItems = _libraryManager.GetItemList(searchQuery);
  170. }
  171. return mediaItems.Select(i => new SearchHintInfo
  172. {
  173. Item = i
  174. }).ToList();
  175. }
  176. }
  177. }