private void SaveWatchedStatus(bool watched, int userID, DateTime?watchedDate, bool updateWatchedDate) { VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository(); VideoLocal_User vidUserRecord = this.GetUserRecord(userID); if (watched) { if (vidUserRecord == null) { vidUserRecord = new VideoLocal_User(); vidUserRecord.WatchedDate = DateTime.Now; } vidUserRecord.JMMUserID = userID; vidUserRecord.VideoLocalID = this.VideoLocalID; if (watchedDate.HasValue) { if (updateWatchedDate) { vidUserRecord.WatchedDate = watchedDate.Value; } } repVidUsers.Save(vidUserRecord); } else { if (vidUserRecord != null) { repVidUsers.Delete(vidUserRecord.VideoLocal_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 override void ProcessCommand() { logger.Info("Processing CommandRequest_SyncMyList"); try { // we will always assume that an anime was downloaded via http first ScheduledUpdateRepository repSched = new ScheduledUpdateRepository(); AniDB_FileRepository repAniFile = new AniDB_FileRepository(); VideoLocalRepository repVidLocals = new VideoLocalRepository(); ScheduledUpdate sched = repSched.GetByUpdateType((int)ScheduledUpdateType.AniDBMyListSync); if (sched == null) { sched = new ScheduledUpdate(); sched.UpdateType = (int)ScheduledUpdateType.AniDBMyListSync; sched.UpdateDetails = ""; } else { int freqHours = Utils.GetScheduledHours(ServerSettings.AniDB_MyList_UpdateFrequency); // if we have run this in the last 24 hours and are not forcing it, then exit TimeSpan tsLastRun = DateTime.Now - sched.LastUpdate; if (tsLastRun.TotalHours < freqHours) { if (!ForceRefresh) { return; } } } AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList(); cmd.Init(ServerSettings.AniDB_Username, ServerSettings.AniDB_Password); enHelperActivityType ev = cmd.Process(); if (ev == enHelperActivityType.GotMyListHTTP && cmd.MyListItems.Count > 1) { int totalItems = 0; int watchedItems = 0; int modifiedItems = 0; double pct = 0; // 2. find files locally for the user, which are not recorded on anidb // and then add them to anidb Dictionary <int, Raw_AniDB_MyListFile> onlineFiles = new Dictionary <int, Raw_AniDB_MyListFile>(); foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems) { onlineFiles[myitem.FileID] = myitem; } Dictionary <string, AniDB_File> dictAniFiles = new Dictionary <string, AniDB_File>(); List <AniDB_File> allAniFiles = repAniFile.GetAll(); foreach (AniDB_File anifile in allAniFiles) { dictAniFiles[anifile.Hash] = anifile; } int missingFiles = 0; foreach (VideoLocal vid in repVidLocals.GetAll()) { if (!dictAniFiles.ContainsKey(vid.Hash)) { continue; } int fileID = dictAniFiles[vid.Hash].FileID; if (!onlineFiles.ContainsKey(fileID)) { // means we have found a file in our local collection, which is not recorded online CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash); cmdAddFile.Save(); missingFiles++; } } logger.Info(string.Format("MYLIST Missing Files: {0} Added to queue for inclusion", missingFiles)); JMMUserRepository repUsers = new JMMUserRepository(); List <JMMUser> aniDBUsers = repUsers.GetAniDBUsers(); VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository(); CrossRef_File_EpisodeRepository repFileEp = new CrossRef_File_EpisodeRepository(); // 1 . sync mylist items foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems) { // ignore files mark as deleted by the user if (myitem.State == (int)AniDBFileStatus.Deleted) { continue; } totalItems++; if (myitem.IsWatched) { watchedItems++; } //calculate percentage pct = (double)totalItems / (double)cmd.MyListItems.Count * (double)100; string spct = pct.ToString("#0.0"); string hash = string.Empty; AniDB_File anifile = repAniFile.GetByFileID(myitem.FileID); if (anifile != null) { hash = anifile.Hash; } else { // look for manually linked files List <CrossRef_File_Episode> xrefs = repFileEp.GetByEpisodeID(myitem.EpisodeID); foreach (CrossRef_File_Episode xref in xrefs) { if (xref.CrossRefSource != (int)CrossRefSource.AniDB) { hash = xref.Hash; break; } } } if (!string.IsNullOrEmpty(hash)) { // find the video associated with this record VideoLocal vl = repVidLocals.GetByHash(hash); if (vl == null) { continue; } foreach (JMMUser juser in aniDBUsers) { bool localStatus = false; int? jmmUserID = null; // doesn't matter which anidb user we use jmmUserID = juser.JMMUserID; VideoLocal_User userRecord = vl.GetUserRecord(juser.JMMUserID); if (userRecord != null) { localStatus = true; } string action = ""; if (localStatus != myitem.IsWatched) { if (localStatus == true) { // local = watched, anidb = unwatched if (ServerSettings.AniDB_MyList_ReadUnwatched) { modifiedItems++; if (jmmUserID.HasValue) { vl.ToggleWatchedStatus(myitem.IsWatched, false, myitem.WatchedDate, false, false, jmmUserID.Value, false, true); } action = "Used AniDB Status"; } } else { // means local is un-watched, and anidb is watched if (ServerSettings.AniDB_MyList_ReadWatched) { modifiedItems++; if (jmmUserID.HasValue) { vl.ToggleWatchedStatus(true, false, myitem.WatchedDate, false, false, jmmUserID.Value, false, true); } action = "Updated Local record to Watched"; } } string msg = string.Format( "MYLISTDIFF:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}", vl.FullServerPath, localStatus, myitem.IsWatched, action); logger.Info(msg); } } //string msg = string.Format("MYLIST:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}", // vl.FullServerPath, localStatus, myitem.IsWatched, action); //logger.Info(msg); } } // now update all stats Importer.UpdateAllStats(); logger.Info("Process MyList: {0} Items, {1} Watched, {2} Modified", totalItems, watchedItems, modifiedItems); sched.LastUpdate = DateTime.Now; repSched.Save(sched); } } catch (Exception ex) { logger.Error("Error processing CommandRequest_SyncMyList: {0} ", ex.ToString()); return; } }
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 VideoLocal_User GetUserRecord(int userID) { VideoLocal_UserRepository repVidUser = new VideoLocal_UserRepository(); return(repVidUser.GetByUserIDAndVideoLocalID(userID, this.VideoLocalID)); }