/* TESTS A int Anime id G int Group id F int File version (ie 1, 2, 3 etc) Can use ! , > , >= , < , <= E text Episode number H text Episode Type (E=episode, S=special, T=trailer, C=credit, P=parody, O=other) X text Total number of episodes R text Rip source [Blu-ray, unknown, camcorder, TV, DTV, VHS, VCD, SVCD, LD, DVD, HKDVD, www] T text Type [unknown, TV, OVA, Movie, Other, web] Y int Year D text Dub language (one of the audio tracks) [japanese, english, ...] S text Sub language (one of the subtitle tracks) [japanese, english, ...] C text Video Codec (one of the video tracks) [H264/AVC, DivX5/6, unknown, VP Other, WMV9 (also WMV3), XviD, ...] J text Audio Codec (one of the audio tracks) [AC3, FLAC, MP3 CBR, MP3 VBR, Other, unknown, Vorbis (Ogg Vorbis) ...] I text Tag has a value. Do not use %, i.e. I(eng) [eng, kan, rom, ...] Z int Video Bith Depth [8,10] W int Video Resolution Width [720, 1280, 1920, ...] U int Video Resolution Height [576, 720, 1080, ...] M null empty - test whether the file is manually linked */ /* TESTS - Alphabetical A int Anime id C text Video Codec (one of the video tracks) [H264/AVC, DivX5/6, unknown, VP Other, WMV9 (also WMV3), XviD, ...] D text Dub language (one of the audio tracks) [japanese, english, ...] E text Episode number F int File version (ie 1, 2, 3 etc) Can use ! , > , >= , < , <= G int Group id H text Episode Type (E=episode, S=special, T=trailer, C=credit, P=parody, O=other) I text Tag has a value. Do not use %, i.e. I(eng) [eng, kan, rom, ...] J text Audio Codec (one of the audio tracks) [AC3, FLAC, MP3 CBR, MP3 VBR, Other, unknown, Vorbis (Ogg Vorbis) ...] M null empty - test whether the file is manually linked N null empty - test whether the file has any episodes linked to it R text Rip source [Blu-ray, unknown, camcorder, TV, DTV, VHS, VCD, SVCD, LD, DVD, HKDVD, www] S text Sub language (one of the subtitle tracks) [japanese, english, ...] T text Type [unknown, TV, OVA, Movie, Other, web] U int Video Resolution Height [576, 720, 1080, ...] W int Video Resolution Width [720, 1280, 1920, ...] X text Total number of episodes Y int Year Z int Video Bith Depth [8,10] */ /// <summary> /// Test if the file belongs to the specified anime /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <returns></returns> private static bool EvaluateTestA(string test, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } int animeID = 0; int.TryParse(test, out animeID); if (notCondition) return animeID != episodes[0].AnimeID; else return animeID == episodes[0].AnimeID; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
// default constructor public AniDB_FileRequest(AniDB_File data) { this.Anime_GroupName = data.Anime_GroupName; this.Anime_GroupNameShort = data.Anime_GroupNameShort; //this.AnimeID = data.AnimeID; this.CRC = data.CRC; this.Episode_Rating = data.Episode_Rating; this.Episode_Votes = data.Episode_Votes; this.File_AudioCodec = data.File_AudioCodec; this.File_Description = data.File_Description; this.File_FileExtension = data.File_FileExtension; this.File_LengthSeconds = data.File_LengthSeconds; this.File_ReleaseDate = data.File_ReleaseDate; this.File_Source = data.File_Source; this.File_VideoCodec = data.File_VideoCodec; this.File_VideoResolution = data.File_VideoResolution; this.FileID = data.FileID; this.FileName = data.FileName; this.FileSize = data.FileSize; this.GroupID = data.GroupID; this.Hash = data.Hash; this.MD5 = data.MD5; this.SHA1 = data.SHA1; this.SubtitlesRAW = data.SubtitlesRAWForWebCache; this.LanguagesRAW = data.LanguagesRAWForWebCache; this.EpisodesRAW = data.EpisodesRAWForWebCache; this.EpisodesPercentRAW = data.EpisodesPercentRAWForWebCache; }
public static void Send_AniDB_File(AniDB_File data) { if (!ServerSettings.WebCache_AniDB_File_Send) return; string uri = string.Format("http://{0}/AddAniDB_File.aspx", ServerSettings.WebCache_Address); AniDB_FileRequest req = new AniDB_FileRequest(data); string xml = req.ToXML(); SendData(uri, xml); }
public FileHashInput(AniDB_File anifile) { ED2K = anifile.Hash; CRC32 = anifile.CRC; MD5 = anifile.MD5; SHA1 = anifile.SHA1; FileSize = anifile.FileSize; this.Username = ServerSettings.AniDB_Username; if (ServerSettings.WebCache_Anonymous) this.Username = Constants.AnonWebCacheUsername; this.AuthGUID = string.Empty; }
public void Save(AniDB_File obj, bool updateStats) { using (var session = JMMService.SessionFactory.OpenSession()) { // populate the database using (var transaction = session.BeginTransaction()) { session.SaveOrUpdate(obj); transaction.Commit(); } } if (updateStats) { logger.Trace("Updating group stats by file from AniDB_FileRepository.Save: {0}", obj.Hash); StatsCache.Instance.UpdateUsingAniDBFile(obj.Hash); } }
private static void PerformActionOnFileName(ref string newFileName, string action, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { // find the first test int posStart = action.IndexOf(" "); if (posStart < 0) return; string actionType = action.Substring(0, posStart); string parameter = action.Substring(posStart + 1, action.Length - posStart - 1); try { // action is to add the the new file name if (actionType.Trim().Equals(Constants.FileRenameReserved.Add, StringComparison.InvariantCultureIgnoreCase)) PerformActionOnFileNameADD(ref newFileName, parameter, vid, aniFile, episodes, anime, vi); if (actionType.Trim().Equals(Constants.FileRenameReserved.Replace, StringComparison.InvariantCultureIgnoreCase)) PerformActionOnFileNameREPLACE(ref newFileName, parameter, vid, aniFile, episodes, anime, vi); } catch (Exception ex) { throw; } }
private static bool EvaluateTestW(string test, VideoLocal vid, AniDB_File aniFile, VideoInfo vi) { try { bool notCondition = false; bool greaterThan = false; bool greaterThanEqual = false; bool lessThan = false; bool lessThanEqual = false; ProcessNumericalOperators(ref test, ref notCondition, ref greaterThan, ref greaterThanEqual, ref lessThan, ref lessThanEqual); if (vi == null) return false; int testWidth = 0; int.TryParse(test, out testWidth); int width = 0; if (aniFile != null) width = Utils.GetVideoWidth(aniFile.File_VideoResolution); if (width == 0) width = Utils.GetVideoWidth(vi.VideoResolution); bool hasFileVersionOperator = greaterThan | greaterThanEqual | lessThan | lessThanEqual; if (!hasFileVersionOperator) { if (!notCondition) { if (testWidth == width) return true; else return false; } else { if (testWidth == width) return false; else return true; } } else { if (greaterThan) { if (width > testWidth) return true; else return false; } if (greaterThanEqual) { if (width >= testWidth) return true; else return false; } if (lessThan) { if (width < testWidth) return true; else return false; } if (lessThanEqual) { if (width <= testWidth) return true; else return false; } } return false; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
private static bool EvaluateTest(string line, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { line = line.Trim(); // determine if this line has a test foreach (char c in validTests) { string prefix = string.Format("IF {0}(", c); if (line.ToUpper().StartsWith(prefix)) { // find the first test int posStart = line.IndexOf('('); int posEnd = line.IndexOf(')'); int posStartOrig = posStart; if (posEnd < posStart) return false; string condition = line.Substring(posStart + 1, posEnd - posStart - 1); bool passed = EvaluateTest(c, condition, vid, aniFile, episodes, anime, vi); // check for OR's and AND's bool foundAND= false; while (posStart > 0) { posStart = line.IndexOf(';', posStart); if (posStart > 0) { foundAND = true; string thisLineRemainder = line.Substring(posStart + 1, line.Length - posStart - 1).Trim(); // remove any spacing //char thisTest = line.Substring(posStart + 1, 1).ToCharArray()[0]; char thisTest = thisLineRemainder.Substring(0, 1).ToCharArray()[0]; int posStartNew = thisLineRemainder.IndexOf('('); int posEndNew = thisLineRemainder.IndexOf(')'); condition = thisLineRemainder.Substring(posStartNew + 1, posEndNew - posStartNew - 1); bool thisPassed = EvaluateTest(thisTest, condition, vid, aniFile, episodes, anime, vi); if (!passed || !thisPassed) return false; posStart = posStart + 1; } } // if the first test passed, and we only have OR's left then it is an automatic success if (passed) return true; if (!foundAND) { posStart = posStartOrig; while (posStart > 0) { posStart = line.IndexOf(',', posStart); if (posStart > 0) { string thisLineRemainder = line.Substring(posStart + 1, line.Length - posStart - 1).Trim(); // remove any spacing //char thisTest = line.Substring(posStart + 1, 1).ToCharArray()[0]; char thisTest = thisLineRemainder.Substring(0, 1).ToCharArray()[0]; int posStartNew = thisLineRemainder.IndexOf('('); int posEndNew = thisLineRemainder.IndexOf(')'); condition = thisLineRemainder.Substring(posStartNew + 1, posEndNew - posStartNew - 1); bool thisPassed = EvaluateTest(thisTest, condition, vid, aniFile, episodes, anime, vi); if (thisPassed) return true; posStart = posStart + 1; } } } } } return false; }
/// <summary> /// Test if the file is manually linked /// No test parameter is required /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <returns></returns> private static bool EvaluateTestM(string test, AniDB_File aniFile, List<AniDB_Episode> episodes) { try { bool notCondition = false; if (!string.IsNullOrEmpty(test) && test.Substring(0, 1).Equals("!")) notCondition = true; // for a file to be manually linked it must NOT have an anifile, but does need episodes attached bool manuallyLinked = false; if (aniFile == null) { manuallyLinked = true; if (episodes == null || episodes.Count == 0) manuallyLinked = false; } if (notCondition) return !manuallyLinked; else return manuallyLinked; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
/// <summary> /// Test if the file has any episodes linked /// No test parameter is required /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <returns></returns> private static bool EvaluateTestN(string test, AniDB_File aniFile, List<AniDB_Episode> episodes) { try { bool notCondition = false; if (!string.IsNullOrEmpty(test) && test.Substring(0, 1).Equals("!")) notCondition = true; bool epsLinked = false; if (aniFile == null) { if (episodes != null && episodes.Count > 0) epsLinked = true; } else epsLinked = true; if (notCondition) return !epsLinked; else return epsLinked; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
private static bool EvaluateTest(char testChar, string testCondition, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { testCondition = testCondition.Trim(); switch (testChar) { case 'A': return EvaluateTestA(testCondition, vid, aniFile, episodes); case 'G': return EvaluateTestG(testCondition, vid, aniFile); case 'D': return EvaluateTestD(testCondition, vid, aniFile); case 'S': return EvaluateTestS(testCondition, vid, aniFile); case 'F': return EvaluateTestF(testCondition, vid, aniFile); case 'R': return EvaluateTestR(testCondition, vid, aniFile); case 'Z': return EvaluateTestZ(testCondition, vid, vi); case 'T': return EvaluateTestT(testCondition, vid, anime); case 'Y': return EvaluateTestY(testCondition, vid, anime); case 'E': return EvaluateTestE(testCondition, vid, episodes); case 'H': return EvaluateTestH(testCondition, vid, episodes); case 'X': return EvaluateTestX(testCondition, vid, anime); case 'C': return EvaluateTestC(testCondition, vid, aniFile); case 'J': return EvaluateTestJ(testCondition, vid, aniFile); case 'I': return EvaluateTestI(testCondition, vid, aniFile, episodes, anime, vi); case 'W': return EvaluateTestW(testCondition, vid, aniFile, vi); case 'U': return EvaluateTestU(testCondition, vid, aniFile, vi); case 'M': return EvaluateTestM(testCondition, aniFile, episodes); case 'N': return EvaluateTestN(testCondition, aniFile, episodes); } return false; }
private static bool EvaluateTestU(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; bool greaterThan = false; bool greaterThanEqual = false; bool lessThan = false; bool lessThanEqual = false; ProcessNumericalOperators(ref test, ref notCondition, ref greaterThan, ref greaterThanEqual, ref lessThan, ref lessThanEqual); if (vid == null) return false; int testHeight = 0; int.TryParse(test, out testHeight); int height = 0; if (aniFile != null) height = Utils.GetVideoHeight(aniFile.File_VideoResolution); if (height == 0) height = Utils.GetVideoHeight(vid.VideoResolution); bool hasFileVersionOperator = greaterThan | greaterThanEqual | lessThan | lessThanEqual; if (!hasFileVersionOperator) { if (!notCondition) { if (testHeight == height) return true; else return false; } else { if (testHeight == height) return false; else return true; } } else { if (greaterThan) { if (height > testHeight) return true; else return false; } if (greaterThanEqual) { if (height >= testHeight) return true; else return false; } if (lessThan) { if (height < testHeight) return true; else return false; } if (lessThanEqual) { if (height <= testHeight) return true; else return false; } } return false; } catch (Exception ex) { logger.Error( ex,ex.ToString()); return false; } }
/// <summary> /// Test if this file has the specified Dub (audio) language /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <returns></returns> private static bool EvaluateTestD(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } if (aniFile == null) return false; if (notCondition) { foreach (Language lan in aniFile.Languages) { if (lan.LanguageName.Trim().Equals(test.Trim(), StringComparison.InvariantCultureIgnoreCase)) return false; } return true; } else { foreach (Language lan in aniFile.Languages) { if (lan.LanguageName.Trim().Equals(test.Trim(), StringComparison.InvariantCultureIgnoreCase)) return true; } return false; } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
/// <summary> /// Test if the file belongs to the specified group /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <param name="aniFile"></param> /// <returns></returns> private static bool EvaluateTestG(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } int groupID = 0; //Leave groupID at 0 if "unknown". if (String.Compare(test, "unknown", StringComparison.OrdinalIgnoreCase) != 0) { int.TryParse(test, out groupID); } if (notCondition) return groupID != aniFile.GroupID; else return groupID == aniFile.GroupID; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
public Contract_VideoDetailed ToContractDetailed(int userID) { Contract_VideoDetailed contract = new Contract_VideoDetailed(); // get the cross ref episode List <CrossRef_File_Episode> xrefs = this.EpisodeCrossRefs; if (xrefs.Count == 0) { return(null); } contract.Percentage = xrefs[0].Percentage; contract.EpisodeOrder = xrefs[0].EpisodeOrder; contract.CrossRefSource = xrefs[0].CrossRefSource; contract.AnimeEpisodeID = xrefs[0].EpisodeID; contract.VideoLocal_FilePath = this.FilePath; contract.VideoLocal_Hash = this.Hash; contract.VideoLocal_FileSize = this.FileSize; contract.VideoLocalID = this.VideoLocalID; contract.VideoLocal_IsIgnored = this.IsIgnored; contract.VideoLocal_IsVariation = this.IsVariation; contract.VideoLocal_MD5 = this.MD5; contract.VideoLocal_SHA1 = this.SHA1; contract.VideoLocal_CRC32 = this.CRC32; contract.VideoLocal_HashSource = this.HashSource; VideoLocal_User userRecord = this.GetUserRecord(userID); if (userRecord == null) { contract.VideoLocal_IsWatched = 0; } else { contract.VideoLocal_IsWatched = 1; } // Import Folder ImportFolder ns = this.ImportFolder; // to prevent multiple db calls if (ns != null) { contract.ImportFolderID = ns.ImportFolderID; contract.ImportFolderLocation = ns.ImportFolderLocation; contract.ImportFolderName = ns.ImportFolderName; } // video info VideoInfo vi = this.VideoInfo; // to prevent multiple db calls if (vi != null) { contract.VideoInfo_AudioBitrate = vi.AudioBitrate; contract.VideoInfo_AudioCodec = vi.AudioCodec; contract.VideoInfo_Duration = vi.Duration; contract.VideoInfo_VideoBitrate = vi.VideoBitrate; contract.VideoInfo_VideoBitDepth = vi.VideoBitDepth; contract.VideoInfo_VideoCodec = vi.VideoCodec; contract.VideoInfo_VideoFrameRate = vi.VideoFrameRate; contract.VideoInfo_VideoResolution = vi.VideoResolution; contract.VideoInfo_VideoInfoID = vi.VideoInfoID; } // AniDB File AniDB_File anifile = this.GetAniDBFile(); // to prevent multiple db calls if (anifile != null) { contract.AniDB_Anime_GroupName = anifile.Anime_GroupName; contract.AniDB_Anime_GroupNameShort = anifile.Anime_GroupNameShort; contract.AniDB_AnimeID = anifile.AnimeID; contract.AniDB_CRC = anifile.CRC; contract.AniDB_Episode_Rating = anifile.Episode_Rating; contract.AniDB_Episode_Votes = anifile.Episode_Votes; contract.AniDB_File_AudioCodec = anifile.File_AudioCodec; contract.AniDB_File_Description = anifile.File_Description; contract.AniDB_File_FileExtension = anifile.File_FileExtension; contract.AniDB_File_LengthSeconds = anifile.File_LengthSeconds; contract.AniDB_File_ReleaseDate = anifile.File_ReleaseDate; contract.AniDB_File_Source = anifile.File_Source; contract.AniDB_File_VideoCodec = anifile.File_VideoCodec; contract.AniDB_File_VideoResolution = anifile.File_VideoResolution; contract.AniDB_FileID = anifile.FileID; contract.AniDB_GroupID = anifile.GroupID; contract.AniDB_MD5 = anifile.MD5; contract.AniDB_SHA1 = anifile.SHA1; contract.AniDB_File_FileVersion = anifile.FileVersion; // languages contract.LanguagesAudio = anifile.LanguagesRAW; contract.LanguagesSubtitle = anifile.SubtitlesRAW; } else { contract.AniDB_Anime_GroupName = ""; contract.AniDB_Anime_GroupNameShort = ""; contract.AniDB_CRC = ""; contract.AniDB_File_AudioCodec = ""; contract.AniDB_File_Description = ""; contract.AniDB_File_FileExtension = ""; contract.AniDB_File_Source = ""; contract.AniDB_File_VideoCodec = ""; contract.AniDB_File_VideoResolution = ""; contract.AniDB_MD5 = ""; contract.AniDB_SHA1 = ""; contract.AniDB_File_FileVersion = 1; // languages contract.LanguagesAudio = ""; contract.LanguagesSubtitle = ""; } AniDB_ReleaseGroup relGroup = this.ReleaseGroup; // to prevent multiple db calls if (relGroup != null) { contract.ReleaseGroup = relGroup.ToContract(); } else { contract.ReleaseGroup = null; } return(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 override void ProcessCommand() { logger.Info("Get AniDB file info: {0}", VideoLocalID); try { AniDB_FileRepository repAniFile = new AniDB_FileRepository(); VideoLocalRepository repVids = new VideoLocalRepository(); vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) return; AniDB_File aniFile = repAniFile.GetByHashAndFileSize(vlocal.Hash, vlocal.FileSize); /*// get anidb file info from web cache if (aniFile == null && ServerSettings.WebCache_AniDB_File_Get) { AniDB_FileRequest fr = XMLService.Get_AniDB_File(vlocal.Hash, vlocal.FileSize); if (fr != null) { aniFile = new AniDB_File(); aniFile.Populate(fr); //overwrite with local file name string localFileName = Path.GetFileName(vlocal.FilePath); aniFile.FileName = localFileName; repAniFile.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); StatsCache.Instance.UpdateUsingAniDBFile(vlocal.Hash); } }*/ Raw_AniDB_File fileInfo = null; if (aniFile == null || ForceAniDB) fileInfo = JMMService.AnidbProcessor.GetFileInfo(vlocal); if (fileInfo != null) { // save to the database if (aniFile == null) aniFile = new AniDB_File(); aniFile.Populate(fileInfo); //overwrite with local file name string localFileName = Path.GetFileName(vlocal.FilePath); aniFile.FileName = localFileName; repAniFile.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); if (!string.IsNullOrEmpty(fileInfo.OtherEpisodesRAW)) { string[] epIDs = fileInfo.OtherEpisodesRAW.Split(','); foreach (string epid in epIDs) { int id = 0; if (int.TryParse(epid, out id)) { CommandRequest_GetEpisode cmdEp = new CommandRequest_GetEpisode(id); cmdEp.Save(); } } } StatsCache.Instance.UpdateUsingAniDBFile(vlocal.Hash); } } catch (Exception ex) { logger.Error("Error processing CommandRequest_GetFile: {0} - {1}", VideoLocalID, ex.ToString()); return; } }
public List <Contract_VideoDetailed> GetVideoDetailedContracts(int userID) { VideoLocalRepository repVids = new VideoLocalRepository(); List <Contract_VideoDetailed> contracts = new List <Contract_VideoDetailed>(); // get all the cross refs foreach (CrossRef_File_Episode xref in FileCrossRefs) { Contract_VideoDetailed contract = new Contract_VideoDetailed(); contract.Percentage = xref.Percentage; contract.EpisodeOrder = xref.EpisodeOrder; contract.CrossRefSource = xref.CrossRefSource; contract.AnimeEpisodeID = this.AnimeEpisodeID; // get the video file // we will assume that it is unique by hash/episodeid VideoLocal vid = repVids.GetByHash(xref.Hash); if (vid != null) { contract.VideoLocal_FilePath = vid.FilePath; contract.VideoLocal_Hash = vid.Hash; contract.VideoLocal_FileSize = vid.FileSize; contract.VideoLocalID = vid.VideoLocalID; contract.VideoLocal_MD5 = vid.MD5; contract.VideoLocal_SHA1 = vid.SHA1; contract.VideoLocal_CRC32 = vid.CRC32; contract.VideoLocal_HashSource = vid.HashSource; VideoLocal_User vidUser = vid.GetUserRecord(userID); //AnimeEpisode_User userRecord = this.GetUserRecord(userID); if (vidUser == null) { contract.VideoLocal_IsWatched = 0; contract.VideoLocal_WatchedDate = null; } else { contract.VideoLocal_IsWatched = 1; contract.VideoLocal_WatchedDate = vidUser.WatchedDate; } contract.VideoLocal_IsIgnored = vid.IsIgnored; contract.VideoLocal_IsVariation = vid.IsVariation; // Import Folder ImportFolder ns = vid.ImportFolder; // to prevent multiple db calls contract.ImportFolderID = ns.ImportFolderID; contract.ImportFolderLocation = ns.ImportFolderLocation; contract.ImportFolderName = ns.ImportFolderName; // video info VideoInfo vi = vid.VideoInfo; // to prevent multiple db calls contract.VideoInfo_AudioBitrate = vi.AudioBitrate; contract.VideoInfo_AudioCodec = vi.AudioCodec; contract.VideoInfo_Duration = vi.Duration; contract.VideoInfo_VideoBitrate = vi.VideoBitrate; contract.VideoInfo_VideoBitDepth = vi.VideoBitDepth; contract.VideoInfo_VideoCodec = vi.VideoCodec; contract.VideoInfo_VideoFrameRate = vi.VideoFrameRate; contract.VideoInfo_VideoResolution = vi.VideoResolution; contract.VideoInfo_VideoInfoID = vi.VideoInfoID; // AniDB File AniDB_File anifile = vid.GetAniDBFile(); // to prevent multiple db calls if (anifile != null) { contract.AniDB_Anime_GroupName = anifile.Anime_GroupName; contract.AniDB_Anime_GroupNameShort = anifile.Anime_GroupNameShort; contract.AniDB_AnimeID = anifile.AnimeID; contract.AniDB_CRC = anifile.CRC; contract.AniDB_Episode_Rating = anifile.Episode_Rating; contract.AniDB_Episode_Votes = anifile.Episode_Votes; contract.AniDB_File_AudioCodec = anifile.File_AudioCodec; contract.AniDB_File_Description = anifile.File_Description; contract.AniDB_File_FileExtension = anifile.File_FileExtension; contract.AniDB_File_LengthSeconds = anifile.File_LengthSeconds; contract.AniDB_File_ReleaseDate = anifile.File_ReleaseDate; contract.AniDB_File_Source = anifile.File_Source; contract.AniDB_File_VideoCodec = anifile.File_VideoCodec; contract.AniDB_File_VideoResolution = anifile.File_VideoResolution; contract.AniDB_FileID = anifile.FileID; contract.AniDB_GroupID = anifile.GroupID; contract.AniDB_MD5 = anifile.MD5; contract.AniDB_SHA1 = anifile.SHA1; contract.AniDB_File_FileVersion = anifile.FileVersion; contract.AniDB_File_IsCensored = anifile.IsCensored; contract.AniDB_File_IsDeprecated = anifile.IsDeprecated; contract.AniDB_File_InternalVersion = anifile.InternalVersion; // languages contract.LanguagesAudio = anifile.LanguagesRAW; contract.LanguagesSubtitle = anifile.SubtitlesRAW; } else { contract.AniDB_Anime_GroupName = ""; contract.AniDB_Anime_GroupNameShort = ""; contract.AniDB_CRC = ""; contract.AniDB_File_AudioCodec = ""; contract.AniDB_File_Description = ""; contract.AniDB_File_FileExtension = ""; contract.AniDB_File_Source = ""; contract.AniDB_File_VideoCodec = ""; contract.AniDB_File_VideoResolution = ""; contract.AniDB_MD5 = ""; contract.AniDB_SHA1 = ""; contract.AniDB_File_FileVersion = 1; // languages contract.LanguagesAudio = ""; contract.LanguagesSubtitle = ""; } AniDB_ReleaseGroup relGroup = vid.ReleaseGroup; // to prevent multiple db calls if (relGroup != null) { contract.ReleaseGroup = relGroup.ToContract(); } else { contract.ReleaseGroup = null; } contracts.Add(contract); } } return(contracts); }
private static void PerformActionOnFileNameADD(ref string newFileName, string action, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { // TODO Remove illegal characters // TODO check for double episodes // TODO allow for synonyms to be used // TODO allow a strategy for episode numbers // fixed 0 padding, look at number of episodes in series newFileName += action; newFileName = newFileName.Replace("'", ""); #region Anime ID if (action.Trim().ToLower().Contains(Constants.FileRenameTag.AnimeID.ToLower())) { newFileName = newFileName.Replace(Constants.FileRenameTag.AnimeID, anime.AnimeID.ToString()); } #endregion #region English title if (action.Trim().ToLower().Contains(Constants.FileRenameTag.AnimeNameEnglish.ToLower())) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.English, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { newFileName = newFileName.Replace(Constants.FileRenameTag.AnimeNameEnglish, ti.Title); } } } } #endregion #region Romaji title if (action.Trim().ToLower().Contains(Constants.FileRenameTag.AnimeNameRomaji.ToLower())) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.Romaji, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { newFileName = newFileName.Replace(Constants.FileRenameTag.AnimeNameRomaji, ti.Title); } } } } #endregion #region Kanji title if (action.Trim().ToLower().Contains(Constants.FileRenameTag.AnimeNameKanji.ToLower())) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.Kanji, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { newFileName = newFileName.Replace(Constants.FileRenameTag.AnimeNameKanji, ti.Title); } } } } #endregion #region Episode Number if (action.Trim().ToLower().Contains(Constants.FileRenameTag.EpisodeNumber.ToLower())) { int zeroPadding = 2; string prefix = ""; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Credits) prefix = "C"; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Other) prefix = "O"; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Parody) prefix = "P"; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Special) prefix = "S"; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Trailer) prefix = "T"; int epCount = 1; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Episode) epCount = anime.EpisodeCountNormal; if (episodes[0].EpisodeTypeEnum == AniDBAPI.enEpisodeType.Special) epCount = anime.EpisodeCountSpecial; if (epCount > 10 && epCount < 100) zeroPadding = 2; if (epCount > 99 && epCount < 1000) zeroPadding = 3; if (epCount > 999) zeroPadding = 4; string episodeNumber = ""; // normal episode episodeNumber = prefix + episodes[0].EpisodeNumber.ToString().PadLeft(zeroPadding, '0'); if (episodes.Count > 1) episodeNumber += "-" + episodes[episodes.Count - 1].EpisodeNumber.ToString().PadLeft(zeroPadding, '0'); newFileName = newFileName.Replace(Constants.FileRenameTag.EpisodeNumber, episodeNumber); } #endregion #region Episode name (english) if (action.Trim().ToLower().Contains(Constants.FileRenameTag.EpisodeNameEnglish.ToLower())) newFileName = newFileName.Replace(Constants.FileRenameTag.EpisodeNameEnglish, episodes[0].EnglishName); #endregion #region Episode name (romaji) if (action.Trim().ToLower().Contains(Constants.FileRenameTag.EpisodeNameRomaji.ToLower())) newFileName = newFileName.Replace(Constants.FileRenameTag.EpisodeNameRomaji, episodes[0].RomajiName); #endregion #region sub group name (short) if (action.Trim().ToLower().Contains(Constants.FileRenameTag.GroupShortName.ToLower())) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.GroupShortName, aniFile.Anime_GroupNameShort); } #endregion #region sub group name (long) if (action.Trim().ToLower().Contains(Constants.FileRenameTag.GroupLongName.ToLower())) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.GroupLongName, aniFile.Anime_GroupName); } #endregion #region ED2k hash (upper) if (action.Trim().Contains(Constants.FileRenameTag.ED2KUpper)) { newFileName = newFileName.Replace(Constants.FileRenameTag.ED2KUpper, vid.Hash.ToUpper()); } #endregion #region ED2k hash (lower) if (action.Trim().Contains(Constants.FileRenameTag.ED2KLower)) { newFileName = newFileName.Replace(Constants.FileRenameTag.ED2KLower, vid.Hash.ToLower()); } #endregion #region CRC (upper) if (action.Trim().Contains(Constants.FileRenameTag.CRCUpper)) { string crc = vid.CRC32; if (string.IsNullOrEmpty(crc) && aniFile != null) crc = aniFile.CRC; if (!string.IsNullOrEmpty(crc)) { crc = crc.ToUpper(); newFileName = newFileName.Replace(Constants.FileRenameTag.CRCUpper, crc); } } #endregion #region CRC (lower) if (action.Trim().Contains(Constants.FileRenameTag.CRCLower)) { string crc = vid.CRC32; if (string.IsNullOrEmpty(crc) && aniFile != null) crc = aniFile.CRC; if (!string.IsNullOrEmpty(crc)) { crc = crc.ToLower(); newFileName = newFileName.Replace(Constants.FileRenameTag.CRCLower, crc); } } #endregion #region File Version if (action.Trim().Contains(Constants.FileRenameTag.FileVersion)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.FileVersion, aniFile.FileVersion.ToString()); } #endregion #region Audio languages (dub) if (action.Trim().Contains(Constants.FileRenameTag.DubLanguage)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.DubLanguage, aniFile.LanguagesRAW); } #endregion #region Subtitle languages (sub) if (action.Trim().Contains(Constants.FileRenameTag.SubLanguage)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.SubLanguage, aniFile.SubtitlesRAW); } #endregion #region Video Codec if (action.Trim().Contains(Constants.FileRenameTag.VideoCodec)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.VideoCodec, aniFile.File_VideoCodec); } #endregion #region Audio Codec if (action.Trim().Contains(Constants.FileRenameTag.AudioCodec)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.AudioCodec, aniFile.File_AudioCodec); } #endregion #region Video Bit Depth if (action.Trim().Contains(Constants.FileRenameTag.VideoBitDepth)) { newFileName = newFileName.Replace(Constants.FileRenameTag.VideoBitDepth, vi.VideoBitDepth); } #endregion #region Video Source if (action.Trim().Contains(Constants.FileRenameTag.Source)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.Source, aniFile.File_Source); } #endregion #region Anime Type if (action.Trim().Contains(Constants.FileRenameTag.Type)) { newFileName = newFileName.Replace(Constants.FileRenameTag.Type, anime.AnimeTypeRAW); } #endregion #region Video Resolution if (action.Trim().Contains(Constants.FileRenameTag.Resolution)) { string res = ""; bool hasResolution = true; if (aniFile != null) { res = aniFile.File_VideoResolution; if (aniFile.File_VideoResolution.Equals("0x0", StringComparison.InvariantCultureIgnoreCase)) hasResolution = false; if (aniFile.File_VideoResolution.Equals(Constants.FileRenameReserved.Unknown, StringComparison.InvariantCultureIgnoreCase)) hasResolution = false; } else hasResolution = false; if (!hasResolution) { // try the video info if (vi != null) res = vi.VideoResolution; } newFileName = newFileName.Replace(Constants.FileRenameTag.Resolution, res.Trim()); } #endregion #region Year if (action.Trim().Contains(Constants.FileRenameTag.Year)) { newFileName = newFileName.Replace(Constants.FileRenameTag.Year, anime.BeginYear.ToString()); } #endregion #region File ID if (action.Trim().Contains(Constants.FileRenameTag.FileID)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.FileID, aniFile.FileID.ToString()); } #endregion #region Episode ID if (action.Trim().Contains(Constants.FileRenameTag.EpisodeID)) { newFileName = newFileName.Replace(Constants.FileRenameTag.EpisodeID, episodes[0].EpisodeID.ToString()); } #endregion #region Group ID if (action.Trim().Contains(Constants.FileRenameTag.GroupID)) { if (aniFile != null) newFileName = newFileName.Replace(Constants.FileRenameTag.GroupID, aniFile.GroupID.ToString()); } #endregion #region Original File Name if (action.Trim().Contains(Constants.FileRenameTag.OriginalFileName)) { // remove the extension first if (aniFile != null) { string ext = Path.GetExtension(aniFile.FileName); string partial = aniFile.FileName.Substring(0, aniFile.FileName.Length - ext.Length); newFileName = newFileName.Replace(Constants.FileRenameTag.OriginalFileName, partial); } } #endregion #region Censored if (action.Trim().Contains(Constants.FileRenameTag.Censored)) { newFileName = newFileName.Replace(Constants.FileRenameTag.Censored, "cen"); } #endregion #region Deprecated if (action.Trim().Contains(Constants.FileRenameTag.Deprecated)) { newFileName = newFileName.Replace(Constants.FileRenameTag.Deprecated, "depr"); } #endregion }
private void ProcessFile_AniDB(VideoLocal vidLocal) { logger.Trace("Checking for AniDB_File record for: {0} --- {1}", vidLocal.Hash, vidLocal.FileName); // check if we already have this AniDB_File info in the database lock (vidLocal) { AniDB_File aniFile = null; if (!ForceAniDB) { aniFile = RepoFactory.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) logger.Trace("AniDB_File record not found"); } int animeID = 0; if (aniFile == null) { // get info from AniDB logger.Debug("Getting AniDB_File record from AniDB...."); Raw_AniDB_File fileInfo = JMMService.AnidbProcessor.GetFileInfo(vidLocal); if (fileInfo != null) { // check if we already have a record aniFile = RepoFactory.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) aniFile = new AniDB_File(); aniFile.Populate(fileInfo); //overwrite with local file name string localFileName = vidLocal.FileName; aniFile.FileName = localFileName; RepoFactory.AniDB_File.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); if (!string.IsNullOrEmpty(fileInfo.OtherEpisodesRAW)) { string[] epIDs = fileInfo.OtherEpisodesRAW.Split(','); foreach (string epid in epIDs) { int id = 0; if (int.TryParse(epid, out id)) { CommandRequest_GetEpisode cmdEp = new CommandRequest_GetEpisode(id); cmdEp.Save(); } } } animeID = aniFile.AnimeID; } } bool missingEpisodes = false; // if we still haven't got the AniDB_File Info we try the web cache or local records if (aniFile == null) { // check if we have any records from previous imports List<CrossRef_File_Episode> crossRefs = RepoFactory.CrossRef_File_Episode.GetByHash(vidLocal.Hash); if (crossRefs == null || crossRefs.Count == 0) { // lets see if we can find the episode/anime info from the web cache if (ServerSettings.WebCache_XRefFileEpisode_Get) { List<JMMServer.Providers.Azure.CrossRef_File_Episode> xrefs = JMMServer.Providers.Azure.AzureWebAPI.Get_CrossRefFileEpisode(vidLocal); crossRefs = new List<CrossRef_File_Episode>(); if (xrefs == null || xrefs.Count == 0) { logger.Debug( "Cannot find AniDB_File record or get cross ref from web cache record so exiting: {0}", vidLocal.ED2KHash); return; } else { foreach (JMMServer.Providers.Azure.CrossRef_File_Episode xref in xrefs) { CrossRef_File_Episode xrefEnt = new CrossRef_File_Episode(); xrefEnt.Hash = vidLocal.ED2KHash; xrefEnt.FileName = vidLocal.FileName; xrefEnt.FileSize = vidLocal.FileSize; xrefEnt.CrossRefSource = (int) JMMServer.CrossRefSource.WebCache; xrefEnt.AnimeID = xref.AnimeID; xrefEnt.EpisodeID = xref.EpisodeID; xrefEnt.Percentage = xref.Percentage; xrefEnt.EpisodeOrder = xref.EpisodeOrder; bool duplicate = false; foreach (CrossRef_File_Episode xrefcheck in crossRefs) { if (xrefcheck.AnimeID == xrefEnt.AnimeID && xrefcheck.EpisodeID == xrefEnt.EpisodeID && xrefcheck.Hash == xrefEnt.Hash) duplicate = true; } if (!duplicate) { crossRefs.Add(xrefEnt); // in this case we need to save the cross refs manually as AniDB did not provide them RepoFactory.CrossRef_File_Episode.Save(xrefEnt); } } } } else { logger.Debug("Cannot get AniDB_File record so exiting: {0}", vidLocal.ED2KHash); return; } } // we assume that all episodes belong to the same anime foreach (CrossRef_File_Episode xref in crossRefs) { animeID = xref.AnimeID; AniDB_Episode ep = RepoFactory.AniDB_Episode.GetByEpisodeID(xref.EpisodeID); if (ep == null) missingEpisodes = true; } } else { // check if we have the episode info // if we don't, we will need to re-download the anime info (which also has episode info) if (aniFile.EpisodeCrossRefs.Count == 0) { animeID = aniFile.AnimeID; // if we have the anidb file, but no cross refs it means something has been broken logger.Debug("Could not find any cross ref records for: {0}", vidLocal.ED2KHash); missingEpisodes = true; } else { foreach (CrossRef_File_Episode xref in aniFile.EpisodeCrossRefs) { AniDB_Episode ep = RepoFactory.AniDB_Episode.GetByEpisodeID(xref.EpisodeID); if (ep == null) missingEpisodes = true; animeID = xref.AnimeID; } } } // get from DB AniDB_Anime anime = RepoFactory.AniDB_Anime.GetByAnimeID(animeID); bool animeRecentlyUpdated = false; if (anime != null) { TimeSpan ts = DateTime.Now - anime.DateTimeUpdated; if (ts.TotalHours < 4) animeRecentlyUpdated = true; } // even if we are missing episode info, don't get data more than once every 4 hours // this is to prevent banning if (missingEpisodes && !animeRecentlyUpdated) { logger.Debug("Getting Anime record from AniDB...."); anime = JMMService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries); } // create the group/series/episode records if needed AnimeSeries ser = null; if (anime != null) { logger.Debug("Creating groups, series and episodes...."); // check if there is an AnimeSeries Record associated with this AnimeID ser = RepoFactory.AnimeSeries.GetByAnimeID(animeID); if (ser == null) { // create a new AnimeSeries record ser = anime.CreateAnimeSeriesAndGroup(); } ser.CreateAnimeEpisodes(); // check if we have any group status data for this associated anime // if not we will download it now if (RepoFactory.AniDB_GroupStatus.GetByAnimeID(anime.AnimeID).Count == 0) { CommandRequest_GetReleaseGroupStatus cmdStatus = new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false); cmdStatus.Save(); } // update stats ser.EpisodeAddedDate = DateTime.Now; RepoFactory.AnimeSeries.Save(ser, false, false); foreach (AnimeGroup grp in ser.AllGroupsAbove) { grp.EpisodeAddedDate = DateTime.Now; RepoFactory.AnimeGroup.Save(grp, true, false); } } vidLocal.Places.ForEach(a => { a.RenameIfRequired(); a.MoveFileIfRequired(); }); // update stats for groups and series if (ser != null) { // update all the groups above this series in the heirarchy ser.QueueUpdateStats(); //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } // Add this file to the users list if (ServerSettings.AniDB_MyList_AddFiles) { CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vidLocal.ED2KHash); cmd.Save(); } } }
private static void PerformActionOnFileNameREPLACE(ref string newFileName, string action, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { try { action = action.Trim(); int posStart1 = action.IndexOf("'", 0); if (posStart1 < 0) return; int posEnd1 = action.IndexOf("'", posStart1 + 1); if (posEnd1 < 0) return; string toReplace = action.Substring(posStart1 + 1, posEnd1 - posStart1 - 1); int posStart2 = action.IndexOf("'", posEnd1 + 1); if (posStart2 < 0) return; int posEnd2 = action.IndexOf("'", posStart2 + 1); if (posEnd2 < 0) return; string replaceWith = action.Substring(posStart2 + 1, posEnd2 - posStart2 - 1); newFileName = newFileName.Replace(toReplace, replaceWith); } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); } }
private void ProcessFile_AniDB(VideoLocal vidLocal) { logger.Trace("Checking for AniDB_File record for: {0} --- {1}", vidLocal.Hash, vidLocal.FilePath); // check if we already have this AniDB_File info in the database AniDB_FileRepository repAniFile = new AniDB_FileRepository(); AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository(); AniDB_AnimeRepository repAniAnime = new AniDB_AnimeRepository(); AnimeSeriesRepository repSeries = new AnimeSeriesRepository(); VideoLocalRepository repVidLocals = new VideoLocalRepository(); AnimeEpisodeRepository repEps = new AnimeEpisodeRepository(); CrossRef_File_EpisodeRepository repXrefFE = new CrossRef_File_EpisodeRepository(); AniDB_File aniFile = null; if (!ForceAniDB) { aniFile = repAniFile.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) logger.Trace("AniDB_File record not found"); } int animeID = 0; if (aniFile == null) { // get info from AniDB logger.Debug("Getting AniDB_File record from AniDB...."); Raw_AniDB_File fileInfo = JMMService.AnidbProcessor.GetFileInfo(vidLocal); if (fileInfo != null) { // check if we already have a record aniFile = repAniFile.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) aniFile = new AniDB_File(); aniFile.Populate(fileInfo); //overwrite with local file name string localFileName = Path.GetFileName(vidLocal.FilePath); aniFile.FileName = localFileName; repAniFile.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); if (!string.IsNullOrEmpty(fileInfo.OtherEpisodesRAW)) { string[] epIDs = fileInfo.OtherEpisodesRAW.Split(','); foreach (string epid in epIDs) { int id = 0; if (int.TryParse(epid, out id)) { CommandRequest_GetEpisode cmdEp = new CommandRequest_GetEpisode(id); cmdEp.Save(); } } } animeID = aniFile.AnimeID; } } bool missingEpisodes = false; // if we still haven't got the AniDB_File Info we try the web cache or local records if (aniFile == null) { // check if we have any records from previous imports List<CrossRef_File_Episode> crossRefs = repXrefFE.GetByHash(vidLocal.Hash); if (crossRefs == null || crossRefs.Count == 0) { // lets see if we can find the episode/anime info from the web cache if (ServerSettings.WebCache_XRefFileEpisode_Get) { crossRefs = XMLService.Get_CrossRef_File_Episode(vidLocal); if (crossRefs == null || crossRefs.Count == 0) { logger.Debug("Cannot find AniDB_File record or get cross ref from web cache record so exiting: {0}", vidLocal.ED2KHash); return; } else { foreach (CrossRef_File_Episode xref in crossRefs) { // in this case we need to save the cross refs manually as AniDB did not provide them repXrefFE.Save(xref); } } } else { logger.Debug("Cannot get AniDB_File record so exiting: {0}", vidLocal.ED2KHash); return; } } // we assume that all episodes belong to the same anime foreach (CrossRef_File_Episode xref in crossRefs) { animeID = xref.AnimeID; AniDB_Episode ep = repAniEps.GetByEpisodeID(xref.EpisodeID); if (ep == null) missingEpisodes = true; } } else { // check if we have the episode info // if we don't, we will need to re-download the anime info (which also has episode info) if (aniFile.EpisodeCrossRefs.Count == 0) { animeID = aniFile.AnimeID; // if we have the anidb file, but no cross refs it means something has been broken logger.Debug("Could not find any cross ref records for: {0}", vidLocal.ED2KHash); missingEpisodes = true; } else { foreach (CrossRef_File_Episode xref in aniFile.EpisodeCrossRefs) { AniDB_Episode ep = repAniEps.GetByEpisodeID(xref.EpisodeID); if (ep == null) missingEpisodes = true; animeID = xref.AnimeID; } } } // get from DB AniDB_Anime anime = repAniAnime.GetByAnimeID(animeID); bool animeRecentlyUpdated = false; if (anime != null) { TimeSpan ts = DateTime.Now - anime.DateTimeUpdated; if (ts.TotalHours < 4) animeRecentlyUpdated = true; } // even if we are missing episode info, don't get data more than once every 4 hours // this is to prevent banning if (missingEpisodes && !animeRecentlyUpdated) { logger.Debug("Getting Anime record from AniDB...."); // try using the cache first using (var session = JMMService.SessionFactory.OpenSession()) { anime = JMMService.AnidbProcessor.GetAnimeInfoHTTPFromCache(session, animeID, ServerSettings.AutoGroupSeries); } // if not in cache try from AniDB if (anime == null) anime = JMMService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries); } // create the group/series/episode records if needed AnimeSeries ser = null; if (anime != null) { logger.Debug("Creating groups, series and episodes...."); // check if there is an AnimeSeries Record associated with this AnimeID ser = repSeries.GetByAnimeID(animeID); if (ser == null) { // create a new AnimeSeries record ser = anime.CreateAnimeSeriesAndGroup(); } ser.CreateAnimeEpisodes(); // check if we have any group status data for this associated anime // if not we will download it now AniDB_GroupStatusRepository repStatus = new AniDB_GroupStatusRepository(); if (repStatus.GetByAnimeID(anime.AnimeID).Count == 0) { CommandRequest_GetReleaseGroupStatus cmdStatus = new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false); cmdStatus.Save(); } // update stats ser.EpisodeAddedDate = DateTime.Now; repSeries.Save(ser); AnimeGroupRepository repGroups = new AnimeGroupRepository(); foreach (AnimeGroup grp in ser.AllGroupsAbove) { grp.EpisodeAddedDate = DateTime.Now; repGroups.Save(grp); } } vidLocal.RenameIfRequired(); vidLocal.MoveFileIfRequired(); // update stats for groups and series if (ser != null) { // update all the groups above this series in the heirarchy ser.UpdateStats(true, true, true); StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); } // Add this file to the users list if (ServerSettings.AniDB_MyList_AddFiles) { CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vidLocal.ED2KHash); cmd.Save(); } // lets also try adding to the users trakt collecion by sync'ing the series if (ser != null) { CommandRequest_TraktSyncCollectionSeries cmdTrakt = new CommandRequest_TraktSyncCollectionSeries(ser.AnimeSeriesID, ser.GetAnime().MainTitle); cmdTrakt.Save(); } // sync the series on MAL if (ser != null) { CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID); cmdMAL.Save(); } }
private static bool EvaluateTestC(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } if (aniFile == null) return false; // Video codecs bool hasSource = !string.IsNullOrEmpty(aniFile.File_VideoCodec); if (test.Trim().Equals(Constants.FileRenameReserved.Unknown, StringComparison.InvariantCultureIgnoreCase) && !hasSource) { if (notCondition) return false; else return true; } if (test.Trim().Equals(aniFile.File_VideoCodec, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } else { if (notCondition) return true; else return false; } } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
/// <summary> /// Test is this files has the specified Sub (subtitle) language /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <returns></returns> private static bool EvaluateTestS(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } if (aniFile == null) return false; if ( test.Trim().Equals(Constants.FileRenameReserved.None, StringComparison.InvariantCultureIgnoreCase) && vid.GetAniDBFile().Subtitles.Count == 0) { if (notCondition) return false; else return true; } if (notCondition) { foreach (Language lan in aniFile.Subtitles) { if (lan.LanguageName.Trim().Equals(test.Trim(), StringComparison.InvariantCultureIgnoreCase)) return false; } return true; } else { foreach (Language lan in aniFile.Subtitles) { if (lan.LanguageName.Trim().Equals(test.Trim(), StringComparison.InvariantCultureIgnoreCase)) return true; } return false; } } catch (Exception ex) { logger.Error( ex,ex.ToString()); return false; } }
private static bool EvaluateTestF(string test, VideoLocal vid, AniDB_File aniFile) { try { bool notCondition = false; bool greaterThan = false; bool greaterThanEqual = false; bool lessThan = false; bool lessThanEqual = false; ProcessNumericalOperators(ref test, ref notCondition, ref greaterThan, ref greaterThanEqual, ref lessThan, ref lessThanEqual); if (aniFile == null) return false; int version = 0; int.TryParse(test, out version); bool hasFileVersionOperator = greaterThan | greaterThanEqual | lessThan | lessThanEqual; if (!hasFileVersionOperator) { if (!notCondition) { if (aniFile.FileVersion == version) return true; else return false; } else { if (aniFile.FileVersion == version) return false; else return true; } } else { if (greaterThan) { if (aniFile.FileVersion > version) return true; else return false; } if (greaterThanEqual) { if (aniFile.FileVersion >= version) return true; else return false; } if (lessThan) { if (aniFile.FileVersion < version) return true; else return false; } if (lessThanEqual) { if (aniFile.FileVersion <= version) return true; else return false; } } return false; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
public void ToggleWatchedStatus(bool watched, bool updateOnline, DateTime?watchedDate, bool updateStats, bool updateStatsCache, int userID, bool syncTrakt, bool updateWatchedDate) { JMMUser user = RepoFactory.JMMUser.GetByID(userID); if (user == null) { return; } List <JMMUser> aniDBUsers = RepoFactory.JMMUser.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 = RepoFactory.AniDB_File.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; } RepoFactory.AniDB_File.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 = RepoFactory.CrossRef_File_Episode.GetByHash(this.Hash); Dictionary <int, AnimeSeries> toUpdateSeries = new Dictionary <int, AnimeSeries>(); 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 episodes for this file, may be more than one (One Piece x Toriko) AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(xref.EpisodeID); // 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 && vidUser.WatchedDate.HasValue) { // if not null means it is watched epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched > 95) { ser = ep.GetAnimeSeries(); if (!toUpdateSeries.ContainsKey(ser.AnimeSeriesID)) { toUpdateSeries.Add(ser.AnimeSeriesID, ser); } 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 (syncTrakt && ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { CommandRequest_TraktHistoryEpisode cmdSyncTrakt = new CommandRequest_TraktHistoryEpisode(ep.AnimeEpisodeID, TraktSyncAction.Add); cmdSyncTrakt.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) { // get the episodes for this file, may be more than one (One Piece x Toriko) AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(xrefEp.EpisodeID); ser = ep.GetAnimeSeries(); if (!toUpdateSeries.ContainsKey(ser.AnimeSeriesID)) { toUpdateSeries.Add(ser.AnimeSeriesID, ser); } // 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 && vidUser.WatchedDate.HasValue) { 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); } } } if (syncTrakt && ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { CommandRequest_TraktHistoryEpisode cmdSyncTrakt = new CommandRequest_TraktHistoryEpisode(ep.AnimeEpisodeID, TraktSyncAction.Remove); cmdSyncTrakt.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 (toUpdateSeries.Count > 0 && updateStats) { foreach (AnimeSeries s in toUpdateSeries.Values) { // update all the groups above this series in the heirarchy s.UpdateStats(true, true, true); } //ser.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, true); } //if (ser != null && updateStatsCache) //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); }
/// <summary> /// Test whether the specified tag has a value /// </summary> /// <param name="test"></param> /// <param name="vid"></param> /// <param name="anime"></param> /// <returns></returns> private static bool EvaluateTestI(string test, VideoLocal vid, AniDB_File aniFile, List<AniDB_Episode> episodes, AniDB_Anime anime, VideoInfo vi) { try { bool notCondition = false; if (test.Substring(0, 1).Equals("!")) { notCondition = true; test = test.Substring(1, test.Length - 1); } if (anime == null) return false; #region Test if Anime ID exists // Test if Anime ID exists string tagAnimeID = Constants.FileRenameTag.AnimeID.Substring(1, Constants.FileRenameTag.AnimeID.Length - 1); // remove % at the front if (test.Trim().Equals(tagAnimeID, StringComparison.InvariantCultureIgnoreCase)) { // manually linked files won't have an anime id if (aniFile != null) { if (notCondition) return false; else return true; } else { if (notCondition) return true; else return false; } } #endregion #region Test if Group ID exists // Test if Group ID exists string tagGroupID = Constants.FileRenameTag.GroupID.Substring(1, Constants.FileRenameTag.GroupID.Length - 1); // remove % at the front if (test.Trim().Equals(tagGroupID, StringComparison.InvariantCultureIgnoreCase)) { // manually linked files won't have an group id if (aniFile != null) { if (notCondition) return false; else return true; } else { if (notCondition) return false; else return true; } } #endregion #region Test if Original File Name exists // Test if Original File Nameexists string tagOriginalFileName = Constants.FileRenameTag.OriginalFileName.Substring(1, Constants.FileRenameTag.OriginalFileName.Length - 1); // remove % at the front if (test.Trim().Equals(tagOriginalFileName, StringComparison.InvariantCultureIgnoreCase)) { // manually linked files won't have an Original File Name if (aniFile != null) { if (string.IsNullOrEmpty(aniFile.FileName)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } else { if (notCondition) return true; else return false; } } #endregion #region Test if Episode Number exists // Test if Episode Number exists string tagEpisodeNumber = Constants.FileRenameTag.EpisodeNumber.Substring(1, Constants.FileRenameTag.EpisodeNumber.Length - 1); // remove % at the front if (test.Trim().Equals(tagEpisodeNumber, StringComparison.InvariantCultureIgnoreCase)) { // manually linked files won't have an Episode Number if (aniFile != null) { if (notCondition) return false; else return true; } else { if (notCondition) return true; else return false; } } #endregion #region Test file version // Test if Group Short Name exists - yes it always does string tagFileVersion = Constants.FileRenameTag.FileVersion.Substring(1, Constants.FileRenameTag.FileVersion.Length - 1); // remove % at the front if (test.Trim().Equals(tagFileVersion, StringComparison.InvariantCultureIgnoreCase)) { // manually linked files won't have an anime id if (aniFile != null) { if (notCondition) return false; else return true; } else { if (notCondition) return true; else return false; } } #endregion #region Test if ED2K Upper exists // Test if Group Short Name exists - yes it always does string tagED2KUpper = Constants.FileRenameTag.ED2KUpper.Substring(1, Constants.FileRenameTag.ED2KUpper.Length - 1); // remove % at the front if (test.Trim().Equals(tagED2KUpper, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } #endregion #region Test if ED2K Lower exists // Test if Group Short Name exists - yes it always does string tagED2KLower = Constants.FileRenameTag.ED2KLower.Substring(1, Constants.FileRenameTag.ED2KLower.Length - 1); // remove % at the front if (test.Trim().Equals(tagED2KLower, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } #endregion #region Test if English title exists string tagAnimeNameEnglish = Constants.FileRenameTag.AnimeNameEnglish.Substring(1, Constants.FileRenameTag.AnimeNameEnglish.Length - 1); // remove % at the front if (test.Trim().Equals(tagAnimeNameEnglish, StringComparison.InvariantCultureIgnoreCase)) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.English, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } } } if (notCondition) return true; else return false; } #endregion #region Test if Kanji title exists string tagAnimeNameKanji = Constants.FileRenameTag.AnimeNameKanji.Substring(1, Constants.FileRenameTag.AnimeNameKanji.Length - 1); // remove % at the front if (test.Trim().Equals(tagAnimeNameKanji, StringComparison.InvariantCultureIgnoreCase)) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.Kanji, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } } } if (notCondition) return true; else return false; } #endregion #region Test if Romaji title exists string tagAnimeNameRomaji = Constants.FileRenameTag.AnimeNameRomaji.Substring(1, Constants.FileRenameTag.AnimeNameRomaji.Length - 1); // remove % at the front if (test.Trim().Equals(tagAnimeNameRomaji, StringComparison.InvariantCultureIgnoreCase)) { foreach (AniDB_Anime_Title ti in anime.GetTitles()) { if (ti.Language.Equals(Constants.AniDBLanguageType.Romaji, StringComparison.InvariantCultureIgnoreCase)) { if (ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Main, StringComparison.InvariantCultureIgnoreCase) || ti.TitleType.Trim().Equals(Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { if (notCondition) return false; else return true; } } } if (notCondition) return true; else return false; } #endregion #region Test if episode name (english) exists string tagEpisodeNameEnglish = Constants.FileRenameTag.EpisodeNameEnglish.Substring(1, Constants.FileRenameTag.EpisodeNameEnglish.Length - 1); // remove % at the front if (test.Trim().Equals(tagEpisodeNameEnglish, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(episodes[0].EnglishName)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if episode name (romaji) exists string tagEpisodeNameRomaji = Constants.FileRenameTag.EpisodeNameRomaji.Substring(1, Constants.FileRenameTag.EpisodeNameRomaji.Length - 1); // remove % at the front if (test.Trim().Equals(tagEpisodeNameRomaji, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(episodes[0].RomajiName)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if group name short exists // Test if Group Short Name exists - yes it always does string tagGroupShortName = Constants.FileRenameTag.GroupShortName.Substring(1, Constants.FileRenameTag.GroupShortName.Length - 1); // remove % at the front if (test.Trim().Equals(tagGroupShortName, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || string.IsNullOrEmpty(aniFile.Anime_GroupNameShort)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if group name long exists // Test if Group Short Name exists - yes it always does string tagGroupLongName = Constants.FileRenameTag.GroupLongName.Substring(1, Constants.FileRenameTag.GroupLongName.Length - 1); // remove % at the front if (test.Trim().Equals(tagGroupLongName, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || string.IsNullOrEmpty(aniFile.Anime_GroupName)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if CRC Lower exists // Test if Group Short Name exists - yes it always does string tagCRCLower = Constants.FileRenameTag.CRCLower.Substring(1, Constants.FileRenameTag.CRCLower.Length - 1); // remove % at the front if (test.Trim().Equals(tagCRCLower, StringComparison.InvariantCultureIgnoreCase)) { string crc = vid.CRC32; if (string.IsNullOrEmpty(crc) && aniFile != null) crc = aniFile.CRC; if (string.IsNullOrEmpty(crc)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if CRC Upper exists // Test if Group Short Name exists - yes it always does string tagCRCUpper = Constants.FileRenameTag.CRCUpper.Substring(1, Constants.FileRenameTag.CRCUpper.Length - 1); // remove % at the front if (test.Trim().Equals(tagCRCUpper, StringComparison.InvariantCultureIgnoreCase)) { string crc = vid.CRC32; if (string.IsNullOrEmpty(crc) && aniFile != null) crc = aniFile.CRC; if (string.IsNullOrEmpty(crc)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test file has an audio track string tagDubLanguage = Constants.FileRenameTag.DubLanguage.Substring(1, Constants.FileRenameTag.DubLanguage.Length - 1); // remove % at the front if (test.Trim().Equals(tagDubLanguage, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || aniFile.Languages.Count == 0) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test file has a subtitle track string tagSubLanguage = Constants.FileRenameTag.SubLanguage.Substring(1, Constants.FileRenameTag.SubLanguage.Length - 1); // remove % at the front if (test.Trim().Equals(tagSubLanguage, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || aniFile.Subtitles.Count == 0) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if Video resolution exists string tagVidRes = Constants.FileRenameTag.Resolution.Substring(1, Constants.FileRenameTag.Resolution.Length - 1); // remove % at the front if (test.Trim().Equals(tagVidRes, StringComparison.InvariantCultureIgnoreCase)) { string vidRes = ""; if (aniFile != null) vidRes = aniFile.File_VideoResolution; if (string.IsNullOrEmpty(vidRes) && vi != null) vidRes = vi.VideoResolution; if (string.IsNullOrEmpty(vidRes)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test file has a video codec defined string tagVideoCodec = Constants.FileRenameTag.VideoCodec.Substring(1, Constants.FileRenameTag.VideoCodec.Length - 1); // remove % at the front if (test.Trim().Equals(tagVideoCodec, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || string.IsNullOrEmpty(aniFile.File_VideoCodec)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test file has an audio codec defined string tagAudioCodec = Constants.FileRenameTag.AudioCodec.Substring(1, Constants.FileRenameTag.AudioCodec.Length - 1); // remove % at the front if (test.Trim().Equals(tagAudioCodec, StringComparison.InvariantCultureIgnoreCase)) { if (aniFile == null || string.IsNullOrEmpty(aniFile.File_AudioCodec)) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test file has Video Bit Depth defined string tagVideoBitDepth = Constants.FileRenameTag.VideoBitDepth.Substring(1, Constants.FileRenameTag.VideoBitDepth.Length - 1); // remove % at the front if (test.Trim().Equals(tagVideoBitDepth, StringComparison.InvariantCultureIgnoreCase)) { bool bitDepthExists = false; if (vi != null) { if (!string.IsNullOrEmpty(vi.VideoBitDepth)) { int bitDepth = 0; int.TryParse(vi.VideoBitDepth, out bitDepth); if (bitDepth > 0) bitDepthExists = true; } } if (!bitDepthExists) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if censored string tagCensored = Constants.FileRenameTag.Censored.Substring(1, Constants.FileRenameTag.Censored.Length - 1); // remove % at the front if (test.Trim().Equals(tagCensored, StringComparison.InvariantCultureIgnoreCase)) { bool isCensored = false; if (aniFile != null) isCensored = aniFile.IsCensored == 1; if (!isCensored) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if Deprecated string tagDeprecated = Constants.FileRenameTag.Deprecated.Substring(1, Constants.FileRenameTag.Deprecated.Length - 1); // remove % at the front if (test.Trim().Equals(tagDeprecated, StringComparison.InvariantCultureIgnoreCase)) { bool isDeprecated = false; if (aniFile != null) isDeprecated = aniFile.IsDeprecated == 1; if (!isDeprecated) { if (notCondition) return true; else return false; } else { if (notCondition) return false; else return true; } } #endregion #region Test if file has more than one episode #endregion return false; } catch (Exception ex) { logger.ErrorException(ex.ToString(), ex); return false; } }
public Contract_VideoDetailed ToContractDetailed(int userID) { Contract_VideoDetailed contract = new Contract_VideoDetailed(); // get the cross ref episode List <CrossRef_File_Episode> xrefs = this.EpisodeCrossRefs; if (xrefs.Count == 0) { return(null); } contract.Percentage = xrefs[0].Percentage; contract.EpisodeOrder = xrefs[0].EpisodeOrder; contract.CrossRefSource = xrefs[0].CrossRefSource; contract.AnimeEpisodeID = xrefs[0].EpisodeID; contract.VideoLocal_FileName = this.FileName; contract.VideoLocal_Hash = this.Hash; contract.VideoLocal_FileSize = this.FileSize; contract.VideoLocalID = this.VideoLocalID; contract.VideoLocal_IsIgnored = this.IsIgnored; contract.VideoLocal_IsVariation = this.IsVariation; contract.Places = Places.Select(a => a.ToContract()).ToList(); contract.VideoLocal_MD5 = this.MD5; contract.VideoLocal_SHA1 = this.SHA1; contract.VideoLocal_CRC32 = this.CRC32; contract.VideoLocal_HashSource = this.HashSource; VideoLocal_User userRecord = this.GetUserRecord(userID); if (userRecord?.WatchedDate == null) { contract.VideoLocal_IsWatched = 0; contract.VideoLocal_WatchedDate = null; contract.VideoLocal_ResumePosition = 0; } else { contract.VideoLocal_IsWatched = userRecord.WatchedDate.HasValue ? 1 : 0; contract.VideoLocal_WatchedDate = userRecord.WatchedDate; } if (userRecord != null) { contract.VideoLocal_ResumePosition = userRecord.ResumePosition; } contract.VideoInfo_AudioBitrate = AudioBitrate; contract.VideoInfo_AudioCodec = AudioCodec; contract.VideoInfo_Duration = Duration; contract.VideoInfo_VideoBitrate = VideoBitrate; contract.VideoInfo_VideoBitDepth = VideoBitDepth; contract.VideoInfo_VideoCodec = VideoCodec; contract.VideoInfo_VideoFrameRate = VideoFrameRate; contract.VideoInfo_VideoResolution = VideoResolution; // AniDB File AniDB_File anifile = this.GetAniDBFile(); // to prevent multiple db calls if (anifile != null) { contract.AniDB_Anime_GroupName = anifile.Anime_GroupName; contract.AniDB_Anime_GroupNameShort = anifile.Anime_GroupNameShort; contract.AniDB_AnimeID = anifile.AnimeID; contract.AniDB_CRC = anifile.CRC; contract.AniDB_Episode_Rating = anifile.Episode_Rating; contract.AniDB_Episode_Votes = anifile.Episode_Votes; contract.AniDB_File_AudioCodec = anifile.File_AudioCodec; contract.AniDB_File_Description = anifile.File_Description; contract.AniDB_File_FileExtension = anifile.File_FileExtension; contract.AniDB_File_LengthSeconds = anifile.File_LengthSeconds; contract.AniDB_File_ReleaseDate = anifile.File_ReleaseDate; contract.AniDB_File_Source = anifile.File_Source; contract.AniDB_File_VideoCodec = anifile.File_VideoCodec; contract.AniDB_File_VideoResolution = anifile.File_VideoResolution; contract.AniDB_FileID = anifile.FileID; contract.AniDB_GroupID = anifile.GroupID; contract.AniDB_MD5 = anifile.MD5; contract.AniDB_SHA1 = anifile.SHA1; contract.AniDB_File_FileVersion = anifile.FileVersion; // languages contract.LanguagesAudio = anifile.LanguagesRAW; contract.LanguagesSubtitle = anifile.SubtitlesRAW; } else { contract.AniDB_Anime_GroupName = ""; contract.AniDB_Anime_GroupNameShort = ""; contract.AniDB_CRC = ""; contract.AniDB_File_AudioCodec = ""; contract.AniDB_File_Description = ""; contract.AniDB_File_FileExtension = ""; contract.AniDB_File_Source = ""; contract.AniDB_File_VideoCodec = ""; contract.AniDB_File_VideoResolution = ""; contract.AniDB_MD5 = ""; contract.AniDB_SHA1 = ""; contract.AniDB_File_FileVersion = 1; // languages contract.LanguagesAudio = ""; contract.LanguagesSubtitle = ""; } AniDB_ReleaseGroup relGroup = this.ReleaseGroup; // to prevent multiple db calls if (relGroup != null) { contract.ReleaseGroup = relGroup.ToContract(); } else { contract.ReleaseGroup = null; } contract.Media = GetMediaFromUser(userID); return(contract); }