Esempio n. 1
0
        /// <summary>
        /// Updates all Group Filters. This should be done as the last step.
        /// </summary>
        /// <remarks>
        /// Assumes that all caches are up to date.
        /// </remarks>
        private void UpdateGroupFilters(ISessionWrapper session)
        {
            _log.Info("Updating Group Filters");
            _log.Info("Calculating Tag Filters");
            ServerState.Instance.DatabaseBlocked = new ServerState.DatabaseBlockedInfo {
                Blocked = true, Status = "Calculating Tag Filters"
            };
            _groupFilterRepo.CalculateAnimeSeriesPerTagGroupFilter(session);
            _log.Info("Calculating All Other Filters");
            ServerState.Instance.DatabaseBlocked = new ServerState.DatabaseBlockedInfo {
                Blocked = true, Status = "Calculating Non-Tag Filters"
            };
            IEnumerable <SVR_GroupFilter> grpFilters = _groupFilterRepo.GetAll(session).Where(a =>
                                                                                              a.FilterType != (int)GroupFilterType.Tag &&
                                                                                              ((GroupFilterType)a.FilterType & GroupFilterType.Directory) == 0).ToList();

            // The main reason for doing this in parallel is because UpdateEntityReferenceStrings does JSON encoding
            // and is enough work that it can benefit from running in parallel
            Parallel.ForEach(
                grpFilters, filter =>
            {
                filter.SeriesIds.Clear();
                filter.CalculateGroupsAndSeries();
                filter.UpdateEntityReferenceStrings();
            });

            using (ITransaction trans = session.BeginTransaction())
            {
                _groupFilterRepo.BatchUpdate(session, grpFilters);
                trans.Commit();
            }

            _log.Info("Group Filters updated");
        }
