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 = Repo.Instance.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 = Repo.Instance.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

                    using (var upd = Repo.Instance.AniDB_File.BeginAddOrUpdate(() => Repo.Instance.AniDB_File.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize)))
                    {
                        bool skip = false;
                        if (!upd.IsUpdate)
                        {
                            Raw_AniDB_File 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.FileName;
                            upd.Entity.FileName = localFileName;

                            aniFile = upd.Commit(false);
                            aniFile.CreateLanguages();
                            aniFile.CreateCrossEpisodes(localFileName);

                            animeID = aniFile.AnimeID;
                        }

                        upd.Commit();
                    }
                }

                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 <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
                                    Repo.Instance.CrossRef_File_Episode.BeginAdd(xrefEnt).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 = 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;
                        }
                    }
                }

                // 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);
                }

                // 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)
                        {
                            CommandRequest_GetReleaseGroupStatus cmdStatus =
                                new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false);
                            cmdStatus.Save();
                        }

                        // 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));

                    // 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)
                    {
                        // 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();
                            }
                        }

                        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()));
                        }
                    }

                    // 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.FileName}");
                }
                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();
                }
            }
        }
Exemple #2
0
        // List of Default priorities for commands
        // Pri 1
        //------
        // Reserved for commands user manually initiates from UI
        //------
        // Pri 2
        //------
        // CommandRequest_GetAnimeHTTP
        //------
        // Pri 3
        //------
        // CommandRequest_ProcessFile
        // CommandRequest_GetFile
        //------
        // Pri 4
        //------
        // CommandRequest_GetUpdated
        // CommandRequest_ReadMediaInfo
        // CommandRequest_GetEpsode
        //------
        // Pri 5
        //------
        // CommandRequest_GetReleaseGroupStatus
        //------
        // Pri 6
        //------
        // CommandRequest_SyncMyList
        // CommandRequest_SyncMyVotes
        //------
        // Pri 7
        //------
        // CommandRequest_GetCalendar
        //------
        // Pri 8
        //------
        // CommandRequest_UpdateMyListFileStatus
        // CommandRequest_GetCharactersCreators
        // CommandRequest_TraktSyncCollection
        // CommandRequest_TvDBUpdateSeriesAndEpisodes
        // CommandRequest_TvDBDownloadImages
        // CommandRequest_TvDBSearchAnime
        // CommandRequest_MovieDBSearchAnime
        // CommandRequest_TraktSearchAnime
        // CommandRequest_MALSearchAnime
        // CommandRequest_LinkFileManually
        //------
        // Pri 9
        //------
        // CommandRequest_WebCacheSendFileHash
        // CommandRequest_GetReviews
        // CommandRequest_GetReleaseGroup
        // CommandRequest_WebCacheSendXRefFileEpisode
        // CommandRequest_WebCacheDeleteXRefFileEpisode
        // CommandRequest_AddFileToMyList
        // CommandRequest_DeleteFileFromMyList
        // CommandRequest_VoteAnime
        // CommandRequest_WebCacheDeleteXRefAniDBTvDB
        // CommandRequest_WebCacheDeleteXRefAniDBTvDBAll
        // CommandRequest_WebCacheSendXRefAniDBTvDB
        // CommandRequest_WebCacheSendXRefAniDBOther
        // CommandRequest_WebCacheDeleteXRefAniDBOther
        // CommandRequest_WebCacheDeleteXRefAniDBTrakt
        // CommandRequest_WebCacheSendXRefAniDBTrakt
        // CommandRequest_TraktUpdateInfoAndImages
        // CommandRequest_TraktSyncCollectionSeries
        // CommandRequest_TraktShowEpisodeUnseen
        // CommandRequest_DownloadImage
        // CommandRequest_TraktUpdateAllSeries
        // CommandRequest_MALUpdatedWatchedStatus
        // CommandRequest_MALUploadStatusToMAL
        // CommandRequest_MALDownloadStatusFromMAL
        // CommandRequest_WebCacheSendAniDB_File
        // CommandRequest_Azure_SendAnimeFull
        //------
        // Pri 10
        //------
        // CommandRequest_UpdateMylistStats
        // CommandRequest_Azure_SendAnimeXML
        //------
        // Pri 11
        //------
        // CommandRequest_Azure_SendAnimeTitle

        public static ICommandRequest GetCommand(CommandRequest crdb)
        {
            CommandRequestType crt = (CommandRequestType)crdb.CommandType;

            switch (crt)
            {
            case CommandRequestType.Trakt_SyncCollectionSeries:
                CommandRequest_TraktSyncCollectionSeries cr_CommandRequest_TraktSyncCollectionSeries =
                    new CommandRequest_TraktSyncCollectionSeries();
                cr_CommandRequest_TraktSyncCollectionSeries.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_TraktSyncCollectionSeries);

            case CommandRequestType.AniDB_GetEpisodeUDP:
                CommandRequest_GetEpisode cr_CommandRequest_GetEpisode = new CommandRequest_GetEpisode();
                cr_CommandRequest_GetEpisode.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_GetEpisode);

            case CommandRequestType.Azure_SendAnimeTitle:
                CommandRequest_Azure_SendAnimeTitle cr_CommandRequest_Azure_SendAnimeTitle =
                    new CommandRequest_Azure_SendAnimeTitle();
                cr_CommandRequest_Azure_SendAnimeTitle.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_Azure_SendAnimeTitle);

            case CommandRequestType.AniDB_GetTitles:
                CommandRequest_GetAniDBTitles cr_CommandRequest_GetAniDBTitles =
                    new CommandRequest_GetAniDBTitles();
                cr_CommandRequest_GetAniDBTitles.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_GetAniDBTitles);

            case CommandRequestType.Azure_SendAnimeXML:
                CommandRequest_Azure_SendAnimeXML cr_CommandRequest_Azure_SendAnimeXML =
                    new CommandRequest_Azure_SendAnimeXML();
                cr_CommandRequest_Azure_SendAnimeXML.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_Azure_SendAnimeXML);

            case CommandRequestType.Azure_SendAnimeFull:
                CommandRequest_Azure_SendAnimeFull cr_CommandRequest_Azure_SendAnimeFull =
                    new CommandRequest_Azure_SendAnimeFull();
                cr_CommandRequest_Azure_SendAnimeFull.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_Azure_SendAnimeFull);

            case CommandRequestType.Azure_SendUserInfo:
                CommandRequest_Azure_SendUserInfo cr_CommandRequest_Azure_SendUserInfo =
                    new CommandRequest_Azure_SendUserInfo();
                cr_CommandRequest_Azure_SendUserInfo.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_CommandRequest_Azure_SendUserInfo);

            case CommandRequestType.AniDB_UpdateMylistStats:
                CommandRequest_UpdateMylistStats cr_AniDB_UpdateMylistStats =
                    new CommandRequest_UpdateMylistStats();
                cr_AniDB_UpdateMylistStats.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_AniDB_UpdateMylistStats);

            case CommandRequestType.MAL_DownloadWatchedStates:
                CommandRequest_MALDownloadStatusFromMAL cr_MAL_DownloadWatchedStates =
                    new CommandRequest_MALDownloadStatusFromMAL();
                cr_MAL_DownloadWatchedStates.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_MAL_DownloadWatchedStates);

            case CommandRequestType.MAL_UploadWatchedStates:
                CommandRequest_MALUploadStatusToMAL cr_MAL_UploadWatchedStates =
                    new CommandRequest_MALUploadStatusToMAL();
                cr_MAL_UploadWatchedStates.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_MAL_UploadWatchedStates);

            case CommandRequestType.MAL_UpdateStatus:
                CommandRequest_MALUpdatedWatchedStatus cr_MAL_UpdateStatus =
                    new CommandRequest_MALUpdatedWatchedStatus();
                cr_MAL_UpdateStatus.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_MAL_UpdateStatus);

            case CommandRequestType.MAL_SearchAnime:
                CommandRequest_MALSearchAnime cr_MAL_SearchAnime = new CommandRequest_MALSearchAnime();
                cr_MAL_SearchAnime.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_MAL_SearchAnime);

            case CommandRequestType.WebCache_SendXRefAniDBMAL:
                CommandRequest_WebCacheSendXRefAniDBMAL cr_WebCacheSendXRefAniDBMAL =
                    new CommandRequest_WebCacheSendXRefAniDBMAL();
                cr_WebCacheSendXRefAniDBMAL.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_WebCacheSendXRefAniDBMAL);

            case CommandRequestType.WebCache_DeleteXRefAniDBMAL:
                CommandRequest_WebCacheDeleteXRefAniDBMAL cr_WebCacheDeleteXRefAniDBMAL =
                    new CommandRequest_WebCacheDeleteXRefAniDBMAL();
                cr_WebCacheDeleteXRefAniDBMAL.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_WebCacheDeleteXRefAniDBMAL);

            case CommandRequestType.AniDB_GetFileUDP:
                CommandRequest_GetFile cr_AniDB_GetFileUDP = new CommandRequest_GetFile();
                cr_AniDB_GetFileUDP.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_AniDB_GetFileUDP);

            case CommandRequestType.ReadMediaInfo:
                CommandRequest_ReadMediaInfo cr_ReadMediaInfo = new CommandRequest_ReadMediaInfo();
                cr_ReadMediaInfo.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_ReadMediaInfo);

            case CommandRequestType.Trakt_UpdateAllSeries:
                CommandRequest_TraktUpdateAllSeries cr_Trakt_UpdateAllSeries =
                    new CommandRequest_TraktUpdateAllSeries();
                cr_Trakt_UpdateAllSeries.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_Trakt_UpdateAllSeries);

            case CommandRequestType.Trakt_EpisodeCollection:
                CommandRequest_TraktCollectionEpisode cr_TraktCollectionEpisode =
                    new CommandRequest_TraktCollectionEpisode();
                cr_TraktCollectionEpisode.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_TraktCollectionEpisode);

            case CommandRequestType.Trakt_SyncCollection:
                CommandRequest_TraktSyncCollection cr_Trakt_SyncCollection =
                    new CommandRequest_TraktSyncCollection();
                cr_Trakt_SyncCollection.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_Trakt_SyncCollection);

            case CommandRequestType.Trakt_EpisodeHistory:
                CommandRequest_TraktHistoryEpisode cr_Trakt_EpisodeHistory =
                    new CommandRequest_TraktHistoryEpisode();
                cr_Trakt_EpisodeHistory.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_Trakt_EpisodeHistory);

            case CommandRequestType.Trakt_UpdateInfoImages:
                CommandRequest_TraktUpdateInfoAndImages cr_Trakt_UpdateInfoImages =
                    new CommandRequest_TraktUpdateInfoAndImages();
                cr_Trakt_UpdateInfoImages.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_Trakt_UpdateInfoImages);

            case CommandRequestType.WebCache_SendXRefAniDBTrakt:
                CommandRequest_WebCacheSendXRefAniDBTrakt cr_WebCache_SendXRefAniDBTrakt =
                    new CommandRequest_WebCacheSendXRefAniDBTrakt();
                cr_WebCache_SendXRefAniDBTrakt.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_WebCache_SendXRefAniDBTrakt);

            case CommandRequestType.WebCache_DeleteXRefAniDBTrakt:
                CommandRequest_WebCacheDeleteXRefAniDBTrakt cr_WebCache_DeleteXRefAniDBTrakt =
                    new CommandRequest_WebCacheDeleteXRefAniDBTrakt();
                cr_WebCache_DeleteXRefAniDBTrakt.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_WebCache_DeleteXRefAniDBTrakt);

            case CommandRequestType.Trakt_SearchAnime:
                CommandRequest_TraktSearchAnime cr_Trakt_SearchAnime = new CommandRequest_TraktSearchAnime();
                cr_Trakt_SearchAnime.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_Trakt_SearchAnime);

            case CommandRequestType.MovieDB_SearchAnime:
                CommandRequest_MovieDBSearchAnime cr_MovieDB_SearchAnime = new CommandRequest_MovieDBSearchAnime();
                cr_MovieDB_SearchAnime.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_MovieDB_SearchAnime);

            case CommandRequestType.WebCache_DeleteXRefAniDBOther:
                CommandRequest_WebCacheDeleteXRefAniDBOther cr_SendXRefAniDBOther =
                    new CommandRequest_WebCacheDeleteXRefAniDBOther();
                cr_SendXRefAniDBOther.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_SendXRefAniDBOther);

            case CommandRequestType.WebCache_SendXRefAniDBOther:
                CommandRequest_WebCacheSendXRefAniDBOther cr_WebCacheSendXRefAniDBOther =
                    new CommandRequest_WebCacheSendXRefAniDBOther();
                cr_WebCacheSendXRefAniDBOther.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_WebCacheSendXRefAniDBOther);

            case CommandRequestType.AniDB_DeleteFileUDP:
                CommandRequest_DeleteFileFromMyList cr_AniDB_DeleteFileUDP =
                    new CommandRequest_DeleteFileFromMyList();
                cr_AniDB_DeleteFileUDP.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_AniDB_DeleteFileUDP);

            case CommandRequestType.ImageDownload:
                CommandRequest_DownloadImage cr_ImageDownload = new CommandRequest_DownloadImage();
                cr_ImageDownload.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_ImageDownload);

            case CommandRequestType.WebCache_DeleteXRefAniDBTvDB:
                CommandRequest_WebCacheDeleteXRefAniDBTvDB cr_DeleteXRefAniDBTvDB =
                    new CommandRequest_WebCacheDeleteXRefAniDBTvDB();
                cr_DeleteXRefAniDBTvDB.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_DeleteXRefAniDBTvDB);

            case CommandRequestType.WebCache_SendXRefAniDBTvDB:
                CommandRequest_WebCacheSendXRefAniDBTvDB cr_SendXRefAniDBTvDB =
                    new CommandRequest_WebCacheSendXRefAniDBTvDB();
                cr_SendXRefAniDBTvDB.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_SendXRefAniDBTvDB);


            case CommandRequestType.TvDB_SearchAnime:
                CommandRequest_TvDBSearchAnime cr_TvDB_SearchAnime = new CommandRequest_TvDBSearchAnime();
                cr_TvDB_SearchAnime.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_TvDB_SearchAnime);

            case CommandRequestType.TvDB_DownloadImages:
                CommandRequest_TvDBDownloadImages cr_TvDB_DownloadImages = new CommandRequest_TvDBDownloadImages();
                cr_TvDB_DownloadImages.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_TvDB_DownloadImages);

            case CommandRequestType.TvDB_SeriesEpisodes:
                CommandRequest_TvDBUpdateSeriesAndEpisodes cr_TvDB_Episodes =
                    new CommandRequest_TvDBUpdateSeriesAndEpisodes();
                cr_TvDB_Episodes.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_TvDB_Episodes);

            case CommandRequestType.AniDB_SyncVotes:
                CommandRequest_SyncMyVotes cr_SyncVotes = new CommandRequest_SyncMyVotes();
                cr_SyncVotes.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_SyncVotes);

            case CommandRequestType.AniDB_VoteAnime:
                CommandRequest_VoteAnime cr_VoteAnime = new CommandRequest_VoteAnime();
                cr_VoteAnime.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_VoteAnime);

            case CommandRequestType.AniDB_GetCalendar:
                CommandRequest_GetCalendar cr_GetCalendar = new CommandRequest_GetCalendar();
                cr_GetCalendar.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_GetCalendar);

            case CommandRequestType.AniDB_GetReleaseGroup:
                CommandRequest_GetReleaseGroup cr_GetReleaseGroup = new CommandRequest_GetReleaseGroup();
                cr_GetReleaseGroup.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_GetReleaseGroup);

            case CommandRequestType.AniDB_GetAnimeHTTP:
                CommandRequest_GetAnimeHTTP cr_geth = new CommandRequest_GetAnimeHTTP();
                cr_geth.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_geth);

            case CommandRequestType.AniDB_GetReleaseGroupStatus:
                CommandRequest_GetReleaseGroupStatus cr_GetReleaseGroupStatus =
                    new CommandRequest_GetReleaseGroupStatus();
                cr_GetReleaseGroupStatus.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_GetReleaseGroupStatus);

            case CommandRequestType.HashFile:
                CommandRequest_HashFile cr_HashFile = new CommandRequest_HashFile();
                cr_HashFile.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_HashFile);

            case CommandRequestType.ProcessFile:
                CommandRequest_ProcessFile cr_pf = new CommandRequest_ProcessFile();
                cr_pf.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_pf);

            case CommandRequestType.AniDB_AddFileUDP:
                CommandRequest_AddFileToMyList cr_af = new CommandRequest_AddFileToMyList();
                cr_af.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_af);

            case CommandRequestType.AniDB_UpdateWatchedUDP:
                CommandRequest_UpdateMyListFileStatus cr_umlf = new CommandRequest_UpdateMyListFileStatus();
                cr_umlf.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_umlf);

            case CommandRequestType.WebCache_DeleteXRefFileEpisode:
                CommandRequest_WebCacheDeleteXRefFileEpisode cr_DeleteXRefFileEpisode =
                    new CommandRequest_WebCacheDeleteXRefFileEpisode();
                cr_DeleteXRefFileEpisode.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_DeleteXRefFileEpisode);

            case CommandRequestType.WebCache_SendXRefFileEpisode:
                CommandRequest_WebCacheSendXRefFileEpisode cr_SendXRefFileEpisode =
                    new CommandRequest_WebCacheSendXRefFileEpisode();
                cr_SendXRefFileEpisode.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_SendXRefFileEpisode);

            case CommandRequestType.AniDB_GetReviews:
                CommandRequest_GetReviews cr_GetReviews = new CommandRequest_GetReviews();
                cr_GetReviews.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_GetReviews);

            case CommandRequestType.AniDB_GetUpdated:
                CommandRequest_GetUpdated cr_GetUpdated = new CommandRequest_GetUpdated();
                cr_GetUpdated.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_GetUpdated);

            case CommandRequestType.AniDB_SyncMyList:
                CommandRequest_SyncMyList cr_SyncMyList = new CommandRequest_SyncMyList();
                cr_SyncMyList.LoadFromDBCommand(crdb);
                return((ICommandRequest)cr_SyncMyList);

            case CommandRequestType.Refresh_AnimeStats:
                CommandRequest_RefreshAnime cr_refreshAnime = new CommandRequest_RefreshAnime();
                cr_refreshAnime.LoadFromDBCommand(crdb);
                return(cr_refreshAnime);

            case CommandRequestType.LinkAniDBTvDB:
                CommandRequest_LinkAniDBTvDB cr_linkAniDBTvDB = new CommandRequest_LinkAniDBTvDB();
                cr_linkAniDBTvDB.LoadFromDBCommand(crdb);
                return(cr_linkAniDBTvDB);

            case CommandRequestType.Refresh_GroupFilter:
                CommandRequest_RefreshGroupFilter cr_refreshGroupFilter = new CommandRequest_RefreshGroupFilter();
                cr_refreshGroupFilter.LoadFromDBCommand(crdb);
                return(cr_refreshGroupFilter);

            case CommandRequestType.Plex_Sync:
                CommandRequest_PlexSyncWatched cr_PlexSync = new CommandRequest_PlexSyncWatched();
                cr_PlexSync.LoadFromDBCommand(crdb);
                return(cr_PlexSync);

            case CommandRequestType.LinkFileManually:
                CommandRequest_LinkFileManually cr_LinkFile = new CommandRequest_LinkFileManually();
                cr_LinkFile.LoadFromDBCommand(crdb);
                return(cr_LinkFile);
            }

            return(null);
        }
        public override void ProcessCommand()
        {
            logger.Info("Processing CommandRequest_GetUpdated");

            try
            {
                List <int> animeIDsToUpdate = new List <int>();

                // check the automated update table to see when the last time we ran this command
                ScheduledUpdate sched =
                    RepoFactory.ScheduledUpdate.GetByUpdateType((int)ScheduledUpdateType.AniDBUpdates);
                if (sched != null)
                {
                    int freqHours = Utils.GetScheduledHours(ServerSettings.AniDB_Anime_UpdateFrequency);

                    // if we have run this in the last 12 hours and are not forcing it, then exit
                    TimeSpan tsLastRun = DateTime.Now - sched.LastUpdate;
                    if (tsLastRun.TotalHours < freqHours)
                    {
                        if (!ForceRefresh)
                        {
                            return;
                        }
                    }
                }


                long webUpdateTime    = 0;
                long webUpdateTimeNew = 0;
                if (sched == null)
                {
                    // if this is the first time, lets ask for last 3 days
                    DateTime localTime = DateTime.Now.AddDays(-3);
                    DateTime utcTime   = localTime.ToUniversalTime();
                    webUpdateTime    = long.Parse(Commons.Utils.AniDB.AniDBDate(utcTime));
                    webUpdateTimeNew = long.Parse(Commons.Utils.AniDB.AniDBDate(DateTime.Now.ToUniversalTime()));

                    sched = new ScheduledUpdate
                    {
                        UpdateType = (int)ScheduledUpdateType.AniDBUpdates
                    };
                }
                else
                {
                    logger.Trace("Last anidb info update was : {0}", sched.UpdateDetails);
                    webUpdateTime    = long.Parse(sched.UpdateDetails);
                    webUpdateTimeNew = long.Parse(Commons.Utils.AniDB.AniDBDate(DateTime.Now.ToUniversalTime()));

                    logger.Info(
                        $"{Utils.FormatSecondsToDisplayTime(int.Parse((webUpdateTimeNew - webUpdateTime).ToString()))} since last UPDATED command");
                }

                // get a list of updates from AniDB
                // startTime will contain the date/time from which the updates apply to
                ShokoService.AnidbProcessor.GetUpdated(ref animeIDsToUpdate, ref webUpdateTime);

                // now save the update time from AniDB
                // we will use this next time as a starting point when querying the web cache
                sched.LastUpdate    = DateTime.Now;
                sched.UpdateDetails = webUpdateTimeNew.ToString();
                RepoFactory.ScheduledUpdate.Save(sched);

                if (animeIDsToUpdate.Count == 0)
                {
                    logger.Info("No anime to be updated");
                    return;
                }


                int countAnime  = 0;
                int countSeries = 0;
                foreach (int animeID in animeIDsToUpdate)
                {
                    // update the anime from HTTP
                    SVR_AniDB_Anime anime = RepoFactory.AniDB_Anime.GetByAnimeID(animeID);
                    if (anime == null)
                    {
                        logger.Trace("No local record found for Anime ID: {0}, so skipping...", animeID);
                        continue;
                    }

                    logger.Info("Updating CommandRequest_GetUpdated: {0} ", animeID);

                    var update = RepoFactory.AniDB_AnimeUpdate.GetByAnimeID(animeID);

                    // but only if it hasn't been recently updated
                    TimeSpan ts = DateTime.Now - update.UpdatedAt;
                    if (ts.TotalHours > 4)
                    {
                        CommandRequest_GetAnimeHTTP cmdAnime = new CommandRequest_GetAnimeHTTP(animeID, true, false);
                        cmdAnime.Save();
                        countAnime++;
                    }

                    // update the group status
                    // this will allow us to determine which anime has missing episodes
                    // so we wonly get by an amime where we also have an associated series
                    SVR_AnimeSeries ser = RepoFactory.AnimeSeries.GetByAnimeID(animeID);
                    if (ser != null)
                    {
                        CommandRequest_GetReleaseGroupStatus cmdStatus =
                            new CommandRequest_GetReleaseGroupStatus(animeID, true);
                        cmdStatus.Save();
                        countSeries++;
                    }
                }

                logger.Info("Updating {0} anime records, and {1} group status records", countAnime, countSeries);
            }
            catch (Exception ex)
            {
                logger.Error("Error processing CommandRequest_GetUpdated: {0}", ex);
            }
        }
