Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
 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);
 }
Example #4
0
        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();
                }
            }
        }
Example #5
0
 // 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);
            }
        }
Example #8
0
        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("");
        }