diff options
Diffstat (limited to 'MediaBrowser.Api/SearchService.cs')
| -rw-r--r-- | MediaBrowser.Api/SearchService.cs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs new file mode 100644 index 000000000..a3d228529 --- /dev/null +++ b/MediaBrowser.Api/SearchService.cs @@ -0,0 +1,192 @@ +using System.Collections; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Search; +using ServiceStack.ServiceHost; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; + +namespace MediaBrowser.Api +{ + /// <summary> + /// Class GetSearchHints + /// </summary> + [Route("/Search/Hints", "GET")] + [Api(Description = "Gets search hints based on a search term")] + public class GetSearchHints : IReturn<List<SearchHintResult>> + { + /// <summary> + /// Skips over a given number of items within the results. Use for paging. + /// </summary> + /// <value>The start index.</value> + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + /// <summary> + /// The maximum number of items to return + /// </summary> + /// <value>The limit.</value> + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Supply a user id to search within a user's library or omit to search all.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + + /// <summary> + /// Search characters used to find items + /// </summary> + /// <value>The index by.</value> + [ApiMember(Name = "SearchTerm", Description = "The search term to filter on", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string SearchTerm { get; set; } + } + + /// <summary> + /// Class SearchService + /// </summary> + public class SearchService : BaseApiService + { + /// <summary> + /// The _user manager + /// </summary> + private readonly IUserManager _userManager; + /// <summary> + /// The _search engine + /// </summary> + private readonly ILibrarySearchEngine _searchEngine; + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="SearchService" /> class. + /// </summary> + /// <param name="userManager">The user manager.</param> + /// <param name="searchEngine">The search engine.</param> + /// <param name="libraryManager">The library manager.</param> + public SearchService(IUserManager userManager, ILibrarySearchEngine searchEngine, ILibraryManager libraryManager) + { + _userManager = userManager; + _searchEngine = searchEngine; + _libraryManager = libraryManager; + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetSearchHints request) + { + var result = GetSearchHintsAsync(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets the search hints async. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{IEnumerable{SearchHintResult}}.</returns> + private async Task<IEnumerable<SearchHintResult>> GetSearchHintsAsync(GetSearchHints request) + { + IEnumerable<BaseItem> inputItems; + + if (request.UserId.HasValue) + { + var user = _userManager.GetUserById(request.UserId.Value); + + inputItems = user.RootFolder.GetRecursiveChildren(user); + } + else + { + inputItems = _libraryManager.RootFolder.RecursiveChildren; + } + + var results = await _searchEngine.GetSearchHints(inputItems, request.SearchTerm).ConfigureAwait(false); + + if (request.StartIndex.HasValue) + { + results = results.Skip(request.StartIndex.Value); + } + + if (request.Limit.HasValue) + { + results = results.Take(request.Limit.Value); + } + + return results.Select(GetSearchHintResult); + } + + /// <summary> + /// Gets the search hint result. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>SearchHintResult.</returns> + private SearchHintResult GetSearchHintResult(BaseItem item) + { + var result = new SearchHintResult + { + Name = item.Name, + IndexNumber = item.IndexNumber, + ParentIndexNumber = item.ParentIndexNumber, + ItemId = DtoBuilder.GetClientItemId(item), + Type = item.GetType().Name, + MediaType = item.MediaType + }; + + if (item.HasImage(ImageType.Primary)) + { + result.PrimaryImageTag = Kernel.Instance.ImageManager.GetImageCacheTag(item, ImageType.Primary, item.GetImage(ImageType.Primary)); + } + + var episode = item as Episode; + + if (episode != null) + { + result.Series = episode.Series.Name; + } + + var season = item as Season; + + if (season != null) + { + result.Series = season.Series.Name; + } + + var album = item as MusicAlbum; + + if (album != null) + { + var songs = album.Children.OfType<Audio>().ToList(); + + result.Artists = songs + .Select(i => i.Artist) + .Where(i => !string.IsNullOrEmpty(i)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); + + result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i)); + } + + var song = item as Audio; + + if (song != null) + { + result.Album = song.Album; + result.AlbumArtist = song.AlbumArtist; + result.Artists = !string.IsNullOrEmpty(song.Artist) ? new[] { song.Artist } : new string[] { }; + } + + return result; + } + } +} |
