< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Entities.UserViewBuilder
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Entities/UserViewBuilder.cs
Line coverage
12%
Covered lines: 54
Uncovered lines: 389
Coverable lines: 443
Total lines: 1011
Line coverage: 12.1%
Branch coverage
30%
Covered branches: 85
Total branches: 282
Branch coverage: 30.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Entities/UserViewBuilder.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Globalization;
 8using System.Linq;
 9using Jellyfin.Data;
 10using Jellyfin.Data.Enums;
 11using Jellyfin.Database.Implementations.Entities;
 12using Jellyfin.Database.Implementations.Enums;
 13using Jellyfin.Extensions;
 14using MediaBrowser.Controller.Library;
 15using MediaBrowser.Controller.TV;
 16using MediaBrowser.Model.Entities;
 17using MediaBrowser.Model.Querying;
 18using Microsoft.Extensions.Logging;
 19using Episode = MediaBrowser.Controller.Entities.TV.Episode;
 20using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
 21using Series = MediaBrowser.Controller.Entities.TV.Series;
 22
 23namespace MediaBrowser.Controller.Entities
 24{
 25    public class UserViewBuilder
 26    {
 27        private readonly IUserViewManager _userViewManager;
 28        private readonly ILibraryManager _libraryManager;
 29        private readonly ILogger<BaseItem> _logger;
 30        private readonly IUserDataManager _userDataManager;
 31        private readonly ITVSeriesManager _tvSeriesManager;
 32
 33        public UserViewBuilder(
 34            IUserViewManager userViewManager,
 35            ILibraryManager libraryManager,
 36            ILogger<BaseItem> logger,
 37            IUserDataManager userDataManager,
 38            ITVSeriesManager tvSeriesManager)
 39        {
 040            _userViewManager = userViewManager;
 041            _libraryManager = libraryManager;
 042            _logger = logger;
 043            _userDataManager = userDataManager;
 044            _tvSeriesManager = tvSeriesManager;
 045        }
 46
 47        public QueryResult<BaseItem> GetUserItems(Folder queryParent, Folder displayParent, CollectionType? viewType, In
 48        {
 049            var user = query.User;
 50
 51            // if (query.IncludeItemTypes is not null &&
 52            //    query.IncludeItemTypes.Length == 1 &&
 53            //    string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
 54            // {
 55            //    if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
 56            //    {
 57            //        return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
 58            //    }
 59            // }
 60
 61            switch (viewType)
 62            {
 63                case CollectionType.folders:
 064                    return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), query);
 65
 66                case CollectionType.tvshows:
 067                    return GetTvView(queryParent, user, query);
 68
 69                case CollectionType.movies:
 070                    return GetMovieFolders(queryParent, user, query);
 71
 72                case CollectionType.tvshowseries:
 073                    return GetTvSeries(queryParent, user, query);
 74
 75                case CollectionType.tvgenres:
 076                    return GetTvGenres(queryParent, user, query);
 77
 78                case CollectionType.tvgenre:
 079                    return GetTvGenreItems(queryParent, displayParent, user, query);
 80
 81                case CollectionType.tvresume:
 082                    return GetTvResume(queryParent, user, query);
 83
 84                case CollectionType.tvnextup:
 085                    return GetTvNextUp(queryParent, query);
 86
 87                case CollectionType.tvlatest:
 088                    return GetTvLatest(queryParent, user, query);
 89
 90                case CollectionType.moviefavorites:
 091                    return GetFavoriteMovies(queryParent, user, query);
 92
 93                case CollectionType.movielatest:
 094                    return GetMovieLatest(queryParent, user, query);
 95
 96                case CollectionType.moviegenres:
 097                    return GetMovieGenres(queryParent, user, query);
 98
 99                case CollectionType.moviegenre:
 0100                    return GetMovieGenreItems(queryParent, displayParent, user, query);
 101
 102                case CollectionType.movieresume:
 0103                    return GetMovieResume(queryParent, user, query);
 104
 105                case CollectionType.moviemovies:
 0106                    return GetMovieMovies(queryParent, user, query);
 107
 108                case CollectionType.moviecollection:
 0109                    return GetMovieCollections(user, query);
 110
 111                case CollectionType.tvfavoriteepisodes:
 0112                    return GetFavoriteEpisodes(queryParent, user, query);
 113
 114                case CollectionType.tvfavoriteseries:
 0115                    return GetFavoriteSeries(queryParent, user, query);
 116
 117                default:
 118                    {
 0119                        if (queryParent is UserView)
 120                        {
 0121                            return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, 
 122                        }
 123
 0124                        return queryParent.GetItems(query);
 125                    }
 126            }
 127        }
 128
 129        private int GetSpecialItemsLimit()
 130        {
 0131            return 50;
 132        }
 133
 134        private QueryResult<BaseItem> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
 135        {
 0136            if (query.Recursive)
 137            {
 0138                query.Recursive = true;
 0139                query.SetUser(user);
 140
 0141                if (query.IncludeItemTypes.Length == 0)
 142                {
 0143                    query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 144                }
 145
 0146                return parent.QueryRecursive(query);
 147            }
 148
 0149            var list = new List<BaseItem>
 0150            {
 0151                GetUserView(CollectionType.movieresume, "HeaderContinueWatching", "0", parent),
 0152                GetUserView(CollectionType.movielatest, "Latest", "1", parent),
 0153                GetUserView(CollectionType.moviemovies, "Movies", "2", parent),
 0154                GetUserView(CollectionType.moviecollection, "Collections", "3", parent),
 0155                GetUserView(CollectionType.moviefavorites, "Favorites", "4", parent),
 0156                GetUserView(CollectionType.moviegenres, "Genres", "5", parent)
 0157            };
 158
 0159            return GetResult(list, query);
 160        }
 161
 162        private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query)
 163        {
 0164            query.Recursive = true;
 0165            query.Parent = parent;
 0166            query.SetUser(user);
 0167            query.IsFavorite = true;
 0168            query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 169
 0170            return _libraryManager.GetItemsResult(query);
 171        }
 172
 173        private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, InternalItemsQuery query)
 174        {
 0175            query.Recursive = true;
 0176            query.Parent = parent;
 0177            query.SetUser(user);
 0178            query.IsFavorite = true;
 0179            query.IncludeItemTypes = new[] { BaseItemKind.Series };
 180
 0181            return _libraryManager.GetItemsResult(query);
 182        }
 183
 184        private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, InternalItemsQuery query)
 185        {
 0186            query.Recursive = true;
 0187            query.Parent = parent;
 0188            query.SetUser(user);
 0189            query.IsFavorite = true;
 0190            query.IncludeItemTypes = new[] { BaseItemKind.Episode };
 191
 0192            return _libraryManager.GetItemsResult(query);
 193        }
 194
 195        private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
 196        {
 0197            query.Recursive = true;
 0198            query.Parent = parent;
 0199            query.SetUser(user);
 200
 0201            query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 202
 0203            return _libraryManager.GetItemsResult(query);
 204        }
 205
 206        private QueryResult<BaseItem> GetMovieCollections(User user, InternalItemsQuery query)
 207        {
 0208            query.Parent = null;
 0209            query.IncludeItemTypes = new[] { BaseItemKind.BoxSet };
 0210            query.SetUser(user);
 0211            query.Recursive = true;
 212
 0213            return _libraryManager.GetItemsResult(query);
 214        }
 215
 216        private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query)
 217        {
 0218            query.OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Desc
 0219            query.Recursive = true;
 0220            query.Parent = parent;
 0221            query.SetUser(user);
 0222            query.Limit = GetSpecialItemsLimit();
 0223            query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 224
 0225            return ConvertToResult(_libraryManager.GetItemList(query));
 226        }
 227
 228        private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
 229        {
 0230            query.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Desce
 0231            query.IsResumable = true;
 0232            query.Recursive = true;
 0233            query.Parent = parent;
 0234            query.SetUser(user);
 0235            query.Limit = GetSpecialItemsLimit();
 0236            query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 237
 0238            return ConvertToResult(_libraryManager.GetItemList(query));
 239        }
 240
 241        private QueryResult<BaseItem> ConvertToResult(IReadOnlyList<BaseItem> items)
 242        {
 0243            return new QueryResult<BaseItem>(items);
 244        }
 245
 246        private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
 247        {
 0248            var genres = parent.QueryRecursive(new InternalItemsQuery(user)
 0249            {
 0250                IncludeItemTypes = new[] { BaseItemKind.Movie },
 0251                Recursive = true,
 0252                EnableTotalRecordCount = false
 0253            }).Items
 0254                .SelectMany(i => i.Genres)
 0255                .DistinctNames()
 0256                .Select(i =>
 0257                {
 0258                    try
 0259                    {
 0260                        return _libraryManager.GetGenre(i);
 0261                    }
 0262                    catch (Exception ex)
 0263                    {
 0264                        _logger.LogError(ex, "Error getting genre");
 0265                        return null;
 0266                    }
 0267                })
 0268                .Where(i => i is not null)
 0269                .Select(i => GetUserViewWithName(CollectionType.moviegenre, i.SortName, parent));
 270
 0271            return GetResult(genres, query);
 272        }
 273
 274        private QueryResult<BaseItem> GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalIt
 275        {
 0276            query.Recursive = true;
 0277            query.Parent = queryParent;
 0278            query.GenreIds = new[] { displayParent.Id };
 0279            query.SetUser(user);
 280
 0281            query.IncludeItemTypes = new[] { BaseItemKind.Movie };
 282
 0283            return _libraryManager.GetItemsResult(query);
 284        }
 285
 286        private QueryResult<BaseItem> GetTvView(Folder parent, User user, InternalItemsQuery query)
 287        {
 0288            if (query.Recursive)
 289            {
 0290                query.Recursive = true;
 0291                query.SetUser(user);
 292
 0293                if (query.IncludeItemTypes.Length == 0)
 294                {
 0295                    query.IncludeItemTypes = new[]
 0296                    {
 0297                        BaseItemKind.Series,
 0298                        BaseItemKind.Season,
 0299                        BaseItemKind.Episode
 0300                    };
 301                }
 302
 0303                return parent.QueryRecursive(query);
 304            }
 305
 0306            var list = new List<BaseItem>
 0307            {
 0308                GetUserView(CollectionType.tvresume, "HeaderContinueWatching", "0", parent),
 0309                GetUserView(CollectionType.tvnextup, "HeaderNextUp", "1", parent),
 0310                GetUserView(CollectionType.tvlatest, "Latest", "2", parent),
 0311                GetUserView(CollectionType.tvshowseries, "Shows", "3", parent),
 0312                GetUserView(CollectionType.tvfavoriteseries, "HeaderFavoriteShows", "4", parent),
 0313                GetUserView(CollectionType.tvfavoriteepisodes, "HeaderFavoriteEpisodes", "5", parent),
 0314                GetUserView(CollectionType.tvgenres, "Genres", "6", parent)
 0315            };
 316
 0317            return GetResult(list, query);
 318        }
 319
 320        private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
 321        {
 0322            query.OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Desc
 0323            query.Recursive = true;
 0324            query.Parent = parent;
 0325            query.SetUser(user);
 0326            query.Limit = GetSpecialItemsLimit();
 0327            query.IncludeItemTypes = new[] { BaseItemKind.Episode };
 0328            query.IsVirtualItem = false;
 329
 0330            return ConvertToResult(_libraryManager.GetItemList(query));
 331        }
 332
 333        private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
 334        {
 0335            var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.tvshows });
 336
 0337            var result = _tvSeriesManager.GetNextUp(
 0338                new NextUpQuery
 0339                {
 0340                    Limit = query.Limit,
 0341                    StartIndex = query.StartIndex,
 0342                    User = query.User
 0343                },
 0344                parentFolders,
 0345                query.DtoOptions);
 346
 0347            return result;
 348        }
 349
 350        private QueryResult<BaseItem> GetTvResume(Folder parent, User user, InternalItemsQuery query)
 351        {
 0352            query.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Desce
 0353            query.IsResumable = true;
 0354            query.Recursive = true;
 0355            query.Parent = parent;
 0356            query.SetUser(user);
 0357            query.Limit = GetSpecialItemsLimit();
 0358            query.IncludeItemTypes = new[] { BaseItemKind.Episode };
 359
 0360            return ConvertToResult(_libraryManager.GetItemList(query));
 361        }
 362
 363        private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query)
 364        {
 0365            query.Recursive = true;
 0366            query.Parent = parent;
 0367            query.SetUser(user);
 368
 0369            query.IncludeItemTypes = new[] { BaseItemKind.Series };
 370
 0371            return _libraryManager.GetItemsResult(query);
 372        }
 373
 374        private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, InternalItemsQuery query)
 375        {
 0376            var genres = parent.QueryRecursive(new InternalItemsQuery(user)
 0377            {
 0378                IncludeItemTypes = new[] { BaseItemKind.Series },
 0379                Recursive = true,
 0380                EnableTotalRecordCount = false
 0381            }).Items
 0382                .SelectMany(i => i.Genres)
 0383                .DistinctNames()
 0384                .Select(i =>
 0385                {
 0386                    try
 0387                    {
 0388                        return _libraryManager.GetGenre(i);
 0389                    }
 0390                    catch (Exception ex)
 0391                    {
 0392                        _logger.LogError(ex, "Error getting genre");
 0393                        return null;
 0394                    }
 0395                })
 0396                .Where(i => i is not null)
 0397                .Select(i => GetUserViewWithName(CollectionType.tvgenre, i.SortName, parent));
 398
 0399            return GetResult(genres, query);
 400        }
 401
 402        private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItems
 403        {
 0404            query.Recursive = true;
 0405            query.Parent = queryParent;
 0406            query.GenreIds = new[] { displayParent.Id };
 0407            query.SetUser(user);
 408
 0409            query.IncludeItemTypes = new[] { BaseItemKind.Series };
 410
 0411            return _libraryManager.GetItemsResult(query);
 412        }
 413
 414        private QueryResult<BaseItem> GetResult<T>(
 415            IEnumerable<T> items,
 416            InternalItemsQuery query)
 417            where T : BaseItem
 418        {
 0419            items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
 420
 0421            return PostFilterAndSort(items, null, query, _libraryManager);
 422        }
 423
 424        public static bool FilterItem(BaseItem item, InternalItemsQuery query)
 425        {
 10426            return Filter(item, query.User, query, BaseItem.UserDataManager, BaseItem.LibraryManager);
 427        }
 428
 429        public static QueryResult<BaseItem> PostFilterAndSort(
 430            IEnumerable<BaseItem> items,
 431            int? totalRecordLimit,
 432            InternalItemsQuery query,
 433            ILibraryManager libraryManager)
 434        {
 435            // This must be the last filter
 0436            if (!query.AdjacentTo.IsNullOrEmpty())
 437            {
 0438                items = FilterForAdjacency(items.ToList(), query.AdjacentTo.Value);
 439            }
 440
 0441            return SortAndPage(items, totalRecordLimit, query, libraryManager);
 442        }
 443
 444        public static QueryResult<BaseItem> SortAndPage(
 445            IEnumerable<BaseItem> items,
 446            int? totalRecordLimit,
 447            InternalItemsQuery query,
 448            ILibraryManager libraryManager)
 449        {
 0450            if (query.OrderBy.Count > 0)
 451            {
 0452                items = libraryManager.Sort(items, query.User, query.OrderBy);
 453            }
 454
 0455            var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();
 0456            var totalCount = itemsArray.Length;
 457
 0458            if (query.Limit.HasValue)
 459            {
 0460                itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray();
 461            }
 0462            else if (query.StartIndex.HasValue)
 463            {
 0464                itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
 465            }
 466
 0467            return new QueryResult<BaseItem>(
 0468                query.StartIndex,
 0469                totalCount,
 0470                itemsArray);
 471        }
 472
 473        public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, 
 474        {
 10475            if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType))
 476            {
 0477                return false;
 478            }
 479
 10480            if (query.IncludeItemTypes.Length > 0 && !query.IncludeItemTypes.Contains(item.GetBaseItemKind()))
 481            {
 0482                return false;
 483            }
 484
 10485            if (query.ExcludeItemTypes.Length > 0 && query.ExcludeItemTypes.Contains(item.GetBaseItemKind()))
 486            {
 0487                return false;
 488            }
 489
 10490            if (query.IsVirtualItem.HasValue && item.IsVirtualItem != query.IsVirtualItem.Value)
 491            {
 0492                return false;
 493            }
 494
 10495            if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
 496            {
 0497                return false;
 498            }
 499
 10500            UserItemData userData = null;
 501
 10502            if (query.IsLiked.HasValue)
 503            {
 0504                userData = userDataManager.GetUserData(user, item);
 505
 0506                if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value)
 507                {
 0508                    return false;
 509                }
 510            }
 511
 10512            if (query.IsFavoriteOrLiked.HasValue)
 513            {
 0514                userData = userData ?? userDataManager.GetUserData(user, item);
 0515                var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false);
 516
 0517                if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value)
 518                {
 0519                    return false;
 520                }
 521            }
 522
 10523            if (query.IsFavorite.HasValue)
 524            {
 0525                userData = userData ?? userDataManager.GetUserData(user, item);
 526
 0527                if (userData.IsFavorite != query.IsFavorite.Value)
 528                {
 0529                    return false;
 530                }
 531            }
 532
 10533            if (query.IsResumable.HasValue)
 534            {
 0535                userData = userData ?? userDataManager.GetUserData(user, item);
 0536                var isResumable = userData.PlaybackPositionTicks > 0;
 537
 0538                if (isResumable != query.IsResumable.Value)
 539                {
 0540                    return false;
 541                }
 542            }
 543
 10544            if (query.IsPlayed.HasValue)
 545            {
 0546                if (item.IsPlayed(user) != query.IsPlayed.Value)
 547                {
 0548                    return false;
 549                }
 550            }
 551
 552            // Filter by Video3DFormat
 10553            if (query.Is3D.HasValue)
 554            {
 0555                var val = query.Is3D.Value;
 0556                var video = item as Video;
 557
 0558                if (video is null || val != video.Video3DFormat.HasValue)
 559                {
 0560                    return false;
 561                }
 562            }
 563
 564            /*
 565             * fuck - fix this
 566            if (query.IsHD.HasValue)
 567            {
 568                if (item.IsHD != query.IsHD.Value)
 569                {
 570                    return false;
 571                }
 572            }
 573            */
 574
 10575            if (query.IsLocked.HasValue)
 576            {
 0577                var val = query.IsLocked.Value;
 0578                if (item.IsLocked != val)
 579                {
 0580                    return false;
 581                }
 582            }
 583
 10584            if (query.HasOverview.HasValue)
 585            {
 0586                var filterValue = query.HasOverview.Value;
 587
 0588                var hasValue = !string.IsNullOrEmpty(item.Overview);
 589
 0590                if (hasValue != filterValue)
 591                {
 0592                    return false;
 593                }
 594            }
 595
 10596            if (query.HasImdbId.HasValue)
 597            {
 0598                var filterValue = query.HasImdbId.Value;
 599
 0600                var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Imdb));
 601
 0602                if (hasValue != filterValue)
 603                {
 0604                    return false;
 605                }
 606            }
 607
 10608            if (query.HasTmdbId.HasValue)
 609            {
 0610                var filterValue = query.HasTmdbId.Value;
 611
 0612                var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tmdb));
 613
 0614                if (hasValue != filterValue)
 615                {
 0616                    return false;
 617                }
 618            }
 619
 10620            if (query.HasTvdbId.HasValue)
 621            {
 0622                var filterValue = query.HasTvdbId.Value;
 623
 0624                var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tvdb));
 625
 0626                if (hasValue != filterValue)
 627                {
 0628                    return false;
 629                }
 630            }
 631
 10632            if (query.HasOfficialRating.HasValue)
 633            {
 0634                var filterValue = query.HasOfficialRating.Value;
 635
 0636                var hasValue = !string.IsNullOrEmpty(item.OfficialRating);
 637
 0638                if (hasValue != filterValue)
 639                {
 0640                    return false;
 641                }
 642            }
 643
 10644            if (query.IsPlaceHolder.HasValue)
 645            {
 0646                var filterValue = query.IsPlaceHolder.Value;
 647
 0648                var isPlaceHolder = false;
 649
 0650                if (item is ISupportsPlaceHolders hasPlaceHolder)
 651                {
 0652                    isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
 653                }
 654
 0655                if (isPlaceHolder != filterValue)
 656                {
 0657                    return false;
 658                }
 659            }
 660
 10661            if (query.HasSpecialFeature.HasValue)
 662            {
 0663                var filterValue = query.HasSpecialFeature.Value;
 664
 0665                if (item is IHasSpecialFeatures movie)
 666                {
 0667                    var ok = filterValue
 0668                        ? movie.SpecialFeatureIds.Count > 0
 0669                        : movie.SpecialFeatureIds.Count == 0;
 670
 0671                    if (!ok)
 672                    {
 0673                        return false;
 674                    }
 675                }
 676                else
 677                {
 0678                    return false;
 679                }
 680            }
 681
 10682            if (query.HasSubtitles.HasValue)
 683            {
 0684                var val = query.HasSubtitles.Value;
 685
 0686                var video = item as Video;
 687
 0688                if (video is null || val != video.HasSubtitles)
 689                {
 0690                    return false;
 691                }
 692            }
 693
 10694            if (query.HasParentalRating.HasValue)
 695            {
 0696                var val = query.HasParentalRating.Value;
 697
 0698                var rating = item.CustomRating;
 699
 0700                if (string.IsNullOrEmpty(rating))
 701                {
 0702                    rating = item.OfficialRating;
 703                }
 704
 0705                if (val)
 706                {
 0707                    if (string.IsNullOrEmpty(rating))
 708                    {
 0709                        return false;
 710                    }
 711                }
 712                else
 713                {
 0714                    if (!string.IsNullOrEmpty(rating))
 715                    {
 0716                        return false;
 717                    }
 718                }
 719            }
 720
 10721            if (query.HasTrailer.HasValue)
 722            {
 0723                var val = query.HasTrailer.Value;
 0724                var trailerCount = 0;
 725
 0726                if (item is IHasTrailers hasTrailers)
 727                {
 0728                    trailerCount = hasTrailers.GetTrailerCount();
 729                }
 730
 0731                var ok = val ? trailerCount > 0 : trailerCount == 0;
 732
 0733                if (!ok)
 734                {
 0735                    return false;
 736                }
 737            }
 738
 10739            if (query.HasThemeSong.HasValue)
 740            {
 0741                var filterValue = query.HasThemeSong.Value;
 742
 0743                var themeCount = item.GetThemeSongs(user).Count;
 0744                var ok = filterValue ? themeCount > 0 : themeCount == 0;
 745
 0746                if (!ok)
 747                {
 0748                    return false;
 749                }
 750            }
 751
 10752            if (query.HasThemeVideo.HasValue)
 753            {
 0754                var filterValue = query.HasThemeVideo.Value;
 755
 0756                var themeCount = item.GetThemeVideos(user).Count;
 0757                var ok = filterValue ? themeCount > 0 : themeCount == 0;
 758
 0759                if (!ok)
 760                {
 0761                    return false;
 762                }
 763            }
 764
 765            // Apply genre filter
 10766            if (query.Genres.Count > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparison.OrdinalIgnoreC
 767            {
 0768                return false;
 769            }
 770
 771            // Filter by VideoType
 10772            if (query.VideoTypes.Length > 0)
 773            {
 0774                var video = item as Video;
 0775                if (video is null || !query.VideoTypes.Contains(video.VideoType))
 776                {
 0777                    return false;
 778                }
 779            }
 780
 10781            if (query.ImageTypes.Length > 0 && !query.ImageTypes.Any(item.HasImage))
 782            {
 0783                return false;
 784            }
 785
 786            // Apply studio filter
 10787            if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id =>
 10788            {
 10789                var studioItem = libraryManager.GetItemById(id);
 10790                return studioItem is not null && item.Studios.Contains(studioItem.Name, StringComparison.OrdinalIgnoreCa
 10791            }))
 792            {
 0793                return false;
 794            }
 795
 796            // Apply genre filter
 10797            if (query.GenreIds.Count > 0 && !query.GenreIds.Any(id =>
 10798            {
 10799                var genreItem = libraryManager.GetItemById(id);
 10800                return genreItem is not null && item.Genres.Contains(genreItem.Name, StringComparison.OrdinalIgnoreCase)
 10801            }))
 802            {
 0803                return false;
 804            }
 805
 806            // Apply year filter
 10807            if (query.Years.Length > 0)
 808            {
 0809                if (!(item.ProductionYear.HasValue && query.Years.Contains(item.ProductionYear.Value)))
 810                {
 0811                    return false;
 812                }
 813            }
 814
 815            // Apply official rating filter
 10816            if (query.OfficialRatings.Length > 0 && !query.OfficialRatings.Contains(item.OfficialRating ?? string.Empty)
 817            {
 0818                return false;
 819            }
 820
 10821            if (query.ItemIds.Length > 0)
 822            {
 0823                if (!query.ItemIds.Contains(item.Id))
 824                {
 0825                    return false;
 826                }
 827            }
 828
 829            // Apply tag filter
 10830            var tags = query.Tags;
 10831            if (tags.Length > 0)
 832            {
 0833                if (!tags.Any(v => item.Tags.Contains(v, StringComparison.OrdinalIgnoreCase)))
 834                {
 0835                    return false;
 836                }
 837            }
 838
 10839            if (query.MinCommunityRating.HasValue)
 840            {
 0841                var val = query.MinCommunityRating.Value;
 842
 0843                if (!(item.CommunityRating.HasValue && item.CommunityRating >= val))
 844                {
 0845                    return false;
 846                }
 847            }
 848
 10849            if (query.MinCriticRating.HasValue)
 850            {
 0851                var val = query.MinCriticRating.Value;
 852
 0853                if (!(item.CriticRating.HasValue && item.CriticRating >= val))
 854                {
 0855                    return false;
 856                }
 857            }
 858
 10859            if (query.MinIndexNumber.HasValue)
 860            {
 0861                var val = query.MinIndexNumber.Value;
 862
 0863                if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val))
 864                {
 0865                    return false;
 866                }
 867            }
 868
 10869            if (query.MinPremiereDate.HasValue)
 870            {
 0871                var val = query.MinPremiereDate.Value;
 872
 0873                if (!(item.PremiereDate.HasValue && item.PremiereDate.Value >= val))
 874                {
 0875                    return false;
 876                }
 877            }
 878
 10879            if (query.MaxPremiereDate.HasValue)
 880            {
 0881                var val = query.MaxPremiereDate.Value;
 882
 0883                if (!(item.PremiereDate.HasValue && item.PremiereDate.Value <= val))
 884                {
 0885                    return false;
 886                }
 887            }
 888
 10889            if (query.ParentIndexNumber.HasValue)
 890            {
 0891                var filterValue = query.ParentIndexNumber.Value;
 892
 0893                if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value != filterValue)
 894                {
 0895                    return false;
 896                }
 897            }
 898
 10899            if (query.SeriesStatuses.Length > 0)
 900            {
 0901                var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.S
 0902                if (!ok)
 903                {
 0904                    return false;
 905                }
 906            }
 907
 10908            if (query.AiredDuringSeason.HasValue)
 909            {
 0910                var episode = item as Episode;
 911
 0912                if (episode is null)
 913                {
 0914                    return false;
 915                }
 916
 0917                if (!Series.FilterEpisodesBySeason(new[] { episode }, query.AiredDuringSeason.Value, true).Any())
 918                {
 0919                    return false;
 920                }
 921            }
 922
 10923            if (query.ExcludeItemIds.Contains(item.Id))
 924            {
 0925                return false;
 926            }
 927
 10928            return true;
 929        }
 930
 931        private IEnumerable<BaseItem> GetMediaFolders(User user)
 932        {
 0933            if (user is null)
 934            {
 0935                return _libraryManager.RootFolder
 0936                    .Children
 0937                    .OfType<Folder>()
 0938                    .Where(UserView.IsEligibleForGrouping);
 939            }
 940
 0941            return _libraryManager.GetUserRootFolder()
 0942                .GetChildren(user, true)
 0943                .OfType<Folder>()
 0944                .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
 945        }
 946
 947        private BaseItem[] GetMediaFolders(User user, IEnumerable<CollectionType> viewTypes)
 948        {
 0949            if (user is null)
 950            {
 0951                return GetMediaFolders(null)
 0952                    .Where(i =>
 0953                    {
 0954                        var folder = i as ICollectionFolder;
 0955
 0956                        return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value);
 0957                    }).ToArray();
 958            }
 959
 0960            return GetMediaFolders(user)
 0961                .Where(i =>
 0962                {
 0963                    var folder = i as ICollectionFolder;
 0964
 0965                    return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value);
 0966                }).ToArray();
 967        }
 968
 969        private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable<CollectionType> viewTypes)
 970        {
 0971            if (parent is null || parent is UserView)
 972            {
 0973                return GetMediaFolders(user, viewTypes);
 974            }
 975
 0976            return new BaseItem[] { parent };
 977        }
 978
 979        private UserView GetUserViewWithName(CollectionType? type, string sortName, BaseItem parent)
 980        {
 0981            return _userViewManager.GetUserSubView(parent.Id, type, parent.Id.ToString("N", CultureInfo.InvariantCulture
 982        }
 983
 984        private UserView GetUserView(CollectionType? type, string localizationKey, string sortName, BaseItem parent)
 985        {
 0986            return _userViewManager.GetUserSubView(parent.Id, type, localizationKey, sortName);
 987        }
 988
 989        public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, Guid adjacentTo)
 990        {
 0991            var adjacentToItem = list.FirstOrDefault(i => i.Id.Equals(adjacentTo));
 992
 0993            var index = list.IndexOf(adjacentToItem);
 994
 0995            var previousId = Guid.Empty;
 0996            var nextId = Guid.Empty;
 997
 0998            if (index > 0)
 999            {
 01000                previousId = list[index - 1].Id;
 1001            }
 1002
 01003            if (index < list.Count - 1)
 1004            {
 01005                nextId = list[index + 1].Id;
 1006            }
 1007
 01008            return list.Where(i => i.Id.Equals(previousId) || i.Id.Equals(nextId) || i.Id.Equals(adjacentTo));
 1009        }
 1010    }
 1011}

