public void SaveWatchedStatus(bool watched, int userID, DateTime?watchedDate, bool updateWatchedDate) { AnimeEpisode_UserRepository repEpisodeUsers = new AnimeEpisode_UserRepository(); AnimeEpisode_User epUserRecord = this.GetUserRecord(userID); if (watched) { // lets check if an update is actually required if (epUserRecord != null) { if (epUserRecord.WatchedDate.HasValue && watchedDate.HasValue && epUserRecord.WatchedDate.Value.Equals(watchedDate.Value)) { // this will happen when we are adding a new file for an episode where we already had another file // and the file/episode was watched already return; } } if (epUserRecord == null) { epUserRecord = new AnimeEpisode_User(); epUserRecord.PlayedCount = 0; epUserRecord.StoppedCount = 0; epUserRecord.WatchedCount = 0; } epUserRecord.AnimeEpisodeID = this.AnimeEpisodeID; epUserRecord.AnimeSeriesID = this.AnimeSeriesID; epUserRecord.JMMUserID = userID; epUserRecord.WatchedCount++; if (watchedDate.HasValue) { if (updateWatchedDate) { epUserRecord.WatchedDate = watchedDate.Value; } } if (!epUserRecord.WatchedDate.HasValue) { epUserRecord.WatchedDate = DateTime.Now; } repEpisodeUsers.Save(epUserRecord); } else { if (epUserRecord != null) { repEpisodeUsers.Delete(epUserRecord.AnimeEpisode_UserID); } } }
private static void InitCache(this IDatabase db) { JMMUserRepository.InitCache(); AniDB_AnimeRepository.InitCache(); VideoInfoRepository.InitCache(); VideoLocalRepository.InitCache(); VideoLocal_UserRepository.InitCache(); List <GroupFilter> recalc = GroupFilterRepository.InitCache(); AnimeEpisodeRepository.InitCache(); AnimeEpisode_UserRepository.InitCache(); AnimeSeriesRepository.InitCache(); AnimeSeries_UserRepository.InitCache(); AnimeGroupRepository.InitCache(); AnimeGroup_UserRepository.InitCache(); GroupFilterRepository.InitCacheSecondPart(recalc); DatabaseFixes.ExecuteDatabaseFixes(); db.CleanUpMemory(); }
public Contract_AnimeEpisode GetUserContract(int userid) { lock (_lock) //Make it atomic on creation { AnimeEpisode_User rr = GetUserRecord(userid); if (rr != null) { return(rr.Contract); } rr = new AnimeEpisode_User(); rr.PlayedCount = 0; rr.StoppedCount = 0; rr.WatchedCount = 0; rr.AnimeEpisodeID = this.AnimeEpisodeID; rr.AnimeSeriesID = this.AnimeSeriesID; rr.JMMUserID = userid; rr.WatchedDate = null; AnimeEpisode_UserRepository repo = new AnimeEpisode_UserRepository(); repo.Save(rr); return(rr.Contract); } }
public void UpdateStats(bool watchedStats, bool missingEpsStats, bool updateAllGroupsAbove) { DateTime start = DateTime.Now; DateTime startOverall = DateTime.Now; logger.Info("Starting Updating STATS for SERIES {0} ({1} - {2} - {3})", this.ToString(), watchedStats, missingEpsStats, updateAllGroupsAbove); AnimeSeries_UserRepository repSeriesUser = new AnimeSeries_UserRepository(); AnimeEpisode_UserRepository repEpisodeUser = new AnimeEpisode_UserRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); CrossRef_File_EpisodeRepository repXrefs = new CrossRef_File_EpisodeRepository(); JMMUserRepository repUsers = new JMMUserRepository(); List <JMMUser> allUsers = repUsers.GetAll(); DateTime startEps = DateTime.Now; List <AnimeEpisode> eps = GetAnimeEpisodes(); TimeSpan tsEps = DateTime.Now - startEps; logger.Trace("Got episodes for SERIES {0} in {1}ms", this.ToString(), tsEps.TotalMilliseconds); DateTime startVids = DateTime.Now; List <VideoLocal> vidsTemp = repVids.GetByAniDBAnimeID(this.AniDB_ID); List <CrossRef_File_Episode> crossRefs = repXrefs.GetByAnimeID(this.AniDB_ID); Dictionary <int, List <CrossRef_File_Episode> > dictCrossRefs = new Dictionary <int, List <CrossRef_File_Episode> >(); foreach (CrossRef_File_Episode xref in crossRefs) { if (!dictCrossRefs.ContainsKey(xref.EpisodeID)) { dictCrossRefs[xref.EpisodeID] = new List <CrossRef_File_Episode>(); } dictCrossRefs[xref.EpisodeID].Add(xref); } Dictionary <string, VideoLocal> dictVids = new Dictionary <string, VideoLocal>(); foreach (VideoLocal vid in vidsTemp) { dictVids[vid.Hash] = vid; } TimeSpan tsVids = DateTime.Now - startVids; logger.Trace("Got video locals for SERIES {0} in {1}ms", this.ToString(), tsVids.TotalMilliseconds); if (watchedStats) { foreach (JMMUser juser in allUsers) { //this.WatchedCount = 0; AnimeSeries_User userRecord = GetUserRecord(juser.JMMUserID); if (userRecord == null) { userRecord = new AnimeSeries_User(juser.JMMUserID, this.AnimeSeriesID); } // reset stats userRecord.UnwatchedEpisodeCount = 0; userRecord.WatchedEpisodeCount = 0; userRecord.WatchedCount = 0; userRecord.WatchedDate = null; DateTime startUser = DateTime.Now; List <AnimeEpisode_User> epUserRecords = repEpisodeUser.GetByUserID(juser.JMMUserID); Dictionary <int, AnimeEpisode_User> dictUserRecords = new Dictionary <int, AnimeEpisode_User>(); foreach (AnimeEpisode_User usrec in epUserRecords) { dictUserRecords[usrec.AnimeEpisodeID] = usrec; } TimeSpan tsUser = DateTime.Now - startUser; logger.Trace("Got user records for SERIES {0}/{1} in {2}ms", this.ToString(), juser.Username, tsUser.TotalMilliseconds); foreach (AnimeEpisode ep in eps) { // if the episode doesn't have any files then it won't count towards watched/unwatched counts List <VideoLocal> epVids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { epVids.Add(dictVids[xref.Hash]); } } } } if (epVids.Count == 0) { continue; } if (ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Episode || ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Special) { AnimeEpisode_User epUserRecord = null; if (dictUserRecords.ContainsKey(ep.AnimeEpisodeID)) { epUserRecord = dictUserRecords[ep.AnimeEpisodeID]; } if (epUserRecord != null && epUserRecord.WatchedDate.HasValue) { userRecord.WatchedEpisodeCount++; } else { userRecord.UnwatchedEpisodeCount++; } if (epUserRecord != null) { if (userRecord.WatchedDate.HasValue) { if (epUserRecord.WatchedDate > userRecord.WatchedDate) { userRecord.WatchedDate = epUserRecord.WatchedDate; } } else { userRecord.WatchedDate = epUserRecord.WatchedDate; } userRecord.WatchedCount += epUserRecord.WatchedCount; } } } repSeriesUser.Save(userRecord); } } TimeSpan ts = DateTime.Now - start; logger.Trace("Updated WATCHED stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; if (missingEpsStats) { enAnimeType animeType = enAnimeType.TVSeries; AniDB_Anime aniDB_Anime = this.GetAnime(); if (aniDB_Anime != null) { animeType = aniDB_Anime.AnimeTypeEnum; } MissingEpisodeCount = 0; MissingEpisodeCountGroups = 0; // get all the group status records AniDB_GroupStatusRepository repGrpStat = new AniDB_GroupStatusRepository(); List <AniDB_GroupStatus> grpStatuses = repGrpStat.GetByAnimeID(this.AniDB_ID); // find all the episodes for which the user has a file // from this we can determine what their latest episode number is // find out which groups the user is collecting List <int> userReleaseGroups = new List <int>(); foreach (AnimeEpisode ep in eps) { List <VideoLocal> vids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { vids.Add(dictVids[xref.Hash]); } } } } //List<VideoLocal> vids = ep.VideoLocals; foreach (VideoLocal vid in vids) { AniDB_File anifile = vid.GetAniDBFile(); if (anifile != null) { if (!userReleaseGroups.Contains(anifile.GroupID)) { userReleaseGroups.Add(anifile.GroupID); } } } } int latestLocalEpNumber = 0; EpisodeList epReleasedList = new EpisodeList(animeType); EpisodeList epGroupReleasedList = new EpisodeList(animeType); foreach (AnimeEpisode ep in eps) { //List<VideoLocal> vids = ep.VideoLocals; if (ep.EpisodeTypeEnum != AniDBAPI.enEpisodeType.Episode) { continue; } List <VideoLocal> vids = new List <VideoLocal>(); if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID)) { foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID]) { if (xref.EpisodeID == ep.AniDB_EpisodeID) { if (dictVids.ContainsKey(xref.Hash)) { vids.Add(dictVids[xref.Hash]); } } } } AniDB_Episode aniEp = ep.AniDB_Episode; int thisEpNum = aniEp.EpisodeNumber; if (thisEpNum > latestLocalEpNumber && vids.Count > 0) { latestLocalEpNumber = thisEpNum; } // does this episode have a file released // does this episode have a file released by the group the user is collecting bool epReleased = false; bool epReleasedGroup = false; foreach (AniDB_GroupStatus gs in grpStatuses) { if (gs.LastEpisodeNumber >= thisEpNum) { epReleased = true; } if (userReleaseGroups.Contains(gs.GroupID) && gs.HasGroupReleasedEpisode(thisEpNum)) { epReleasedGroup = true; } } try { epReleasedList.Add(ep, (!epReleased || vids.Count != 0)); epGroupReleasedList.Add(ep, (!epReleasedGroup || vids.Count != 0)); } catch (Exception e) { logger.Trace("Error {0}", e.ToString()); throw; } } foreach (EpisodeList.StatEpisodes eplst in epReleasedList) { if (!eplst.Available) { MissingEpisodeCount++; } } foreach (EpisodeList.StatEpisodes eplst in epGroupReleasedList) { if (!eplst.Available) { MissingEpisodeCountGroups++; } } this.LatestLocalEpisodeNumber = latestLocalEpNumber; } ts = DateTime.Now - start; logger.Trace("Updated MISSING EPS stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; AnimeSeriesRepository rep = new AnimeSeriesRepository(); rep.Save(this); if (updateAllGroupsAbove) { foreach (AnimeGroup grp in AllGroupsAbove) { grp.UpdateStats(watchedStats, missingEpsStats); } } ts = DateTime.Now - start; logger.Trace("Updated GROUPS ABOVE stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds); start = DateTime.Now; TimeSpan tsOverall = DateTime.Now - startOverall; logger.Info("Finished Updating STATS for SERIES {0} in {1}ms ({2} - {3} - {4})", this.ToString(), tsOverall.TotalMilliseconds, watchedStats, missingEpsStats, updateAllGroupsAbove); }
public void ToggleWatchedStatus(bool watched, bool updateOnline, DateTime?watchedDate, bool updateStats, bool updateStatsCache, int userID, bool scrobbleTrakt, bool updateWatchedDate) { VideoLocalRepository repVids = new VideoLocalRepository(); AnimeEpisodeRepository repEpisodes = new AnimeEpisodeRepository(); AniDB_FileRepository repAniFile = new AniDB_FileRepository(); CrossRef_File_EpisodeRepository repCross = new CrossRef_File_EpisodeRepository(); VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository(); JMMUserRepository repUsers = new JMMUserRepository(); AnimeEpisode_UserRepository repEpisodeUsers = new AnimeEpisode_UserRepository(); JMMUser user = repUsers.GetByID(userID); if (user == null) { return; } List <JMMUser> aniDBUsers = repUsers.GetAniDBUsers(); // update the video file to watched int mywatched = watched ? 1 : 0; if (user.IsAniDBUser == 0) { SaveWatchedStatus(watched, userID, watchedDate, updateWatchedDate); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { SaveWatchedStatus(watched, juser.JMMUserID, watchedDate, updateWatchedDate); } } } // now lets find all the associated AniDB_File record if there is one if (user.IsAniDBUser == 1) { AniDB_File aniFile = repAniFile.GetByHash(this.Hash); if (aniFile != null) { aniFile.IsWatched = mywatched; if (watched) { if (watchedDate.HasValue) { aniFile.WatchedDate = watchedDate; } else { aniFile.WatchedDate = DateTime.Now; } } else { aniFile.WatchedDate = null; } repAniFile.Save(aniFile, false); } if (updateOnline) { if ((watched && ServerSettings.AniDB_MyList_SetWatched) || (!watched && ServerSettings.AniDB_MyList_SetUnwatched)) { CommandRequest_UpdateMyListFileStatus cmd = new CommandRequest_UpdateMyListFileStatus(this.Hash, watched, false, watchedDate.HasValue ? Utils.GetAniDBDateAsSeconds(watchedDate) : 0); cmd.Save(); } } } // now find all the episode records associated with this video file // but we also need to check if theer are any other files attached to this episode with a watched // status, AnimeSeries ser = null; // get all files associated with this episode List <CrossRef_File_Episode> xrefs = repCross.GetByHash(this.Hash); if (watched) { // find the total watched percentage // eg one file can have a % = 100 // or if 2 files make up one episodes they will each have a % = 50 foreach (CrossRef_File_Episode xref in xrefs) { // get the episode for this file AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xref.EpisodeID); if (ep == null) { continue; } // get all the files for this episode int epPercentWatched = 0; foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs) { VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID); if (vidUser != null) { // if not null means it is watched epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched > 95) { ser = ep.GetAnimeSeries(); if (user.IsAniDBUser == 0) { ep.SaveWatchedStatus(true, userID, watchedDate, updateWatchedDate); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { ep.SaveWatchedStatus(true, juser.JMMUserID, watchedDate, updateWatchedDate); } } } if (scrobbleTrakt && !string.IsNullOrEmpty(ServerSettings.Trakt_Username) && !string.IsNullOrEmpty(ServerSettings.Trakt_Password)) { CommandRequest_TraktShowScrobble cmdScrobble = new CommandRequest_TraktShowScrobble(ep.AnimeEpisodeID); cmdScrobble.Save(); } if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password)) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } } } } else { // if setting a file to unwatched only set the episode unwatched, if ALL the files are unwatched foreach (CrossRef_File_Episode xrefEp in xrefs) { AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xrefEp.EpisodeID); if (ep == null) { continue; } ser = ep.GetAnimeSeries(); // get all the files for this episode int epPercentWatched = 0; foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs) { VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID); if (vidUser != null) { epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched < 95) { if (user.IsAniDBUser == 0) { ep.SaveWatchedStatus(false, userID, watchedDate, true); } else { // if the user is AniDB user we also want to update any other AniDB // users to keep them in sync foreach (JMMUser juser in aniDBUsers) { if (juser.IsAniDBUser == 1) { ep.SaveWatchedStatus(false, juser.JMMUserID, watchedDate, true); } } } CommandRequest_TraktShowEpisodeUnseen cmdUnseen = new CommandRequest_TraktShowEpisodeUnseen(ep.AnimeEpisodeID); cmdUnseen.Save(); } } if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password)) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } } // update stats for groups and series if (ser != null && updateStats) { // update all the groups above this series in the heirarchy ser.UpdateStats(true, true, true); //ser.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, true); } if (ser != null && updateStatsCache) { StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } }
public static UserInfo GetUserInfoData(string dashType = "", string vidPlayer = "") { try { if (string.IsNullOrEmpty(ServerSettings.AniDB_Username)) { return(null); } UserInfo uinfo = new UserInfo(); uinfo.DateTimeUpdated = DateTime.Now; uinfo.DateTimeUpdatedUTC = 0; // Optional JMM Desktop data uinfo.DashboardType = null; uinfo.VideoPlayer = vidPlayer; System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); try { if (a != null) { uinfo.JMMServerVersion = Utils.GetApplicationVersion(a); } } catch { } uinfo.UsernameHash = Utils.GetMd5Hash(ServerSettings.AniDB_Username); uinfo.DatabaseType = ServerSettings.DatabaseType; uinfo.WindowsVersion = Utils.GetOSInfo(); uinfo.TraktEnabled = ServerSettings.Trakt_IsEnabled ? 1 : 0; uinfo.MALEnabled = string.IsNullOrEmpty(ServerSettings.MAL_Username) ? 0 : 1; uinfo.CountryLocation = ""; // this field is not actually used uinfo.LastEpisodeWatchedAsDate = DateTime.Now.AddDays(-5); JMMUserRepository repUsers = new JMMUserRepository(); uinfo.LocalUserCount = (int)repUsers.GetTotalRecordCount(); VideoLocalRepository repVids = new VideoLocalRepository(); uinfo.FileCount = repVids.GetTotalRecordCount(); AnimeEpisode_UserRepository repEps = new AnimeEpisode_UserRepository(); AnimeEpisode_User rec = repEps.GetLastWatchedEpisode(); uinfo.LastEpisodeWatched = 0; if (rec != null) { uinfo.LastEpisodeWatched = Utils.GetAniDBDateAsSeconds(rec.WatchedDate); } return(uinfo); } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return(null); } }
public AnimeEpisode_User GetUserRecord(ISession session, int userID) { AnimeEpisode_UserRepository repEpUser = new AnimeEpisode_UserRepository(); return(repEpUser.GetByUserIDAndEpisodeID(session, userID, this.AnimeEpisodeID)); }