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();
                }
            }
        }
Exemplo n.º 2
0
        public override void ProcessCommand()
        {
            CrossRef_File_Episode xref = new CrossRef_File_Episode();

            try
            {
                xref.PopulateManually(vlocal, episode);
                if (Percentage > 0 && Percentage <= 100)
                {
                    xref.Percentage = Percentage;
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Error populating XREF: {0}", vlocal.ToStringDetailed());
                throw;
            }
            RepoFactory.CrossRef_File_Episode.Save(xref);
            CommandRequest_WebCacheSendXRefFileEpisode cr = new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);

            cr.Save();

            if (ServerSettings.FileQualityFilterEnabled)
            {
                List <SVR_VideoLocal> videoLocals = episode.GetVideoLocals();
                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 (videoLocals.Contains(vlocal))
                    {
                        videoLocals.Remove(vlocal);
                    }
                    videoLocals = videoLocals.Where(FileQualityFilter.CheckFileKeep).ToList();

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

            vlocal.Places.ForEach(a => { a.RenameAndMoveAsRequired(); });

            SVR_AnimeSeries ser = episode.GetAnimeSeries();

            ser.EpisodeAddedDate = DateTime.Now;
            RepoFactory.AnimeSeries.Save(ser, false, true);

            //Update will re-save
            ser.QueueUpdateStats();


            foreach (SVR_AnimeGroup grp in ser.AllGroupsAbove)
            {
                grp.EpisodeAddedDate = DateTime.Now;
                RepoFactory.AnimeGroup.Save(grp, false, false);
            }

            if (ServerSettings.AniDB_MyList_AddFiles)
            {
                CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vlocal.Hash);
                cmdAddFile.Save();
            }
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 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();
                }
            }
        }
        public override void ProcessCommand()
        {
            logger.Info("Processing CommandRequest_SyncMyList");

            try
            {
                // we will always assume that an anime was downloaded via http first
                ScheduledUpdate sched =
                    RepoFactory.ScheduledUpdate.GetByUpdateType((int)ScheduledUpdateType.AniDBMyListSync);
                if (sched == null)
                {
                    sched = new ScheduledUpdate
                    {
                        UpdateType    = (int)ScheduledUpdateType.AniDBMyListSync,
                        UpdateDetails = string.Empty
                    };
                }
                else
                {
                    int freqHours = Utils.GetScheduledHours(ServerSettings.Instance.AniDb.MyList_UpdateFrequency);

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

                // Get the list from AniDB
                AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList();
                cmd.Init(ServerSettings.Instance.AniDb.Username, ServerSettings.Instance.AniDb.Password);
                AniDBUDPResponseCode ev = cmd.Process();
                if (ev != AniDBUDPResponseCode.GotMyListHTTP)
                {
                    logger.Warn("AniDB did not return a successful code: " + ev);
                    return;
                }

                int totalItems    = 0;
                int watchedItems  = 0;
                int modifiedItems = 0;

                // Add missing files on AniDB
                var onlineFiles  = cmd.MyListItems.ToLookup(a => a.FileID);
                var dictAniFiles = RepoFactory.AniDB_File.GetAll().ToLookup(a => a.Hash);

                int missingFiles = 0;
                foreach (SVR_VideoLocal vid in RepoFactory.VideoLocal.GetAll()
                         .Where(a => !string.IsNullOrEmpty(a.Hash)).ToList())
                {
                    // Does it have a linked AniFile
                    if (!dictAniFiles.Contains(vid.Hash))
                    {
                        continue;
                    }

                    int fileID = dictAniFiles[vid.Hash].FirstOrDefault()?.FileID ?? 0;
                    if (fileID == 0)
                    {
                        continue;
                    }
                    // Is it in MyList
                    if (onlineFiles.Contains(fileID))
                    {
                        Raw_AniDB_MyListFile file = onlineFiles[fileID].FirstOrDefault(a => a != null);

                        if (file != null)
                        {
                            if (vid.MyListID == 0)
                            {
                                vid.MyListID = file.ListID;
                                RepoFactory.VideoLocal.Save(vid);
                            }

                            // Update file state if deleted
                            if (file.State != (int)ServerSettings.Instance.AniDb.MyList_StorageState)
                            {
                                int seconds = Commons.Utils.AniDB.GetAniDBDateAsSeconds(file.WatchedDate);
                                CommandRequest_UpdateMyListFileStatus cmdUpdateFile =
                                    new CommandRequest_UpdateMyListFileStatus(vid.Hash, file.WatchedDate.HasValue,
                                                                              false,
                                                                              seconds);
                                cmdUpdateFile.Save();
                            }

                            continue;
                        }
                    }

                    // means we have found a file in our local collection, which is not recorded online
                    if (ServerSettings.Instance.AniDb.MyList_AddFiles)
                    {
                        CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash);
                        cmdAddFile.Save();
                    }
                    missingFiles++;
                }
                logger.Info($"MYLIST Missing Files: {missingFiles} Added to queue for inclusion");

                List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers();
                LinkedHashSet <SVR_AnimeSeries> modifiedSeries = new LinkedHashSet <SVR_AnimeSeries>();

                // Remove Missing Files and update watched states (single loop)
                List <int> filesToRemove = new List <int>();
                foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems)
                {
                    try
                    {
                        totalItems++;
                        if (myitem.IsWatched)
                        {
                            watchedItems++;
                        }

                        string hash = string.Empty;

                        SVR_AniDB_File anifile = RepoFactory.AniDB_File.GetByFileID(myitem.FileID);
                        if (anifile != null)
                        {
                            hash = anifile.Hash;
                        }
                        else
                        {
                            // look for manually linked files
                            List <CrossRef_File_Episode> xrefs =
                                RepoFactory.CrossRef_File_Episode.GetByEpisodeID(myitem.EpisodeID);
                            foreach (CrossRef_File_Episode xref in xrefs)
                            {
                                if (xref.CrossRefSource == (int)CrossRefSource.AniDB)
                                {
                                    continue;
                                }
                                hash = xref.Hash;
                                break;
                            }
                        }

                        // We couldn't evem find a hash, so remove it
                        if (string.IsNullOrEmpty(hash))
                        {
                            filesToRemove.Add(myitem.ListID);
                            continue;
                        }

                        // If there's no video local, we don't have it
                        SVR_VideoLocal vl = RepoFactory.VideoLocal.GetByHash(hash);
                        if (vl == null)
                        {
                            filesToRemove.Add(myitem.ListID);
                            continue;
                        }

                        foreach (SVR_JMMUser juser in aniDBUsers)
                        {
                            bool localStatus = false;

                            // doesn't matter which anidb user we use
                            int             jmmUserID  = juser.JMMUserID;
                            VideoLocal_User userRecord = vl.GetUserRecord(juser.JMMUserID);
                            if (userRecord != null)
                            {
                                localStatus = userRecord.WatchedDate.HasValue;
                            }

                            string action = string.Empty;
                            if (localStatus == myitem.IsWatched)
                            {
                                continue;
                            }

                            // localStatus and AniDB Status are different
                            DateTime?watchedDate = myitem.WatchedDate ?? DateTime.Now;
                            if (localStatus)
                            {
                                // local = watched, anidb = unwatched
                                if (ServerSettings.Instance.AniDb.MyList_ReadUnwatched)
                                {
                                    modifiedItems++;
                                    vl.ToggleWatchedStatus(false, false, watchedDate,
                                                           false, jmmUserID, false,
                                                           true);
                                    action = "Used AniDB Status";
                                }
                                else if (ServerSettings.Instance.AniDb.MyList_SetWatched)
                                {
                                    vl.ToggleWatchedStatus(true, true, userRecord.WatchedDate, false, jmmUserID,
                                                           false, true);
                                }
                            }
                            else
                            {
                                // means local is un-watched, and anidb is watched
                                if (ServerSettings.Instance.AniDb.MyList_ReadWatched)
                                {
                                    modifiedItems++;
                                    vl.ToggleWatchedStatus(true, false, watchedDate, false,
                                                           jmmUserID, false, true);
                                    action = "Updated Local record to Watched";
                                }
                                else if (ServerSettings.Instance.AniDb.MyList_SetUnwatched)
                                {
                                    vl.ToggleWatchedStatus(false, true, watchedDate, false, jmmUserID,
                                                           false, true);
                                }
                            }

                            vl.GetAnimeEpisodes().Select(a => a.GetAnimeSeries()).Where(a => a != null)
                            .DistinctBy(a => a.AnimeSeriesID).ForEach(a => modifiedSeries.Add(a));
                            logger.Info(
                                $"MYLISTDIFF:: File {vl.FileName} - Local Status = {localStatus}, AniDB Status = {myitem.IsWatched} --- {action}");
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Error($"A MyList Item threw an error while syncing: {ex}");
                    }
                }

                // Actually remove the files
                if (filesToRemove.Count > 0)
                {
                    foreach (int listID in filesToRemove)
                    {
                        CommandRequest_DeleteFileFromMyList deleteCommand =
                            new CommandRequest_DeleteFileFromMyList(listID);
                        deleteCommand.Save();
                    }
                    logger.Info($"MYLIST Missing Files: {filesToRemove.Count} Added to queue for deletion");
                }

                modifiedSeries.ForEach(a => a.QueueUpdateStats());

                logger.Info($"Process MyList: {totalItems} Items, {missingFiles} Added, {filesToRemove.Count} Deleted, {watchedItems} Watched, {modifiedItems} Modified");

                sched.LastUpdate = DateTime.Now;
                RepoFactory.ScheduledUpdate.Save(sched);
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Error processing CommandRequest_SyncMyList: {0} ", ex);
            }
        }
