public static void PopulateMyListIDs()
        {
            // Get the list from AniDB
            AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList();

            cmd.Init(ServerSettings.AniDB_Username, ServerSettings.AniDB_Password);
            enHelperActivityType ev = cmd.Process();

            if (ev != enHelperActivityType.GotMyListHTTP)
            {
                logger.Warn("AniDB did not return a successful code: " + ev);
                return;
            }
            // Add missing files on AniDB
            var onlineFiles  = cmd.MyListItems.ToLookup(a => a.FileID);
            var dictAniFiles = RepoFactory.AniDB_File.GetAll().ToLookup(a => a.Hash);

            var list  = RepoFactory.VideoLocal.GetAll().Where(a => !string.IsNullOrEmpty(a.Hash)).ToList();
            int count = 0;

            foreach (SVR_VideoLocal vid in list)
            {
                count++;
                if (count % 10 == 0)
                {
                    ServerState.Instance.CurrentSetupStatus = string.Format(
                        Commons.Properties.Resources.Database_Validating, "Populating MyList IDs (this will help solve MyList issues)",
                        $" {count}/{list.Count}");
                }

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

                Raw_AniDB_MyListFile file = onlineFiles[fileID].FirstOrDefault(a => a != null && a.ListID != 0);
                if (file == null || vid.MyListID != 0)
                {
                    continue;
                }

                vid.MyListID = file.ListID;
                RepoFactory.VideoLocal.Save(vid);
            }
        }
示例#2
0
        public override void ProcessCommand()
        {
            logger.Info("Processing CommandRequest_SyncMyList");

            try
            {
                // we will always assume that an anime was downloaded via http first
                ScheduledUpdateRepository repSched     = new ScheduledUpdateRepository();
                AniDB_FileRepository      repAniFile   = new AniDB_FileRepository();
                VideoLocalRepository      repVidLocals = new VideoLocalRepository();

                ScheduledUpdate sched = repSched.GetByUpdateType((int)ScheduledUpdateType.AniDBMyListSync);
                if (sched == null)
                {
                    sched               = new ScheduledUpdate();
                    sched.UpdateType    = (int)ScheduledUpdateType.AniDBMyListSync;
                    sched.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)
                {
                    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, AniDB_File> dictAniFiles = new Dictionary <string, AniDB_File>();
                    List <AniDB_File> allAniFiles = repAniFile.GetAll();
                    foreach (AniDB_File anifile in allAniFiles)
                    {
                        dictAniFiles[anifile.Hash] = anifile;
                    }

                    int missingFiles = 0;
                    foreach (VideoLocal vid in repVidLocals.GetAll())
                    {
                        if (!dictAniFiles.ContainsKey(vid.Hash))
                        {
                            continue;
                        }

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

                        if (!onlineFiles.ContainsKey(fileID))
                        {
                            // 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(string.Format("MYLIST Missing Files: {0} Added to queue for inclusion", missingFiles));

                    JMMUserRepository repUsers   = new JMMUserRepository();
                    List <JMMUser>    aniDBUsers = repUsers.GetAniDBUsers();

                    VideoLocal_UserRepository       repVidUsers = new VideoLocal_UserRepository();
                    CrossRef_File_EpisodeRepository repFileEp   = new CrossRef_File_EpisodeRepository();

                    // 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 = (double)totalItems / (double)cmd.MyListItems.Count * (double)100;
                        string spct = pct.ToString("#0.0");

                        string hash = string.Empty;

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


                        if (!string.IsNullOrEmpty(hash))
                        {
                            // find the video associated with this record
                            VideoLocal vl = repVidLocals.GetByHash(hash);
                            if (vl == null)
                            {
                                continue;
                            }

                            foreach (JMMUser juser in aniDBUsers)
                            {
                                bool localStatus = false;
                                int? jmmUserID   = null;

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

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

                                    string msg =
                                        string.Format(
                                            "MYLISTDIFF:: File {0} - Local Status = {1}, AniDB Status = {2} --- {3}",
                                            vl.FullServerPath, localStatus, 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;
                    repSched.Save(sched);
                }
            }
            catch (Exception ex)
            {
                logger.Error("Error processing CommandRequest_SyncMyList: {0} ", ex.ToString());
                return;
            }
        }
        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);
            }
        }
示例#4
0
        public static void PopulateMyListIDs()
        {
            // Don't bother with no AniDB creds, we assume first run
            if (!ShokoService.AnidbProcessor.ValidAniDBCredentials())
            {
                return;
            }

            // Don't even bother on new DBs
            using (var session = DatabaseFactory.SessionFactory.OpenSession())
            {
                long vlCount = session.CreateSQLQuery("SELECT COUNT(VideoLocalID) FROM VideoLocal").UniqueResult <long>();
                if (vlCount == 0)
                {
                    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;
            }
            // Add missing files on AniDB
            var onlineFiles  = cmd.MyListItems.ToLookup(a => a.FileID);
            var dictAniFiles = RepoFactory.AniDB_File.GetAll().ToLookup(a => a.Hash);

            var list  = RepoFactory.VideoLocal.GetAll().Where(a => !string.IsNullOrEmpty(a.Hash)).ToList();
            int count = 0;

            foreach (SVR_VideoLocal vid in list)
            {
                count++;
                if (count % 10 == 0)
                {
                    ServerState.Instance.CurrentSetupStatus = string.Format(
                        Commons.Properties.Resources.Database_Validating, "Populating MyList IDs (this will help solve MyList issues)",
                        $" {count}/{list.Count}");
                }

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

                Raw_AniDB_MyListFile file = onlineFiles[fileID].FirstOrDefault(a => a != null && a.ListID != 0);
                if (file == null || vid.MyListID != 0)
                {
                    continue;
                }

                vid.MyListID = file.ListID;
                RepoFactory.VideoLocal.Save(vid);
            }
        }