public override void Run(IProgress <ICommand> progress = null) { try { ReportInit(progress); if (vidLocal == null) { ReportFinish(progress); return; } //now that we have all the has info, we can get the AniDB Info logger.Trace($"Checking for AniDB_File record for: {vidLocal.Hash} --- {vidLocal.Info}"); // check if we already have this AniDB_File info in the database lock (vidLocal) { List <ICommand> cmds = new List <ICommand>(); SVR_AniDB_File aniFile = null; if (!ForceAniDB) { aniFile = Repo.Instance.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vidLocal.FileSize); if (aniFile == null) { logger.Trace("AniDB_File record not found"); } } // If cross refs were wiped, but the AniDB_File was not, we unfortunately need to requery the info List <CrossRef_File_Episode> crossRefs = Repo.Instance.CrossRef_File_Episode.GetByHash(vidLocal.Hash); if (crossRefs == null || crossRefs.Count == 0) { aniFile = null; } ReportUpdate(progress, 10); int animeID = 0; if (aniFile == null || ForceAniDB) { // get info from AniDB logger.Debug("Getting AniDB_File record from AniDB...."); // check if we already have a record using (var upd = Repo.Instance.AniDB_File.BeginAddOrUpdate(() => Repo.Instance.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vidLocal.FileSize))) { bool skip = false; Raw_AniDB_File fileInfo = null; if (!upd.IsUpdate || ForceAniDB) { fileInfo = ShokoService.AnidbProcessor.GetFileInfo(vidLocal); if (fileInfo != null) { upd.Entity.Populate_RA(fileInfo); } else { skip = true; } } if (!skip) { //overwrite with local file name string localFileName = vidLocal.GetBestVideoLocalPlace()?.FullServerPath; localFileName = !string.IsNullOrEmpty(localFileName) ? Path.GetFileName(localFileName) : vidLocal.Info; upd.Entity.FileName = localFileName; if (fileInfo != null) { upd.Entity.Populate_RA(fileInfo); } aniFile = upd.Commit(); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); animeID = aniFile.AnimeID; } } ReportUpdate(progress, 20); } 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 crossRefs = Repo.Instance.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.Instance.WebCache.XRefFileEpisode_Get) { List <CrossRef_File_Episode> xrefs = WebCacheAPI.Instance.GetCrossRef_File_Episodes(vidLocal.Hash); 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: {vidLocal.ED2KHash}"); ReportFinish(progress); return; } string fileName = vidLocal.GetBestVideoLocalPlace()?.FullServerPath; fileName = !string.IsNullOrEmpty(fileName) ? Path.GetFileName(fileName) : vidLocal.Info; foreach (CrossRef_File_Episode xref in xrefs) { CrossRef_File_Episode xrefEnt = new CrossRef_File_Episode { Hash = vidLocal.ED2KHash, FileName = fileName, FileSize = vidLocal.FileSize, CrossRefSource = (int)CrossRefSource.WebCache, AnimeID = xref.AnimeID, EpisodeID = xref.EpisodeID, Percentage = xref.Percentage, 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 Repo.Instance.CrossRef_File_Episode.BeginAdd(xrefEnt).Commit(); } } } else { logger.Debug($"Cannot get AniDB_File record so exiting: {vidLocal.ED2KHash}"); ReportFinish(progress); return; } } ReportUpdate(progress, 30); // we assume that all episodes belong to the same anime foreach (CrossRef_File_Episode xref in crossRefs) { animeID = xref.AnimeID; AniDB_Episode ep = Repo.Instance.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: {vidLocal.ED2KHash}"); missingEpisodes = true; } else { foreach (CrossRef_File_Episode xref in aniFile.EpisodeCrossRefs) { AniDB_Episode ep = Repo.Instance.AniDB_Episode.GetByEpisodeID(xref.EpisodeID); if (ep == null) { missingEpisodes = true; } animeID = xref.AnimeID; } } ReportUpdate(progress, 30); } // get from DB SVR_AniDB_Anime anime = Repo.Instance.AniDB_Anime.GetByAnimeID(animeID); var update = Repo.Instance.AniDB_AnimeUpdate.GetByAnimeID(animeID); bool animeRecentlyUpdated = false; if (anime != null && update != null) { TimeSpan ts = DateTime.Now - update.UpdatedAt; if (ts.TotalHours < 4) { animeRecentlyUpdated = true; } } else { missingEpisodes = 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 = ShokoService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.Instance.AutoGroupSeries || ServerSettings.Instance.AniDb.DownloadRelatedAnime); } ReportUpdate(progress, 40); // create the group/series/episode records if needed if (anime != null) { logger.Debug("Creating groups, series and episodes...."); // check if there is an AnimeSeries Record associated with this AnimeID SVR_AnimeSeries ser; using (var upd = Repo.Instance.AnimeSeries.BeginAddOrUpdate(() => Repo.Instance.AnimeSeries.GetByAnimeID(animeID), () => anime.CreateAnimeSeriesAndGroup())) { upd.Entity.CreateAnimeEpisodes(); // check if we have any group status data for this associated anime // if not we will download it now if (Repo.Instance.AniDB_GroupStatus.GetByAnimeID(anime.AnimeID).Count == 0) { cmds.Add(new CmdAniDBGetReleaseGroupStatus(anime.AnimeID, false)); } // update stats upd.Entity.EpisodeAddedDate = DateTime.Now; ser = upd.Commit(); } Repo.Instance.AnimeGroup.BatchAction(ser.AllGroupsAbove, ser.AllGroupsAbove.Count, (grp, _) => grp.EpisodeAddedDate = DateTime.Now, (true, false, false)); ReportUpdate(progress, 50); // We do this inside, as the info will not be available as needed otherwise List <SVR_VideoLocal> videoLocals = aniFile?.EpisodeIDs?.SelectMany(a => Repo.Instance.VideoLocal.GetByAniDBEpisodeID(a)).Where(b => b != null).ToList(); if (videoLocals != null) { if (ServerSettings.Instance.Import.UseExistingFileWatchedStatus) { // Copy over watched states foreach (var user in Repo.Instance.JMMUser.GetAll()) { var watchedVideo = videoLocals.FirstOrDefault(a => a?.GetUserRecord(user.JMMUserID)?.WatchedDate != null); // No files that are watched if (watchedVideo == null) { continue; } var watchedRecord = watchedVideo.GetUserRecord(user.JMMUserID); using (var upd = Repo.Instance.VideoLocal_User.BeginAddOrUpdate(() => vidLocal.GetUserRecord(user.JMMUserID), () => new VideoLocal_User { JMMUserID = user.JMMUserID, VideoLocalID = vidLocal.VideoLocalID })) { upd.Entity.WatchedDate = watchedRecord.WatchedDate; upd.Entity.ResumePosition = watchedRecord.ResumePosition; upd.Commit(); } } } ReportUpdate(progress, 60); if (ServerSettings.Instance.FileQualityFilterEnabled) { videoLocals.Sort(FileQualityFilter.CompareTo); List <SVR_VideoLocal> keep = videoLocals.Take(FileQualityFilter.Settings.MaxNumberOfFilesToKeep).ToList(); foreach (SVR_VideoLocal vl2 in keep) { videoLocals.Remove(vl2); } if (!FileQualityFilter.Settings.AllowDeletionOfImportedFiles && videoLocals.Contains(vidLocal)) { videoLocals.Remove(vidLocal); } videoLocals = videoLocals.Where(a => !FileQualityFilter.CheckFileKeep(a)).ToList(); videoLocals.ForEach(a => a.Places.ForEach(b => b.RemoveAndDeleteFile())); } } ReportUpdate(progress, 70); // update stats for groups and series // update all the groups above this series in the heirarchy SVR_AniDB_Anime.UpdateStatsByAnimeID(animeID); } else { logger.Warn($"Unable to create AniDB_Anime for file: {vidLocal.Info}"); } ReportUpdate(progress, 80); vidLocal.Places.ForEach(a => { a.RenameAndMoveAsRequired(); }); // Add this file to the users list if (ServerSettings.Instance.AniDb.MyList_AddFiles) { cmds.Add(new CmdAniDBAddFileToMyList(vidLocal.Hash)); } ReportUpdate(progress, 90); if (cmds.Count > 0) { Queue.Instance.AddRange(cmds); } ReportFinish(progress); } } catch (Exception ex) { ReportError(progress, $"Error processing ServerProcessFile: {VideoLocalID} - {ex}", ex); } }
private bool ProcessSearchResults(List <TVDB_Series_Search_Response> results, string searchCriteria) { if (results.Count == 1) { // since we are using this result, lets download the info logger.Trace("Found 1 tvdb results for search on {0} --- Linked to {1} ({2})", searchCriteria, results[0].SeriesName, results[0].SeriesID); TvDB_Series tvser = TvDBApiHelper.GetSeriesInfoOnline(results[0].SeriesID, false); TvDBApiHelper.LinkAniDBTvDB(AnimeID, EpisodeType.Episode, 1, results[0].SeriesID, 1, 1, true); // add links for multiple seasons (for long shows) List <int> seasons = RepoFactory.TvDB_Episode.GetSeasonNumbersForSeries(results[0].SeriesID); foreach (int season in seasons) { if (season < 2) { continue; // we just linked season 1, so start after (and skip specials) } TvDB_Episode ep = RepoFactory.TvDB_Episode.GetBySeriesIDSeasonNumberAndEpisode(results[0].SeriesID, season, 1); if (ep?.AbsoluteNumber != null) { AddCrossRef_AniDB_TvDBV2(AnimeID, ep.AbsoluteNumber.Value, results[0].SeriesID, season, tvser?.SeriesName ?? string.Empty); } } SVR_AniDB_Anime.UpdateStatsByAnimeID(AnimeID); return(true); } if (results.Count > 1) { logger.Trace("Found multiple ({0}) tvdb results for search on so checking for english results {1}", results.Count, searchCriteria); foreach (TVDB_Series_Search_Response sres in results) { // since we are using this result, lets download the info logger.Trace("Found english result for search on {0} --- Linked to {1} ({2})", searchCriteria, sres.SeriesName, sres.SeriesID); TvDB_Series tvser = TvDBApiHelper.GetSeriesInfoOnline(results[0].SeriesID, false); TvDBApiHelper.LinkAniDBTvDB(AnimeID, EpisodeType.Episode, 1, sres.SeriesID, 1, 1, true); // add links for multiple seasons (for long shows) List <int> seasons = RepoFactory.TvDB_Episode.GetSeasonNumbersForSeries(results[0].SeriesID); foreach (int season in seasons) { if (season < 2) { continue; // we just linked season 1, so start after (and skip specials) } TvDB_Episode ep = RepoFactory.TvDB_Episode .GetBySeriesIDSeasonNumberAndEpisode(results[0].SeriesID, season, 1); if (ep?.AbsoluteNumber != null) { AddCrossRef_AniDB_TvDBV2(AnimeID, ep.AbsoluteNumber.Value, results[0].SeriesID, season, tvser?.SeriesName ?? string.Empty); } } return(true); } logger.Trace("No english results found, so SKIPPING: {0}", searchCriteria); } return(false); }
internal override void EndSave(CrossRef_File_Episode entity, object returnFromBeginSave, object parameters) { logger.Trace("Updating group stats by file from CrossRef_File_EpisodeRepository.Save: {0}", entity.Hash); SVR_AniDB_Anime.UpdateStatsByAnimeID(entity.AnimeID); }
private void ProcessFile_AniDB(SVR_VideoLocal vidLocal) { logger.Trace($"Checking for AniDB_File record for: {vidLocal.Hash} --- {vidLocal.FileName}"); // check if we already have this AniDB_File info in the database lock (vidLocal) { SVR_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"); } } // If cross refs were wiped, but the AniDB_File was not, we unfortunately need to requery the info List <CrossRef_File_Episode> crossRefs = RepoFactory.CrossRef_File_Episode.GetByHash(vidLocal.Hash); if (crossRefs == null || crossRefs.Count == 0) { aniFile = null; } int animeID = 0; if (aniFile == null) { // get info from AniDB logger.Debug("Getting AniDB_File record from AniDB...."); // check if we already have a record aniFile = RepoFactory.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize); if (aniFile == null) { aniFile = new SVR_AniDB_File(); ForceAniDB = true; } if (ForceAniDB) { if (!ShokoService.AnidbProcessor.IsUdpBanned) { Raw_AniDB_File fileInfo = ShokoService.AnidbProcessor.GetFileInfo(vidLocal); if (fileInfo != null) { SVR_AniDB_File.Populate(aniFile, fileInfo); } else { aniFile = null; } } else { CommandRequest_GetFile fileCommand = new CommandRequest_GetFile(vlocal.VideoLocalID, true); fileCommand.Save(); } } if (aniFile != null) { //overwrite with local file name string localFileName = vidLocal.GetBestVideoLocalPlace()?.FullServerPath; localFileName = !string.IsNullOrEmpty(localFileName) ? Path.GetFileName(localFileName) : vidLocal.FileName; aniFile.FileName = localFileName; RepoFactory.AniDB_File.Save(aniFile, false); aniFile.CreateLanguages(); aniFile.CreateCrossEpisodes(localFileName); 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 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.Instance.WebCache.Enabled && ServerSettings.Instance.WebCache.XRefFileEpisode_Get) { List <Azure_CrossRef_File_Episode> xrefs = 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: {vidLocal.ED2KHash}"); return; } string fileName = vidLocal.GetBestVideoLocalPlace()?.FullServerPath; fileName = !string.IsNullOrEmpty(fileName) ? Path.GetFileName(fileName) : vidLocal.FileName; foreach (Azure_CrossRef_File_Episode xref in xrefs) { CrossRef_File_Episode xrefEnt = new CrossRef_File_Episode { Hash = vidLocal.ED2KHash, FileName = fileName, FileSize = vidLocal.FileSize, CrossRefSource = (int)CrossRefSource.WebCache, AnimeID = xref.AnimeID, EpisodeID = xref.EpisodeID, Percentage = xref.Percentage, 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 // use a session to prevent updating stats using (var session = DatabaseFactory.SessionFactory.OpenSession()) { using (var trans = session.BeginTransaction()) { RepoFactory.CrossRef_File_Episode.SaveWithOpenTransaction(session, xrefEnt); trans.Commit(); } } } } } else { logger.Debug($"Cannot get AniDB_File record so exiting: {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: {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 SVR_AniDB_Anime anime = RepoFactory.AniDB_Anime.GetByAnimeID(animeID); var update = RepoFactory.AniDB_AnimeUpdate.GetByAnimeID(animeID); bool animeRecentlyUpdated = false; if (anime != null && update != null) { TimeSpan ts = DateTime.Now - update.UpdatedAt; if (ts.TotalHours < 4) { animeRecentlyUpdated = true; } } else { missingEpisodes = 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 = ShokoService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.Instance.AutoGroupSeries || ServerSettings.Instance.AniDb.DownloadRelatedAnime); } // create the group/series/episode records if needed if (anime != null) { logger.Debug("Creating groups, series and episodes...."); // check if there is an AnimeSeries Record associated with this AnimeID var ser = RepoFactory.AnimeSeries.GetByAnimeID(animeID); if (ser == null) { // We will put UpdatedAt in the CreateAnimeSeriesAndGroup method, to ensure it exists at first write ser = anime.CreateAnimeSeriesAndGroup(); ser.CreateAnimeEpisodes(); } else { TimeSpan ts = DateTime.Now - ser.UpdatedAt; // don't even check episodes if we've done it recently... if (ts.TotalHours > 6) { if (ser.NeedsEpisodeUpdate()) { logger.Info($"Series {anime.MainTitle} needs episodes regenerated (an episode was added or deleted from AniDB)"); ser.CreateAnimeEpisodes(); ser.UpdatedAt = DateTime.Now; } } } // 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(); } // Only save the date, we'll update GroupFilters and stats in one pass // don't bother saving the series here, it'll happen in SVR_AniDB_Anime.UpdateStatsByAnimeID() // just don't do anything that needs this changed data before then ser.EpisodeAddedDate = DateTime.Now; foreach (SVR_AnimeGroup grp in ser.AllGroupsAbove) { grp.EpisodeAddedDate = DateTime.Now; RepoFactory.AnimeGroup.Save(grp, false, false, false); } // We do this inside, as the info will not be available as needed otherwise List <SVR_VideoLocal> videoLocals = aniFile?.EpisodeIDs?.SelectMany(a => RepoFactory.VideoLocal.GetByAniDBEpisodeID(a)) .Where(b => b != null) .ToList(); if (videoLocals != null) { if (ServerSettings.Instance.Import.UseExistingFileWatchedStatus) { // Copy over watched states foreach (var user in RepoFactory.JMMUser.GetAll()) { var watchedVideo = videoLocals.FirstOrDefault(a => a?.GetUserRecord(user.JMMUserID)?.WatchedDate != null); // No files that are watched if (watchedVideo == null) { continue; } var watchedRecord = watchedVideo.GetUserRecord(user.JMMUserID); var userRecord = vidLocal.GetUserRecord(user.JMMUserID) ?? new VideoLocal_User { JMMUserID = user.JMMUserID, VideoLocalID = vidLocal.VideoLocalID, }; userRecord.WatchedDate = watchedRecord.WatchedDate; userRecord.ResumePosition = watchedRecord.ResumePosition; RepoFactory.VideoLocalUser.Save(userRecord); } } // update stats for groups and series SVR_AniDB_Anime.UpdateStatsByAnimeID(animeID); if (ServerSettings.Instance.FileQualityFilterEnabled) { videoLocals.Sort(FileQualityFilter.CompareTo); List <SVR_VideoLocal> keep = videoLocals .Take(FileQualityFilter.Settings.MaxNumberOfFilesToKeep) .ToList(); foreach (SVR_VideoLocal vl2 in keep) { videoLocals.Remove(vl2); } if (!FileQualityFilter.Settings.AllowDeletionOfImportedFiles && videoLocals.Contains(vidLocal)) { videoLocals.Remove(vidLocal); } videoLocals = videoLocals.Where(a => !FileQualityFilter.CheckFileKeep(a)).ToList(); videoLocals.ForEach(a => a.Places.ForEach(b => b.RemoveAndDeleteFile())); } } } else { logger.Warn($"Unable to create AniDB_Anime for file: {vidLocal.FileName}"); logger.Warn($"Queuing GET for AniDB_Anime: {animeID}"); CommandRequest_GetAnimeHTTP animeCommand = new CommandRequest_GetAnimeHTTP(animeID, true, true); animeCommand.Save(); } vidLocal.Places.ForEach(a => { a.RenameAndMoveAsRequired(); }); // Add this file to the users list if (ServerSettings.Instance.AniDb.MyList_AddFiles) { CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vidLocal.ED2KHash); cmd.Save(); } } }
// Removes all TVDB information from a series, bringing it back to a blank state. public static void RemoveLinkAniDBTvDB(int animeID, int tvDBID) { Repo.Instance.CrossRef_AniDB_Provider.FindAndDelete(() => Repo.Instance.CrossRef_AniDB_Provider.GetByAnimeIdAndProvider(CrossRefType.TvDB, animeID, tvDBID.ToString())); SVR_AniDB_Anime.UpdateStatsByAnimeID(animeID); }
public override void ProcessCommand() { SVR_AniDB_Anime.UpdateStatsByAnimeID(AnimeID); }
public override void Run(IProgress <ICommand> progress = null) { logger.Info("Processing CommandRequest_TvDBSearchAnime: {0}", AnimeID); try { ReportInit(progress); // first check if the user wants to use the web cache if (ServerSettings.Instance.WebCache.TvDB_Get) { try { List <WebCache_CrossRef_AniDB_Provider> resultsCache = WebCacheAPI.Instance.GetCrossRef_AniDB_Provider(AnimeID, CrossRefType.TvDB); ReportUpdate(progress, 30); if (resultsCache != null && resultsCache.Count > 0) { List <WebCache_CrossRef_AniDB_Provider> best = resultsCache.BestProvider(); if (best.Count > 0) { TvDBApiHelper.RemoveAllAniDBTvDBLinks(AnimeID, false); ReportUpdate(progress, 70); foreach (WebCache_CrossRef_AniDB_Provider xref in best) { TvDBApiHelper.LinkAniDBTvDBFromWebCache(xref); } SVR_AniDB_Anime.UpdateStatsByAnimeID(AnimeID); logger.Trace("Changed trakt association: {0}", AnimeID); ReportFinish(progress); return; } } } catch (Exception ex) { logger.Error(ex, ex.ToString()); } } if (!ServerSettings.Instance.TvDB.AutoLink) { ReportFinish(progress); return; } // try to pull a link from a prequel/sequel var relations = Repo.Instance.AniDB_Anime_Relation.GetFullLinearRelationTree(AnimeID); string tvDBID = relations.SelectMany(a => Repo.Instance.CrossRef_AniDB_Provider.GetByAnimeIDAndType(a, CrossRefType.TvDB)) .FirstOrDefault(a => a != null)?.CrossRefID; ReportUpdate(progress, 25); if (tvDBID != null) { TvDBApiHelper.LinkAniDBTvDB(AnimeID, int.Parse(tvDBID), true); ReportFinish(progress); return; } ReportUpdate(progress, 50); // search TvDB SVR_AniDB_Anime anime = Repo.Instance.AniDB_Anime.GetByAnimeID(AnimeID); if (anime == null) { ReportFinish(progress); return; } var searchCriteria = anime.MainTitle; // if not wanting to use web cache, or no match found on the web cache go to TvDB directly List <TVDB_Series_Search_Response> results = TvDBApiHelper.SearchSeries(searchCriteria); logger.Trace("Found {0} tvdb results for {1} on TheTvDB", results.Count, searchCriteria); if (ProcessSearchResults(results, searchCriteria)) { ReportFinish(progress); return; } if (results.Count != 0) { ReportFinish(progress); return; } bool foundResult = false; ReportUpdate(progress, 75); foreach (AniDB_Anime_Title title in anime.GetTitles()) { if (!title.TitleType.Equals(Shoko.Models.Constants.AnimeTitleType.Official, StringComparison.InvariantCultureIgnoreCase)) { continue; } if (!title.Language.Equals(Shoko.Models.Constants.AniDBLanguageType.English, StringComparison.InvariantCultureIgnoreCase) && !title.Language.Equals(Shoko.Models.Constants.AniDBLanguageType.Romaji, StringComparison.InvariantCultureIgnoreCase)) { continue; } if (searchCriteria.Equals(title.Title, StringComparison.InvariantCultureIgnoreCase)) { continue; } searchCriteria = title.Title; results = TvDBApiHelper.SearchSeries(searchCriteria); if (results.Count > 0) { foundResult = true; } logger.Trace("Found {0} tvdb results for search on {1}", results.Count, title.Title); if (ProcessSearchResults(results, title.Title)) { ReportFinish(progress); return; } } if (!foundResult) { logger.Warn("Unable to find a matching TvDB series for {0}", anime.MainTitle); } ReportFinish(progress); } catch (Exception ex) { ReportError(progress, $"Error processing CommandRequest_TvDBSearchAnime: {AnimeID} - {ex}", ex); } }
public static string LinkAniDBTvDB(int animeID, enEpisodeType aniEpType, int aniEpNumber, int tvDBID, int tvSeasonNumber, int tvEpNumber, bool excludeFromWebCache, bool additiveLink = false) { using (var session = DatabaseFactory.SessionFactory.OpenSession()) { if (!additiveLink) { // remove all current links RemoveAllAniDBTvDBLinks(session.Wrap(), animeID); } // check if we have this information locally // if not download it now TvDB_Series tvSeries = RepoFactory.TvDB_Series.GetByTvDBID(tvDBID); if (tvSeries == null) { // we download the series info here just so that we have the basic info in the // database before the queued task runs later tvSeries = GetSeriesInfoOnline(tvDBID); } // download and update series info, episode info and episode images // will also download fanart, posters and wide banners CommandRequest_TvDBUpdateSeriesAndEpisodes cmdSeriesEps = new CommandRequest_TvDBUpdateSeriesAndEpisodes(tvDBID, false); //Optimize for batch updates, if there are a lot of LinkAniDBTvDB commands queued //this will cause only one updateSeriesAndEpisodes command to be created if (RepoFactory.CommandRequest.GetByCommandID(cmdSeriesEps.CommandID) == null) { cmdSeriesEps.Save(); } CrossRef_AniDB_TvDBV2 xref = RepoFactory.CrossRef_AniDB_TvDBV2.GetByTvDBID(session, tvDBID, tvSeasonNumber, tvEpNumber, animeID, (int)aniEpType, aniEpNumber); if (xref == null) { xref = new CrossRef_AniDB_TvDBV2(); } xref.AnimeID = animeID; xref.AniDBStartEpisodeType = (int)aniEpType; xref.AniDBStartEpisodeNumber = aniEpNumber; xref.TvDBID = tvDBID; xref.TvDBSeasonNumber = tvSeasonNumber; xref.TvDBStartEpisodeNumber = tvEpNumber; if (tvSeries != null) { xref.TvDBTitle = tvSeries.SeriesName; } if (excludeFromWebCache) { xref.CrossRefSource = (int)CrossRefSource.WebCache; } else { xref.CrossRefSource = (int)CrossRefSource.User; } RepoFactory.CrossRef_AniDB_TvDBV2.Save(xref); SVR_AniDB_Anime.UpdateStatsByAnimeID(animeID); logger.Trace("Changed tvdb association: {0}", animeID); if (!excludeFromWebCache) { var req = new CommandRequest_WebCacheSendXRefAniDBTvDB(xref.CrossRef_AniDB_TvDBV2ID); req.Save(); } if (ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { // check for Trakt associations List <CrossRef_AniDB_TraktV2> trakt = RepoFactory.CrossRef_AniDB_TraktV2.GetByAnimeID(animeID); if (trakt.Count != 0) { // remove them and rescan foreach (CrossRef_AniDB_TraktV2 a in trakt) { RepoFactory.CrossRef_AniDB_TraktV2.Delete(a); } } var cmd2 = new CommandRequest_TraktSearchAnime(animeID, false); cmd2.Save(session); } } return(""); }