Esempio n. 2
0
        public void UpdateGroupFilters()
        {
            AnimeGroupRepository  repGroups    = new AnimeGroupRepository();
            AnimeSeriesRepository repSeries    = new AnimeSeriesRepository();
            GroupFilterRepository repGrpFilter = new GroupFilterRepository();
            List <GroupFilter>    gfs          = repGrpFilter.GetAll();
            List <AnimeGroup>     allGrps      = repGroups.GetAllTopLevelGroups(); // No Need of subgroups
            List <AnimeSeries>    allSeries    = repSeries.GetAll();

            foreach (GroupFilter gf in gfs)
            {
                bool change = false;
                foreach (AnimeGroup grp in allGrps)
                {
                    Contract_AnimeGroup cgrp = grp.GetUserContract(this.JMMUserID);
                    change |= gf.CalculateGroupFilterGroups(cgrp, Contract, JMMUserID);
                }
                foreach (AnimeSeries ser in allSeries)
                {
                    Contract_AnimeSeries cser = ser.GetUserContract(this.JMMUserID);
                    change |= gf.CalculateGroupFilterSeries(cser, Contract, JMMUserID);
                }
                if (change)
                {
                    repGrpFilter.Save(gf);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Updates all Group Filters. This should be done as the last step.
        /// </summary>
        /// <remarks>
        /// Assumes that all caches are up to date.
        /// </remarks>
        private void UpdateGroupFilters(ISessionWrapper session)
        {
            _log.Info("Updating Group Filters");

            IReadOnlyList <GroupFilter> grpFilters = _groupFilterRepo.GetAll(session);
            ILookup <int, int>          groupsForTagGroupFilter = _groupFilterRepo.CalculateAnimeGroupsPerTagGroupFilter(session);
            IReadOnlyList <JMMUser>     users = _userRepo.GetAll();

            // The main reason for doing this in parallel is because UpdateEntityReferenceStrings does JSON encoding
            // and is enough work that it can benefit from running in parallel
            Parallel.ForEach(grpFilters.Where(f => ((GroupFilterType)f.FilterType & GroupFilterType.Directory) != GroupFilterType.Directory), filter =>
            {
                var userGroupIds = filter.GroupsIds;

                userGroupIds.Clear();

                if (filter.FilterType == (int)GroupFilterType.Tag)
                {
                    foreach (var user in users)
                    {
                        userGroupIds[user.JMMUserID] = groupsForTagGroupFilter[filter.GroupFilterID].ToHashSet();
                    }
                }
                else     // All other group filters are to be handled normally
                {
                    filter.EvaluateAnimeGroups();
                }

                filter.UpdateEntityReferenceStrings(updateGroups: true, updateSeries: false);
            });

            _groupFilterRepo.BatchUpdate(session, grpFilters);
            _log.Info("Group Filters updated");
        }
        /// <summary>
        /// Updates all Group Filters. This should be done as the last step.
        /// </summary>
        /// <remarks>
        /// Assumes that all caches are up to date.
        /// </remarks>
        private void UpdateGroupFilters(ISessionWrapper session)
        {
            _log.Info("Updating Group Filters");

            IReadOnlyList <SVR_GroupFilter> grpFilters          = _groupFilterRepo.GetAll(session);
            ILookup <int, int>          seriesForTagGroupFilter = _groupFilterRepo.CalculateAnimeSeriesPerTagGroupFilter(session);
            IReadOnlyList <SVR_JMMUser> users = _userRepo.GetAll();

            // The main reason for doing this in parallel is because UpdateEntityReferenceStrings does JSON encoding
            // and is enough work that it can benefit from running in parallel
            Parallel.ForEach(
                grpFilters.Where(f => ((GroupFilterType)f.FilterType & GroupFilterType.Directory) !=
                                 GroupFilterType.Directory), filter =>
            {
                filter.SeriesIds.Clear();

                if (filter.FilterType == (int)GroupFilterType.Tag)
                {
                    filter.SeriesIds[0] = seriesForTagGroupFilter[filter.GroupFilterID].ToHashSet();
                    filter.GroupsIds[0] = filter.SeriesIds[0]
                                          .Select(id => RepoFactory.AnimeSeries.GetByID(id).TopLevelAnimeGroup?.AnimeGroupID ?? -1)
                                          .Where(id => id != -1).ToHashSet();
                    foreach (var user in users)
                    {
                        filter.SeriesIds[user.JMMUserID] = seriesForTagGroupFilter[filter.GroupFilterID]
                                                           .Select(id => RepoFactory.AnimeSeries.GetByID(id))
                                                           .Where(ser =>
                                                                  !(ser.GetAnime()?.GetAllTags()?.FindInEnumerable(user.GetHideCategories()) ??
                                                                    false)).Select(a => a.AnimeSeriesID).ToHashSet();
                        filter.GroupsIds[user.JMMUserID] = filter.SeriesIds[user.JMMUserID]
                                                           .Select(id => RepoFactory.AnimeSeries.GetByID(id).TopLevelAnimeGroup?.AnimeGroupID ?? -1)
                                                           .Where(id => id != -1).ToHashSet();
                    }
                }
                else     // All other group filters are to be handled normally
                {
                    filter.CalculateGroupsAndSeries();
                }

                filter.UpdateEntityReferenceStrings();
            });

            _groupFilterRepo.BatchUpdate(session, grpFilters);
            _log.Info("Group Filters updated");
        }
Esempio n. 5
0
        public void DeleteFromFilters()
        {
            GroupFilterRepository repo = new GroupFilterRepository();

            foreach (GroupFilter gf in repo.GetAll())
            {
                bool change = false;
                if (gf.SeriesIds.ContainsKey(JMMUserID))
                {
                    if (gf.SeriesIds[JMMUserID].Contains(AnimeSeriesID))
                    {
                        gf.SeriesIds[JMMUserID].Remove(AnimeSeriesID);
                        change = true;
                    }
                }
                if (change)
                {
                    repo.Save(gf);
                }
            }
        }
Esempio n. 6
0
        private static void CreateInitialGroupFilters()
        {
            // group filters
            GroupFilterRepository          repFilters = new GroupFilterRepository();
            GroupFilterConditionRepository repGFC     = new GroupFilterConditionRepository();

            if (repFilters.GetAll().Count() > 0)
            {
                return;
            }

            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(ServerSettings.Culture);

            // Favorites
            GroupFilter gf = new GroupFilter();

            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_Favorites;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            GroupFilterCondition gfc = new GroupFilterCondition();

            gfc.ConditionType      = (int)GroupFilterConditionType.Favourite;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);

            // Missing Episodes
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_MissingEpisodes;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.MissingEpisodesCollecting;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);


            // Newly Added Series
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_Added;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.SeriesCreatedDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "10";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);

            // Newly Airing Series
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_Airing;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.AirDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "30";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);

            // Votes Needed
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_Votes;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.CompletedSeries;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.HasUnwatchedEpisodes;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.UserVotedAny;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);

            // Recently Watched
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_RecentlyWatched;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.EpisodeWatchedDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "10";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);

            // TvDB/MovieDB Link Missing
            gf = new GroupFilter();
            gf.GroupFilterName = JMMServer.Properties.Resources.Filter_LinkMissing;
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;
            gf.Locked          = 0;
            gf.FilterType      = (int)GroupFilterType.UserDefined;
            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.AssignedTvDBOrMovieDBInfo;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gf.Conditions.Add(gfc);
            gf.EvaluateAnimeGroups();
            gf.EvaluateAnimeSeries();
            repFilters.Save(gf);
        }
        public System.IO.Stream GetFilters(string uid)
        {
            JMMUser user = KodiHelper.GetUser(uid);

            if (user == null)
            {
                return(new MemoryStream());
            }
            int        userid = user.JMMUserID;
            KodiObject ret    = new KodiObject(KodiHelper.NewMediaContainer("Anime", false));

            if (!ret.Init())
            {
                return(new MemoryStream());
            }
            List <Video> dirs = new List <Video>();

            try
            {
                using (var session = JMMService.SessionFactory.OpenSession())
                {
                    GroupFilterRepository            repGF  = new GroupFilterRepository();
                    List <GroupFilter>               allGfs = repGF.GetAll(session);
                    Dictionary <int, HashSet <int> > gstats = StatsCache.Instance.StatUserGroupFilter[userid];
                    foreach (GroupFilter gg in allGfs.ToArray())
                    {
                        if ((!StatsCache.Instance.StatUserGroupFilter.ContainsKey(userid)) ||
                            (!StatsCache.Instance.StatUserGroupFilter[userid].ContainsKey(gg.GroupFilterID)))
                        {
                            allGfs.Remove(gg);
                        }
                    }


                    AnimeGroupRepository repGroups = new AnimeGroupRepository();
                    allGfs.Insert(0, new GroupFilter()
                    {
                        GroupFilterName = "All", GroupFilterID = -999
                    });
                    foreach (GroupFilter gg in allGfs)
                    {
                        Random    rnd = new Random(123456789);
                        Directory pp  = new Directory();
                        pp.Key = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort),
                                                      MainWindow.PathAddressKodi + "/GetMetadata/" + userid + "/" +
                                                      (int)JMMType.GroupFilter + "/" + gg.GroupFilterID);
                        pp.PrimaryExtraKey = pp.Key;
                        pp.Title           = gg.GroupFilterName;
                        HashSet <int> groups;
                        groups = gg.GroupFilterID == -999 ? new HashSet <int>(repGroups.GetAllTopLevelGroups(session).Select(a => a.AnimeGroupID)) : gstats[gg.GroupFilterID];
                        if (groups.Count != 0)
                        {
                            bool repeat;
                            int  nn = 0;
                            pp.LeafCount       = groups.Count.ToString();
                            pp.ViewedLeafCount = "0";
                            do
                            {
                                repeat = true;
                                int                grp  = groups.ElementAt(rnd.Next(groups.Count));
                                AnimeGroup         ag   = repGroups.GetByID(grp);
                                List <AnimeSeries> sers = ag.GetSeries(session);
                                if (sers.Count > 0)
                                {
                                    AnimeSeries ser  = sers[rnd.Next(sers.Count)];
                                    AniDB_Anime anim = ser.GetAnime(session);
                                    if (anim != null)
                                    {
                                        ImageDetails poster = anim.GetDefaultPosterDetailsNoBlanks(session);
                                        ImageDetails fanart = anim.GetDefaultFanartDetailsNoBlanks(session);
                                        if (poster != null)
                                        {
                                            pp.Thumb = poster.GenPoster();
                                        }
                                        if (fanart != null)
                                        {
                                            pp.Art = fanart.GenArt();
                                        }
                                        if (poster != null)
                                        {
                                            repeat = false;
                                        }
                                    }
                                }
                                nn++;
                                if ((repeat) && (nn == 15))
                                {
                                    repeat = false;
                                }
                            } while (repeat);
                            dirs.Add(pp);
                        }
                    }
                    VideoLocalRepository repVids = new VideoLocalRepository();
                    List <VideoLocal>    vids    = repVids.GetVideosWithoutEpisode();
                    if (vids.Count > 0)
                    {
                        JMMContracts.KodiContracts.Directory pp = new JMMContracts.KodiContracts.Directory();
                        pp.Key = pp.PrimaryExtraKey = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort),
                                                                           MainWindow.PathAddressKodi + "/GetMetadata/0/" + (int)JMMType.GroupUnsort + "/0");
                        pp.Title = "Unsort";
                        pp.Thumb = KodiHelper.ServerUrl(int.Parse(ServerSettings.JMMServerPort),
                                                        MainWindow.PathAddressKodi + "/GetSupportImage/plex_unsort.png");
                        pp.LeafCount       = vids.Count.ToString();
                        pp.ViewedLeafCount = "0";
                        dirs.Add(pp);
                    }
                    dirs = dirs.OrderBy(a => a.Title).ToList();
                }
                ret.Childrens = dirs;
                return(ret.GetStream());
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return(new MemoryStream());
            }
        }
