UserViewBuilder.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. using MediaBrowser.Controller.Channels;
  2. using MediaBrowser.Controller.Entities.Audio;
  3. using MediaBrowser.Controller.Entities.Movies;
  4. using MediaBrowser.Controller.Entities.TV;
  5. using MediaBrowser.Controller.Library;
  6. using MediaBrowser.Controller.LiveTv;
  7. using MediaBrowser.Controller.TV;
  8. using MediaBrowser.Model.Channels;
  9. using MediaBrowser.Model.Entities;
  10. using MediaBrowser.Model.LiveTv;
  11. using MediaBrowser.Model.Logging;
  12. using MediaBrowser.Model.Querying;
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. namespace MediaBrowser.Controller.Entities
  19. {
  20. public class UserViewBuilder
  21. {
  22. private readonly IChannelManager _channelManager;
  23. private readonly ILiveTvManager _liveTvManager;
  24. private readonly IUserViewManager _userViewManager;
  25. private readonly ILibraryManager _libraryManager;
  26. private readonly ILogger _logger;
  27. private readonly IUserDataManager _userDataManager;
  28. private readonly ITVSeriesManager _tvSeriesManager;
  29. public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager)
  30. {
  31. _userViewManager = userViewManager;
  32. _liveTvManager = liveTvManager;
  33. _channelManager = channelManager;
  34. _libraryManager = libraryManager;
  35. _logger = logger;
  36. _userDataManager = userDataManager;
  37. _tvSeriesManager = tvSeriesManager;
  38. }
  39. public async Task<QueryResult<BaseItem>> GetUserItems(Folder parent, string viewType, UserItemsQuery query)
  40. {
  41. var user = query.User;
  42. switch (viewType)
  43. {
  44. case CollectionType.Channels:
  45. {
  46. var result = await _channelManager.GetChannelsInternal(new ChannelQuery
  47. {
  48. UserId = user.Id.ToString("N"),
  49. Limit = query.Limit,
  50. StartIndex = query.StartIndex
  51. }, CancellationToken.None).ConfigureAwait(false);
  52. return GetResult(result);
  53. }
  54. case CollectionType.LiveTvChannels:
  55. {
  56. var result = await _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
  57. {
  58. UserId = query.User.Id.ToString("N"),
  59. Limit = query.Limit,
  60. StartIndex = query.StartIndex
  61. }, CancellationToken.None).ConfigureAwait(false);
  62. return GetResult(result);
  63. }
  64. case CollectionType.LiveTvNowPlaying:
  65. {
  66. var result = await _liveTvManager.GetRecommendedProgramsInternal(new RecommendedProgramQuery
  67. {
  68. UserId = query.User.Id.ToString("N"),
  69. Limit = query.Limit,
  70. IsAiring = true
  71. }, CancellationToken.None).ConfigureAwait(false);
  72. return GetResult(result);
  73. }
  74. case CollectionType.LiveTvRecordingGroups:
  75. {
  76. var result = await _liveTvManager.GetInternalRecordings(new RecordingQuery
  77. {
  78. UserId = query.User.Id.ToString("N"),
  79. Status = RecordingStatus.Completed,
  80. Limit = query.Limit,
  81. StartIndex = query.StartIndex
  82. }, CancellationToken.None).ConfigureAwait(false);
  83. return GetResult(result);
  84. }
  85. case CollectionType.LiveTv:
  86. {
  87. var result = await GetLiveTvFolders(user).ConfigureAwait(false);
  88. return GetResult(result, query);
  89. }
  90. case CollectionType.Folders:
  91. return GetResult(user.RootFolder.GetChildren(user, true), query);
  92. case CollectionType.Games:
  93. return await GetGameView(user, parent, query).ConfigureAwait(false);
  94. case CollectionType.BoxSets:
  95. return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), query);
  96. case CollectionType.TvShows:
  97. return await GetTvView(parent, user, query).ConfigureAwait(false);
  98. case CollectionType.Music:
  99. return await GetMusicFolders(parent, user, query).ConfigureAwait(false);
  100. case CollectionType.Movies:
  101. return await GetMovieFolders(parent, user, query).ConfigureAwait(false);
  102. case CollectionType.GameGenres:
  103. return GetGameGenres(parent, user, query);
  104. case CollectionType.GameSystems:
  105. return GetGameSystems(parent, user, query);
  106. case CollectionType.LatestGames:
  107. return GetLatestGames(parent, user, query);
  108. case CollectionType.RecentlyPlayedGames:
  109. return GetRecentlyPlayedGames(parent, user, query);
  110. case CollectionType.GameFavorites:
  111. return GetFavoriteGames(parent, user, query);
  112. case CollectionType.ViewTypeTvShowSeries:
  113. return GetTvSeries(parent, user, query);
  114. case CollectionType.TvGenres:
  115. return GetTvGenres(parent, user, query);
  116. case CollectionType.TvResume:
  117. return GetTvResume(parent, user, query);
  118. case CollectionType.TvNextUp:
  119. return GetTvNextUp(parent, query);
  120. case CollectionType.TvLatest:
  121. return GetTvLatest(parent, user, query);
  122. case CollectionType.MovieFavorites:
  123. return GetFavoriteMovies(parent, user, query);
  124. case CollectionType.MovieLatest:
  125. return GetMovieLatest(parent, user, query);
  126. case CollectionType.MovieGenres:
  127. return GetMovieGenres(parent, user, query);
  128. case CollectionType.MovieResume:
  129. return GetMovieResume(parent, user, query);
  130. case CollectionType.MovieMovies:
  131. return GetMovieMovies(parent, user, query);
  132. case CollectionType.MovieCollections:
  133. return GetMovieCollections(parent, user, query);
  134. case CollectionType.MusicLatest:
  135. return GetMusicLatest(parent, user, query);
  136. case CollectionType.MusicAlbums:
  137. return GetMusicAlbums(parent, user, query);
  138. case CollectionType.MusicAlbumArtists:
  139. return GetMusicAlbumArtists(parent, user, query);
  140. case CollectionType.MusicArtists:
  141. return GetMusicArtists(parent, user, query);
  142. case CollectionType.TvFavoriteEpisodes:
  143. return GetFavoriteEpisodes(parent, user, query);
  144. case CollectionType.TvFavoriteSeries:
  145. return GetFavoriteSeries(parent, user, query);
  146. default:
  147. return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), query);
  148. }
  149. }
  150. private int GetSpecialItemsLimit()
  151. {
  152. return 50;
  153. }
  154. private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, UserItemsQuery query)
  155. {
  156. if (query.Recursive)
  157. {
  158. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }), query);
  159. }
  160. var list = new List<BaseItem>();
  161. var category = "music";
  162. list.Add(await GetUserView(category, CollectionType.MusicLatest, user, "0", parent).ConfigureAwait(false));
  163. list.Add(await GetUserView(category, CollectionType.MusicAlbums, user, "1", parent).ConfigureAwait(false));
  164. list.Add(await GetUserView(category, CollectionType.MusicAlbumArtists, user, "2", parent).ConfigureAwait(false));
  165. //list.Add(await GetUserView(CollectionType.MusicArtists, user, "3", parent).ConfigureAwait(false));
  166. //list.Add(await GetUserView(CollectionType.MusicGenres, user, "5", parent).ConfigureAwait(false));
  167. return GetResult(list, query);
  168. }
  169. private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, UserItemsQuery query)
  170. {
  171. var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music })
  172. .Where(i => !i.IsFolder)
  173. .OfType<IHasAlbumArtist>()
  174. .SelectMany(i => i.AlbumArtists)
  175. .Distinct(StringComparer.OrdinalIgnoreCase)
  176. .Select(i =>
  177. {
  178. try
  179. {
  180. return _libraryManager.GetArtist(i);
  181. }
  182. catch
  183. {
  184. // Already logged at lower levels
  185. return null;
  186. }
  187. })
  188. .Where(i => i != null);
  189. return GetResult(artists, query);
  190. }
  191. private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, UserItemsQuery query)
  192. {
  193. var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music })
  194. .Where(i => !i.IsFolder)
  195. .OfType<IHasArtist>()
  196. .SelectMany(i => i.Artists)
  197. .Distinct(StringComparer.OrdinalIgnoreCase)
  198. .Select(i =>
  199. {
  200. try
  201. {
  202. return _libraryManager.GetArtist(i);
  203. }
  204. catch
  205. {
  206. // Already logged at lower levels
  207. return null;
  208. }
  209. })
  210. .Where(i => i != null);
  211. return GetResult(artists, query);
  212. }
  213. private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, UserItemsQuery query)
  214. {
  215. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is MusicAlbum), query);
  216. }
  217. private QueryResult<BaseItem> GetMusicLatest(Folder parent, User user, UserItemsQuery query)
  218. {
  219. query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
  220. query.SortOrder = SortOrder.Descending;
  221. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is MusicVideo || i is Audio.Audio), GetSpecialItemsLimit(), query);
  222. }
  223. private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, UserItemsQuery query)
  224. {
  225. if (query.Recursive)
  226. {
  227. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie || i is BoxSet), query);
  228. }
  229. var list = new List<BaseItem>();
  230. var category = "movies";
  231. list.Add(await GetUserView(category, CollectionType.MovieResume, user, "0", parent).ConfigureAwait(false));
  232. list.Add(await GetUserView(category, CollectionType.MovieLatest, user, "1", parent).ConfigureAwait(false));
  233. list.Add(await GetUserView(category, CollectionType.MovieMovies, user, "2", parent).ConfigureAwait(false));
  234. list.Add(await GetUserView(category, CollectionType.MovieCollections, user, "3", parent).ConfigureAwait(false));
  235. list.Add(await GetUserView(category, CollectionType.MovieFavorites, user, "4", parent).ConfigureAwait(false));
  236. //list.Add(await GetUserView(CollectionType.MovieGenres, user, "5", parent).ConfigureAwait(false));
  237. return GetResult(list, query);
  238. }
  239. private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, UserItemsQuery query)
  240. {
  241. query.IsFavorite = true;
  242. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
  243. }
  244. private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, UserItemsQuery query)
  245. {
  246. query.IsFavorite = true;
  247. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series), query);
  248. }
  249. private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, UserItemsQuery query)
  250. {
  251. query.IsFavorite = true;
  252. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Episode), query);
  253. }
  254. private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, UserItemsQuery query)
  255. {
  256. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
  257. }
  258. private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, UserItemsQuery query)
  259. {
  260. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is BoxSet), query);
  261. }
  262. private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, UserItemsQuery query)
  263. {
  264. query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
  265. query.SortOrder = SortOrder.Descending;
  266. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
  267. }
  268. private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, UserItemsQuery query)
  269. {
  270. query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
  271. query.SortOrder = SortOrder.Descending;
  272. query.IsResumable = true;
  273. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
  274. }
  275. private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, UserItemsQuery query)
  276. {
  277. var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
  278. .Where(i => i is Movie)
  279. .SelectMany(i => i.Genres)
  280. .Distinct(StringComparer.OrdinalIgnoreCase)
  281. .Select(i =>
  282. {
  283. try
  284. {
  285. return _libraryManager.GetGenre(i);
  286. }
  287. catch
  288. {
  289. // Full exception logged at lower levels
  290. _logger.Error("Error getting genre");
  291. return null;
  292. }
  293. })
  294. .Where(i => i != null);
  295. return GetResult(genres, query);
  296. }
  297. private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, UserItemsQuery query)
  298. {
  299. if (query.Recursive)
  300. {
  301. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series || i is Season || i is Episode), query);
  302. }
  303. var list = new List<BaseItem>();
  304. var category = "tv";
  305. list.Add(await GetUserView(category, CollectionType.TvResume, user, "0", parent).ConfigureAwait(false));
  306. list.Add(await GetUserView(category, CollectionType.TvNextUp, user, "1", parent).ConfigureAwait(false));
  307. list.Add(await GetUserView(category, CollectionType.TvLatest, user, "2", parent).ConfigureAwait(false));
  308. list.Add(await GetUserView(category, CollectionType.ViewTypeTvShowSeries, user, "3", parent).ConfigureAwait(false));
  309. list.Add(await GetUserView(category, CollectionType.TvFavoriteSeries, user, "4", parent).ConfigureAwait(false));
  310. list.Add(await GetUserView(category, CollectionType.TvFavoriteEpisodes, user, "5", parent).ConfigureAwait(false));
  311. //list.Add(await GetUserView(CollectionType.TvGenres, user, "5", parent).ConfigureAwait(false));
  312. return GetResult(list, query);
  313. }
  314. private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, UserItemsQuery query)
  315. {
  316. if (query.Recursive)
  317. {
  318. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }), query);
  319. }
  320. var list = new List<BaseItem>();
  321. var category = "games";
  322. list.Add(await GetUserView(category, CollectionType.LatestGames, user, "0", parent).ConfigureAwait(false));
  323. list.Add(await GetUserView(category, CollectionType.RecentlyPlayedGames, user, "1", parent).ConfigureAwait(false));
  324. list.Add(await GetUserView(category, CollectionType.GameFavorites, user, "2", parent).ConfigureAwait(false));
  325. list.Add(await GetUserView(category, CollectionType.GameSystems, user, "3", parent).ConfigureAwait(false));
  326. //list.Add(await GetUserView(CollectionType.GameGenres, user, "4", parent).ConfigureAwait(false));
  327. return GetResult(list, query);
  328. }
  329. private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, UserItemsQuery query)
  330. {
  331. query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
  332. query.SortOrder = SortOrder.Descending;
  333. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
  334. }
  335. private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, UserItemsQuery query)
  336. {
  337. query.IsPlayed = true;
  338. query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
  339. query.SortOrder = SortOrder.Descending;
  340. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
  341. }
  342. private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, UserItemsQuery query)
  343. {
  344. query.IsFavorite = true;
  345. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), query);
  346. }
  347. private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, UserItemsQuery query)
  348. {
  349. query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
  350. query.SortOrder = SortOrder.Descending;
  351. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
  352. }
  353. private QueryResult<BaseItem> GetTvNextUp(Folder parent, UserItemsQuery query)
  354. {
  355. var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty });
  356. var result = _tvSeriesManager.GetNextUp(new NextUpQuery
  357. {
  358. Limit = query.Limit,
  359. StartIndex = query.StartIndex,
  360. UserId = query.User.Id.ToString("N")
  361. }, parentFolders);
  362. return result;
  363. }
  364. private QueryResult<BaseItem> GetTvResume(Folder parent, User user, UserItemsQuery query)
  365. {
  366. query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
  367. query.SortOrder = SortOrder.Descending;
  368. query.IsResumable = true;
  369. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
  370. }
  371. private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, UserItemsQuery query)
  372. {
  373. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), query);
  374. }
  375. private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, UserItemsQuery query)
  376. {
  377. var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
  378. .OfType<Series>()
  379. .SelectMany(i => i.Genres)
  380. .Distinct(StringComparer.OrdinalIgnoreCase)
  381. .Select(i =>
  382. {
  383. try
  384. {
  385. return _libraryManager.GetGenre(i);
  386. }
  387. catch
  388. {
  389. // Full exception logged at lower levels
  390. _logger.Error("Error getting genre");
  391. return null;
  392. }
  393. })
  394. .Where(i => i != null);
  395. return GetResult(genres, query);
  396. }
  397. private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, UserItemsQuery query)
  398. {
  399. return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), query);
  400. }
  401. private QueryResult<BaseItem> GetGameGenres(Folder parent, User user, UserItemsQuery query)
  402. {
  403. var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
  404. .OfType<Game>()
  405. .SelectMany(i => i.Genres)
  406. .Distinct(StringComparer.OrdinalIgnoreCase)
  407. .Select(i =>
  408. {
  409. try
  410. {
  411. return _libraryManager.GetGameGenre(i);
  412. }
  413. catch
  414. {
  415. // Full exception logged at lower levels
  416. _logger.Error("Error getting game genre");
  417. return null;
  418. }
  419. })
  420. .Where(i => i != null);
  421. return GetResult(genres, query);
  422. }
  423. private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
  424. where T : BaseItem
  425. {
  426. return new QueryResult<BaseItem>
  427. {
  428. Items = result.Items,
  429. TotalRecordCount = result.TotalRecordCount
  430. };
  431. }
  432. private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
  433. UserItemsQuery query)
  434. where T : BaseItem
  435. {
  436. return GetResult(items, null, query);
  437. }
  438. private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
  439. int? totalRecordLimit,
  440. UserItemsQuery query)
  441. where T : BaseItem
  442. {
  443. return SortAndFilter(items, totalRecordLimit, query, _libraryManager, _userDataManager);
  444. }
  445. public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items,
  446. int? totalRecordLimit,
  447. UserItemsQuery query,
  448. ILibraryManager libraryManager,
  449. IUserDataManager userDataManager)
  450. {
  451. var user = query.User;
  452. items = items.Where(i => Filter(i, user, query, userDataManager));
  453. return Sort(items, totalRecordLimit, query, libraryManager);
  454. }
  455. public static QueryResult<BaseItem> Sort(IEnumerable<BaseItem> items,
  456. int? totalRecordLimit,
  457. UserItemsQuery query,
  458. ILibraryManager libraryManager)
  459. {
  460. var user = query.User;
  461. items = libraryManager.ReplaceVideosWithPrimaryVersions(items);
  462. if (query.SortBy.Length > 0)
  463. {
  464. items = libraryManager.Sort(items, user, query.SortBy, query.SortOrder);
  465. }
  466. var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();
  467. var totalCount = itemsArray.Length;
  468. if (query.Limit.HasValue)
  469. {
  470. itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray();
  471. }
  472. else if (query.StartIndex.HasValue)
  473. {
  474. itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
  475. }
  476. return new QueryResult<BaseItem>
  477. {
  478. TotalRecordCount = totalCount,
  479. Items = itemsArray
  480. };
  481. }
  482. private static bool Filter(BaseItem item, User user, UserItemsQuery query, IUserDataManager userDataManager)
  483. {
  484. if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
  485. {
  486. return false;
  487. }
  488. if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
  489. {
  490. return false;
  491. }
  492. if (query.Filter != null && !query.Filter(item, user))
  493. {
  494. return false;
  495. }
  496. UserItemData userData = null;
  497. if (query.IsFavorite.HasValue)
  498. {
  499. userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
  500. if (userData.IsFavorite != query.IsFavorite.Value)
  501. {
  502. return false;
  503. }
  504. }
  505. if (query.IsResumable.HasValue)
  506. {
  507. userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
  508. var isResumable = userData.PlaybackPositionTicks > 0;
  509. if (isResumable != query.IsResumable.Value)
  510. {
  511. return false;
  512. }
  513. }
  514. if (query.IsPlayed.HasValue)
  515. {
  516. if (item.IsPlayed(user) != query.IsPlayed.Value)
  517. {
  518. return false;
  519. }
  520. }
  521. return true;
  522. }
  523. private IEnumerable<Folder> GetMediaFolders(User user)
  524. {
  525. var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
  526. return user.RootFolder
  527. .GetChildren(user, true, true)
  528. .OfType<Folder>()
  529. .Where(i => !excludeFolderIds.Contains(i.Id) && !UserView.IsExcludedFromGrouping(i));
  530. }
  531. private IEnumerable<Folder> GetMediaFolders(User user, string[] viewTypes)
  532. {
  533. return GetMediaFolders(user)
  534. .Where(i =>
  535. {
  536. var folder = i as ICollectionFolder;
  537. return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
  538. });
  539. }
  540. private IEnumerable<Folder> GetMediaFolders(Folder parent, User user, string[] viewTypes)
  541. {
  542. if (parent == null || parent is UserView)
  543. {
  544. return GetMediaFolders(user, viewTypes);
  545. }
  546. return new[] { parent };
  547. }
  548. private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, string[] viewTypes)
  549. {
  550. if (parent == null || parent is UserView)
  551. {
  552. return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user));
  553. }
  554. return parent.GetRecursiveChildren(user);
  555. }
  556. private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user)
  557. {
  558. var list = new List<BaseItem>();
  559. list.Add(await _userViewManager.GetUserView("livetv", CollectionType.LiveTvNowPlaying, user, "0", CancellationToken.None).ConfigureAwait(false));
  560. list.Add(await _userViewManager.GetUserView("livetv", CollectionType.LiveTvChannels, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
  561. list.Add(await _userViewManager.GetUserView("livetv", CollectionType.LiveTvRecordingGroups, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
  562. return list;
  563. }
  564. private async Task<UserView> GetUserView(string category, string type, User user, string sortName, Folder parent)
  565. {
  566. var view = await _userViewManager.GetUserView(category, type, user, sortName, CancellationToken.None)
  567. .ConfigureAwait(false);
  568. if (parent.Id != view.ParentId)
  569. {
  570. view.ParentId = parent.Id;
  571. await view.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None)
  572. .ConfigureAwait(false);
  573. }
  574. return view;
  575. }
  576. }
  577. }