Ejemplo n.º 1
0
        /// <summary>
        /// Creates an <see cref="SVR_AnimeGroup"/> instance.
        /// </summary>
        /// <remarks>
        /// This method only creates an <see cref="SVR_AnimeGroup"/> instance. It does NOT save it to the database.
        /// </remarks>
        /// <param name="session">The NHibernate session.</param>
        /// <param name="mainSeries">The <see cref="SVR_AnimeSeries"/> whose name will represent the group (Optional. Pass <c>null</c> if not available).</param>
        /// <param name="mainAnimeId">The ID of the anime whose name will represent the group if <paramref name="mainSeries"/> is <c>null</c>.</param>
        /// <param name="now">The current date/time.</param>
        /// <returns>The created <see cref="SVR_AnimeGroup"/>.</returns>
        private void CreateAnimeGroup_RA(SVR_AnimeGroup animeGroup_ra, SVR_AnimeSeries mainSeries, int mainAnimeId,
                                         DateTime now)
        {
            SVR_AnimeGroup animeGroup = new SVR_AnimeGroup();
            string         groupName;

            if (mainSeries != null)
            {
                animeGroup.Populate_RA(mainSeries, now);
                groupName = animeGroup.GroupName;
            }
            else // The anime chosen as the group's main anime doesn't actually have a series
            {
                SVR_AniDB_Anime mainAnime = Repo.Instance.AniDB_Anime.GetByID(mainAnimeId);

                animeGroup.Populate_RA(mainAnime, now);
                groupName = animeGroup.GroupName;
            }

            // If the title appears to end with a year suffix, then remove it
            groupName            = _truncateYearRegex.Replace(groupName, string.Empty);
            animeGroup.GroupName = groupName;
            animeGroup.SortName  = groupName;

            return;
        }