Exemple #4
0
        private void ProcessFile_AniDB(SVR_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)
            {
                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");
                    }
                }

                int animeID = 0;

                if (aniFile == null)
                {
                    // get info from AniDB
                    logger.Debug("Getting AniDB_File record from AniDB....");
                    Raw_AniDB_File fileInfo = ShokoService.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 SVR_AniDB_File();
                        }

                        SVR_AniDB_File.Populate(aniFile, 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 <Shoko.Models.Azure.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: {0}",
                                    vidLocal.ED2KHash);
                                return;
                            }
                            else
                            {
                                foreach (Shoko.Models.Azure.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)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
                SVR_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 = ShokoService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries);
                }

                // create the group/series/episode records if needed
                SVR_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 (SVR_AnimeGroup grp in ser.AllGroupsAbove)
                    {
                        grp.EpisodeAddedDate = DateTime.Now;
                        RepoFactory.AnimeGroup.Save(grp, true, false);
                    }

                    if (ServerSettings.FileQualityFilterEnabled)
                    {
                        // 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)
                        {
                            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();

                            foreach (SVR_VideoLocal toDelete in videoLocals)
                            {
                                toDelete.Places.ForEach(a => a.RemoveAndDeleteFile());
                            }
                        }
                    }
                }
                vidLocal.Places.ForEach(a => { a.RenameAndMoveAsRequired(); });


                // 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();
                }
            }
        }