/// <summary> /// Creates a single <see cref="AnimeGroup"/> for each <see cref="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="AnimeSeries"/> to create groups for.</param> /// <returns>A sequence of the created <see cref="AnimeGroup"/>s.</returns> private IEnumerable <AnimeGroup> CreateGroupPerSeries(ISessionWrapper session, IReadOnlyList <AnimeSeries> seriesList) { _log.Info("Generating AnimeGroups for {0} AnimeSeries", seriesList.Count); DateTime now = DateTime.Now; var newGroupsToSeries = new Tuple <AnimeGroup, AnimeSeries> [seriesList.Count]; // Create one group per series for (int grp = 0; grp < seriesList.Count; grp++) { AnimeGroup group = new AnimeGroup(); AnimeSeries series = seriesList[grp]; group.Populate(series, now); newGroupsToSeries[grp] = new Tuple <AnimeGroup, 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 <AnimeGroup, AnimeSeries> groupAndSeries in newGroupsToSeries) { groupAndSeries.Item2.AnimeGroupID = groupAndSeries.Item1.AnimeGroupID; } _log.Info("Generated {0} AnimeGroups", newGroupsToSeries.Length); return(newGroupsToSeries.Select(gts => gts.Item1)); }
public static Video VideoFromAnimeGroup(ISession session, AnimeGroup grp, int userid, List <AnimeSeries> allSeries) { Contract_AnimeGroup cgrp = grp.ToContract(grp.GetUserRecord(session, userid)); if (StatsCache.Instance.StatGroupSeriesCount[grp.AnimeGroupID] == 1) { AnimeSeries ser = JMMServiceImplementation.GetSeriesForGroup(grp.AnimeGroupID, allSeries); if (ser != null) { Contract_AnimeSeries cserie = ser.ToContract(ser.GetUserRecord(session, userid), true); Video v = FromSerieWithPossibleReplacement(cserie, ser, userid); v.AirDate = ser.AirDate.HasValue ? ser.AirDate.Value : DateTime.MinValue; v.Group = cgrp; return(v); } } else { AnimeSeries ser = grp.DefaultAnimeSeriesID.HasValue ? allSeries.FirstOrDefault(a => a.AnimeSeriesID == grp.DefaultAnimeSeriesID.Value) : JMMServiceImplementation.GetSeriesForGroup(grp.AnimeGroupID, allSeries); if (ser != null) { Video v = FromGroup(cgrp, ser.ToContract(ser.GetUserRecord(session, userid), true), userid); v.Group = cgrp; v.AirDate = cgrp.Stat_AirDate_Min.HasValue ? cgrp.Stat_AirDate_Min.Value : DateTime.MinValue; return(v); } } return(null); }
public static void Init() { JMMUser.Populate(a => a.JMMUserID); CloudAccount.Populate(a => a.CloudID); ImportFolder.Populate(a => a.ImportFolderID); AniDB_Anime.Populate(a => a.AniDB_AnimeID); AniDB_Episode.Populate(a => a.AniDB_EpisodeID); AniDB_File.Populate(a => a.AniDB_FileID); AniDB_Anime_Title.Populate(a => a.AniDB_Anime_TitleID); AniDB_Anime_Tag.Populate(a => a.AniDB_Anime_TagID); AniDB_Tag.Populate(a => a.AniDB_TagID); CustomTag.Populate(a => a.CustomTagID); CrossRef_CustomTag.Populate(a => a.CrossRef_CustomTagID); CrossRef_File_Episode.Populate(a => a.CrossRef_File_EpisodeID); VideoLocalPlace.Populate(a => a.VideoLocal_Place_ID); VideoLocal.Populate(a => a.VideoLocalID); VideoLocalUser.Populate(a => a.VideoLocal_UserID); GroupFilter.Populate(a => a.GroupFilterID); AnimeEpisode.Populate(a => a.AnimeEpisodeID); AnimeEpisode_User.Populate(a => a.AnimeEpisode_UserID); AnimeSeries.Populate(a => a.AnimeSeriesID); AnimeSeries_User.Populate(a => a.AnimeSeries_UserID); AnimeGroup.Populate(a => a.AnimeGroupID); AnimeGroup_User.Populate(a => a.AnimeGroup_UserID); GroupFilter.PostProcess(); CleanUpMemory(); }
public static void Init() { JMMUser.Populate(); CloudAccount.Populate(); ImportFolder.Populate(); AniDB_Anime.Populate(); AniDB_Episode.Populate(); AniDB_File.Populate(); AniDB_Anime_Title.Populate(); AniDB_Anime_Tag.Populate(); AniDB_Tag.Populate(); CustomTag.Populate(); CrossRef_CustomTag.Populate(); CrossRef_File_Episode.Populate(); VideoLocalPlace.Populate(); VideoLocal.Populate(); VideoLocalUser.Populate(); GroupFilter.Populate(); AnimeEpisode.Populate(); AnimeEpisode_User.Populate(); AnimeSeries.Populate(); AnimeSeries_User.Populate(); AnimeGroup.Populate(); AnimeGroup_User.Populate(); // Update Contracts if necessary try { JMMUser.RegenerateDb(); CloudAccount.RegenerateDb(); ImportFolder.RegenerateDb(); AniDB_Anime.RegenerateDb(); AniDB_Episode.RegenerateDb(); AniDB_File.RegenerateDb(); AniDB_Anime_Title.RegenerateDb(); AniDB_Anime_Tag.RegenerateDb(); AniDB_Tag.RegenerateDb(); CustomTag.RegenerateDb(); CrossRef_CustomTag.RegenerateDb(); CrossRef_File_Episode.RegenerateDb(); VideoLocalPlace.RegenerateDb(); VideoLocal.RegenerateDb(); VideoLocalUser.RegenerateDb(); AnimeEpisode.RegenerateDb(); AnimeEpisode_User.RegenerateDb(); AnimeSeries.RegenerateDb(); AnimeSeries_User.RegenerateDb(); AnimeGroup.RegenerateDb(); AnimeGroup_User.RegenerateDb(); GroupFilter.RegenerateDb(); GroupFilter.PostProcess(); } catch (Exception e) { LogManager.GetCurrentClassLogger().Error(e, "There was an error starting the Database Factory"); } CleanUpMemory(); }
public static void CleanUpMemory() { AniDB_Anime.GetAll().ForEach(a => a.CollectContractMemory()); VideoLocal.GetAll().ForEach(a => a.CollectContractMemory()); AnimeEpisode.GetAll().ForEach(a => a.CollectContractMemory()); AnimeEpisode_User.GetAll().ForEach(a => a.CollectContractMemory()); AnimeSeries.GetAll().ForEach(a => a.CollectContractMemory()); AnimeSeries_User.GetAll().ForEach(a => a.CollectContractMemory()); AnimeGroup.GetAll().ForEach(a => a.CollectContractMemory()); AnimeGroup_User.GetAll().ForEach(a => a.CollectContractMemory()); GC.Collect(); }
public static void Init() { JMMUser.Populate(); CloudAccount.Populate(); ImportFolder.Populate(); AniDB_Anime.Populate(); AniDB_Episode.Populate(); AniDB_File.Populate(); AniDB_Anime_Title.Populate(); AniDB_Anime_Tag.Populate(); AniDB_Tag.Populate(); CustomTag.Populate(); CrossRef_CustomTag.Populate(); CrossRef_File_Episode.Populate(); VideoLocalPlace.Populate(); VideoLocal.Populate(); VideoLocalUser.Populate(); GroupFilter.Populate(); AnimeEpisode.Populate(); AnimeEpisode_User.Populate(); AnimeSeries.Populate(); AnimeSeries_User.Populate(); AnimeGroup.Populate(); AnimeGroup_User.Populate(); // Update Contracts if necessary JMMUser.RegenerateDb(); CloudAccount.RegenerateDb(); ImportFolder.RegenerateDb(); AniDB_Anime.RegenerateDb(); AniDB_Episode.RegenerateDb(); AniDB_File.RegenerateDb(); AniDB_Anime_Title.RegenerateDb(); AniDB_Anime_Tag.RegenerateDb(); AniDB_Tag.RegenerateDb(); CustomTag.RegenerateDb(); CrossRef_CustomTag.RegenerateDb(); CrossRef_File_Episode.RegenerateDb(); VideoLocalPlace.RegenerateDb(); VideoLocal.RegenerateDb(); VideoLocalUser.RegenerateDb(); AnimeEpisode.RegenerateDb(); AnimeEpisode_User.RegenerateDb(); AnimeSeries.RegenerateDb(); AnimeSeries_User.RegenerateDb(); AnimeGroup.RegenerateDb(); AnimeGroup_User.RegenerateDb(); GroupFilter.RegenerateDb(); GroupFilter.PostProcess(); CleanUpMemory(); }
public static void CleanUpMemory() { AniDB_Anime.GetAll().ForEach(a => a.CollectContractMemory()); VideoLocal.GetAll().ForEach(a => a.CollectContractMemory()); AnimeEpisode_User.GetAll().ForEach(a => a.CollectContractMemory()); AnimeSeries.GetAll().ForEach(a => a.CollectContractMemory()); AnimeSeries_User.GetAll().ForEach(a => a.CollectContractMemory()); AnimeGroup.GetAll().ForEach(a => a.CollectContractMemory()); AnimeGroup_User.GetAll().ForEach(a => a.CollectContractMemory()); GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); }
public void Save(AnimeSeries obj, bool updateStats) { bool updateStatsCache = false; AnimeGroup oldGroup = null; if (obj.AnimeSeriesID == 0) { updateStatsCache = true; // a new series } else { // get the old version from the DB AnimeSeries oldSeries = GetByID(obj.AnimeSeriesID); if (oldSeries != null) { // means we are moving series to a different group if (oldSeries.AnimeGroupID != obj.AnimeGroupID) { AnimeGroupRepository repGroups = new AnimeGroupRepository(); oldGroup = repGroups.GetByID(oldSeries.AnimeGroupID); updateStatsCache = true; } } } using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(obj); transaction.Commit(); } } if (updateStats) { if (updateStatsCache) { logger.Trace("Updating group stats by series from AnimeSeriesRepository.Save: {0}", obj.AnimeSeriesID); StatsCache.Instance.UpdateUsingSeries(obj.AnimeSeriesID); } if (oldGroup != null) { logger.Trace("Updating group stats by group from AnimeSeriesRepository.Save: {0}", oldGroup.AnimeGroupID); StatsCache.Instance.UpdateUsingGroup(oldGroup.AnimeGroupID); } } }
public void Save(AnimeGroup obj) { using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(obj); transaction.Commit(); } } logger.Trace("Updating group stats by group from AnimeGroupRepository.Save: {0}", obj.AnimeGroupID); StatsCache.Instance.UpdateUsingGroup(obj.AnimeGroupID); }
private void UpdateAnimeGroupsAndTheirContracts(ISessionWrapper session, IReadOnlyCollection <AnimeGroup> groups) { _log.Info("Updating statistics and contracts for AnimeGroups"); var allCreatedGroupUsers = new ConcurrentBag <List <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 <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 AnimeGroup.BatchUpdateStats(groupBatch, watchedStats: true, missingEpsStats: true, createdGroupUsers: createdGroupUsers); allCreatedGroupUsers.Add(createdGroupUsers); 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"); _log.Info("Creating AnimeGroup_Users and updating plex/kodi contracts"); List <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 (AnimeGroup_User groupUser in animeGroupUsers) { groupUser.UpdatePlexKodiContracts(session); } _animeGroupUserRepo.UpdateBatch(session, animeGroupUsers); _log.Info("AnimeGroup_Users have been created"); }
public System.IO.Stream GetItemsFromGroup(int userid, string GroupId) { KodiObject ret = new KodiObject(KodiHelper.NewMediaContainer("Groups", true)); if (!ret.Init()) { return(new MemoryStream()); } int groupID; int.TryParse(GroupId, out groupID); List <Video> retGroups = new List <Video>(); if (groupID == -1) { return(new MemoryStream()); } using (var session = JMMService.SessionFactory.OpenSession()) { AnimeGroupRepository repGroups = new AnimeGroupRepository(); AnimeGroup grp = repGroups.GetByID(groupID); if (grp != null) { Contract_AnimeGroup basegrp = grp.ToContract(grp.GetUserRecord(session, userid)); ret.MediaContainer.Title1 = ret.MediaContainer.Title2 = basegrp.GroupName; List <AnimeSeries> sers2 = grp.GetSeries(session); ret.MediaContainer.Art = KodiHelper.GetRandomFanartFromSeries(sers2, session); foreach (AnimeGroup grpChild in grp.GetChildGroups()) { Video v = StatsCache.Instance.StatKodiGroupsCache[userid][grpChild.AnimeGroupID]; v.Type = "show"; if (v != null) { retGroups.Add(v.Clone()); } } foreach (AnimeSeries ser in grp.GetSeries()) { Contract_AnimeSeries cserie = ser.ToContract(ser.GetUserRecord(session, userid), true); Video v = KodiHelper.FromSerieWithPossibleReplacement(cserie, ser, userid); v.AirDate = ser.AirDate.HasValue ? ser.AirDate.Value : DateTime.MinValue; v.Group = basegrp; retGroups.Add(v); } } ret.Childrens = retGroups.OrderBy(a => a.AirDate).ToList(); return(ret.GetStream()); } }
public static Filter FilterFromAnimeGroup(AnimeGroup grp, int uid) { Filter ob = new Filter(); ob.type = "show"; ob.name = grp.GroupName; ob.id = grp.AnimeGroupID; ob.url = APIHelper.ConstructFilterIdUrl(grp.AnimeGroupID); ob.size = -1; ob.viewed = -1; foreach (AnimeSeries ser in grp.GetSeries().Randomize()) { 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((int)fanart.ImageType, fanart.ImageID), index = ob.art.fanart.Count }); ob.art.thumb.Add(new Art() { url = APIHelper.ConstructImageLinkFromTypeAndId((int)fanart.ImageType, fanart.ImageID), index = ob.art.thumb.Count }); } if (banner != null) { ob.art.banner.Add(new Art() { url = APIHelper.ConstructImageLinkFromTypeAndId((int)banner.ImageType, banner.ImageID), index = ob.art.banner.Count }); } if (ob.art.fanart.Count > 0) { break; } } } return(ob); }
public System.IO.Stream GetItemsFromGroup(int userid, string GroupId, HistoryInfo info) { PlexObject ret = new PlexObject(PlexHelper.NewMediaContainer(MediaContainerTypes.Show, info, false)); if (!ret.Init()) { return(new MemoryStream()); } int groupID; int.TryParse(GroupId, out groupID); List <Video> retGroups = new List <Video>(); if (groupID == -1) { return(new MemoryStream()); } using (var session = JMMService.SessionFactory.OpenSession()) { AnimeGroupRepository repGroups = new AnimeGroupRepository(); AnimeGroup grp = repGroups.GetByID(groupID); if (grp != null) { Contract_AnimeGroup basegrp = grp.ToContract(grp.GetUserRecord(session, userid)); List <AnimeSeries> sers2 = grp.GetSeries(session); foreach (AnimeGroup grpChild in grp.GetChildGroups()) { Video v = StatsCache.Instance.StatPlexGroupsCache[userid][grpChild.AnimeGroupID]; if (v != null) { retGroups.Add(v.Clone(), info); } } foreach (AnimeSeries ser in grp.GetSeries()) { Contract_AnimeSeries cserie = ser.ToContract(ser.GetUserRecord(session, userid), true); Video v = PlexHelper.FromSerieWithPossibleReplacement(cserie, ser, ser.GetAnime(), userid); v.AirDate = ser.AirDate.HasValue ? ser.AirDate.Value : DateTime.MinValue; v.Group = basegrp; retGroups.Add(v, info); } } ret.Childrens = PlexHelper.ConvertToDirectoryIfNotUnique(retGroups.OrderBy(a => a.AirDate).ToList()); return(ret.GetStream()); } }
public void Delete(int id) { AnimeGroup cr = GetByID(id); if (cr != null) { // delete user records AnimeGroup_UserRepository repUsers = new AnimeGroup_UserRepository(); foreach (AnimeGroup_User grpUser in repUsers.GetByGroupID(id)) { repUsers.Delete(grpUser.AnimeGroup_UserID); } cr.DeleteFromFilters(); Cache.Remove(cr); Changes.Remove(cr.AnimeGroupID); } int parentID = 0; using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { if (cr != null) { if (cr.AnimeGroupParentID.HasValue) { parentID = cr.AnimeGroupParentID.Value; } session.Delete(cr); transaction.Commit(); } } } if (parentID > 0) { logger.Trace("Updating group stats by group from AnimeGroupRepository.Delete: {0}", parentID); AnimeGroup ngrp = GetByID(parentID); if (ngrp != null) { this.Save(ngrp, false, true); } } }
public void Save(AnimeGroup grp, bool updategrpcontractstats, bool recursive, bool verifylockedFilters = true) { using (var session = JMMService.SessionFactory.OpenSession()) { HashSet <GroupFilterConditionType> types; lock (grp) { if (grp.AnimeGroupID == 0) //We are creating one, and we need the AnimeGroupID before Update the contracts { grp.Contract = null; using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(grp); transaction.Commit(); } } types = grp.UpdateContract(session, updategrpcontractstats); //Types will contains the affected GroupFilterConditionTypes using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(grp); transaction.Commit(); } Changes.AddOrUpdate(grp.AnimeGroupID); Cache.Update(grp); } if (verifylockedFilters) { GroupFilterRepository.CreateOrVerifyTagsAndYearsFilters(false, grp.Contract.Stat_AllTags, grp.Contract.Stat_AirDate_Min); //This call will create extra years or tags if the Group have a new year or tag grp.UpdateGroupFilters(types, null); } if (grp.AnimeGroupParentID.HasValue && recursive) { AnimeGroup pgroup = GetByID(session, grp.AnimeGroupParentID.Value); // This will avoid the recursive error that would be possible, it won't update it, but that would be // the least of the issues if (pgroup != null && pgroup.AnimeGroupParentID == grp.AnimeGroupID) { Save(pgroup, updategrpcontractstats, true, verifylockedFilters); } } } }
/// <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="AnimeGroup"/>.</returns> private AnimeGroup CreateTempAnimeGroup(ISessionWrapper session) { DateTime now = DateTime.Now; var tempGroup = new 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); }
private static void GetValidVideoRecursive(AnimeGroupRepository repGroups, GroupFilter f, int userid, Directory pp) { GroupFilterRepository repo = new GroupFilterRepository(); List <GroupFilter> gfs = repo.GetByParentID(f.GroupFilterID).Where(a => a.GroupsIds.ContainsKey(userid) && a.GroupsIds[userid].Count > 0).ToList(); foreach (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) { AnimeGroup ag = repGroups.GetByID(grp); Video v = ag.GetPlexContract(userid); if (v?.Art != null && v.Thumb != null) { pp.Art = Helper.ReplaceSchemeHost(v.Art); pp.Thumb = Helper.ReplaceSchemeHost(v.Thumb); break; } } } } if (pp.Art != null) { break; } } if (pp.Art == null) { foreach (GroupFilter gg in gfs.Where(a => (a.FilterType & (int)GroupFilterType.Directory) == (int)GroupFilterType.Directory && a.InvisibleInClients == 0)) { GetValidVideoRecursive(repGroups, gg, userid, pp); if (pp.Art != null) { break; } } } pp.LeafCount = gfs.Count.ToString(); pp.ViewedLeafCount = "0"; }
/// <summary> /// Gets or creates an <see cref="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="AnimeGroup"/> to use for the specified series.</returns> /// <exception cref="ArgumentNullException"><paramref name="session"/> or <paramref name="series"/> is <c>null</c>.</exception> public AnimeGroup GetOrCreateSingleGroupForSeries(ISessionWrapper session, AnimeSeries series) { if (session == null) { throw new ArgumentNullException(nameof(session)); } if (series == null) { throw new ArgumentNullException(nameof(series)); } 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.Select(id => RepoFactory.AnimeSeries.GetByAnimeID(id)) .Where(s => s != null) .Select(s => RepoFactory.AnimeGroup.GetByID(s.AnimeGroupID)) .FirstOrDefault(); if (animeGroup == null) { // No existing group was found, so create a new one int mainAnimeId = grpCalculator.GetGroupAnimeId(series.AniDB_ID); AnimeSeries mainSeries = _animeSeriesRepo.GetByAnimeID(mainAnimeId); animeGroup = CreateAnimeGroup(session, 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 AnimeGroup(); animeGroup.Populate(series, DateTime.Now); RepoFactory.AnimeGroup.Save(animeGroup, true, true); } return(animeGroup); }
/// <summary> /// Creates <see cref="AnimeGroup"/> that contain <see cref="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="AnimeSeries"/> to create groups for.</param> /// <returns>A sequence of the created <see cref="AnimeGroup"/>s.</returns> private IEnumerable <AnimeGroup> AutoCreateGroupsWithRelatedSeries(ISessionWrapper session, IReadOnlyCollection <AnimeSeries> seriesList) { _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 <AnimeGroup, IReadOnlyCollection <AnimeSeries> > >(seriesList.Count); foreach (var groupAndSeries in seriesByGroup) { int mainAnimeId = groupAndSeries.Key; AnimeSeries mainSeries = groupAndSeries.FirstOrDefault(series => series.AniDB_ID == mainAnimeId); AnimeGroup animeGroup = CreateAnimeGroup(session, mainSeries, mainAnimeId, now); newGroupsToSeries.Add(new Tuple <AnimeGroup, IReadOnlyCollection <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 (AnimeSeries series in groupAndSeries.Item2) { series.AnimeGroupID = groupAndSeries.Item1.AnimeGroupID; } } _log.Info("Generated {0} AnimeGroups", newGroupsToSeries.Count); return(newGroupsToSeries.Select(gts => gts.Item1)); }
private 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) { logger.Trace("Updating group stats by group from AnimeSeriesRepository.Delete: {0}", cr.AnimeGroupID); AnimeGroup oldGroup = RepoFactory.AnimeGroup.GetByID(cr.AnimeGroupID); if (oldGroup != null) { RepoFactory.AnimeGroup.Save(oldGroup, true, true); } } }; }
public void Delete(int id) { AnimeGroup cr = GetByID(id); if (cr != null) { // delete user records AnimeGroup_UserRepository repUsers = new AnimeGroup_UserRepository(); foreach (AnimeGroup_User grpUser in repUsers.GetByGroupID(id)) { repUsers.Delete(grpUser.AnimeGroup_UserID); } } int parentID = 0; using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { if (cr != null) { if (cr.AnimeGroupParentID.HasValue) { parentID = cr.AnimeGroupParentID.Value; } session.Delete(cr); transaction.Commit(); } } } if (parentID > 0) { logger.Trace("Updating group stats by group from AnimeGroupRepository.Delete: {0}", parentID); StatsCache.Instance.UpdateUsingGroup(parentID); } }
public static Directory DirectoryFromFilter(AnimeGroupRepository repGroups, IProvider prov, 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.ToString(); pp.AnimeType = JMMContracts.PlexAndKodi.AnimeTypes.AnimeGroupFilter.ToString(); if ((gg.FilterType & (int)GroupFilterType.Directory) == (int)GroupFilterType.Directory) { GetValidVideoRecursive(repGroups, gg, userid, pp); } else if (gg.GroupsIds.ContainsKey(userid)) { HashSet <int> groups = gg.GroupsIds[userid]; if (groups.Count != 0) { pp.LeafCount = groups.Count.ToString(); pp.ViewedLeafCount = "0"; foreach (int grp in groups) { AnimeGroup ag = repGroups.GetByID(grp); Video v = ag.GetPlexContract(userid); if (v?.Art != null && v.Thumb != null) { pp.Art = Helper.ReplaceSchemeHost(v.Art); pp.Thumb = Helper.ReplaceSchemeHost(v.Thumb); break; } } return(pp); } } return(pp); }
public void Delete(int id) { int oldGroupID = 0; using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { AnimeSeries cr = GetByID(id); if (cr != null) { Cache.Remove(cr); // delete user records AnimeSeries_UserRepository repUsers = new AnimeSeries_UserRepository(); foreach (AnimeSeries_User grpUser in repUsers.GetBySeriesID(id)) { repUsers.Delete(grpUser.AnimeSeries_UserID); } Changes.Remove(cr.AnimeSeriesID); oldGroupID = cr.AnimeGroupID; session.Delete(cr); transaction.Commit(); cr.DeleteFromFilters(); } } } if (oldGroupID > 0) { logger.Trace("Updating group stats by group from AnimeSeriesRepository.Delete: {0}", oldGroupID); AnimeGroupRepository repGroups = new AnimeGroupRepository(); AnimeGroup oldGroup = repGroups.GetByID(oldGroupID); if (oldGroup != null) { repGroups.Save(oldGroup, true, true); } } }
public static Filter FilterFromGroupFilter(GroupFilter gg, int uid) { Filter ob = new Filter(); ob.type = "show"; ob.name = gg.GroupFilterName; ob.id = gg.GroupFilterID; ob.url = APIHelper.ConstructFilterIdUrl(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) { AnimeGroup ag = RepoFactory.AnimeGroup.GetByID(grp); Video v = ag.GetPlexContract(uid); if (v?.Art != null && v.Thumb != null) { ob.art.fanart.Add(new Art() { url = APIHelper.ConstructImageLinkFromRest(v.Art), index = 0 }); ob.art.thumb.Add(new Art() { url = APIHelper.ConstructImageLinkFromRest(v.Thumb), index = 0 }); break; } } } } return(ob); }
/// <summary> /// Creates an <see cref="AnimeGroup"/> instance. /// </summary> /// <remarks> /// This method only creates an <see cref="AnimeGroup"/> instance. It does NOT save it to the database. /// </remarks> /// <param name="session">The NHibernate session.</param> /// <param name="mainSeries">The <see cref="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="AnimeGroup"/>.</returns> private AnimeGroup CreateAnimeGroup(ISessionWrapper session, AnimeSeries mainSeries, int mainAnimeId, DateTime now) { AnimeGroup animeGroup = new AnimeGroup(); string groupName = null; if (mainSeries != null) { animeGroup.Populate(mainSeries, now); groupName = mainSeries.GetSeriesName(session); } else // The anime chosen as the group's main anime doesn't actually have a series { 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); }
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()); } }
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()); } }
public void Save(AnimeSeries obj, bool updateGroups, bool onlyupdatestats, bool skipgroupfilters = false) { bool newSeries = false; AnimeGroup oldGroup = null; AnimeGroupRepository repGroups = new AnimeGroupRepository(); bool isMigrating = false; lock (obj) { if (obj.AnimeSeriesID == 0) { newSeries = true; // a new series } else { // get the old version from the DB AnimeSeries oldSeries; using (var session = JMMService.SessionFactory.OpenSession()) { oldSeries = session.Get <AnimeSeries>(obj.AnimeSeriesID); } if (oldSeries != null) { // means we are moving series to a different group if (oldSeries.AnimeGroupID != obj.AnimeGroupID) { oldGroup = repGroups.GetByID(oldSeries.AnimeGroupID); AnimeGroup newGroup = repGroups.GetByID(obj.AnimeGroupID); if (newGroup != null && newGroup.GroupName.Equals("AAA Migrating Groups AAA")) { isMigrating = true; } newSeries = true; } } } if (newSeries && !isMigrating) { using (var session = JMMService.SessionFactory.OpenSession()) { obj.Contract = null; // populate the database using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(obj); transaction.Commit(); } } } HashSet <GroupFilterConditionType> types = obj.UpdateContract(onlyupdatestats); using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(obj); transaction.Commit(); } } if (!skipgroupfilters && !isMigrating) { GroupFilterRepository.CreateOrVerifyTagsAndYearsFilters(false, obj.Contract?.AniDBAnime?.AniDBAnime?.AllTags, obj.Contract?.AniDBAnime?.AniDBAnime?.AirDate); //This call will create extra years or tags if the Group have a new year or tag obj.UpdateGroupFilters(types, null); } Cache.Update(obj); Changes.AddOrUpdate(obj.AnimeSeriesID); } if (updateGroups && !isMigrating) { if (newSeries) { logger.Trace("Updating group stats by series from AnimeSeriesRepository.Save: {0}", obj.AnimeSeriesID); AnimeGroup grp = repGroups.GetByID(obj.AnimeGroupID); if (grp != null) { repGroups.Save(grp, true, true); } } if (oldGroup != null) { logger.Trace("Updating group stats by group from AnimeSeriesRepository.Save: {0}", oldGroup.AnimeGroupID); repGroups.Save(oldGroup, true, true); } } }
private System.IO.Stream GetGroupsFromFilter(int userid, string GroupFilterId) { KodiObject ret = new KodiObject(KodiHelper.NewMediaContainer("Filters", true)); if (!ret.Init()) { return(new MemoryStream()); } //List<Joint> retGroups = new List<Joint>(); List <Video> retGroups = new List <Video>(); try { int groupFilterID; int.TryParse(GroupFilterId, out groupFilterID); using (var session = JMMService.SessionFactory.OpenSession()) { if (groupFilterID == -1) { return(new MemoryStream()); } DateTime start = DateTime.Now; GroupFilterRepository repGF = new GroupFilterRepository(); GroupFilter gf; if (groupFilterID == -999) { // all groups gf = new GroupFilter(); gf.GroupFilterName = "All"; } else { gf = repGF.GetByID(session, groupFilterID); if (gf == null) { return(new MemoryStream()); } } ret.MediaContainer.Title2 = ret.MediaContainer.Title1 = gf.GroupFilterName; //Contract_GroupFilterExtended contract = gf.ToContractExtended(user); AnimeGroupRepository repGroups = new AnimeGroupRepository(); List <AnimeGroup> allGrps = repGroups.GetAll(session); TimeSpan ts = DateTime.Now - start; string msg = string.Format("Got groups for filter DB: {0} - {1} in {2} ms", gf.GroupFilterName, allGrps.Count, ts.TotalMilliseconds); logger.Info(msg); start = DateTime.Now; if ((StatsCache.Instance.StatUserGroupFilter.ContainsKey(userid)) && (StatsCache.Instance.StatUserGroupFilter[userid].ContainsKey(gf.GroupFilterID))) { HashSet <int> groups = StatsCache.Instance.StatUserGroupFilter[userid][gf.GroupFilterID]; var tas = StatsCache.Instance.StatKodiGroupsCache; foreach (AnimeGroup grp in allGrps) { if (groups.Contains(grp.AnimeGroupID)) { try { //if (grp.GroupName == "Rockman.EXE") //{ // int x = grp.MissingEpisodeCount; //} Video v = StatsCache.Instance.StatKodiGroupsCache[userid][grp.AnimeGroupID]; if (v != null) { //proper naming AniDB_Anime anim = grp.Anime[0]; v.OriginalTitle = ""; foreach (AniDB_Anime_Title title in anim.GetTitles()) { if (title.TitleType == "official" || title.TitleType == "main") { v.OriginalTitle += "{" + title.TitleType + ":" + title.Language + "}" + title.Title + "|"; } } v.OriginalTitle = v.OriginalTitle.Substring(0, v.OriginalTitle.Length - 1); //proper naming end retGroups.Add(v.Clone()); } } catch (Exception e) { int x = retGroups.Count; } } } } ts = DateTime.Now - start; msg = string.Format("Got groups for filter EVAL: {0} - {1} in {2} ms", gf.GroupFilterName, retGroups.Count, ts.TotalMilliseconds); logger.Info(msg); if ((groupFilterID == -999) || (gf.SortCriteriaList.Count == 0)) { ret.Childrens = retGroups.OrderBy(a => a.Group.SortName).ToList(); return(ret.GetStream()); } List <Contract_AnimeGroup> grps = retGroups.Select(a => a.Group).ToList(); List <SortPropOrFieldAndDirection> sortCriteria = new List <SortPropOrFieldAndDirection>(); foreach (GroupFilterSortingCriteria g in gf.SortCriteriaList) { sortCriteria.Add(GroupFilterHelper.GetSortDescription(g.SortType, g.SortDirection)); } grps = Sorting.MultiSort(grps, sortCriteria); List <Video> joints2 = new List <Video>(); foreach (Contract_AnimeGroup gr in grps) { foreach (Video j in retGroups) { if (j.Group == gr) { //experiment AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository(); AnimeSeriesRepository repSeries = new AnimeSeriesRepository(); AnimeGroup ag = repGroups.GetByID(gr.AnimeGroupID); List <AnimeSeries> sers = ag.GetAllSeries(); AnimeSeries ser = sers[0]; AniDB_Anime anim = ser.GetAnime(); j.CharactersList = new List <Characters>(); Characters c = new Characters(); c.CharactersList = GetCharactersFromAniDB(anim); j.CharactersList.Add(c); //experimentEND //proper naming j.OriginalTitle = ""; foreach (AniDB_Anime_Title title in anim.GetTitles()) { if (title.TitleType == "official" || title.TitleType == "main") { j.OriginalTitle += "{" + title.TitleType + ":" + title.Language + "}" + title.Title + "|"; } } j.OriginalTitle = j.OriginalTitle.Substring(0, j.OriginalTitle.Length - 1); //proper naming end //community support //CrossRef_AniDB_TraktV2Repository repCrossRef = new CrossRef_AniDB_TraktV2Repository(); //List<CrossRef_AniDB_TraktV2> Trakt = repCrossRef.GetByAnimeID(anim.AnimeID); //if (Trakt != null) //{ // if (Trakt.Count > 0) // { // j.Trakt = Trakt[0].TraktID; // } //} //CrossRef_AniDB_TvDBV2Repository repCrossRefV2 = new CrossRef_AniDB_TvDBV2Repository(); //List<CrossRef_AniDB_TvDBV2> TvDB = repCrossRefV2.GetByAnimeID(anim.AnimeID); //if (TvDB != null) //{ // if (TvDB.Count > 0) // { // j.TvDB = TvDB[0].TvDBID.ToString(); // } //} //community support END joints2.Add(j); retGroups.Remove(j); break; } } } ret.Childrens = joints2; ret.MediaContainer.Art = KodiHelper.GetRandomFanartFromVideoList(ret.Childrens); ts = DateTime.Now - start; msg = string.Format("Got groups final: {0} - {1} in {2} ms", gf.GroupFilterName, retGroups.Count, ts.TotalMilliseconds); logger.Info(msg); return(ret.GetStream()); } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } return(new MemoryStream()); }
public static Video GenerateFromAnimeGroup(ISession session, AnimeGroup grp, int userid, List <AnimeSeries> allSeries) { Contract_AnimeGroup cgrp = grp.GetUserContract(userid); int subgrpcnt = grp.GetAllChildGroups().Count; if ((cgrp.Stat_SeriesCount == 1) && (subgrpcnt == 0)) { AnimeSeries ser = JMMServiceImplementation.GetSeriesForGroup(grp.AnimeGroupID, allSeries); if (ser != null) { Contract_AnimeSeries cserie = ser.GetUserContract(userid); if (cserie != null) { Video v = GenerateFromSeries(cserie, ser, ser.GetAnime(session), userid); v.AirDate = ser.AirDate; v.UpdatedAt = ser.LatestEpisodeAirDate.HasValue ? ser.LatestEpisodeAirDate.Value.ToUnixTime() : null; v.Group = cgrp; return(v); } } } else { AnimeSeries ser = grp.DefaultAnimeSeriesID.HasValue ? allSeries.FirstOrDefault(a => a.AnimeSeriesID == grp.DefaultAnimeSeriesID.Value) : allSeries.Find(a => a.AirDate != DateTime.MinValue); if ((ser == null) && (allSeries != null && allSeries.Count > 0)) { ser = allSeries[0]; } Contract_AnimeSeries 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 = "" + 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) { List <AnimeTitle> newTitles = new List <AnimeTitle>(); foreach (AniDB_Anime_Title title in ser.GetAnime(session).GetTitles()) { AnimeTitle newTitle = new AnimeTitle(); newTitle.Title = title.Title; newTitle.Language = title.Language; newTitle.Type = title.TitleType; newTitles.Add(newTitle); } 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(session).Contract?.AniDBAnime?.Characters != null) { foreach (Contract_AniDB_Character c in ser.GetAnime(session).Contract.AniDBAnime.Characters) { string ch = c?.CharName; Contract_AniDB_Seiyuu seiyuu = c?.Seiyuu; if (!string.IsNullOrEmpty(ch)) { RoleTag t = new RoleTag(); t.Value = seiyuu?.SeiyuuName; if (seiyuu != null) { t.TagPicture = Helper.ConstructSeiyuuImage(seiyuu.AniDB_SeiyuuID); } t.Role = ch; t.RoleDescription = c?.CharDescription; t.RolePicture = Helper.ConstructCharacterImage(c.CharID); v.Roles.Add(t); } } } } return(v); } return(null); }