Exemplo n.º 6
0
        public override void ProcessCommand()
        {
            logger.Info("Processing CommandRequest_SyncMyList");

            try
            {
                // we will always assume that an anime was downloaded via http first
                ScheduledUpdate sched =
                    RepoFactory.ScheduledUpdate.GetByUpdateType((int)ScheduledUpdateType.AniDBMyListSync);
                if (sched == null)
                {
                    sched = new ScheduledUpdate
                    {
                        UpdateType    = (int)ScheduledUpdateType.AniDBMyListSync,
                        UpdateDetails = ""
                    };
                }
                else
                {
                    int freqHours = Utils.GetScheduledHours(ServerSettings.AniDB_MyList_UpdateFrequency);

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

                AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList();
                cmd.Init(ServerSettings.AniDB_Username, ServerSettings.AniDB_Password);
                enHelperActivityType ev = cmd.Process();
                if (ev != enHelperActivityType.GotMyListHTTP || cmd.MyListItems.Count <= 1)
                {
                    return;
                }


                int    totalItems    = 0;
                int    watchedItems  = 0;
                int    modifiedItems = 0;
                double pct           = 0;

                // 2. find files locally for the user, which are not recorded on anidb
                //    and then add them to anidb
                Dictionary <int, Raw_AniDB_MyListFile> onlineFiles = new Dictionary <int, Raw_AniDB_MyListFile>();
                foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems)
                {
                    onlineFiles[myitem.FileID] = myitem;
                }

                Dictionary <string, SVR_AniDB_File> dictAniFiles = new Dictionary <string, SVR_AniDB_File>();
                IReadOnlyList <SVR_AniDB_File>      allAniFiles  = RepoFactory.AniDB_File.GetAll();
                foreach (SVR_AniDB_File anifile in allAniFiles)
                {
                    dictAniFiles[anifile.Hash] = anifile;
                }

                int missingFiles = 0;
                foreach (SVR_VideoLocal vid in RepoFactory.VideoLocal.GetAll()
                         .Where(a => !string.IsNullOrEmpty(a.Hash)).ToList())
                {
                    if (!dictAniFiles.ContainsKey(vid.Hash))
                    {
                        continue;
                    }

                    int fileID = dictAniFiles[vid.Hash].FileID;

                    if (onlineFiles.ContainsKey(fileID))
                    {
                        continue;
                    }

                    // means we have found a file in our local collection, which is not recorded online
                    CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash);
                    cmdAddFile.Save();
                    missingFiles++;
                }
                logger.Info($"MYLIST Missing Files: {missingFiles} Added to queue for inclusion");

                List <SVR_JMMUser> aniDBUsers = RepoFactory.JMMUser.GetAniDBUsers();


                // 1 . sync mylist items
                foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems)
                {
                    // ignore files mark as deleted by the user
                    if (myitem.State == (int)AniDBFileStatus.Deleted)
                    {
                        continue;
                    }

                    totalItems++;
                    if (myitem.IsWatched)
                    {
                        watchedItems++;
                    }

                    //calculate percentage
                    pct = totalItems / (double)cmd.MyListItems.Count * 100;
                    string spct = pct.ToString("#0.0");

                    string hash = string.Empty;

                    SVR_AniDB_File anifile = RepoFactory.AniDB_File.GetByFileID(myitem.FileID);
                    if (anifile != null)
                    {
                        hash = anifile.Hash;
                    }
                    else
                    {
                        // look for manually linked files
                        List <CrossRef_File_Episode> xrefs =
                            RepoFactory.CrossRef_File_Episode.GetByEpisodeID(myitem.EpisodeID);
                        foreach (CrossRef_File_Episode xref in xrefs)
                        {
                            if (xref.CrossRefSource == (int)CrossRefSource.AniDB)
                            {
                                continue;
                            }
                            hash = xref.Hash;
                            break;
                        }
                    }


                    if (string.IsNullOrEmpty(hash))
                    {
                        continue;
                    }

                    // find the video associated with this record
                    SVR_VideoLocal vl = RepoFactory.VideoLocal.GetByHash(hash);
                    if (vl == null)
                    {
                        continue;
                    }

                    foreach (SVR_JMMUser juser in aniDBUsers)
                    {
                        bool localStatus = false;

                        // doesn't matter which anidb user we use
                        int             jmmUserID  = juser.JMMUserID;
                        VideoLocal_User userRecord = vl.GetUserRecord(juser.JMMUserID);
                        if (userRecord != null)
                        {
                            localStatus = userRecord.WatchedDate.HasValue;
                        }

                        string action = "";
                        if (localStatus == myitem.IsWatched)
                        {
                            continue;
                        }

                        if (localStatus)
                        {
                            // local = watched, anidb = unwatched
                            if (ServerSettings.AniDB_MyList_ReadUnwatched)
                            {
                                modifiedItems++;
                                vl.ToggleWatchedStatus(myitem.IsWatched, false, myitem.WatchedDate,
                                                       false, false, jmmUserID, false,
                                                       true);
                                action = "Used AniDB Status";
                            }
                        }
                        else
                        {
                            // means local is un-watched, and anidb is watched
                            if (ServerSettings.AniDB_MyList_ReadWatched)
                            {
                                modifiedItems++;
                                vl.ToggleWatchedStatus(true, false, myitem.WatchedDate, false, false,
                                                       jmmUserID, false, true);
                                action = "Updated Local record to Watched";
                            }
                        }

                        string msg =
                            $"MYLISTDIFF:: File {vl.FileName} - Local Status = {localStatus}, AniDB Status = {myitem.IsWatched} --- {action}";
                        logger.Info(msg);
                    }


                    //string msg = string.Format("MYLIST:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}",
                    //    vl.FullServerPath, localStatus, myitem.IsWatched, action);
                    //logger.Info(msg);
                }


                // now update all stats
                Importer.UpdateAllStats();

                logger.Info("Process MyList: {0} Items, {1} Watched, {2} Modified", totalItems, watchedItems,
                            modifiedItems);

                sched.LastUpdate = DateTime.Now;
                RepoFactory.ScheduledUpdate.Save(sched);
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Error processing CommandRequest_SyncMyList: {0} ", ex.Message);
            }
        }