Ejemplo n.º 2
0
        public Group(HttpContext ctx, SVR_AnimeGroup group)
        {
            int uid       = ctx.GetUser()?.JMMUserID ?? 0;
            var allSeries = group.GetAllSeries(skipSorting: true);
            List <SVR_AnimeEpisode> ael = allSeries.SelectMany(a => a.GetAnimeEpisodes()).ToList();

            IDs = new GroupIDs {
                ID = group.AnimeGroupID
            };
            if (group.DefaultAnimeSeriesID != null)
            {
                IDs.DefaultSeries = group.DefaultAnimeSeriesID.Value;
            }
            if (group.AnimeGroupParentID.HasValue)
            {
                IDs.ParentGroup = group.AnimeGroupParentID.Value;
            }
            IDs.TopLevelGroup = group.TopLevelAnimeGroup.AnimeGroupID;


            Name        = group.GroupName;
            SortName    = group.SortName;
            Description = group.Description;
            Sizes       = ModelHelper.GenerateSizes(ael, uid);
            Size        = group.GetSeries().Count;

            HasCustomName = GetHasCustomName(group);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a single <see cref="SVR_AnimeGroup"/> for each <see cref="SVR_AnimeSeries"/> in <paramref name="seriesList"/>.
        /// </summary>
        /// <remarks>
        /// This method assumes that there are no active transactions on the specified <paramref name="session"/>.
        /// </remarks>
        /// <param name="session">The NHibernate session.</param>
        /// <param name="seriesList">The list of <see cref="SVR_AnimeSeries"/> to create groups for.</param>
        /// <returns>A sequence of the created <see cref="SVR_AnimeGroup"/>s.</returns>
        private IEnumerable <SVR_AnimeGroup> CreateGroupPerSeries(ISessionWrapper session,
                                                                  IReadOnlyList <SVR_AnimeSeries> seriesList)
        {
            _log.Info("Generating AnimeGroups for {0} AnimeSeries", seriesList.Count);

            DateTime now = DateTime.Now;
            var      newGroupsToSeries = new Tuple <SVR_AnimeGroup, SVR_AnimeSeries> [seriesList.Count];

            // Create one group per series
            for (int grp = 0; grp < seriesList.Count; grp++)
            {
                SVR_AnimeGroup  group  = new SVR_AnimeGroup();
                SVR_AnimeSeries series = seriesList[grp];

                @group.Populate(series, now);
                newGroupsToSeries[grp] = new Tuple <SVR_AnimeGroup, SVR_AnimeSeries>(group, series);
            }

            using (ITransaction trans = session.BeginTransaction())
            {
                _animeGroupRepo.InsertBatch(session, newGroupsToSeries.Select(gts => gts.Item1).AsReadOnlyCollection());
                trans.Commit();
            }

            // Anime groups should have IDs now they've been inserted. Now assign the group ID's to their respective series
            // (The caller of this method will be responsible for saving the AnimeSeries)
            foreach (Tuple <SVR_AnimeGroup, SVR_AnimeSeries> groupAndSeries in newGroupsToSeries)
            {
                groupAndSeries.Item2.AnimeGroupID = groupAndSeries.Item1.AnimeGroupID;
            }

            _log.Info("Generated {0} AnimeGroups", newGroupsToSeries.Length);

            return(newGroupsToSeries.Select(gts => gts.Item1));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates an <see cref="SVR_AnimeGroup"/> instance.
        /// </summary>
        /// <remarks>
        /// This method only creates an <see cref="SVR_AnimeGroup"/> instance. It does NOT save it to the database.
        /// </remarks>
        /// <param name="session">The NHibernate session.</param>
        /// <param name="mainSeries">The <see cref="SVR_AnimeSeries"/> whose name will represent the group (Optional. Pass <c>null</c> if not available).</param>
        /// <param name="mainAnimeId">The ID of the anime whose name will represent the group if <paramref name="mainSeries"/> is <c>null</c>.</param>
        /// <param name="now">The current date/time.</param>
        /// <returns>The created <see cref="SVR_AnimeGroup"/>.</returns>
        private SVR_AnimeGroup CreateAnimeGroup(SVR_AnimeSeries mainSeries, int mainAnimeId,
                                                DateTime now)
        {
            SVR_AnimeGroup animeGroup = new SVR_AnimeGroup();
            string         groupName  = null;

            if (mainSeries != null)
            {
                animeGroup.Populate(mainSeries, now);
                groupName = mainSeries.GetSeriesName();
            }
            else // The anime chosen as the group's main anime doesn't actually have a series
            {
                SVR_AniDB_Anime mainAnime = _aniDbAnimeRepo.GetByAnimeID(mainAnimeId);

                animeGroup.Populate(mainAnime, now);
                groupName = mainAnime.GetFormattedTitle();
            }

            groupName =
                _truncateYearRegex.Replace(groupName,
                                           String.Empty); // If the title appears to end with a year suffix, then remove it
            animeGroup.GroupName = groupName;
            animeGroup.SortName  = groupName;

            return(animeGroup);
        }
Ejemplo n.º 5
0
 private AnimeSeriesRepository()
 {
     BeginDeleteCallback = (cr) =>
     {
         RepoFactory.AnimeSeries_User.Delete(RepoFactory.AnimeSeries_User.GetBySeriesID(cr.AnimeSeriesID));
         lock (Changes)
         {
             Changes.Remove(cr.AnimeSeriesID);
         }
     };
     EndDeleteCallback = (cr) =>
     {
         cr.DeleteFromFilters();
         if (cr.AnimeGroupID > 0)
         {
             logger.Trace("Updating group stats by group from AnimeSeriesRepository.Delete: {0}",
                          cr.AnimeGroupID);
             SVR_AnimeGroup oldGroup = RepoFactory.AnimeGroup.GetByID(cr.AnimeGroupID);
             if (oldGroup != null)
             {
                 RepoFactory.AnimeGroup.Save(oldGroup, true, true);
             }
         }
     };
 }
Ejemplo n.º 6
0
        private void UpdateAnimeGroupsAndTheirContracts(ISessionWrapper session,
                                                        IReadOnlyCollection <SVR_AnimeGroup> groups)
        {
            ServerState.Instance.DatabaseBlocked = new ServerState.DatabaseBlockedInfo {
                Blocked = true, Status = "Updating statistics and contracts for AnimeGroups"
            };
            _log.Info("Updating statistics and contracts for AnimeGroups");

            var allCreatedGroupUsers = new ConcurrentBag <List <SVR_AnimeGroup_User> >();

            // Update batches of AnimeGroup contracts in parallel. Each parallel branch requires it's own session since NHibernate sessions aren't thread safe.
            // The reason we're doing this in parallel is because updating contacts does a reasonable amount of work (including LZ4 compression)
            Parallel.ForEach(groups.Batch(DefaultBatchSize), new ParallelOptions {
                MaxDegreeOfParallelism = 4
            },
                             localInit: () => DatabaseFactory.SessionFactory.OpenStatelessSession(),
                             body: (groupBatch, state, localSession) =>
            {
                var createdGroupUsers = new List <SVR_AnimeGroup_User>(groupBatch.Length);

                // We shouldn't need to keep track of updates to AnimeGroup_Users in the below call, because they should have all been deleted,
                // therefore they should all be new
                SVR_AnimeGroup.BatchUpdateStats(groupBatch, watchedStats: true, missingEpsStats: true,
                                                createdGroupUsers: createdGroupUsers);
                allCreatedGroupUsers.Add(createdGroupUsers);
                SVR_AnimeGroup.BatchUpdateContracts(localSession.Wrap(), groupBatch, updateStats: true);

                return(localSession);
            },
                             localFinally: localSession => { localSession.Dispose(); });

            _animeGroupRepo.UpdateBatch(session, groups);
            _log.Info("AnimeGroup statistics and contracts have been updated");

            ServerState.Instance.DatabaseBlocked = new ServerState.DatabaseBlockedInfo {
                Blocked = true, Status = "Creating AnimeGroup_Users and updating plex/kodi contracts"
            };
            _log.Info("Creating AnimeGroup_Users and updating plex/kodi contracts");

            List <SVR_AnimeGroup_User> animeGroupUsers = allCreatedGroupUsers.SelectMany(groupUsers => groupUsers)
                                                         .ToList();

            // Insert the AnimeGroup_Users so that they get assigned a primary key before we update plex/kodi contracts
            _animeGroupUserRepo.InsertBatch(session, animeGroupUsers);
            // We need to repopulate caches for AnimeGroup_User and AnimeGroup because we've updated/inserted them
            // and they need to be up to date for the plex/kodi contract updating to work correctly
            _animeGroupUserRepo.Populate(session, displayname: false);
            _animeGroupRepo.Populate(session, displayname: false);

            // NOTE: There are situations in which UpdatePlexKodiContracts will cause database database writes to occur, so we can't
            // use Parallel.ForEach for the time being (If it was guaranteed to only read then we'd be ok)
            foreach (SVR_AnimeGroup_User groupUser in animeGroupUsers)
            {
                groupUser.UpdatePlexKodiContracts(session);
            }

            _animeGroupUserRepo.UpdateBatch(session, animeGroupUsers);
            _log.Info("AnimeGroup_Users have been created");
        }
Ejemplo n.º 7
0
        private static CL_AniDB_Anime GetAnimeContractFromGroup(SVR_AnimeGroup grp)
        {
            var anime = grp.Anime.OrderBy(a => a.BeginYear)
                        .ThenBy(a => a.AirDate ?? DateTime.MaxValue)
                        .FirstOrDefault();

            return(anime?.Contract.AniDBAnime);
        }
Ejemplo n.º 8
0
 public static void Populate(this SVR_AnimeGroup agroup, SVR_AniDB_Anime anime, DateTime now)
 {
     agroup.Description     = anime.Description;
     agroup.GroupName       = anime.PreferredTitle;
     agroup.SortName        = anime.PreferredTitle;
     agroup.DateTimeUpdated = now;
     agroup.DateTimeCreated = now;
 }
Ejemplo n.º 9
0
        public static void Populate(this SVR_AnimeGroup agroup, SVR_AniDB_Anime anime, DateTime now)
        {
            agroup.Description = anime.Description;
            string name = anime.GetFormattedTitle();

            agroup.GroupName       = name;
            agroup.SortName        = name;
            agroup.DateTimeUpdated = now;
            agroup.DateTimeCreated = now;
        }
Ejemplo n.º 10
0
        public void UpdateGroupFilter(HashSet <GroupFilterConditionType> types)
        {
            SVR_AnimeGroup grp = RepoFactory.AnimeGroup.GetByID(AnimeGroupID);
            SVR_JMMUser    usr = RepoFactory.JMMUser.GetByID(JMMUserID);

            if (grp != null && usr != null)
            {
                grp.UpdateGroupFilters(types, usr);
            }
        }
        public void UpdatePlexKodiContracts_RA()
        {
            SVR_AnimeGroup grp = Repo.Instance.AnimeGroup.GetByID(AnimeGroupID);

            if (grp == null)
            {
                return;
            }
            List <SVR_AnimeSeries> series = grp.GetAllSeries();

            PlexContract = Helper.GenerateFromAnimeGroup(grp, JMMUserID, series);
        }
Ejemplo n.º 12
0
        public void UpdatePlexKodiContracts(ISessionWrapper session = null)
        {
            SVR_AnimeGroup grp = RepoFactory.AnimeGroup.GetByID(AnimeGroupID);

            if (grp == null)
            {
                return;
            }
            List <SVR_AnimeSeries> series = grp.GetAllSeries();

            PlexContract = Helper.GenerateFromAnimeGroup(grp, JMMUserID, series, session);
        }
Ejemplo n.º 13
0
 public bool AllowedGroup(SVR_AnimeGroup grp)
 {
     if (this.GetHideCategories().Count == 0)
     {
         return(true);
     }
     if (grp.Contract == null)
     {
         return(false);
     }
     return(!this.GetHideCategories().FindInEnumerable(grp.Contract.Stat_AllTags));
 }
Ejemplo n.º 14
0
        public static void Populate(this SVR_AnimeGroup agroup, SVR_AnimeSeries series, DateTime now)
        {
            SVR_AniDB_Anime anime = series.GetAnime();

            agroup.Description = anime.Description;
            string name = series.GetSeriesName();

            agroup.GroupName       = name;
            agroup.SortName        = name;
            agroup.DateTimeUpdated = now;
            agroup.DateTimeCreated = now;
        }
Ejemplo n.º 15
0
        public static Filter FilterFromAnimeGroup(HttpContext ctx, SVR_AnimeGroup grp, int uid)
        {
            Filter ob = new Filter
            {
                name   = grp.GroupName,
                id     = grp.AnimeGroupID,
                url    = APIHelper.ConstructFilterIdUrl(ctx, grp.AnimeGroupID),
                size   = -1,
                viewed = -1
            };

            foreach (SVR_AnimeSeries ser in grp.GetSeries().Randomize())
            {
                SVR_AniDB_Anime anim = ser.GetAnime();
                if (anim != null)
                {
                    ImageDetails fanart = anim.GetDefaultFanartDetailsNoBlanks();
                    ImageDetails banner = anim.GetDefaultWideBannerDetailsNoBlanks();

                    if (fanart != null)
                    {
                        ob.art.fanart.Add(new Art()
                        {
                            url   = APIHelper.ConstructImageLinkFromTypeAndId(ctx, (int)fanart.ImageType, fanart.ImageID),
                            index = ob.art.fanart.Count
                        });
                        ob.art.thumb.Add(new Art()
                        {
                            url   = APIHelper.ConstructImageLinkFromTypeAndId(ctx, (int)fanart.ImageType, fanart.ImageID),
                            index = ob.art.thumb.Count
                        });
                    }

                    if (banner != null)
                    {
                        ob.art.banner.Add(new Art()
                        {
                            url   = APIHelper.ConstructImageLinkFromTypeAndId(ctx, (int)banner.ImageType, banner.ImageID),
                            index = ob.art.banner.Count
                        });
                    }

                    if (ob.art.fanart.Count > 0)
                    {
                        break;
                    }
                }
            }
            return(ob);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Creates <see cref="SVR_AnimeGroup"/> that contain <see cref="SVR_AnimeSeries"/> that appear to be related.
        /// </summary>
        /// <remarks>
        /// This method assumes that there are no active transactions on the specified <paramref name="session"/>.
        /// </remarks>
        /// <param name="session">The NHibernate session.</param>
        /// <param name="seriesList">The list of <see cref="SVR_AnimeSeries"/> to create groups for.</param>
        /// <returns>A sequence of the created <see cref="SVR_AnimeGroup"/>s.</returns>
        private IEnumerable <SVR_AnimeGroup> AutoCreateGroupsWithRelatedSeries(ISessionWrapper session,
                                                                               IReadOnlyCollection <SVR_AnimeSeries> seriesList)
        {
            ServerState.Instance.DatabaseBlocked = new ServerState.DatabaseBlockedInfo {
                Blocked = true, Status = "Auto-generating Groups based on Relation Trees"
            };
            _log.Info("Auto-generating AnimeGroups for {0} AnimeSeries based on aniDB relationships", seriesList.Count);

            DateTime now           = DateTime.Now;
            var      grpCalculator = AutoAnimeGroupCalculator.CreateFromServerSettings(session);

            _log.Info(
                "The following exclusions will be applied when generating the groups: " + grpCalculator.Exclusions);

            // Group all of the specified series into their respective groups (keyed by the groups main anime ID)
            var seriesByGroup     = seriesList.ToLookup(s => grpCalculator.GetGroupAnimeId(s.AniDB_ID));
            var newGroupsToSeries =
                new List <Tuple <SVR_AnimeGroup, IReadOnlyCollection <SVR_AnimeSeries> > >(seriesList.Count);

            foreach (var groupAndSeries in seriesByGroup)
            {
                int             mainAnimeId = groupAndSeries.Key;
                SVR_AnimeSeries mainSeries  = groupAndSeries.FirstOrDefault(series => series.AniDB_ID == mainAnimeId);
                SVR_AnimeGroup  animeGroup  = CreateAnimeGroup(mainSeries, mainAnimeId, now);

                newGroupsToSeries.Add(
                    new Tuple <SVR_AnimeGroup, IReadOnlyCollection <SVR_AnimeSeries> >(animeGroup,
                                                                                       groupAndSeries.AsReadOnlyCollection()));
            }

            using (ITransaction trans = session.BeginTransaction())
            {
                _animeGroupRepo.InsertBatch(session, newGroupsToSeries.Select(gts => gts.Item1).AsReadOnlyCollection());
                trans.Commit();
            }

            // Anime groups should have IDs now they've been inserted. Now assign the group ID's to their respective series
            // (The caller of this method will be responsible for saving the AnimeSeries)
            foreach (var groupAndSeries in newGroupsToSeries)
            {
                foreach (SVR_AnimeSeries series in groupAndSeries.Item2)
                {
                    series.AnimeGroupID = groupAndSeries.Item1.AnimeGroupID;
                }
            }

            _log.Info("Generated {0} AnimeGroups", newGroupsToSeries.Count);

            return(newGroupsToSeries.Select(gts => gts.Item1));
        }
Ejemplo n.º 17
0
        private void UpdateAnimeGroupsAndTheirContracts(IEnumerable <SVR_AnimeGroup> groups)
        {
            _log.Info("Updating statistics and contracts for AnimeGroups");

            var allCreatedGroupUsers = new ConcurrentBag <List <SVR_AnimeGroup_User> >();

            // Update batches of AnimeGroup contracts in parallel. Each parallel branch requires it's own session since NHibernate sessions aren't thread safe.
            // The reason we're doing this in parallel is because updating contacts does a reasonable amount of work (including LZ4 compression)
            Parallel.ForEach(groups.Batch(DefaultBatchSize), new ParallelOptions {
                MaxDegreeOfParallelism = 4
            },
                             body: (groupBatch, state, localSession) =>
            {
                var createdGroupUsers = new List <SVR_AnimeGroup_User>(groupBatch.Length);

                // We shouldn't need to keep track of updates to AnimeGroup_Users in the below call, because they should have all been deleted,
                // therefore they should all be new
                SVR_AnimeGroup.BatchUpdateStats(groupBatch, watchedStats: true, missingEpsStats: true,
                                                createdGroupUsers: createdGroupUsers);
                allCreatedGroupUsers.Add(createdGroupUsers);
                SVR_AnimeGroup.BatchUpdateContracts(groupBatch, updateStats: true);
            });

            _log.Info("AnimeGroup statistics and contracts have been updated");

            _log.Info("Creating AnimeGroup_Users and updating plex/kodi contracts");


            // Insert the AnimeGroup_Users so that they get assigned a primary key before we update plex/kodi contracts
            // We need to repopulate caches for AnimeGroup_User and AnimeGroup because we've updated/inserted them
            // and they need to be up to date for the plex/kodi contract updating to work correctly

            // NOTE: There are situations in which UpdatePlexKodiContracts will cause database database writes to occur, so we can't
            // use Parallel.ForEach for the time being (If it was guaranteed to only read then we'd be ok)
            List <int> ids = allCreatedGroupUsers.SelectMany(a => a).Select(a => a.AnimeGroup_UserID).ToList();

            using (var upd = Repo.Instance.AnimeGroup_User.BeginBatchUpdate(() => Repo.Instance.AnimeGroup_User.GetMany(ids)))
            {
                foreach (SVR_AnimeGroup_User guser in upd)
                {
                    guser.UpdatePlexKodiContracts_RA();
                    upd.Update(guser);
                }

                upd.Commit();
            }

            _log.Info("AnimeGroup_Users have been created");
        }
Ejemplo n.º 18
0
        private static void GetValidVideoRecursive(IProvider prov, SVR_GroupFilter f, int userid, Directory pp)
        {
            List <SVR_GroupFilter> gfs = RepoFactory.GroupFilter.GetByParentID(f.GroupFilterID)
                                         .Where(a => a.GroupsIds.ContainsKey(userid) && a.GroupsIds[userid].Count > 0)
                                         .ToList();

            foreach (SVR_GroupFilter gg in gfs.Where(a => (a.FilterType & (int)GroupFilterType.Directory) == 0))
            {
                if (gg.GroupsIds.ContainsKey(userid))
                {
                    HashSet <int> groups = gg.GroupsIds[userid];
                    if (groups.Count != 0)
                    {
                        foreach (int grp in groups.Randomize(f.GroupFilterID))
                        {
                            SVR_AnimeGroup ag = RepoFactory.AnimeGroup.GetByID(grp);
                            Video          v  = ag.GetPlexContract(userid);
                            if (v?.Art == null || v.Thumb == null)
                            {
                                continue;
                            }
                            pp.Art   = prov.ReplaceSchemeHost(v.Art);
                            pp.Thumb = prov.ReplaceSchemeHost(v.Thumb);
                            break;
                        }
                    }
                }
                if (pp.Art != null)
                {
                    break;
                }
            }
            if (pp.Art == null)
            {
                foreach (SVR_GroupFilter gg in gfs
                         .Where(a => (a.FilterType & (int)GroupFilterType.Directory) == (int)GroupFilterType.Directory &&
                                a.InvisibleInClients == 0)
                         .Randomize(f.GroupFilterID))
                {
                    GetValidVideoRecursive(prov, gg, userid, pp);
                    if (pp.Art != null)
                    {
                        break;
                    }
                }
            }
            pp.LeafCount       = gfs.Count;
            pp.ViewedLeafCount = 0;
        }
Ejemplo n.º 19
0
 private bool GetHasCustomName(SVR_AnimeGroup grp)
 {
     using (var session = DatabaseFactory.SessionFactory.OpenSession())
     {
         var groupCalculator = AutoAnimeGroupCalculator.Create(session.Wrap(), AutoGroupExclude.None);
         int id = grp.GetSeries().FirstOrDefault()?.AniDB_ID ?? 0;
         if (id == 0)
         {
             return(true);
         }
         var ids = groupCalculator.GetIdsOfAnimeInSameGroup(id);
         return(!ids.Select(aid => RepoFactory.AniDB_Anime.GetByAnimeID(aid)).Where(anime => anime != null)
                .Any(anime => anime.GetAllTitles().Contains(grp.GroupName)));
     }
 }
Ejemplo n.º 20
0
        public ActionResult <Group> SaveGroup(Group.FullGroup group)
        {
            SVR_AnimeGroup g = null;

            if (group.IDs.ID != 0)
            {
                g = RepoFactory.AnimeGroup.GetByID(group.IDs.ID);
                if (g == null)
                {
                    return(BadRequest("No Group with ID"));
                }
            }
            g = group.ToServerModel(g);
            RepoFactory.AnimeGroup.Save(g);

            return(new Group(HttpContext, g));
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Creates a new group that series will be put in during group re-calculation.
        /// </summary>
        /// <param name="session">The NHibernate session.</param>
        /// <returns>The temporary <see cref="SVR_AnimeGroup"/>.</returns>
        private SVR_AnimeGroup CreateTempAnimeGroup(ISessionWrapper session)
        {
            DateTime now = DateTime.Now;

            var tempGroup = new SVR_AnimeGroup
            {
                GroupName       = TempGroupName,
                Description     = TempGroupName,
                SortName        = TempGroupName,
                DateTimeUpdated = now,
                DateTimeCreated = now
            };

            // We won't use AnimeGroupRepository.Save because we don't need to perform all the extra stuff since this is for temporary use only
            session.Insert(tempGroup);

            return(tempGroup);
        }
Ejemplo n.º 22
0
        private static bool GroupHasMostlyCompleteArt(SVR_AnimeGroup grp)
        {
            var anime = grp.Anime.OrderBy(a => a.BeginYear)
                        .ThenBy(a => a.AirDate ?? DateTime.MaxValue)
                        .FirstOrDefault();
            var fanarts = anime?.Contract.AniDBAnime.Fanarts;

            if (fanarts == null || fanarts.Count <= 0)
            {
                return(false);
            }
            fanarts = anime.Contract.AniDBAnime.Banners;
            if (fanarts == null || fanarts.Count <= 0)
            {
                return(false);
            }
            return(true);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Gets or creates an <see cref="SVR_AnimeGroup"/> for the specified series.
        /// </summary>
        /// <param name="session">The NHibernate session.</param>
        /// <param name="series">The series for which the group is to be created/retrieved (Must be initialised first).</param>
        /// <returns>The <see cref="SVR_AnimeGroup"/> to use for the specified series.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="session"/> or <paramref name="series"/> is <c>null</c>.</exception>
        public SVR_AnimeGroup GetOrCreateSingleGroupForSeries(ISessionWrapper session, SVR_AnimeSeries series)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (series == null)
            {
                throw new ArgumentNullException(nameof(series));
            }

            SVR_AnimeGroup animeGroup = null;

            if (_autoGroupSeries)
            {
                var grpCalculator = AutoAnimeGroupCalculator.CreateFromServerSettings(session);
                IReadOnlyList <int> grpAnimeIds = grpCalculator.GetIdsOfAnimeInSameGroup(series.AniDB_ID);
                // Try to find an existing AnimeGroup to add the series to
                // We basically pick the first group that any of the related series belongs to already
                animeGroup = grpAnimeIds.Where(id => id != series.AniDB_ID)
                             .Select(id => RepoFactory.AnimeSeries.GetByAnimeID(id))
                             .Where(s => s != null)
                             .Select(s => RepoFactory.AnimeGroup.GetByID(s.AnimeGroupID))
                             .FirstOrDefault(s => s != null);

                if (animeGroup == null)
                {
                    // No existing group was found, so create a new one
                    int             mainAnimeId = grpCalculator.GetGroupAnimeId(series.AniDB_ID);
                    SVR_AnimeSeries mainSeries  = _animeSeriesRepo.GetByAnimeID(mainAnimeId);

                    animeGroup = CreateAnimeGroup(mainSeries, mainAnimeId, DateTime.Now);
                    RepoFactory.AnimeGroup.Save(animeGroup, true, true);
                }
            }
            else // We're not auto grouping (e.g. we're doing group per series)
            {
                animeGroup = new SVR_AnimeGroup();
                animeGroup.Populate(series, DateTime.Now);
                RepoFactory.AnimeGroup.Save(animeGroup, true, true);
            }

            return(animeGroup);
        }
Ejemplo n.º 24
0
        public static Directory DirectoryFromFilter(IProvider prov, SVR_GroupFilter gg,
                                                    int userid)
        {
            Directory pp = new Directory {
                Type = "show"
            };

            pp.Key       = prov.ConstructFilterIdUrl(userid, gg.GroupFilterID);
            pp.Title     = gg.GroupFilterName;
            pp.Id        = gg.GroupFilterID;
            pp.AnimeType = AnimeTypes.AnimeGroupFilter.ToString();
            if ((gg.FilterType & (int)GroupFilterType.Directory) == (int)GroupFilterType.Directory)
            {
                GetValidVideoRecursive(prov, gg, userid, pp);
            }
            else if (gg.GroupsIds.ContainsKey(userid))
            {
                HashSet <int> groups = gg.GroupsIds[userid];
                if (groups.Count == 0)
                {
                    return(pp);
                }
                pp.LeafCount       = groups.Count;
                pp.ViewedLeafCount = 0;
                foreach (int grp in groups.Randomize())
                {
                    SVR_AnimeGroup ag = RepoFactory.AnimeGroup.GetByID(grp);
                    Video          v  = ag.GetPlexContract(userid);
                    if (v?.Art == null || v.Thumb == null)
                    {
                        continue;
                    }
                    pp.Art   = prov.ReplaceSchemeHost(v.Art);
                    pp.Thumb = prov.ReplaceSchemeHost(v.Thumb);
                    break;
                }
                return(pp);
            }
            return(pp);
        }
Ejemplo n.º 25
0
        public void RecalculateStatsContractsForGroup(SVR_AnimeGroup group)
        {
            using (ISession sessionNotWrapped = DatabaseFactory.SessionFactory.OpenSession())
            {
                var groups = new List <SVR_AnimeGroup> {
                    group
                };
                var session = sessionNotWrapped.Wrap();
                var series  = group.GetAllSeries(true);
                // recalculate series
                _log.Info($"Recalculating Series Stats and Contracts for Group: {group.GroupName} ({group.AnimeGroupID})");
                using (ITransaction trans = session.BeginTransaction())
                {
                    UpdateAnimeSeriesContractsAndSave(session, series);
                    trans.Commit();
                }

                // Update Cache so that group can recalculate
                series.ForEach(a => _animeSeriesRepo.Cache.Update(a));

                // Recalculate group
                _log.Info($"Recalculating Group Stats and Contracts for Group: {group.GroupName} ({group.AnimeGroupID})");
                using (ITransaction trans = session.BeginTransaction())
                {
                    UpdateAnimeGroupsAndTheirContracts(session, groups);
                    trans.Commit();
                }

                // update cache
                _animeGroupRepo.Cache.Update(group);
                var groupsUsers = _animeGroupUserRepo.GetByGroupID(group.AnimeGroupID);
                groupsUsers.ForEach(a => _animeGroupUserRepo.Cache.Update(a));

                // update filters
                _log.Info($"Recalculating Filters for Group: {group.GroupName} ({group.AnimeGroupID})");
                UpdateGroupFilters(session);

                _log.Info($"Done Recalculating Stats and Contracts for Group: {group.GroupName} ({group.AnimeGroupID})");
            }
        }
Ejemplo n.º 26
0
        public static Filter FilterFromGroupFilter(HttpContext ctx, SVR_GroupFilter gg, int uid)
        {
            Filter ob = new Filter
            {
                name = gg.GroupFilterName,
                id   = gg.GroupFilterID,
                url  = APIHelper.ConstructFilterIdUrl(ctx, gg.GroupFilterID)
            };

            if (gg.GroupsIds.ContainsKey(uid))
            {
                HashSet <int> groups = gg.GroupsIds[uid];
                if (groups.Count != 0)
                {
                    ob.size   = groups.Count;
                    ob.viewed = 0;

                    foreach (int grp in groups)
                    {
                        SVR_AnimeGroup ag = Repo.Instance.AnimeGroup.GetByID(grp);
                        Video          v  = ag.GetPlexContract(uid);
                        if (v?.Art != null && v.Thumb != null)
                        {
                            ob.art.fanart.Add(new Art()
                            {
                                url = APIHelper.ConstructImageLinkFromRest(ctx, v.Art), index = 0
                            });
                            ob.art.thumb.Add(new Art()
                            {
                                url   = APIHelper.ConstructImageLinkFromRest(ctx, v.Thumb),
                                index = 0
                            });
                            break;
                        }
                    }
                }
            }
            return(ob);
        }
Ejemplo n.º 27
0
 public AnimeSeriesRepository()
 {
     BeginDeleteCallback = cr =>
     {
         RepoFactory.AnimeSeries_User.Delete(RepoFactory.AnimeSeries_User.GetBySeriesID(cr.AnimeSeriesID));
         Changes.Remove(cr.AnimeSeriesID);
     };
     EndDeleteCallback = cr =>
     {
         cr.DeleteFromFilters();
         if (cr.AnimeGroupID <= 0)
         {
             return;
         }
         logger.Trace("Updating group stats by group from AnimeSeriesRepository.Delete: {0}",
                      cr.AnimeGroupID);
         SVR_AnimeGroup oldGroup = RepoFactory.AnimeGroup.GetByID(cr.AnimeGroupID);
         if (oldGroup != null)
         {
             RepoFactory.AnimeGroup.Save(oldGroup, true, true);
         }
     };
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Re-creates all AnimeGroups based on the existing AnimeSeries.
        /// </summary>
        /// <param name="session">The NHibernate session.</param>
        /// <exception cref="ArgumentNullException"><paramref name="session"/> is <c>null</c>.</exception>
        public void RecreateAllGroups(ISessionWrapper session)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }

            bool cmdProcGeneralPaused = ShokoService.CmdProcessorGeneral.Paused;
            bool cmdProcHasherPaused  = ShokoService.CmdProcessorHasher.Paused;
            bool cmdProcImagesPaused  = ShokoService.CmdProcessorImages.Paused;

            try
            {
                // Pause queues
                ShokoService.CmdProcessorGeneral.Paused = true;
                ShokoService.CmdProcessorHasher.Paused  = true;
                ShokoService.CmdProcessorImages.Paused  = true;

                _log.Info("Beginning re-creation of all groups");

                IReadOnlyList <SVR_AnimeSeries>      animeSeries   = RepoFactory.AnimeSeries.GetAll();
                IReadOnlyCollection <SVR_AnimeGroup> createdGroups = null;
                SVR_AnimeGroup tempGroup = null;

                using (ITransaction trans = session.BeginTransaction())
                {
                    tempGroup = CreateTempAnimeGroup(session);
                    ClearGroupsAndDependencies(session, tempGroup.AnimeGroupID);
                    trans.Commit();
                }

                if (_autoGroupSeries)
                {
                    createdGroups = AutoCreateGroupsWithRelatedSeries(session, animeSeries)
                                    .AsReadOnlyCollection();
                }
                else // Standard group re-create
                {
                    createdGroups = CreateGroupPerSeries(session, animeSeries)
                                    .AsReadOnlyCollection();
                }

                using (ITransaction trans = session.BeginTransaction())
                {
                    UpdateAnimeSeriesContractsAndSave(session, animeSeries);
                    session.Delete(tempGroup); // We should no longer need the temporary group we created earlier
                    trans.Commit();
                }

                // We need groups and series cached for updating of AnimeGroup contracts to work
                _animeGroupRepo.Populate(session, displayname: false);
                _animeSeriesRepo.Populate(session, displayname: false);

                using (ITransaction trans = session.BeginTransaction())
                {
                    UpdateAnimeGroupsAndTheirContracts(session, createdGroups);
                    trans.Commit();
                }

                // We need to update the AnimeGroups cache again now that the contracts have been saved
                // (Otherwise updating Group Filters won't get the correct results)
                _animeGroupRepo.Populate(session, displayname: false);
                _animeGroupUserRepo.Populate(session, displayname: false);
                _groupFilterRepo.Populate(session, displayname: false);

                using (ITransaction trans = session.BeginTransaction())
                {
                    UpdateGroupFilters(session);
                    trans.Commit();
                }

                _log.Info("Successfuly completed re-creating all groups");
            }
            catch (Exception e)
            {
                _log.Error(e, "An error occurred while re-creating all groups");

                try
                {
                    // If an error occurs then chances are the caches are in an inconsistent state. So re-populate them
                    _animeSeriesRepo.Populate();
                    _animeGroupRepo.Populate();
                    _groupFilterRepo.Populate();
                    _animeGroupUserRepo.Populate();
                }
                catch (Exception ie)
                {
                    _log.Warn(ie, "Failed to re-populate caches");
                }

                throw;
            }
            finally
            {
                // Un-pause queues (if they were previously running)
                ShokoService.CmdProcessorGeneral.Paused = cmdProcGeneralPaused;
                ShokoService.CmdProcessorHasher.Paused  = cmdProcHasherPaused;
                ShokoService.CmdProcessorImages.Paused  = cmdProcImagesPaused;
            }
        }
Ejemplo n.º 29
0
        public void Save(SVR_AnimeSeries obj, bool updateGroups, bool onlyupdatestats, bool skipgroupfilters = false,
                         bool alsoupdateepisodes = false)
        {
            bool           newSeries   = false;
            SVR_AnimeGroup oldGroup    = null;
            bool           isMigrating = false;

            lock (obj)
            {
                if (obj.AnimeSeriesID == 0)
                {
                    newSeries = true; // a new series
                }
                else
                {
                    // get the old version from the DB
                    SVR_AnimeSeries oldSeries;
                    using (var session = DatabaseFactory.SessionFactory.OpenSession())
                    {
                        lock (globalDBLock)
                        {
                            oldSeries = session.Get <SVR_AnimeSeries>(obj.AnimeSeriesID);
                        }
                    }
                    if (oldSeries != null)
                    {
                        // means we are moving series to a different group
                        if (oldSeries.AnimeGroupID != obj.AnimeGroupID)
                        {
                            oldGroup = RepoFactory.AnimeGroup.GetByID(oldSeries.AnimeGroupID);
                            SVR_AnimeGroup newGroup = RepoFactory.AnimeGroup.GetByID(obj.AnimeGroupID);
                            if (newGroup != null && newGroup.GroupName.Equals("AAA Migrating Groups AAA"))
                            {
                                isMigrating = true;
                            }
                            newSeries = true;
                        }
                    }
                }
                if (newSeries && !isMigrating)
                {
                    obj.Contract = null;
                    base.Save(obj);
                }
                HashSet <GroupFilterConditionType> types = obj.UpdateContract(onlyupdatestats);
                base.Save(obj);

                if (updateGroups && !isMigrating)
                {
                    logger.Trace("Updating group stats by series from AnimeSeriesRepository.Save: {0}", obj.AnimeSeriesID);
                    SVR_AnimeGroup grp = RepoFactory.AnimeGroup.GetByID(obj.AnimeGroupID);
                    if (grp != null)
                    {
                        RepoFactory.AnimeGroup.Save(grp, true, true);
                    }

                    if (oldGroup != null)
                    {
                        logger.Trace("Updating group stats by group from AnimeSeriesRepository.Save: {0}",
                                     oldGroup.AnimeGroupID);
                        RepoFactory.AnimeGroup.Save(oldGroup, true, true);
                    }
                }
                if (!skipgroupfilters && !isMigrating)
                {
                    int endyear = obj.Contract?.AniDBAnime?.AniDBAnime?.EndYear ?? 0;
                    if (endyear == 0)
                    {
                        endyear = DateTime.Today.Year;
                    }
                    HashSet <int> allyears = null;
                    if ((obj.Contract?.AniDBAnime?.AniDBAnime?.BeginYear ?? 0) != 0)
                    {
                        allyears = new HashSet <int>(Enumerable.Range(obj.Contract.AniDBAnime.AniDBAnime.BeginYear,
                                                                      endyear - obj.Contract.AniDBAnime.AniDBAnime.BeginYear + 1));
                    }
                    //This call will create extra years or tags if the Group have a new year or tag
                    RepoFactory.GroupFilter.CreateOrVerifyDirectoryFilters(false,
                                                                           obj.Contract?.AniDBAnime?.AniDBAnime?.GetAllTags(), allyears,
                                                                           obj.Contract?.AniDBAnime?.Stat_AllSeasons);

                    // Update other existing filters
                    obj.UpdateGroupFilters(types, null);
                }
                lock (Changes)
                {
                    Changes.AddOrUpdate(obj.AnimeSeriesID);
                }
            }
            if (alsoupdateepisodes)
            {
                List <SVR_AnimeEpisode> eps = RepoFactory.AnimeEpisode.GetBySeriesID(obj.AnimeSeriesID);
                RepoFactory.AnimeEpisode.Save(eps);
            }
        }
Ejemplo n.º 30
0
        public static Video GenerateFromAnimeGroup(SVR_AnimeGroup grp, int userid, List <SVR_AnimeSeries> allSeries,
                                                   ISessionWrapper session = null)
        {
            CL_AnimeGroup_User cgrp = grp.GetUserContract(userid);
            int subgrpcnt           = grp.GetAllChildGroups().Count;

            if ((cgrp.Stat_SeriesCount == 1) && (subgrpcnt == 0))
            {
                SVR_AnimeSeries     ser    = ShokoServiceImplementation.GetSeriesForGroup(grp.AnimeGroupID, allSeries);
                CL_AnimeSeries_User cserie = ser?.GetUserContract(userid);
                if (cserie == null)
                {
                    return(null);
                }
                Video v = GenerateFromSeries(cserie, ser, ser.GetAnime(), userid, session);
                v.AirDate   = ser.AirDate;
                v.UpdatedAt = ser.LatestEpisodeAirDate.HasValue
                    ? ser.LatestEpisodeAirDate.Value.ToUnixTime()
                    : null;
                v.Group = cgrp;
                return(v);
            }
            else
            {
                SVR_AnimeSeries ser = grp.DefaultAnimeSeriesID.HasValue
                    ? allSeries.FirstOrDefault(a => a.AnimeSeriesID == grp.DefaultAnimeSeriesID.Value)
                    : allSeries.Find(a => a.AirDate != DateTime.MinValue);
                if (ser == null && allSeries.Count > 0)
                {
                    ser = allSeries[0];
                }
                CL_AnimeSeries_User cserie = ser?.GetUserContract(userid);
                Video v = FromGroup(cgrp, cserie, userid, subgrpcnt);
                v.Group     = cgrp;
                v.AirDate   = cgrp.Stat_AirDate_Min ?? DateTime.MinValue;
                v.UpdatedAt = cgrp.LatestEpisodeAirDate?.ToUnixTime();
                v.Rating    = (int)Math.Round((grp.AniDBRating / 100), 1);
                List <Tag> newTags = new List <Tag>();
                foreach (AniDB_Tag tag in grp.Tags)
                {
                    Tag      newTag   = new Tag();
                    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                    newTag.Value = textInfo.ToTitleCase(tag.TagName.Trim());
                    if (!newTags.Contains(newTag))
                    {
                        newTags.Add(newTag);
                    }
                }
                v.Genres = newTags;
                if (ser == null)
                {
                    return(v);
                }
                List <AnimeTitle> newTitles = ser.GetAnime()
                                              .GetTitles()
                                              .Select(title => new AnimeTitle
                {
                    Title    = title.Title,
                    Language = title.Language,
                    Type     = title.TitleType
                })
                                              .ToList();
                v.Titles = newTitles;

                v.Roles = new List <RoleTag>();

                //TODO Character implementation is limited in JMM, One Character, could have more than one Seiyuu
                if (ser.GetAnime()?.Contract?.AniDBAnime?.Characters != null)
                {
                    foreach (CL_AniDB_Character c in ser.GetAnime().Contract.AniDBAnime.Characters)
                    {
                        string       ch     = c?.CharName;
                        AniDB_Seiyuu seiyuu = c?.Seiyuu;
                        if (String.IsNullOrEmpty(ch))
                        {
                            continue;
                        }
                        RoleTag t = new RoleTag
                        {
                            Value = seiyuu?.SeiyuuName
                        };
                        if (seiyuu != null)
                        {
                            t.TagPicture = ConstructSeiyuuImage(null, seiyuu.AniDB_SeiyuuID);
                        }
                        t.Role            = ch;
                        t.RoleDescription = c?.CharDescription;
                        t.RolePicture     = ConstructCharacterImage(null, c.CharID);
                        v.Roles.Add(t);
                    }
                }
                if (cserie?.AniDBAnime?.AniDBAnime?.Fanarts != null)
                {
                    v.Fanarts = new List <Contract_ImageDetails>();
                    cserie?.AniDBAnime?.AniDBAnime?.Fanarts.ForEach(
                        a =>
                        v.Fanarts.Add(new Contract_ImageDetails
                    {
                        ImageID   = a.AniDB_Anime_DefaultImageID,
                        ImageType = a.ImageType
                    }));
                }
                if (cserie?.AniDBAnime?.AniDBAnime?.Banners == null)
                {
                    return(v);
                }
                v.Banners = new List <Contract_ImageDetails>();
                cserie?.AniDBAnime?.AniDBAnime?.Banners.ForEach(
                    a =>
                    v.Banners.Add(new Contract_ImageDetails
                {
                    ImageID   = a.AniDB_Anime_DefaultImageID,
                    ImageType = a.ImageType
                }));
                return(v);
            }
        }