Esempio n. 8
0
        private static void CreateInitialGroupFilters()
        {
            // group filters
            GroupFilterRepository          repFilters = new GroupFilterRepository();
            GroupFilterConditionRepository repGFC     = new GroupFilterConditionRepository();

            if (repFilters.GetAll().Count() > 0)
            {
                return;
            }

            // Favorites
            GroupFilter gf = new GroupFilter();

            gf.GroupFilterName = "Favorites";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            GroupFilterCondition gfc = new GroupFilterCondition();

            gfc.ConditionType      = (int)GroupFilterConditionType.Favourite;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);



            // Missing Episodes
            gf = new GroupFilter();
            gf.GroupFilterName = "Missing Episodes";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.MissingEpisodesCollecting;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            // Newly Added Series
            gf = new GroupFilter();
            gf.GroupFilterName = "Newly Added Series";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.SeriesCreatedDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "10";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            // Newly Airing Series
            gf = new GroupFilter();
            gf.GroupFilterName = "Newly Airing Series";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.AirDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "30";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            // Votes Needed
            gf = new GroupFilter();
            gf.GroupFilterName = "Votes Needed";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.CompletedSeries;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Include;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.HasUnwatchedEpisodes;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.UserVotedAny;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            // Recently Watched
            gf = new GroupFilter();
            gf.GroupFilterName = "Recently Watched";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.EpisodeWatchedDate;
            gfc.ConditionOperator  = (int)GroupFilterOperator.LastXDays;
            gfc.ConditionParameter = "10";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);

            // TvDB/MovieDB Link Missing
            gf = new GroupFilter();
            gf.GroupFilterName = "TvDB/MovieDB Link Missing";
            gf.ApplyToSeries   = 0;
            gf.BaseCondition   = 1;

            repFilters.Save(gf);

            gfc = new GroupFilterCondition();
            gfc.ConditionType      = (int)GroupFilterConditionType.AssignedTvDBOrMovieDBInfo;
            gfc.ConditionOperator  = (int)GroupFilterOperator.Exclude;
            gfc.ConditionParameter = "";
            gfc.GroupFilterID      = gf.GroupFilterID;
            repGFC.Save(gfc);
        }
        public System.IO.Stream GetFilters(string uid)
        {
            int t = 0;

            int.TryParse(uid, out t);
            JMMUser user = t > 0 ? PlexHelper.GetJMMUser(uid) : PlexHelper.GetUser(uid);

            if (user == null)
            {
                return(new MemoryStream());
            }
            int         userid = user.JMMUserID;
            HistoryInfo info   = new HistoryInfo {
                Key = PlexHelper.ConstructFiltersUrl(userid), Title = "Anime"
            };
            PlexObject ret = new PlexObject(PlexHelper.NewMediaContainer(MediaContainerTypes.Show, info, false));

            if (!ret.Init())
            {
                return(new MemoryStream());
            }
            List <Video> dirs = new List <Video>();

            try
            {
                using (var session = JMMService.SessionFactory.OpenSession())
                {
                    GroupFilterRepository            repGF  = new GroupFilterRepository();
                    List <GroupFilter>               allGfs = repGF.GetAll(session);
                    Dictionary <int, HashSet <int> > gstats = StatsCache.Instance.StatUserGroupFilter[userid];
                    foreach (GroupFilter gg in allGfs.ToArray())
                    {
                        if ((!StatsCache.Instance.StatUserGroupFilter.ContainsKey(userid)) ||
                            (!StatsCache.Instance.StatUserGroupFilter[userid].ContainsKey(gg.GroupFilterID)))
                        {
                            allGfs.Remove(gg);
                        }
                    }


                    AnimeGroupRepository repGroups = new AnimeGroupRepository();
                    allGfs.Insert(0, new GroupFilter()
                    {
                        GroupFilterName = "All", GroupFilterID = -999
                    });
                    foreach (GroupFilter gg in allGfs)
                    {
                        Random    rnd = new Random(123456789);
                        Directory pp  = new Directory {
                            Type = "show"
                        };
                        pp.Key   = PlexHelper.ConstructFilterIdUrl(userid, gg.GroupFilterID);
                        pp.Title = gg.GroupFilterName;
                        HashSet <int> groups;
                        groups = gg.GroupFilterID == -999 ? new HashSet <int>(repGroups.GetAllTopLevelGroups(session).Select(a => a.AnimeGroupID)) : gstats[gg.GroupFilterID];
                        if (groups.Count != 0)
                        {
                            bool repeat;
                            int  nn = 0;
                            pp.LeafCount       = groups.Count.ToString();
                            pp.ViewedLeafCount = "0";
                            do
                            {
                                repeat = true;
                                int                grp  = groups.ElementAt(rnd.Next(groups.Count));
                                AnimeGroup         ag   = repGroups.GetByID(grp);
                                List <AnimeSeries> sers = ag.GetSeries(session);
                                if (sers.Count > 0)
                                {
                                    AnimeSeries ser  = sers[rnd.Next(sers.Count)];
                                    AniDB_Anime anim = ser.GetAnime(session);
                                    if (anim != null)
                                    {
                                        ImageDetails poster = anim.GetDefaultPosterDetailsNoBlanks(session);
                                        ImageDetails fanart = anim.GetDefaultFanartDetailsNoBlanks(session);
                                        if (poster != null)
                                        {
                                            pp.Thumb = poster.GenPoster();
                                        }
                                        if (fanart != null)
                                        {
                                            pp.Art = fanart.GenArt();
                                        }
                                        if (poster != null)
                                        {
                                            repeat = false;
                                        }
                                    }
                                }
                                nn++;
                                if ((repeat) && (nn == 15))
                                {
                                    repeat = false;
                                }
                            } while (repeat);
                            dirs.Add(pp, info);
                        }
                    }
                    VideoLocalRepository repVids = new VideoLocalRepository();
                    List <VideoLocal>    vids    = repVids.GetVideosWithoutEpisode();
                    if (vids.Count > 0)
                    {
                        Directory pp = new Directory()
                        {
                            Type = "show"
                        };
                        pp.Key             = PlexHelper.ConstructUnsortUrl(userid);
                        pp.Title           = "Unsort";
                        pp.Thumb           = PlexHelper.ConstructSupportImageLink("plex_unsort.png");
                        pp.LeafCount       = vids.Count.ToString();
                        pp.ViewedLeafCount = "0";
                        dirs.Add(pp, info);
                    }
                    var repPlaylist = new PlaylistRepository();
                    var playlists   = repPlaylist.GetAll();
                    if (playlists.Count > 0)
                    {
                        Directory pp = new Directory()
                        {
                            Type = "show"
                        };
                        pp.Key             = PlexHelper.ConstructPlaylistUrl(userid);
                        pp.Title           = "Playlists";
                        pp.Thumb           = PlexHelper.ConstructSupportImageLink("plex_playlists.png");
                        pp.LeafCount       = playlists.Count.ToString();
                        pp.ViewedLeafCount = "0";
                        dirs.Add(pp, info);
                    }
                    dirs = dirs.OrderBy(a => a.Title).ToList();
                }
                ret.Childrens = dirs;
                return(ret.GetStream());
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return(new MemoryStream());
            }
        }