Methods/Properties

.ctor(MediaBrowser.Controller.Library.IUserViewManager,MediaBrowser.Controller.Library.ILibraryManager,Microsoft.Extensions.Logging.ILogger`1<MediaBrowser.Controller.Entities.BaseItem>,MediaBrowser.Controller.Library.IUserDataManager,MediaBrowser.Controller.TV.ITVSeriesManager)
GetUserItems(MediaBrowser.Controller.Entities.Folder,MediaBrowser.Controller.Entities.Folder,System.Nullable`1<Jellyfin.Data.Enums.CollectionType>,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetSpecialItemsLimit()
GetMovieFolders(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetFavoriteMovies(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetFavoriteSeries(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetFavoriteEpisodes(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetMovieMovies(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetMovieCollections(Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetMovieLatest(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetMovieResume(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
ConvertToResult(System.Collections.Generic.IReadOnlyList`1<MediaBrowser.Controller.Entities.BaseItem>)
GetMovieGenres(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetMovieGenreItems(MediaBrowser.Controller.Entities.Folder,MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvView(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvLatest(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvNextUp(MediaBrowser.Controller.Entities.Folder,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvResume(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvSeries(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvGenres(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetTvGenreItems(MediaBrowser.Controller.Entities.Folder,MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetResult(System.Collections.Generic.IEnumerable`1<T>,MediaBrowser.Controller.Entities.InternalItemsQuery)
FilterItem(MediaBrowser.Controller.Entities.BaseItem,MediaBrowser.Controller.Entities.InternalItemsQuery)
PostFilterAndSort(System.Collections.Generic.IEnumerable`1<MediaBrowser.Controller.Entities.BaseItem>,System.Nullable`1<System.Int32>,MediaBrowser.Controller.Entities.InternalItemsQuery,MediaBrowser.Controller.Library.ILibraryManager)
SortAndPage(System.Collections.Generic.IEnumerable`1<MediaBrowser.Controller.Entities.BaseItem>,System.Nullable`1<System.Int32>,MediaBrowser.Controller.Entities.InternalItemsQuery,MediaBrowser.Controller.Library.ILibraryManager)
Filter(MediaBrowser.Controller.Entities.BaseItem,Jellyfin.Database.Implementations.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery,MediaBrowser.Controller.Library.IUserDataManager,MediaBrowser.Controller.Library.ILibraryManager)
GetMediaFolders(Jellyfin.Database.Implementations.Entities.User)
GetMediaFolders(Jellyfin.Database.Implementations.Entities.User,System.Collections.Generic.IEnumerable`1<Jellyfin.Data.Enums.CollectionType>)
GetMediaFolders(MediaBrowser.Controller.Entities.Folder,Jellyfin.Database.Implementations.Entities.User,System.Collections.Generic.IEnumerable`1<Jellyfin.Data.Enums.CollectionType>)
GetUserViewWithName(System.Nullable`1<Jellyfin.Data.Enums.CollectionType>,System.String,MediaBrowser.Controller.Entities.BaseItem)
GetUserView(System.Nullable`1<Jellyfin.Data.Enums.CollectionType>,System.String,System.String,MediaBrowser.Controller.Entities.BaseItem)
FilterForAdjacency(System.Collections.Generic.List`1<MediaBrowser.Controller.Entities.BaseItem>,System.Guid)